Commit 4532b305e8f0c238dd73048068ff8a6dd1380291

Authored by H. Peter Anvin
1 parent 69309a0590

x86, asm: Clean up and simplify <asm/cmpxchg.h>

Remove the __xg() hack to create a memory barrier near xchg and
cmpxchg; it has been there since 1.3.11 but should not be necessary
with "asm volatile" and a "memory" clobber, neither of which were
there in the original implementation.

However, we *should* make this a volatile reference.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
LKML-Reference: <AANLkTikAmaDPji-TVDarmG1yD=fwbffcsmEU=YEuP+8r@mail.gmail.com>

Showing 2 changed files with 84 additions and 52 deletions Side-by-side Diff

arch/x86/include/asm/cmpxchg_32.h
... ... @@ -11,38 +11,42 @@
11 11 extern void __xchg_wrong_size(void);
12 12  
13 13 /*
14   - * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
15   - * Note 2: xchg has side effect, so that attribute volatile is necessary,
16   - * but generally the primitive is invalid, *ptr is output argument. --ANK
  14 + * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
  15 + * Since this is generally used to protect other memory information, we
  16 + * use "asm volatile" and "memory" clobbers to prevent gcc from moving
  17 + * information around.
17 18 */
18   -
19   -struct __xchg_dummy {
20   - unsigned long a[100];
21   -};
22   -#define __xg(x) ((struct __xchg_dummy *)(x))
23   -
24 19 #define __xchg(x, ptr, size) \
25 20 ({ \
26 21 __typeof(*(ptr)) __x = (x); \
27 22 switch (size) { \
28 23 case 1: \
29   - asm volatile("xchgb %b0,%1" \
30   - : "=q" (__x), "+m" (*__xg(ptr)) \
  24 + { \
  25 + volatile u8 *__ptr = (volatile u8 *)(ptr); \
  26 + asm volatile("xchgb %0,%1" \
  27 + : "=q" (__x), "+m" (*__ptr) \
31 28 : "0" (__x) \
32 29 : "memory"); \
33 30 break; \
  31 + } \
34 32 case 2: \
35   - asm volatile("xchgw %w0,%1" \
36   - : "=r" (__x), "+m" (*__xg(ptr)) \
  33 + { \
  34 + volatile u16 *__ptr = (volatile u16 *)(ptr); \
  35 + asm volatile("xchgw %0,%1" \
  36 + : "=r" (__x), "+m" (*__ptr) \
37 37 : "0" (__x) \
38 38 : "memory"); \
39 39 break; \
  40 + } \
40 41 case 4: \
  42 + { \
  43 + volatile u32 *__ptr = (volatile u32 *)(ptr); \
41 44 asm volatile("xchgl %0,%1" \
42   - : "=r" (__x), "+m" (*__xg(ptr)) \
  45 + : "=r" (__x), "+m" (*__ptr) \
43 46 : "0" (__x) \
44 47 : "memory"); \
45 48 break; \
  49 + } \
46 50 default: \
47 51 __xchg_wrong_size(); \
48 52 } \
49 53  
50 54  
51 55  
52 56  
53 57  
54 58  
... ... @@ -94,23 +98,32 @@
94 98 __typeof__(*(ptr)) __new = (new); \
95 99 switch (size) { \
96 100 case 1: \
97   - asm volatile(lock "cmpxchgb %b2,%1" \
98   - : "=a" (__ret), "+m" (*__xg(ptr)) \
  101 + { \
  102 + volatile u8 *__ptr = (volatile u8 *)(ptr); \
  103 + asm volatile(lock "cmpxchgb %2,%1" \
  104 + : "=a" (__ret), "+m" (*__ptr) \
99 105 : "q" (__new), "0" (__old) \
100 106 : "memory"); \
101 107 break; \
  108 + } \
102 109 case 2: \
103   - asm volatile(lock "cmpxchgw %w2,%1" \
104   - : "=a" (__ret), "+m" (*__xg(ptr)) \
  110 + { \
  111 + volatile u16 *__ptr = (volatile u16 *)(ptr); \
  112 + asm volatile(lock "cmpxchgw %2,%1" \
  113 + : "=a" (__ret), "+m" (*__ptr) \
105 114 : "r" (__new), "0" (__old) \
106 115 : "memory"); \
107 116 break; \
  117 + } \
108 118 case 4: \
  119 + { \
  120 + volatile u32 *__ptr = (volatile u32 *)(ptr); \
109 121 asm volatile(lock "cmpxchgl %2,%1" \
110   - : "=a" (__ret), "+m" (*__xg(ptr)) \
  122 + : "=a" (__ret), "+m" (*__ptr) \
111 123 : "r" (__new), "0" (__old) \
112 124 : "memory"); \
113 125 break; \
  126 + } \
114 127 default: \
115 128 __cmpxchg_wrong_size(); \
116 129 } \
117 130  
118 131  
119 132  
120 133  
121 134  
... ... @@ -148,31 +161,27 @@
148 161 (unsigned long long)(n)))
149 162 #endif
150 163  
151   -static inline unsigned long long __cmpxchg64(volatile void *ptr,
152   - unsigned long long old,
153   - unsigned long long new)
  164 +static inline u64 __cmpxchg64(volatile u64 *ptr, u64 old, u64 new)
154 165 {
155   - unsigned long long prev;
  166 + u64 prev;
156 167 asm volatile(LOCK_PREFIX "cmpxchg8b %1"
157 168 : "=A" (prev),
158   - "+m" (*__xg(ptr))
159   - : "b" ((unsigned long)new),
160   - "c" ((unsigned long)(new >> 32)),
  169 + "+m" (*ptr)
  170 + : "b" ((u32)new),
  171 + "c" ((u32)(new >> 32)),
161 172 "0" (old)
162 173 : "memory");
163 174 return prev;
164 175 }
165 176  
166   -static inline unsigned long long __cmpxchg64_local(volatile void *ptr,
167   - unsigned long long old,
168   - unsigned long long new)
  177 +static inline u64 __cmpxchg64_local(volatile u64 *ptr, u64 old, u64 new)
169 178 {
170   - unsigned long long prev;
  179 + u64 prev;
171 180 asm volatile("cmpxchg8b %1"
172 181 : "=A" (prev),
173   - "+m" (*__xg(ptr))
174   - : "b" ((unsigned long)new),
175   - "c" ((unsigned long)(new >> 32)),
  182 + "+m" (*ptr)
  183 + : "b" ((u32)new),
  184 + "c" ((u32)(new >> 32)),
176 185 "0" (old)
177 186 : "memory");
178 187 return prev;
arch/x86/include/asm/cmpxchg_64.h
... ... @@ -3,8 +3,6 @@
3 3  
4 4 #include <asm/alternative.h> /* Provides LOCK_PREFIX */
5 5  
6   -#define __xg(x) ((volatile long *)(x))
7   -
8 6 static inline void set_64bit(volatile u64 *ptr, u64 val)
9 7 {
10 8 *ptr = val;
11 9  
12 10  
13 11  
14 12  
15 13  
16 14  
17 15  
18 16  
19 17  
... ... @@ -14,38 +12,51 @@
14 12 extern void __cmpxchg_wrong_size(void);
15 13  
16 14 /*
17   - * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
18   - * Note 2: xchg has side effect, so that attribute volatile is necessary,
19   - * but generally the primitive is invalid, *ptr is output argument. --ANK
  15 + * Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
  16 + * Since this is generally used to protect other memory information, we
  17 + * use "asm volatile" and "memory" clobbers to prevent gcc from moving
  18 + * information around.
20 19 */
21 20 #define __xchg(x, ptr, size) \
22 21 ({ \
23 22 __typeof(*(ptr)) __x = (x); \
24 23 switch (size) { \
25 24 case 1: \
26   - asm volatile("xchgb %b0,%1" \
27   - : "=q" (__x), "+m" (*__xg(ptr)) \
  25 + { \
  26 + volatile u8 *__ptr = (volatile u8 *)(ptr); \
  27 + asm volatile("xchgb %0,%1" \
  28 + : "=q" (__x), "+m" (*__ptr) \
28 29 : "0" (__x) \
29 30 : "memory"); \
30 31 break; \
  32 + } \
31 33 case 2: \
32   - asm volatile("xchgw %w0,%1" \
33   - : "=r" (__x), "+m" (*__xg(ptr)) \
  34 + { \
  35 + volatile u16 *__ptr = (volatile u16 *)(ptr); \
  36 + asm volatile("xchgw %0,%1" \
  37 + : "=r" (__x), "+m" (*__ptr) \
34 38 : "0" (__x) \
35 39 : "memory"); \
36 40 break; \
  41 + } \
37 42 case 4: \
38   - asm volatile("xchgl %k0,%1" \
39   - : "=r" (__x), "+m" (*__xg(ptr)) \
  43 + { \
  44 + volatile u32 *__ptr = (volatile u32 *)(ptr); \
  45 + asm volatile("xchgl %0,%1" \
  46 + : "=r" (__x), "+m" (*__ptr) \
40 47 : "0" (__x) \
41 48 : "memory"); \
42 49 break; \
  50 + } \
43 51 case 8: \
  52 + { \
  53 + volatile u64 *__ptr = (volatile u64 *)(ptr); \
44 54 asm volatile("xchgq %0,%1" \
45   - : "=r" (__x), "+m" (*__xg(ptr)) \
  55 + : "=r" (__x), "+m" (*__ptr) \
46 56 : "0" (__x) \
47 57 : "memory"); \
48 58 break; \
  59 + } \
49 60 default: \
50 61 __xchg_wrong_size(); \
51 62 } \
52 63  
53 64  
54 65  
55 66  
56 67  
57 68  
58 69  
59 70  
... ... @@ -69,29 +80,41 @@
69 80 __typeof__(*(ptr)) __new = (new); \
70 81 switch (size) { \
71 82 case 1: \
72   - asm volatile(lock "cmpxchgb %b2,%1" \
73   - : "=a" (__ret), "+m" (*__xg(ptr)) \
  83 + { \
  84 + volatile u8 *__ptr = (volatile u8 *)(ptr); \
  85 + asm volatile(lock "cmpxchgb %2,%1" \
  86 + : "=a" (__ret), "+m" (*__ptr) \
74 87 : "q" (__new), "0" (__old) \
75 88 : "memory"); \
76 89 break; \
  90 + } \
77 91 case 2: \
78   - asm volatile(lock "cmpxchgw %w2,%1" \
79   - : "=a" (__ret), "+m" (*__xg(ptr)) \
  92 + { \
  93 + volatile u16 *__ptr = (volatile u16 *)(ptr); \
  94 + asm volatile(lock "cmpxchgw %2,%1" \
  95 + : "=a" (__ret), "+m" (*__ptr) \
80 96 : "r" (__new), "0" (__old) \
81 97 : "memory"); \
82 98 break; \
  99 + } \
83 100 case 4: \
84   - asm volatile(lock "cmpxchgl %k2,%1" \
85   - : "=a" (__ret), "+m" (*__xg(ptr)) \
  101 + { \
  102 + volatile u32 *__ptr = (volatile u32 *)(ptr); \
  103 + asm volatile(lock "cmpxchgl %2,%1" \
  104 + : "=a" (__ret), "+m" (*__ptr) \
86 105 : "r" (__new), "0" (__old) \
87 106 : "memory"); \
88 107 break; \
  108 + } \
89 109 case 8: \
  110 + { \
  111 + volatile u64 *__ptr = (volatile u64 *)(ptr); \
90 112 asm volatile(lock "cmpxchgq %2,%1" \
91   - : "=a" (__ret), "+m" (*__xg(ptr)) \
  113 + : "=a" (__ret), "+m" (*__ptr) \
92 114 : "r" (__new), "0" (__old) \
93 115 : "memory"); \
94 116 break; \
  117 + } \
95 118 default: \
96 119 __cmpxchg_wrong_size(); \
97 120 } \