xref: /kvm-unit-tests/lib/x86/atomic.h (revision 584afc90e9404e2b98a763fb615b689215744802)
1*584afc90SJason Wang #ifndef __ATOMIC_H
2*584afc90SJason Wang #define __ATOMIC_H
3*584afc90SJason Wang 
4*584afc90SJason Wang typedef struct {
5*584afc90SJason Wang 	volatile int counter;
6*584afc90SJason Wang } atomic_t;
7*584afc90SJason Wang 
8*584afc90SJason Wang #ifdef __i386__
9*584afc90SJason Wang 
10*584afc90SJason Wang /**
11*584afc90SJason Wang  * atomic_read - read atomic variable
12*584afc90SJason Wang  * @v: pointer of type atomic_t
13*584afc90SJason Wang  *
14*584afc90SJason Wang  * Atomically reads the value of @v.
15*584afc90SJason Wang  */
16*584afc90SJason Wang static inline int atomic_read(const atomic_t *v)
17*584afc90SJason Wang {
18*584afc90SJason Wang 	return v->counter;
19*584afc90SJason Wang }
20*584afc90SJason Wang 
21*584afc90SJason Wang /**
22*584afc90SJason Wang  * atomic_set - set atomic variable
23*584afc90SJason Wang  * @v: pointer of type atomic_t
24*584afc90SJason Wang  * @i: required value
25*584afc90SJason Wang  *
26*584afc90SJason Wang  * Atomically sets the value of @v to @i.
27*584afc90SJason Wang  */
28*584afc90SJason Wang static inline void atomic_set(atomic_t *v, int i)
29*584afc90SJason Wang {
30*584afc90SJason Wang 	v->counter = i;
31*584afc90SJason Wang }
32*584afc90SJason Wang 
33*584afc90SJason Wang /**
34*584afc90SJason Wang  * atomic_inc - increment atomic variable
35*584afc90SJason Wang  * @v: pointer of type atomic_t
36*584afc90SJason Wang  *
37*584afc90SJason Wang  * Atomically increments @v by 1.
38*584afc90SJason Wang  */
39*584afc90SJason Wang static inline void atomic_inc(atomic_t *v)
40*584afc90SJason Wang {
41*584afc90SJason Wang 	asm volatile("lock incl %0"
42*584afc90SJason Wang 		     : "+m" (v->counter));
43*584afc90SJason Wang }
44*584afc90SJason Wang 
45*584afc90SJason Wang /**
46*584afc90SJason Wang  * atomic_dec - decrement atomic variable
47*584afc90SJason Wang  * @v: pointer of type atomic_t
48*584afc90SJason Wang  *
49*584afc90SJason Wang  * Atomically decrements @v by 1.
50*584afc90SJason Wang  */
51*584afc90SJason Wang static inline void atomic_dec(atomic_t *v)
52*584afc90SJason Wang {
53*584afc90SJason Wang 	asm volatile("lock decl %0"
54*584afc90SJason Wang 		     : "+m" (v->counter));
55*584afc90SJason Wang }
56*584afc90SJason Wang 
57*584afc90SJason Wang typedef struct {
58*584afc90SJason Wang 	u64 __attribute__((aligned(8))) counter;
59*584afc90SJason Wang } atomic64_t;
60*584afc90SJason Wang 
61*584afc90SJason Wang #define ATOMIC64_INIT(val)	{ (val) }
62*584afc90SJason Wang 
63*584afc90SJason Wang /**
64*584afc90SJason Wang  * atomic64_read - read atomic64 variable
65*584afc90SJason Wang  * @ptr:      pointer to type atomic64_t
66*584afc90SJason Wang  *
67*584afc90SJason Wang  * Atomically reads the value of @ptr and returns it.
68*584afc90SJason Wang  */
69*584afc90SJason Wang static inline u64 atomic64_read(atomic64_t *ptr)
70*584afc90SJason Wang {
71*584afc90SJason Wang 	u64 res;
72*584afc90SJason Wang 
73*584afc90SJason Wang 	/*
74*584afc90SJason Wang 	 * Note, we inline this atomic64_t primitive because
75*584afc90SJason Wang 	 * it only clobbers EAX/EDX and leaves the others
76*584afc90SJason Wang 	 * untouched. We also (somewhat subtly) rely on the
77*584afc90SJason Wang 	 * fact that cmpxchg8b returns the current 64-bit value
78*584afc90SJason Wang 	 * of the memory location we are touching:
79*584afc90SJason Wang 	 */
80*584afc90SJason Wang 	asm volatile("mov %%ebx, %%eax\n\t"
81*584afc90SJason Wang                      "mov %%ecx, %%edx\n\t"
82*584afc90SJason Wang                      "lock cmpxchg8b %1\n"
83*584afc90SJason Wang                      : "=&A" (res)
84*584afc90SJason Wang                      : "m" (*ptr)
85*584afc90SJason Wang                      );
86*584afc90SJason Wang 	return res;
87*584afc90SJason Wang }
88*584afc90SJason Wang 
89*584afc90SJason Wang u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new);
90*584afc90SJason Wang 
91*584afc90SJason Wang #elif defined(__x86_64__)
92*584afc90SJason Wang 
93*584afc90SJason Wang /**
94*584afc90SJason Wang  * atomic_read - read atomic variable
95*584afc90SJason Wang  * @v: pointer of type atomic_t
96*584afc90SJason Wang  *
97*584afc90SJason Wang  * Atomically reads the value of @v.
98*584afc90SJason Wang  */
99*584afc90SJason Wang static inline int atomic_read(const atomic_t *v)
100*584afc90SJason Wang {
101*584afc90SJason Wang 	return v->counter;
102*584afc90SJason Wang }
103*584afc90SJason Wang 
104*584afc90SJason Wang /**
105*584afc90SJason Wang  * atomic_set - set atomic variable
106*584afc90SJason Wang  * @v: pointer of type atomic_t
107*584afc90SJason Wang  * @i: required value
108*584afc90SJason Wang  *
109*584afc90SJason Wang  * Atomically sets the value of @v to @i.
110*584afc90SJason Wang  */
111*584afc90SJason Wang static inline void atomic_set(atomic_t *v, int i)
112*584afc90SJason Wang {
113*584afc90SJason Wang 	v->counter = i;
114*584afc90SJason Wang }
115*584afc90SJason Wang 
116*584afc90SJason Wang /**
117*584afc90SJason Wang  * atomic_inc - increment atomic variable
118*584afc90SJason Wang  * @v: pointer of type atomic_t
119*584afc90SJason Wang  *
120*584afc90SJason Wang  * Atomically increments @v by 1.
121*584afc90SJason Wang  */
122*584afc90SJason Wang static inline void atomic_inc(atomic_t *v)
123*584afc90SJason Wang {
124*584afc90SJason Wang 	asm volatile("lock incl %0"
125*584afc90SJason Wang 		     : "=m" (v->counter)
126*584afc90SJason Wang 		     : "m" (v->counter));
127*584afc90SJason Wang }
128*584afc90SJason Wang 
129*584afc90SJason Wang /**
130*584afc90SJason Wang  * atomic_dec - decrement atomic variable
131*584afc90SJason Wang  * @v: pointer of type atomic_t
132*584afc90SJason Wang  *
133*584afc90SJason Wang  * Atomically decrements @v by 1.
134*584afc90SJason Wang  */
135*584afc90SJason Wang static inline void atomic_dec(atomic_t *v)
136*584afc90SJason Wang {
137*584afc90SJason Wang 	asm volatile("lock decl %0"
138*584afc90SJason Wang 		     : "=m" (v->counter)
139*584afc90SJason Wang 		     : "m" (v->counter));
140*584afc90SJason Wang }
141*584afc90SJason Wang 
142*584afc90SJason Wang typedef struct {
143*584afc90SJason Wang 	long long counter;
144*584afc90SJason Wang } atomic64_t;
145*584afc90SJason Wang 
146*584afc90SJason Wang #define ATOMIC64_INIT(i)	{ (i) }
147*584afc90SJason Wang 
148*584afc90SJason Wang /**
149*584afc90SJason Wang  * atomic64_read - read atomic64 variable
150*584afc90SJason Wang  * @v: pointer of type atomic64_t
151*584afc90SJason Wang  *
152*584afc90SJason Wang  * Atomically reads the value of @v.
153*584afc90SJason Wang  * Doesn't imply a read memory barrier.
154*584afc90SJason Wang  */
155*584afc90SJason Wang static inline long atomic64_read(const atomic64_t *v)
156*584afc90SJason Wang {
157*584afc90SJason Wang 	return v->counter;
158*584afc90SJason Wang }
159*584afc90SJason Wang 
160*584afc90SJason Wang u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new);
161*584afc90SJason Wang 
162*584afc90SJason Wang #endif
163*584afc90SJason Wang 
164*584afc90SJason Wang #endif
165