Is my spin lock implementation correct and optimal?

Viewed 49269

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:

  • Is this code correct? Does it correctly ensure mutual exclusion?
  • Does it work on all x86 operating systems?
  • Does it work on x86_64 too? On all operating systems?
  • Is it optimal?
    • I've seen spin lock implementations using compare-and-swap but I'm not sure which is better.
    • According to the GCC atomic builtins documentation (http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html) there's also __sync_lock_release. I'm not an expert on memory barriers so I'm not sure whether it's okay for me to use this instead of __sync_synchronize.
    • I'm optimizing for the case in which there's no contention.

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.

11 Answers

To make your spinlock implementation more efficient , you can yield to the scheduler whenever the lock acquisition fails .

void lock() {
    while (__sync_lock_test_and_set(&exclusion, 1)) yield(-1) ;
}
Related