LDREX/STREX and pre-emption on SMP hardware

Jamie Lokier jamie at shareable.org
Mon Sep 14 19:16:18 EDT 2009


Catalin Marinas wrote:
>  #define atomic_read(v)	((v)->counter)
> +#define atomic_set(v,i)	(((v)->counter) = (i))
>  
>  #if __LINUX_ARM_ARCH__ >= 6
>  
>  /*
>   * ARMv6 UP and SMP safe atomic ops.  We use load exclusive and
>   * store exclusive to ensure that these are atomic.  We may loop
> - * to ensure that the update happens.  Writing to 'v->counter'
> - * without using the following operations WILL break the atomic
> - * nature of these ops.
> + * to ensure that the update happens.
>   */
> -static inline void atomic_set(atomic_t *v, int i)
> -{
> -	unsigned long tmp;
> -
> -	__asm__ __volatile__("@ atomic_set\n"
> -"1:	ldrex	%0, [%1]\n"
> -"	strex	%0, %2, [%1]\n"
> -"	teq	%0, #0\n"
> -"	bne	1b"
> -	: "=&r" (tmp)
> -	: "r" (&v->counter), "r" (i)
> -	: "cc");
> -}

I was going to say this won't work, because I'd read this in
<asm/atomic.h>:

    /* Atomic operations are already serializing on ARM */
    #define smp_mb__before_atomic_dec()    barrier()
    [etc]

and imagined that atomic_set() needed to provide the same.

But then but then I spotted Documentation/atomic_ops.txt:

    *** WARNING: atomic_read() and atomic_set() DO NOT IMPLY BARRIERS! ***

So that's alright then.

Besides, it turns out the comment in <asm/atomic.h> was wrong, and was
removed recently, with explicit barrier instructions being added where
expected.

Regarding the patch, a command saying _why_ it's ok for atomic_set()
to be a simple assignment would be good:

    /*
     * On ARM, ordinary assignment (str instruction) doesn't clear the
     * _local_ strex/ldrex monitor on some implementations.  The
     * reason we can use it for atomic_set() is the clrex or dummy
     * strex done on every exception return and context switch.
     */

-- Jamie



More information about the linux-arm-kernel mailing list