SuperTinyKernel™ RTOS 1.08.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk::hw::SpinLock Class Reference

Atomic busy-wait lock used as the global cross-core synchronisation primitive inside CriticalSection. More...

#include <stk_arch.h>

Classes

class  ScopedLock
 RAII guard that the spin lock is locked on construction and unlocked it on destruction. More...

Public Types

enum  EState {
  UNLOCKED = 0 ,
  LOCKED
}
 Internal lock state values. More...

Public Member Functions

 SpinLock ()
 Construct a SpinLock (unlocked by default).
void Lock ()
 Acquire SpinLock, blocking until it is available.
void Unlock ()
 Release SpinLock, allowing another thread or core to acquire it.
bool TryLock ()
 Attempt to acquire SpinLock in a single non-blocking attempt.
bool IsLocked () const
 Sample current lock state.

Protected Member Functions

 SpinLock (const SpinLock &)=delete
SpinLockoperator= (const SpinLock &)=delete

Protected Attributes

volatile bool m_lock
 Lock state (see EState). 8-byte aligned to occupy its own cache line word and avoid false sharing on SMP targets.

Detailed Description

Atomic busy-wait lock used as the global cross-core synchronisation primitive inside CriticalSection.

Note
Implemented using an atomic test-and-set (or hardware spinlock peripheral on RP2040) so that it is safe across multiple CPU cores. CriticalSection::Enter() acquires this lock (via s_StkCortexmCsuLock on the ARM Cortex-M back-end) after masking local interrupts, giving the combined interrupt-mask + cross-core guarantee described in CriticalSection.
SpinLock is exposed as a public API for use cases that need a bare cross-core lock without interrupt masking, for example protecting data shared only between two tasks on different cores where ISR access is not a concern.
Use only for very short, low-latency critical sections. Spinning wastes CPU cycles and can increase interrupt latency and power consumption.
Non-recursive: calling Lock() twice from the same thread/core without an intervening Unlock() will deadlock. The ARM implementation guards against this: Lock() times out after approximately STK_SPINLOCK_TIMEOUT_US (default 5 seconds) of wall-clock spin time, computed at runtime from the core clock speed, and raises STK_KERNEL_PANIC(KERNEL_PANIC_SPINLOCK_DEADLOCK) - in all build configurations, not just debug builds.
See also
CriticalSection

Definition at line 569 of file stk_arch.h.

Member Enumeration Documentation

◆ EState

Internal lock state values.

Enumerator
UNLOCKED 

Lock is free and available for acquisition.

LOCKED 

Lock is held by a thread or core.

Definition at line 575 of file stk_arch.h.

576 {
577 UNLOCKED = 0,
578 LOCKED
579 };
@ UNLOCKED
Lock is free and available for acquisition.
Definition stk_arch.h:577
@ LOCKED
Lock is held by a thread or core.
Definition stk_arch.h:578

Constructor & Destructor Documentation

◆ SpinLock() [1/2]

stk::hw::SpinLock::SpinLock ( )
inlineexplicit

Construct a SpinLock (unlocked by default).

Definition at line 617 of file stk_arch.h.

618 {}
volatile bool m_lock
Lock state (see EState). 8-byte aligned to occupy its own cache line word and avoid false sharing on ...
Definition stk_arch.h:662

References m_lock, and UNLOCKED.

Referenced by operator=(), and stk::hw::SpinLock::ScopedLock::ScopedLock().

Here is the caller graph for this function:

◆ SpinLock() [2/2]

stk::hw::SpinLock::SpinLock ( const SpinLock & )
protecteddelete

Member Function Documentation

◆ IsLocked()

bool stk::hw::SpinLock::IsLocked ( ) const
inline

Sample current lock state.

Returns
true if the lock is currently held; false if it is free.
Note
The result is a snapshot only. On SMP systems another core may acquire or release the lock between this read and any subsequent action, so IsLocked() must not be used as a synchronization check. Use TryLock() or Lock() for safe acquisition.

Definition at line 654 of file stk_arch.h.

654{ return (m_lock == LOCKED); }

References LOCKED, and m_lock.

◆ Lock()

void stk::hw::SpinLock::Lock ( )

Acquire SpinLock, blocking until it is available.

Note
Busy-waits (spins) using __stk_relax_cpu() until the lock transitions to UNLOCKED and this call wins the atomic acquisition.
Warning
Non-recursive. Calling Lock() a second time from the same thread/core while already holding the lock will spin forever (deadlock).
Calling Lock() from an ISR while the interrupted task holds the same lock will also deadlock. Prefer CriticalSection for ISR-to-task synchronization.

Referenced by stk::hw::SpinLock::ScopedLock::ScopedLock().

Here is the caller graph for this function:

◆ operator=()

SpinLock & stk::hw::SpinLock::operator= ( const SpinLock & )
protecteddelete

References m_lock, and SpinLock().

Here is the call graph for this function:

◆ TryLock()

bool stk::hw::SpinLock::TryLock ( )

Attempt to acquire SpinLock in a single non-blocking attempt.

Returns
true if the lock was acquired; false if it was already held by another thread/core.
Note
Returns immediately regardless of lock state. On success the caller holds the lock and must call Unlock() when done. On failure the lock state is unchanged.
Useful in try-acquire / back-off patterns or when a fallback action is available if the resource is busy.

◆ Unlock()

void stk::hw::SpinLock::Unlock ( )

Release SpinLock, allowing another thread or core to acquire it.

Note
The lock transitions immediately to UNLOCKED. If another core is spinning in Lock(), it will acquire the lock on its next successful atomic attempt.
Warning
Must only be called by the thread or core that currently holds the lock (via Lock() or a successful TryLock()). Calling Unlock() without a prior acquisition produces undefined behavior.

Member Data Documentation

◆ m_lock

volatile bool stk::hw::SpinLock::m_lock
protected

Lock state (see EState). 8-byte aligned to occupy its own cache line word and avoid false sharing on SMP targets.

Definition at line 662 of file stk_arch.h.

Referenced by IsLocked(), operator=(), and SpinLock().


The documentation for this class was generated from the following file: