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 */
 

Reply via email to