SpinRaw
Relevant source files
Purpose and Scope
This page documents SpinRaw<T>, the raw spinlock implementation in the kspin crate that provides no built-in protection mechanisms. SpinRaw offers the fastest performance among the three spinlock types but requires manual management of preemption and interrupt state by the caller.
For information about spinlocks with built-in preemption protection, see SpinNoPreempt. For full protection including IRQ disabling, see SpinNoIrq. For detailed implementation internals, see BaseSpinLock and BaseSpinLockGuard. For comprehensive usage guidelines across all spinlock types, see Usage Guidelines and Safety.
Type Definition and Basic Interface
SpinRaw<T> is implemented as a type alias that specializes the generic BaseSpinLock with the NoOp guard type from the kernel_guard crate.
Core Type Definitions
flowchart TD
subgraph subGraph0["SpinRaw Type System"]
SpinRaw["SpinRaw<T>Type alias"]
BaseSpinLock["BaseSpinLock<NoOp, T>Generic implementation"]
SpinRawGuard["SpinRawGuard<'a, T>RAII guard"]
BaseSpinLockGuard["BaseSpinLockGuard<'a, NoOp, T>Generic guard"]
NoOp["NoOpkernel_guard guard type"]
end
BaseSpinLock --> BaseSpinLockGuard
BaseSpinLock --> NoOp
BaseSpinLockGuard --> NoOp
SpinRaw --> BaseSpinLock
SpinRawGuard --> BaseSpinLockGuard
Sources: src/lib.rs(L33 - L36)
The SpinRaw<T> type provides the standard spinlock interface methods inherited from BaseSpinLock:
| Method | Return Type | Description |
|---|---|---|
| new(data: T) | SpinRaw | Creates a new spinlock containing the given data |
| lock() | SpinRawGuard<'_, T> | Acquires the lock, spinning until successful |
| try_lock() | Option<SpinRawGuard<'_, T>> | Attempts to acquire the lock without spinning |
Protection Behavior and NoOp Guard
The defining characteristic of SpinRaw is its use of the NoOp guard type, which performs no protection actions during lock acquisition or release.
Protection Flow Diagram
flowchart TD
subgraph subGraph1["NoOp Guard Behavior"]
NoOpAcquire["NoOp::acquire()Does nothing"]
NoOpRelease["NoOp::release()Does nothing"]
end
subgraph subGraph0["SpinRaw Lock Acquisition Flow"]
Start["lock() called"]
TryAcquire["Attempt atomic acquisition"]
IsLocked["Lock alreadyheld?"]
Spin["Spin wait(busy loop)"]
Acquired["Lock acquired"]
GuardCreated["SpinRawGuard createdwith NoOp::acquire()"]
end
note1["Note: No preemption disablingNo IRQ disablingNo protection barriers"]
Acquired --> GuardCreated
GuardCreated --> NoOpAcquire
GuardCreated --> NoOpRelease
IsLocked --> Acquired
IsLocked --> Spin
NoOpAcquire --> note1
NoOpRelease --> note1
Spin --> TryAcquire
Start --> TryAcquire
TryAcquire --> IsLocked
Sources: src/lib.rs(L29 - L36) src/base.rs
Unlike SpinNoPreempt and SpinNoIrq, the NoOp guard performs no system-level protection operations:
- No preemption disabling/enabling
- No interrupt disabling/enabling
- No memory barriers beyond those required for the atomic lock operations
Safety Requirements and Usage Contexts
SpinRaw places the burden of ensuring safe usage entirely on the caller. The lock itself provides only the basic mutual exclusion mechanism without any system-level protections.
Required Caller Responsibilities
flowchart TD
subgraph subGraph1["Consequences of Violation"]
Deadlock["Potential deadlockif preempted while holding lock"]
RaceCondition["Race conditionswith interrupt handlers"]
DataCorruption["Data corruptionfrom concurrent access"]
end
subgraph subGraph0["Caller Must Ensure"]
PreemptDisabled["Preemption already disabledBefore calling lock()"]
IRQDisabled["Local IRQs already disabledBefore calling lock()"]
NoInterruptUse["Never used ininterrupt handlers"]
ProperContext["Operating in appropriatekernel context"]
end
subgraph subGraph2["Safe Usage Pattern"]
DisablePreempt["disable_preemption()"]
DisableIRQ["disable_local_irq()"]
UseLock["SpinRaw::lock()"]
CriticalSection["/* critical section */"]
ReleaseLock["drop(guard)"]
EnableIRQ["enable_local_irq()"]
EnablePreempt["enable_preemption()"]
end
CriticalSection --> ReleaseLock
DisableIRQ --> UseLock
DisablePreempt --> DisableIRQ
EnableIRQ --> EnablePreempt
IRQDisabled --> RaceCondition
NoInterruptUse --> RaceCondition
PreemptDisabled --> Deadlock
ProperContext --> DataCorruption
ReleaseLock --> EnableIRQ
UseLock --> CriticalSection
Sources: src/lib.rs(L31 - L32) README.md(L19 - L22)
Performance Characteristics
SpinRaw offers the highest performance among the three spinlock types due to its minimal overhead approach.
Performance Comparison
| Spinlock Type | Acquisition Overhead | Release Overhead | Context Switches |
|---|---|---|---|
| SpinRaw | Atomic operation only | Atomic operation only | Manual control required |
| SpinNoPreempt | Atomic + preemption disable | Atomic + preemption enable | Prevented during lock |
| SpinNoIrq | Atomic + preemption + IRQ disable | Atomic + preemption + IRQ enable | Fully prevented |
SMP vs Single-Core Behavior
flowchart TD
subgraph subGraph2["Feature Flag Impact on SpinRaw"]
SMPEnabled["smp featureenabled?"]
subgraph subGraph1["Single-Core Path (no smp)"]
NoLockField["No lock fieldoptimized out"]
NoAtomics["No atomic operationslock always succeeds"]
NoSpinning["No spinning behaviorimmediate success"]
NoOverhead["Zero overheadcompile-time optimization"]
end
subgraph subGraph0["Multi-Core Path (smp)"]
AtomicField["AtomicBool lock fieldin BaseSpinLock"]
CompareExchange["compare_exchange operationsfor acquisition"]
RealSpin["Actual spinning behavioron contention"]
MemoryOrder["Memory orderingconstraints"]
end
end
AtomicField --> CompareExchange
CompareExchange --> RealSpin
NoAtomics --> NoSpinning
NoLockField --> NoAtomics
NoSpinning --> NoOverhead
RealSpin --> MemoryOrder
SMPEnabled --> AtomicField
SMPEnabled --> NoLockField
Sources: README.md(L12) src/base.rs
In single-core environments (without the smp feature), SpinRaw becomes a zero-cost abstraction since no actual locking is necessary when preemption and interrupts are properly controlled.
Integration with BaseSpinLock Architecture
SpinRaw leverages the generic BaseSpinLock implementation while providing no additional protection through its NoOp guard parameter.
Architectural Mapping
classDiagram
class SpinRaw {
<<type alias>>
+new(data: T) SpinRaw~T~
+lock() SpinRawGuard~T~
+try_lock() Option~SpinRawGuard~T~~
}
class BaseSpinLock~NoOp_T~ {
-lock_state: AtomicBool
+new(data: T) Self
+lock() BaseSpinLockGuard~NoOp_T~
+try_lock() Option~BaseSpinLockGuard~NoOp_T~~
-try_lock_inner() bool
}
class SpinRawGuard {
<<type alias>>
+deref() &T
+deref_mut() &mut T
}
class BaseSpinLockGuard~NoOp_T~ {
-lock: BaseSpinLock~NoOp_T~
-guard_state: NoOp
+new() Self
+deref() &T
+deref_mut() &mut T
}
class NoOp {
+acquire() Self
+release()
}
SpinRaw --|> BaseSpinLock : type alias
SpinRawGuard --|> BaseSpinLockGuard : type alias
BaseSpinLock --> BaseSpinLockGuard : creates
BaseSpinLockGuard --> NoOp : uses
Sources: src/lib.rs(L33 - L36) src/base.rs
The SpinRaw type inherits all functionality from BaseSpinLock while the NoOp guard ensures minimal overhead by performing no protection operations during the guard's lifetime.