diff --git a/include/spinLock.h b/include/spinLock.h index afda9a5..f3436d8 100644 --- a/include/spinLock.h +++ b/include/spinLock.h @@ -2,6 +2,17 @@ #define SPIN_LOCK_H #include +#ifdef __x86_64__ +#include +#elif defined(__i386__) +#include +#elif defined(__arm__) +#include +#elif defined(__aarch64__) +#include +#elif defined(__aarch32__) +#include +#endif namespace smo { @@ -21,6 +32,41 @@ public: return locked.compare_exchange_strong(expected, true); } + inline void spinPause() + { +#ifdef __x86_64__ + _mm_pause(); +#elif defined(__i386__) + _mm_pause(); +#elif defined(__arm__) + __asm__ volatile("yield"); +#elif defined(__aarch64__) + __asm__ volatile("yield"); +#elif defined(__aarch32__) + __asm__ volatile("yield"); +#else +# error "Unsupported architecture" +#endif + } + + void acquire() + { + while (!tryAcquire()) + { + /** EXPLANATION: + * Busy-wait: keep trying to acquire the lock + * The CPU will spin here until the lock becomes available + * + * The spinPause() function is architecture-specific and is + * essential because I once fried an older Intel M-class laptop CPU + * when I forgot to include a PAUSE instruction in a for (;;){} + * loop. I'm not interested in frying my RPi or my other testbed + * robot boards. + */ + spinPause(); + } + } + void release() { locked.store(false);