SuperTinyKernel™ RTOS 1.07.x
Lightweight, high-performance, deterministic, bare-metal C++ RTOS for resource-constrained embedded systems. MIT Open Source License.
Loading...
Searching...
No Matches
stk_sync_semaphore.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_SEMAPHORE_H_
11#define STK_SYNC_SEMAPHORE_H_
12
13#include "stk_sync_cs.h"
14
18
19namespace stk {
20namespace sync {
21
55class Semaphore final : private SyncObjectBase, public ITraceable
56{
57public:
60 static const uint16_t COUNT_MAX = 0xFFFEU;
61
71 explicit Semaphore(uint16_t initial_count = 0U, uint16_t max_count = COUNT_MAX)
72 : m_count(initial_count), m_count_max(max_count)
73 {
74 STK_ASSERT(initial_count < max_count); // API contract: initial count must not exceed maximum
75 }
76
84 {
85 STK_ASSERT(m_wait_list.IsEmpty()); // API contract: must not be destroyed with waiting tasks
86 }
87
93 bool Wait(Timeout timeout_ticks = WAIT_INFINITE);
94
102 bool TryWait() { return Wait(NO_WAIT); }
103
109 void Signal();
110
117 uint16_t GetCount() const { return m_count; }
118
119private:
121
122 uint16_t m_count;
123 uint16_t m_count_max;
124};
125
126// ---------------------------------------------------------------------------
127// Wait
128// ---------------------------------------------------------------------------
129
130inline bool Semaphore::Wait(Timeout timeout_ticks)
131{
133 bool success = false;
134
135 // fast path: resource is available
136 if (m_count != 0U)
137 {
138 m_count = static_cast<uint16_t>(m_count - 1U);
139 __stk_full_memfence();
140 success = true;
141 }
142 // slow path: block until Signal() or timeout
143 else if (timeout_ticks != NO_WAIT)
144 {
145 STK_ASSERT(!hw::IsInsideISR()); // API contract: caller must not be in ISR if timeout_ticks!=NO_WAIT
146
147 // note: after waking, if not a timeout, we effectively own the resource that Signal() produced
148 // but didn't put into m_count (see logic of if (m_wait_list.IsEmpty()) in Signal())
149 success = (IKernelService::GetInstance()->Wait(this, &cs_, timeout_ticks) == WAIT_RESULT_SIGNAL);
150 }
151 // try lock behavior (timeout_ticks=NO_WAIT)
152 else
153 {
154 // success is false already, noop
155 }
156
157 return success;
158}
159
160// ---------------------------------------------------------------------------
161// Signal
162// ---------------------------------------------------------------------------
163
164inline void Semaphore::Signal()
165{
166 const ScopedCriticalSection cs_;
167
168 if (m_wait_list.IsEmpty())
169 {
170 STK_ASSERT(m_count < m_count_max); // API contract: the count must not exceed maximum
171
172 // no one is waiting, save signal for later
173 m_count = static_cast<uint16_t>(m_count + 1U);
174 __stk_full_memfence();
175 }
176 else
177 {
178 // give signal directly to the first waiting task
179 WakeOne();
180 }
181}
182
183} // namespace sync
184} // namespace stk
185
186#endif /* STK_SYNC_SEMAPHORE_H_ */
#define STK_NONCOPYABLE_CLASS(TYPE)
Disables copy construction and assignment for a class.
Definition stk_defs.h:622
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:430
#define STK_VIRT_DTOR
Makes destructors virtual and compliant to strict rules if STK_STRICT_COMPLIANCY=0.
Definition stk_defs.h:180
Implementation of synchronization primitive: stk::sync::ScopedCriticalSection.
Namespace of STK package.
static constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
Definition stk_common.h:214
@ WAIT_RESULT_SIGNAL
The wake was caused by a signal.
Definition stk_common.h:120
int32_t Timeout
Timeout time (ticks).
Definition stk_common.h:150
static constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
Definition stk_common.h:208
bool IsInsideISR()
Check whether the CPU is currently executing inside a hardware interrupt service routine (ISR).
Synchronization primitives for task coordination and resource protection.
Traceable object.
Definition stk_common.h:425
static IKernelService * GetInstance()
Get CPU-local instance of the kernel service.
virtual EWaitResult Wait(ISyncObject *sobj, IMutex *mutex, Timeout timeout)=0
Put calling process into a waiting state until synchronization object is signaled or timeout occurs.
SyncObjectBase()
Constructor.
Definition stk_helper.h:240
IWaitObject::ListHeadType m_wait_list
Tasks blocked on this object.
Definition stk_helper.h:263
void WakeOne() override
Wake the first task in the wait list (FIFO order).
Definition stk_helper.h:248
RAII-style low-level synchronization primitive for atomic code execution. Used as building brick for ...
Definition stk_sync_cs.h:54
void Signal()
Post a signal (increment counter).
uint16_t m_count_max
Counter max limit.
uint16_t m_count
Internal resource counter.
uint16_t GetCount() const
Get current counter value.
static const uint16_t COUNT_MAX
Max count value supported.
bool Wait(Timeout timeout_ticks=WAIT_INFINITE)
Wait for a signal (decrement counter).
Semaphore(uint16_t initial_count=0U, uint16_t max_count=COUNT_MAX)
Constructor.
bool TryWait()
Poll the semaphore without blocking (decrement counter if available).