I'm reading through this online book on x86 and I'm curious about an implementation detail in their example code for implementing a spin lock. In the example, they use a xchg
to set a memory location to 0 rather than a mov
and I'm trying to understand why that choice was made.
In the spin lock example there is a function, spinUnlock
which puts a 0
in the memory location [sLock]
. [sLock]
is set to 0
if the lock is free and 1
when it is aquired. The spinUnlock
function sets [sLock]
to 0
freeing the lock. The code follows:
spinUnlock:
push ebp
mov ebp, esp
mov eax, 0
xchg eax, [sLock]
pop ebp
ret
Why use mov eax, 0; xchg eax, [sLock]
to set [sLock]
to 0
rather than mov [sLock], 0
? The eax
register is not used for anything after the calls to spinUnlock
. I know that xchg
will lock the memory location, but if mov
is already atomic then a lock is unnecessary.
Only the author can say why the choice was made.
A single mov dword [sLock],0
would work fine; and an xchg eax, [sLock]
(which has an implied lock
) is likely to be more expensive (for both performance and code size).
All of the example's code is awful (e.g. no pause
in the spinLock
routine where it should be used despite having pause
in places where it shouldn't be used at all); and their choice of example isn't good either.
Note: using spinlocks in user-space is "almost never" sane because the OS may do a task switch after you acquire a lock but before you release it, causing all other tasks to waste a massive amount of CPU time spinning with no hope of acquiring the lock.