This is the mail archive of the libc-ports@sources.redhat.com mailing list for the libc-ports project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Update ARM atomic operations question


This is a question regarding the patch posted on Wed, 5 Oct 2005 and entitled "Update ARM atomic operations". I'm puzzling about the 2 versions of the compare_and_swap primitive included in the patch:
- with the first version (inline function), 'result' indicates success (1) or failure (0), with the macro version, 'result' seems to always hold the memory value whatever the result of the operation: is it right? and if yes, why? (I've commented the assembly code below with pseudo code and comments to give my understanding of the code)
- I guess there is a strong rationale behind the two step approach: a) getting the actual value, comparing with the expected value b) trying to swap, but why not directly doing the swap? is it to avoid the race condition in 6) as much as possible?
- and finally, why moving from an inline typed function implementation to a raw untyped macro?


Thanks in advance for your reply,
Dominique Fober


static inline int
__attribute__ ((unused))
compare_and_swap (volatile long int *p, long int oldval, long int newval)
{
int result, tmp;
__asm__ ("\n"
"0:\tldr\t%1,[%2]\n\t" a) tmp = *p load *p into tmp
"mov\t%0,#0\n\t" b) result=0 clear result (0=failure)
"cmp\t%1,%4\n\t" c) if (tmp != oldval) compare tmp and oldval
"bne\t1f\n\t" d) goto 1 if not equal, branch to end)
"swp\t%0,%3,[%2]\n\t" e| result=*p swap newval and p content - > result
e| *p= newval
"cmp\t%1,%0\n\t" f) if (result != tmp) compare result and tmp
"swpne\t%1,%0,[%2]\n\t" g| tmp=*p if not equal, swap result and p content -> tmp (cc flags not affected)
g| *p=result
"bne\t0b\n\t" h) goto 0 if not equal, loop to a)
"mov\t%0,#1\n" i) result=1 set result (1=success)
"1:"
: "=&r" (result), "=&r" (tmp)
: "r" (p), "r" (newval), "r" (oldval)
: "cc", "memory");
return result;
}




#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \
({ __typeof (oldval) result, tmp; \
__asm__ ("\n" \
"0:\tldr\t%1,[%2]\n\t" \ 1) tmp = *mem load *mem into tmp
"cmp\t%1,%4\n\t" \ 2) if (tmp != oldval) compare tmp and oldval
"movne\t%0,%1\n\t" \ 3) result=tmp if not equal, move tmp to result (cc flags not affected)
"bne\t1f\n\t" \ 4) goto 1 if not equal, branch to end)
"swp\t%0,%3,[%2]\n\t" \ 5| result=*mem swap newval and mem content -> result
5| *mem= newval
"cmp\t%1,%0\n\t" \ 6) if (result != tmp) compare result and tmp
"swpne\t%1,%0,[%2]\n\t" \ 7| tmp=*mem if not equal, swap result and mem content -> tmp (cc flags not affected)
7| *mem=result
"bne\t0b\n\t" \ 8) goto 0 if not equal, loop to 1)
"1:" \ end)
: "=&r" (result), "=&r" (tmp) \
: "r" (mem), "r" (newval), "r" (oldval) \
: "cc", "memory"); \
result; })




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]