Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Layer 0 Spec — process Family, CPU Affinity (sched_setaffinity)

Technical specification — Version 1.0 (target kernel: Linux 6.12 LTS). Extension of the process family.

Position

This document specifies the CPU affinity primitive of layer 0 — pinning a task to a subset of logical CPUs. Gap identified while specifying layer 1: air-thread::cpu_affinity needs it and no sched_setaffinity/sched_getaffinity wrapper existed.

Placement: process family. Affinity is a property of a task’s scheduling (identified by a Tid); it therefore lives alongside gettid, clone3, waitid, setpgid… in air-sys-syscall::process. The mask reuses CpuSet (already defined in air-sys-types::system in Temps 3a for IORING_REGISTER_IOWQ_AFF) — a shared type, not recreated. (Rejected alternative: the system family — but system covers machine information (uname, sysinfo, entropy), not the scheduling of a specific task.)

Emergence (doc-first method). Like inotify, this gap was revealed by the specification of layer 1 — consuming layer 0 surfaces its holes. No prior spec: this document is produced before the implementation.


Surface

#![allow(unused)]
fn main() {
/// `sched_setaffinity(2)` — sets a task's CPU affinity: it will only be
/// scheduled on the CPUs present in `cpus`. `tid = None` = calling task
/// (kernel sentinel `0` typed as `Option`, ADR-021 conv. 1).
pub fn set_cpu_affinity(tid: Option<Tid>, cpus: &CpuSet) -> Result<(), Errno>;

/// `sched_getaffinity(2)` — reads the current affinity **into** `cpus` (buffer
/// supplied by the caller, zero allocation). `tid = None` = calling task.
pub fn get_cpu_affinity(tid: Option<Tid>, cpus: &mut CpuSet) -> Result<(), Errno>;
}
  • CpuSet reused (air-sys-types::system, CPU_SETSIZE = 1024 bits / 128 bytes, cpu_set_t layout): new/set/clear/contains/count/is_empty/ as_bytes. get_cpu_affinity writes into the mask via a pointer to the &mut CpuSet (#[repr(C)] without padding ⇒ every byte pattern valid) — no new accessor added to the type.
  • None = calling task: translated to pid = 0 (never exposed as a magic integer — ADR-021 conv. 1).
  • EINTR: sched_*affinity are not interruptible; no hidden retry (ADR-021 conv. 2 remains the general rule).

Underlying syscalls (verified against uapi 6.12, per arch)

Syscallx86_64aarch64
sched_setaffinity203122
sched_getaffinity204123

set: the kernel reads len bytes of the mask (asm readonly). get: the kernel writes into the mask (asm without readonly) and returns the number of bytes filled (≥ 0) or -errno. The size passed is size_of::<CpuSet>() (128 bytes) ≥ the kernel size of cpumask — the kernel fills what it has and leaves the rest at zero.

Preconditions / errors

  • set_cpu_affinity:
    • [Errno::EINVAL]: cpus contains no allowed / online CPU.
    • [Errno::ESRCH]: no task bears this tid.
    • [Errno::EPERM]: insufficient privileges (changing the affinity of a task belonging to another user, or a cpuset cgroup constraint).
  • get_cpu_affinity:
    • [Errno::ESRCH]: nonexistent tid.
    • [Errno::EINVAL]: inconsistent mask size — does not occur with a CpuSet of CPU_SETSIZE bits (always ≥ the kernel size).

Tests

  • Round-trip (real): get the current affinity (count ≥ 1), set to a subset (CPU 0, always online), get and verify contains(0) + count == 1, then restore the original affinity.
  • None vs Some(tid): both target the calling task (Some(gettid())).
  • Errors: empty mask → EINVAL; nonexistent tidESRCH.
  • Cross-arch: numbers verified x86_64 + aarch64; tests run on both.
  • Coverage 100 % lines + branches (the real Ok/Err paths cover both arms; affinity_pid None/Some covered); no expected exception.

Core decisions

  1. Affinity in process (scheduling of a task), mask shared from system::CpuSet — no type duplication.
  2. None = calling task (pid = 0 typed), compliant with ADR-021 conv. 1.
  3. Buffer supplied, zero allocation for get (the caller owns the CpuSet).
  4. Primitive unblocking layer 1 (air-thread::cpu_affinity).

Document license: MPL 2.0 Status: Technical specification of CPU affinity (sched_set/getaffinity), extension of the process family (layer 0), target kernel 6.12 LTS.