Subj : atomic powerpc To : netscape.public.mozilla.jseng From : Kevin Diggs Date : Wed Jun 01 2005 01:02 pm Hi, I am trying to add native ppc linux atomic support. It's, like ya know, not going well. Crashin, floppin, n droppin. So far I have managed to create a random interval ~40M core file creator. Crash frequency increases with system load. First off, am I barking up a tree that has no benefit to being barked up, so to speak? Someone thought this was a good idea for x86? Assumming there is some benefit ... The crashes (segv) appear to occur when releasing locks (nv=0). Assumming the compare (ov==*w) never fails (valid assumption?) for the nv=0 case, is it possible for the x86 js_CompareAndSwap() to fail when nv=0? I may be way off base (gee, what are the odds) but if I understand it, the semantics of atomic operations between the x86 and ppc architectures are quite different. The x86 uses a locked read-modify-write bus access. While the ppc uses this reservation stuff to detect unauthorized poking around. Seems to me that this means that lock manipulation fails will be more frequent on ppc. The original version stopped at the andi. It caused crashes near JS_AtomizeString() (js_CompareAndSwap() was not in the stack trace). The current version, which retries if nv=0 and the compare succeeded, causes crashes in js_CompareAndSwap(). That's progress, right? Can someone who knows ppc assembly more better than me (that is anyone who knows ppc assembly) take a look and see if you see what I are doing wrong? Here is the patch for jslock.c (somewhere near 1.8b, and ignore the 386 stuff hopefully it is not getting run): --- jslock-old_c Wed Dec 8 17:32:19 2004 +++ jslock-new_c Wed Jun 1 10:45:47 2005 @@ -107,7 +107,41 @@ js_CompareAndSwap(jsword *w, jsword ov, jsword nv) { unsigned int res; - +#ifdef MOZ_BUILD_FOR_386 +//printf(__FILE__"-%d: ov=0x%x, nv=0x%x, *w=0x%x\n",__LINE__,ov,nv,*w); +//fflush(stdout); + /* + * I have stolen the MSBit for 386 use. If it is used something bad is + * gonna happen ... sooner or later. Might as well die now. + */ + JS_ASSERT(((ov|nv)&0x80000000)==0); + JS_ASSERT(ov==0 || nv==0); + + __asm__ __volatile__ ( + "L0: lock " + "btsl $31,(%1)\n" + "jnc L4\n" +#if 0 + "L1: btl $31,(%1)\n" + "jc L1\n" + "jmp L0\n" +#else + "xor %%al,%%al\n" + "jmp L3\n" +#endif + "L4: orl $0x80000000,%%eax\n" + "cmpl %%eax,(%1)\n" + "jne L2\n" + "movl %2,(%1)\n" + "jmp L3\n" + "L2: btrl $31,(%1)\n" + "L3: sete %%al\n" + "movzx %%al,%%eax\n" + : "=a" (res) + : "r" (w), "r" (nv), "a" (ov) + : "cc", "memory"); +//printf("\n"); +#else __asm__ __volatile__ ( "lock\n" "cmpxchgl %2, (%1)\n" @@ -116,7 +150,49 @@ : "=a" (res) : "r" (w), "r" (nv), "a" (ov) : "cc", "memory"); +#endif return (int)res; +} + +#elif defined(__GNUC__) && defined(__powerpc__) + +static JS_INLINE int +js_CompareAndSwap(jsword *w, jsword ov, jsword nv) +{ + unsigned int res; + static int fail=0; +#if 0 + printf(__FILE__"-%d: ov=0x%x, nv=0x%x, *w=0x%x\n",__LINE__,ov,nv,*w); + fflush(stdout); +#endif + __asm__ __volatile__ ( + "3: lwarx 6,0,%0\n" + "cmpw 7,6,%1\n" + "bne- 7,1f\n" + "mr 6,%2\n" + "1: stwcx. 6,0,%0\n" + "crand 4*cr7+so,eq,4*cr7+eq\n" + "mfcr %0\n" + "andi. %0,%0,1\n" + "bso+ 7,2f\n" + "cmpwi 6,%2,0\n" + "crand 4*cr6+eq,4*cr7+eq,4*cr6+eq\n" + "beq- 6,3b\n" + "2:\n" + : "=r" (res) + : "r" (ov), "r" (nv), "0" (w) + : "cc", "memory","r6"); +#if 0 + if(!res) + { + fail++; + + printf(__FILE__"-%d: ov=0x%x, nv=0x%x, *w=0x%x: fail count is %d\n", + __LINE__,ov,nv,*w,fail); + fflush(stdout); + } +#endif + return (int) res; } #elif defined(SOLARIS) && defined(sparc) && defined(ULTRA_SPARC) Here is post mortem stack trace from gdb: (gdb) whe #0 0x0f71bea8 in kill () from /lib/libc.so.6 #1 0x0fd23f90 in pthread_kill (thread=1024, signo=11) at signals.c:65 #2 0x0fd245f8 in raise (sig=11) at signals.c:232 #3 0x0e9d47b4 in nsProfileLock::FatalSignalHandler () from /mnt/mnt0/mozilla/suite-opt/dist/bin/components/libprofile.so #4 0x0fd240b4 in pthread_sighandler (signo=11, ctx=0x7fffd910) at signals.c:97 #5 #6 0x0fe4ecd0 in js_CompareAndSwap (w=0x10095f48, ov=268575912, nv=0) at /mnt/mnt0/mozilla/js/src/jslock.c:168 #7 0x0fe506a0 in js_Unlock (tl=0x10095f48, me=268575912) at /mnt/mnt0/mozilla/js/src/jslock.c:1092 #8 0x0fe20cac in js_AtomizeString () from suite-opt/dist/bin/libmozjs.so #9 0x0fe20df0 in js_AtomizeChars () from suite-opt/dist/bin/libmozjs.so #10 0x0fe77568 in js_GetToken () from suite-opt/dist/bin/libmozjs.so #11 0x0fe76984 in js_PeekToken () from suite-opt/dist/bin/libmozjs.so #12 0x0fe6581c in Statements () from suite-opt/dist/bin/libmozjs.so #13 0x0fe64b64 in FunctionBody () from suite-opt/dist/bin/libmozjs.so #14 0x0fe6543c in FunctionDef () from suite-opt/dist/bin/libmozjs.so #15 0x0fe65624 in FunctionExpr () from suite-opt/dist/bin/libmozjs.so #16 0x0fe6abf4 in PrimaryExpr () from suite-opt/dist/bin/libmozjs.so #17 0x0fe692fc in MemberExpr () from suite-opt/dist/bin/libmozjs.so #18 0x0fe68fa8 in UnaryExpr () from suite-opt/dist/bin/libmozjs.so #19 0x0fe68a98 in MulExpr () from suite-opt/dist/bin/libmozjs.so Don't enable the lower debug code. That causes crashes with 2 js_CompareAndSwap()s on the stack. Is that a threadism (i.e. can't do I/O in a thread)? System is a PowerMac8600 with a PowerLogix 750GX cpu card running YellowDog 2.1 (kernel 2.4.30), compiler and binutils built from YDL 2.3 src rpms: gcc-2.95.4-4j binutils-2.11.93.0.2-3b kevin .