atomic.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /* Atomic operations usable in machine independent code */
  2. #ifndef _LINUX_ATOMIC_H
  3. #define _LINUX_ATOMIC_H
  4. #include <asm/atomic.h>
  5. /*
  6. * Provide __deprecated wrappers for the new interface, avoid flag day changes.
  7. * We need the ugly external functions to break header recursion hell.
  8. */
  9. #ifndef smp_mb__before_atomic_inc
  10. static inline void __deprecated smp_mb__before_atomic_inc(void)
  11. {
  12. extern void __smp_mb__before_atomic(void);
  13. __smp_mb__before_atomic();
  14. }
  15. #endif
  16. #ifndef smp_mb__after_atomic_inc
  17. static inline void __deprecated smp_mb__after_atomic_inc(void)
  18. {
  19. extern void __smp_mb__after_atomic(void);
  20. __smp_mb__after_atomic();
  21. }
  22. #endif
  23. #ifndef smp_mb__before_atomic_dec
  24. static inline void __deprecated smp_mb__before_atomic_dec(void)
  25. {
  26. extern void __smp_mb__before_atomic(void);
  27. __smp_mb__before_atomic();
  28. }
  29. #endif
  30. #ifndef smp_mb__after_atomic_dec
  31. static inline void __deprecated smp_mb__after_atomic_dec(void)
  32. {
  33. extern void __smp_mb__after_atomic(void);
  34. __smp_mb__after_atomic();
  35. }
  36. #endif
  37. /**
  38. * atomic_add_unless - add unless the number is already a given value
  39. * @v: pointer of type atomic_t
  40. * @a: the amount to add to v...
  41. * @u: ...unless v is equal to u.
  42. *
  43. * Atomically adds @a to @v, so long as @v was not already @u.
  44. * Returns non-zero if @v was not @u, and zero otherwise.
  45. */
  46. static inline int atomic_add_unless(atomic_t *v, int a, int u)
  47. {
  48. return __atomic_add_unless(v, a, u) != u;
  49. }
  50. /**
  51. * atomic_inc_not_zero - increment unless the number is zero
  52. * @v: pointer of type atomic_t
  53. *
  54. * Atomically increments @v by 1, so long as @v is non-zero.
  55. * Returns non-zero if @v was non-zero, and zero otherwise.
  56. */
  57. #ifndef atomic_inc_not_zero
  58. #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
  59. #endif
  60. /**
  61. * atomic_inc_not_zero_hint - increment if not null
  62. * @v: pointer of type atomic_t
  63. * @hint: probable value of the atomic before the increment
  64. *
  65. * This version of atomic_inc_not_zero() gives a hint of probable
  66. * value of the atomic. This helps processor to not read the memory
  67. * before doing the atomic read/modify/write cycle, lowering
  68. * number of bus transactions on some arches.
  69. *
  70. * Returns: 0 if increment was not done, 1 otherwise.
  71. */
  72. #ifndef atomic_inc_not_zero_hint
  73. static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint)
  74. {
  75. int val, c = hint;
  76. /* sanity test, should be removed by compiler if hint is a constant */
  77. if (!hint)
  78. return atomic_inc_not_zero(v);
  79. do {
  80. val = atomic_cmpxchg(v, c, c + 1);
  81. if (val == c)
  82. return 1;
  83. c = val;
  84. } while (c);
  85. return 0;
  86. }
  87. #endif
  88. #ifndef atomic_inc_unless_negative
  89. static inline int atomic_inc_unless_negative(atomic_t *p)
  90. {
  91. int v, v1;
  92. for (v = 0; v >= 0; v = v1) {
  93. v1 = atomic_cmpxchg(p, v, v + 1);
  94. if (likely(v1 == v))
  95. return 1;
  96. }
  97. return 0;
  98. }
  99. #endif
  100. #ifndef atomic_dec_unless_positive
  101. static inline int atomic_dec_unless_positive(atomic_t *p)
  102. {
  103. int v, v1;
  104. for (v = 0; v <= 0; v = v1) {
  105. v1 = atomic_cmpxchg(p, v, v - 1);
  106. if (likely(v1 == v))
  107. return 1;
  108. }
  109. return 0;
  110. }
  111. #endif
  112. /*
  113. * atomic_dec_if_positive - decrement by 1 if old value positive
  114. * @v: pointer of type atomic_t
  115. *
  116. * The function returns the old value of *v minus 1, even if
  117. * the atomic variable, v, was not decremented.
  118. */
  119. #ifndef atomic_dec_if_positive
  120. static inline int atomic_dec_if_positive(atomic_t *v)
  121. {
  122. int c, old, dec;
  123. c = atomic_read(v);
  124. for (;;) {
  125. dec = c - 1;
  126. if (unlikely(dec < 0))
  127. break;
  128. old = atomic_cmpxchg((v), c, dec);
  129. if (likely(old == c))
  130. break;
  131. c = old;
  132. }
  133. return dec;
  134. }
  135. #endif
  136. #ifndef CONFIG_ARCH_HAS_ATOMIC_OR
  137. static inline void atomic_or(int i, atomic_t *v)
  138. {
  139. int old;
  140. int new;
  141. do {
  142. old = atomic_read(v);
  143. new = old | i;
  144. } while (atomic_cmpxchg(v, old, new) != old);
  145. }
  146. #endif /* #ifndef CONFIG_ARCH_HAS_ATOMIC_OR */
  147. #include <asm-generic/atomic-long.h>
  148. #ifdef CONFIG_GENERIC_ATOMIC64
  149. #include <asm-generic/atomic64.h>
  150. #endif
  151. #endif /* _LINUX_ATOMIC_H */