On Tue, Mar 15, 2022 at 09:11:30AM +0000, Visa Hankala wrote:
> This patch adds a function for getting a snapshot of a reference
> counter. This will let code like crcopy() access the value in an
> API-observing way.
Here is a revised version.
Based on input from dlg@, the patch now adds refcnt_shared() for
testing if the object has multiple references. This interface is
possibly more robust than refcnt_read().
The patch still provides refcnt_read() for special (mis)uses.
OK?
Index: share/man/man9/refcnt_init.9
===================================================================
RCS file: src/share/man/man9/refcnt_init.9,v
retrieving revision 1.1
diff -u -p -r1.1 refcnt_init.9
--- share/man/man9/refcnt_init.9 11 Sep 2015 19:13:22 -0000 1.1
+++ share/man/man9/refcnt_init.9 15 Mar 2022 13:43:20 -0000
@@ -23,6 +23,8 @@
.Nm refcnt_rele ,
.Nm refcnt_rele_wake ,
.Nm refcnt_finalize ,
+.Nm refcnt_shared ,
+.Nm refcnt_read ,
.Nm REFCNT_INITIALIZER
.Nd reference count API
.Sh SYNOPSIS
@@ -37,6 +39,10 @@
.Fn "refcnt_rele_wake" "struct refcnt *r"
.Ft void
.Fn "refcnt_finalize" "struct refcnt *r" "const char *wmesg"
+.Ft int
+.Fn "refcnt_shared" "struct refcnt *r"
+.Ft unsigned int
+.Fn "refcnt_read" "struct refcnt *r"
.Fn "REFCNT_INITIALIZER"
.Sh DESCRIPTION
The refcnt API provides simple reference counters that can be used
@@ -68,14 +74,26 @@ There may only be one caller to
per refcnt
.Fa r .
.Pp
+.Fn refcnt_shared
+tests if the object has multiple references.
+.Pp
+.Fn refcnt_read
+returns a snapshot of the counter value.
+Its use is discouraged,
+code should use
+.Fn refcnt_shared
+whenever possible.
+.Pp
.Fn REFCNT_INITIALIZER
initialises a declaration of a refcnt to 1.
.Sh CONTEXT
.Fn refcnt_init ,
.Fn refcnt_take ,
.Fn refcnt_rele ,
+.Fn refcnt_rele_wake ,
+.Fn refcnt_shared
and
-.Fn refcnt_rele_wake
+.Fn refcnt_read
can be called during autoconf, from process context, or from interrupt
context.
.Pp
@@ -85,3 +103,10 @@ can be called from process context.
.Fn refcnt_rele
returns a non-zero value if the last reference has been released,
otherwise 0.
+.Pp
+.Fn refcnt_shared
+returns a non-zero value if the object has multiple references,
+otherwise 0.
+.Pp
+.Fn refcnt_read
+returns a snapshot of the counter value.
Index: sys/kern/kern_synch.c
===================================================================
RCS file: src/sys/kern/kern_synch.c,v
retrieving revision 1.183
diff -u -p -r1.183 kern_synch.c
--- sys/kern/kern_synch.c 10 Mar 2022 15:21:08 -0000 1.183
+++ sys/kern/kern_synch.c 15 Mar 2022 13:43:20 -0000
@@ -852,6 +852,18 @@ refcnt_finalize(struct refcnt *r, const
}
}
+int
+refcnt_shared(struct refcnt *r)
+{
+ return (atomic_load_int(&r->r_refs) > 1);
+}
+
+unsigned int
+refcnt_read(struct refcnt *r)
+{
+ return (atomic_load_int(&r->r_refs));
+}
+
void
cond_init(struct cond *c)
{
Index: sys/sys/refcnt.h
===================================================================
RCS file: src/sys/sys/refcnt.h,v
retrieving revision 1.5
diff -u -p -r1.5 refcnt.h
--- sys/sys/refcnt.h 10 Mar 2022 15:21:08 -0000 1.5
+++ sys/sys/refcnt.h 15 Mar 2022 13:43:20 -0000
@@ -37,6 +37,8 @@ void refcnt_take(struct refcnt *);
int refcnt_rele(struct refcnt *);
void refcnt_rele_wake(struct refcnt *);
void refcnt_finalize(struct refcnt *, const char *);
+int refcnt_shared(struct refcnt *);
+unsigned int refcnt_read(struct refcnt *);
#endif /* _KERNEL */