Core Implementation Architecture
Relevant source files
This page provides a detailed analysis of the core implementation that underlies all spinlock types in the kspin crate. It covers the generic BaseSpinLock architecture, the RAII guard system, and the feature-conditional compilation strategy that enables optimization for different target environments.
For information about the specific spinlock types that users interact with, see Spinlock Types and Public API. For detailed implementation analysis of individual components, see BaseSpinLock and BaseSpinLockGuard, BaseGuard Trait System, SMP vs Single-Core Implementation, and Memory Ordering and Atomic Operations.
Architectural Overview
The kspin crate implements a layered architecture where all public spinlock types (SpinRaw, SpinNoPreempt, SpinNoIrq) are type aliases that wrap a single generic implementation: BaseSpinLock<G, T>. This design provides compile-time specialization through the type system while maintaining a unified codebase.
Core Components Diagram
flowchart TD
subgraph subGraph4["External Dependencies"]
KernelGuard["kernel_guard crate"]
CoreHint["core::hint::spin_loop()"]
CoreSync["core::sync::atomic"]
end
subgraph subGraph3["Data Storage"]
UnsafeCell["UnsafeCell<T>"]
AtomicBool["AtomicBool (SMP only)"]
end
subgraph subGraph2["Type System Integration"]
BaseGuard["BaseGuard trait"]
PhantomData["PhantomData<G>"]
end
subgraph subGraph1["Generic Implementation Layer"]
BaseSpinLock["BaseSpinLock<G, T>"]
BaseSpinLockGuard["BaseSpinLockGuard<'a, G, T>"]
end
subgraph subGraph0["Public API Layer"]
SpinRaw["SpinRaw<T>"]
SpinNoPreempt["SpinNoPreempt<T>"]
SpinNoIrq["SpinNoIrq<T>"]
end
AtomicBool --> CoreSync
BaseGuard --> KernelGuard
BaseSpinLock --> AtomicBool
BaseSpinLock --> BaseSpinLockGuard
BaseSpinLock --> CoreHint
BaseSpinLock --> PhantomData
BaseSpinLock --> UnsafeCell
PhantomData --> BaseGuard
SpinNoIrq --> BaseSpinLock
SpinNoPreempt --> BaseSpinLock
SpinRaw --> BaseSpinLock
Sources: src/base.rs(L27 - L32) src/base.rs(L37 - L43)
Generic Type Parameterization
The BaseSpinLock<G, T> struct uses two generic parameters that enable compile-time specialization:
| Parameter | Purpose | Constraints |
|---|---|---|
| G | Guard behavior type | Must implementBaseGuardtrait |
| T | Protected data type | Supports?Sizedfor unsized types |
The guard type G determines the protection behavior through the BaseGuard trait, which provides acquire() and release() methods that are called when entering and exiting the critical section.
Type Parameterization Flow
flowchart TD
subgraph subGraph2["Public Type Aliases"]
SpinRawAlias["SpinRaw<T>"]
SpinNoPreemptAlias["SpinNoPreempt<T>"]
SpinNoIrqAlias["SpinNoIrq<T>"]
end
subgraph subGraph1["BaseSpinLock Instantiations"]
RawLock["BaseSpinLock<NoOp, T>"]
PreemptLock["BaseSpinLock<NoPreempt, T>"]
IrqLock["BaseSpinLock<NoPreemptIrqSave, T>"]
end
subgraph subGraph0["Guard Types (kernel_guard)"]
NoOp["NoOp"]
NoPreempt["NoPreempt"]
NoPreemptIrqSave["NoPreemptIrqSave"]
end
IrqLock --> SpinNoIrqAlias
NoOp --> RawLock
NoPreempt --> PreemptLock
NoPreemptIrqSave --> IrqLock
PreemptLock --> SpinNoPreemptAlias
RawLock --> SpinRawAlias
Sources: src/base.rs(L27 - L32) src/lib.rs
Feature-Conditional Architecture
The implementation uses the smp feature flag to provide dramatically different code paths for single-core versus multi-core environments:
SMP Feature Compilation Strategy
Sources: src/base.rs(L13 - L14) src/base.rs(L29 - L30) src/base.rs(L41 - L42) src/base.rs(L79 - L93) src/base.rs(L111 - L118) src/base.rs(L125 - L136)
Lock Acquisition and Guard Lifecycle
The core operation flow demonstrates how the RAII pattern ensures correct lock management:
Lock Lifecycle Flow
sequenceDiagram
participant Client as Client
participant BaseSpinLock as BaseSpinLock
participant BaseGuard as BaseGuard
participant AtomicBool as AtomicBool
participant BaseSpinLockGuard as BaseSpinLockGuard
Client ->> BaseSpinLock: lock()
BaseSpinLock ->> BaseGuard: G::acquire()
Note over BaseGuard: Disable IRQs/preemption
BaseGuard -->> BaseSpinLock: irq_state
alt SMP enabled
BaseSpinLock ->> AtomicBool: compare_exchange_weak(false, true)
loop While locked
AtomicBool -->> BaseSpinLock: Err (already locked)
BaseSpinLock ->> AtomicBool: load(Ordering::Relaxed)
BaseSpinLock ->> BaseSpinLock: core::hint::spin_loop()
end
AtomicBool -->> BaseSpinLock: Ok (acquired)
else SMP disabled
Note over BaseSpinLock: Lock always succeeds
end
BaseSpinLock -->> Client: BaseSpinLockGuard
Note over Client: Use protected data via Deref/DerefMut
Client ->> BaseSpinLockGuard: drop()
alt SMP enabled
BaseSpinLockGuard ->> AtomicBool: store(false, Ordering::Release)
end
BaseSpinLockGuard ->> BaseGuard: G::release(irq_state)
Note over BaseGuard: Restore IRQs/preemption
Sources: src/base.rs(L77 - L101) src/base.rs(L218 - L227)
Memory Safety and Synchronization
The implementation provides memory safety through several mechanisms:
| Mechanism | Implementation | Purpose |
|---|---|---|
| UnsafeCell | src/base.rs31 | Interior mutability for protected data |
| RAII Guard | src/base.rs37-43 | Automatic lock release on scope exit |
| Raw pointer in guard | src/base.rs40 | Direct data access while lock is held |
| Atomic operations | src/base.rs83-85 | Multi-core synchronization |
| Memory ordering | Ordering::Acquire/Release | Proper memory barriers |
Data Access Safety Model
flowchart TD
subgraph subGraph2["Safety Guarantees"]
ExclusiveAccess["Exclusive data access"]
AutoRelease["Automatic lock release"]
MemoryOrdering["Proper memory ordering"]
end
subgraph subGraph1["BaseSpinLockGuard Structure"]
DataPtr["data: *mut T"]
LockRef["lock: &'a AtomicBool"]
IrqState["irq_state: G::State"]
PhantomRef["_phantom: &'a PhantomData<G>"]
end
subgraph subGraph0["BaseSpinLock Structure"]
UnsafeCellField["data: UnsafeCell<T>"]
AtomicLock["lock: AtomicBool"]
PhantomG["_phantom: PhantomData<G>"]
end
AtomicLock --> LockRef
AtomicLock --> MemoryOrdering
DataPtr --> ExclusiveAccess
LockRef --> AtomicLock
LockRef --> AutoRelease
PhantomG --> PhantomRef
PhantomRef --> UnsafeCellField
UnsafeCellField --> DataPtr
Sources: src/base.rs(L27 - L32) src/base.rs(L37 - L43) src/base.rs(L195 - L210) src/base.rs(L218 - L227)