atomic64_64.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #ifndef _ASM_X86_ATOMIC64_64_H
  2. #define _ASM_X86_ATOMIC64_64_H
  3. #include <linux/types.h>
  4. #include <asm/alternative.h>
  5. #include <asm/cmpxchg.h>
  6. /* The 64-bit atomic type */
  7. #define ATOMIC64_INIT(i) { (i) }
  8. /**
  9. * atomic64_read - read atomic64 variable
  10. * @v: pointer of type atomic64_t
  11. *
  12. * Atomically reads the value of @v.
  13. * Doesn't imply a read memory barrier.
  14. */
  15. static inline long atomic64_read(const atomic64_t *v)
  16. {
  17. return (*(volatile long *)&(v)->counter);
  18. }
  19. /**
  20. * atomic64_set - set atomic64 variable
  21. * @v: pointer to type atomic64_t
  22. * @i: required value
  23. *
  24. * Atomically sets the value of @v to @i.
  25. */
  26. static inline void atomic64_set(atomic64_t *v, long i)
  27. {
  28. v->counter = i;
  29. }
  30. /**
  31. * atomic64_add - add integer to atomic64 variable
  32. * @i: integer value to add
  33. * @v: pointer to type atomic64_t
  34. *
  35. * Atomically adds @i to @v.
  36. */
  37. static inline void atomic64_add(long i, atomic64_t *v)
  38. {
  39. asm volatile(LOCK_PREFIX "addq %1,%0"
  40. : "=m" (v->counter)
  41. : "er" (i), "m" (v->counter));
  42. }
  43. /**
  44. * atomic64_sub - subtract the atomic64 variable
  45. * @i: integer value to subtract
  46. * @v: pointer to type atomic64_t
  47. *
  48. * Atomically subtracts @i from @v.
  49. */
  50. static inline void atomic64_sub(long i, atomic64_t *v)
  51. {
  52. asm volatile(LOCK_PREFIX "subq %1,%0"
  53. : "=m" (v->counter)
  54. : "er" (i), "m" (v->counter));
  55. }
  56. /**
  57. * atomic64_sub_and_test - subtract value from variable and test result
  58. * @i: integer value to subtract
  59. * @v: pointer to type atomic64_t
  60. *
  61. * Atomically subtracts @i from @v and returns
  62. * true if the result is zero, or false for all
  63. * other cases.
  64. */
  65. static inline int atomic64_sub_and_test(long i, atomic64_t *v)
  66. {
  67. GEN_BINARY_RMWcc(LOCK_PREFIX "subq", v->counter, i, "%0", "e");
  68. }
  69. /**
  70. * atomic64_inc - increment atomic64 variable
  71. * @v: pointer to type atomic64_t
  72. *
  73. * Atomically increments @v by 1.
  74. */
  75. static inline void atomic64_inc(atomic64_t *v)
  76. {
  77. asm volatile(LOCK_PREFIX "incq %0"
  78. : "=m" (v->counter)
  79. : "m" (v->counter));
  80. }
  81. /**
  82. * atomic64_dec - decrement atomic64 variable
  83. * @v: pointer to type atomic64_t
  84. *
  85. * Atomically decrements @v by 1.
  86. */
  87. static inline void atomic64_dec(atomic64_t *v)
  88. {
  89. asm volatile(LOCK_PREFIX "decq %0"
  90. : "=m" (v->counter)
  91. : "m" (v->counter));
  92. }
  93. /**
  94. * atomic64_dec_and_test - decrement and test
  95. * @v: pointer to type atomic64_t
  96. *
  97. * Atomically decrements @v by 1 and
  98. * returns true if the result is 0, or false for all other
  99. * cases.
  100. */
  101. static inline int atomic64_dec_and_test(atomic64_t *v)
  102. {
  103. GEN_UNARY_RMWcc(LOCK_PREFIX "decq", v->counter, "%0", "e");
  104. }
  105. /**
  106. * atomic64_inc_and_test - increment and test
  107. * @v: pointer to type atomic64_t
  108. *
  109. * Atomically increments @v by 1
  110. * and returns true if the result is zero, or false for all
  111. * other cases.
  112. */
  113. static inline int atomic64_inc_and_test(atomic64_t *v)
  114. {
  115. GEN_UNARY_RMWcc(LOCK_PREFIX "incq", v->counter, "%0", "e");
  116. }
  117. /**
  118. * atomic64_add_negative - add and test if negative
  119. * @i: integer value to add
  120. * @v: pointer to type atomic64_t
  121. *
  122. * Atomically adds @i to @v and returns true
  123. * if the result is negative, or false when
  124. * result is greater than or equal to zero.
  125. */
  126. static inline int atomic64_add_negative(long i, atomic64_t *v)
  127. {
  128. GEN_BINARY_RMWcc(LOCK_PREFIX "addq", v->counter, i, "%0", "s");
  129. }
  130. /**
  131. * atomic64_add_return - add and return
  132. * @i: integer value to add
  133. * @v: pointer to type atomic64_t
  134. *
  135. * Atomically adds @i to @v and returns @i + @v
  136. */
  137. static inline long atomic64_add_return(long i, atomic64_t *v)
  138. {
  139. return i + xadd(&v->counter, i);
  140. }
  141. static inline long atomic64_sub_return(long i, atomic64_t *v)
  142. {
  143. return atomic64_add_return(-i, v);
  144. }
  145. #define atomic64_inc_return(v) (atomic64_add_return(1, (v)))
  146. #define atomic64_dec_return(v) (atomic64_sub_return(1, (v)))
  147. static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new)
  148. {
  149. return cmpxchg(&v->counter, old, new);
  150. }
  151. static inline long atomic64_xchg(atomic64_t *v, long new)
  152. {
  153. return xchg(&v->counter, new);
  154. }
  155. /**
  156. * atomic64_add_unless - add unless the number is a given value
  157. * @v: pointer of type atomic64_t
  158. * @a: the amount to add to v...
  159. * @u: ...unless v is equal to u.
  160. *
  161. * Atomically adds @a to @v, so long as it was not @u.
  162. * Returns the old value of @v.
  163. */
  164. static inline int atomic64_add_unless(atomic64_t *v, long a, long u)
  165. {
  166. long c, old;
  167. c = atomic64_read(v);
  168. for (;;) {
  169. if (unlikely(c == (u)))
  170. break;
  171. old = atomic64_cmpxchg((v), c, c + (a));
  172. if (likely(old == c))
  173. break;
  174. c = old;
  175. }
  176. return c != (u);
  177. }
  178. #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
  179. /*
  180. * atomic64_dec_if_positive - decrement by 1 if old value positive
  181. * @v: pointer of type atomic_t
  182. *
  183. * The function returns the old value of *v minus 1, even if
  184. * the atomic variable, v, was not decremented.
  185. */
  186. static inline long atomic64_dec_if_positive(atomic64_t *v)
  187. {
  188. long c, old, dec;
  189. c = atomic64_read(v);
  190. for (;;) {
  191. dec = c - 1;
  192. if (unlikely(dec < 0))
  193. break;
  194. old = atomic64_cmpxchg((v), c, dec);
  195. if (likely(old == c))
  196. break;
  197. c = old;
  198. }
  199. return dec;
  200. }
  201. #endif /* _ASM_X86_ATOMIC64_64_H */