}
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
{
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);
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];
* 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;
*
/* 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);