aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2015-12-27 06:50:07 -0500
committerMichael S. Tsirkin <mst@redhat.com>2016-01-12 13:46:52 -0500
commita9e4252a9b147043142282ebb65da94dcb951e2a (patch)
tree3dfee15c77d72dbc33843f587afd291bd2a06f8a
parent300b06d4555305dc227748674f75970f2f84c224 (diff)
asm-generic: add __smp_xxx wrappers
On !SMP, most architectures define their barriers as compiler barriers. On SMP, most need an actual barrier. Make it possible to remove the code duplication for !SMP by defining low-level __smp_xxx barriers which do not depend on the value of SMP, then use them from asm-generic conditionally. Besides reducing code duplication, these low level APIs will also be useful for virtualization, where a barrier is sometimes needed even if !SMP since we might be talking to another kernel on the same SMP system. Both virtio and Xen drivers will benefit. The smp_xxx variants should use __smp_XXX ones or barrier() depending on SMP, identically for all architectures. We keep ifndef guards around them for now - once/if all architectures are converted to use the generic code, we'll be able to remove these. Suggested-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
-rw-r--r--include/asm-generic/barrier.h91
1 files changed, 82 insertions, 9 deletions
diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h
index 987b2e04ad5a..8752964f8ff7 100644
--- a/include/asm-generic/barrier.h
+++ b/include/asm-generic/barrier.h
@@ -54,22 +54,38 @@
54#define read_barrier_depends() do { } while (0) 54#define read_barrier_depends() do { } while (0)
55#endif 55#endif
56 56
57#ifndef __smp_mb
58#define __smp_mb() mb()
59#endif
60
61#ifndef __smp_rmb
62#define __smp_rmb() rmb()
63#endif
64
65#ifndef __smp_wmb
66#define __smp_wmb() wmb()
67#endif
68
69#ifndef __smp_read_barrier_depends
70#define __smp_read_barrier_depends() read_barrier_depends()
71#endif
72
57#ifdef CONFIG_SMP 73#ifdef CONFIG_SMP
58 74
59#ifndef smp_mb 75#ifndef smp_mb
60#define smp_mb() mb() 76#define smp_mb() __smp_mb()
61#endif 77#endif
62 78
63#ifndef smp_rmb 79#ifndef smp_rmb
64#define smp_rmb() rmb() 80#define smp_rmb() __smp_rmb()
65#endif 81#endif
66 82
67#ifndef smp_wmb 83#ifndef smp_wmb
68#define smp_wmb() wmb() 84#define smp_wmb() __smp_wmb()
69#endif 85#endif
70 86
71#ifndef smp_read_barrier_depends 87#ifndef smp_read_barrier_depends
72#define smp_read_barrier_depends() read_barrier_depends() 88#define smp_read_barrier_depends() __smp_read_barrier_depends()
73#endif 89#endif
74 90
75#else /* !CONFIG_SMP */ 91#else /* !CONFIG_SMP */
@@ -92,23 +108,78 @@
92 108
93#endif /* CONFIG_SMP */ 109#endif /* CONFIG_SMP */
94 110
111#ifndef __smp_store_mb
112#define __smp_store_mb(var, value) do { WRITE_ONCE(var, value); __smp_mb(); } while (0)
113#endif
114
115#ifndef __smp_mb__before_atomic
116#define __smp_mb__before_atomic() __smp_mb()
117#endif
118
119#ifndef __smp_mb__after_atomic
120#define __smp_mb__after_atomic() __smp_mb()
121#endif
122
123#ifndef __smp_store_release
124#define __smp_store_release(p, v) \
125do { \
126 compiletime_assert_atomic_type(*p); \
127 __smp_mb(); \
128 WRITE_ONCE(*p, v); \
129} while (0)
130#endif
131
132#ifndef __smp_load_acquire
133#define __smp_load_acquire(p) \
134({ \
135 typeof(*p) ___p1 = READ_ONCE(*p); \
136 compiletime_assert_atomic_type(*p); \
137 __smp_mb(); \
138 ___p1; \
139})
140#endif
141
142#ifdef CONFIG_SMP
143
144#ifndef smp_store_mb
145#define smp_store_mb(var, value) __smp_store_mb(var, value)
146#endif
147
148#ifndef smp_mb__before_atomic
149#define smp_mb__before_atomic() __smp_mb__before_atomic()
150#endif
151
152#ifndef smp_mb__after_atomic
153#define smp_mb__after_atomic() __smp_mb__after_atomic()
154#endif
155
156#ifndef smp_store_release
157#define smp_store_release(p, v) __smp_store_release(p, v)
158#endif
159
160#ifndef smp_load_acquire
161#define smp_load_acquire(p) __smp_load_acquire(p)
162#endif
163
164#else /* !CONFIG_SMP */
165
95#ifndef smp_store_mb 166#ifndef smp_store_mb
96#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); smp_mb(); } while (0) 167#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); barrier(); } while (0)
97#endif 168#endif
98 169
99#ifndef smp_mb__before_atomic 170#ifndef smp_mb__before_atomic
100#define smp_mb__before_atomic() smp_mb() 171#define smp_mb__before_atomic() barrier()
101#endif 172#endif
102 173
103#ifndef smp_mb__after_atomic 174#ifndef smp_mb__after_atomic
104#define smp_mb__after_atomic() smp_mb() 175#define smp_mb__after_atomic() barrier()
105#endif 176#endif
106 177
107#ifndef smp_store_release 178#ifndef smp_store_release
108#define smp_store_release(p, v) \ 179#define smp_store_release(p, v) \
109do { \ 180do { \
110 compiletime_assert_atomic_type(*p); \ 181 compiletime_assert_atomic_type(*p); \
111 smp_mb(); \ 182 barrier(); \
112 WRITE_ONCE(*p, v); \ 183 WRITE_ONCE(*p, v); \
113} while (0) 184} while (0)
114#endif 185#endif
@@ -118,10 +189,12 @@ do { \
118({ \ 189({ \
119 typeof(*p) ___p1 = READ_ONCE(*p); \ 190 typeof(*p) ___p1 = READ_ONCE(*p); \
120 compiletime_assert_atomic_type(*p); \ 191 compiletime_assert_atomic_type(*p); \
121 smp_mb(); \ 192 barrier(); \
122 ___p1; \ 193 ___p1; \
123}) 194})
124#endif 195#endif
125 196
197#endif
198
126#endif /* !__ASSEMBLY__ */ 199#endif /* !__ASSEMBLY__ */
127#endif /* __ASM_GENERIC_BARRIER_H */ 200#endif /* __ASM_GENERIC_BARRIER_H */