[ovs-dev] [RFC 02/10] ovs-rcu: Introduce ovsrcu_compare_exchange()
Daniele Di Proietto
ddiproietto at vmware.com
Wed Oct 8 21:09:48 UTC 2014
ovsrcu_compare_exchange() can be used to write to RCU pointers without explicit
locking. It maybe useful to implement lists and other simple data structures.
Following commits make use of this
Signed-off-by: Daniele Di Proietto <ddiproietto at vmware.com>
---
lib/ovs-rcu.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/lib/ovs-rcu.h b/lib/ovs-rcu.h
index 96b3233..5a8064b 100644
--- a/lib/ovs-rcu.h
+++ b/lib/ovs-rcu.h
@@ -112,6 +112,24 @@
* ovs_mutex_unlock(&mutex);
* }
*
+ * Use ovsrcu_compare_exchange() to write an RCU-protected pointer without
+ * external synchronization. E.g.:
+ *
+ * OVSRCU_TYPE(struct flow *) flowp;
+ *
+ * void
+ * change_flow(struct flow *new_flow)
+ * {
+ * struct flow *old;
+ *
+ * old = ovsrcu_get(struct flow *, &flowp);
+ *
+ * do {
+ *
+ * } while (!ovsrcu_compare_exchange(&flowp, &old, new_flow));
+ *
+ * ovsrcu_postpone(free, old);
+ * }
*/
#include "compiler.h"
@@ -134,6 +152,25 @@
ovsrcu_get__(TYPE, VAR, memory_order_consume)
#define ovsrcu_get_protected(TYPE, VAR) \
ovsrcu_get__(TYPE, VAR, memory_order_relaxed)
+#define ovsrcu_compare_exchange__(VAR, EXP, VALUE, ORDER_SUCC, ORDER_FAIL) \
+ ({ \
+ typeof(VAR) ovsrcu_var = (VAR); \
+ typeof(VALUE) ovsrcu_value = (VALUE); \
+ \
+ atomic_compare_exchange_weak_explicit(&ovsrcu_var->p, (EXP), \
+ ovsrcu_value, \
+ (ORDER_SUCC), (ORDER_FAIL)); \
+ })
+#define ovsrcu_compare_exchange_strong__(VAR, EXP, VALUE, ORDER_SUCC, \
+ ORDER_FAIL) \
+ ({ \
+ typeof(VAR) ovsrcu_var = (VAR); \
+ typeof(VALUE) ovsrcu_value = (VALUE); \
+ \
+ atomic_compare_exchange_strong_explicit(&ovsrcu_var->p, (EXP), \
+ ovsrcu_value, \
+ (ORDER_SUCC), (ORDER_FAIL)); \
+ })
/* 'VALUE' may be an atomic operation, which must be evaluated before
* any of the body of the atomic_store_explicit. Since the type of
@@ -171,6 +208,33 @@ static inline void ovsrcu_set__(struct ovsrcu_pointer *pointer,
{
atomic_store_explicit(&pointer->p, CONST_CAST(void *, value), order);
}
+
+static inline bool ovsrcu_compare_exchange__(struct ovsrcu_pointer *pointer,
+ const void *exp,
+ void *value,
+ memory_order order_succ,
+ memory_order order_fail)
+{
+ return atomic_compare_exchange_weak_explicit(&pointer->p,
+ CONST_CAST(void *, exp),
+ value,
+ order_succ,
+ order_fail);
+}
+
+static inline bool ovsrcu_compare_exchange_strong__
+ (struct ovsrcu_pointer *pointer,
+ const void *exp,
+ void *value,
+ memory_order order_succ,
+ memory_order order_fail)
+{
+ return atomic_compare_exchange_strong_explicit(&pointer->p,
+ CONST_CAST(void *, exp),
+ value,
+ order_succ,
+ order_fail);
+}
#endif
/* Writes VALUE to the RCU-protected pointer whose address is VAR.
@@ -198,6 +262,23 @@ void ovsrcu_postpone__(void (*function)(void *aux), void *aux);
(void) sizeof(*(ARG)), \
ovsrcu_postpone__((void (*)(void *))(FUNCTION), ARG))
+/* Writes VALUE to the RCU-protected pointer whose address is VAR, only if *VAR
+ * and *EXP contain the same value. If successful returns true, else return
+ * false.
+ *
+ * Users might not require external synchronization. See "Usage" above
+ * for an example. */
+#define ovsrcu_compare_exchange(VAR, EXP, VALUE) \
+ ovsrcu_compare_exchange__(VAR, EXP, VALUE, memory_order_release, \
+ memory_order_consume)
+
+/* Same as ovsrcu_compare_exchange(), but uses compare_exchange_strong
+ * semantics. This should be used only if it is not acceptable to have
+ * 'spurious failures' (see ovs-atomic.h)
+*/
+#define ovsrcu_compare_exchange_strong(VAR, EXP, VALUE) \
+ ovsrcu_compare_exchange_strong__(VAR, EXP, VALUE, memory_order_release, \
+ memory_order_consume)
/* Quiescent states. */
void ovsrcu_quiesce_start(void);
void ovsrcu_quiesce_end(void);
--
2.1.0.rc1
More information about the dev
mailing list