LDREX/STREX and pre-emption on SMP hardware
flat view
From: catalin.marinas@arm.com (Catalin Marinas)
Date: 2009-09-14 14:29:36
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:quoted
On Mon, 2009-09-14 at 11:00 +0100, Russell King - ARM Linux wrote:quoted
On Mon, Sep 14, 2009 at 02:43:53AM +0100, Jamie Lokier wrote:quoted
Catalin Marinas wrote:quoted
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) STREXAs 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:quoted
quoted
T1 T2 LDREXCLREXquoted
quoted
LDREX STREXEQ (not satsified)CLREXquoted
quoted
STREXwhich 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