[ovs-dev] [PATCH] ovs-rcu: Add new ovsrcu_index type.
Jarno Rajahalme
jarno at ovn.org
Wed Aug 3 22:00:12 UTC 2016
Looks good to me,
Acked-by: Jarno Rajahalme <jarno at ovn.org>
> On Aug 2, 2016, at 5:03 PM, Daniele Di Proietto <diproiettod at vmware.com> wrote:
>
> With RCU in Open vSwitch it's very easy to protect objects accessed by
> a pointer, but sometimes a pointer is not available.
>
> One example is the vhost id for DPDK 16.07. Until DPDK 16.04 a pointer
> was used to access a vhost device with RCU semantics. From DPDK 16.07
> an integer id (which is an array index) is used to access a vhost
> device. Ideally, we want the exact same RCU semantics that we had for
> the pointer, on the integer (atomicity, memory barriers, behaviour
> around quiescent states)
>
> This commit implements a new type in ovs-rcu: ovsrcu_index. The newly
> implemented ovsrcu_index_*() functions should be used to access the
> type.
>
> Even though we say "Do not, in general, declare a typedef for a struct,
> union, or enum.", I think we're not in the "general" case.
>
> Signed-off-by: Daniele Di Proietto <diproiettod at vmware.com>
> ---
> lib/ovs-rcu.h | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 84 insertions(+)
>
> diff --git a/lib/ovs-rcu.h b/lib/ovs-rcu.h
> index dc75749..2887bb8 100644
> --- a/lib/ovs-rcu.h
> +++ b/lib/ovs-rcu.h
> @@ -125,6 +125,36 @@
> * ovs_mutex_unlock(&mutex);
> * }
> *
> + * In some rare cases an object may not be addressable with a pointer, but only
> + * through an array index (e.g. because it's provided by another library). It
> + * is still possible to have RCU semantics by using the ovsrcu_index type.
> + *
> + * static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
> + *
> + * ovsrcu_index port_id;
> + *
> + * void tx()
> + * {
> + * int id = ovsrcu_index_get(&port_id);
> + * if (id == -1) {
> + * return;
> + * }
> + * port_tx(id);
> + * }
> + *
> + * void delete()
> + * {
> + * int id;
> + *
> + * ovs_mutex_lock(&mutex);
> + * id = ovsrcu_index_get_protected(&port_id);
> + * ovsrcu_index_set(&port_id, -1);
> + * ovs_mutex_unlock(&mutex);
> + *
> + * ovsrcu_synchronize();
> + * port_delete(id);
> + * }
> + *
> */
>
> #include "compiler.h"
> @@ -213,6 +243,60 @@ void ovsrcu_postpone__(void (*function)(void *aux), void *aux);
> (void) sizeof(*(ARG)), \
> ovsrcu_postpone__((void (*)(void *))(FUNCTION), ARG))
>
> +/* An array index protected by RCU semantics. This is an easier alternative to
> + * an RCU protected pointer to a malloc'd int. */
> +typedef struct { atomic_int v; } ovsrcu_index;
> +
> +static inline int ovsrcu_index_get__(const ovsrcu_index *i, memory_order order)
> +{
> + int ret;
> + atomic_read_explicit(CONST_CAST(atomic_int *, &i->v), &ret, order);
> + return ret;
> +}
> +
> +/* Returns the index contained in 'i'. The returned value can be used until
> + * the next grace period. */
> +static inline int ovsrcu_index_get(const ovsrcu_index *i)
> +{
> + return ovsrcu_index_get__(i, memory_order_consume);
> +}
> +
> +/* Returns the index contained in 'i'. This is an alternative to
> + * ovsrcu_index_get() that can be used when there's no possible concurrent
> + * writer. */
> +static inline int ovsrcu_index_get_protected(const ovsrcu_index *i)
> +{
> + return ovsrcu_index_get__(i, memory_order_relaxed);
> +}
> +
> +static inline void ovsrcu_index_set__(ovsrcu_index *i, int value,
> + memory_order order)
> +{
> + atomic_store_explicit(&i->v, value, order);
> +}
> +
> +/* Writes the index 'value' in 'i'. The previous value of 'i' may still be
> + * used by readers until the next grace period. */
> +static inline void ovsrcu_index_set(ovsrcu_index *i, int value)
> +{
> + ovsrcu_index_set__(i, value, memory_order_release);
> +}
> +
> +/* Writes the index 'value' in 'i'. This is an alternative to
> + * ovsrcu_index_set() that can be used when there's no possible concurrent
> + * reader. */
> +static inline void ovsrcu_index_set_hidden(ovsrcu_index *i, int value)
> +{
> + ovsrcu_index_set__(i, value, memory_order_relaxed);
> +}
> +
> +/* Initializes 'i' with 'value'. This is safe to call as long as there are no
> + * concurrent readers. */
> +static inline void ovsrcu_index_init(ovsrcu_index *i, int value)
> +{
> + atomic_init(&i->v, value);
> +}
> +
> /* Quiescent states. */
> void ovsrcu_quiesce_start(void);
> void ovsrcu_quiesce_end(void);
> --
> 2.8.1
>
More information about the dev
mailing list