#include <ctime>
#include <cstdlib>
class SmallSpinLock
{
class Sleeper
{
public:
Sleeper () : _spinCount (0)
{
}
void wait()
{
if (_spinCount < kMaxActiveSpin) {
++_spinCount;
asm volatile ("pause");
}
else {
/*
* Always sleep 0.2ms, assuming this will make the kernel put
* us down for whatever its minimum timer resolution is (in
* linux this varies by kernel version from 1ms to 10ms).
*/
struct timespec ts = { 0, 200000 };
nanosleep (&ts, NULL);
}
}
private:
Sleeper (const Sleeper&);
Sleeper& operator= (const Sleeper&);
private:
uint32_t _spinCount;
static const uint32_t kMaxActiveSpin = 8000;
};
private:
enum { FREE = 0, LOCKED = 1 };
uint8_t _lock;
/*
* Atomically move _lock from "compare" to "newval". Return boolean
* success. Do not play on or around.
*
* 拿comapre变量的值同_lock变量比较是否相等,如果相等则把newval的值赋给_lock,
* 然后zf标志会被置位,并通过setz设置结果out。即当我们想获得锁的时候这样用:cas (0,1); 返回true表示成功。
*/
bool cas (uint8_t compare, uint8_t newVal)
{
bool out;
asm volatile ("lock; cmpxchgb %2, (%3);"
"setz %0;"
: "=r" (out)
: "a" (compare), // cmpxchgb constrains this to be in %al
"q" (newVal), // Needs to be byte-accessible
"r" (&_lock)
: "memory", "flags");
return out;
}
SmallSpinLock (const SmallSpinLock&);
SmallSpinLock& operator= (const SmallSpinLock&);
public:
SmallSpinLock ()
{
_lock = FREE;
}
~SmallSpinLock ()
{
}
bool try_lock ()
{
return cas (FREE, LOCKED);
}
void lock ()
{
Sleeper sleeper;
do {
while (_lock != FREE) {
asm volatile ("" : : : "memory");
sleeper.wait ();
}
} while (!try_lock ());
assert (_lock == LOCKED);
}
void unlock ()
{
assert (_lock == LOCKED);
asm volatile("" : : : "memory");
_lock = FREE; // release barrier on x86
}
};
注:
barrier内存栅栏
#define barrier() __asm__ __volatile__("": : :"memory")
1)__asm__用于指示编译器在此插入汇编语句
2)__volatile__用于告诉编译器,严禁将此处的汇编语句与其它的语句重组合优化。即:原原本本按原来的样子处理这这里的汇编。
3)memory强制gcc编译器假设RAM所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将作废。cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存。
4)"":::表示这是个空指令。