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.
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 07:52:39 -0000 @@ -23,6 +23,7 @@ .Nm refcnt_rele , .Nm refcnt_rele_wake , .Nm refcnt_finalize , +.Nm refcnt_read , .Nm REFCNT_INITIALIZER .Nd reference count API .Sh SYNOPSIS @@ -37,6 +38,8 @@ .Fn "refcnt_rele_wake" "struct refcnt *r" .Ft void .Fn "refcnt_finalize" "struct refcnt *r" "const char *wmesg" +.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 +71,21 @@ There may only be one caller to per refcnt .Fa r . .Pp +.Fn refcnt_read +returns a snapshot of the counter value. +The value can become stale immediately if other CPUs are able to change +the counter in parallel. +The function does not enforce any memory access order. +.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 , and -.Fn refcnt_rele_wake +.Fn refcnt_read can be called during autoconf, from process context, or from interrupt context. .Pp @@ -85,3 +95,6 @@ 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_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 07:52:39 -0000 @@ -852,6 +852,12 @@ refcnt_finalize(struct refcnt *r, const } } +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 07:52:39 -0000 @@ -37,6 +37,7 @@ void refcnt_take(struct refcnt *); int refcnt_rele(struct refcnt *); void refcnt_rele_wake(struct refcnt *); void refcnt_finalize(struct refcnt *, const char *); +unsigned int refcnt_read(struct refcnt *); #endif /* _KERNEL */