X-Git-Url: https://git.lttng.org/?p=urcu.git;a=blobdiff_plain;f=urcu%2Fref.h;h=2b803e5b68e4710606df29f128ff7f1637dc1472;hp=74be50d6bbe4e46d28603ba4cb8de3db2ed7794a;hb=7ce99d0278e87880d1382cdf791bb84f7b489ea4;hpb=b2633d211b186cb201be327ded53ecf523ecf0bd diff --git a/urcu/ref.h b/urcu/ref.h index 74be50d..2b803e5 100644 --- a/urcu/ref.h +++ b/urcu/ref.h @@ -16,6 +16,8 @@ #include #include +#include +#include #include struct urcu_ref { @@ -34,7 +36,20 @@ static inline void urcu_ref_init(struct urcu_ref *ref) static inline void urcu_ref_get(struct urcu_ref *ref) { - uatomic_add(&ref->refcount, 1); + long old, _new, res; + + old = uatomic_read(&ref->refcount); + for (;;) { + if (old == LONG_MAX) { + abort(); + } + _new = old + 1; + res = uatomic_cmpxchg(&ref->refcount, old, _new); + if (res == old) { + return; + } + old = res; + } } static inline void urcu_ref_put(struct urcu_ref *ref, @@ -53,7 +68,8 @@ static inline void urcu_ref_put(struct urcu_ref *ref, * 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. + * count. False is also returned in case incrementing the refcount would + * result in an overflow. */ static inline bool urcu_ref_get_unless_zero(struct urcu_ref *ref) { @@ -61,7 +77,7 @@ static inline bool urcu_ref_get_unless_zero(struct urcu_ref *ref) old = uatomic_read(&ref->refcount); for (;;) { - if (old == 0) + if (old == 0 || old == LONG_MAX) return false; /* Failure. */ _new = old + 1; res = uatomic_cmpxchg(&ref->refcount, old, _new);