Module Name: src Committed By: pgoyette Date: Fri May 19 00:01:34 UTC 2017
Modified Files: src/distrib/sets/lists/comp: mi src/doc: CHANGES src/sys/kern: files.kern src/sys/sys: Makefile param.h Added Files: src/share/man/man9: localcount.9 src/sys/kern: subr_localcount.c src/sys/sys: localcount.h Log Message: Introduce new localcount(9) reference-count primitives. To generate a diff of this commit: cvs rdiff -u -r1.2132 -r1.2133 src/distrib/sets/lists/comp/mi cvs rdiff -u -r1.2282 -r1.2283 src/doc/CHANGES cvs rdiff -u -r0 -r1.2 src/share/man/man9/localcount.9 cvs rdiff -u -r1.14 -r1.15 src/sys/kern/files.kern cvs rdiff -u -r0 -r1.2 src/sys/kern/subr_localcount.c cvs rdiff -u -r1.160 -r1.161 src/sys/sys/Makefile cvs rdiff -u -r0 -r1.2 src/sys/sys/localcount.h cvs rdiff -u -r1.538 -r1.539 src/sys/sys/param.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/comp/mi diff -u src/distrib/sets/lists/comp/mi:1.2132 src/distrib/sets/lists/comp/mi:1.2133 --- src/distrib/sets/lists/comp/mi:1.2132 Tue May 9 22:43:09 2017 +++ src/distrib/sets/lists/comp/mi Fri May 19 00:01:33 2017 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.2132 2017/05/09 22:43:09 kamil Exp $ +# $NetBSD: mi,v 1.2133 2017/05/19 00:01:33 pgoyette Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. ./etc/mtree/set.comp comp-sys-root @@ -2873,6 +2873,7 @@ ./usr/include/sys/ksyms.h comp-c-include ./usr/include/sys/ktrace.h comp-c-include ./usr/include/sys/lkm.h comp-obsolete obsolete +./usr/include/sys/localcount.h comp-c-include ./usr/include/sys/localedef.h comp-c-include ./usr/include/sys/lock.h comp-c-include ./usr/include/sys/lockf.h comp-c-include @@ -10745,6 +10746,7 @@ ./usr/share/man/cat9/le64enc.0 comp-sys-catman .cat ./usr/share/man/cat9/le64toh.0 comp-sys-catman .cat ./usr/share/man/cat9/linedisc.0 comp-sys-catman .cat +./usr/share/man/cat9/localcount.0 comp-sys-catman .cat ./usr/share/man/cat9/lock.0 comp-sys-catman .cat ./usr/share/man/cat9/locking.0 comp-sys-catman .cat ./usr/share/man/cat9/lockinit.0 comp-sys-catman .cat @@ -18192,6 +18194,7 @@ ./usr/share/man/html9/le64enc.html comp-sys-htmlman html ./usr/share/man/html9/le64toh.html comp-sys-htmlman html ./usr/share/man/html9/linedisc.html comp-sys-htmlman html +./usr/share/man/html9/localcount.html comp-sys-htmlman html ./usr/share/man/html9/lock.html comp-sys-htmlman html ./usr/share/man/html9/locking.html comp-sys-htmlman html ./usr/share/man/html9/lockinit.html comp-sys-htmlman html @@ -25793,6 +25796,7 @@ ./usr/share/man/man9/le64enc.9 comp-sys-man .man ./usr/share/man/man9/le64toh.9 comp-sys-man .man ./usr/share/man/man9/linedisc.9 comp-sys-man .man +./usr/share/man/man9/localcount.9 comp-sys-man .man ./usr/share/man/man9/lock.9 comp-sys-man .man ./usr/share/man/man9/locking.9 comp-sys-man .man ./usr/share/man/man9/lockinit.9 comp-sys-man .man Index: src/doc/CHANGES diff -u src/doc/CHANGES:1.2282 src/doc/CHANGES:1.2283 --- src/doc/CHANGES:1.2282 Tue May 16 23:00:42 2017 +++ src/doc/CHANGES Fri May 19 00:01:33 2017 @@ -1,4 +1,4 @@ -# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.2282 $> +# LIST OF CHANGES FROM LAST RELEASE: <$Revision: 1.2283 $> # # # [Note: This file does not mention every change made to the NetBSD source tree. @@ -513,3 +513,4 @@ Changes from NetBSD 7.0 to NetBSD 8.0: openpam(3): update to 20170430 (resedacea) [christos 20170506] dhcpcd: Import dhcpcd 7.0.0-rc1 [roy 20170510] vioscsi(4): Stability fixes [jdolecek 20170515] + localcount(9): Add localcount ref-count primitives [pgoyette 20170519] Index: src/sys/kern/files.kern diff -u src/sys/kern/files.kern:1.14 src/sys/kern/files.kern:1.15 --- src/sys/kern/files.kern:1.14 Wed Apr 12 20:05:54 2017 +++ src/sys/kern/files.kern Fri May 19 00:01:33 2017 @@ -1,4 +1,4 @@ -# $NetBSD: files.kern,v 1.14 2017/04/12 20:05:54 christos Exp $ +# $NetBSD: files.kern,v 1.15 2017/05/19 00:01:33 pgoyette Exp $ # # kernel sources @@ -121,6 +121,7 @@ defparam opt_kmem.h KMEM_GUARD_DEPTH file kern/subr_kmem.c kern file kern/subr_kobj.c kern file kern/subr_kobj_vfs.c kern +file kern/subr_localcount.c kern file kern/subr_lockdebug.c kern file kern/subr_log.c kern file kern/subr_lwp_specificdata.c kern Index: src/sys/sys/Makefile diff -u src/sys/sys/Makefile:1.160 src/sys/sys/Makefile:1.161 --- src/sys/sys/Makefile:1.160 Fri Dec 16 22:10:12 2016 +++ src/sys/sys/Makefile Fri May 19 00:01:34 2017 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.160 2016/12/16 22:10:12 christos Exp $ +# $NetBSD: Makefile,v 1.161 2017/05/19 00:01:34 pgoyette Exp $ .include <bsd.own.mk> @@ -25,7 +25,7 @@ INCS= acct.h agpio.h aio.h ansi.h aout_m ioctl_compat.h iostat.h ipc.h \ joystick.h \ kcore.h kcpuset.h kgdb.h kmem.h ksem.h ksyms.h ktrace.h \ - localedef.h lock.h lockf.h lua.h lwp.h lwpctl.h \ + localcount.h localedef.h lock.h lockf.h lua.h lwp.h lwpctl.h \ malloc.h mallocvar.h mbuf.h md4.h md5.h midiio.h \ mman.h module.h mount.h mqueue.h msg.h msgbuf.h mtio.h mutex.h \ namei.h null.h \ Index: src/sys/sys/param.h diff -u src/sys/sys/param.h:1.538 src/sys/sys/param.h:1.539 --- src/sys/sys/param.h:1.538 Thu Apr 27 19:18:50 2017 +++ src/sys/sys/param.h Fri May 19 00:01:34 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: param.h,v 1.538 2017/04/27 19:18:50 riastradh Exp $ */ +/* $NetBSD: param.h,v 1.539 2017/05/19 00:01:34 pgoyette Exp $ */ /*- * Copyright (c) 1982, 1986, 1989, 1993 @@ -67,7 +67,7 @@ * 2.99.9 (299000900) */ -#define __NetBSD_Version__ 799007100 /* NetBSD 7.99.71 */ +#define __NetBSD_Version__ 799007200 /* NetBSD 7.99.72 */ #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \ (m) * 1000000) + (p) * 100) <= __NetBSD_Version__) Added files: Index: src/share/man/man9/localcount.9 diff -u /dev/null src/share/man/man9/localcount.9:1.2 --- /dev/null Fri May 19 00:01:34 2017 +++ src/share/man/man9/localcount.9 Fri May 19 00:01:33 2017 @@ -0,0 +1,192 @@ +.\" $NetBSD: localcount.9,v 1.2 2017/05/19 00:01:33 pgoyette Exp $ +.\" +.\" Copyright (c) 2016 +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to The NetBSD Foundation +.\" by Taylor R. Campbell. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd December 8, 2016 +.Dt LOCALCOUNT 9 +.Os +.Sh NAME +.Nm localcount , +.Nm localcount_init , +.Nm localcount_fini , +.Nm localcount_acquire , +.Nm localcount_release , +.Nm localcount_drain +.Sh SYNOPSIS +.In sys/localcount.h +.Ft int +.Fn localcount_init "struct localcount *lc" +.Ft void +.Fn localcount_fini "struct localcount *lc" +.Ft void +.Fn localcount_acquire "struct localcount *lc" +.Ft void +.Fn localcount_release "struct localcount *lc" "struct kcondvar *cv" \ +"struct kmutex *mtx" +.Ft void +.Fn localcount_drain "struct localcount *lc" "struct kcondvar *cv" \ +"struct kmutex *mtx" +.Sh DESCRIPTION +Localcounts are used in the kernel to implement a medium-weight reference +counting mechanism. +During normal operations, localcounts do not need the interprocessor +synchronization associated with +.Xr atomic_ops 3 +atomic memory operations, and (unlike +.Xr psref 9 ) +.Nm +references can be held across sleeps and can migrate between CPUs. +Draining a +.Nm +requires more expensive interprocessor synchronization than +.Xr atomic_ops 3 +(similar to +.Xr psref 9 ) . +And +.Nm +references require eight bytes of memory per object per-CPU, significantly +more than +.Xr atomic_ops 3 +and almost always more than +.Xr psref 9 . +.Pp +As a rough heuristic, +.Nm +should be used for classes of objects of which there are perhaps a few dozen +instances (such as +.Xr autoconf 9 +devices) but not thousands of instances (such as +network flows) and on which there may be a mixture of long-term I/O waits, +such as xyzread for a device xyz(4), and short-term fast operations, such as +.Dv xyzioctl(IOC_READ_A_CPU_REG) . +.Sh FUNCTIONS +.Bl -tag -width abcd +.It Fn localcount_init "lc" +.Pp +Dynamically initialize localcount +.Ar lc +for use. +.Pp +No other operations can be performed on a localcount until it has been +initialized. +.It Fn localcount_fini "lc" +.Pp +Release resources used by localcount +.Ar lc . +The caller must have already called +.Fn localcount_drain . +The localcount may not be used after +.Fn localcount_fini +has been called until it has been re-initialized by +.Fn localcount_init . +.It Fn localcount_acquire "lc" +.Pp +Acquire a reference to the localcount +.Ar lc . +.It Fn localcount_release "lc" "cv" "mtx" +.Pp +Release a reference to the localcount +.Ar lc . +If the localcount is currently being drained, the mutex +.Ar mtx +will be used to synchronize updates to the global reference count (i.e. +the total across all CPUs). +If the reference count goes to zero, +.Fn localcount_release +will broadcast availability of the condvar +.Ar cv . +.It Fn localcount_drain "lc" "cv" "mtx" +.Pp +Wait for all references to the localcount +.Ar lc +to be released. +The caller must hold the mutex +.Ar mtx ; +the mutex will be released during inter-CPU cross-calls (see +.Xr xcall 9 ) and while waiting on the condvar +.Ar cv . +The same +.Ar cv +and +.Ar mtx +must be used with +.Fn localcount_release . +.Pp +The caller must guarantee that no new references can be acquired with +localcount_acquire before calling +.Fn localcount_drain . +For example, any object that may be found in a list and acquired must be +removed from the list before calling +.Fn localcount_drain . +Once the localcount object +.Ar lc +is passed to +.Fn localcount_drain , +it must be passed to +.Fn localcount_fini +before any other re-use. +.Sh CODE REFERENCES +The core of the localcount implementation is in +.Pa sys/kern/subr_localcount.c . +.Pp +The header file +.Pa sys/sys/localcount.h +describes the public interface, and interfaces that machine-dependent +code must provide to support localcounts. +.Sh SEE ALSO +.Xr atomic_ops 3 , +.Xr condvar 9 , +.Xr mutex 9 , +and +.Xr psref 9 +.Sh HISTORY +The localcount primitives first appeared in +.Nx 8.0 . +.Sh AUTHORS +.Nm +was designed by +.An -nosplit +.An Taylor R. Campbell , +who also provided a draft implementation. +The implementation was completed, tested, and integrated by +.An Paul Goyette . +.Sh CAVEATS +The +.Nm +facility does not provide any way to examine the reference count without +actually waiting for the count to reach zero. +.Pp +Waiting for a +.Nm +reference count to reach zero is a one-shot operation. +Once the +.Nm +has been waited for, no further operations are allowed until the +.Nm +has been re-initialized. + Index: src/sys/kern/subr_localcount.c diff -u /dev/null src/sys/kern/subr_localcount.c:1.2 --- /dev/null Fri May 19 00:01:35 2017 +++ src/sys/kern/subr_localcount.c Fri May 19 00:01:33 2017 @@ -0,0 +1,255 @@ +/* $NetBSD: subr_localcount.c,v 1.2 2017/05/19 00:01:33 pgoyette Exp $ */ + +/*- + * Copyright (c) 2016 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * CPU-local reference counts + * + * localcount(9) is a reference-counting scheme that involves no + * interprocessor synchronization most of the time, at the cost of + * eight bytes of memory per CPU per object and at the cost of + * expensive interprocessor synchronization to drain references. + * + * localcount(9) references may be held across sleeps, may be + * transferred from CPU to CPU or thread to thread: they behave + * semantically like typical reference counts, with different + * pragmatic performance characteristics. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: subr_localcount.c,v 1.2 2017/05/19 00:01:33 pgoyette Exp $"); + +#include <sys/param.h> +#include <sys/localcount.h> +#include <sys/types.h> +#include <sys/condvar.h> +#include <sys/errno.h> +#include <sys/mutex.h> +#include <sys/percpu.h> +#include <sys/xcall.h> + +/* + * localcount_init(lc) + * + * Initialize a localcount object. Returns 0 on success, error + * code on failure. May fail to allocate memory for percpu(9). + * + * The caller must call localcount_drain and then localcount_fini + * when done with lc. + */ +static void localcount_xc(void *, void *); + +int +localcount_init(struct localcount *lc) +{ + + lc->lc_totalp = NULL; + lc->lc_percpu = percpu_alloc(sizeof(int64_t)); + if (lc->lc_percpu == NULL) + return ENOMEM; + + return 0; +} + +/* + * localcount_drain(lc, cv, interlock) + * + * Wait for all acquired references to lc to drain. Caller must + * hold interlock; localcount_drain releases it during cross-calls + * and waits on cv. The cv and interlock passed here must be the + * same as are passed to localcount_release for this lc. + * + * Caller must guarantee that no new references can be acquired + * with localcount_acquire before calling localcount_drain. For + * example, any object that may be found in a list and acquired + * must be removed from the list before localcount_drain. + * + * The localcount object lc may be used only with localcount_fini + * after this, unless reinitialized after localcount_fini with + * localcount_init. + */ +void +localcount_drain(struct localcount *lc, kcondvar_t *cv, kmutex_t *interlock) +{ + int64_t total = 0; + + KASSERT(mutex_owned(interlock)); + KASSERT(lc->lc_totalp == NULL); + + /* Mark it draining. */ + lc->lc_totalp = &total; + + /* + * Count up all references on all CPUs. + * + * This serves as a global memory barrier: after xc_wait, all + * CPUs will have witnessed the nonnull value of lc->lc_totalp, + * so that it is safe to wait on the cv for them. + */ + mutex_exit(interlock); + xc_wait(xc_broadcast(0, &localcount_xc, lc, interlock)); + mutex_enter(interlock); + + /* Wait for remaining references to drain. */ + while (total != 0) { + /* + * At this point, now that we have added up all + * references on all CPUs, the total had better be + * nonnegative. + */ + KASSERTMSG((0 < total), + "negatively referenced localcount: %p, %"PRId64, + lc, total); + cv_wait(cv, interlock); + } + + /* Paranoia: Cause any further use of lc->lc_totalp to crash. */ + lc->lc_totalp = (void *)(uintptr_t)1; +} + +/* + * localcount_fini(lc) + * + * Finalize a localcount object, releasing any memory allocated + * for it. Caller must have already called localcount_drain. + */ +void +localcount_fini(struct localcount *lc) +{ + + KASSERT(lc->lc_totalp == (void *)(uintptr_t)1); + percpu_free(lc->lc_percpu, sizeof(uint64_t)); +} + +/* + * localcount_xc(cookie0, cookie1) + * + * Accumulate and transfer the per-CPU reference counts to a + * global total, resetting the per-CPU counter to zero. Once + * localcount_drain() has started, we only maintain the total + * count in localcount_release(). + */ +static void +localcount_xc(void *cookie0, void *cookie1) +{ + struct localcount *lc = cookie0; + kmutex_t *interlock = cookie1; + int64_t *localp; + + mutex_enter(interlock); + localp = percpu_getref(lc->lc_percpu); + *lc->lc_totalp += *localp; + *localp -= *localp; /* ie, *localp = 0; */ + percpu_putref(lc->lc_percpu); + mutex_exit(interlock); +} + +static void +localcount_adjust(struct localcount *lc, int delta) +{ + int64_t *localp; + + localp = percpu_getref(lc->lc_percpu); + *localp += delta; + percpu_putref(lc->lc_percpu); +} + +/* + * localcount_acquire(lc) + * + * Acquire a reference to lc. + * + * The reference may be held across sleeps and may be migrated + * from CPU to CPU, or even thread to thread -- it is only + * counted, not associated with a particular concrete owner. + * + * Involves no interprocessor synchronization. May be used in any + * context: while a lock is held, within a pserialize(9) read + * section, in hard interrupt context (provided other users block + * hard interrupts), in soft interrupt context, in thread context, + * &c. + * + * Caller must guarantee that there is no concurrent + * localcount_drain. For example, any object that may be found in + * a list and acquired must be removed from the list before + * localcount_drain. + */ +void +localcount_acquire(struct localcount *lc) +{ + + KASSERT(lc->lc_totalp == NULL); + localcount_adjust(lc, +1); +} + +/* + * localcount_release(lc, cv, interlock) + * + * Release a reference to lc. If there is a concurrent + * localcount_drain and this may be the last reference, notify + * localcount_drain by acquiring interlock, waking cv, and + * releasing interlock. The cv and interlock passed here must be + * the same as are passed to localcount_drain for this lc. + * + * Involves no interprocessor synchronization unless there is a + * concurrent localcount_drain in progress. + */ +void +localcount_release(struct localcount *lc, kcondvar_t *cv, kmutex_t *interlock) +{ + + /* + * Block xcall so that if someone begins draining after we see + * lc->lc_totalp as null, then they won't start cv_wait until + * after they have counted this CPU's contributions. + * + * Otherwise, localcount_drain may notice an extant reference + * from this CPU and cv_wait for it, but having seen + * lc->lc_totalp as null, this CPU will not wake + * localcount_drain. + */ + kpreempt_disable(); + + KDASSERT(mutex_ownable(interlock)); + if (__predict_false(lc->lc_totalp != NULL)) { + /* + * Slow path -- wake localcount_drain in case this is + * the last reference. + */ + mutex_enter(interlock); + if (--*lc->lc_totalp == 0) + cv_broadcast(cv); + mutex_exit(interlock); + goto out; + } + + localcount_adjust(lc, -1); + out: kpreempt_enable(); +} Index: src/sys/sys/localcount.h diff -u /dev/null src/sys/sys/localcount.h:1.2 --- /dev/null Fri May 19 00:01:35 2017 +++ src/sys/sys/localcount.h Fri May 19 00:01:34 2017 @@ -0,0 +1,65 @@ +/* $NetBSD: localcount.h,v 1.2 2017/05/19 00:01:34 pgoyette Exp $ */ + +/*- + * Copyright (c) 2016 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Taylor R. Campbell. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_LOCALCOUNT_H +#define _SYS_LOCALCOUNT_H + +#ifndef _KERNEL +#error <sys/localcount.h> is for kernel consumers only. +#endif + +#include <sys/types.h> + +struct kcondvar; +struct kmutex; +struct percpu; + +struct localcount { + int64_t *lc_totalp; + struct percpu *lc_percpu; /* int64_t */ +}; + +int localcount_init(struct localcount *); +void localcount_drain(struct localcount *, struct kcondvar *, + struct kmutex *); +void localcount_fini(struct localcount *); +void localcount_acquire(struct localcount *); +void localcount_release(struct localcount *, struct kcondvar *, + struct kmutex *); + +#ifdef _MODULE +#define DEVSW_MODULE_INIT \ + .d_localcount = &(struct localcount){NULL, NULL}, +#else +#define DEVSW_MODULE_INIT +#endif + +#endif /* _SYS_LOCALCOUNT_H */