# KRN-THR requirements ::::{req} One RUNNING thread per processor :id: KRN-THR-001 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md At most one thread shall be in the RUNNING state on each online logical processor. **Rationale:** Definition of the scheduler's invariant. **Status:** Accepted 2026-10-07 **Verification:** Analysis: model invariant (`current` per CPU); Test: SMP conformance `sched/one_running_per_cpu`. **Trace:** SPEC-008 §1; 03 §1.1; v0.1 §3.3 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} READY is eligible :id: KRN-THR-002 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md A READY thread shall be eligible for scheduling. **Rationale:** State definition. **Status:** Accepted 2026-10-07 **Verification:** Analysis: model invariant 5 of SPEC-004 §5.4. **Trace:** SPEC-008 §1 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} BLOCKED is ineligible :id: KRN-THR-003 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md A BLOCKED thread shall not be eligible for scheduling. **Rationale:** State definition. **Status:** Accepted 2026-10-07 **Verification:** Analysis: model invariant 5. **Trace:** SPEC-008 §1 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Independent context and stack :id: KRN-THR-004 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Each normal thread shall possess an independent execution context and stack. **Rationale:** Preemptive multithreading. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/stacks_independent` (fill pattern of one thread untouched by another). **Trace:** SPEC-008 §4, §10 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Entry return terminates :id: KRN-THR-005 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Returning from a thread entry function shall cause controlled thread termination through the kernel. **Rationale:** No fall-off-the-end crash. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/entry_return_exits_with_zero`. **Trace:** SPEC-008 §4, §5 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Execution and object lifetimes are independent :id: KRN-THR-006 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Thread execution lifetime and thread-object lifetime shall be independent. **Rationale:** The exit code and the storage outlive execution; the object can exist before start. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/join_after_exit_returns_code`, `thr/init_without_start_then_destroy`. **Trace:** SPEC-008 §1, §5, §6, §8 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Static threads :id: KRN-THR-007 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md The kernel shall support statically allocated threads without requiring a dynamic allocator. **Rationale:** KRN-MEM-001; the tiny profile. **Status:** Accepted 2026-10-07 **Verification:** Analysis: `emb_thread_init` allocates nothing; `EMB_THREAD_DEFINE` is fully static. **Trace:** SPEC-008 §2, §4 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Stable identity :id: KRN-THR-008 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Thread identity shall remain stable for the lifetime of the thread object. **Rationale:** Handles and debugger views. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/index_stable_across_states`. **Trace:** SPEC-008 §3, §8 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Start, suspend, resume are wait reasons :id: KRN-THR-009 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Thread start, suspend, and resume shall be expressed through the common wait mechanism as wait reasons, not as additional scheduler states. **Rationale:** One protocol (SPEC-004). **Status:** Accepted 2026-10-07 **Verification:** Analysis: `emb_thread_start` is a wake with reason START; suspend is the overlay. **Trace:** SPEC-008 §4, §7; SPEC-004 §6.5 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Suspend keeps the wait :id: KRN-THR-010 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md :links: KRN-WAIT-014 A suspended thread shall retain any pending object wait and its deadline; resume shall re-enter that wait without losing the thread's wait-queue position relative to later waiters. **Rationale:** Removes the classic suspend-while-waiting ambiguity. **Status:** Accepted 2026-10-07 **Verification:** Test: `wait/suspend_while_waiting`; model scenario `suspend_while_waiting`. **Trace:** SPEC-008 §7; KRN-WAIT-014 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Cooperative cancellation :id: KRN-THR-011 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md :links: KRN-WAIT-015 Thread cancellation shall be cooperative: a cancel request is delivered as a wake result at the next blocking call or explicit cancellation point; threads are never asynchronously killed. **Rationale:** Asynchronous kills leave locks and buffers in undefined states. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/cancel_*`; model scenarios `cancel_*`. **Trace:** SPEC-008 §5, §7; KRN-WAIT-015 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Join and detach :id: KRN-THR-012 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Join shall be supported for joinable threads; a detached thread's object storage becomes reusable immediately on termination according to its storage policy. **Rationale:** POSIX-shaped lifetime control without an allocator. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/join_*`, `thr/detach_*`; model scenarios `join_*`. **Trace:** SPEC-008 §6 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} TLS slots :id: KRN-THR-013 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Thread-local storage slots shall be available as a compile-time option with a fixed per-thread slot count. **Rationale:** Per-thread state for libraries without compiler TLS. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/tls_slots`. **Trace:** SPEC-008 §9 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} No compiler TLS :id: KRN-THR-014 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md The kernel, ports, and drivers shall not use compiler thread-local storage (`_Thread_local`, `__thread`); EmbCC compiles it to one shared instance on embedded targets (09 §3). Kernel TLS slots are the only per-thread storage mechanism. **Rationale:** Toolchain constraint. **Status:** Accepted 2026-10-07 **Verification:** Analysis: CI grep for `_Thread_local` and `__thread` in kernel, arch, drivers. **Trace:** SPEC-008 §9; 09 §3 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Lifecycle states and reusability :id: KRN-THR-015 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md A thread object shall pass through `INACTIVE` (initialized, not started), the scheduler states, and `TERMINATED`; its storage shall become reusable only when it is `INACTIVE`, or `TERMINATED` and either detached or joined, and the switch-out of its last execution has completed. **Rationale:** A defined reuse point instead of idle-task reclamation (R-001 §1, FreeRTOS) or a spin on in-flight timeouts (Zephyr). **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/reuse_after_join`, `thr/reuse_detached`; SMP test `thr/destroy_waits_switch_out`. **Trace:** SPEC-008 §5, §8 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Start semantics :id: KRN-THR-016 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md `start` shall be ISR-safe, legal before kernel start, shall make an `INACTIVE` thread READY behind its peers, and shall return `EMB_ESTATE` for any other state; statically defined threads shall autostart at kernel start unless marked otherwise. **Rationale:** One way to begin execution; no implicit start at init. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/start_before_kernel_start`, `thr/start_twice_estate`, `thr/define_autostart`. **Trace:** SPEC-008 §4 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Exit path :id: KRN-THR-017 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Termination shall release owned mutexes per `CONFIG_EMB_MUTEX_OWNER_DEATH`, finalize statistics, store the exit code, wake the joiner with the code handed over, discard the thread's timeout, notification bits, TLS slots and bindings, set `TERMINATED`, and switch away, in that order; a pending cancel request shall not be delivered during the exit path. **Rationale:** Deterministic teardown order that other specifications can rely on. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/exit_releases_mutex`, `thr/exit_wakes_joiner`; trace check of the event order. **Trace:** SPEC-008 §5 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Single joiner, exit-code hand-off :id: KRN-THR-018 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Exactly one thread may join a given thread (`EMB_EBUSY` for a second); the exit code shall be delivered by hand-off; joining oneself shall be `EMB_EDEADLK`, joining a detached thread `EMB_EINVAL`, joining a restarted thread's old generation `EMB_ESTALE`; join of a `TERMINATED` thread shall return at once. **Rationale:** One-slot join is O(1) and unambiguous. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/join_*`; model scenarios `join_before_exit`, `join_after_exit`, `join_timeout`, `join_second_ebusy`. **Trace:** SPEC-008 §6 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Detach :id: KRN-THR-019 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md `detach` shall make a joinable thread detached, shall make an already terminated thread reusable at once, and shall be refused with `EMB_EBUSY` while a joiner is blocked. **Rationale:** Lifetime control for fire-and-forget threads. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/detach_*`. **Trace:** SPEC-008 §6 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Suspend and resume are idempotent and overlaid :id: KRN-THR-020 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md `suspend` and `resume` shall be idempotent, shall implement the overlay of SPEC-004 §6.5, and shall be refused with `EMB_EPERM` on kernel threads. **Rationale:** Counting suspends are a classic source of stuck threads. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/suspend_twice_resume_once`, `misuse/suspend_idle`. **Trace:** SPEC-008 §7, §11 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Cancellation delivery and disable count :id: KRN-THR-021 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md A cancel request shall wake a blocked cancelable wait at once when cancellation is enabled, otherwise be delivered at the next cancellation point; delivery shall clear the request; a per-thread disable count (bounded at 255) shall defer delivery while nonzero; `cancel_point()` shall be a cancellation point. **Rationale:** Threads need regions where cancellation cannot interrupt a protocol. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/cancel_disabled_deferred`, `thr/cancel_point`; model scenarios `cancel_*`. **Trace:** SPEC-008 §7 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Priority range and direction :id: KRN-THR-022 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Larger numeric values shall mean higher priority; `0` shall be the idle level and not assignable to application threads; application priorities shall be `1 .. CONFIG_EMB_PRIORITY_COUNT - 1`; `get_priority` shall return the base and `get_effective_priority` the effective priority. **Rationale:** v0.1 §3.5; consistency with the interrupt numbering of SPEC-002 §8. **Status:** Accepted 2026-10-07 **Verification:** Test: `misuse/thread_priority_zero`; Analysis: KRN-SCH-036 range. **Trace:** SPEC-008 §1, §3; SPEC-005 §2.3 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Stacks :id: KRN-THR-023 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Thread stacks shall be caller-provided, aligned to `EMB_STACK_ALIGN`, at least `EMB_THREAD_STACK_MIN` for the architecture; `EMB_THREAD_STACK` shall declare one; checked and statistics builds shall fill stacks at init and report the high-water mark; overflow shall be checked at every switch-out when `CONFIG_EMB_STACK_CHECK` is set and by hardware limits or MPU guards where available. **Rationale:** KRN-MEM-009, 010, 011 applied to threads. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/stack_high_water`, `thr/stack_overflow_detected` (fault injection). **Trace:** SPEC-008 §10; KRN-MEM-009 to 011 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Destroy :id: KRN-THR-024 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md `destroy` shall require `INACTIVE`, or `TERMINATED` and reusable; it shall remove the thread from the all-threads list and bump the handle generation; anything else shall be misuse. **Rationale:** KRN-OBJ-001 to 003 for threads. **Status:** Accepted 2026-10-07 **Verification:** Test: `misuse/thread_destroy_running`, `thr/destroy_after_join`. **Trace:** SPEC-008 §8 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Introspection :id: KRN-THR-025 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md The kernel shall report a thread's state and wait reason, name, stable index, base and effective priority, and (optionally) stack usage, and shall offer `emb_thread_foreach` when `CONFIG_EMB_THREAD_LIST` is set. **Rationale:** Tooling and statistics. **Status:** Accepted 2026-10-07 **Verification:** Test: `thr/state_queries`; debug descriptor consumer test. **Trace:** SPEC-008 §3, §13 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Kernel threads :id: KRN-THR-026 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md The idle thread and work queue threads shall be kernel threads: not suspendable, cancelable, joinable, or re-prioritizable by the application (`EMB_EPERM`), invisible to `foreach` unless asked for. **Rationale:** The kernel's own progress must not depend on application calls. **Status:** Accepted 2026-10-07 **Verification:** Test: `misuse/kernel_thread_ops`. **Trace:** SPEC-008 §11 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Isolated profile rules :id: KRN-THR-027 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md :links: KRN-CAP-002;KRN-PART-001 A thread shall belong to one partition; an unprivileged partition shall create threads only in itself, from storage in its own region, before freeze; cross-partition thread operations shall require the corresponding right on a thread capability. **Rationale:** KRN-PART-001, ADR-033, SPEC-009. **Status:** Accepted 2026-10-07 **Verification:** Isolated-profile tests `part/thread_create_*`, `part/thread_op_without_right`. **Trace:** SPEC-008 §4; KRN-PART-001, 007; KRN-CAP-002 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Trace and statistics :id: KRN-THR-028 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md Init, start, exit with code, join, suspend, resume, cancel, priority change, and destroy shall be trace events; CPU time, switch count, blocked time, and stack high-water shall be optional per-thread statistics. **Rationale:** 04 §7.5. **Status:** Accepted 2026-10-07 **Verification:** Test: trace decoder; statistics API test. **Trace:** SPEC-008 §13 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Tiny profile :id: KRN-THR-029 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md With the table scheduler a thread's slot shall be its unique priority, up to 16 threads including idle; `start`, `suspend`, `resume`, and `join` shall be bit operations; TLS and stack statistics shall default off; destroy shall be allowed only before freeze. **Rationale:** ADR-036; targets T1 and T2. **Status:** Accepted 2026-10-07 **Verification:** Footprint test of the tiny reference configuration; `thr/` conformance group on it. **Trace:** SPEC-008 §14 [Normative source](../../requirements/KRN-THR.md). :::: ::::{req} Model coverage :id: KRN-THR-030 :status: Accepted :evidence: not evaluated :design_source: requirements/KRN-THR.md :links: KRN-WAIT-007 The reference model shall include start of inactive threads, join with exit-code hand-off and the one-joiner rule, explicit exit codes, and shall be explored over join before and after exit, join with timeout, cancellation of a joiner, start by another thread, and exit while owning a mutex. **Rationale:** Lifecycle races are protocol races. **Status:** Accepted 2026-10-07 **Verification:** Analysis: `tools/model/tests` scenarios `JOIN`. **Trace:** SPEC-008 §15; KRN-WAIT-007 [Normative source](../../requirements/KRN-THR.md). ::::