This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: Using __kuser_cmpxchg
- From: Pavel Pisa <ppisa4lists at pikron dot com>
- To: linux-arm-kernel at lists dot arm dot linux dot org dot uk
- Cc: Nicolas Pitre <nico at cam dot org>, Paul Brook <paul at codesourcery dot com>, Andrew Haley <aph-gcc at littlepinkcloud dot com>, java at gcc dot gnu dot org
- Date: Fri, 16 Nov 2007 11:33:32 +0100
- Subject: Re: Using __kuser_cmpxchg
- References: <200711151759.lAFHxKa4027497@devserv.devel.redhat.com> <200711160025.03542.paul@codesourcery.com> <alpine.LFD.0.9999.0711152013320.21255@xanadu.home>
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