xref: /kvm-unit-tests/lib/x86/atomic.h (revision ae21b795ecb2f6fad39e211bf32b15fc18e106dd)
1584afc90SJason Wang #ifndef __ATOMIC_H
2584afc90SJason Wang #define __ATOMIC_H
3584afc90SJason Wang 
4*ae21b795SPeter Xu #include "asm-generic/atomic.h"
5*ae21b795SPeter Xu 
6584afc90SJason Wang typedef struct {
7584afc90SJason Wang 	volatile int counter;
8584afc90SJason Wang } atomic_t;
9584afc90SJason Wang 
10584afc90SJason Wang #ifdef __i386__
11584afc90SJason Wang 
12584afc90SJason Wang /**
13584afc90SJason Wang  * atomic_read - read atomic variable
14584afc90SJason Wang  * @v: pointer of type atomic_t
15584afc90SJason Wang  *
16584afc90SJason Wang  * Atomically reads the value of @v.
17584afc90SJason Wang  */
18584afc90SJason Wang static inline int atomic_read(const atomic_t *v)
19584afc90SJason Wang {
20584afc90SJason Wang 	return v->counter;
21584afc90SJason Wang }
22584afc90SJason Wang 
23584afc90SJason Wang /**
24584afc90SJason Wang  * atomic_set - set atomic variable
25584afc90SJason Wang  * @v: pointer of type atomic_t
26584afc90SJason Wang  * @i: required value
27584afc90SJason Wang  *
28584afc90SJason Wang  * Atomically sets the value of @v to @i.
29584afc90SJason Wang  */
30584afc90SJason Wang static inline void atomic_set(atomic_t *v, int i)
31584afc90SJason Wang {
32584afc90SJason Wang 	v->counter = i;
33584afc90SJason Wang }
34584afc90SJason Wang 
35584afc90SJason Wang /**
36584afc90SJason Wang  * atomic_inc - increment atomic variable
37584afc90SJason Wang  * @v: pointer of type atomic_t
38584afc90SJason Wang  *
39584afc90SJason Wang  * Atomically increments @v by 1.
40584afc90SJason Wang  */
41584afc90SJason Wang static inline void atomic_inc(atomic_t *v)
42584afc90SJason Wang {
43584afc90SJason Wang 	asm volatile("lock incl %0"
44584afc90SJason Wang 		     : "+m" (v->counter));
45584afc90SJason Wang }
46584afc90SJason Wang 
47584afc90SJason Wang /**
48584afc90SJason Wang  * atomic_dec - decrement atomic variable
49584afc90SJason Wang  * @v: pointer of type atomic_t
50584afc90SJason Wang  *
51584afc90SJason Wang  * Atomically decrements @v by 1.
52584afc90SJason Wang  */
53584afc90SJason Wang static inline void atomic_dec(atomic_t *v)
54584afc90SJason Wang {
55584afc90SJason Wang 	asm volatile("lock decl %0"
56584afc90SJason Wang 		     : "+m" (v->counter));
57584afc90SJason Wang }
58584afc90SJason Wang 
59584afc90SJason Wang typedef struct {
60584afc90SJason Wang 	u64 __attribute__((aligned(8))) counter;
61584afc90SJason Wang } atomic64_t;
62584afc90SJason Wang 
63584afc90SJason Wang #define ATOMIC64_INIT(val)	{ (val) }
64584afc90SJason Wang 
65584afc90SJason Wang /**
66584afc90SJason Wang  * atomic64_read - read atomic64 variable
67584afc90SJason Wang  * @ptr:      pointer to type atomic64_t
68584afc90SJason Wang  *
69584afc90SJason Wang  * Atomically reads the value of @ptr and returns it.
70584afc90SJason Wang  */
71584afc90SJason Wang static inline u64 atomic64_read(atomic64_t *ptr)
72584afc90SJason Wang {
73584afc90SJason Wang 	u64 res;
74584afc90SJason Wang 
75584afc90SJason Wang 	/*
76584afc90SJason Wang 	 * Note, we inline this atomic64_t primitive because
77584afc90SJason Wang 	 * it only clobbers EAX/EDX and leaves the others
78584afc90SJason Wang 	 * untouched. We also (somewhat subtly) rely on the
79584afc90SJason Wang 	 * fact that cmpxchg8b returns the current 64-bit value
80584afc90SJason Wang 	 * of the memory location we are touching:
81584afc90SJason Wang 	 */
82584afc90SJason Wang 	asm volatile("mov %%ebx, %%eax\n\t"
83584afc90SJason Wang                      "mov %%ecx, %%edx\n\t"
84584afc90SJason Wang                      "lock cmpxchg8b %1\n"
85584afc90SJason Wang                      : "=&A" (res)
86584afc90SJason Wang                      : "m" (*ptr)
87584afc90SJason Wang                      );
88584afc90SJason Wang 	return res;
89584afc90SJason Wang }
90584afc90SJason Wang 
91584afc90SJason Wang u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new);
92584afc90SJason Wang 
93584afc90SJason Wang #elif defined(__x86_64__)
94584afc90SJason Wang 
95584afc90SJason Wang /**
96584afc90SJason Wang  * atomic_read - read atomic variable
97584afc90SJason Wang  * @v: pointer of type atomic_t
98584afc90SJason Wang  *
99584afc90SJason Wang  * Atomically reads the value of @v.
100584afc90SJason Wang  */
101584afc90SJason Wang static inline int atomic_read(const atomic_t *v)
102584afc90SJason Wang {
103584afc90SJason Wang 	return v->counter;
104584afc90SJason Wang }
105584afc90SJason Wang 
106584afc90SJason Wang /**
107584afc90SJason Wang  * atomic_set - set atomic variable
108584afc90SJason Wang  * @v: pointer of type atomic_t
109584afc90SJason Wang  * @i: required value
110584afc90SJason Wang  *
111584afc90SJason Wang  * Atomically sets the value of @v to @i.
112584afc90SJason Wang  */
113584afc90SJason Wang static inline void atomic_set(atomic_t *v, int i)
114584afc90SJason Wang {
115584afc90SJason Wang 	v->counter = i;
116584afc90SJason Wang }
117584afc90SJason Wang 
118584afc90SJason Wang /**
119584afc90SJason Wang  * atomic_inc - increment atomic variable
120584afc90SJason Wang  * @v: pointer of type atomic_t
121584afc90SJason Wang  *
122584afc90SJason Wang  * Atomically increments @v by 1.
123584afc90SJason Wang  */
124584afc90SJason Wang static inline void atomic_inc(atomic_t *v)
125584afc90SJason Wang {
126584afc90SJason Wang 	asm volatile("lock incl %0"
127584afc90SJason Wang 		     : "=m" (v->counter)
128584afc90SJason Wang 		     : "m" (v->counter));
129584afc90SJason Wang }
130584afc90SJason Wang 
131584afc90SJason Wang /**
132584afc90SJason Wang  * atomic_dec - decrement atomic variable
133584afc90SJason Wang  * @v: pointer of type atomic_t
134584afc90SJason Wang  *
135584afc90SJason Wang  * Atomically decrements @v by 1.
136584afc90SJason Wang  */
137584afc90SJason Wang static inline void atomic_dec(atomic_t *v)
138584afc90SJason Wang {
139584afc90SJason Wang 	asm volatile("lock decl %0"
140584afc90SJason Wang 		     : "=m" (v->counter)
141584afc90SJason Wang 		     : "m" (v->counter));
142584afc90SJason Wang }
143584afc90SJason Wang 
144584afc90SJason Wang typedef struct {
145584afc90SJason Wang 	long long counter;
146584afc90SJason Wang } atomic64_t;
147584afc90SJason Wang 
148584afc90SJason Wang #define ATOMIC64_INIT(i)	{ (i) }
149584afc90SJason Wang 
150584afc90SJason Wang /**
151584afc90SJason Wang  * atomic64_read - read atomic64 variable
152584afc90SJason Wang  * @v: pointer of type atomic64_t
153584afc90SJason Wang  *
154584afc90SJason Wang  * Atomically reads the value of @v.
155584afc90SJason Wang  * Doesn't imply a read memory barrier.
156584afc90SJason Wang  */
157584afc90SJason Wang static inline long atomic64_read(const atomic64_t *v)
158584afc90SJason Wang {
159584afc90SJason Wang 	return v->counter;
160584afc90SJason Wang }
161584afc90SJason Wang 
162584afc90SJason Wang u64 atomic64_cmpxchg(atomic64_t *v, u64 old, u64 new);
163584afc90SJason Wang 
164584afc90SJason Wang #endif
165584afc90SJason Wang 
166584afc90SJason Wang #endif
167