Trait System

Relevant source files

This document explains the trait-based architecture that forms the foundation of the kernel_guard crate. The trait system defines the interfaces for implementing critical section guards and provides extension points for user code to integrate preemption control. For information about specific guard implementations, see RAII Guards. For details on architecture-specific implementations, see Multi-Architecture Support.

Core Trait Architecture

The kernel_guard crate is built around two primary traits that define the interface contracts for guard behavior and user integration.

BaseGuard Trait

The BaseGuard trait serves as the foundational interface that all guard types must implement. It defines the basic lifecycle operations for entering and exiting critical sections using the RAII pattern.

flowchart TD
BG["BaseGuard trait"]
ST["Associated Type: State"]
ACQ["acquire() -> State"]
REL["release(state: State)"]
CLONE["Clone + Copy bounds"]
BEFORE["Execute before critical section"]
AFTER["Execute after critical section"]
IMPL1["NoOp"]
IMPL2["IrqSave"]
IMPL3["NoPreempt"]
IMPL4["NoPreemptIrqSave"]

ACQ --> BEFORE
BG --> ACQ
BG --> REL
BG --> ST
IMPL1 --> BG
IMPL2 --> BG
IMPL3 --> BG
IMPL4 --> BG
REL --> AFTER
ST --> CLONE

BaseGuard Trait Definition

The trait defines three key components at src/lib.rs(L68 - L78) :

ComponentPurposeRequirements
Stateassociated typeStores state information during critical sectionMust implementClone + Copy
acquire()methodPerforms setup operations before critical sectionReturnsStatevalue
release(state)methodPerforms cleanup operations after critical sectionConsumes savedState

Sources: src/lib.rs(L68 - L78) 

KernelGuardIf Trait

The KernelGuardIf trait provides an extension point for user code to implement preemption control functionality. This trait uses the crate_interface mechanism to enable runtime dispatch to user-provided implementations.

flowchart TD
DEF["KernelGuardIf trait definition"]
ENABLE["enable_preempt()"]
DISABLE["disable_preempt()"]
IMPL["User Implementation"]
CRATE_IMPL["#[crate_interface::impl_interface]"]
RUNTIME["Runtime dispatch"]
CALL1["NoPreempt::acquire()"]
DISPATCH1["crate_interface::call_interface!"]
CALL2["NoPreempt::release()"]
DISPATCH2["crate_interface::call_interface!"]

CALL1 --> DISPATCH1
CALL2 --> DISPATCH2
CRATE_IMPL --> RUNTIME
DEF --> DISABLE
DEF --> ENABLE
DISPATCH1 --> RUNTIME
DISPATCH2 --> RUNTIME
IMPL --> CRATE_IMPL
RUNTIME --> IMPL

Interface Definition

The trait is defined at src/lib.rs(L59 - L66)  with two required methods:

  • enable_preempt(): Called when preemption should be re-enabled
  • disable_preempt(): Called when preemption should be disabled

Sources: src/lib.rs(L59 - L66) 

Runtime Dispatch Mechanism

The crate uses the crate_interface library to implement a stable interface between the kernel_guard crate and user code. This mechanism allows the library to call user-provided functions at runtime without compile-time dependencies.

crate_interface Integration

Interface Declaration

The trait is declared as an interface using #[crate_interface::def_interface] at src/lib.rs(L59)  which generates the necessary infrastructure for runtime dispatch.

User Implementation Pattern

Users must implement the trait using the #[crate_interface::impl_interface] attribute, as shown in the example at src/lib.rs(L35 - L43) :

#![allow(unused)]
fn main() {
#[crate_interface::impl_interface]
impl KernelGuardIf for KernelGuardIfImpl {
    fn enable_preempt() { /* implementation */ }
    fn disable_preempt() { /* implementation */ }
}
}

Runtime Calls

The library invokes user implementations using crate_interface::call_interface! macro at several locations:

Sources: src/lib.rs(L59)  src/lib.rs(L35 - L43)  src/lib.rs(L154)  src/lib.rs(L159)  src/lib.rs(L168)  src/lib.rs(L177) 

Trait Implementation Patterns

Feature-Conditional Implementation

The KernelGuardIf calls are conditionally compiled based on the preempt feature flag. When the feature is disabled, the calls become no-ops:


Conditional Compilation Points:

Sources: src/lib.rs(L153 - L154)  src/lib.rs(L158 - L159)  src/lib.rs(L167 - L168)  src/lib.rs(L176 - L177) 

State Management Patterns

Different guard types use different State type strategies:

Guard TypeState TypePurpose
NoOp()No state needed
IrqSaveusizeStores IRQ flags for restoration
NoPreempt()Preemption state managed externally
NoPreemptIrqSaveusizeStores IRQ flags, preemption managed externally

Sources: src/lib.rs(L114)  src/lib.rs(L135)  src/lib.rs(L150)  src/lib.rs(L164) 

Complete Trait Interaction Flow

The following diagram shows how the traits interact during a complete guard lifecycle:

sequenceDiagram
    participant UserCode as "User Code"
    participant GuardInstance as "Guard Instance"
    participant BaseGuardacquire as "BaseGuard::acquire()"
    participant archlocal_irq_ as "arch::local_irq_*"
    participant KernelGuardIf as "KernelGuardIf"
    participant UserImplementation as "User Implementation"

    UserCode ->> GuardInstance: new()
    GuardInstance ->> BaseGuardacquire: acquire()
    alt NoPreempt or NoPreemptIrqSave
        BaseGuardacquire ->> KernelGuardIf: crate_interface::call_interface!
        KernelGuardIf ->> UserImplementation: disable_preempt()
        UserImplementation -->> KernelGuardIf: ​
        KernelGuardIf -->> BaseGuardacquire: ​
    end
    alt IrqSave or NoPreemptIrqSave
        BaseGuardacquire ->> archlocal_irq_: local_irq_save_and_disable()
        archlocal_irq_ -->> BaseGuardacquire: flags: usize
    end
    BaseGuardacquire -->> GuardInstance: State
    GuardInstance -->> UserCode: Guard instance
    Note over UserCode: Critical Section Execution
    UserCode ->> GuardInstance: drop()
    GuardInstance ->> BaseGuardacquire: release(state)
    alt IrqSave or NoPreemptIrqSave
        BaseGuardacquire ->> archlocal_irq_: local_irq_restore(flags)
        archlocal_irq_ -->> BaseGuardacquire: ​
    end
    alt NoPreempt or NoPreemptIrqSave
        BaseGuardacquire ->> KernelGuardIf: crate_interface::call_interface!
        KernelGuardIf ->> UserImplementation: enable_preempt()
        UserImplementation -->> KernelGuardIf: ​
        KernelGuardIf -->> BaseGuardacquire: ​
    end
    BaseGuardacquire -->> GuardInstance: ​
    GuardInstance -->> UserCode: ​

Sources: src/lib.rs(L183 - L185)  src/lib.rs(L202 - L205)  src/lib.rs(L222 - L224)  src/lib.rs(L134 - L147)  src/lib.rs(L149 - L161)  src/lib.rs(L163 - L179)