KCPUSET(9)
π KCPUSET(9) β dynamic kernel CPU sets, explained by your fave kernel dev bestie
okay so this is a page from the Kernel Developer's Manual, and it's all about kcpuset β the dynamic kernel CPU sets. if you live in kernel land and you've ever needed to keep track of "which CPUs are in my group", this is literally your girl. no cap, it's iconic. β¨
πΈ NAME πΈ
kcpuset, kcpuset_create, kcpuset_destroy, kcpuset_clone, kcpuset_copy, kcpuset_use, kcpuset_unuse, kcpuset_copyin, kcpuset_copyout, kcpuset_zero, kcpuset_fill, kcpuset_set, kcpuset_clear, kcpuset_isset, kcpuset_isotherset, kcpuset_iszero, kcpuset_match, kcpuset_intersect, kcpuset_merge, kcpuset_remove, kcpuset_ffs, kcpuset_ffs_intersecting, kcpuset_countset, kcpuset_atomic_set, kcpuset_atomic_clear, kcpuset_atomicly_intersect, kcpuset_atomicly_merge, kcpuset_atomicly_remove, kcpuset_export_32
...and that whole squad is just: dynamic kernel CPU sets. periodt. π
π SYNOPSIS π
like every good kernel page, we start with an include. here's the whole lineup, bestie, verbatim:
#include <sys/kcpuset.h>
void
kcpuset_create(kcpuset_t **retkcp, bool zero);
void
kcpuset_destroy(kcpuset_t *kcp);
void
kcpuset_clone(kcpuset_t **retkcp, const kcpuset_t *skcp);
void
kcpuset_copy(kcpuset_t *dkcp, const kcpuset_t *skcp);
void
kcpuset_use(kcpuset_t *kcp);
void
kcpuset_unuse(kcpuset_t *kcp, kcpuset_t **lst);
int
kcpuset_copyin(const cpuset_t *ucp, kcpuset_t *kcp, size_t len);
int
kcpuset_copyout(kcpuset_t *kcp, cpuset_t *ucp, size_t len);
void
kcpuset_zero(kcpuset_t *kcp);
void
kcpuset_fill(kcpuset_t *kcp);
void
kcpuset_set(kcpuset_t *kcp, cpuid_t cpu);
void
kcpuset_clear(kcpuset_t *kcp, cpuid_t cpu);
bool
kcpuset_isset(const kcpuset_t * kcp, cpuid_t cpu);
bool
kcpuset_isotherset(const kcpuset_t * kcp, cpuid_t cpu);
bool
kcpuset_iszero(const kcpuset_t *kcp);
bool
kcpuset_intersecting_p(const kcpuset_t *kcp1, const kcpuset_t *kcp2);
bool
kcpuset_match(const kcpuset_t *kcp1, const kcpuset_t *kcp2);
void
kcpuset_intersect(kcpuset_t *kcp1, const kcpuset_t *kcp2);
void
kcpuset_merge(kcpuset_t *kcp1, const kcpuset_t *kcp2);
void
kcpuset_remove(kcpuset_t *kcp1, const kcpuset_t *kcp2);
cpuid_t
kcpuset_ffs(const kcpuset_t *kcp);
cpuid_t
kcpuset_ffs_intersecting(const kcpuset_t *kcp1, const kcpuset_t *kcp2);
int
kcpuset_countset(const kcpuset_t *kcp);
void
kcpuset_atomic_set(kcpuset_t *kcp, cpuid_t cpu);
void
kcpuset_atomic_clear(kcpuset_t *kcp, cpuid_t cpu);
void
kcpuset_atomicly_intersect(kcpuset_t *kcp1, const kcpuset_t *kcp2);
void
kcpuset_atomicly_merge(kcpuset_t *kcp1, const kcpuset_t *kcp2);
void
kcpuset_atomicly_remove(kcpuset_t *kcp1, const kcpuset_t *kcp2);
void
kcpuset_export_u32(const kcpuset_t *kcp, uint32_t *bitfield,
size_t len);
(quick note: the NAME list up there says kcpuset_export_32 and the prototype says kcpuset_export_u32 β the prototypes are the source of truth for what you actually type, so copy the code block, not my bullet list. iykyk π«Ά)
π¦ DESCRIPTION π¦
The machine-independent kcpuset subsystem provides support for dynamic processor sets. Conceptually kcpuset can be understood to be the kernel equivalent of the user space cpuset(3) interface β like, same vibes, but it's the kernel version, which is main character energy tbh. π
β FUNCTIONS β
one bullet per bestie, in the same order as the page, because we do not skip. ever.
kcpuset_create(retkcp, zero)β creates a dynamic CPU set and stores the result toretkcp. if the booleanzerois not false, the allocated set is also initialized to zero. β¨kcpuset_destroy(kcp)β destroys the CPU setkcpand schedules any linked CPU sets for deferred destruction. it's giving "you can go, but your friends have to wait in the lobby" πkcpuset_copy(dkcp, skcp)β copies the CPU set pointed byskcptodkcp.kcpuset_clone(retkcp, skcp)β creates a dynamic CPU set, stores the result toretkcp, and copies the CPU set pointed byskcpto that shiny new CPU set. new set, who dis πkcpuset_use(kcp)β markskcpas being in use by increasing the reference count of the object. note that initiallykcpuset_create()sets the reference count to1.kcpuset_unuse(kcp, lst)β decreases the internal reference count ofkcp, and on the last reference (when the count reaches zero), destroyskcp. iflstis notNULL, then instead of destroying,kcpwill be added to thelstlist for a deferred destruction. π«Άkcpuset_copyin(ucp, kcp, len)β copies thelenbytes long user-space CPU setucpto the kernel CPU setkcp.kcpuset_copyout(kcp, ucp, len)β copies the kernel CPU setkcpto the user-space CPU setucp. it's the reverse of the one above, obviously, we stay consistent πkcpuset_zero(kcp)β clears the setkcp.kcpuset_fill(kcp)β fills the whole setkcpwith ones.kcpuset_set(kcp, cpu)β addscputo the setkcp.kcpuset_clear(kcp, cpu)β removescpufrom the setkcp.kcpuset_isset(kcp, cpu)β returnstrueifcpuis part of the CPU setkcp.kcpuset_isotherset(kcp, cpu)β returnstrueif there any CPUs other thancpuin the CPU setkcp. (yes, that's exactly how the page words it, do not come for me π«Ά)kcpuset_iszero(kcp)β returnstrueif the setkcpis empty.kcpuset_match(kcp1, kcp2)β compares the setskcp1andkcp2, returningtrueif these are identical. twin check π―kcpuset_intersect(kcp1, kcp2)β removes any CPU not set inkcp2from the setkcp1. lowkey savage but necessarykcpuset_merge(kcp1, kcp2)β merges the setkcp2to the setkcp1.kcpuset_remove(kcp1, kcp2)β removes any CPU present inkcp2from the setkcp1.kcpuset_ffs(kcp)β returns the lowest numberedcpupresent inkcpplus1. ifkcpis empty, a value of0is returned. (the page genuinely trails off with the wordkcpright there at the end, bestie β i'm not making that up π)kcpuset_ffs_intersecting(kcp1, kcp2)β returns the lowest numberedcpupresent in the intersection ofkcp1andkcp2plus1. if the intersection is empty, a value of0is returned.kcpuset_countset(kcp)β counts how many CPUs are in the setkcp. math girl summer π₯kcpuset_atomic_set(kcp, cpu)β operates askcpuset_set(), but the operation is atomic; seeatomic_ops(3)for more details.kcpuset_atomic_clear(kcp, cpu)β removescpufrom the CPU setkcpatomically.kcpuset_atomicly_intersect(kcp1, kcp2)β operates askcpuset_intersect(), but the operation is performed using atomic operations; seeatomic_ops(3)for more details.kcpuset_atomicly_merge(kcp1, kcp2)β operates askcpuset_merge(), but the operation is performed using atomic operations; seeatomic_ops(3)for more details.kcpuset_atomicly_remove(kcp1, kcp2)β operates askcpuset_remove(), but the operation is performed using atomic operations; seeatomic_ops(3)for more details.kcpuset_export_u32(kcp, bitfield, len)β exports the CPU setkcpinto a format of32-bitinteger array, specified bybitfieldand length in bytes bylen. an integer is in the host byte-order and represents a bit field. the first bit at index zero represents CPU number0, and so on. π
ok real talk β there's alsokcpuset_intersecting_pup in the SYNOPSIS and#includelist, and this page never gives it its own description paragraph. i'm not gonna invent one for you, bestie. it exists, it's declared, the manual is simply mysterious about it. π
π§ CODE REFERENCES π§
The kcpuset subsystem is implemented within sys/kern/subr_kcpuset.c. that's your file, go read it if you want the lore π
π SEE ALSO π
πΈ HISTORY πΈ
The kcpuset subsystem first appeared in NetBSD 6.0. vintage β¨
and that's the whole page, bestie β 100% of the details, 0% of the boring. you're welcome π π¦
this cute little sign-off is brought to you by the Debian crew, dated July 17, 2013 β that's the source/version and date from the footer, preserved with love π
π¦ where this page comes from
- nixpkgs unstable: netbsd-source 11.0
- Copyright (c) 2011 Jukka Ruohonen <jruohonen.iki.fi>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms