add thread affinity: pin a task to a core
spawnOn(entry, priority, cpu) routes to a per-core pinned queue, merged with the global queue at O(1) selection. Falls back to unpinned for an offline/invalid core.
This commit is contained in:
@@ -67,6 +67,27 @@ exist, which is what a real-time scheduler needs.
|
||||
- **Round-robin within a level.** When a task is descheduled it goes to the *back*
|
||||
of its level's queue, so equal-priority tasks share the CPU fairly.
|
||||
|
||||
## Affinity: pinning a task to a core
|
||||
|
||||
By default a task runs on **any** core — the ready queue above is global, and any
|
||||
idle core pulls the highest-priority task from it (work-conserving; see
|
||||
[smp.md](smp.md)). A task can instead be **pinned** to one core with
|
||||
`spawnOn(entry, priority, cpu)`, giving it an *affinity*: it will only ever run
|
||||
there, never migrating.
|
||||
|
||||
Mechanically, each core has its **own** pinned queue (same 8-level FIFO + bitmap)
|
||||
alongside the global one. A pinned task is enqueued only into its core's pinned
|
||||
queue; selection compares the top of the global queue and the running core's pinned
|
||||
queue and takes the higher priority (still O(1) — two bit-scans and a compare), with
|
||||
a pinned task winning an equal-priority tie so it can't be starved by global work.
|
||||
Because every queue is mutated under the [big kernel lock](smp.md), one core enqueuing
|
||||
into another core's pinned queue is safe.
|
||||
|
||||
This is the *explicit-affinity* model (no surprise migration mid-deadline), which is
|
||||
the more real-time-predictable direction. `spawnOn` refuses to pin to an offline or
|
||||
out-of-range core — it creates the task unpinned instead, so it still runs somewhere
|
||||
rather than stranding in a queue no core services, and returns whether the pin took.
|
||||
|
||||
## Sleeping and the idle task
|
||||
|
||||
A task can **block** — give up the CPU until an event, rather than busy-wait
|
||||
|
||||
Reference in New Issue
Block a user