2 .\" Copyright (c) 2017 Robert N. M. Watson
3 .\" All rights reserved.
5 .\" Redistribution and use in source and binary forms, with or without
6 .\" modification, are permitted provided that the following conditions
8 .\" 1. Redistributions of source code must retain the above copyright
9 .\" notice, this list of conditions and the following disclaimer.
10 .\" 2. Redistributions in binary form must reproduce the above copyright
11 .\" notice, this list of conditions and the following disclaimer in the
12 .\" documentation and/or other materials provided with the distribution.
14 .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 .Nd Kernel Dynamic Per-CPU Memory Allocator
36 .Ss Per-CPU Variable Definition and Declaration
37 .Fn DPCPU_DEFINE "type" "name"
38 .Fn DPCPU_DECLARE "type" "name"
39 .Ss Current CPU Accessor Functions
42 .Fn DPCPU_SET "name" "value"
43 .Ss Named CPU Accessor Functions
44 .Fn DPCPU_ID_PTR "cpu" "name"
45 .Fn DPCPU_ID_GET "cpu" "name"
46 .Fn DPCPU_ID_SET "cpu" "name" "value"
49 instantiates one instance of a global variable with each CPU in the system.
50 Dynamically allocated per-CPU variables are defined using
52 which defines a variable of name
56 Arbitrary C types may be used, including structures and arrays.
57 If no initialization is provided, then each per-CPU instance of the variable
58 will be zero-filled (i.e., as though allocated in BSS):
59 .Bd -literal -offset 1234
60 DPCPU_DEFINE(int, foo_int);
63 Values may also be initialized statically with the definition, causing each
64 per-CPU instance to be initialized with the value:
65 .Bd -literal -offset 1234
66 DPCPU_DEFINE(int, foo_int) = 1;
69 Syntactically, the definition may be treated as a variable.
70 For example, a dynamic per-CPU variable may be declared as
72 .Bd -literal -offset 1234
73 static DPCPU_DEFINE(int, foo_int);
77 produces a declaration of the per-CPU variable suitable for use in header
80 The current CPU's variable instance can be accessed via
82 (which returns a pointer to the per-CPU instance),
84 (which retrieves the value of the per-CPU instance),
87 (which sets the value of the per-CPU instance).
89 Instances of variables associated with specific CPUs can be accessed via the
94 accessor functions, which accept an additional CPU ID argument,
97 In addition to the ordinary synchronization concerns associated with global
98 variables, which may imply the use of
101 or other kernel synchronization primitives, it is further the case that
102 thread migration could dynamically change the instance of a variable being
103 accessed by a thread between operations.
104 This requires additional care when reasoning about and protecting per-CPU
107 For example, it may be desirable to protect access using
108 .Xr critical_section 9
109 to prevent both preemption and migration during use.
110 Alternatively, it may be desirable to cache the CPU ID at the start of a
111 sequence of accesses, using suitable synchronization to make non-atomic
112 sequences safe in the presence of migration.
113 .Bd -literal -offset 1234
114 static DPCPU_DEFINE(int, foo_int);
115 static DPCPU_DEFINE(struct mutex, foo_lock);
118 foo_int_increment(void)
122 /* Safe as atomic access. */
123 atomic_add_int(DPCPU_PTR(foo_int), 1);
126 * Protect with a critical section, which prevents preemption
127 * and migration. However, access to instances from remote CPUs
128 * is not safe, as critical sections prevent concurrent access
129 * only from the current CPU.
132 value = DPCPU_GET(foo_int);
134 DPCPU_SET(foo_int, value);
138 * Protect with a per-CPU mutex, tolerating migration, but
139 * potentially accessing the variable from multiple CPUs if
140 * migration occurs after reading curcpu. Remote access to a
141 * per-CPU variable is safe as long as the correct mutex is
145 mtx_lock(DPCPU_ID_PTR(cpu, foo_lock));
146 value = DPCPU_ID_GET(cpu, foo_int);
148 DPCPU_ID_SET(cpu, foo_int);
149 mtx_unlock(DPCPU_ID_PTR(cpu, foo_lock));
154 .Xr critical_enter 9 ,
158 was first introduced by
162 This manual page was written by
163 .An Robert N. M. Watson.