Changeset View
Changeset View
Standalone View
Standalone View
head/sys/sys/refcount.h
Show First 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | for (lcount = *count;;) { | ||||
if (__predict_false(lcount + 1 < lcount)) | if (__predict_false(lcount + 1 < lcount)) | ||||
return (false); | return (false); | ||||
if (__predict_true(atomic_fcmpset_int(count, &lcount, | if (__predict_true(atomic_fcmpset_int(count, &lcount, | ||||
lcount + 1) == 1)) | lcount + 1) == 1)) | ||||
return (true); | return (true); | ||||
} | } | ||||
} | } | ||||
static __inline int | static __inline bool | ||||
refcount_release(volatile u_int *count) | refcount_release(volatile u_int *count) | ||||
{ | { | ||||
u_int old; | u_int old; | ||||
atomic_thread_fence_rel(); | atomic_thread_fence_rel(); | ||||
old = atomic_fetchadd_int(count, -1); | old = atomic_fetchadd_int(count, -1); | ||||
KASSERT(old > 0, ("refcount %p is zero", count)); | KASSERT(old > 0, ("refcount %p is zero", count)); | ||||
if (old > 1) | if (old > 1) | ||||
return (0); | return (false); | ||||
/* | /* | ||||
* Last reference. Signal the user to call the destructor. | * Last reference. Signal the user to call the destructor. | ||||
* | * | ||||
* Ensure that the destructor sees all updates. The fence_rel | * Ensure that the destructor sees all updates. The fence_rel | ||||
* at the start of the function synchronized with this fence. | * at the start of the function synchronized with this fence. | ||||
*/ | */ | ||||
atomic_thread_fence_acq(); | atomic_thread_fence_acq(); | ||||
return (1); | return (true); | ||||
} | } | ||||
/* | /* | ||||
* This functions returns non-zero if the refcount was | * This functions returns non-zero if the refcount was | ||||
* incremented. Else zero is returned. | * incremented. Else zero is returned. | ||||
*/ | */ | ||||
static __inline __result_use_check int | static __inline __result_use_check bool | ||||
refcount_acquire_if_not_zero(volatile u_int *count) | refcount_acquire_if_not_zero(volatile u_int *count) | ||||
{ | { | ||||
u_int old; | u_int old; | ||||
old = *count; | old = *count; | ||||
for (;;) { | for (;;) { | ||||
KASSERT(old < UINT_MAX, ("refcount %p overflowed", count)); | KASSERT(old < UINT_MAX, ("refcount %p overflowed", count)); | ||||
if (old == 0) | if (old == 0) | ||||
return (0); | return (false); | ||||
if (atomic_fcmpset_int(count, &old, old + 1)) | if (atomic_fcmpset_int(count, &old, old + 1)) | ||||
return (1); | return (true); | ||||
} | } | ||||
} | } | ||||
static __inline __result_use_check int | static __inline __result_use_check bool | ||||
refcount_release_if_not_last(volatile u_int *count) | refcount_release_if_not_last(volatile u_int *count) | ||||
{ | { | ||||
u_int old; | u_int old; | ||||
old = *count; | old = *count; | ||||
for (;;) { | for (;;) { | ||||
KASSERT(old > 0, ("refcount %p is zero", count)); | KASSERT(old > 0, ("refcount %p is zero", count)); | ||||
if (old == 1) | if (old == 1) | ||||
return (0); | return (false); | ||||
if (atomic_fcmpset_int(count, &old, old - 1)) | if (atomic_fcmpset_int(count, &old, old - 1)) | ||||
return (1); | return (true); | ||||
} | } | ||||
} | } | ||||
#endif /* ! __SYS_REFCOUNT_H__ */ | #endif /* ! __SYS_REFCOUNT_H__ */ |