linux-old/include/asm-ppc/atomic.h
<<
>>
Prefs
   1/*
   2 * PowerPC atomic operations
   3 */
   4
   5#ifndef _ASM_PPC_ATOMIC_H_
   6#define _ASM_PPC_ATOMIC_H_
   7
   8typedef struct { volatile int counter; } atomic_t;
   9
  10#ifdef __KERNEL__
  11
  12#define ATOMIC_INIT(i)  { (i) }
  13
  14#define atomic_read(v)          ((v)->counter)
  15#define atomic_set(v,i)         (((v)->counter) = (i))
  16
  17extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
  18extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
  19
  20#ifdef CONFIG_SMP
  21#define SMP_ISYNC       "\n\tisync"
  22#else
  23#define SMP_ISYNC
  24#endif
  25
  26/* Erratum #77 on the 405 means we need a sync or dcbt before every stwcx.
  27 * The old ATOMIC_SYNC_FIX covered some but not all of this.
  28 */
  29#ifdef CONFIG_IBM405_ERR77
  30#define PPC405_ERR77(ra,rb)     "dcbt " #ra "," #rb ";"
  31#else
  32#define PPC405_ERR77(ra,rb)
  33#endif
  34
  35static __inline__ void atomic_add(int a, atomic_t *v)
  36{
  37        int t;
  38
  39        __asm__ __volatile__(
  40"1:     lwarx   %0,0,%3         # atomic_add\n\
  41        add     %0,%2,%0\n"
  42        PPC405_ERR77(0,%3)
  43"       stwcx.  %0,0,%3 \n\
  44        bne-    1b"
  45        : "=&r" (t), "=m" (v->counter)
  46        : "r" (a), "r" (&v->counter), "m" (v->counter)
  47        : "cc");
  48}
  49
  50static __inline__ int atomic_add_return(int a, atomic_t *v)
  51{
  52        int t;
  53
  54        __asm__ __volatile__(
  55"1:     lwarx   %0,0,%2         # atomic_add_return\n\
  56        add     %0,%1,%0\n"
  57        PPC405_ERR77(0,%2)
  58"       stwcx.  %0,0,%2 \n\
  59        bne-    1b"
  60        SMP_ISYNC
  61        : "=&r" (t)
  62        : "r" (a), "r" (&v->counter)
  63        : "cc", "memory");
  64
  65        return t;
  66}
  67
  68static __inline__ void atomic_sub(int a, atomic_t *v)
  69{
  70        int t;
  71
  72        __asm__ __volatile__(
  73"1:     lwarx   %0,0,%3         # atomic_sub\n\
  74        subf    %0,%2,%0\n"
  75        PPC405_ERR77(0,%3)
  76"       stwcx.  %0,0,%3 \n\
  77        bne-    1b"
  78        : "=&r" (t), "=m" (v->counter)
  79        : "r" (a), "r" (&v->counter), "m" (v->counter)
  80        : "cc");
  81}
  82
  83static __inline__ int atomic_sub_return(int a, atomic_t *v)
  84{
  85        int t;
  86
  87        __asm__ __volatile__(
  88"1:     lwarx   %0,0,%2         # atomic_sub_return\n\
  89        subf    %0,%1,%0\n"
  90        PPC405_ERR77(0,%2)
  91"       stwcx.  %0,0,%2 \n\
  92        bne-    1b"
  93        SMP_ISYNC
  94        : "=&r" (t)
  95        : "r" (a), "r" (&v->counter)
  96        : "cc", "memory");
  97
  98        return t;
  99}
 100
 101static __inline__ void atomic_inc(atomic_t *v)
 102{
 103        int t;
 104
 105        __asm__ __volatile__(
 106"1:     lwarx   %0,0,%2         # atomic_inc\n\
 107        addic   %0,%0,1\n"
 108        PPC405_ERR77(0,%2)
 109"       stwcx.  %0,0,%2 \n\
 110        bne-    1b"
 111        : "=&r" (t), "=m" (v->counter)
 112        : "r" (&v->counter), "m" (v->counter)
 113        : "cc");
 114}
 115
 116static __inline__ int atomic_inc_return(atomic_t *v)
 117{
 118        int t;
 119
 120        __asm__ __volatile__(
 121"1:     lwarx   %0,0,%1         # atomic_inc_return\n\
 122        addic   %0,%0,1\n"
 123        PPC405_ERR77(0,%1)
 124"       stwcx.  %0,0,%1 \n\
 125        bne-    1b"
 126        SMP_ISYNC
 127        : "=&r" (t)
 128        : "r" (&v->counter)
 129        : "cc", "memory");
 130
 131        return t;
 132}
 133
 134static __inline__ void atomic_dec(atomic_t *v)
 135{
 136        int t;
 137
 138        __asm__ __volatile__(
 139"1:     lwarx   %0,0,%2         # atomic_dec\n\
 140        addic   %0,%0,-1\n"
 141        PPC405_ERR77(0,%2)\
 142"       stwcx.  %0,0,%2\n\
 143        bne-    1b"
 144        : "=&r" (t), "=m" (v->counter)
 145        : "r" (&v->counter), "m" (v->counter)
 146        : "cc");
 147}
 148
 149static __inline__ int atomic_dec_return(atomic_t *v)
 150{
 151        int t;
 152
 153        __asm__ __volatile__(
 154"1:     lwarx   %0,0,%1         # atomic_dec_return\n\
 155        addic   %0,%0,-1\n"
 156        PPC405_ERR77(0,%1)
 157"       stwcx.  %0,0,%1\n\
 158        bne-    1b"
 159        SMP_ISYNC
 160        : "=&r" (t)
 161        : "r" (&v->counter)
 162        : "cc", "memory");
 163
 164        return t;
 165}
 166
 167#define atomic_sub_and_test(a, v)       (atomic_sub_return((a), (v)) == 0)
 168#define atomic_dec_and_test(v)          (atomic_dec_return((v)) == 0)
 169
 170/*
 171 * Atomically test *v and decrement if it is greater than 0.
 172 * The function returns the old value of *v minus 1.
 173 */
 174static __inline__ int atomic_dec_if_positive(atomic_t *v)
 175{
 176        int t;
 177
 178        __asm__ __volatile__(
 179"1:     lwarx   %0,0,%1         # atomic_dec_if_positive\n\
 180        addic.  %0,%0,-1\n\
 181        blt-    2f\n"
 182        PPC405_ERR77(0,%1)
 183"       stwcx.  %0,0,%1\n\
 184        bne-    1b"
 185        SMP_ISYNC
 186        "\n\
 1872:"     : "=&r" (t)
 188        : "r" (&v->counter)
 189        : "cc", "memory");
 190
 191        return t;
 192}
 193
 194#define smp_mb__before_atomic_dec()     smp_mb()
 195#define smp_mb__after_atomic_dec()      smp_mb()
 196#define smp_mb__before_atomic_inc()     smp_mb()
 197#define smp_mb__after_atomic_inc()      smp_mb()
 198
 199#endif /* __KERNEL__ */
 200#endif /* _ASM_PPC_ATOMIC_H_ */
 201
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.