From cd21955a846566b3cd7ca77d58cd3d006f3c533a Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 17 Sep 2015 12:21:05 -0400 Subject: [PATCH] urcu/ref.h: implement urcu_ref_get_unless_zero() Allows getting a reference atomically if the reference count is not zero. Returns true if the reference is taken, false otherwise. This needs to be used in conjunction with another synchronization technique (e.g. RCU or mutex) to ensure existence of the reference count. Signed-off-by: Mathieu Desnoyers --- urcu/ref.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/urcu/ref.h b/urcu/ref.h index a422a99..74be50d 100644 --- a/urcu/ref.h +++ b/urcu/ref.h @@ -15,6 +15,7 @@ */ #include +#include #include struct urcu_ref { @@ -45,4 +46,30 @@ static inline void urcu_ref_put(struct urcu_ref *ref, release(ref); } +/* + * urcu_ref_get_unless_zero + * + * Allows getting a reference atomically if the reference count is not + * zero. Returns true if the reference is taken, false otherwise. This + * needs to be used in conjunction with another synchronization + * technique (e.g. RCU or mutex) to ensure existence of the reference + * count. + */ +static inline bool urcu_ref_get_unless_zero(struct urcu_ref *ref) +{ + long old, _new, res; + + old = uatomic_read(&ref->refcount); + for (;;) { + if (old == 0) + return false; /* Failure. */ + _new = old + 1; + res = uatomic_cmpxchg(&ref->refcount, old, _new); + if (res == old) { + return true; /* Success. */ + } + old = res; + } +} + #endif /* _URCU_REF_H */ -- 2.34.1