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