Add refcnt_shared() and refcnt_read()
authorvisa <visa@openbsd.org>
Wed, 16 Mar 2022 14:13:01 +0000 (14:13 +0000)
committervisa <visa@openbsd.org>
Wed, 16 Mar 2022 14:13:01 +0000 (14:13 +0000)
refcnt_shared() checks whether the object has multiple references.
When refcnt_shared() returns zero, the caller is the only reference
holder.

refcnt_read() returns a snapshot of the counter value.

refcnt_shared() suggested by dlg@.

OK dlg@ mvs@

share/man/man9/refcnt_init.9
sys/kern/kern_synch.c
sys/sys/refcnt.h

index 1b19d3b..cd19b15 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: refcnt_init.9,v 1.1 2015/09/11 19:13:22 dlg Exp $
+.\"    $OpenBSD: refcnt_init.9,v 1.2 2022/03/16 14:13:01 visa Exp $
 .\"
 .\" Copyright (c) 2015 David Gwynne <dlg@openbsd.org>
 .\"
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: September 11 2015 $
+.Dd $Mdocdate: March 16 2022 $
 .Dt REFCNT_INIT 9
 .Os
 .Sh NAME
@@ -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
 .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 27e3650..e877acf 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_synch.c,v 1.183 2022/03/10 15:21:08 bluhm Exp $  */
+/*     $OpenBSD: kern_synch.c,v 1.184 2022/03/16 14:13:01 visa Exp $   */
 /*     $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
 
 /*
@@ -852,6 +852,18 @@ refcnt_finalize(struct refcnt *r, const char *wmesg)
        }
 }
 
+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 2642334..7f7b4e8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: refcnt.h,v 1.5 2022/03/10 15:21:08 bluhm Exp $ */
+/*     $OpenBSD: refcnt.h,v 1.6 2022/03/16 14:13:01 visa Exp $ */
 
 /*
  * Copyright (c) 2015 David Gwynne <dlg@openbsd.org>
@@ -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 */