| 1 |
|
| 2 | #ifndef __TOOLS_ASM_GENERIC_ATOMIC_H
|
| 3 | #define __TOOLS_ASM_GENERIC_ATOMIC_H
|
| 4 |
|
| 5 | #include <linux/compiler.h>
|
| 6 | #include <linux/types.h>
|
| 7 | #include <linux/bitops.h>
|
| 8 |
|
| 9 | |
| 10 | * Atomic operations that C can't guarantee us. Useful for
|
| 11 | * resource counting etc..
|
| 12 | *
|
| 13 | * Excerpts obtained from the Linux kernel sources.
|
| 14 |
|
| 15 |
|
| 16 | #define ATOMIC_INIT(i) { (i) }
|
| 17 |
|
| 18 | |
| 19 | * atomic_read - read atomic variable
|
| 20 | * @v: pointer of type atomic_t
|
| 21 | *
|
| 22 | * Atomically reads the value of @v.
|
| 23 |
|
| 24 | static inline int atomic_read(const atomic_t *v)
|
| 25 | {
|
| 26 | return READ_ONCE((v)->counter);
|
| 27 | }
|
| 28 |
|
| 29 | |
| 30 | * atomic_set - set atomic variable
|
| 31 | * @v: pointer of type atomic_t
|
| 32 | * @i: required value
|
| 33 | *
|
| 34 | * Atomically sets the value of @v to @i.
|
| 35 |
|
| 36 | static inline void atomic_set(atomic_t *v, int i)
|
| 37 | {
|
| 38 | v->counter = i;
|
| 39 | }
|
| 40 |
|
| 41 | |
| 42 | * atomic_inc - increment atomic variable
|
| 43 | * @v: pointer of type atomic_t
|
| 44 | *
|
| 45 | * Atomically increments @v by 1.
|
| 46 |
|
| 47 | static inline void atomic_inc(atomic_t *v)
|
| 48 | {
|
| 49 | __sync_add_and_fetch(&v->counter, 1);
|
| 50 | }
|
| 51 |
|
| 52 | |
| 53 | * atomic_dec_and_test - decrement and test
|
| 54 | * @v: pointer of type atomic_t
|
| 55 | *
|
| 56 | * Atomically decrements @v by 1 and
|
| 57 | * returns true if the result is 0, or false for all other
|
| 58 | * cases.
|
| 59 |
|
| 60 | static inline int atomic_dec_and_test(atomic_t *v)
|
| 61 | {
|
| 62 | return __sync_sub_and_fetch(&v->counter, 1) == 0;
|
| 63 | }
|
| 64 |
|
| 65 | #define cmpxchg(ptr, oldval, newval) \
|
| 66 | __sync_val_compare_and_swap(ptr, oldval, newval)
|
| 67 |
|
| 68 | static inline int atomic_cmpxchg(atomic_t *v, int oldval, int newval)
|
| 69 | {
|
| 70 | return cmpxchg(&(v)->counter, oldval, newval);
|
| 71 | }
|
| 72 |
|
| 73 | static inline int test_and_set_bit(long nr, unsigned long *addr)
|
| 74 | {
|
| 75 | unsigned long mask = BIT_MASK(nr);
|
| 76 | long old;
|
| 77 |
|
| 78 | addr += BIT_WORD(nr);
|
| 79 |
|
| 80 | old = __sync_fetch_and_or(addr, mask);
|
| 81 | return !!(old & mask);
|
| 82 | }
|
| 83 |
|
| 84 | static inline int test_and_clear_bit(long nr, unsigned long *addr)
|
| 85 | {
|
| 86 | unsigned long mask = BIT_MASK(nr);
|
| 87 | long old;
|
| 88 |
|
| 89 | addr += BIT_WORD(nr);
|
| 90 |
|
| 91 | old = __sync_fetch_and_and(addr, ~mask);
|
| 92 | return !!(old & mask);
|
| 93 | }
|
| 94 |
|
| 95 | #endif
|