Core Architecture
Relevant source files
This document describes the core architecture of the kernel_guard
crate, focusing on the trait system, RAII guard implementations, and conditional compilation strategy. The architecture provides a unified interface for creating critical sections while abstracting platform-specific interrupt handling and kernel preemption control.
For information about platform-specific implementations, see Multi-Architecture Support. For integration details and feature configuration, see Integration Guide.
Trait System Foundation
The kernel_guard
crate is built around two core traits that define the contract for critical section management and kernel integration.
BaseGuard Trait
The BaseGuard
trait serves as the fundamental interface that all guard implementations must satisfy. It defines a generic pattern for acquiring and releasing critical section protection.
classDiagram class BaseGuard { <<trait>> +type State: Clone + Copy +acquire() State +release(state: State) } class NoOp { +type State =() +acquire()() +release(()) } class IrqSave { +type State = usize +acquire() usize +release(usize) } class NoPreempt { +type State =() +acquire()() +release(()) } class NoPreemptIrqSave { +type State = usize +acquire() usize +release(usize) } BaseGuard ..|> NoOp BaseGuard ..|> IrqSave BaseGuard ..|> NoPreempt NoPreemptIrqSave ..|> IrqSave
BaseGuard Trait Architecture
The trait uses an associated State
type to capture platform-specific information needed to restore the system state when the critical section ends. For example, interrupt guards store the previous interrupt flag state, while preemption-only guards use unit type since no state needs preservation.
Sources: src/lib.rs(L68 - L78)
KernelGuardIf Interface
The KernelGuardIf
trait provides the integration point between kernel_guard
and the user's kernel implementation. This trait must be implemented by crate users when the preempt
feature is enabled.
flowchart TD subgraph subGraph1["kernel_guard Crate"] KernelGuardIf["KernelGuardIf Traitenable_preempt()disable_preempt()"] CallInterface["crate_interface::call_interface!Runtime dispatch"] NoPreempt["NoPreempt Guard"] NoPreemptIrqSave["NoPreemptIrqSave Guard"] end subgraph subGraph0["User Crate"] UserImpl["User ImplementationKernelGuardIfImpl"] end CallInterface --> KernelGuardIf NoPreempt --> CallInterface NoPreemptIrqSave --> CallInterface UserImpl --> KernelGuardIf
KernelGuardIf Integration Pattern
The interface uses the crate_interface
crate to provide stable ABI boundaries, allowing the kernel implementation to be provided at runtime rather than compile time.
Sources: src/lib.rs(L58 - L66) src/lib.rs(L154) src/lib.rs(L159) src/lib.rs(L168) src/lib.rs(L177)
Guard Implementation Hierarchy
The crate provides four distinct guard types, each designed for specific synchronization requirements in kernel contexts.
Guard Type Matrix
Guard Type | IRQ Control | Preemption Control | State Type | Primary Use Case |
---|---|---|---|---|
NoOp | None | None | () | Testing, userspace |
IrqSave | Disable/Restore | None | usize | IRQ-sensitive operations |
NoPreempt | None | Disable/Enable | () | Scheduler coordination |
NoPreemptIrqSave | Disable/Restore | Disable/Enable | usize | Complete critical sections |
Implementation Strategy
flowchart TD subgraph subGraph2["Platform Integration"] ArchIRQ["arch::local_irq_save_and_disable()"] ArchRestore["arch::local_irq_restore(state)"] KernelIF["KernelGuardIf::disable_preempt()"] KernelRestore["KernelGuardIf::enable_preempt()"] end subgraph subGraph1["State Management"] IRQState["IRQ State (usize)Platform flags"] NoState["No State (())Simple enable/disable"] end subgraph subGraph0["Guard Lifecycle"] Create["Guard::new()"] Acquire["BaseGuard::acquire()"] Critical["Critical SectionUser Code"] Drop["impl Drop"] Release["BaseGuard::release(state)"] end Acquire --> ArchIRQ Acquire --> Critical Acquire --> KernelIF ArchIRQ --> IRQState Create --> Acquire Critical --> Drop Drop --> Release IRQState --> ArchRestore KernelIF --> NoState NoState --> KernelRestore Release --> ArchRestore Release --> KernelRestore
RAII Guard Lifecycle and Platform Integration
Sources: src/lib.rs(L134 - L179) src/lib.rs(L181 - L237)
Conditional Compilation Strategy
The crate uses sophisticated conditional compilation to provide different implementations based on the target environment and available features.
Target Environment Detection
flowchart TD subgraph subGraph3["Feature Gates"] PreemptEnabled["#[cfg(feature = 'preempt')]crate_interface calls"] PreemptDisabled["No preemption control"] end subgraph subGraph2["Userspace Path"] AliasIrqSave["type IrqSave = NoOp"] AliasNoPreempt["type NoPreempt = NoOp"] AliasNoPreemptIrqSave["type NoPreemptIrqSave = NoOp"] end subgraph subGraph1["Bare Metal Path"] RealIrqSave["struct IrqSave(usize)"] RealNoPreempt["struct NoPreempt"] RealNoPreemptIrqSave["struct NoPreemptIrqSave(usize)"] ArchIntegration["arch::local_irq_* calls"] end subgraph subGraph0["Compilation Decision"] CfgIf["cfg_if! macro"] TargetCheck["target_os = 'none' or doc?"] FeatureCheck["preempt feature enabled?"] end CfgIf --> TargetCheck FeatureCheck --> PreemptDisabled FeatureCheck --> PreemptEnabled RealIrqSave --> ArchIntegration RealNoPreempt --> PreemptEnabled RealNoPreemptIrqSave --> ArchIntegration RealNoPreemptIrqSave --> PreemptEnabled TargetCheck --> AliasIrqSave TargetCheck --> AliasNoPreempt TargetCheck --> AliasNoPreemptIrqSave TargetCheck --> RealIrqSave TargetCheck --> RealNoPreempt TargetCheck --> RealNoPreemptIrqSave
Conditional Compilation Flow
The compilation strategy ensures that:
- Bare metal targets (
target_os = "none"
) receive full guard implementations with platform-specific interrupt control - Userspace targets receive no-op aliases to prevent compilation errors while maintaining API compatibility
- Feature-gated preemption only compiles preemption control when the
preempt
feature is enabled
Sources: src/lib.rs(L83 - L111) src/lib.rs(L130 - L238) src/lib.rs(L153 - L154) src/lib.rs(L158 - L159) src/lib.rs(L167 - L168) src/lib.rs(L176 - L177)
Architecture Module Integration
The core library integrates with platform-specific implementations through the arch
module, which provides a uniform interface for interrupt control across different CPU architectures.
Architecture Abstraction Interface
flowchart TD subgraph subGraph2["Platform Implementations"] X86["x86::local_irq_*"] RISCV["riscv::local_irq_*"] AArch64["aarch64::local_irq_*"] LoongArch["loongarch64::local_irq_*"] end subgraph subGraph1["Architecture Module"] ArchMod["mod arch"] LocalIrqSave["local_irq_save_and_disable()"] LocalIrqRestore["local_irq_restore(state)"] end subgraph subGraph0["Core Library"] IrqSave["IrqSave::acquire()"] IrqRestore["IrqSave::release()"] NoPreemptIrqSave["NoPreemptIrqSave"] end ArchMod --> LocalIrqRestore ArchMod --> LocalIrqSave IrqRestore --> LocalIrqRestore IrqSave --> LocalIrqSave LocalIrqRestore --> AArch64 LocalIrqRestore --> LoongArch LocalIrqRestore --> RISCV LocalIrqRestore --> X86 LocalIrqSave --> AArch64 LocalIrqSave --> LoongArch LocalIrqSave --> RISCV LocalIrqSave --> X86 NoPreemptIrqSave --> LocalIrqRestore NoPreemptIrqSave --> LocalIrqSave
Architecture Module Integration Pattern
The architecture module provides two critical functions that abstract platform-specific interrupt handling:
local_irq_save_and_disable()
: Returns current interrupt state and disables interruptslocal_irq_restore(state)
: Restores interrupt state from saved value
Sources: src/lib.rs(L56) src/lib.rs(L139) src/lib.rs(L145) src/lib.rs(L170) src/lib.rs(L174)
RAII Lifecycle Management
The crate implements the RAII (Resource Acquisition Is Initialization) pattern to ensure critical sections are properly managed without requiring explicit cleanup calls.
Drop Implementation Pattern
sequenceDiagram participant UserCode as "User Code" participant GuardInstance as "Guard Instance" participant BaseGuardacquirerelease as "BaseGuard::acquire/release" participant PlatformLayer as "Platform Layer" UserCode ->> GuardInstance: "Guard::new()" GuardInstance ->> BaseGuardacquirerelease: "acquire()" BaseGuardacquirerelease ->> PlatformLayer: "disable IRQ/preemption" PlatformLayer -->> BaseGuardacquirerelease: "return state" BaseGuardacquirerelease -->> GuardInstance: "return state" GuardInstance -->> UserCode: "return guard instance" Note over UserCode: Critical section executes UserCode ->> GuardInstance: "drop(guard) or scope end" GuardInstance ->> BaseGuardacquirerelease: "release(state)" BaseGuardacquirerelease ->> PlatformLayer: "restore IRQ/preemption" PlatformLayer -->> BaseGuardacquirerelease: "complete" BaseGuardacquirerelease -->> GuardInstance: "complete" GuardInstance -->> UserCode: "destruction complete"
RAII Lifecycle Sequence
Each guard type implements the Drop
trait to ensure that critical section protection is automatically released when the guard goes out of scope, preventing resource leaks and ensuring system stability.
Sources: src/lib.rs(L126 - L128) src/lib.rs(L188 - L192) src/lib.rs(L208 - L212) src/lib.rs(L227 - L231)