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:

MethodReturn TypeDescription
new(data: T)SpinRawCreates 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 TypeAcquisition OverheadRelease OverheadContext Switches
SpinRawAtomic operation onlyAtomic operation onlyManual control required
SpinNoPreemptAtomic + preemption disableAtomic + preemption enablePrevented during lock
SpinNoIrqAtomic + preemption + IRQ disableAtomic + preemption + IRQ enableFully 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.