[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