---
name: "dpcpu"
section: "9"
platform: "freebsd"
package: "base"
version: "16.0-CURRENT-20261027-61c70dc16a79"
release: "FreeBSD 16.0-CURRENT (2026-10-27)"
platforms: ["freebsd"]
url: "https://new.carta.tech/DPCPU_DECLARE"
---

# dpcpu(9)

Kernel Dynamic Per-CPU Memory Allocator

Part of [DPCPU\_DECLARE(9)](/DPCPU_DECLARE/9.md).

## NAME

**dpcpu** – Kernel Dynamic Per-CPU Memory Allocator

## SYNOPSIS

**#include \<sys/pcpu.h\>**

### Per-CPU Variable Definition and Declaration

**DPCPU\_DEFINE**(*type*, *name*);

**DPCPU\_DEFINE\_STATIC**(*type*, *name*);

**DPCPU\_DECLARE**(*type*, *name*);

### Current CPU Accessor Functions

**DPCPU\_PTR**(*name*);

**DPCPU\_GET**(*name*);

**DPCPU\_SET**(*name*, *value*);

### Named CPU Accessor Functions

**DPCPU\_ID\_PTR**(*cpu*, *name*);

**DPCPU\_ID\_GET**(*cpu*, *name*);

**DPCPU\_ID\_SET**(*cpu*, *name*, *value*);

## DESCRIPTION

**dpcpu** instantiates one instance of a global variable with each CPU in the system. Dynamically allocated per-CPU variables are defined using **DPCPU\_DEFINE**(), which defines a variable of name *name* and type *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):

```
DPCPU_DEFINE(int, foo_int);
```

Values may also be initialized statically with the definition, causing each per-CPU instance to be initialized with the value:

```
DPCPU_DEFINE(int, foo_int) = 1;
```

Values that can be defined as static must use **DPCPU\_DEFINE\_STATIC**():

```
DPCPU_DEFINE_STATIC(int, foo_int);
```

**DPCPU\_DECLARE**() produces a declaration of the per-CPU variable suitable for use in header files.

The current CPU's variable instance can be accessed via **DPCPU\_PTR** (which returns a pointer to the per-CPU instance), **DPCPU\_GET** (which retrieves the value of the per-CPU instance), and **DPCPU\_SET** (which sets the value of the per-CPU instance).

Instances of variables associated with specific CPUs can be accessed via the **DPCPU\_ID\_PTR**, **DPCPU\_ID\_GET**, and **DPGPU\_ID\_SET** accessor functions, which accept an additional CPU ID argument, *cpu*.

### Synchronization

In addition to the ordinary synchronization concerns associated with global variables, which may imply the use of [atomic(9)](/atomic/9.md), [mutex(9)](/mutex/9.md), 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.

For example, it may be desirable to protect access using 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.

```
DPCPU_DEFINE_STATIC(int, foo_int);
DPCPU_DEFINE_STATIC(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));
}
```

## SEE ALSO

[atomic(9)](/atomic/9.md), [critical\_enter(9)](/critical_enter/9.md), [mutex(9)](/mutex/9.md)

## HISTORY

**dpcpu** was first introduced by Jeff Roberson in FreeBSD 8.0. This manual page was written by Robert N. M. Watson.
