xref: /freebsd-src/share/man/man9/dpcpu.9 (revision fa9896e082a1046ff4fbc75fcba4d18d1f2efc19)
18509f632SRobert Watson.\"-
28509f632SRobert Watson.\" Copyright (c) 2017 Robert N. M. Watson
38509f632SRobert Watson.\" All rights reserved.
48509f632SRobert Watson.\"
58509f632SRobert Watson.\" Redistribution and use in source and binary forms, with or without
68509f632SRobert Watson.\" modification, are permitted provided that the following conditions
78509f632SRobert Watson.\" are met:
88509f632SRobert Watson.\" 1. Redistributions of source code must retain the above copyright
98509f632SRobert Watson.\"    notice, this list of conditions and the following disclaimer.
108509f632SRobert Watson.\" 2. Redistributions in binary form must reproduce the above copyright
118509f632SRobert Watson.\"    notice, this list of conditions and the following disclaimer in the
128509f632SRobert Watson.\"    documentation and/or other materials provided with the distribution.
138509f632SRobert Watson.\"
148509f632SRobert Watson.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
158509f632SRobert Watson.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
168509f632SRobert Watson.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
178509f632SRobert Watson.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
188509f632SRobert Watson.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
198509f632SRobert Watson.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
208509f632SRobert Watson.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
218509f632SRobert Watson.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
228509f632SRobert Watson.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
238509f632SRobert Watson.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
248509f632SRobert Watson.\" SUCH DAMAGE.
258509f632SRobert Watson.\"
26*2bf95012SAndrew Turner.Dd July 5, 2018
278509f632SRobert Watson.Dt DPCPU 9
288509f632SRobert Watson.Os
298509f632SRobert Watson.Sh NAME
308509f632SRobert Watson.Nm dpcpu
318509f632SRobert Watson.Nd Kernel Dynamic Per-CPU Memory Allocator
328509f632SRobert Watson.Sh SYNOPSIS
338509f632SRobert Watson.In sys/pcpu.h
348509f632SRobert Watson.Ss Per-CPU Variable Definition and Declaration
358509f632SRobert Watson.Fn DPCPU_DEFINE "type" "name"
36*2bf95012SAndrew Turner.Fn DPCPU_DEFINE_STATIC "type" "name"
378509f632SRobert Watson.Fn DPCPU_DECLARE "type" "name"
388509f632SRobert Watson.Ss Current CPU Accessor Functions
398509f632SRobert Watson.Fn DPCPU_PTR "name"
408509f632SRobert Watson.Fn DPCPU_GET "name"
418509f632SRobert Watson.Fn DPCPU_SET "name" "value"
428509f632SRobert Watson.Ss Named CPU Accessor Functions
438509f632SRobert Watson.Fn DPCPU_ID_PTR "cpu" "name"
448509f632SRobert Watson.Fn DPCPU_ID_GET "cpu" "name"
458509f632SRobert Watson.Fn DPCPU_ID_SET "cpu" "name" "value"
468509f632SRobert Watson.Sh DESCRIPTION
478509f632SRobert Watson.Nm
488509f632SRobert Watsoninstantiates one instance of a global variable with each CPU in the system.
498509f632SRobert WatsonDynamically allocated per-CPU variables are defined using
508509f632SRobert Watson.Fn DPCPU_DEFINE ,
518509f632SRobert Watsonwhich defines a variable of name
528509f632SRobert Watson.Ar name
538509f632SRobert Watsonand type
548509f632SRobert Watson.Ar type .
558509f632SRobert WatsonArbitrary C types may be used, including structures and arrays.
568509f632SRobert WatsonIf no initialization is provided, then each per-CPU instance of the variable
578509f632SRobert Watsonwill be zero-filled (i.e., as though allocated in BSS):
588509f632SRobert Watson.Bd -literal -offset 1234
592cb46844SRobert WatsonDPCPU_DEFINE(int, foo_int);
608509f632SRobert Watson.Ed
618509f632SRobert Watson.Pp
628509f632SRobert WatsonValues may also be initialized statically with the definition, causing each
638509f632SRobert Watsonper-CPU instance to be initialized with the value:
648509f632SRobert Watson.Bd -literal -offset 1234
652cb46844SRobert WatsonDPCPU_DEFINE(int, foo_int) = 1;
668509f632SRobert Watson.Ed
678509f632SRobert Watson.Pp
68*2bf95012SAndrew TurnerValues that can be defined as
69*2bf95012SAndrew Turner.Dv static
70*2bf95012SAndrew Turnermust use
71*2bf95012SAndrew Turner.Fn DPCPU_DEFINE_STATIC :
728509f632SRobert Watson.Bd -literal -offset 1234
73*2bf95012SAndrew TurnerDPCPU_DEFINE_STATIC(int, foo_int);
748509f632SRobert Watson.Ed
758509f632SRobert Watson.Pp
768509f632SRobert Watson.Fn DPCPU_DECLARE
778509f632SRobert Watsonproduces a declaration of the per-CPU variable suitable for use in header
788509f632SRobert Watsonfiles.
798509f632SRobert Watson.Pp
808509f632SRobert WatsonThe current CPU's variable instance can be accessed via
818509f632SRobert Watson.Nm DPCPU_PTR
828509f632SRobert Watson(which returns a pointer to the per-CPU instance),
838509f632SRobert Watson.Nm DPCPU_GET
848509f632SRobert Watson(which retrieves the value of the per-CPU instance),
858509f632SRobert Watsonand
868509f632SRobert Watson.Nm DPCPU_SET
878509f632SRobert Watson(which sets the value of the per-CPU instance).
888509f632SRobert Watson.Pp
898509f632SRobert WatsonInstances of variables associated with specific CPUs can be accessed via the
908509f632SRobert Watson.Nm DPCPU_ID_PTR ,
918509f632SRobert Watson.Nm DPCPU_ID_GET ,
928509f632SRobert Watsonand
938509f632SRobert Watson.Nm DPGPU_ID_SET
948509f632SRobert Watsonaccessor functions, which accept an additional CPU ID argument,
958509f632SRobert Watson.Ar cpu .
968509f632SRobert Watson.Ss Synchronization
978509f632SRobert WatsonIn addition to the ordinary synchronization concerns associated with global
988509f632SRobert Watsonvariables, which may imply the use of
998509f632SRobert Watson.Xr atomic 9 ,
1008509f632SRobert Watson.Xr mutex 9 ,
1018509f632SRobert Watsonor other kernel synchronization primitives, it is further the case that
1028509f632SRobert Watsonthread migration could dynamically change the instance of a variable being
1038509f632SRobert Watsonaccessed by a thread between operations.
1048509f632SRobert WatsonThis requires additional care when reasoning about and protecting per-CPU
1058509f632SRobert Watsonvariables.
1068509f632SRobert Watson.Pp
1078509f632SRobert WatsonFor example, it may be desirable to protect access using
1088509f632SRobert Watson.Xr critical_section 9
1098509f632SRobert Watsonto prevent both preemption and migration during use.
1108509f632SRobert WatsonAlternatively, it may be desirable to cache the CPU ID at the start of a
1118509f632SRobert Watsonsequence of accesses, using suitable synchronization to make non-atomic
1128509f632SRobert Watsonsequences safe in the presence of migration.
1138509f632SRobert Watson.Bd -literal -offset 1234
114*2bf95012SAndrew TurnerDPCPU_DEFINE_STATIC(int, foo_int);
115*2bf95012SAndrew TurnerDPCPU_DEFINE_STATIC(struct mutex, foo_lock);
1168509f632SRobert Watson
1178509f632SRobert Watsonvoid
1188509f632SRobert Watsonfoo_int_increment(void)
1198509f632SRobert Watson{
1208509f632SRobert Watson    int cpu, value;
1218509f632SRobert Watson
1228509f632SRobert Watson    /* Safe as atomic access. */
1238509f632SRobert Watson    atomic_add_int(DPCPU_PTR(foo_int), 1);
1248509f632SRobert Watson
1258509f632SRobert Watson    /*
1268509f632SRobert Watson     * Protect with a critical section, which prevents preemption
1278509f632SRobert Watson     * and migration.  However, access to instances from remote CPUs
1288509f632SRobert Watson     * is not safe, as critical sections prevent concurrent access
1298509f632SRobert Watson     * only from the current CPU.
1308509f632SRobert Watson     */
1318509f632SRobert Watson    critical_enter();
1328509f632SRobert Watson    value = DPCPU_GET(foo_int);
1338509f632SRobert Watson    value++;
1348509f632SRobert Watson    DPCPU_SET(foo_int, value);
1358509f632SRobert Watson    critical_exit();
1368509f632SRobert Watson
1378509f632SRobert Watson    /*
1388509f632SRobert Watson     * Protect with a per-CPU mutex, tolerating migration, but
1398509f632SRobert Watson     * potentially accessing the variable from multiple CPUs if
1408509f632SRobert Watson     * migration occurs after reading curcpu.  Remote access to a
1418509f632SRobert Watson     * per-CPU variable is safe as long as the correct mutex is
1428509f632SRobert Watson     * acquired.
1438509f632SRobert Watson     */
1448509f632SRobert Watson    cpu = curcpu;
1458509f632SRobert Watson    mtx_lock(DPCPU_ID_PTR(cpu, foo_lock));
1468509f632SRobert Watson    value = DPCPU_ID_GET(cpu, foo_int);
1478509f632SRobert Watson    value++;
1488509f632SRobert Watson    DPCPU_ID_SET(cpu, foo_int);
1498509f632SRobert Watson    mtx_unlock(DPCPU_ID_PTR(cpu, foo_lock));
1508509f632SRobert Watson}
1518509f632SRobert Watson.Ed
1528509f632SRobert Watson.Sh SEE ALSO
1538509f632SRobert Watson.Xr atomic 9 ,
1548509f632SRobert Watson.Xr critical_enter 9 ,
1558509f632SRobert Watson.Xr mutex 9
1568509f632SRobert Watson.Sh HISTORY
1578509f632SRobert Watson.Nm
1588509f632SRobert Watsonwas first introduced by
1598509f632SRobert Watson.An Jeff Roberson
1608509f632SRobert Watsonin
1618509f632SRobert Watson.Fx 8.0 .
1628509f632SRobert WatsonThis manual page was written by
1638509f632SRobert Watson.An Robert N. M. Watson .
164