SuperTinyKernel™ RTOS 1.05.3
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk_sync_mutex.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_MUTEX_H_
11#define STK_SYNC_MUTEX_H_
12
13#include "stk_sync_cs.h"
14
18
19namespace stk {
20namespace sync {
21
54class Mutex : public IMutex, public ITraceable, private ISyncObject
55{
56public:
60 {}
61
68 {
69 STK_ASSERT(m_wait_list.IsEmpty()); // API contract: must not be destroyed with waiting tasks
70 }
71
78 bool TimedLock(Timeout timeout);
79
83 void Lock() { (void)TimedLock(WAIT_INFINITE); }
84
89 bool TryLock() { return TimedLock(NO_WAIT); }
90
94 void Unlock();
95
96private:
98
99 static const uint16_t RECURSION_MAX = 0xFFFEu;
100
103};
104
105// ---------------------------------------------------------------------------
106// TimedLock
107// ---------------------------------------------------------------------------
108
109inline bool Mutex::TimedLock(Timeout timeout)
110{
111 STK_ASSERT(!hw::IsInsideISR()); // API contract: caller must not be in ISR
112
114 TId current_tid = svc->GetTid();
115
117
118 // already owned by the calling thread (recursive path)
119 if ((m_recursion_count != 0U) && (m_owner_tid == current_tid))
120 {
121 STK_ASSERT(m_recursion_count < RECURSION_MAX); // API contract: caller must not exceed max recursion depth
122
123 m_recursion_count = static_cast<uint16_t>(m_recursion_count + 1U);
124 return true;
125 }
126
127 // mutex is free (fast path)
128 if (m_recursion_count == 0U)
129 {
130 // kernel invariant: counter is zero so owner must be TID_NONE
131 if (m_owner_tid != TID_NONE)
133
135 m_owner_tid = current_tid;
136 __stk_full_memfence();
137
138 return true;
139 }
140
141 // try lock behavior
142 if (timeout == NO_WAIT)
143 return false;
144
145 // mutex owned by another thread (slow path/blocking)
146 if (svc->Wait(this, &cs_, timeout)->IsTimeout())
147 return false;
148
149 // kernel invariant: if either condition is false, the low-level lock and the
150 // recursion counter are out of sync, this is an internal defect, not a caller error
151 if ((m_owner_tid != current_tid) || (m_recursion_count != 1U))
153
154 return true;
155}
156
157// ---------------------------------------------------------------------------
158// Unlock
159// ---------------------------------------------------------------------------
160
161inline void Mutex::Unlock()
162{
163 STK_ASSERT(!hw::IsInsideISR()); // API contract: caller must not be in ISR
164 STK_ASSERT(m_owner_tid == GetTid()); // API contract: caller must own the lock
165 STK_ASSERT(m_recursion_count != 0U); // API contract: must have matching Lock()
166
168
169 m_recursion_count = static_cast<uint16_t>(m_recursion_count - 1U);
170
171 if (m_recursion_count == 0U)
172 {
173 if (!m_wait_list.IsEmpty())
174 {
175 // pass ownership directly to the first waiter (FIFO order)
176 IWaitObject *waiter = static_cast<IWaitObject *>(m_wait_list.GetFirst());
177
178 // transfer ownership to the waiter
180 m_owner_tid = waiter->GetTid();
181 __stk_full_memfence();
182
183 waiter->Wake(false);
184 }
185 else
186 {
187 // free completely if there are no waiters
189 __stk_full_memfence();
190 }
191 }
192}
193
194} // namespace sync
195} // namespace stk
196
197#endif /* STK_SYNC_MUTEX_H_ */
#define STK_KERNEL_PANIC(id)
Called when the kernel detects an unrecoverable internal fault.
Definition stk_arch.h:63
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:330
Implementation of synchronization primitive: stk::sync::ScopedCriticalSection.
Namespace of STK package.
const Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
Definition stk_common.h:139
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:133
const Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
Definition stk_common.h:145
TId GetTid()
Get task/thread Id of the calling task.
Definition stk_helper.h:217
Word TId
Definition stk_common.h:117
const TId TID_NONE
Reserved task/thread id representing zero/none thread id.
Definition stk_common.h:128
@ KERNEL_PANIC_ASSERT
Internal assertion failed (maps from STK_ASSERT).
Definition stk_common.h:56
bool IsInsideISR()
Check whether the CPU is currently executing inside a hardware interrupt service routine (ISR).
Definition stktest.cpp:103
Synchronization primitives for task coordination and resource protection.
Wait object.
Definition stk_common.h:212
virtual TId GetTid() const =0
Get thread Id of this task.
virtual bool IsTimeout() const =0
Check if task woke up due to a timeout.
virtual void Wake(bool timeout)=0
Wake task.
Traceable object.
Definition stk_common.h:255
IWaitObject::ListHeadType m_wait_list
tasks blocked on this object
Definition stk_common.h:373
ISyncObject()
Constructor.
Definition stk_common.h:350
Interface for mutex synchronization primitive.
Definition stk_common.h:381
Interface for the kernel services exposed to the user processes during run-time when Kernel started s...
Definition stk_common.h:929
virtual TId GetTid() const =0
Get thread Id of the currently running task.
static IKernelService * GetInstance()
Get CPU-local instance of the kernel service.
Definition stktest.cpp:69
virtual IWaitObject * Wait(ISyncObject *sobj, IMutex *mutex, Timeout timeout)=0
Put calling process into a waiting state until synchronization object is signaled or timeout occurs.
RAII-style low-level synchronization primitive for atomic code execution. Used as building brick for ...
Definition stk_sync_cs.h:54
TId m_owner_tid
thread id of the current owner
~Mutex()
Destructor.
void Unlock()
Release lock.
Mutex()
Constructor.
bool TryLock()
Acquire the lock.
void Lock()
Acquire lock.
uint16_t m_recursion_count
recursion depth
STK_NONCOPYABLE_CLASS(Mutex)
bool TimedLock(Timeout timeout)
Acquire lock.
static const uint16_t RECURSION_MAX
maximum nesting depth