This is the mail archive of the java@gcc.gnu.org mailing list for the Java 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]

Re: Using __kuser_cmpxchg


On Friday 16 November 2007 02:17, Nicolas Pitre wrote:
> On Fri, 16 Nov 2007, Paul Brook wrote:
> > > >  > In the mean time you can work around it by using a mutex around
> > > >  > the thread state modification instead of using cmpxchg on it.  Or
> > > >  > if your platform is ARMv6 or higher then you won't get those
> > > >  > spurious false negatives.
> > > >
> > > > Ah, OK, that's interesting: it sounds like you understand under what
> > > > circumstances it may fail "spuriously".
> > >
> > > Heh, I wrote that code (and comment).  :-)
> > >
> > > > What are these?
> > >
> > > On a pre-ARMv6 processor
> >
> > Similar "spurious" failures can happen on ARMv6 processors.
> >
> > ARMv6 cpus don't have atomic operations either. They have ldrex/strex,
> > where the latter will fail if another CPU modifies the memory *or* a
> > context switch occurs.
>
> Due to the current implementation this is indeed true.
>
> ARMv6 is more trivial to fix though, since the operation can be
> reattempted whenever the strex fails.

Hello All,

may it be, I am off topic and do not see real problem,
but I have next idea.

There could occur four cases during cmpxchg/CAS processing

                 no disturbance    exception, etc.
  old==actual        succeed         FAIL
  old!=actual        fail            fail

The problematic case from the caller point of view is the false
"FAIL" case which could be incompatible with some other logic
(requires retry/busy loop) even that in "fail" case some other
activity - sleep report failure etc.

The expected can be achieved by two ways:
 - wrap up cmpxchg_orig() such way, that

   cmpxchg(ptr, old, new)
     do {
       ret = cmpxchg_orig()
     } while ((ret!=old) && (*ptr==old));

 - do the same in the assembly by replacing teqeq with instruction
   storing result 

        r2 ... ptr
        r0 ... old
        r1 ... new

+1:
        teq     ip, ip                  @ set Z flag
        ldr     ip, [r2]                @ load current val
        add     r3, r2, #1              @ prepare store ptr
-       teqeq   ip, r0                  @ compare with oldval if still allowed
+       subeqs  ip, ip, r0              @ compare with oldval if still allowed
        streq   r1, [r3, #-1]!          @ store newval if still allowed
        subs    r0, r2, r3              @ if r2 == r3 the str occured
-       usr_ret  lr
+       bxcc     lr                     @ succeed, return with C clear
+       adds     ip, ip, #-1            @ compare ip to zero, but Z flag cannot be used
+       bcc      1b                     @ jump if old == *ptr
+       bx       lr                     @ return with C set

I do not know if this second little more complex solution is possible
there or it would burden atomic add and others expecting false negatives
too much.

BX should not be used directly, but I do not know, if there exists
conditionalized usr_ret variant.

Best wishes

              Pavel Pisa


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