ovsrcu_compare_exchange() can be used to write to RCU pointers without explicit locking. It maybe useful to implement lists and other simple data structures.
Following commits make use of this Signed-off-by: Daniele Di Proietto <ddiproie...@vmware.com> --- lib/ovs-rcu.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/lib/ovs-rcu.h b/lib/ovs-rcu.h index 96b3233..5a8064b 100644 --- a/lib/ovs-rcu.h +++ b/lib/ovs-rcu.h @@ -112,6 +112,24 @@ * ovs_mutex_unlock(&mutex); * } * + * Use ovsrcu_compare_exchange() to write an RCU-protected pointer without + * external synchronization. E.g.: + * + * OVSRCU_TYPE(struct flow *) flowp; + * + * void + * change_flow(struct flow *new_flow) + * { + * struct flow *old; + * + * old = ovsrcu_get(struct flow *, &flowp); + * + * do { + * + * } while (!ovsrcu_compare_exchange(&flowp, &old, new_flow)); + * + * ovsrcu_postpone(free, old); + * } */ #include "compiler.h" @@ -134,6 +152,25 @@ ovsrcu_get__(TYPE, VAR, memory_order_consume) #define ovsrcu_get_protected(TYPE, VAR) \ ovsrcu_get__(TYPE, VAR, memory_order_relaxed) +#define ovsrcu_compare_exchange__(VAR, EXP, VALUE, ORDER_SUCC, ORDER_FAIL) \ + ({ \ + typeof(VAR) ovsrcu_var = (VAR); \ + typeof(VALUE) ovsrcu_value = (VALUE); \ + \ + atomic_compare_exchange_weak_explicit(&ovsrcu_var->p, (EXP), \ + ovsrcu_value, \ + (ORDER_SUCC), (ORDER_FAIL)); \ + }) +#define ovsrcu_compare_exchange_strong__(VAR, EXP, VALUE, ORDER_SUCC, \ + ORDER_FAIL) \ + ({ \ + typeof(VAR) ovsrcu_var = (VAR); \ + typeof(VALUE) ovsrcu_value = (VALUE); \ + \ + atomic_compare_exchange_strong_explicit(&ovsrcu_var->p, (EXP), \ + ovsrcu_value, \ + (ORDER_SUCC), (ORDER_FAIL)); \ + }) /* 'VALUE' may be an atomic operation, which must be evaluated before * any of the body of the atomic_store_explicit. Since the type of @@ -171,6 +208,33 @@ static inline void ovsrcu_set__(struct ovsrcu_pointer *pointer, { atomic_store_explicit(&pointer->p, CONST_CAST(void *, value), order); } + +static inline bool ovsrcu_compare_exchange__(struct ovsrcu_pointer *pointer, + const void *exp, + void *value, + memory_order order_succ, + memory_order order_fail) +{ + return atomic_compare_exchange_weak_explicit(&pointer->p, + CONST_CAST(void *, exp), + value, + order_succ, + order_fail); +} + +static inline bool ovsrcu_compare_exchange_strong__ + (struct ovsrcu_pointer *pointer, + const void *exp, + void *value, + memory_order order_succ, + memory_order order_fail) +{ + return atomic_compare_exchange_strong_explicit(&pointer->p, + CONST_CAST(void *, exp), + value, + order_succ, + order_fail); +} #endif /* Writes VALUE to the RCU-protected pointer whose address is VAR. @@ -198,6 +262,23 @@ void ovsrcu_postpone__(void (*function)(void *aux), void *aux); (void) sizeof(*(ARG)), \ ovsrcu_postpone__((void (*)(void *))(FUNCTION), ARG)) +/* Writes VALUE to the RCU-protected pointer whose address is VAR, only if *VAR + * and *EXP contain the same value. If successful returns true, else return + * false. + * + * Users might not require external synchronization. See "Usage" above + * for an example. */ +#define ovsrcu_compare_exchange(VAR, EXP, VALUE) \ + ovsrcu_compare_exchange__(VAR, EXP, VALUE, memory_order_release, \ + memory_order_consume) + +/* Same as ovsrcu_compare_exchange(), but uses compare_exchange_strong + * semantics. This should be used only if it is not acceptable to have + * 'spurious failures' (see ovs-atomic.h) +*/ +#define ovsrcu_compare_exchange_strong(VAR, EXP, VALUE) \ + ovsrcu_compare_exchange_strong__(VAR, EXP, VALUE, memory_order_release, \ + memory_order_consume) /* Quiescent states. */ void ovsrcu_quiesce_start(void); void ovsrcu_quiesce_end(void); -- 2.1.0.rc1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev