axiom-spinlock 🌀
A lightweight, no_std-compatible spinlock and exponential backoff implementation for low-level concurrent systems.
This crate provides a minimal, efficient spin-based mutual exclusion primitive (SpinLock<T>) together with an adaptive exponential BackOff utility to reduce contention in busy-wait loops.
The implementation focuses on environments where blocking is not an option (kernels, embedded runtimes, custom executors), so it avoids OS-level mutexes and context switching.
Highlights
- no_std compatible (uses
coreonly). - Optional
stdfeature (default) to enable thread yielding. SpinLock<T>: atomic test-and-set spinlock with RAII guard (SpinGuard).BackOff: exponential backoff with configurable start, relax/reset and optionalstdyielding.- Small, well-tested, and appropriate for short critical sections.
Crate name
This repository builds the crate axiom-spinlock (see Cargo.toml).
Quick examples
Using SpinLock:
use SpinLock;
let lock = new;
// unlocked when `guard` is dropped
assert_eq!;
// convenience API
lock.with_lock;
Using BackOff:
use BackOff;
let backoff = new;
for _ in 0..5
API overview
SpinLock
A minimal spin-based mutual exclusion primitive:
const fn new(data: T) -> Self— create a new lock.fn lock(&self) -> SpinGuard<'_, T>— acquire the lock (blocks by spinning); returns a guard that releases on drop.unsafe fn unlock(&self)— unsafely release the lock (only call if you own the lock).fn try_lock(&self) -> Option<SpinGuard<'_, T>>— try to acquire without blocking.fn try_lock_for(&self, spins: usize) -> Option<SpinGuard<'_, T>>— attempt to acquire within a fixed number of spin attempts.fn is_locked(&self) -> bool— check whether the lock is currently held.fn with_lock<R>(&self, f: impl FnOnce(&mut T) -> R) -> R— convenience wrapper to run a closure while holding the lock.
Notes:
- The lock uses an
AtomicBoolwith Acquire/Release ordering. - The guard implements
DerefandDerefMutfor ergonomic access. SpinLockis markedSend/SyncwhenT: Send.- Not reentrant and not fair — starvation is possible under heavy contention.
BackOff
A simple exponential backoff manager used to reduce contention in spin loops.
const fn new() -> BackOff— default start value.const fn new_with(start: u32) -> BackOff— create with custom start.fn wait(&self)— perform one backoff step (spins, doubles internal counter up toMAX_SPIN, optionally yields withstd).fn relax(&self)— reduce current spin intensity.fn current(&self) -> u32— get current spin iteration value.fn reset(&self)— reset to default start.fn reset_to(&self, spin: u32)— reset to explicit value.#[cfg(feature = "std")] fn yield_now(&self)— explicit yield (only when compiled withstd).
Implementation details:
- Uses
core::hint::spin_loop()to inform the CPU of busy-wait. - When built with the
stdfeature (the crate defaults to enabling this),std::thread::yield_now()is called once contention exceeds a threshold.
Example program (from src/main.rs)
The repository includes an example program that creates a static SpinLock<i64> and spawns 100 threads, each incrementing the shared counter 1_000_000 times. This is useful to stress-test the lock, but be aware it is CPU-intensive.
To run the example (default features include std):
Expect the program to be CPU-bound and run for a while depending on your CPU.
Building & testing
Build the project:
Run tests (crate default features include std — if you want to test no_std behavior you must change features accordingly):
Features
std(default): Enablesstd::thread::yield_now()during prolonged backoff and allows examples/tests that spawn threads.
The crate is implemented to be usable without std by disabling this feature in embedded or kernel contexts.
Safety notes & recommended usage
- Use
SpinLockonly for short critical sections. - Avoid holding a spinlock during blocking operations or long computations.
SpinLockis not reentrant.unlock()isunsafeand should only be used by code that truly owns the lock.
Contributing
- The
Cargo.tomlcontains author and repository metadata. - Contributions are welcome; open issues and pull requests on the repository: https://github.com/LOKESH-999/axiom-spinlock
Acknowledgements
This crate is intentionally small and targeted for embedded/low-level use cases. It pairs a tiny spinlock with a configurable backoff to provide a lightweight synchronization primitive where OS-level primitives are unavailable or undesired.