x86 spinlock using cmpxchg

Viewed 14621

I'm new to using gcc inline assembly, and was wondering if, on an x86 multi-core machine, a spinlock (without race conditions) could be implemented as (using AT&T syntax):

spin_lock:
mov 0 eax
lock cmpxchg 1 [lock_addr]
jnz spin_lock
ret

spin_unlock:
lock mov 0 [lock_addr]
ret
3 Answers

The syntax is wrong. It works after a little modification.

spin_lock:
    movl $0, %eax
    movl $1, %ecx
    lock cmpxchg %ecx, (lock_addr)
    jnz spin_lock
    ret
spin_unlock:
    movl $0, (lock_addr)
    ret

To provide a code running faster. Assume lock_addr is store in %rdi redister.

Use movl and test instead of lock cmpxchgl %ecx, (%rdi) to spin.

Use lock cmpxchgl %ecx, (%rdi) for trying to enter critical section only if there's a chance.

Then could avoid unneeded bus locking.

spin_lock:
    movl $1, %ecx
loop:
    movl (%rdi), %eax
    test %eax, %eax
    jnz loop
    lock cmpxchgl %ecx, (%rdi)
    jnz loop
    ret
spin_unlock:
    movl $0, (%rdi)
    ret

I have tested it using pthread and an easy loop like this.

for(i = 0; i < 10000000; ++i){
    spin_lock(&mutex);
    ++count;
    spin_unlock(&mutex);
}

In my test, the first one take 2.5~3 secs and the second one take 1.3~1.8 secs.

Related