diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2022-03-16 14:13:02 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2022-03-16 14:13:02 +0000 |
commit | 4defa17785a08f6a628a5a171283148594c5ff0f (patch) | |
tree | f70a173813c596bd32bed13f53b1e6622b7290c2 | |
parent | a854baef1d2ef3a7acb26f7475302c84bc02b5fd (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.9 | 31 | ||||
-rw-r--r-- | sys/kern/kern_synch.c | 14 | ||||
-rw-r--r-- | sys/sys/refcnt.h | 4 |
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 */ |