1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef _TOOLS_LINUX_ASM_X86_ATOMIC_H 3 #define _TOOLS_LINUX_ASM_X86_ATOMIC_H 4 5 #include <linux/compiler.h> 6 #include <linux/types.h> 7 #include "rmwcc.h" 8 9 #define LOCK_PREFIX "\n\tlock; " 10 11 #include <asm/asm.h> 12 #include <asm/cmpxchg.h> 13 14 /* 15 * Atomic operations that C can't guarantee us. Useful for 16 * resource counting etc.. 17 */ 18 19 #define ATOMIC_INIT(i) { (i) } 20 21 /** 22 * atomic_read - read atomic variable 23 * @v: pointer of type atomic_t 24 * 25 * Atomically reads the value of @v. 26 */ 27 static inline int atomic_read(const atomic_t *v) 28 { 29 return READ_ONCE((v)->counter); 30 } 31 32 /** 33 * atomic_set - set atomic variable 34 * @v: pointer of type atomic_t 35 * @i: required value 36 * 37 * Atomically sets the value of @v to @i. 38 */ 39 static inline void atomic_set(atomic_t *v, int i) 40 { 41 v->counter = i; 42 } 43 44 /** 45 * atomic_inc - increment atomic variable 46 * @v: pointer of type atomic_t 47 * 48 * Atomically increments @v by 1. 49 */ 50 static inline void atomic_inc(atomic_t *v) 51 { 52 asm volatile(LOCK_PREFIX "incl %0" 53 : "+m" (v->counter)); 54 } 55 56 /** 57 * atomic_dec_and_test - decrement and test 58 * @v: pointer of type atomic_t 59 * 60 * Atomically decrements @v by 1 and 61 * returns true if the result is 0, or false for all other 62 * cases. 63 */ 64 static inline int atomic_dec_and_test(atomic_t *v) 65 { 66 GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e"); 67 } 68 69 static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new) 70 { 71 return cmpxchg(&v->counter, old, new); 72 } 73 74 static inline int test_and_set_bit(long nr, unsigned long *addr) 75 { 76 GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(bts), *addr, "Ir", nr, "%0", "c"); 77 } 78 79 static inline int test_and_clear_bit(long nr, unsigned long *addr) 80 { 81 GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(btc), *addr, "Ir", nr, "%0", "c"); 82 } 83 84 #endif /* _TOOLS_LINUX_ASM_X86_ATOMIC_H */ 85