There is actually less voodoo involved than inline assembly "magic", but that is less tricky:
First of all, the xchg assembly instruction does just one thing: it exchanges
atomically, i.e., as one non-dividable operation, the contents of a memory location and a register. With the lock prefix, it (simply said) also prevents other CPUs from interfering.
Now let's have a look at the inline assembly. The first line
"lock; xchgl %0, %1" is the actual assembly code to be emitted. It has two placeholders, %0 and %1, which the compiler must replace before emitting the instruction, and the following lines tell it how to do so. The
"+m" ( *addr ) tells the compiler that %0 shall refer to the memory location which contains the value of
addr, and the
+ in particular means that this address is both read from and written to. The
"=a" ( result ) means that %1 shall be replaced with the "a" register (which is actually eax here, since the operand size is 32 bit), and that the contents of this register is stored in the variable
result after the operation. The next line
"1" ( newval ) says that before the instruction, the register corresponding to placeholder %1 (so eax) shall be filled with the contents of
newval. The last line
"cc" informs the compiler that also condition codes in eflags wll change during the operation, so it shall not rely on them being preserved. See
http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html for more information.
Not this is what a
simple test gives me, if I remove the "inline" attribute:
Code:
movl 4(%esp), %edx
movl 8(%esp), %eax
lock; xchgl (%edx), %eax
ret
The first line moves the address that
addr points to into the edx register, while the second line moves the contents of
newval into eax. The third line atomically exchanges the contents of the memory location that edx points to with the contents of eax. Now whatever was at that memory location is in eax. But this is also what the function is supposed to return, namely
result, so there is nothing left to do, because eax is just the place where a function returns its return value, and that value is already there. So the function simply returns.
So mostly this is about understanding how inline assembly works with input and output operands. The actual result will still be a bit more tricky because the "inline" at the beginning tells the compiler to inline the function instead of emitting it as shown here. But I guess you get the point.