linux-bk/include/asm-i386/atomic.h
<<
>>
Prefs
   1#ifndef __ARCH_I386_ATOMIC__
   2#define __ARCH_I386_ATOMIC__
   3
   4#include <linux/config.h>
   5
   6/*
   7 * Atomic operations that C can't guarantee us.  Useful for
   8 * resource counting etc..
   9 */
  10
  11#ifdef CONFIG_SMP
  12#define LOCK "lock ; "
  13#else
  14#define LOCK ""
  15#endif
  16
  17/*
  18 * Make sure gcc doesn't try to be clever and move things around
  19 * on us. We need to use _exactly_ the address the user gave us,
  20 * not some alias that contains the same information.
  21 */
  22typedef struct { volatile int counter; } atomic_t;
  23
  24#define ATOMIC_INIT(i)  { (i) }
  25
  26/**
  27 * atomic_read - read atomic variable
  28 * @v: pointer of type atomic_t
  29 * 
  30 * Atomically reads the value of @v.
  31 */ 
  32#define atomic_read(v)          ((v)->counter)
  33
  34/**
  35 * atomic_set - set atomic variable
  36 * @v: pointer of type atomic_t
  37 * @i: required value
  38 * 
  39 * Atomically sets the value of @v to @i.
  40 */ 
  41#define atomic_set(v,i)         (((v)->counter) = (i))
  42
  43/**
  44 * atomic_add - add integer to atomic variable
  45 * @i: integer value to add
  46 * @v: pointer of type atomic_t
  47 * 
  48 * Atomically adds @i to @v.
  49 */
  50static __inline__ void atomic_add(int i, atomic_t *v)
  51{
  52        __asm__ __volatile__(
  53                LOCK "addl %1,%0"
  54                :"=m" (v->counter)
  55                :"ir" (i), "m" (v->counter));
  56}
  57
  58/**
  59 * atomic_sub - subtract the atomic variable
  60 * @i: integer value to subtract
  61 * @v: pointer of type atomic_t
  62 * 
  63 * Atomically subtracts @i from @v.
  64 */
  65static __inline__ void atomic_sub(int i, atomic_t *v)
  66{
  67        __asm__ __volatile__(
  68                LOCK "subl %1,%0"
  69                :"=m" (v->counter)
  70                :"ir" (i), "m" (v->counter));
  71}
  72
  73/**
  74 * atomic_sub_and_test - subtract value from variable and test result
  75 * @i: integer value to subtract
  76 * @v: pointer of type atomic_t
  77 * 
  78 * Atomically subtracts @i from @v and returns
  79 * true if the result is zero, or false for all
  80 * other cases.
  81 */
  82static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
  83{
  84        unsigned char c;
  85
  86        __asm__ __volatile__(
  87                LOCK "subl %2,%0; sete %1"
  88                :"=m" (v->counter), "=qm" (c)
  89                :"ir" (i), "m" (v->counter) : "memory");
  90        return c;
  91}
  92
  93/**
  94 * atomic_inc - increment atomic variable
  95 * @v: pointer of type atomic_t
  96 * 
  97 * Atomically increments @v by 1.
  98 */ 
  99static __inline__ void atomic_inc(atomic_t *v)
 100{
 101        __asm__ __volatile__(
 102                LOCK "incl %0"
 103                :"=m" (v->counter)
 104                :"m" (v->counter));
 105}
 106
 107/**
 108 * atomic_dec - decrement atomic variable
 109 * @v: pointer of type atomic_t
 110 * 
 111 * Atomically decrements @v by 1.
 112 */ 
 113static __inline__ void atomic_dec(atomic_t *v)
 114{
 115        __asm__ __volatile__(
 116                LOCK "decl %0"
 117                :"=m" (v->counter)
 118                :"m" (v->counter));
 119}
 120
 121/**
 122 * atomic_dec_and_test - decrement and test
 123 * @v: pointer of type atomic_t
 124 * 
 125 * Atomically decrements @v by 1 and
 126 * returns true if the result is 0, or false for all other
 127 * cases.
 128 */ 
 129static __inline__ int atomic_dec_and_test(atomic_t *v)
 130{
 131        unsigned char c;
 132
 133        __asm__ __volatile__(
 134                LOCK "decl %0; sete %1"
 135                :"=m" (v->counter), "=qm" (c)
 136                :"m" (v->counter) : "memory");
 137        return c != 0;
 138}
 139
 140/**
 141 * atomic_inc_and_test - increment and test 
 142 * @v: pointer of type atomic_t
 143 * 
 144 * Atomically increments @v by 1
 145 * and returns true if the result is zero, or false for all
 146 * other cases.
 147 */ 
 148static __inline__ int atomic_inc_and_test(atomic_t *v)
 149{
 150        unsigned char c;
 151
 152        __asm__ __volatile__(
 153                LOCK "incl %0; sete %1"
 154                :"=m" (v->counter), "=qm" (c)
 155                :"m" (v->counter) : "memory");
 156        return c != 0;
 157}
 158
 159/**
 160 * atomic_add_negative - add and test if negative
 161 * @v: pointer of type atomic_t
 162 * @i: integer value to add
 163 * 
 164 * Atomically adds @i to @v and returns true
 165 * if the result is negative, or false when
 166 * result is greater than or equal to zero.
 167 */ 
 168static __inline__ int atomic_add_negative(int i, atomic_t *v)
 169{
 170        unsigned char c;
 171
 172        __asm__ __volatile__(
 173                LOCK "addl %2,%0; sets %1"
 174                :"=m" (v->counter), "=qm" (c)
 175                :"ir" (i), "m" (v->counter) : "memory");
 176        return c;
 177}
 178
 179/* These are x86-specific, used by some header files */
 180#define atomic_clear_mask(mask, addr) \
 181__asm__ __volatile__(LOCK "andl %0,%1" \
 182: : "r" (~(mask)),"m" (*addr) : "memory")
 183
 184#define atomic_set_mask(mask, addr) \
 185__asm__ __volatile__(LOCK "orl %0,%1" \
 186: : "r" (mask),"m" (*(addr)) : "memory")
 187
 188/* Atomic operations are already serializing on x86 */
 189#define smp_mb__before_atomic_dec()     barrier()
 190#define smp_mb__after_atomic_dec()      barrier()
 191#define smp_mb__before_atomic_inc()     barrier()
 192#define smp_mb__after_atomic_inc()      barrier()
 193
 194#endif
 195
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.