summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2022-03-16 14:13:02 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2022-03-16 14:13:02 +0000
commit4defa17785a08f6a628a5a171283148594c5ff0f (patch)
treef70a173813c596bd32bed13f53b1e6622b7290c2
parenta854baef1d2ef3a7acb26f7475302c84bc02b5fd (diff)
Add refcnt_shared() and refcnt_read()
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@
-rw-r--r--share/man/man9/refcnt_init.931
-rw-r--r--sys/kern/kern_synch.c14
-rw-r--r--sys/sys/refcnt.h4
3 files changed, 44 insertions, 5 deletions
diff --git a/share/man/man9/refcnt_init.9 b/share/man/man9/refcnt_init.9
index 1b19d3b653a..cd19b150e93 100644
--- a/share/man/man9/refcnt_init.9
+++ b/share/man/man9/refcnt_init.9
@@ -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
@@ -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.
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index 27e36501ae9..e877acff824 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -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)
{
diff --git a/sys/sys/refcnt.h b/sys/sys/refcnt.h
index 26423346e51..7f7b4e87d60 100644
--- a/sys/sys/refcnt.h
+++ b/sys/sys/refcnt.h
@@ -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 */