X86 using cmpxchg

I am new to using the gcc inline assembly and am wondering if it is possible to implement spinlock (without race conditions) on an x86 multi-core machine like (using the 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
+13
assembly gcc synchronization x86 spinlock
Aug 04 '11 at 2:15 am
source share
2 answers

You have the right idea, but your asm is broken:

cmpxchg cannot work with the direct operand, it is registered only.

lock not a valid prefix for mov . mov to a aligned address is atomic on x86, so you don't need lock anyway.

It has been a while since I used the AT & T syntax, I hope I remembered everything:

 spin_lock: xorl %ecx, %ecx incl %ecx spin_lock_retry: xorl %eax, %eax lock; cmpxchgl %ecx, (lock_addr) jnz spin_lock_retry ret spin_unlock: movl $0 (lock_addr) ret 

Note that GCC has atomic built-in functions, so you do not need to use the built-in asm to accomplish this:

 void spin_lock(int *p) { while(!__sync_bool_compare_and_swap(p, 0, 1)); } void spin_unlock(int volatile *p) { asm volatile (""); // acts as a memory barrier. *p = 0; } 

As stated below in God, locked instructions carry costs: everyone you use must clear your cache and lock your system memory bus, which can be quite expensive if you have enough processors. Even without the use of many processors, it is still easy and worth optimizing:

 void spin_lock(int volatile *p) { while(!__sync_bool_compare_and_swap(p, 0, 1)) { while(*p) _mm_pause(); } } 

The pause instruction is vital for performance on HyperThreading processors when you have code that rotates this way - it allows the second thread to execute while the first thread is spinning. On CPUs that do not support pause , it is treated as nop .

+21
Aug 04 2018-11-11T00:
source share

This will lead to less conflict on the memory bus:

 void spin_lock(int *p) { while(!__sync_bool_compare_and_swap(p, 0, 1)) while(*p); } 
+3
Oct. 16
source share



All Articles