# KRN-IRQ requirements ::::{req} No blocking in interrupt context :id: KRN-IRQ-001 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md Interrupt context shall not perform blocking operations. **Rationale:** An ISR has no thread to block; blocking there corrupts the scheduler's model of who is running. **Status:** Accepted (v0.1) **Verification:** Test: `tests/conformance/misuse/` calls each thread-only function from an ISR in checked and release builds (API-015). **Trace:** v0.1 §3.7; SPEC-002 §3.1; SPEC-001 §5.2 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Interrupt context is distinguishable :id: KRN-IRQ-002 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md Interrupt context shall be distinguishable from thread context. **Rationale:** Every context-class check and every ISR-safe code path depends on it. **Status:** Accepted (v0.1) **Verification:** Test: `emb_context()` returns `EMB_CONTEXT_ISR` inside every handler level and `EMB_CONTEXT_THREAD` outside, on every port. **Trace:** v0.1 §3.7; SPEC-002 §2; SPEC-001 §5.1 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Wakeup from an interrupt permits scheduling before thread resume :id: KRN-IRQ-003 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md An interrupt that makes a higher-priority thread READY shall permit scheduling before returning to thread execution when preemption is enabled. **Rationale:** This is the definition of preemptive scheduling driven by events rather than ticks. **Status:** Accepted (v0.1) **Verification:** Test: ISR wakes a higher-priority thread; that thread runs before the interrupted thread's next instruction (measured by a sequence counter). **Trace:** v0.1 §3.7; SPEC-002 §6; KRN-SCH-020 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} ISR-safe operations are explicit :id: KRN-IRQ-010 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md :links: API-014 ISR-safe kernel operations shall be explicitly identified. **Rationale:** Callers cannot guess; the annotation is the contract. **Status:** Accepted (v0.1) **Verification:** Analysis: every public function has a `@ctx` tag (API-003); the ISR-safe set is the functions tagged `thread isr`. **Trace:** v0.1 §6.6; SPEC-001 §9; API-014 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} ISR-safe operations never block the caller :id: KRN-IRQ-011 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md :links: API-014 An ISR-safe operation shall not require the caller to block. **Rationale:** Follows from KRN-IRQ-001 for the kernel's own implementation paths. **Status:** Accepted (v0.1) **Verification:** Analysis: `@ctx thread isr` functions are `@blocks no`, or `@blocks timeout` with a documented ISR-safe `EMB_NO_WAIT` path. **Trace:** v0.1 §6.6; API-014 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Nesting depth is observable :id: KRN-IRQ-012 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md Nested interrupt depth shall be observable to the kernel when nesting is supported. **Rationale:** The outermost-exit rule, stack sizing, and diagnostics all need the depth. **Status:** Accepted (v0.1) **Verification:** Test: `emb_irq_nesting_depth()` equals the actual depth in a nested-interrupt test on Cortex-M, RISC-V with nesting, and native. **Trace:** v0.1 §6.6; SPEC-002 §7.1 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Reschedule during nested handling stays pending :id: KRN-IRQ-013 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md A reschedule requested during nested interrupt handling shall remain pending until a legal thread-resume boundary. **Rationale:** Switching threads from inside a nested interrupt would leave an interrupted handler's frame on the wrong stack. **Status:** Accepted (v0.1) **Verification:** Test: nested ISR wakes a higher-priority thread; the switch occurs only after the outer handler returns. **Trace:** v0.1 §6.6; SPEC-002 §6.1; KRN-SCH-021 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Bounded kernel masking :id: KRN-IRQ-014 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md Interrupt masking used by kernel internals shall have bounded duration. **Rationale:** Kernel masking is the floor of every interrupt latency figure. **Status:** Accepted (v0.1) **Verification:** Demonstration: `CONFIG_EMB_IRQ_LOCK_STATS` under the stress suite on HIL reports the maximum; it is published per release. **Trace:** v0.1 §6.6; SPEC-002 §4.2, §10; KRN-RT-003 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} No controller assumption in the generic kernel :id: KRN-IRQ-015 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md The generic kernel shall not assume a specific interrupt-controller architecture. **Rationale:** NVIC, PLIC, CLIC, AVR's fixed vectors, and the simulator are all targets. **Status:** Accepted (v0.1) **Verification:** Analysis: `kernel/` includes no architecture header and references no controller register (02 §5 dependency check). **Trace:** v0.1 §6.6; SPEC-002 §8 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Documented entry, exit, save, and reschedule behavior :id: KRN-IRQ-016 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md Architecture documentation shall define interrupt-entry, interrupt-exit, context-save, and rescheduling behavior. **Rationale:** A port's correctness is reviewable only against a written description. **Status:** Accepted (v0.1) **Verification:** Inspection: each `docs/ports/.md` has the sections named in 05 §9. **Trace:** v0.1 §6.6; SPEC-002 §13 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Two interrupt classes :id: KRN-IRQ-017 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md The kernel shall distinguish kernel-aware interrupts, which it may mask and whose handlers may call ISR-safe API, from kernel-independent interrupts, which it shall never mask and whose handlers shall call no kernel function. The boundary shall be the configured level `CONFIG_EMB_IRQ_KERNEL_LEVEL`. The kernel-independent class shall be available only on architectures with interrupt priority masking and shall be rejected at configuration time elsewhere. **Rationale:** Zero-latency interrupts are a real-time requirement the kernel can only meet by staying out of their way (v0.1 §6.3). **Status:** Accepted 2026-10-07 **Verification:** Test: with the class enabled on Cortex-M, a kernel-independent interrupt fires inside a kernel critical section and its handler runs within hardware latency; Analysis: Kconfig rejects `CONFIG_EMB_IRQ_ZERO_LATENCY` on Armv6-M, AVR, and native. **Trace:** SPEC-002 §3 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Key-based, nestable critical sections :id: KRN-IRQ-018 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md The kernel shall provide `emb_irq_lock()` returning the previous mask state and `emb_irq_unlock(key)` restoring exactly that state, callable from thread, interrupt, and pre-kernel context, nestable, with unlocks in reverse order of locks. Both shall be O(1), shall never block or yield, and shall act as compiler barriers. **Rationale:** Key-based masking nests for free, works identically from ISRs, and maps to one or two instructions on every architecture (SPEC-002 §4.1). **Status:** Accepted 2026-10-07 **Verification:** Test: nesting test restores the outer state exactly; Analysis: the inline wrappers carry a `"memory"` clobber on all three compilers. **Trace:** SPEC-002 §4.1; KRN-RT-003 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Critical sections are per CPU :id: KRN-IRQ-019 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md `emb_irq_lock()` shall protect against interrupts and preemption on the current CPU only. Data shared across CPUs shall be protected by a spinlock acquired with interrupts masked, which on uniprocessor builds shall compile to the critical section alone. **Rationale:** Masking is a local operation; pretending otherwise is the classic SMP porting bug (KRN-SMP-004). **Status:** Accepted 2026-10-07 **Verification:** Analysis: SMP specification lock-ordering rules; Test: the spinlock reduces to `emb_irq_lock()` on UP (symbol inspection). **Trace:** SPEC-002 §4.3; KRN-SMP-002, KRN-SMP-004 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Measured critical-section budgets :id: KRN-IRQ-020 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md Each architecture port shall declare a cycle budget for the kernel's own critical sections and scheduler locks, and a configuration option shall measure the longest observed durations with the cycle counter. The measured maxima shall be published per reference board with full metadata. **Rationale:** Evidence, not assertion (principle 6, KRN-RT-007). **Status:** Accepted 2026-10-07 **Verification:** Demonstration: benchmark pipeline output per release; Test: checked builds fault when a declared budget is exceeded under the stress suite. **Trace:** SPEC-002 §10 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} No blocking inside a critical section :id: KRN-IRQ-021 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md A blocking call with a nonzero timeout, a thread-only operation, or a scheduler-lock release that would reschedule, made while a critical section opened by the caller is active, shall be misuse: a kernel fault in checked builds and `EMB_EPERM` in release builds. **Rationale:** A critical section that spans a preemption point leaves interrupts masked for an unbounded time in another thread. **Status:** Accepted 2026-10-07 **Verification:** Test: `tests/conformance/misuse/` in both build kinds. **Trace:** SPEC-002 §4.2; SPEC-001 §5.3; KRN-RT-002 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Scheduler lock semantics :id: KRN-IRQ-022 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md `emb_sched_lock()` and `emb_sched_unlock()` shall be thread-only, nestable by depth, shall not mask interrupts, and the unlock that reaches depth zero shall perform any pending reschedule immediately. A scheduler-lock operation from interrupt context shall be misuse. Yield while locked shall keep the reschedule pending and shall not switch. **Rationale:** Restates KRN-SCH-016 to 019 at the API level and fixes the two edge cases v0.1 left open. **Status:** Accepted 2026-10-07 **Verification:** Test: conformance tests for nesting, ISR wakeup while locked, yield while locked, and the ISR misuse case. **Trace:** SPEC-002 §5; KRN-SCH-016, KRN-SCH-017, KRN-SCH-018, KRN-SCH-019 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Enumerated preemption points :id: KRN-IRQ-023 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md :links: KRN-IRQ-013 A thread switch shall occur only at: the outermost exit of a kernel-aware interrupt when a reschedule is pending and the scheduler is not locked; inside a thread-context kernel operation that changes schedulability when the caller is not in a critical section and the scheduler is not locked; and kernel start. A thread switch shall never occur inside a nested interrupt or inside a critical section. **Rationale:** A closed list of preemption points is what makes the kernel's behavior analyzable and the reference model finite (ADR-013). **Status:** Accepted 2026-10-07 **Verification:** Test: differential tests against the reference model's switch oracle on the native port; Analysis: the kernel has one switch call site per architecture path. **Trace:** SPEC-002 §6.1; KRN-SCH-021; KRN-IRQ-013 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Reschedule on outermost exit :id: KRN-IRQ-024 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md When an ISR-safe operation changes the scheduling decision, the kernel shall set the per-CPU reschedule-pending flag and request the architecture's deferred switch; the architecture's outermost interrupt exit shall perform the switch when the flag is set and the scheduler is not locked, and shall clear the flag. **Rationale:** This is the single mechanism by which interrupts drive scheduling (KRN-SCH-020, KRN-IRQ-003). **Status:** Accepted 2026-10-07 **Verification:** Test: ISR wakeup latency test on each port; the switch happens exactly once per outermost exit. **Trace:** SPEC-002 §6.2; KRN-SCH-020 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Portable handler declaration :id: KRN-IRQ-025 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md The kernel shall provide `EMB_ISR(name)` as the only portable declaration of a kernel-aware handler, expanding per architecture to the form that provides the kernel's entry and exit behavior, and `EMB_ISR_RAW(name)` for handlers that call no kernel function. **Rationale:** Cortex-M handlers are plain functions, AVR needs a full-context `naked` vector, RISC-V needs a dispatcher entry; the application should not know (09 §8). **Status:** Accepted 2026-10-07 **Verification:** Test: the same handler source builds and passes the ISR conformance tests on every port. **Trace:** SPEC-002 §6.2, §8.3 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Bounded nesting :id: KRN-IRQ-026 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md Kernel-aware interrupt nesting shall be enabled only where the architecture permits and the configuration selects it. The maximum depth shall be a configuration constant used to size the interrupt stack, and exceeding it shall be a kernel fault in checked builds. **Rationale:** Unbounded nesting is unbounded stack use. **Status:** Accepted 2026-10-07 **Verification:** Test: nesting-depth test on the native port with fault injection; Analysis: Kconfig gating per architecture. **Trace:** SPEC-002 §7.1 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Interrupt stacks :id: KRN-IRQ-027 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md Where the architecture permits, kernel-aware interrupts shall execute on a dedicated per-CPU interrupt stack sized from the maximum nesting depth and the handlers' measured frames. Where it does not (AVR), every thread's stack budget shall include a configured interrupt reserve, and the architecture documentation shall state its size derivation. **Rationale:** Thread stacks must be sized for thread work only wherever the hardware allows (KRN-MEM-011). **Status:** Accepted 2026-10-07 **Verification:** Analysis: `-fstack-usage` sums in the stack report; Test: interrupt-stack overflow detection fires in checked builds under the nesting stress test. **Trace:** SPEC-002 §7.2; KRN-MEM-011 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Generic interrupt priority numbering :id: KRN-IRQ-028 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md Generic interrupt priorities shall use the thread convention (a larger number is more urgent), with level 0 the least urgent kernel-aware level and levels above `CONFIG_EMB_IRQ_KERNEL_LEVEL` kernel-independent. The architecture port shall map generic levels to hardware encodings, and the hardware description shall store generic levels. **Rationale:** One priority direction across threads and interrupts removes a documented source of configuration mistakes, and the mapping belongs in one place per architecture. **Status:** Accepted 2026-10-07 **Verification:** Test: `emb_irq_set_level()` followed by observed preemption order on each port; Analysis: generator emits encoded values from generic input. **Trace:** SPEC-002 §8.1 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Interrupt management API :id: KRN-IRQ-029 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md :links: HW-001 The kernel shall provide O(1), non-blocking `emb_irq_enable`, `emb_irq_disable`, `emb_irq_is_enabled`, `emb_irq_set_level`, `emb_irq_pend`, and `emb_irq_clear_pending`, and, only when `CONFIG_EMB_IRQ_DYNAMIC` is selected, `emb_irq_connect`. By default the vector table shall be generated from the hardware description and static. **Rationale:** A static table costs no RAM and no init code; dynamic connection is an option for the applications that need it. **Status:** Accepted 2026-10-07 **Verification:** Test: API conformance per port; Analysis: no RAM vector table in the tiny profile image. **Trace:** SPEC-002 §8.2; HW-001 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Exceptions route to the fault manager :id: KRN-IRQ-030 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md Synchronous faults shall enter through the architecture fault entry, which shall capture the available context and dispatch to the fault manager, classifying a fault from an unprivileged partition as a partition fault and any other as a kernel fault. System-call traps shall not be treated as faults. The crash record shall be written before any recovery action. **Rationale:** Fault handling that is designed, not improvised (01 §6); isolation requires the partition classification. **Status:** Accepted 2026-10-07 **Verification:** Test: provoked faults of each class on native and Cortex-M (emulated) produce decodable crash records and the right classification. **Trace:** SPEC-002 §9; 03 §10; FLT-001, FLT-002 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Timer interrupt level and bound :id: KRN-IRQ-031 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md :links: KRN-TIM-006 The system timer interrupt shall be a kernel-aware interrupt whose level defaults to the highest kernel-aware level and is configurable, and whose handler shall be bounded to moving expired timeouts to READY, setting the reschedule flag, and programming the next event. **Rationale:** Timeout jitter should depend on critical sections and zero-latency interrupts only, and the handler must not become a place where work accumulates. **Status:** Accepted 2026-10-07 **Verification:** Demonstration: timer jitter benchmark; Analysis: handler `-fstack-usage` and cycle budget. **Trace:** SPEC-002 §11; KRN-TIM-006 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Latency metrics are defined and published :id: KRN-IRQ-032 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md The project shall define interrupt latency, kernel masking latency, ISR overhead, ISR-to-thread latency, and scheduler-lock latency as in SPEC-002 §10.1, shall measure them on every reference board with the benchmark pipeline, and shall publish worst observed values with full metadata. **Rationale:** KRN-RT-004 to 007 require measurability; this fixes what is measured. **Status:** Accepted 2026-10-07 **Verification:** Demonstration: published benchmark data per release. **Trace:** SPEC-002 §10; KRN-RT-004, KRN-RT-005, KRN-RT-006, KRN-RT-007; TEST-006 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} The kernel never unmasks behind a caller :id: KRN-IRQ-033 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md An ISR-safe kernel operation called while the caller holds a critical section shall return with the caller's mask state unchanged; kernel internals shall save and restore mask state with the same key-based primitive and shall never unconditionally enable interrupts. **Rationale:** A kernel that enables interrupts inside a caller's critical section breaks the caller's invariant silently. **Status:** Accepted 2026-10-07 **Verification:** Test: every ISR-safe function called under `emb_irq_lock()`; the key read after the call equals the key before; Analysis: no unconditional enable instruction in `kernel/` or in the ports' kernel paths. **Trace:** SPEC-002 §4.2 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Context query is O(1) and exact :id: KRN-IRQ-034 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md :links: KRN-IRQ-002 `emb_context()` shall be O(1), callable from any context including nested interrupts and pre-kernel, and shall agree with the hardware's notion of exception activity on architectures that expose one. **Rationale:** It is executed on every checked API entry and must be cheap and right. **Status:** Accepted 2026-10-07 **Verification:** Test: context query inside nested interrupts and before kernel start on every port. **Trace:** SPEC-002 §2.1; KRN-IRQ-002 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Checked-build detection :id: KRN-IRQ-035 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md :links: API-015 Checked builds shall detect and raise a kernel fault for: out-of-order `emb_irq_unlock()`, scheduler-lock operations from interrupt context, nesting beyond the configured maximum, interrupt stack overflow, and kernel calls from `EMB_ISR_RAW` handlers on architectures where context can be distinguished. **Rationale:** These bugs are invisible in release builds until they corrupt state. **Status:** Accepted 2026-10-07 **Verification:** Test: `tests/conformance/misuse/irq/` provokes each condition on the native port and on an emulated Cortex-M. **Trace:** SPEC-002 §12; API-015 [Normative source](../../requirements/KRN-IRQ.md). :::: ::::{req} Handoff from kernel-independent interrupts :id: KRN-IRQ-036 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-IRQ.md The architecture port shall provide `emb_arch_irq_pend_soft()`, callable from a kernel-independent handler, that pends a kernel-aware software interrupt whose handler may perform kernel work on behalf of the kernel-independent handler. Documentation shall present this as the only sanctioned path from a kernel-independent handler to the kernel. **Rationale:** Zero-latency handlers need a way to wake threads without touching kernel state. **Status:** Accepted 2026-10-07 **Verification:** Test: on Cortex-M with the class enabled, a kernel-independent handler pends the software interrupt and a thread is woken with measured latency. **Trace:** SPEC-002 §3.2 [Normative source](../../requirements/KRN-IRQ.md). ::::