|
@@ -207,5 +207,44 @@ do { \
|
|
|
#define virt_store_release(p, v) __smp_store_release(p, v)
|
|
|
#define virt_load_acquire(p) __smp_load_acquire(p)
|
|
|
|
|
|
+/**
|
|
|
+ * smp_acquire__after_ctrl_dep() - Provide ACQUIRE ordering after a control dependency
|
|
|
+ *
|
|
|
+ * A control dependency provides a LOAD->STORE order, the additional RMB
|
|
|
+ * provides LOAD->LOAD order, together they provide LOAD->{LOAD,STORE} order,
|
|
|
+ * aka. (load)-ACQUIRE.
|
|
|
+ *
|
|
|
+ * Architectures that do not do load speculation can have this be barrier().
|
|
|
+ */
|
|
|
+#ifndef smp_acquire__after_ctrl_dep
|
|
|
+#define smp_acquire__after_ctrl_dep() smp_rmb()
|
|
|
+#endif
|
|
|
+
|
|
|
+/**
|
|
|
+ * smp_cond_load_acquire() - (Spin) wait for cond with ACQUIRE ordering
|
|
|
+ * @ptr: pointer to the variable to wait on
|
|
|
+ * @cond: boolean expression to wait for
|
|
|
+ *
|
|
|
+ * Equivalent to using smp_load_acquire() on the condition variable but employs
|
|
|
+ * the control dependency of the wait to reduce the barrier on many platforms.
|
|
|
+ *
|
|
|
+ * Due to C lacking lambda expressions we load the value of *ptr into a
|
|
|
+ * pre-named variable @VAL to be used in @cond.
|
|
|
+ */
|
|
|
+#ifndef smp_cond_load_acquire
|
|
|
+#define smp_cond_load_acquire(ptr, cond_expr) ({ \
|
|
|
+ typeof(ptr) __PTR = (ptr); \
|
|
|
+ typeof(*ptr) VAL; \
|
|
|
+ for (;;) { \
|
|
|
+ VAL = READ_ONCE(*__PTR); \
|
|
|
+ if (cond_expr) \
|
|
|
+ break; \
|
|
|
+ cpu_relax(); \
|
|
|
+ } \
|
|
|
+ smp_acquire__after_ctrl_dep(); \
|
|
|
+ VAL; \
|
|
|
+})
|
|
|
+#endif
|
|
|
+
|
|
|
#endif /* !__ASSEMBLY__ */
|
|
|
#endif /* __ASM_GENERIC_BARRIER_H */
|