Date: Sun, 26 Mar 2017 20:15:09 +0000 (UTC) From: Robert Watson <rwatson@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r316003 - head/share/man/man9 Message-ID: <201703262015.v2QKF9k9062425@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: rwatson Date: Sun Mar 26 20:15:08 2017 New Revision: 316003 URL: https://svnweb.freebsd.org/changeset/base/316003 Log: Add a man page for the kernel's dynamic per-CPU memory allocator. MFC after: 3 days Added: head/share/man/man9/dpcpu.9 (contents, props changed) Modified: head/share/man/man9/Makefile Modified: head/share/man/man9/Makefile ============================================================================== --- head/share/man/man9/Makefile Sun Mar 26 19:47:43 2017 (r316002) +++ head/share/man/man9/Makefile Sun Mar 26 20:15:08 2017 (r316003) @@ -116,6 +116,7 @@ MAN= accept_filter.9 \ disk.9 \ dnv.9 \ domain.9 \ + dpcpu.9 \ drbr.9 \ driver.9 \ DRIVER_MODULE.9 \ Added: head/share/man/man9/dpcpu.9 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/share/man/man9/dpcpu.9 Sun Mar 26 20:15:08 2017 (r316003) @@ -0,0 +1,163 @@ +.\"- +.\" Copyright (c) 2017 Robert N. M. Watson +.\" All rights reserved. +.\" +.\" 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 AUTHOR 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 AUTHOR 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. +.\" +.\" $FreeBSD$ +.\" +.Dd March 26, 2017 +.Dt DPCPU 9 +.Os +.Sh NAME +.Nm dpcpu +.Nd Kernel Dynamic Per-CPU Memory Allocator +.Sh SYNOPSIS +.In sys/pcpu.h +.Ss Per-CPU Variable Definition and Declaration +.Fn DPCPU_DEFINE "type" "name" +.Fn DPCPU_DECLARE "type" "name" +.Ss Current CPU Accessor Functions +.Fn DPCPU_PTR "name" +.Fn DPCPU_GET "name" +.Fn DPCPU_SET "name" "value" +.Ss Named CPU Accessor Functions +.Fn DPCPU_ID_PTR "cpu" "name" +.Fn DPCPU_ID_GET "cpu" "name" +.Fn DPCPU_ID_SET "cpu" "name" "value" +.Sh DESCRIPTION +.Nm +instantiates one instance of a global variable with each CPU in the system. +Dynamically allocated per-CPU variables are defined using +.Fn DPCPU_DEFINE , +which defines a variable of name +.Ar name +and type +.Ar type . +Arbitrary C types may be used, including structures and arrays. +If no initialization is provided, then each per-CPU instance of the variable +will be zero-filled (i.e., as though allocated in BSS): +.Bd -literal -offset 1234 +DPCPU_DEFINE(int, fooint); +.Ed +.Pp +Values may also be initialized statically with the definition, causing each +per-CPU instance to be initialized with the value: +.Bd -literal -offset 1234 +DPCPU_DEFINE(int, fooint) = 1; +.Ed +.Pp +Syntactically, the definition may be treated as a variable. +For example, a dynamic per-CPU variable may be declared as +.Dv static : +.Bd -literal -offset 1234 +static DPCPU_DEFINE(int, fooint); +.Ed +.Pp +.Fn DPCPU_DECLARE +produces a declaration of the per-CPU variable suitable for use in header +files. +.Pp +The current CPU's variable instance can be accessed via +.Nm DPCPU_PTR +(which returns a pointer to the per-CPU instance), +.Nm DPCPU_GET +(which retrieves the value of the per-CPU instance), +and +.Nm DPCPU_SET +(which sets the value of the per-CPU instance). +.Pp +Instances of variables associated with specific CPUs can be accessed via the +.Nm DPCPU_ID_PTR , +.Nm DPCPU_ID_GET , +and +.Nm DPGPU_ID_SET +accessor functions, which accept an additional CPU ID argument, +.Ar cpu . +.Ss Synchronization +In addition to the ordinary synchronization concerns associated with global +variables, which may imply the use of +.Xr atomic 9 , +.Xr mutex 9 , +or other kernel synchronization primitives, it is further the case that +thread migration could dynamically change the instance of a variable being +accessed by a thread between operations. +This requires additional care when reasoning about and protecting per-CPU +variables. +.Pp +For example, it may be desirable to protect access using +.Xr critical_section 9 +to prevent both preemption and migration during use. +Alternatively, it may be desirable to cache the CPU ID at the start of a +sequence of accesses, using suitable synchronization to make non-atomic +sequences safe in the presence of migration. +.Bd -literal -offset 1234 +static DPCPU_DEFINE(int, foo_int); +static DPCPU_DEFINE(struct mutex, foo_lock); + +void +foo_int_increment(void) +{ + int cpu, value; + + /* Safe as atomic access. */ + atomic_add_int(DPCPU_PTR(foo_int), 1); + + /* + * Protect with a critical section, which prevents preemption + * and migration. However, access to instances from remote CPUs + * is not safe, as critical sections prevent concurrent access + * only from the current CPU. + */ + critical_enter(); + value = DPCPU_GET(foo_int); + value++; + DPCPU_SET(foo_int, value); + critical_exit(); + + /* + * Protect with a per-CPU mutex, tolerating migration, but + * potentially accessing the variable from multiple CPUs if + * migration occurs after reading curcpu. Remote access to a + * per-CPU variable is safe as long as the correct mutex is + * acquired. + */ + cpu = curcpu; + mtx_lock(DPCPU_ID_PTR(cpu, foo_lock)); + value = DPCPU_ID_GET(cpu, foo_int); + value++; + DPCPU_ID_SET(cpu, foo_int); + mtx_unlock(DPCPU_ID_PTR(cpu, foo_lock)); +} +.Ed +.Sh SEE ALSO +.Xr atomic 9 , +.Xr critical_enter 9 , +.Xr mutex 9 +.Sh HISTORY +.Nm +was first introduced by +.An Jeff Roberson +in +.Fx 8.0 . +This manual page was written by +.An Robert N. M. Watson.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703262015.v2QKF9k9062425>