> 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>
Acked-by: YAMAMOTO Takashi <yamam...@valinux.co.jp> > --- > 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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev