diff options
author | Len Brown <len.brown@intel.com> | 2010-08-15 01:06:31 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-08-15 01:06:31 -0400 |
commit | 95ee46aa8698f2000647dfb362400fadbb5807cf (patch) | |
tree | e5a05c7297f997e191c73091934e42e3195c0e40 /arch/x86/include/asm/cmpxchg_64.h | |
parent | cfa806f059801dbe7e435745eb2e187c8bfe1e7f (diff) | |
parent | 92fa5bd9a946b6e7aab6764e7312e4e3d9bed295 (diff) |
Merge branch 'linus' into release
Conflicts:
drivers/acpi/debug.c
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'arch/x86/include/asm/cmpxchg_64.h')
-rw-r--r-- | arch/x86/include/asm/cmpxchg_64.h | 83 |
1 files changed, 52 insertions, 31 deletions
diff --git a/arch/x86/include/asm/cmpxchg_64.h b/arch/x86/include/asm/cmpxchg_64.h index 485ae415faec..423ae58aa020 100644 --- a/arch/x86/include/asm/cmpxchg_64.h +++ b/arch/x86/include/asm/cmpxchg_64.h | |||
@@ -3,51 +3,60 @@ | |||
3 | 3 | ||
4 | #include <asm/alternative.h> /* Provides LOCK_PREFIX */ | 4 | #include <asm/alternative.h> /* Provides LOCK_PREFIX */ |
5 | 5 | ||
6 | #define __xg(x) ((volatile long *)(x)) | 6 | static inline void set_64bit(volatile u64 *ptr, u64 val) |
7 | |||
8 | static inline void set_64bit(volatile unsigned long *ptr, unsigned long val) | ||
9 | { | 7 | { |
10 | *ptr = val; | 8 | *ptr = val; |
11 | } | 9 | } |
12 | 10 | ||
13 | #define _set_64bit set_64bit | ||
14 | |||
15 | extern void __xchg_wrong_size(void); | 11 | extern void __xchg_wrong_size(void); |
16 | extern void __cmpxchg_wrong_size(void); | 12 | extern void __cmpxchg_wrong_size(void); |
17 | 13 | ||
18 | /* | 14 | /* |
19 | * Note: no "lock" prefix even on SMP: xchg always implies lock anyway | 15 | * Note: no "lock" prefix even on SMP: xchg always implies lock anyway. |
20 | * Note 2: xchg has side effect, so that attribute volatile is necessary, | 16 | * Since this is generally used to protect other memory information, we |
21 | * but generally the primitive is invalid, *ptr is output argument. --ANK | 17 | * use "asm volatile" and "memory" clobbers to prevent gcc from moving |
18 | * information around. | ||
22 | */ | 19 | */ |
23 | #define __xchg(x, ptr, size) \ | 20 | #define __xchg(x, ptr, size) \ |
24 | ({ \ | 21 | ({ \ |
25 | __typeof(*(ptr)) __x = (x); \ | 22 | __typeof(*(ptr)) __x = (x); \ |
26 | switch (size) { \ | 23 | switch (size) { \ |
27 | case 1: \ | 24 | case 1: \ |
28 | asm volatile("xchgb %b0,%1" \ | 25 | { \ |
29 | : "=q" (__x) \ | 26 | volatile u8 *__ptr = (volatile u8 *)(ptr); \ |
30 | : "m" (*__xg(ptr)), "0" (__x) \ | 27 | asm volatile("xchgb %0,%1" \ |
28 | : "=q" (__x), "+m" (*__ptr) \ | ||
29 | : "0" (__x) \ | ||
31 | : "memory"); \ | 30 | : "memory"); \ |
32 | break; \ | 31 | break; \ |
32 | } \ | ||
33 | case 2: \ | 33 | case 2: \ |
34 | asm volatile("xchgw %w0,%1" \ | 34 | { \ |
35 | : "=r" (__x) \ | 35 | volatile u16 *__ptr = (volatile u16 *)(ptr); \ |
36 | : "m" (*__xg(ptr)), "0" (__x) \ | 36 | asm volatile("xchgw %0,%1" \ |
37 | : "=r" (__x), "+m" (*__ptr) \ | ||
38 | : "0" (__x) \ | ||
37 | : "memory"); \ | 39 | : "memory"); \ |
38 | break; \ | 40 | break; \ |
41 | } \ | ||
39 | case 4: \ | 42 | case 4: \ |
40 | asm volatile("xchgl %k0,%1" \ | 43 | { \ |
41 | : "=r" (__x) \ | 44 | volatile u32 *__ptr = (volatile u32 *)(ptr); \ |
42 | : "m" (*__xg(ptr)), "0" (__x) \ | 45 | asm volatile("xchgl %0,%1" \ |
46 | : "=r" (__x), "+m" (*__ptr) \ | ||
47 | : "0" (__x) \ | ||
43 | : "memory"); \ | 48 | : "memory"); \ |
44 | break; \ | 49 | break; \ |
50 | } \ | ||
45 | case 8: \ | 51 | case 8: \ |
52 | { \ | ||
53 | volatile u64 *__ptr = (volatile u64 *)(ptr); \ | ||
46 | asm volatile("xchgq %0,%1" \ | 54 | asm volatile("xchgq %0,%1" \ |
47 | : "=r" (__x) \ | 55 | : "=r" (__x), "+m" (*__ptr) \ |
48 | : "m" (*__xg(ptr)), "0" (__x) \ | 56 | : "0" (__x) \ |
49 | : "memory"); \ | 57 | : "memory"); \ |
50 | break; \ | 58 | break; \ |
59 | } \ | ||
51 | default: \ | 60 | default: \ |
52 | __xchg_wrong_size(); \ | 61 | __xchg_wrong_size(); \ |
53 | } \ | 62 | } \ |
@@ -71,29 +80,41 @@ extern void __cmpxchg_wrong_size(void); | |||
71 | __typeof__(*(ptr)) __new = (new); \ | 80 | __typeof__(*(ptr)) __new = (new); \ |
72 | switch (size) { \ | 81 | switch (size) { \ |
73 | case 1: \ | 82 | case 1: \ |
74 | asm volatile(lock "cmpxchgb %b1,%2" \ | 83 | { \ |
75 | : "=a"(__ret) \ | 84 | volatile u8 *__ptr = (volatile u8 *)(ptr); \ |
76 | : "q"(__new), "m"(*__xg(ptr)), "0"(__old) \ | 85 | asm volatile(lock "cmpxchgb %2,%1" \ |
86 | : "=a" (__ret), "+m" (*__ptr) \ | ||
87 | : "q" (__new), "0" (__old) \ | ||
77 | : "memory"); \ | 88 | : "memory"); \ |
78 | break; \ | 89 | break; \ |
90 | } \ | ||
79 | case 2: \ | 91 | case 2: \ |
80 | asm volatile(lock "cmpxchgw %w1,%2" \ | 92 | { \ |
81 | : "=a"(__ret) \ | 93 | volatile u16 *__ptr = (volatile u16 *)(ptr); \ |
82 | : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ | 94 | asm volatile(lock "cmpxchgw %2,%1" \ |
95 | : "=a" (__ret), "+m" (*__ptr) \ | ||
96 | : "r" (__new), "0" (__old) \ | ||
83 | : "memory"); \ | 97 | : "memory"); \ |
84 | break; \ | 98 | break; \ |
99 | } \ | ||
85 | case 4: \ | 100 | case 4: \ |
86 | asm volatile(lock "cmpxchgl %k1,%2" \ | 101 | { \ |
87 | : "=a"(__ret) \ | 102 | volatile u32 *__ptr = (volatile u32 *)(ptr); \ |
88 | : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ | 103 | asm volatile(lock "cmpxchgl %2,%1" \ |
104 | : "=a" (__ret), "+m" (*__ptr) \ | ||
105 | : "r" (__new), "0" (__old) \ | ||
89 | : "memory"); \ | 106 | : "memory"); \ |
90 | break; \ | 107 | break; \ |
108 | } \ | ||
91 | case 8: \ | 109 | case 8: \ |
92 | asm volatile(lock "cmpxchgq %1,%2" \ | 110 | { \ |
93 | : "=a"(__ret) \ | 111 | volatile u64 *__ptr = (volatile u64 *)(ptr); \ |
94 | : "r"(__new), "m"(*__xg(ptr)), "0"(__old) \ | 112 | asm volatile(lock "cmpxchgq %2,%1" \ |
113 | : "=a" (__ret), "+m" (*__ptr) \ | ||
114 | : "r" (__new), "0" (__old) \ | ||
95 | : "memory"); \ | 115 | : "memory"); \ |
96 | break; \ | 116 | break; \ |
117 | } \ | ||
97 | default: \ | 118 | default: \ |
98 | __cmpxchg_wrong_size(); \ | 119 | __cmpxchg_wrong_size(); \ |
99 | } \ | 120 | } \ |