home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-x86_64 / atomic.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  9.7 KB  |  430 lines

  1. #ifndef __ARCH_X86_64_ATOMIC__
  2. #define __ARCH_X86_64_ATOMIC__
  3.  
  4. #include <asm/alternative.h>
  5.  
  6. /* atomic_t should be 32 bit signed type */
  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 { volatile int counter; } atomic_t;
  19.  
  20. #define ATOMIC_INIT(i)    { (i) }
  21.  
  22. /**
  23.  * atomic_read - read atomic variable
  24.  * @v: pointer of type atomic_t
  25.  * 
  26.  * Atomically reads the value of @v.
  27.  */ 
  28. #define atomic_read(v)        ((v)->counter)
  29.  
  30. /**
  31.  * atomic_set - set atomic variable
  32.  * @v: pointer of type atomic_t
  33.  * @i: required value
  34.  * 
  35.  * Atomically sets the value of @v to @i.
  36.  */ 
  37. #define atomic_set(v,i)        (((v)->counter) = (i))
  38.  
  39. /**
  40.  * atomic_add - add integer to atomic variable
  41.  * @i: integer value to add
  42.  * @v: pointer of type atomic_t
  43.  * 
  44.  * Atomically adds @i to @v.
  45.  */
  46. static __inline__ void atomic_add(int i, atomic_t *v)
  47. {
  48.     __asm__ __volatile__(
  49.         LOCK_PREFIX "addl %1,%0"
  50.         :"=m" (v->counter)
  51.         :"ir" (i), "m" (v->counter));
  52. }
  53.  
  54. /**
  55.  * atomic_sub - subtract the atomic variable
  56.  * @i: integer value to subtract
  57.  * @v: pointer of type atomic_t
  58.  * 
  59.  * Atomically subtracts @i from @v.
  60.  */
  61. static __inline__ void atomic_sub(int i, atomic_t *v)
  62. {
  63.     __asm__ __volatile__(
  64.         LOCK_PREFIX "subl %1,%0"
  65.         :"=m" (v->counter)
  66.         :"ir" (i), "m" (v->counter));
  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__(
  83.         LOCK_PREFIX "subl %2,%0; sete %1"
  84.         :"=m" (v->counter), "=qm" (c)
  85.         :"ir" (i), "m" (v->counter) : "memory");
  86.     return c;
  87. }
  88.  
  89. /**
  90.  * atomic_inc - increment atomic variable
  91.  * @v: pointer of type atomic_t
  92.  * 
  93.  * Atomically increments @v by 1.
  94.  */ 
  95. static __inline__ void atomic_inc(atomic_t *v)
  96. {
  97.     __asm__ __volatile__(
  98.         LOCK_PREFIX "incl %0"
  99.         :"=m" (v->counter)
  100.         :"m" (v->counter));
  101. }
  102.  
  103. /**
  104.  * atomic_dec - decrement atomic variable
  105.  * @v: pointer of type atomic_t
  106.  * 
  107.  * Atomically decrements @v by 1.
  108.  */ 
  109. static __inline__ void atomic_dec(atomic_t *v)
  110. {
  111.     __asm__ __volatile__(
  112.         LOCK_PREFIX "decl %0"
  113.         :"=m" (v->counter)
  114.         :"m" (v->counter));
  115. }
  116.  
  117. /**
  118.  * atomic_dec_and_test - decrement and test
  119.  * @v: pointer of type atomic_t
  120.  * 
  121.  * Atomically decrements @v by 1 and
  122.  * returns true if the result is 0, or false for all other
  123.  * cases.
  124.  */ 
  125. static __inline__ int atomic_dec_and_test(atomic_t *v)
  126. {
  127.     unsigned char c;
  128.  
  129.     __asm__ __volatile__(
  130.         LOCK_PREFIX "decl %0; sete %1"
  131.         :"=m" (v->counter), "=qm" (c)
  132.         :"m" (v->counter) : "memory");
  133.     return c != 0;
  134. }
  135.  
  136. /**
  137.  * atomic_inc_and_test - increment and test 
  138.  * @v: pointer of type atomic_t
  139.  * 
  140.  * Atomically increments @v by 1
  141.  * and returns true if the result is zero, or false for all
  142.  * other cases.
  143.  */ 
  144. static __inline__ int atomic_inc_and_test(atomic_t *v)
  145. {
  146.     unsigned char c;
  147.  
  148.     __asm__ __volatile__(
  149.         LOCK_PREFIX "incl %0; sete %1"
  150.         :"=m" (v->counter), "=qm" (c)
  151.         :"m" (v->counter) : "memory");
  152.     return c != 0;
  153. }
  154.  
  155. /**
  156.  * atomic_add_negative - add and test if negative
  157.  * @i: integer value to add
  158.  * @v: pointer of type atomic_t
  159.  * 
  160.  * Atomically adds @i to @v and returns true
  161.  * if the result is negative, or false when
  162.  * result is greater than or equal to zero.
  163.  */ 
  164. static __inline__ int atomic_add_negative(int i, atomic_t *v)
  165. {
  166.     unsigned char c;
  167.  
  168.     __asm__ __volatile__(
  169.         LOCK_PREFIX "addl %2,%0; sets %1"
  170.         :"=m" (v->counter), "=qm" (c)
  171.         :"ir" (i), "m" (v->counter) : "memory");
  172.     return c;
  173. }
  174.  
  175. /**
  176.  * atomic_add_return - add and return
  177.  * @i: integer value to add
  178.  * @v: pointer of type atomic_t
  179.  *
  180.  * Atomically adds @i to @v and returns @i + @v
  181.  */
  182. static __inline__ int atomic_add_return(int i, atomic_t *v)
  183. {
  184.     int __i = i;
  185.     __asm__ __volatile__(
  186.         LOCK_PREFIX "xaddl %0, %1;"
  187.         :"=r"(i)
  188.         :"m"(v->counter), "0"(i));
  189.     return i + __i;
  190. }
  191.  
  192. static __inline__ int atomic_sub_return(int i, atomic_t *v)
  193. {
  194.     return atomic_add_return(-i,v);
  195. }
  196.  
  197. #define atomic_inc_return(v)  (atomic_add_return(1,v))
  198. #define atomic_dec_return(v)  (atomic_sub_return(1,v))
  199.  
  200. /* An 64bit atomic type */
  201.  
  202. typedef struct { volatile long counter; } atomic64_t;
  203.  
  204. #define ATOMIC64_INIT(i)    { (i) }
  205.  
  206. /**
  207.  * atomic64_read - read atomic64 variable
  208.  * @v: pointer of type atomic64_t
  209.  *
  210.  * Atomically reads the value of @v.
  211.  * Doesn't imply a read memory barrier.
  212.  */
  213. #define atomic64_read(v)        ((v)->counter)
  214.  
  215. /**
  216.  * atomic64_set - set atomic64 variable
  217.  * @v: pointer to type atomic64_t
  218.  * @i: required value
  219.  *
  220.  * Atomically sets the value of @v to @i.
  221.  */
  222. #define atomic64_set(v,i)        (((v)->counter) = (i))
  223.  
  224. /**
  225.  * atomic64_add - add integer to atomic64 variable
  226.  * @i: integer value to add
  227.  * @v: pointer to type atomic64_t
  228.  *
  229.  * Atomically adds @i to @v.
  230.  */
  231. static __inline__ void atomic64_add(long i, atomic64_t *v)
  232. {
  233.     __asm__ __volatile__(
  234.         LOCK_PREFIX "addq %1,%0"
  235.         :"=m" (v->counter)
  236.         :"ir" (i), "m" (v->counter));
  237. }
  238.  
  239. /**
  240.  * atomic64_sub - subtract the atomic64 variable
  241.  * @i: integer value to subtract
  242.  * @v: pointer to type atomic64_t
  243.  *
  244.  * Atomically subtracts @i from @v.
  245.  */
  246. static __inline__ void atomic64_sub(long i, atomic64_t *v)
  247. {
  248.     __asm__ __volatile__(
  249.         LOCK_PREFIX "subq %1,%0"
  250.         :"=m" (v->counter)
  251.         :"ir" (i), "m" (v->counter));
  252. }
  253.  
  254. /**
  255.  * atomic64_sub_and_test - subtract value from variable and test result
  256.  * @i: integer value to subtract
  257.  * @v: pointer to type atomic64_t
  258.  *
  259.  * Atomically subtracts @i from @v and returns
  260.  * true if the result is zero, or false for all
  261.  * other cases.
  262.  */
  263. static __inline__ int atomic64_sub_and_test(long i, atomic64_t *v)
  264. {
  265.     unsigned char c;
  266.  
  267.     __asm__ __volatile__(
  268.         LOCK_PREFIX "subq %2,%0; sete %1"
  269.         :"=m" (v->counter), "=qm" (c)
  270.         :"ir" (i), "m" (v->counter) : "memory");
  271.     return c;
  272. }
  273.  
  274. /**
  275.  * atomic64_inc - increment atomic64 variable
  276.  * @v: pointer to type atomic64_t
  277.  *
  278.  * Atomically increments @v by 1.
  279.  */
  280. static __inline__ void atomic64_inc(atomic64_t *v)
  281. {
  282.     __asm__ __volatile__(
  283.         LOCK_PREFIX "incq %0"
  284.         :"=m" (v->counter)
  285.         :"m" (v->counter));
  286. }
  287.  
  288. /**
  289.  * atomic64_dec - decrement atomic64 variable
  290.  * @v: pointer to type atomic64_t
  291.  *
  292.  * Atomically decrements @v by 1.
  293.  */
  294. static __inline__ void atomic64_dec(atomic64_t *v)
  295. {
  296.     __asm__ __volatile__(
  297.         LOCK_PREFIX "decq %0"
  298.         :"=m" (v->counter)
  299.         :"m" (v->counter));
  300. }
  301.  
  302. /**
  303.  * atomic64_dec_and_test - decrement and test
  304.  * @v: pointer to type atomic64_t
  305.  *
  306.  * Atomically decrements @v by 1 and
  307.  * returns true if the result is 0, or false for all other
  308.  * cases.
  309.  */
  310. static __inline__ int atomic64_dec_and_test(atomic64_t *v)
  311. {
  312.     unsigned char c;
  313.  
  314.     __asm__ __volatile__(
  315.         LOCK_PREFIX "decq %0; sete %1"
  316.         :"=m" (v->counter), "=qm" (c)
  317.         :"m" (v->counter) : "memory");
  318.     return c != 0;
  319. }
  320.  
  321. /**
  322.  * atomic64_inc_and_test - increment and test
  323.  * @v: pointer to type atomic64_t
  324.  *
  325.  * Atomically increments @v by 1
  326.  * and returns true if the result is zero, or false for all
  327.  * other cases.
  328.  */
  329. static __inline__ int atomic64_inc_and_test(atomic64_t *v)
  330. {
  331.     unsigned char c;
  332.  
  333.     __asm__ __volatile__(
  334.         LOCK_PREFIX "incq %0; sete %1"
  335.         :"=m" (v->counter), "=qm" (c)
  336.         :"m" (v->counter) : "memory");
  337.     return c != 0;
  338. }
  339.  
  340. /**
  341.  * atomic64_add_negative - add and test if negative
  342.  * @i: integer value to add
  343.  * @v: pointer to type atomic64_t
  344.  *
  345.  * Atomically adds @i to @v and returns true
  346.  * if the result is negative, or false when
  347.  * result is greater than or equal to zero.
  348.  */
  349. static __inline__ int atomic64_add_negative(long i, atomic64_t *v)
  350. {
  351.     unsigned char c;
  352.  
  353.     __asm__ __volatile__(
  354.         LOCK_PREFIX "addq %2,%0; sets %1"
  355.         :"=m" (v->counter), "=qm" (c)
  356.         :"ir" (i), "m" (v->counter) : "memory");
  357.     return c;
  358. }
  359.  
  360. /**
  361.  * atomic64_add_return - add and return
  362.  * @i: integer value to add
  363.  * @v: pointer to type atomic64_t
  364.  *
  365.  * Atomically adds @i to @v and returns @i + @v
  366.  */
  367. static __inline__ long atomic64_add_return(long i, atomic64_t *v)
  368. {
  369.     long __i = i;
  370.     __asm__ __volatile__(
  371.         LOCK_PREFIX "xaddq %0, %1;"
  372.         :"=r"(i)
  373.         :"m"(v->counter), "0"(i));
  374.     return i + __i;
  375. }
  376.  
  377. static __inline__ long atomic64_sub_return(long i, atomic64_t *v)
  378. {
  379.     return atomic64_add_return(-i,v);
  380. }
  381.  
  382. #define atomic64_inc_return(v)  (atomic64_add_return(1,v))
  383. #define atomic64_dec_return(v)  (atomic64_sub_return(1,v))
  384.  
  385. #define atomic_cmpxchg(v, old, new) ((int)cmpxchg(&((v)->counter), old, new))
  386. #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
  387.  
  388. /**
  389.  * atomic_add_unless - add unless the number is a given value
  390.  * @v: pointer of type atomic_t
  391.  * @a: the amount to add to v...
  392.  * @u: ...unless v is equal to u.
  393.  *
  394.  * Atomically adds @a to @v, so long as it was not @u.
  395.  * Returns non-zero if @v was not @u, and zero otherwise.
  396.  */
  397. #define atomic_add_unless(v, a, u)                \
  398. ({                                \
  399.     int c, old;                        \
  400.     c = atomic_read(v);                    \
  401.     for (;;) {                        \
  402.         if (unlikely(c == (u)))                \
  403.             break;                    \
  404.         old = atomic_cmpxchg((v), c, c + (a));        \
  405.         if (likely(old == c))                \
  406.             break;                    \
  407.         c = old;                    \
  408.     }                            \
  409.     c != (u);                        \
  410. })
  411. #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
  412.  
  413. /* These are x86-specific, used by some header files */
  414. #define atomic_clear_mask(mask, addr) \
  415. __asm__ __volatile__(LOCK_PREFIX "andl %0,%1" \
  416. : : "r" (~(mask)),"m" (*addr) : "memory")
  417.  
  418. #define atomic_set_mask(mask, addr) \
  419. __asm__ __volatile__(LOCK_PREFIX "orl %0,%1" \
  420. : : "r" ((unsigned)mask),"m" (*(addr)) : "memory")
  421.  
  422. /* Atomic operations are already serializing on x86 */
  423. #define smp_mb__before_atomic_dec()    barrier()
  424. #define smp_mb__after_atomic_dec()    barrier()
  425. #define smp_mb__before_atomic_inc()    barrier()
  426. #define smp_mb__after_atomic_inc()    barrier()
  427.  
  428. #include <asm-generic/atomic.h>
  429. #endif
  430.