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