xref: /linux/arch/x86/include/asm/atomic64_32.h (revision 1a3b1d89eded68d64e5ea409ad37827310059441)
1*1a3b1d89SBrian Gerst #ifndef _ASM_X86_ATOMIC64_32_H
2*1a3b1d89SBrian Gerst #define _ASM_X86_ATOMIC64_32_H
3*1a3b1d89SBrian Gerst 
4*1a3b1d89SBrian Gerst #include <linux/compiler.h>
5*1a3b1d89SBrian Gerst #include <linux/types.h>
6*1a3b1d89SBrian Gerst #include <asm/processor.h>
7*1a3b1d89SBrian Gerst //#include <asm/cmpxchg.h>
8*1a3b1d89SBrian Gerst 
9*1a3b1d89SBrian Gerst /* An 64bit atomic type */
10*1a3b1d89SBrian Gerst 
11*1a3b1d89SBrian Gerst typedef struct {
12*1a3b1d89SBrian Gerst 	u64 __aligned(8) counter;
13*1a3b1d89SBrian Gerst } atomic64_t;
14*1a3b1d89SBrian Gerst 
15*1a3b1d89SBrian Gerst #define ATOMIC64_INIT(val)	{ (val) }
16*1a3b1d89SBrian Gerst 
17*1a3b1d89SBrian Gerst extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val);
18*1a3b1d89SBrian Gerst 
19*1a3b1d89SBrian Gerst /**
20*1a3b1d89SBrian Gerst  * atomic64_xchg - xchg atomic64 variable
21*1a3b1d89SBrian Gerst  * @ptr:      pointer to type atomic64_t
22*1a3b1d89SBrian Gerst  * @new_val:  value to assign
23*1a3b1d89SBrian Gerst  *
24*1a3b1d89SBrian Gerst  * Atomically xchgs the value of @ptr to @new_val and returns
25*1a3b1d89SBrian Gerst  * the old value.
26*1a3b1d89SBrian Gerst  */
27*1a3b1d89SBrian Gerst extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val);
28*1a3b1d89SBrian Gerst 
29*1a3b1d89SBrian Gerst /**
30*1a3b1d89SBrian Gerst  * atomic64_set - set atomic64 variable
31*1a3b1d89SBrian Gerst  * @ptr:      pointer to type atomic64_t
32*1a3b1d89SBrian Gerst  * @new_val:  value to assign
33*1a3b1d89SBrian Gerst  *
34*1a3b1d89SBrian Gerst  * Atomically sets the value of @ptr to @new_val.
35*1a3b1d89SBrian Gerst  */
36*1a3b1d89SBrian Gerst extern void atomic64_set(atomic64_t *ptr, u64 new_val);
37*1a3b1d89SBrian Gerst 
38*1a3b1d89SBrian Gerst /**
39*1a3b1d89SBrian Gerst  * atomic64_read - read atomic64 variable
40*1a3b1d89SBrian Gerst  * @ptr:      pointer to type atomic64_t
41*1a3b1d89SBrian Gerst  *
42*1a3b1d89SBrian Gerst  * Atomically reads the value of @ptr and returns it.
43*1a3b1d89SBrian Gerst  */
44*1a3b1d89SBrian Gerst static inline u64 atomic64_read(atomic64_t *ptr)
45*1a3b1d89SBrian Gerst {
46*1a3b1d89SBrian Gerst 	u64 res;
47*1a3b1d89SBrian Gerst 
48*1a3b1d89SBrian Gerst 	/*
49*1a3b1d89SBrian Gerst 	 * Note, we inline this atomic64_t primitive because
50*1a3b1d89SBrian Gerst 	 * it only clobbers EAX/EDX and leaves the others
51*1a3b1d89SBrian Gerst 	 * untouched. We also (somewhat subtly) rely on the
52*1a3b1d89SBrian Gerst 	 * fact that cmpxchg8b returns the current 64-bit value
53*1a3b1d89SBrian Gerst 	 * of the memory location we are touching:
54*1a3b1d89SBrian Gerst 	 */
55*1a3b1d89SBrian Gerst 	asm volatile(
56*1a3b1d89SBrian Gerst 		"mov %%ebx, %%eax\n\t"
57*1a3b1d89SBrian Gerst 		"mov %%ecx, %%edx\n\t"
58*1a3b1d89SBrian Gerst 		LOCK_PREFIX "cmpxchg8b %1\n"
59*1a3b1d89SBrian Gerst 			: "=&A" (res)
60*1a3b1d89SBrian Gerst 			: "m" (*ptr)
61*1a3b1d89SBrian Gerst 		);
62*1a3b1d89SBrian Gerst 
63*1a3b1d89SBrian Gerst 	return res;
64*1a3b1d89SBrian Gerst }
65*1a3b1d89SBrian Gerst 
66*1a3b1d89SBrian Gerst extern u64 atomic64_read(atomic64_t *ptr);
67*1a3b1d89SBrian Gerst 
68*1a3b1d89SBrian Gerst /**
69*1a3b1d89SBrian Gerst  * atomic64_add_return - add and return
70*1a3b1d89SBrian Gerst  * @delta: integer value to add
71*1a3b1d89SBrian Gerst  * @ptr:   pointer to type atomic64_t
72*1a3b1d89SBrian Gerst  *
73*1a3b1d89SBrian Gerst  * Atomically adds @delta to @ptr and returns @delta + *@ptr
74*1a3b1d89SBrian Gerst  */
75*1a3b1d89SBrian Gerst extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr);
76*1a3b1d89SBrian Gerst 
77*1a3b1d89SBrian Gerst /*
78*1a3b1d89SBrian Gerst  * Other variants with different arithmetic operators:
79*1a3b1d89SBrian Gerst  */
80*1a3b1d89SBrian Gerst extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr);
81*1a3b1d89SBrian Gerst extern u64 atomic64_inc_return(atomic64_t *ptr);
82*1a3b1d89SBrian Gerst extern u64 atomic64_dec_return(atomic64_t *ptr);
83*1a3b1d89SBrian Gerst 
84*1a3b1d89SBrian Gerst /**
85*1a3b1d89SBrian Gerst  * atomic64_add - add integer to atomic64 variable
86*1a3b1d89SBrian Gerst  * @delta: integer value to add
87*1a3b1d89SBrian Gerst  * @ptr:   pointer to type atomic64_t
88*1a3b1d89SBrian Gerst  *
89*1a3b1d89SBrian Gerst  * Atomically adds @delta to @ptr.
90*1a3b1d89SBrian Gerst  */
91*1a3b1d89SBrian Gerst extern void atomic64_add(u64 delta, atomic64_t *ptr);
92*1a3b1d89SBrian Gerst 
93*1a3b1d89SBrian Gerst /**
94*1a3b1d89SBrian Gerst  * atomic64_sub - subtract the atomic64 variable
95*1a3b1d89SBrian Gerst  * @delta: integer value to subtract
96*1a3b1d89SBrian Gerst  * @ptr:   pointer to type atomic64_t
97*1a3b1d89SBrian Gerst  *
98*1a3b1d89SBrian Gerst  * Atomically subtracts @delta from @ptr.
99*1a3b1d89SBrian Gerst  */
100*1a3b1d89SBrian Gerst extern void atomic64_sub(u64 delta, atomic64_t *ptr);
101*1a3b1d89SBrian Gerst 
102*1a3b1d89SBrian Gerst /**
103*1a3b1d89SBrian Gerst  * atomic64_sub_and_test - subtract value from variable and test result
104*1a3b1d89SBrian Gerst  * @delta: integer value to subtract
105*1a3b1d89SBrian Gerst  * @ptr:   pointer to type atomic64_t
106*1a3b1d89SBrian Gerst  *
107*1a3b1d89SBrian Gerst  * Atomically subtracts @delta from @ptr and returns
108*1a3b1d89SBrian Gerst  * true if the result is zero, or false for all
109*1a3b1d89SBrian Gerst  * other cases.
110*1a3b1d89SBrian Gerst  */
111*1a3b1d89SBrian Gerst extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr);
112*1a3b1d89SBrian Gerst 
113*1a3b1d89SBrian Gerst /**
114*1a3b1d89SBrian Gerst  * atomic64_inc - increment atomic64 variable
115*1a3b1d89SBrian Gerst  * @ptr: pointer to type atomic64_t
116*1a3b1d89SBrian Gerst  *
117*1a3b1d89SBrian Gerst  * Atomically increments @ptr by 1.
118*1a3b1d89SBrian Gerst  */
119*1a3b1d89SBrian Gerst extern void atomic64_inc(atomic64_t *ptr);
120*1a3b1d89SBrian Gerst 
121*1a3b1d89SBrian Gerst /**
122*1a3b1d89SBrian Gerst  * atomic64_dec - decrement atomic64 variable
123*1a3b1d89SBrian Gerst  * @ptr: pointer to type atomic64_t
124*1a3b1d89SBrian Gerst  *
125*1a3b1d89SBrian Gerst  * Atomically decrements @ptr by 1.
126*1a3b1d89SBrian Gerst  */
127*1a3b1d89SBrian Gerst extern void atomic64_dec(atomic64_t *ptr);
128*1a3b1d89SBrian Gerst 
129*1a3b1d89SBrian Gerst /**
130*1a3b1d89SBrian Gerst  * atomic64_dec_and_test - decrement and test
131*1a3b1d89SBrian Gerst  * @ptr: pointer to type atomic64_t
132*1a3b1d89SBrian Gerst  *
133*1a3b1d89SBrian Gerst  * Atomically decrements @ptr by 1 and
134*1a3b1d89SBrian Gerst  * returns true if the result is 0, or false for all other
135*1a3b1d89SBrian Gerst  * cases.
136*1a3b1d89SBrian Gerst  */
137*1a3b1d89SBrian Gerst extern int atomic64_dec_and_test(atomic64_t *ptr);
138*1a3b1d89SBrian Gerst 
139*1a3b1d89SBrian Gerst /**
140*1a3b1d89SBrian Gerst  * atomic64_inc_and_test - increment and test
141*1a3b1d89SBrian Gerst  * @ptr: pointer to type atomic64_t
142*1a3b1d89SBrian Gerst  *
143*1a3b1d89SBrian Gerst  * Atomically increments @ptr by 1
144*1a3b1d89SBrian Gerst  * and returns true if the result is zero, or false for all
145*1a3b1d89SBrian Gerst  * other cases.
146*1a3b1d89SBrian Gerst  */
147*1a3b1d89SBrian Gerst extern int atomic64_inc_and_test(atomic64_t *ptr);
148*1a3b1d89SBrian Gerst 
149*1a3b1d89SBrian Gerst /**
150*1a3b1d89SBrian Gerst  * atomic64_add_negative - add and test if negative
151*1a3b1d89SBrian Gerst  * @delta: integer value to add
152*1a3b1d89SBrian Gerst  * @ptr:   pointer to type atomic64_t
153*1a3b1d89SBrian Gerst  *
154*1a3b1d89SBrian Gerst  * Atomically adds @delta to @ptr and returns true
155*1a3b1d89SBrian Gerst  * if the result is negative, or false when
156*1a3b1d89SBrian Gerst  * result is greater than or equal to zero.
157*1a3b1d89SBrian Gerst  */
158*1a3b1d89SBrian Gerst extern int atomic64_add_negative(u64 delta, atomic64_t *ptr);
159*1a3b1d89SBrian Gerst 
160*1a3b1d89SBrian Gerst #endif /* _ASM_X86_ATOMIC64_32_H */
161