home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / x86 / include / asm / atomic_32.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  5.9 KB  |  260 lines

  1. #ifndef _ASM_X86_ATOMIC_32_H
  2. #define _ASM_X86_ATOMIC_32_H
  3.  
  4. #include <linux/compiler.h>
  5. #include <asm/processor.h>
  6. #include <asm/cmpxchg.h>
  7.  
  8. /*
  9.  * Atomic operations that C can't guarantee us.  Useful for
  10.  * resource counting etc..
  11.  */
  12.  
  13. /*
  14.  * Make sure gcc doesn't try to be clever and move things around
  15.  * on us. We need to use _exactly_ the address the user gave us,
  16.  * not some alias that contains the same information.
  17.  */
  18. typedef struct {
  19.     int counter;
  20. } atomic_t;
  21.  
  22. #define ATOMIC_INIT(i)    { (i) }
  23.  
  24. /**
  25.  * atomic_read - read atomic variable
  26.  * @v: pointer of type atomic_t
  27.  *
  28.  * Atomically reads the value of @v.
  29.  */
  30. #define atomic_read(v)        ((v)->counter)
  31.  
  32. /**
  33.  * atomic_set - set atomic variable
  34.  * @v: pointer of type atomic_t
  35.  * @i: required value
  36.  *
  37.  * Atomically sets the value of @v to @i.
  38.  */
  39. #define atomic_set(v, i)    (((v)->counter) = (i))
  40.  
  41. /**
  42.  * atomic_add - add integer to atomic variable
  43.  * @i: integer value to add
  44.  * @v: pointer of type atomic_t
  45.  *
  46.  * Atomically adds @i to @v.
  47.  */
  48. static inline void atomic_add(int i, atomic_t *v)
  49. {
  50.     asm volatile(LOCK_PREFIX "addl %1,%0"
  51.              : "+m" (v->counter)
  52.              : "ir" (i));
  53. }
  54.  
  55. /**
  56.  * atomic_sub - subtract integer from atomic variable
  57.  * @i: integer value to subtract
  58.  * @v: pointer of type atomic_t
  59.  *
  60.  * Atomically subtracts @i from @v.
  61.  */
  62. static inline void atomic_sub(int i, atomic_t *v)
  63. {
  64.     asm volatile(LOCK_PREFIX "subl %1,%0"
  65.              : "+m" (v->counter)
  66.              : "ir" (i));
  67. }
  68.  
  69. /**
  70.  * atomic_sub_and_test - subtract value from variable and test result
  71.  * @i: integer value to subtract
  72.  * @v: pointer of type atomic_t
  73.  *
  74.  * Atomically subtracts @i from @v and returns
  75.  * true if the result is zero, or false for all
  76.  * other cases.
  77.  */
  78. static inline int atomic_sub_and_test(int i, atomic_t *v)
  79. {
  80.     unsigned char c;
  81.  
  82.     asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
  83.              : "+m" (v->counter), "=qm" (c)
  84.              : "ir" (i) : "memory");
  85.     return c;
  86. }
  87.  
  88. /**
  89.  * atomic_inc - increment atomic variable
  90.  * @v: pointer of type atomic_t
  91.  *
  92.  * Atomically increments @v by 1.
  93.  */
  94. static inline void atomic_inc(atomic_t *v)
  95. {
  96.     asm volatile(LOCK_PREFIX "incl %0"
  97.              : "+m" (v->counter));
  98. }
  99.  
  100. /**
  101.  * atomic_dec - decrement atomic variable
  102.  * @v: pointer of type atomic_t
  103.  *
  104.  * Atomically decrements @v by 1.
  105.  */
  106. static inline void atomic_dec(atomic_t *v)
  107. {
  108.     asm volatile(LOCK_PREFIX "decl %0"
  109.              : "+m" (v->counter));
  110. }
  111.  
  112. /**
  113.  * atomic_dec_and_test - decrement and test
  114.  * @v: pointer of type atomic_t
  115.  *
  116.  * Atomically decrements @v by 1 and
  117.  * returns true if the result is 0, or false for all other
  118.  * cases.
  119.  */
  120. static inline int atomic_dec_and_test(atomic_t *v)
  121. {
  122.     unsigned char c;
  123.  
  124.     asm volatile(LOCK_PREFIX "decl %0; sete %1"
  125.              : "+m" (v->counter), "=qm" (c)
  126.              : : "memory");
  127.     return c != 0;
  128. }
  129.  
  130. /**
  131.  * atomic_inc_and_test - increment and test
  132.  * @v: pointer of type atomic_t
  133.  *
  134.  * Atomically increments @v by 1
  135.  * and returns true if the result is zero, or false for all
  136.  * other cases.
  137.  */
  138. static inline int atomic_inc_and_test(atomic_t *v)
  139. {
  140.     unsigned char c;
  141.  
  142.     asm volatile(LOCK_PREFIX "incl %0; sete %1"
  143.              : "+m" (v->counter), "=qm" (c)
  144.              : : "memory");
  145.     return c != 0;
  146. }
  147.  
  148. /**
  149.  * atomic_add_negative - add and test if negative
  150.  * @v: pointer of type atomic_t
  151.  * @i: integer value to add
  152.  *
  153.  * Atomically adds @i to @v and returns true
  154.  * if the result is negative, or false when
  155.  * result is greater than or equal to zero.
  156.  */
  157. static inline int atomic_add_negative(int i, atomic_t *v)
  158. {
  159.     unsigned char c;
  160.  
  161.     asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
  162.              : "+m" (v->counter), "=qm" (c)
  163.              : "ir" (i) : "memory");
  164.     return c;
  165. }
  166.  
  167. /**
  168.  * atomic_add_return - add integer and return
  169.  * @v: pointer of type atomic_t
  170.  * @i: integer value to add
  171.  *
  172.  * Atomically adds @i to @v and returns @i + @v
  173.  */
  174. static inline int atomic_add_return(int i, atomic_t *v)
  175. {
  176.     int __i;
  177. #ifdef CONFIG_M386
  178.     unsigned long flags;
  179.     if (unlikely(boot_cpu_data.x86 <= 3))
  180.         goto no_xadd;
  181. #endif
  182.     /* Modern 486+ processor */
  183.     __i = i;
  184.     asm volatile(LOCK_PREFIX "xaddl %0, %1"
  185.              : "+r" (i), "+m" (v->counter)
  186.              : : "memory");
  187.     return i + __i;
  188.  
  189. #ifdef CONFIG_M386
  190. no_xadd: /* Legacy 386 processor */
  191.     local_irq_save(flags);
  192.     __i = atomic_read(v);
  193.     atomic_set(v, i + __i);
  194.     local_irq_restore(flags);
  195.     return i + __i;
  196. #endif
  197. }
  198.  
  199. /**
  200.  * atomic_sub_return - subtract integer and return
  201.  * @v: pointer of type atomic_t
  202.  * @i: integer value to subtract
  203.  *
  204.  * Atomically subtracts @i from @v and returns @v - @i
  205.  */
  206. static inline int atomic_sub_return(int i, atomic_t *v)
  207. {
  208.     return atomic_add_return(-i, v);
  209. }
  210.  
  211. #define atomic_cmpxchg(v, old, new) (cmpxchg(&((v)->counter), (old), (new)))
  212. #define atomic_xchg(v, new) (xchg(&((v)->counter), (new)))
  213.  
  214. /**
  215.  * atomic_add_unless - add unless the number is already a given value
  216.  * @v: pointer of type atomic_t
  217.  * @a: the amount to add to v...
  218.  * @u: ...unless v is equal to u.
  219.  *
  220.  * Atomically adds @a to @v, so long as @v was not already @u.
  221.  * Returns non-zero if @v was not @u, and zero otherwise.
  222.  */
  223. static inline int atomic_add_unless(atomic_t *v, int a, int u)
  224. {
  225.     int c, old;
  226.     c = atomic_read(v);
  227.     for (;;) {
  228.         if (unlikely(c == (u)))
  229.             break;
  230.         old = atomic_cmpxchg((v), c, c + (a));
  231.         if (likely(old == c))
  232.             break;
  233.         c = old;
  234.     }
  235.     return c != (u);
  236. }
  237.  
  238. #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
  239.  
  240. #define atomic_inc_return(v)  (atomic_add_return(1, v))
  241. #define atomic_dec_return(v)  (atomic_sub_return(1, v))
  242.  
  243. /* These are x86-specific, used by some header files */
  244. #define atomic_clear_mask(mask, addr)                \
  245.     asm volatile(LOCK_PREFIX "andl %0,%1"            \
  246.              : : "r" (~(mask)), "m" (*(addr)) : "memory")
  247.  
  248. #define atomic_set_mask(mask, addr)                \
  249.     asm volatile(LOCK_PREFIX "orl %0,%1"                \
  250.              : : "r" (mask), "m" (*(addr)) : "memory")
  251.  
  252. /* Atomic operations are already serializing on x86 */
  253. #define smp_mb__before_atomic_dec()    barrier()
  254. #define smp_mb__after_atomic_dec()    barrier()
  255. #define smp_mb__before_atomic_inc()    barrier()
  256. #define smp_mb__after_atomic_inc()    barrier()
  257.  
  258. #include <asm-generic/atomic.h>
  259. #endif /* _ASM_X86_ATOMIC_32_H */
  260.