Correct fences for sys/refcount.h.

The acq barrier in refcount_acquire() has no use, constructor must
ensure that the changes are visible before publication by other means.
Last release must sync/with the constructor and all updaters.

This is based on the refcount/shared_ptr analysis I heard at the Hans
Boehm and Herb Sutter talks about C++ atomics.

Reviewed by:	alc, jhb, markj
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
Differential revision:	https://reviews.freebsd.org/D11270
This commit is contained in:
Konstantin Belousov 2017-06-30 16:16:21 +00:00
parent cfb2d93ba6
commit 157d5e6df3

View File

@ -50,7 +50,7 @@ refcount_acquire(volatile u_int *count)
{
KASSERT(*count < UINT_MAX, ("refcount %p overflowed", count));
atomic_add_acq_int(count, 1);
atomic_add_int(count, 1);
}
static __inline int
@ -58,10 +58,20 @@ refcount_release(volatile u_int *count)
{
u_int old;
/* XXX: Should this have a rel membar? */
atomic_thread_fence_rel();
old = atomic_fetchadd_int(count, -1);
KASSERT(old > 0, ("negative refcount %p", count));
return (old == 1);
if (old > 1)
return (0);
/*
* Last reference. Signal the user to call the destructor.
*
* Ensure that the destructor sees all updates. The fence_rel
* at the start of the function synchronized with this fence.
*/
atomic_thread_fence_acq();
return (1);
}
#endif /* ! __SYS_REFCOUNT_H__ */