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