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