# K09 — scheduler facade and scoped kernel guards K09 separates a process-wide service from genuinely scoped operations: - `Scheduler` is a non-constructible static facade for start, state, suspend and resume; - `this_task` exposes the current handle, tick count and context yield; - `CriticalSection` pairs `taskENTER_CRITICAL` with `taskEXIT_CRITICAL`; - `SchedulerSuspendGuard` pairs `vTaskSuspendAll` with `xTaskResumeAll`. Both guards are non-copyable and non-movable. Their destructors restore state on three distinct early-return paths. Always-inline methods leave no wrapper symbols or virtual/runtime machinery in the target ELF. ## Measured Hazard3 result ```text critical nesting: 0 -> 1 -> 2 -> 1 -> 0 MIE bit: 1 -> 0 -> 0 -> 0 -> 1 suspend scheduler: state running -> suspended -> running MIE while suspended: 1 (interrupts remain enabled) nested guards: running -> suspended -> suspended -> suspended -> running ``` All three critical paths return with nesting 0 and MIE 1. All three scheduler paths return in `running` state with MIE 1. The current handle seen through `this_task` equals the native worker handle. ## Build and evidence ```sh make check ``` Expected: ```text PASS host: static facade, this_task and balanced guards on all exits PASS ABI: facade/guards inline; no vtable/runtime; mstatus transitions present PASS task01: kernel facade + scoped guards restore all paths ``` ## Debug ```gdb b kernel_facade_debug_checkpoint p g_raw_critical_depth p g_raw_critical_mie p g_guard_critical_after_depth p g_guard_critical_after_mie p g_raw_scheduler_state p g_guard_scheduler_after_state p g_nested_scheduler_state p g_kernel_facade_pass ``` ## Scope boundaries Scheduler suspension prevents context switches but does not disable interrupts. Do not call a potentially blocking API while the scheduler is suspended. `CriticalSection` is a task-context guard, not an ISR mutex. `Scheduler` itself is not RAII because scheduler start has no useful lexical lifetime and normally does not return.