cmultithreadingconcurrencymutual-exclusionspinlock

Is my spin lock implementation correct and optimal?


I'm using a spin lock to protect a very small critical section. Contention happens very rarely so a spin lock is more appropriate than a regular mutex.

My current code is as follows, and assumes x86 and GCC:

volatile int exclusion = 0;

void lock() {
    while (__sync_lock_test_and_set(&exclusion, 1)) {
        // Do nothing. This GCC builtin instruction
        // ensures memory barrier.
    }
}

void unlock() {
    __sync_synchronize(); // Memory barrier.
    exclusion = 0;
}

So I'm wondering:

I do not care at all about contention. There may be 1, maybe 2 other threads trying to lock the spin lock once every few days.


Solution

  • So I'm wondering:

    * Is it correct?
    

    In the context mentioned, I would say yes.

    * Is it optimal?
    

    That's a loaded question. By reinventing the wheel you are also reinventing a lot of problems that have been solved by other implementations

    Note that there was a comment saying that the release barrier wasn't required. That isn't true even on x86 because the release barrier also serves as an instruction to the compiler to not shuffle other memory accesses around the "barrier". Very much like what you'd get if you used asm ("" ::: "memory" ).

    * on compare and swap
    

    On x86 the sync_lock_test_and_set will map to a xchg instruction which has an implied lock prefix. Definitely the most compact generated code (esp. if you use a byte for the "lock word" instead of an int), but no less correct than if you used LOCK CMPXCHG. Use of compare and swap can be used for fancier algorthims (like putting a non-zero pointer to metadata for the first "waiter" into the lockword on failure).