Page MenuHomeFreeBSD

D27056.diff
No OneTemporary

D27056.diff

Index: head/share/man/man9/refcount.9
===================================================================
--- head/share/man/man9/refcount.9
+++ head/share/man/man9/refcount.9
@@ -32,7 +32,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 23, 2019
+.Dd November 2, 2020
.Dt REFCOUNT 9
.Os
.Sh NAME
@@ -46,6 +46,8 @@
.In sys/refcount.h
.Ft void
.Fn refcount_init "volatile u_int *count" "u_int value"
+.Ft u_int
+.Fn refcount_load "volatile u_int *count"
.Ft void
.Fn refcount_acquire "volatile u_int *count"
.Ft bool
@@ -55,6 +57,8 @@
.Ft bool
.Fn refcount_release "volatile u_int *count"
.Ft bool
+.Fn refcount_release_if_last "volatile u_int *count"
+.Ft bool
.Fn refcount_release_if_not_last "volatile u_int *count"
.Sh DESCRIPTION
The
@@ -75,6 +79,16 @@
It is normally used when creating a reference-counted object.
.Pp
The
+.Fn refcount_load
+function returns a snapshot of the counter value.
+This value may immediately become out-of-date in the absence of external
+synchronization.
+.Fn refcount_load
+should be used instead of relying on the properties of the
+.Vt volatile
+qualifier.
+.Pp
+The
.Fn refcount_acquire
function is used to acquire a new reference.
The caller is responsible for ensuring that it holds a valid reference
@@ -119,16 +133,33 @@
otherwise, it returns false.
.Pp
The
+.Fn refcount_release_if_last
+and
.Fn refcount_release_if_not_last
-is a variant of
+functions are variants of
.Fn refcount_release
-which only drops the reference when it is not the last reference.
-In other words, the function returns
+which only drop the reference when it is or is not the last reference,
+respectively.
+In other words,
+.Fn refcount_release_if_last
+returns
.Dv true
when
.Fa *count
+is equal to one, in which case it is decremented to zero.
+Otherwise,
+.Fa *count
+is not modified and the function returns
+.Dv false .
+Similarly,
+.Fn refcount_release_if_not_last
+returns
+.Dv true
+when
+.Fa *count
is greater than one, in which case
-.Fa *count is decremented.
+.Fa *count
+is decremented.
Otherwise, if
.Fa *count
is equal to one, the reference is not released and the function returns
Index: head/sys/sys/refcount.h
===================================================================
--- head/sys/sys/refcount.h
+++ head/sys/sys/refcount.h
@@ -67,6 +67,12 @@
}
static __inline u_int
+refcount_load(volatile u_int *count)
+{
+ return (atomic_load_int(count));
+}
+
+static __inline u_int
refcount_acquire(volatile u_int *count)
{
u_int old;
@@ -168,32 +174,50 @@
return (refcount_releasen(count, 1));
}
+#define _refcount_release_if_cond(cond, name) \
+static __inline __result_use_check bool \
+_refcount_release_if_##name(volatile u_int *count, u_int n) \
+{ \
+ u_int old; \
+ \
+ KASSERT(n > 0, ("%s: zero increment", __func__)); \
+ old = atomic_load_int(count); \
+ for (;;) { \
+ if (!(cond)) \
+ return (false); \
+ if (__predict_false(REFCOUNT_SATURATED(old))) \
+ return (false); \
+ if (atomic_fcmpset_rel_int(count, &old, old - 1)) \
+ return (true); \
+ } \
+}
+_refcount_release_if_cond(old > n, gt)
+_refcount_release_if_cond(old == n, eq)
+
static __inline __result_use_check bool
refcount_release_if_gt(volatile u_int *count, u_int n)
{
- u_int old;
- KASSERT(n > 0,
- ("refcount_release_if_gt: Use refcount_release for final ref"));
- old = atomic_load_int(count);
- for (;;) {
- if (old <= n)
- return (false);
- if (__predict_false(REFCOUNT_SATURATED(old)))
- return (true);
- /*
- * Paired with acquire fence in refcount_releasen().
- */
- if (atomic_fcmpset_rel_int(count, &old, old - 1))
- return (true);
+ return (_refcount_release_if_gt(count, n));
+}
+
+static __inline __result_use_check bool
+refcount_release_if_last(volatile u_int *count)
+{
+
+ if (_refcount_release_if_eq(count, 1)) {
+ /* See the comment in refcount_releasen(). */
+ atomic_thread_fence_acq();
+ return (true);
}
+ return (false);
}
static __inline __result_use_check bool
refcount_release_if_not_last(volatile u_int *count)
{
- return (refcount_release_if_gt(count, 1));
+ return (_refcount_release_if_gt(count, 1));
}
#endif /* !__SYS_REFCOUNT_H__ */

File Metadata

Mime Type
text/plain
Expires
Tue, Jan 21, 6:02 AM (12 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16001298
Default Alt Text
D27056.diff (4 KB)

Event Timeline