Results 1 to 2 of 2
I'm working on a program where I've implemented a wrapper around an assembly atomic compare-and-exchange function. It seems to "work" correctly in some cases... however... in one case (implementation of ...
- 07-18-2007 #1Just Joined!
- Join Date
- Jan 2005
- Posts
- 3
gcc asm (x86) issue
I'm working on a program where I've implemented a wrapper around an assembly atomic compare-and-exchange function. It seems to "work" correctly in some cases... however... in one case (implementation of a type of spin-lock) it does not. Here is the assembly block:
And here is how it is being called in this case:Code://Compares expectedValue with the value at pInt, and if they are the same, sets pInt to newValue and returns true with outResultValue set to newValue. If they are different then pInt is unaffected, and returns false with outResultValue set to the value that was found at pInt. inline bool AtomicCompareExchange(volatile unsigned int *pInt, unsigned int expectedValue, unsigned int newValue, volatile unsigned int &outResultValue) { unsigned int changed=0; unsigned int rval; asm( "lock cmpxchgl %4, (%2);" "jnz AtomCmpExch_Diff%=;" "movl %%ecx, %%eax;" "incl %1;" "AtomCmpExch_Diff%=:;" "movl %%eax, %0;" :"=g"(rval), "=g"(changed) :"b"(pInt), "a"(expectedValue), "c"(newValue) :"memory", "cc"); outResultValue=rval; return changed!=0; }
Interesting to note also, when compiled using g++ with -g, the problem does not occur. When compiled with -O2 it does show up. Similar assembly written in intel format and compiled on msvc (this is a cross-platform project) also does not have this problem (with or without optimizations).Code://TODO: check for single processor system bool isSingleProc=false; // unsigned int yawn; while (!AtomicCompareExchange(&locker.taken, 0, 1, yawn)) { locker.collision=true; if (isSingleProc) Sleep(0); }
I'm still relatively new to g++'s asm syntax... am I just missing something in the clobbered list maybe? It doesn't let me add any registers I've used in the input/output list there.
- 07-19-2007 #2Just Joined!
- Join Date
- Jan 2005
- Posts
- 3
I've messed with it a very little... it's currently:
I see the problem though from looking at the disassembly it generated in one case.Code:inline bool AtomicCompareExchange(volatile unsigned int *pInt, unsigned int expectedValue, unsigned int newValue, volatile unsigned int &outResultValue) { unsigned int changed=0; unsigned int rval; asm( "lock cmpxchgl %4, (%2);" "jnz AtomCmpExch_Diff%=;" "movl %4, %%eax;" "incl %1;" "AtomCmpExch_Diff%=:;" "movl %%eax, %0;" :"=g"(rval), "=g"(changed) :"r"(pInt), "a"(expectedValue), "r"(newValue) :"memory", "cc"); outResultValue=rval; return changed!=0; }
Being called like:
Here's the relevant part generated:Code:uint someInt=1000; unsigned int newVal=0; bool changed=AtomicCompareExchange(&someInt,900,800,newVal); if (changed) ......
...it then uses edx (the "return value") in a jnz.Code:mov $0x320,%edx movl $0x0,0xffffffdc(%ebp) movl $0x3e8,0xffffffe0(%ebp) lock cmpxchg %edx,(%esi) jne 0x804bdd9 <AtomCmpExch_Diff1012> mov %edx,%eax mov $0x1,%edx mov %eax,%eax test %edx,%edx
Looking at that.. there's no possible way for edx to be 0 there. Is this a bug in the compiler/assembler? I'm running out of ideas here. If this forum is meant for less technical questions, can anyone point me to one more specialized in lower level issues like this?


Reply With Quote