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 */ 27static 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 */ 39static 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 */ 50static 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 */ 64static inline int atomic_dec_and_test(atomic_t *v) 65{ 66 GEN_UNARY_RMWcc(LOCK_PREFIX "decl", v->counter, "%0", "e"); 67} 68 69static __always_inline int atomic_cmpxchg(atomic_t *v, int old, int new) 70{ 71 return cmpxchg(&v->counter, old, new); 72} 73 74static 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 79static 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