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 <jrajaha...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev