Subject: Re: Inline Assembly queries

From: Andrew Haley <[email-masked]>
Date: Tue, 30 Jun 2009 10:30:53 +0100

kernel mailz wrote:
> Consider atomic_add and atomic_add_return in kernel code.
> 
> On Tue, Jun 30, 2009 at 2:59 AM, Ian Lance Taylor<[email-masked]> wrote:
>> kernel mailz <[email-masked]> writes:
>>
>>> I tried a small example
>>>
>>> int *p = 0x1000;
>>> int a = *p;
>>> asm("sync":::"memory");
>>> a = *p;
>>>
>>> and
>>>
>>> volatile int *p = 0x1000;
>>> int a = *p;
>>> asm("sync");
>>> a = *p
>>>
>>> Got the same assembly.
>>> Which is right.
>>>
>>> So does it mean, if proper use of volatile is done, there is no need
>>> of "memory" ?
>> You have to consider the effects of inlining, which may bring in other
>> memory loads and stores through non-volatile pointers.

> Consider
> 
> static __inline__ void atomic_add(int a, atomic_t *v)
> {
>         int t;
> 
>         __asm__ __volatile__(
> "1:     lwarx   %0,0,%3         # atomic_add\n\
>         add     %0,%2,%0\n"
>         PPC405_ERR77(0,%3)
> "       stwcx.  %0,0,%3 \n\
>         bne-    1b"
>         : "=&r" (t), "+m" (v->counter)
>         : "r" (a), "r" (&v->counter)
>         : "cc");
> }
> 
> static __inline__ int atomic_add_return(int a, atomic_t *v)
> {
>         int t;
> 
>         __asm__ __volatile__(
>         LWSYNC_ON_SMP
> "1:     lwarx   %0,0,%2         # atomic_add_return\n\
>         add     %0,%1,%0\n"
>         PPC405_ERR77(0,%2)
> "       stwcx.  %0,0,%2 \n\
>         bne-    1b"
>         ISYNC_ON_SMP
>         : "=&r" (t)
>         : "r" (a), "r" (&v->counter)
>         : "cc", "memory");
> 
>         return t;
> }
> 
> I am not able to figure out why "memory" is added in latter

The latter, as well as its stated purpose, forms a memory barrier, so the
compiler must be prevented from moving memory access across it.  See
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2745.html

Andrew.