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_sync_spinlock.h
Go to the documentation of this file.
1/*
2 * SuperTinyKernel(TM) RTOS: Lightweight High-Performance Deterministic C++ RTOS for Embedded Systems.
3 *
4 * Source: https://github.com/SuperTinyKernel-RTOS
5 *
6 * Copyright (c) 2022-2026 Neutron Code Limited <stk@neutroncode.com>. All Rights Reserved.
7 * License: MIT License, see LICENSE for a full text.
8 */
9
10#ifndef STK_SYNC_SPINLOCK_H_
11#define STK_SYNC_SPINLOCK_H_
12
13#include "stk_helper.h"
14
18
19namespace stk {
20namespace sync {
21
53class SpinLock final : public IMutex
54{
55public:
60
67 {
68 STK_ASSERT(m_owner_tid == TID_NONE); // API contract: lock must not be destroyed while held
69 }
70
77 void Lock();
78
84 bool TryLock();
85
92 void Unlock();
93
94private:
96
97 bool LockRecursively(TId locking_tid);
98 void MakeLocked(TId locking_tid);
99
100 static const uint16_t RECURSION_MAX = 0xFFFEU;
101
105};
106
107// ---------------------------------------------------------------------------
108// Lock
109// ---------------------------------------------------------------------------
110
111inline void SpinLock::Lock()
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}
122
123// ---------------------------------------------------------------------------
124// TryLock
125// ---------------------------------------------------------------------------
126
127inline bool SpinLock::TryLock()
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}
147
148// ---------------------------------------------------------------------------
149// Unlock
150// ---------------------------------------------------------------------------
151
152inline void SpinLock::Unlock()
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}
166
167// ---------------------------------------------------------------------------
168// LockRecursively
169// ---------------------------------------------------------------------------
170
171inline bool SpinLock::LockRecursively(TId locking_tid)
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}
185
186// ---------------------------------------------------------------------------
187// MakeLocked
188// ---------------------------------------------------------------------------
189
190inline void SpinLock::MakeLocked(TId locking_tid)
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}
203
204} // namespace sync
205} // namespace stk
206
207#endif /* STK_SYNC_SPINLOCK_H_ */
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:455
#define STK_VIRT_DTOR
Makes destructors virtual and compliant to strict rules if STK_STRICT_COMPLIANCY=0.
Definition stk_defs.h:202
Contains helper implementations which simplify user-side code.
Namespace of STK package.
static __stk_forceinline void STK_KERNEL_PANIC(stk::EKernelPanicId id)
Called when the kernel detects an unrecoverable internal fault.
Definition stk_arch.h:75
static TId GetTid()
Get task/thread Id of the calling task.
Definition stk_helper.h:359
static constexpr TId TID_NONE
Reserved task/thread id representing zero/none thread id.
Definition stk_common.h:202
Word TId
Task (thread) id.
Definition stk_common.h:145
@ KERNEL_PANIC_ASSERT
Internal assertion failed (maps from STK_ASSERT).
Definition stk_common.h:62
bool IsInsideISR()
Check whether the CPU is currently executing inside a hardware interrupt service routine (ISR).
Synchronization primitives for task coordination and resource protection.
Atomic busy-wait lock used as the global cross-core synchronisation primitive inside CriticalSection.
Definition stk_arch.h:462
Interface for mutex synchronization primitive.
Definition stk_common.h:677
static const uint16_t RECURSION_MAX
maximum nesting depth
STK_NONCOPYABLE_CLASS(SpinLock)
void Unlock()
Release the lock or decrement the recursion counter.
uint16_t m_recursion_count
nesting depth
hw::SpinLock m_lock
low-level spin lock
bool LockRecursively(TId locking_tid)
TId m_owner_tid
thread id of the current owner
bool TryLock()
Attempt to acquire the lock without blocking.
void MakeLocked(TId locking_tid)
void Lock()
Acquire the lock.
SpinLock()
Construct a SpinLock in the unlocked state.
STK_VIRT_DTOR ~SpinLock()
Destructor.