The problem is that you load mx_state into the register (the restriction is “r”) and then exchange with the registers only by writing the result to mx_state at the end of the asm code. What you want is more like
asm( "movl $0x01,%%eax\n\t" // move 1 to eax "xchg %%eax,%1\n\t" // try to set the lock bit "mov %%eax,%0\n\t" // export our result to a test var :"=r"(failure) :"m" (mutexlock->mx_state) :"%eax" );
Even this is somewhat dangerous, since theoretically the compiler can load mx_state, spill it into the slot of the local temporary package and make xchg there. It is also somewhat inefficient, as it has hard gestures that may not be needed, but cannot be eliminated by the optimizer. You better use a simpler asm that expands to a single command, e.g.
failure = 1; asm("xchg %0,0(%1)" : "=r" (failure) : "r" (&mutex->mx_state), "0" (failure));
Notice how we force the use of mx_state in place using its address rather than its value.
Chris dodd
source share