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

Recursive spinlock. More...

#include <stk_sync_spinlock.h>

Inheritance diagram for stk::sync::SpinLock:
Collaboration diagram for stk::sync::SpinLock:

Public Member Functions

 SpinLock ()
 Construct a SpinLock in the unlocked state.
STK_VIRT_DTOR ~SpinLock ()
 Destructor.
void Lock ()
 Acquire the lock.
bool TryLock ()
 Attempt to acquire the lock without blocking.
void Unlock ()
 Release the lock or decrement the recursion counter.

Private Member Functions

 STK_NONCOPYABLE_CLASS (SpinLock)
bool LockRecursively (TId locking_tid)
void MakeLocked (TId locking_tid)

Private Attributes

TId m_owner_tid
 thread id of the current owner
uint16_t m_recursion_count
 nesting depth
hw::SpinLock m_lock
 low-level spin lock

Static Private Attributes

static const uint16_t RECURSION_MAX = 0xFFFEU
 maximum nesting depth

Detailed Description

Recursive spinlock.

SpinLock is a high-performance synchronization primitive intended for extremely short critical sections where the overhead of a kernel context switch (as seen in Mutex) is undesirable.

This implementation provides:

  • Nesting (Recursion): Allows the owning thread to acquire the lock multiple times without deadlocking. Max recursion depth is 0xFFFE.
// Example: Protecting high-frequency parameter updates
stk::sync::SpinLock g_ParamLock;
void Param_Process_Task() {
// acquisition is extremely fast if the lock is free
g_Lock.Lock();
// ... update parameters ...
g_Lock.Unlock();
}
Recursive spinlock.
void Lock()
Acquire the lock.
Warning
While faster than a Mutex for uncontended or very short locks, prolonged spinning wastes CPU cycles. If critical section involves I/O or complex logic, prefer stk::sync::Mutex.
ISR-unsafe, for guarding code accessible by ISR use hw::CriticalSection instead.
See also
IMutex, Mutex, ScopedCriticalSection, Yield

Definition at line 53 of file stk_sync_spinlock.h.

Constructor & Destructor Documentation

◆ SpinLock()

stk::sync::SpinLock::SpinLock ( )
inlineexplicit

Construct a SpinLock in the unlocked state.

Definition at line 58 of file stk_sync_spinlock.h.

59 {}
static constexpr TId TID_NONE
Reserved task/thread id representing zero/none thread id.
Definition stk_common.h:177
uint16_t m_recursion_count
nesting depth
TId m_owner_tid
thread id of the current owner

References m_owner_tid, m_recursion_count, and stk::TID_NONE.

Referenced by STK_NONCOPYABLE_CLASS().

Here is the caller graph for this function:

◆ ~SpinLock()

STK_VIRT_DTOR stk::sync::SpinLock::~SpinLock ( )
inline

Destructor.

Note
If tasks are still waiting at destruction time it is considered a logical error (dangling waiters). An assertion is triggered in debug builds.
MISRA deviation: [STK-DEV-005] Rule 10-3-2.

Definition at line 66 of file stk_sync_spinlock.h.

67 {
68 STK_ASSERT(m_owner_tid == TID_NONE); // API contract: lock must not be destroyed while held
69 }
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:411

References m_owner_tid, STK_ASSERT, STK_VIRT_DTOR, and stk::TID_NONE.

Member Function Documentation

◆ Lock()

void stk::sync::SpinLock::Lock ( )
inlinevirtual

Acquire the lock.

Blocks until the low-level lock is available, then takes ownership. If the calling task already owns the lock, increments the recursion counter and returns immediately without re-acquiring.

Warning
ISR-unsafe.

Implements stk::IMutex.

Definition at line 111 of file stk_sync_spinlock.h.

112{
113 const TId current_tid = GetTid();
114
115 // increase recursion if this thread already owns the lock
116 if (!LockRecursively(current_tid))
117 {
118 m_lock.Lock();
119 MakeLocked(current_tid);
120 }
121}
TId GetTid()
Get task/thread Id of the calling task.
Definition stk_helper.h:243
Word TId
Definition stk_common.h:120
hw::SpinLock m_lock
low-level spin lock
bool LockRecursively(TId locking_tid)
void MakeLocked(TId locking_tid)

References stk::GetTid(), LockRecursively(), m_lock, and MakeLocked().

Referenced by stk_spinlock_lock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ LockRecursively()

bool stk::sync::SpinLock::LockRecursively ( TId locking_tid)
inlineprivate

Definition at line 171 of file stk_sync_spinlock.h.

172{
173 bool success = false;
174
175 if ((m_owner_tid == locking_tid) && (m_recursion_count != 0U))
176 {
177 STK_ASSERT(m_recursion_count < RECURSION_MAX); // API contract: caller must not exceed max recursion depth
178
180 success = true;
181 }
182
183 return success;
184}
static const uint16_t RECURSION_MAX
maximum nesting depth

References m_owner_tid, m_recursion_count, RECURSION_MAX, and STK_ASSERT.

Referenced by Lock(), and TryLock().

Here is the caller graph for this function:

◆ MakeLocked()

void stk::sync::SpinLock::MakeLocked ( TId locking_tid)
inlineprivate

Definition at line 190 of file stk_sync_spinlock.h.

191{
192 // kernel invariant: if either condition is false, the low-level lock and the
193 // recursion counter are out of sync, this is an internal defect, not a caller error
194 if ((m_owner_tid != TID_NONE) || (m_recursion_count != 0U))
195 {
197 }
198
199 m_owner_tid = locking_tid;
201 __stk_full_memfence();
202}
static __stk_forceinline void STK_KERNEL_PANIC(stk::EKernelPanicId id)
Called when the kernel detects an unrecoverable internal fault.
Definition stk_arch.h:75
@ KERNEL_PANIC_ASSERT
Internal assertion failed (maps from STK_ASSERT).
Definition stk_common.h:57

References stk::KERNEL_PANIC_ASSERT, m_owner_tid, m_recursion_count, stk::STK_KERNEL_PANIC(), and stk::TID_NONE.

Referenced by Lock(), and TryLock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ STK_NONCOPYABLE_CLASS()

stk::sync::SpinLock::STK_NONCOPYABLE_CLASS ( SpinLock )
private

References SpinLock().

Here is the call graph for this function:

◆ TryLock()

bool stk::sync::SpinLock::TryLock ( )
inline

Attempt to acquire the lock without blocking.

Returns
true if acquired (or already owned by the calling task); false if currently owned by another task.
Warning
ISR-unsafe.

Definition at line 127 of file stk_sync_spinlock.h.

128{
129 const TId current_tid = GetTid();
130 bool success = true;
131
132 // increase recursion if this thread already owns the lock
133 if (!LockRecursively(current_tid))
134 {
135 if (!m_lock.TryLock())
136 {
137 success = false;
138 }
139 else
140 {
141 MakeLocked(current_tid);
142 }
143 }
144
145 return success;
146}

References stk::GetTid(), LockRecursively(), m_lock, and MakeLocked().

Referenced by stk_spinlock_trylock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Unlock()

void stk::sync::SpinLock::Unlock ( )
inlinevirtual

Release the lock or decrement the recursion counter.

If the calling task holds the lock recursively, decrements the recursion counter and returns. On the final Unlock() the lock is fully released and becomes available to other tasks.

Warning
ISR-unsafe.

Implements stk::IMutex.

Definition at line 152 of file stk_sync_spinlock.h.

153{
154 STK_ASSERT(!hw::IsInsideISR()); // API contract: caller must not be in ISR
155 STK_ASSERT(m_owner_tid == GetTid()); // API contract: caller must own the lock
156 STK_ASSERT(m_recursion_count != 0U); // API contract: must have matching Lock()
157
158 if (--m_recursion_count == 0U)
159 {
161 __stk_full_memfence();
162
163 m_lock.Unlock();
164 }
165}
bool IsInsideISR()
Check whether the CPU is currently executing inside a hardware interrupt service routine (ISR).

References stk::GetTid(), stk::hw::IsInsideISR(), m_lock, m_owner_tid, m_recursion_count, STK_ASSERT, and stk::TID_NONE.

Referenced by stk_spinlock_unlock().

Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_lock

hw::SpinLock stk::sync::SpinLock::m_lock
private

low-level spin lock

Definition at line 104 of file stk_sync_spinlock.h.

Referenced by Lock(), TryLock(), and Unlock().

◆ m_owner_tid

TId stk::sync::SpinLock::m_owner_tid
private

thread id of the current owner

Definition at line 102 of file stk_sync_spinlock.h.

Referenced by LockRecursively(), MakeLocked(), SpinLock(), Unlock(), and ~SpinLock().

◆ m_recursion_count

uint16_t stk::sync::SpinLock::m_recursion_count
private

nesting depth

Definition at line 103 of file stk_sync_spinlock.h.

Referenced by LockRecursively(), MakeLocked(), SpinLock(), and Unlock().

◆ RECURSION_MAX

const uint16_t stk::sync::SpinLock::RECURSION_MAX = 0xFFFEU
staticprivate

maximum nesting depth

Definition at line 100 of file stk_sync_spinlock.h.

Referenced by LockRecursively().


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