[ovs-dev] [PATCH 3/3] lib/ovs-rcu: Rename ovsrcu_init() as ovsrcu_set_hidden().

Jarno Rajahalme jrajahalme at nicira.com
Tue Jun 3 00:32:16 UTC 2014


ovsrcu_init() was named after the atomic_init(), but the semantics are
different enough to warrant a different name.  Basically C11
atomic_init is defined in a way that allows the implementation to
assign the value without any syncronization, so in theory stores via
atomic_init could be seen by others after stores via atomic_set, even
if the atomic_init appeared earlier in the code.

ovsrcu_set_hidden() can be used to set an RCU protected variable when
it is not yet accessible by any active reader, but will be made
visible later via an ovsrcu_set call on some other pointer.

This patch also adds a new ovsrcu_init() that can be used to initilize
RCU protected variables when the readers are not yet executing.  The
new ovsrcu_init() is implemented with atomic_init(), so it does not
provide any kind of syncronization.

Signed-off-by: Jarno Rajahalme <jrajahalme at nicira.com>
---
 lib/cmap.c    |    6 +++---
 lib/ovs-rcu.h |   20 +++++++++++++-------
 2 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/lib/cmap.c b/lib/cmap.c
index a760235..ae362f5 100644
--- a/lib/cmap.c
+++ b/lib/cmap.c
@@ -448,7 +448,7 @@ cmap_insert_dup(struct cmap_node *new_node, uint32_t hash,
                     }
                     p = next;
                 }
-                ovsrcu_init(&p->next, node);
+                ovsrcu_set_hidden(&p->next, node);
             } else {
                 /* The hash value is there from some previous insertion, but
                  * the associated node has been removed.  We're not really
@@ -660,7 +660,7 @@ cmap_insert(struct cmap *cmap, struct cmap_node *node, uint32_t hash)
 {
     struct cmap_impl *impl = cmap_get_impl(cmap);
 
-    ovsrcu_init(&node->next, NULL);
+    ovsrcu_set_hidden(&node->next, NULL);
 
     if (OVS_UNLIKELY(impl->n >= impl->max_n)) {
         impl = cmap_rehash(cmap, (impl->mask << 1) | 1);
@@ -690,7 +690,7 @@ cmap_replace__(struct cmap_impl *impl, struct cmap_node *node,
         replacement = cmap_node_next_protected(node);
     } else {
         /* 'replacement' takes the position of 'node' in the list. */
-        ovsrcu_init(&replacement->next, cmap_node_next_protected(node));
+        ovsrcu_set_hidden(&replacement->next, cmap_node_next_protected(node));
     }
 
     struct cmap_node *iter = &b->nodes[slot];
diff --git a/lib/ovs-rcu.h b/lib/ovs-rcu.h
index e27dfad..571a139 100644
--- a/lib/ovs-rcu.h
+++ b/lib/ovs-rcu.h
@@ -89,12 +89,14 @@
  * compilers will merrily carry along accepting the wrong type.)
  *
  * Use ovsrcu_set() to write an RCU-protected pointer and ovsrcu_postpone() to
- * free the previous data.  ovsrcu_init() can be used on (newly created) RCU-
- * protected pointer that is not yet visible to the readers.  If more than one
- * thread can write the pointer, then some form of external synchronization,
- * e.g. a mutex, is needed to prevent writers from interfering with one
- * another.  For example, to write the pointer variable declared above while
- * safely freeing the old value:
+ * free the previous data.  ovsrcu_set_hidden() can be used on RCU protected
+ * data not visible to any readers yet, but will be made visible by a later
+ * ovsrcu_set().   ovsrcu_init() can be used to initialize RCU pointers when
+ * no readers are yet executing.  If more than one thread can write the
+ * pointer, then some form of external synchronization, e.g. a mutex, is
+ * needed to prevent writers from interfering with one another.  For example,
+ * to write the pointer variable declared above while safely freeing the old
+ * value:
  *
  *     static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
  *
@@ -180,9 +182,13 @@ static inline void ovsrcu_set__(struct ovsrcu_pointer *pointer,
 /* This can be used for initializing RCU pointers before any readers can
  * see them.  A later ovsrcu_set() needs to make the bigger structure this
  * is part of visible to the readers. */
-#define ovsrcu_init(VAR, VALUE) \
+#define ovsrcu_set_hidden(VAR, VALUE) \
     ovsrcu_set__(VAR, VALUE, memory_order_relaxed)
 
+/* This can be used for initializing RCU pointers before any readers are
+ * executing. */
+#define ovsrcu_init(VAR, VALUE) atomic_init(&(VAR)->p, VALUE)
+
 /* Calls FUNCTION passing ARG as its pointer-type argument following the next
  * grace period.  See "Usage" above for example.  */
 void ovsrcu_postpone__(void (*function)(void *aux), void *aux);
-- 
1.7.10.4




More information about the dev mailing list