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