BaseGuard Trait System
Relevant source files
The BaseGuard trait system is the core abstraction that enables different protection behaviors in kspin spinlocks through type parameterization. This system allows BaseSpinLock<G, T> to provide varying levels of interrupt and preemption protection by substituting different guard implementations at compile time.
For information about the specific spinlock types that use these guards, see Spinlock Types and Public API. For details about the underlying BaseSpinLock implementation, see BaseSpinLock and BaseSpinLockGuard.
BaseGuard Trait Interface
The BaseGuard trait is defined in the external kernel_guard crate and provides a standardized interface for managing system-level protection states during critical sections.
classDiagram
class BaseGuard {
<<trait>>
+type State
+acquire() State
+release(state: State)
}
class NoOp {
+type State =()
+acquire()()
+release(state:())
}
class NoPreempt {
+type State = PreemptState
+acquire() PreemptState
+release(state: PreemptState)
}
class NoPreemptIrqSave {
+type State = IrqState
+acquire() IrqState
+release(state: IrqState)
}
BaseGuard --|> NoOp
BaseGuard --|> NoPreempt
NoPreemptIrqSave --|> NoPreempt
BaseGuard Trait Interface
Sources: src/base.rs(L16) src/lib.rs(L6)
Integration with BaseSpinLock
The BaseSpinLock<G, T> struct uses the BaseGuard trait as a type parameter to customize protection behavior without runtime overhead. The guard type G determines what system-level protections are applied during lock acquisition and release.
flowchart TD
subgraph subGraph1["Lock Operations"]
Lock["lock()"]
TryLock["try_lock()"]
Drop["Drop::drop()"]
end
subgraph subGraph0["Guard Integration Points"]
Acquire["G::acquire()"]
Release["G::release(state)"]
StateStorage["irq_state: G::State"]
end
BaseSpinLock["BaseSpinLock<G: BaseGuard, T>"]
BaseSpinLockGuard["BaseSpinLockGuard<G, T>"]
Acquire --> StateStorage
BaseSpinLock --> Lock
BaseSpinLock --> TryLock
BaseSpinLockGuard --> Drop
Drop --> Release
Lock --> Acquire
StateStorage --> BaseSpinLockGuard
TryLock --> Acquire
BaseGuard Integration Flow
The integration occurs at three key points in src/base.rs:
- State acquisition during lock operations src/base.rs(L78) src/base.rs(L123)
- State storage in the guard struct src/base.rs(L39)
- State release during guard destruction src/base.rs(L225)
Sources: src/base.rs(L27) src/base.rs(L37 - L43) src/base.rs(L77 - L101) src/base.rs(L218 - L227)
Concrete Guard Implementations
The kspin crate uses three specific implementations of BaseGuard from the kernel_guard crate, each providing different levels of system protection.
| Guard Type | Protection Level | State Type | Use Context |
|---|---|---|---|
| NoOp | None | () | IRQ-disabled, preemption-disabled |
| NoPreempt | Disable preemption | PreemptState | IRQ-disabled contexts |
| NoPreemptIrqSave | Disable preemption + IRQs | IrqState | Any context |
flowchart TD
subgraph subGraph1["Spinlock Types"]
SpinRaw["SpinRaw<T>"]
SpinNoPreempt["SpinNoPreempt<T>"]
SpinNoIrq["SpinNoIrq<T>"]
end
subgraph subGraph0["Protection Levels"]
NoOp["NoOpRaw Protection"]
NoPreempt["NoPreemptPreemption Protection"]
NoPreemptIrqSave["NoPreemptIrqSaveFull Protection"]
end
NoOp --> SpinRaw
NoPreempt --> SpinNoPreempt
NoPreemptIrqSave --> SpinNoIrq
Guard Type to Spinlock Type Mapping
Sources: src/lib.rs(L6) src/lib.rs(L15) src/lib.rs(L24) src/lib.rs(L33)
Type-Driven Protection Behavior
The BaseGuard trait system enables compile-time selection of protection behavior through Rust's type system. Each guard implementation provides different acquire() and release() semantics without requiring runtime branching.
sequenceDiagram
participant Client as Client
participant BaseSpinLock as BaseSpinLock
participant GBaseGuard as "G: BaseGuard"
participant KernelSubsystems as "Kernel Subsystems"
Client ->> BaseSpinLock: lock()
BaseSpinLock ->> GBaseGuard: G::acquire()
GBaseGuard ->> KernelSubsystems: Disable preemption/IRQs
KernelSubsystems -->> GBaseGuard: Return saved state
GBaseGuard -->> BaseSpinLock: G::State
BaseSpinLock ->> BaseSpinLock: Acquire atomic lock
BaseSpinLock -->> Client: BaseSpinLockGuard
Note over Client: Use protected data
Client ->> BaseSpinLock: Drop guard
BaseSpinLock ->> BaseSpinLock: Release atomic lock
BaseSpinLock ->> GBaseGuard: G::release(state)
GBaseGuard ->> KernelSubsystems: Restore preemption/IRQs
KernelSubsystems -->> GBaseGuard: Complete
Protection State Management Sequence
The type-driven approach ensures that:
NoOp:acquire()andrelease()are no-ops, providing zero overheadNoPreempt: Manages preemption state to prevent task switchingNoPreemptIrqSave: Manages both preemption and interrupt state for maximum protection
Sources: src/base.rs(L77 - L79) src/base.rs(L122 - L124) src/base.rs(L222 - L225)
State Management in Guard Lifecycle
The BaseSpinLockGuard stores the protection state returned by G::acquire() and ensures proper cleanup through Rust's RAII pattern. This guarantees that system protection state is always restored, even in the presence of panics.
Guard State Lifecycle
The state management implementation in BaseSpinLockGuard:
- State storage:
irq_state: G::Statefield holds the protection state src/base.rs(L39) - State acquisition: Captured during guard creation src/base.rs(L96) src/base.rs(L141)
- State restoration: Automatically handled in
Drop::drop()src/base.rs(L225)
This design ensures that protection state is never leaked and that the system always returns to its original state when the critical section ends.
Sources: src/base.rs(L37 - L43) src/base.rs(L94 - L100) src/base.rs(L138 - L145) src/base.rs(L218 - L227)