]> git.buserror.net Git - polintos/scott/priv.git/blob - include/c/lowlevel/arch-x86-common/atomic.h
Initial checkin from Perforce.
[polintos/scott/priv.git] / include / c / lowlevel / arch-x86-common / atomic.h
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.
8
9 #ifndef _LL_ARCH_X86C_ATOMIC_H
10 #define _LL_ARCH_X86C_ATOMIC_H
11
12 #include <lowlevel/types.h>
13
14 static inline void ll_atomic_inc(int32_t *val)
15 {
16         if (_LL_SMP)
17                 asm("lock; incl %0" : "+m" (*val) : : "memory");
18         else
19                 asm("incl %0" : "+m" (*val) : : "memory");
20 }
21
22 static inline void ll_atomic_dec(int32_t *val)
23 {
24         if (_LL_SMP)
25                 asm("lock; decl %0" : "+m" (*val) : : "memory");
26         else
27                 asm("decl %0" : "+m" (*val) : : "memory");
28 }
29
30 // Increment/Decrement and return non-zero if the new count is zero.
31
32 static inline int ll_atomic_inc_and_test(int32_t *val)
33 {
34         uint8_t ret;
35
36         if (_LL_SMP)
37                 asm("lock; incl %0; setz %b1" : "+m" (*val), "=r" (ret) : : "memory");
38         else
39                 asm("incl %0; setz %b1" : "+m" (*val), "=r" (ret) : : "memory");
40
41         return ret;
42 }
43
44 static inline int ll_atomic_dec_and_test(int32_t *val)
45 {
46         uint8_t ret;
47
48         if (_LL_SMP)
49                 asm("lock; decl %0; setz %b1" : "+m" (*val), "=r" (ret) : : "memory");
50         else
51                 asm("decl %0; setz %b1" : "+m" (*val), "=r" (ret) : : "memory");
52
53         return ret;
54 }
55
56 static inline int ll_test_and_set(uint32_t *val, int bit)
57 {
58         uint8_t ret;
59
60         if (_LL_SMP)
61                 asm("lock; btsl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
62                     "ri" (bit) : "memory");
63         else
64                 asm("btsl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
65                     "ri" (bit) : "memory");
66
67         return ret;
68 }
69
70 static inline int ll_test_and_clear(uint32_t *val, int bit)
71 {
72         uint8_t ret;
73
74         if (_LL_SMP)
75                 asm("lock; btrl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
76                     "ri" (bit) : "memory");
77         else
78                 asm("btrl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
79                     "ri" (bit) : "memory");
80
81         return ret;
82 }
83
84 static inline int ll_test_and_flip(uint32_t *val, int bit)
85 {
86         uint8_t ret;
87
88         if (_LL_SMP)
89                 asm("lock; btcl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
90                     "ri" (bit) : "memory");
91         else
92                 asm("btcl %2, %0; setc %b1" : "+m" (*val), "=r" (ret) :
93                     "ri" (bit) : "memory");
94
95         return ret;
96 }
97
98 // Store newval in the pointer if oldval was there before.
99 // Returns non-zero if the store succeded.
100
101 static inline int ll_cmpxchg(uint32_t *val, uint32_t oldval, uint32_t newval)
102 {
103         uint8_t ret;
104
105         if (_LL_SMP)
106                 asm("lock; cmpxchgl %2, %0; setz %b1" :
107                     "+m" (*val), "=r" (ret) : "r" (newval), "a" (oldval) : "memory");
108         else
109                 asm("cmpxchgl %2, %0; setz %b1" :
110                     "+m" (*val), "=r" (ret) : "r" (newval), "a" (oldval) : "memory");
111
112         return ret;
113 }
114
115 static inline unsigned long ll_xchg(uint32_t *ptr, uint32_t val)
116 {
117         asm("xchgl %0, %1" : "+r" (val), "+m" (*ptr));
118         return val;
119 }
120
121 #endif