summaryrefslogtreecommitdiff
path: root/lib/ovs-rcu.h
diff options
context:
space:
mode:
authorJarno Rajahalme <jrajahalme@nicira.com>2014-05-28 16:56:29 -0700
committerJarno Rajahalme <jrajahalme@nicira.com>2014-05-28 16:56:29 -0700
commite10022d2ac4045a739788670ef26fe48b75ac8af (patch)
treefae6e4c55210fd63f2f778d69029da27e0e6d376 /lib/ovs-rcu.h
parent08feeb7572107988d9bc35259a487e2463c793e8 (diff)
downloadopenvswitch-e10022d2ac4045a739788670ef26fe48b75ac8af.tar.gz
lib/ovs-rcu: Fix documentation, add ovsrcu_init().
lib/ovs-rcu.h had some of the comments duplicated. Add ovsrcu_init() that can be used like ovsrcu_set() when the RCU protected pointer is not yet visible any readers. ovs-rcu internal initialization function is renamed as ovsrcu_init_module(). Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib/ovs-rcu.h')
-rw-r--r--lib/ovs-rcu.h52
1 files changed, 23 insertions, 29 deletions
diff --git a/lib/ovs-rcu.h b/lib/ovs-rcu.h
index 0b4013336..775b829ec 100644
--- a/lib/ovs-rcu.h
+++ b/lib/ovs-rcu.h
@@ -78,27 +78,33 @@
* Use ovsrcu_get(TYPE, VAR) to read an RCU-protected pointer, e.g. to read the
* pointer variable declared above:
*
- * struct flow *flow = ovsrcu_get(struct flow *, flowp);
+ * struct flow *flow = ovsrcu_get(struct flow *, &flowp);
+ *
+ * If the pointer variable is currently protected against change (because
+ * the current thread holds a mutex that protects it), ovsrcu_get_protected()
+ * may be used instead. Only on the Alpha architecture is this likely to
+ * generate different code, but it may be useful documentation.
+ *
+ * (With GNU C or Clang, you get a compiler error if TYPE is wrong; other
+ * 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. 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_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:
*
* static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
*
- * static void
- * free_flow(struct flow *flow)
- * {
- * free(flow);
- * }
+ * OVSRCU_TYPE(struct flow *) flowp;
*
* void
* change_flow(struct flow *new_flow)
* {
* ovs_mutex_lock(&mutex);
- * ovsrcu_postpone(free_flow,
+ * ovsrcu_postpone(free,
* ovsrcu_get_protected(struct flow *, &flowp));
* ovsrcu_set(&flowp, new_flow);
* ovs_mutex_unlock(&mutex);
@@ -109,24 +115,6 @@
#include "compiler.h"
#include "ovs-atomic.h"
-/* Use OVSRCU_TYPE(TYPE) to declare a pointer to RCU-protected data, e.g. the
- * following declares an RCU-protected "struct flow *" named flowp:
- *
- * OVSRCU_TYPE(struct flow *) flowp;
- *
- * Use ovsrcu_get(TYPE, VAR) to read an RCU-protected pointer, e.g. to read the
- * pointer variable declared above:
- *
- * struct flow *flow = ovsrcu_get(struct flow *, &flowp);
- *
- * If the pointer variable is currently protected against change (because
- * the current thread holds a mutex that protects it), ovsrcu_get_protected()
- * may be used instead. Only on the Alpha architecture is this likely to
- * generate different code, but it may be useful documentation.
- *
- * (With GNU C or Clang, you get a compiler error if TYPE is wrong; other
- * compilers will merrily carry along accepting the wrong type.)
- */
#if __GNUC__
#define OVSRCU_TYPE(TYPE) struct { ATOMIC(TYPE) p; }
#define OVSRCU_TYPE_INITIALIZER { NULL }
@@ -168,6 +156,12 @@ ovsrcu_get__(const struct ovsrcu_pointer *pointer, memory_order order)
#define ovsrcu_set(VAR, VALUE) \
atomic_store_explicit(&(VAR)->p, VALUE, memory_order_release)
+/* 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) \
+ atomic_store_explicit(&(VAR)->p, VALUE, memory_order_relaxed)
+
/* 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);