LDREX/STREX and pre-emption on SMP hardware

Catalin Marinas catalin.marinas at arm.com
Mon Sep 14 10:29:36 EDT 2009


On Mon, 2009-09-14 at 15:23 +0100, Russell King - ARM Linux wrote:
> On Mon, Sep 14, 2009 at 11:06:13AM +0100, Catalin Marinas wrote:
> > On Mon, 2009-09-14 at 11:00 +0100, Russell King - ARM Linux wrote:
> > > On Mon, Sep 14, 2009 at 02:43:53AM +0100, Jamie Lokier wrote:
> > > > Catalin Marinas wrote:
> > > > > With interrupts (I1, I2 interrupt handlers)
> > > > > 
> > > > > I1			I2
> > > > > LDREX
> > > > > 			LDREX
> > > > > 			STREX (succeeds)
> > > > > STREX (fails)
> > > > > 
> > > > > In the interrupt case, they are nested so the STREX in I2 is always
> > > > > executed before STREX in I1 (you can extrapolate with several nested
> > > > > interrupts).
> > > > 
> > > > This assumes LDREX/STREX are always called in pairs.  But this is in
> > > > fact _not_ the case.  Take a look at atomic_cmpxchg:
> > > > 
> > > > 	do {
> > > > 		__asm__ __volatile__("@ atomic_cmpxchg\n"
> > > > 		"ldrex	%1, [%2]\n"
> > > > 		"mov	%0, #0\n"
> > > > 		"teq	%1, %3\n"
> > > > 		"strexeq %0, %4, [%2]\n"
> > > > 		    : "=&r" (res), "=&r" (oldval)
> > > > 		    : "r" (&ptr->counter), "Ir" (old), "r" (new)
> > > > 		    : "cc");
> > > > 	} while (res);
> > > > 
> > > > In the case where ptr->counter != old, STREX is not executed, and the
> > > > do{...}while loop does not loop.  Thus LDREX/STREX aren't paired.
> > > 
> > > It doesn't matter though - consider two threads using LDREX on the same
> > > location:
> > > 
> > > 	T1		T2
> > > 	LDREX
> > > 			LDREX
> > > 			STREXEQ (not satsified)
> > > 	STREX
> > 
> > As I replied to Jamie on a similar issue, you can have:
> > 
> > T1			T2
> > LDREX
> > 			LDREX
> > 			STREXEQ (satisfied, succeeds)
> > 			LDREX
> > 			STREXEQ (not satisfied)
> > STREX (succeeds)
> > 
> > Though this may be an unlikely sequence.
> 
> Actually, both of these can't happen because they imply a context switch
> and a context switch clears the exclusive monitor.  

T2 here in an interrupt handler (misleadingly called thread, though the
architecture people here in ARM just call everything a thread of
execution). Jamie's reply here was referring to interrupt handlers.

> So the real sequence
> is:
> 
> > > 	T1		T2
> > > 	LDREX
> 		CLREX
> > > 			LDREX
> > > 			STREXEQ (not satsified)
> 		CLREX
> > > 	STREX
> 
> which results in the STREX not succeeding.  Ditto for your case.

The other case where I replied was discussing the need for CLREX at
context switch and that's needed to get the correct behaviour (T1 and T2
are OS threads in this case).

-- 
Catalin




More information about the linux-arm-kernel mailing list