1 // Atomic operations. These functions are not privileged, but may not be
2 // available on all architectures. By default, they operate on 32-bit
3 // quantities; however, certain functions are also available in a "long"
4 // version which uses "unsigned long"; these are provided when the
5 // function is likely to be useful for storing pointers rather than just
6 // counters. The long versions are defined arch-x86/atomic.h and
7 // arch-x64/atomic.h, not here.
9 #ifndef _LL_ARCH_X86C_ATOMIC_H
10 #define _LL_ARCH_X86C_ATOMIC_H
12 #include <lowlevel/types.h>
14 static inline void ll_atomic_inc(int32_t *val)
17 asm("lock; incl %0" : "+m" (*val) : : "memory");
19 asm("incl %0" : "+m" (*val) : : "memory");
22 static inline void ll_atomic_dec(int32_t *val)
25 asm("lock; decl %0" : "+m" (*val) : : "memory");
27 asm("decl %0" : "+m" (*val) : : "memory");
30 // Increment/Decrement and return non-zero if the new count is zero.
32 static inline int ll_atomic_inc_and_test(int32_t *val)
37 asm("lock; incl %0; setz %b1" : "+m" (*val), "=r" (ret) : : "memory");
39 asm("incl %0; setz %b1" : "+m" (*val), "=r" (ret) : : "memory");
44 static inline int ll_atomic_dec_and_test(int32_t *val)
49 asm("lock; decl %0; setz %b1" : "+m" (*val), "=r" (ret) : : "memory");
51 asm("decl %0; setz %b1" : "+m" (*val), "=r" (ret) : : "memory");
56 static inline int ll_test_and_set(uint32_t *val, int bit)
61 asm("lock; btsl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
62 "ri" (bit) : "memory");
64 asm("btsl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
65 "ri" (bit) : "memory");
70 static inline int ll_test_and_clear(uint32_t *val, int bit)
75 asm("lock; btrl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
76 "ri" (bit) : "memory");
78 asm("btrl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
79 "ri" (bit) : "memory");
84 static inline int ll_test_and_flip(uint32_t *val, int bit)
89 asm("lock; btcl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
90 "ri" (bit) : "memory");
92 asm("btcl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
93 "ri" (bit) : "memory");
98 // Store newval in the pointer if oldval was there before.
99 // Returns non-zero if the store succeded.
101 static inline int ll_cmpxchg(uint32_t *val, uint32_t oldval, uint32_t newval)
106 asm("lock; cmpxchgl %2, %0; setz %b1" :
107 "+m" (*val), "=r" (ret) : "r" (newval), "a" (oldval) : "memory");
109 asm("cmpxchgl %2, %0; setz %b1" :
110 "+m" (*val), "=r" (ret) : "r" (newval), "a" (oldval) : "memory");
115 static inline unsigned long ll_xchg(uint32_t *ptr, uint32_t val)
117 asm("xchgl %0, %1" : "+r" (val), "+m" (*ptr));