linux/arch/alpha/include/asm/atomic.h
<<
>>
Prefs
   1#ifndef _ALPHA_ATOMIC_H
   2#define _ALPHA_ATOMIC_H
   3
   4#include <asm/barrier.h>
   5#include <asm/system.h>
   6
   7/*
   8 * Atomic operations that C can't guarantee us.  Useful for
   9 * resource counting etc...
  10 *
  11 * But use these as seldom as possible since they are much slower
  12 * than regular operations.
  13 */
  14
  15
  16/*
  17 * Counter is volatile to make sure gcc doesn't try to be clever
  18 * and move things around on us. We need to use _exactly_ the address
  19 * the user gave us, not some alias that contains the same information.
  20 */
  21typedef struct { volatile int counter; } atomic_t;
  22typedef struct { volatile long counter; } atomic64_t;
  23
  24#define ATOMIC_INIT(i)          ( (atomic_t) { (i) } )
  25#define ATOMIC64_INIT(i)        ( (atomic64_t) { (i) } )
  26
  27#define atomic_read(v)          ((v)->counter + 0)
  28#define atomic64_read(v)        ((v)->counter + 0)
  29
  30#define atomic_set(v,i)         ((v)->counter = (i))
  31#define atomic64_set(v,i)       ((v)->counter = (i))
  32
  33/*
  34 * To get proper branch prediction for the main line, we must branch
  35 * forward to code at the end of this object's .text section, then
  36 * branch back to restart the operation.
  37 */
  38
  39static __inline__ void atomic_add(int i, atomic_t * v)
  40{
  41        unsigned long temp;
  42        __asm__ __volatile__(
  43        "1:     ldl_l %0,%1\n"
  44        "       addl %0,%2,%0\n"
  45        "       stl_c %0,%1\n"
  46        "       beq %0,2f\n"
  47        ".subsection 2\n"
  48        "2:     br 1b\n"
  49        ".previous"
  50        :"=&r" (temp), "=m" (v->counter)
  51        :"Ir" (i), "m" (v->counter));
  52}
  53
  54static __inline__ void atomic64_add(long i, atomic64_t * v)
  55{
  56        unsigned long temp;
  57        __asm__ __volatile__(
  58        "1:     ldq_l %0,%1\n"
  59        "       addq %0,%2,%0\n"
  60        "       stq_c %0,%1\n"
  61        "       beq %0,2f\n"
  62        ".subsection 2\n"
  63        "2:     br 1b\n"
  64        ".previous"
  65        :"=&r" (temp), "=m" (v->counter)
  66        :"Ir" (i), "m" (v->counter));
  67}
  68
  69static __inline__ void atomic_sub(int i, atomic_t * v)
  70{
  71        unsigned long temp;
  72        __asm__ __volatile__(
  73        "1:     ldl_l %0,%1\n"
  74        "       subl %0,%2,%0\n"
  75        "       stl_c %0,%1\n"
  76        "       beq %0,2f\n"
  77        ".subsection 2\n"
  78        "2:     br 1b\n"
  79        ".previous"
  80        :"=&r" (temp), "=m" (v->counter)
  81        :"Ir" (i), "m" (v->counter));
  82}
  83
  84static __inline__ void atomic64_sub(long i, atomic64_t * v)
  85{
  86        unsigned long temp;
  87        __asm__ __volatile__(
  88        "1:     ldq_l %0,%1\n"
  89        "       subq %0,%2,%0\n"
  90        "       stq_c %0,%1\n"
  91        "       beq %0,2f\n"
  92        ".subsection 2\n"
  93        "2:     br 1b\n"
  94        ".previous"
  95        :"=&r" (temp), "=m" (v->counter)
  96        :"Ir" (i), "m" (v->counter));
  97}
  98
  99
 100/*
 101 * Same as above, but return the result value
 102 */
 103static inline int atomic_add_return(int i, atomic_t *v)
 104{
 105        long temp, result;
 106        smp_mb();
 107        __asm__ __volatile__(
 108        "1:     ldl_l %0,%1\n"
 109        "       addl %0,%3,%2\n"
 110        "       addl %0,%3,%0\n"
 111        "       stl_c %0,%1\n"
 112        "       beq %0,2f\n"
 113        ".subsection 2\n"
 114        "2:     br 1b\n"
 115        ".previous"
 116        :"=&r" (temp), "=m" (v->counter), "=&r" (result)
 117        :"Ir" (i), "m" (v->counter) : "memory");
 118        smp_mb();
 119        return result;
 120}
 121
 122static __inline__ long atomic64_add_return(long i, atomic64_t * v)
 123{
 124        long temp, result;
 125        smp_mb();
 126        __asm__ __volatile__(
 127        "1:     ldq_l %0,%1\n"
 128        "       addq %0,%3,%2\n"
 129        "       addq %0,%3,%0\n"
 130        "       stq_c %0,%1\n"
 131        "       beq %0,2f\n"
 132        ".subsection 2\n"
 133        "2:     br 1b\n"
 134        ".previous"
 135        :"=&r" (temp), "=m" (v->counter), "=&r" (result)
 136        :"Ir" (i), "m" (v->counter) : "memory");
 137        smp_mb();
 138        return result;
 139}
 140
 141static __inline__ long atomic_sub_return(int i, atomic_t * v)
 142{
 143        long temp, result;
 144        smp_mb();
 145        __asm__ __volatile__(
 146        "1:     ldl_l %0,%1\n"
 147        "       subl %0,%3,%2\n"
 148        "       subl %0,%3,%0\n"
 149        "       stl_c %0,%1\n"
 150        "       beq %0,2f\n"
 151        ".subsection 2\n"
 152        "2:     br 1b\n"
 153        ".previous"
 154        :"=&r" (temp), "=m" (v->counter), "=&r" (result)
 155        :"Ir" (i), "m" (v->counter) : "memory");
 156        smp_mb();
 157        return result;
 158}
 159
 160static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
 161{
 162        long temp, result;
 163        smp_mb();
 164        __asm__ __volatile__(
 165        "1:     ldq_l %0,%1\n"
 166        "       subq %0,%3,%2\n"
 167        "       subq %0,%3,%0\n"
 168        "       stq_c %0,%1\n"
 169        "       beq %0,2f\n"
 170        ".subsection 2\n"
 171        "2:     br 1b\n"
 172        ".previous"
 173        :"=&r" (temp), "=m" (v->counter), "=&r" (result)
 174        :"Ir" (i), "m" (v->counter) : "memory");
 175        smp_mb();
 176        return result;
 177}
 178
 179#define atomic64_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
 180#define atomic64_xchg(v, new) (xchg(&((v)->counter), new))
 181
 182#define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), old, new))
 183#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
 184
 185/**
 186 * atomic_add_unless - add unless the number is a given value
 187 * @v: pointer of type atomic_t
 188 * @a: the amount to add to v...
 189 * @u: ...unless v is equal to u.
 190 *
 191 * Atomically adds @a to @v, so long as it was not @u.
 192 * Returns non-zero if @v was not @u, and zero otherwise.
 193 */
 194static __inline__ int atomic_add_unless(atomic_t *v, int a, int u)
 195{
 196        int c, old;
 197        c = atomic_read(v);
 198        for (;;) {
 199                if (unlikely(c == (u)))
 200                        break;
 201                old = atomic_cmpxchg((v), c, c + (a));
 202                if (likely(old == c))
 203                        break;
 204                c = old;
 205        }
 206        return c != (u);
 207}
 208
 209#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
 210
 211/**
 212 * atomic64_add_unless - add unless the number is a given value
 213 * @v: pointer of type atomic64_t
 214 * @a: the amount to add to v...
 215 * @u: ...unless v is equal to u.
 216 *
 217 * Atomically adds @a to @v, so long as it was not @u.
 218 * Returns non-zero if @v was not @u, and zero otherwise.
 219 */
 220static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
 221{
 222        long c, old;
 223        c = atomic64_read(v);
 224        for (;;) {
 225                if (unlikely(c == (u)))
 226                        break;
 227                old = atomic64_cmpxchg((v), c, c + (a));
 228                if (likely(old == c))
 229                        break;
 230                c = old;
 231        }
 232        return c != (u);
 233}
 234
 235#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 236
 237#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0)
 238#define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0)
 239
 240#define atomic_dec_return(v) atomic_sub_return(1,(v))
 241#define atomic64_dec_return(v) atomic64_sub_return(1,(v))
 242
 243#define atomic_inc_return(v) atomic_add_return(1,(v))
 244#define atomic64_inc_return(v) atomic64_add_return(1,(v))
 245
 246#define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
 247#define atomic64_sub_and_test(i,v) (atomic64_sub_return((i), (v)) == 0)
 248
 249#define atomic_inc_and_test(v) (atomic_add_return(1, (v)) == 0)
 250#define atomic64_inc_and_test(v) (atomic64_add_return(1, (v)) == 0)
 251
 252#define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
 253#define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0)
 254
 255#define atomic_inc(v) atomic_add(1,(v))
 256#define atomic64_inc(v) atomic64_add(1,(v))
 257
 258#define atomic_dec(v) atomic_sub(1,(v))
 259#define atomic64_dec(v) atomic64_sub(1,(v))
 260
 261#define smp_mb__before_atomic_dec()     smp_mb()
 262#define smp_mb__after_atomic_dec()      smp_mb()
 263#define smp_mb__before_atomic_inc()     smp_mb()
 264#define smp_mb__after_atomic_inc()      smp_mb()
 265
 266#include <asm-generic/atomic.h>
 267#endif /* _ALPHA_ATOMIC_H */
 268
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.