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::Semaphore Class Referencefinal

Counting semaphore primitive for resource management and signaling. More...

#include <stk_sync_semaphore.h>

Inheritance diagram for stk::sync::Semaphore:
Collaboration diagram for stk::sync::Semaphore:

Public Member Functions

 Semaphore (uint16_t initial_count=0U, uint16_t max_count=COUNT_MAX)
 Constructor.
 ~Semaphore ()
 Destructor.
bool Wait (Timeout timeout_ticks=WAIT_INFINITE)
 Wait for a signal (decrement counter).
bool TryWait ()
 Poll the semaphore without blocking (decrement counter if available).
void Signal ()
 Post a signal (increment counter).
uint16_t GetCount () const
 Get current counter value.
void SetTraceName (const char *name)
 Set name.
const char * GetTraceName () const
 Get name.

Static Public Attributes

static const uint16_t COUNT_MAX = 0xFFFEU
 Max count value supported.

Private Types

typedef DLHeadType ListHeadType
 List head type for ISyncObject elements.
typedef DLEntryType ListEntryType
 List entry type of ISyncObject elements.
enum  
 A tag for type-safe casts done by CastListEntryToParent. More...
typedef DListEntry< ISyncObject, TClosedLoop > DLEntryType
 Convenience alias for this entry type. Used to avoid repeating the full template spelling.
typedef DListHead< ISyncObject, TClosedLoop > DLHeadType
 Convenience alias for the corresponding list head type.

Private Member Functions

 Semaphore (const Semaphore &)=delete
Semaphoreoperator= (const Semaphore &)=delete
virtual void AddWaitObject (IWaitObject *wobj)
 Called by kernel when a new task starts waiting on this event.
virtual void RemoveWaitObject (IWaitObject *wobj)
 Called by kernel when a waiting task is being removed (timeout expired, wait aborted, task terminated etc.).
virtual bool Tick (Timeout elapsed_ticks)
 Called by kernel on every system tick to handle timeout logic of waiting tasks.
Weight FindWeightHigherThan (Weight comp) const
 Find higher weight within linked wait objects.
virtual void WakeOne ()
 Wake the first task in the wait list (FIFO order).
virtual void WakeAll ()
 Wake all tasks currently in the wait list.
IWaitObject::ListHeadTypeGetWaitList ()
DLHeadTypeGetHead ()
 Get the list head this entry currently belongs to.
DLEntryTypeGetNext ()
 Get the next entry in the list.
DLEntryTypeGetPrev ()
 Get the previous entry in the list.
bool IsLinked () const
 Check whether this entry is currently a member of any list.
 operator ISyncObject * ()
 Implicit conversion to a mutable pointer to the host object (T).
 operator const ISyncObject * () const
 Implicit conversion to a const pointer to the host object (T).
void Link (DLHeadType *head, DLEntryType *next, DLEntryType *prev)
 Wire this entry into a list between prev and next.
void Unlink ()
 Remove this entry from its current list.

Static Private Member Functions

static void AddWaitObject (IWaitObject::ListHeadType &wlist, IWaitObject *wobj)
 Called by kernel when a new task starts waiting on this event.
static void RemoveWaitObject (IWaitObject::ListHeadType &wlist, IWaitObject *wobj)
 Called by kernel when a waiting task is being removed (timeout expired, wait aborted, task terminated etc.).
static void WakeOne (IWaitObject::ListHeadType &wlist)
 Wake the first task in the wait list (FIFO order).
static void WakeAll (IWaitObject::ListHeadType &wlist)
 Wake all tasks currently in the wait list.

Private Attributes

uint16_t m_count
 Internal resource counter.
uint16_t m_count_max
 Counter max limit.
IWaitObject::ListHeadType m_wait_list
 tasks blocked on this object
DLHeadTypem_head
 Owning list head, or NULL when the entry is not linked.
DLEntryTypem_next
 Next entry in the list, or NULL (open list boundary) / first entry (closed loop).
DLEntryTypem_prev
 Previous entry in the list, or NULL (open list boundary) / last entry (closed loop).

Detailed Description

Counting semaphore primitive for resource management and signaling.

Counting semaphore maintains an internal counter to manage access to a limited number of resources. Unlike a Condition Variable, a Semaphore is stateful: if Signal() is called when no tasks are waiting, the signal is "remembered" by incrementing the internal counter.

Note
This implementation uses a Direct Handover policy: when a task is waiting, Signal() gives the resource "token" directly to the first task in the wait list without incrementing the counter. The waking task is then guaranteed ownership of that token upon returning from Wait().
// Example: Resource throttling
// Initialize with 3 permits (e.g., max 3 concurrent tasks accessing the same resource)
stk::sync::Semaphore g_Limiter(3);
void Worker() {
// attempt to acquire a permit with a 1000 tick timeout
if (g_Limiter.Wait(1000)) {
// ... access limited resource ...
// release the permit back to the semaphore
g_Limiter.Signal();
}
}
Counting semaphore primitive for resource management and signaling.
See also
ISyncObject, IWaitObject, IKernelService::Wait
Note
Only available when kernel is compiled with KERNEL_SYNC mode enabled.

Definition at line 55 of file stk_sync_semaphore.h.

Member Typedef Documentation

◆ DLEntryType

typedef DListEntry<ISyncObject, TClosedLoop> stk::util::DListEntry< ISyncObject, TClosedLoop >::DLEntryType
inherited

Convenience alias for this entry type. Used to avoid repeating the full template spelling.

Definition at line 75 of file stk_linked_list.h.

◆ DLHeadType

typedef DListHead<ISyncObject, TClosedLoop> stk::util::DListEntry< ISyncObject, TClosedLoop >::DLHeadType
inherited

Convenience alias for the corresponding list head type.

Definition at line 80 of file stk_linked_list.h.

◆ ListEntryType

List entry type of ISyncObject elements.

Definition at line 469 of file stk_common.h.

◆ ListHeadType

List head type for ISyncObject elements.

Definition at line 464 of file stk_common.h.

Member Enumeration Documentation

◆ anonymous enum

anonymous enum
inherited

A tag for type-safe casts done by CastListEntryToParent.

See also
CastListEntryToParent.

Definition at line 70 of file stk_linked_list.h.

70{ DLEntryTag = 1 };
Intrusive doubly-linked list node. Embed this as a base class in any object (T) that needs to partici...

Constructor & Destructor Documentation

◆ Semaphore() [1/2]

stk::sync::Semaphore::Semaphore ( uint16_t initial_count = 0U,
uint16_t max_count = COUNT_MAX )
inlineexplicit

Constructor.

Initializes the semaphore with a specific count and maximum limit. Setting initial_count to a non-zero value allows for immediate resource acquisition.

Parameters
[in]initial_countStarting value of the internal counter (available permits).
[in]max_countMaximum value the counter is allowed to reach.
Precondition
initial_count <= max_count.
Note
Triggers an assertion in a debug build if initial_count exceeds max_count.

Definition at line 71 of file stk_sync_semaphore.h.

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 }
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:409
uint16_t m_count_max
Counter max limit.
uint16_t m_count
Internal resource counter.

References COUNT_MAX, m_count, m_count_max, and STK_ASSERT.

Referenced by operator=().

Here is the caller graph for this function:

◆ ~Semaphore()

stk::sync::Semaphore::~Semaphore ( )
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 83 of file stk_sync_semaphore.h.

84 {
85 STK_ASSERT(m_wait_list.IsEmpty()); // API contract: must not be destroyed with waiting tasks
86 }
IWaitObject::ListHeadType m_wait_list
tasks blocked on this object
Definition stk_common.h:605

References stk::ISyncObject::m_wait_list, STK_ASSERT, and STK_VIRT_DTOR.

◆ Semaphore() [2/2]

stk::sync::Semaphore::Semaphore ( const Semaphore & )
privatedelete

Member Function Documentation

◆ AddWaitObject() [1/2]

virtual void stk::ISyncObject::AddWaitObject ( IWaitObject * wobj)
inlinevirtualinherited

Called by kernel when a new task starts waiting on this event.

Parameters
[in]wobjWait object representing blocked task.
Note
Must be called inside the critical section (see hw::CriticalSection, sync::ScopedCrticalSection).

Definition at line 485 of file stk_common.h.

486 {
488 }
static void AddWaitObject(IWaitObject::ListHeadType &wlist, IWaitObject *wobj)
Called by kernel when a new task starts waiting on this event.
Definition stk_common.h:475

References AddWaitObject(), and m_wait_list.

Here is the call graph for this function:

◆ AddWaitObject() [2/2]

void stk::ISyncObject::AddWaitObject ( IWaitObject::ListHeadType & wlist,
IWaitObject * wobj )
inlinestaticinherited

Called by kernel when a new task starts waiting on this event.

Parameters
[in]wobjWait object representing blocked task.
Note
Utility for AddWaitObject and ARM TrustZone support.

Definition at line 475 of file stk_common.h.

476 {
477 STK_ASSERT(wobj->GetHead() == nullptr);
478 wlist.LinkBack(wobj);
479 }

References stk::util::DListEntry< T, TClosedLoop >::GetHead(), stk::util::DListHead< T, TClosedLoop >::LinkBack(), and STK_ASSERT.

Referenced by AddWaitObject(), and stk::Kernel< TMode, TSize, TStrategy, TPlatform >::KernelTask::WaitObject::SetupWait().

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

◆ FindWeightHigherThan()

Weight stk::ISyncObject::FindWeightHigherThan ( Weight comp) const
inlineinherited

Find higher weight within linked wait objects.

Implementation of ISyncObject::Tick, see ISyncObject. Placed here as it depends on GetUserTaskFromTid.

Parameters
[in]compWeight to compare with.
Returns
Higher weight value than comp, or NO_WEIGHT if there is no object with a higher weight.
Note
Must be called inside the critical section (see hw::CriticalSection, sync::ScopedCrticalSection).

Definition at line 208 of file stk_helper.h.

209{
210 Weight max_weight = NO_WEIGHT;
211 const IWaitObject *itr = util::DListCast::ListEntryToParent<const IWaitObject>(m_wait_list.GetFirst());
212
213 while (itr != nullptr)
214 {
215 const Weight w = GetUserTaskFromTid(itr->GetTid())->GetWeight();
216 if (w > max_weight)
217 {
218 max_weight = w;
219 }
220
222 }
223
224 return ((max_weight > comp) ? max_weight : NO_WEIGHT);
225}
static constexpr ITask * GetUserTaskFromTid(TId task_id) noexcept
Get task instance from its identifier.
Definition stk_arch.h:532
constexpr Weight NO_WEIGHT
Weight value: weight is not set.
Definition stk_common.h:215
int32_t Weight
Weight value (aka priority).
Definition stk_common.h:166
virtual Weight GetWeight() const
Get static base weight of the task.
Definition stk_common.h:722
static __stk_forceinline TTargetType * ListEntryToParent(TSourceType *const lentry)
Safely casts an intrusive list entry to its concrete parent container object type.

References stk::util::DListEntry< T, TClosedLoop >::GetNext(), stk::IWaitObject::GetTid(), stk::GetUserTaskFromTid(), stk::ITask::GetWeight(), stk::util::DListCast::ListEntryToParent(), m_wait_list, and stk::NO_WEIGHT.

Referenced by stk::Kernel< stk::KERNEL_DYNAMIC|stk::KERNEL_SYNC|stk::KERNEL_TICKLESS,(16U), stk::SwitchStrategyFP32, stk::PlatformDefault >::OnRestoreWeight(), and stk::sync::Mutex::Unlock().

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

◆ GetCount()

uint16_t stk::sync::Semaphore::GetCount ( ) const
inline

Get current counter value.

Returns
Advisory snapshot of the counter. May be stale by the time the caller acts on it. Atomic on 32-bit aligned targets.
Note
ISR-safe on targets where a 32-bit aligned read is a single instruction (all supported STK architectures). Not safe for read-modify-write use.

Definition at line 117 of file stk_sync_semaphore.h.

117{ return m_count; }

References m_count.

Referenced by osSemaphoreGetCount(), stk_sem_get_count(), uxSemaphoreGetCount(), xQueueAddToSet(), xQueueRemoveFromSet(), xSemaphoreGive(), xSemaphoreGiveFromISR(), and xTaskNotifyStateClearIndexed().

Here is the caller graph for this function:

◆ GetHead()

DLHeadType * stk::util::DListEntry< ISyncObject, TClosedLoop >::GetHead ( )
inlineinherited

Get the list head this entry currently belongs to.

Returns
Pointer to the owning DListHead, or NULL if the entry is not linked.

Definition at line 85 of file stk_linked_list.h.

85{ return m_head; }

◆ GetNext()

DLEntryType * stk::util::DListEntry< ISyncObject, TClosedLoop >::GetNext ( )
inlineinherited

Get the next entry in the list.

Returns
Pointer to the next DListEntry, or NULL if this is the last entry (open list) or the first entry (closed loop, where next wraps to first).
Note
In a closed loop (TClosedLoop == true) this pointer is never NULL when the entry is linked.

Definition at line 98 of file stk_linked_list.h.

98{ return m_next; }

◆ GetPrev()

DLEntryType * stk::util::DListEntry< ISyncObject, TClosedLoop >::GetPrev ( )
inlineinherited

Get the previous entry in the list.

Returns
Pointer to the previous DListEntry, or NULL if this is the first entry (open list) or the last entry (closed loop, where prev wraps to last).
Note
In a closed loop (TClosedLoop == true) this pointer is never NULL when the entry is linked.

Definition at line 114 of file stk_linked_list.h.

114{ return m_prev; }

◆ GetTraceName()

const char * stk::ITraceable::GetTraceName ( ) const
inlineinherited

Get name.

Returns
Name string, or NULL if not set or if STK_SYNC_DEBUG_NAMES is 0.

Definition at line 433 of file stk_common.h.

434 {
435 #if STK_SYNC_DEBUG_NAMES
436 return m_trace_name;
437 #else
438 return nullptr;
439 #endif
440 }

◆ GetWaitList()

IWaitObject::ListHeadType & stk::ISyncObject::GetWaitList ( )
inlineprotectedinherited

Definition at line 600 of file stk_common.h.

601 {
602 return m_wait_list;
603 }

References m_wait_list.

◆ IsLinked()

bool stk::util::DListEntry< ISyncObject, TClosedLoop >::IsLinked ( ) const
inlineinherited

Check whether this entry is currently a member of any list.

Returns
true if linked (m_head != NULL); false otherwise.

Definition at line 127 of file stk_linked_list.h.

127{ return (GetHead() != nullptr); }

◆ Link()

void stk::util::DListEntry< ISyncObject, TClosedLoop >::Link ( DLHeadType * head,
DLEntryType * next,
DLEntryType * prev )
inlineprivateinherited

Wire this entry into a list between prev and next.

Parameters
[in]headThe owning DListHead. Stored as a back-pointer for IsLinked() and ownership checks.
[in]nextThe entry that will follow this one, or NULL if this becomes the last entry.
[in]prevThe entry that will precede this one, or NULL if this becomes the first entry.
Note
Called exclusively by DListHead::Link(). Assumes the entry is not currently linked. Updates the neighbours' forward/back pointers to splice this entry in.

Definition at line 162 of file stk_linked_list.h.

163 {
164 m_head = head;
165 m_next = next;
166 m_prev = prev;
167
168 if (m_prev != nullptr)
169 {
170 m_prev->m_next = this;
171 }
172
173 if (m_next != nullptr)
174 {
175 m_next->m_prev = this;
176 }
177 }
DLEntryType * m_next
Next entry in the list, or NULL (open list boundary) / first entry (closed loop).
DLEntryType * m_prev
Previous entry in the list, or NULL (open list boundary) / last entry (closed loop).

◆ operator const ISyncObject *()

stk::util::DListEntry< ISyncObject, TClosedLoop >::operator const ISyncObject * ( ) const
inlineinherited

Implicit conversion to a const pointer to the host object (T).

Note
Safe because T must derive from DListEntry<T, TClosedLoop>. Eliminates the need for explicit static_cast at call sites.
MISRA deviation: [STK-DEV-004] Rule 5-2-x.

Definition at line 141 of file stk_linked_list.h.

141{ return static_cast<const T *>(this); }

◆ operator ISyncObject *()

stk::util::DListEntry< ISyncObject, TClosedLoop >::operator ISyncObject* ( )
inlineinherited

Implicit conversion to a mutable pointer to the host object (T).

Note
Safe because T must derive from DListEntry<T, TClosedLoop>. Eliminates the need for explicit static_cast at call sites.
MISRA deviation: [STK-DEV-004] Rule 5-2-x.

Definition at line 134 of file stk_linked_list.h.

134{ return static_cast<T *>(this); }

◆ operator=()

Semaphore & stk::sync::Semaphore::operator= ( const Semaphore & )
privatedelete

References Semaphore().

Here is the call graph for this function:

◆ RemoveWaitObject() [1/2]

virtual void stk::ISyncObject::RemoveWaitObject ( IWaitObject * wobj)
inlinevirtualinherited

Called by kernel when a waiting task is being removed (timeout expired, wait aborted, task terminated etc.).

Parameters
[in]wobjWait object to remove from the wait list.
Note
Must be called inside the critical section (see hw::CriticalSection, sync::ScopedCrticalSection).

Reimplemented in stk::sync::Event.

Definition at line 504 of file stk_common.h.

505 {
507 }
static void RemoveWaitObject(IWaitObject::ListHeadType &wlist, IWaitObject *wobj)
Called by kernel when a waiting task is being removed (timeout expired, wait aborted,...
Definition stk_common.h:494

References m_wait_list, and RemoveWaitObject().

Here is the call graph for this function:

◆ RemoveWaitObject() [2/2]

void stk::ISyncObject::RemoveWaitObject ( IWaitObject::ListHeadType & wlist,
IWaitObject * wobj )
inlinestaticinherited

Called by kernel when a waiting task is being removed (timeout expired, wait aborted, task terminated etc.).

Parameters
[in]wobjWait object to remove from the wait list.
Note
Utility for AddWaitObject and ARM TrustZone support.

Definition at line 494 of file stk_common.h.

495 {
496 STK_ASSERT(wobj->GetHead() == &wlist);
497 wlist.Unlink(wobj);
498 }

References stk::util::DListEntry< T, TClosedLoop >::GetHead(), STK_ASSERT, and stk::util::DListHead< T, TClosedLoop >::Unlink().

Referenced by RemoveWaitObject(), and stk::sync::Event::RemoveWaitObject().

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

◆ SetTraceName()

void stk::ITraceable::SetTraceName ( const char * name)
inlineinherited

Set name.

Parameters
[in]nameNull-terminated string or NULL.
Note
If STK_SYNC_DEBUG_NAMES is 0 then calling this function has no effect.

Definition at line 421 of file stk_common.h.

422 {
423 #if STK_SYNC_DEBUG_NAMES
424 m_trace_name = name;
425 #else
426 STK_UNUSED(name);
427 #endif
428 }
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
Definition stk_defs.h:608

References STK_UNUSED.

Referenced by stk::memory::BlockMemoryPool::BlockMemoryPool(), and stk::memory::BlockMemoryPool::BlockMemoryPool().

Here is the caller graph for this function:

◆ Signal()

void stk::sync::Semaphore::Signal ( )
inline

Post a signal (increment counter).

Note
Gives "token" directly to the waking task. The count is not incremented, and the waking task does not decrement it.
ISR-safe.

Definition at line 164 of file stk_sync_semaphore.h.

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}
virtual void WakeOne()
Wake the first task in the wait list (FIFO order).
Definition stk_common.h:576

References m_count, m_count_max, stk::ISyncObject::m_wait_list, STK_ASSERT, and stk::ISyncObject::WakeOne().

Referenced by stk_sem_signal(), xSemaphoreGive(), xSemaphoreGiveFromISR(), xTaskNotifyAndQueryIndexed(), xTaskNotifyGiveIndexed(), and xTaskNotifyIndexed().

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

◆ Tick()

bool stk::ISyncObject::Tick ( Timeout elapsed_ticks)
inlinevirtualinherited

Called by kernel on every system tick to handle timeout logic of waiting tasks.

Implementation of ISyncObject::Tick, see ISyncObject. Placed here as it depends on hw namespace.

Parameters
[in]elapsed_ticksNumber of ticks elapsed between this and previous calls, in case of KERNEL_TICKLESS mode this value can be >1, for non-tickless mode it is always 1.
Returns
true if this synchronization object still has waiters with a finite timeout and requires further tick calls. false if the wait list is empty or all remaining waiters have infinite timeouts, signaling to the kernel that it may stop calling Tick() for this object until a new waiter is added.
Note
When this method returns false, the kernel unlinks this object from its active sync list. It will be re-linked automatically when the next waiter is added via AddWaitObject().
Does not need to be called inside critical section.

Definition at line 175 of file stk_helper.h.

176{
177 // note: ScopedCriticalSection usage
178 //
179 // Single-core: no critical section needed - Tick() runs inside the
180 // SysTick ISR which already executes with interrupts disabled, making
181 // re-entrancy impossible on the local core.
182 //
183 // Multi-core: critical section is required because the tick handler on
184 // each core may call Tick() concurrently for the same Semaphore instance,
185 // and ISyncObject::Tick() is not re-entrant.
186#if (STK_ARCH_CPU_COUNT > 1)
187 hw::CriticalSection::ScopedLock cs_;
188#endif
189
191
192 while (itr != nullptr)
193 {
194 IWaitObject *const next = util::DListCast::ListEntryToParent<IWaitObject>(itr->GetNext());
195
196 if (!itr->Tick(elapsed_ticks))
197 {
198 itr->Wake(true);
199 }
200
201 itr = next;
202 }
203
204 return !m_wait_list.IsEmpty();
205}

References stk::util::DListEntry< T, TClosedLoop >::GetNext(), stk::util::DListCast::ListEntryToParent(), m_wait_list, stk::IWaitObject::Tick(), and stk::IWaitObject::Wake().

Here is the call graph for this function:

◆ TryWait()

bool stk::sync::Semaphore::TryWait ( )
inline

Poll the semaphore without blocking (decrement counter if available).

Checks if a resource token is available. If so, decrements the counter and returns immediately without yielding the CPU or touching the kernel wait list. If the counter is zero, returns immediately with false.

Note
ISR-safe.
Returns
true if a resource token was acquired, false if count was zero.

Definition at line 102 of file stk_sync_semaphore.h.

102{ return Wait(NO_WAIT); }
constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
Definition stk_common.h:210
bool Wait(Timeout timeout_ticks=WAIT_INFINITE)
Wait for a signal (decrement counter).

References stk::NO_WAIT, and Wait().

Referenced by stk_sem_trywait(), xSemaphoreTakeFromISR(), and xTaskNotifyStateClearIndexed().

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

◆ Unlink()

void stk::util::DListEntry< ISyncObject, TClosedLoop >::Unlink ( )
inlineprivateinherited

Remove this entry from its current list.

Note
Called exclusively by DListHead::Unlink(). Patches the neighbours' pointers to bridge over this entry, then clears m_head, m_next, and m_prev to NULL so the entry is in a clean unlinked state.
Does not update DListHead::m_count or m_first / m_last — those are the responsibility of the calling DListHead::Unlink().

Definition at line 186 of file stk_linked_list.h.

187 {
188 if (m_prev != nullptr)
189 {
191 }
192
193 if (m_next != nullptr)
194 {
196 }
197
198 m_head = nullptr;
199 m_next = nullptr;
200 m_prev = nullptr;
201 }

◆ Wait()

bool stk::sync::Semaphore::Wait ( Timeout timeout_ticks = WAIT_INFINITE)
inline

Wait for a signal (decrement counter).

Parameters
[in]timeout_ticksMaximum time to wait (ticks).
Warning
ISR-safe only with timeout = NO_WAIT, ISR-unsafe otherwise.
Returns
True if acquired, false if timeout occurred.

Definition at line 130 of file stk_sync_semaphore.h.

131{
132 ScopedCriticalSection cs_;
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}
@ WAIT_RESULT_SIGNAL
The wake was caused by a signal.
Definition stk_common.h:125
bool IsInsideISR()
Check whether the CPU is currently executing inside a hardware interrupt service routine (ISR).
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.

References stk::IKernelService::GetInstance(), stk::hw::IsInsideISR(), m_count, stk::NO_WAIT, STK_ASSERT, stk::IKernelService::Wait(), and stk::WAIT_RESULT_SIGNAL.

Referenced by osSemaphoreAcquire(), stk_sem_wait(), TryWait(), ulTaskNotifyTakeIndexed(), xSemaphoreTake(), and xTaskNotifyWaitIndexed().

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

◆ WakeAll() [1/2]

virtual void stk::ISyncObject::WakeAll ( )
inlineprotectedvirtualinherited

Wake all tasks currently in the wait list.

Note
Each woken task is notified with timeout=false, indicating a successful signal (not a timeout expiry).
Does nothing if no tasks are currently waiting.
Must be called inside the critical section (see hw::CriticalSection, sync::ScopedCrticalSection).

Definition at line 591 of file stk_common.h.

592 {
593 #ifdef _STK_CORTEX_M_TRUSTZONE_NON_SECURE
594 NSC_stk_ISyncObject_WakeAll(this);
595 #else
597 #endif
598 }
virtual void WakeAll()
Wake all tasks currently in the wait list.
Definition stk_common.h:591

References m_wait_list, and WakeAll().

Referenced by stk::sync::ConditionVariable::NotifyAll_CS(), stk::sync::Event::Pulse(), stk::sync::Event::Set(), and WakeAll().

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

◆ WakeAll() [2/2]

void stk::ISyncObject::WakeAll ( IWaitObject::ListHeadType & wlist)
inlinestaticinherited

Wake all tasks currently in the wait list.

Note
Each woken task is notified with timeout=false, indicating a successful signal (not a timeout expiry).
Does nothing if no tasks are currently waiting.
Utility for AddWaitObject and ARM TrustZone support.

Definition at line 550 of file stk_common.h.

551 {
552 while (IWaitObject *const obj = util::DListCast::ListEntryToParent<IWaitObject>(wlist.GetFirst()))
553 {
554 obj->Wake(false);
555 }
556 }

References stk::util::DListHead< T, TClosedLoop >::GetFirst(), and stk::util::DListCast::ListEntryToParent().

Here is the call graph for this function:

◆ WakeOne() [1/2]

virtual void stk::ISyncObject::WakeOne ( )
inlineprotectedvirtualinherited

Wake the first task in the wait list (FIFO order).

Note
The woken task is notified with timeout=false, indicating a successful signal (not a timeout expiry).
Does nothing if no tasks are currently waiting.
Must be called inside the critical section (see hw::CriticalSection, sync::ScopedCrticalSection).

Definition at line 576 of file stk_common.h.

577 {
578 #ifdef _STK_CORTEX_M_TRUSTZONE_NON_SECURE
579 NSC_stk_ISyncObject_WakeOne(this);
580 #else
582 #endif
583 }

References m_wait_list, and WakeOne().

Referenced by stk::sync::ConditionVariable::NotifyOne_CS(), stk::sync::Event::Pulse(), stk::sync::Event::Set(), stk::sync::Semaphore::Signal(), and WakeOne().

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

◆ WakeOne() [2/2]

void stk::ISyncObject::WakeOne ( IWaitObject::ListHeadType & wlist)
inlinestaticinherited

Wake the first task in the wait list (FIFO order).

Note
The woken task is notified with timeout=false, indicating a successful signal (not a timeout expiry).
Does nothing if no tasks are currently waiting.
Utility for AddWaitObject and ARM TrustZone support.

Definition at line 536 of file stk_common.h.

537 {
538 if (IWaitObject *const obj = util::DListCast::ListEntryToParent<IWaitObject>(wlist.GetFirst()))
539 {
540 obj->Wake(false);
541 }
542 }

References stk::util::DListHead< T, TClosedLoop >::GetFirst(), and stk::util::DListCast::ListEntryToParent().

Here is the call graph for this function:

Member Data Documentation

◆ COUNT_MAX

const uint16_t stk::sync::Semaphore::COUNT_MAX = 0xFFFEU
static

◆ m_count

uint16_t stk::sync::Semaphore::m_count
private

Internal resource counter.

Definition at line 122 of file stk_sync_semaphore.h.

Referenced by GetCount(), Semaphore(), Signal(), and Wait().

◆ m_count_max

uint16_t stk::sync::Semaphore::m_count_max
private

Counter max limit.

Definition at line 123 of file stk_sync_semaphore.h.

Referenced by Semaphore(), and Signal().

◆ m_head

DLHeadType* stk::util::DListEntry< ISyncObject, TClosedLoop >::m_head
privateinherited

Owning list head, or NULL when the entry is not linked.

Definition at line 203 of file stk_linked_list.h.

◆ m_next

DLEntryType* stk::util::DListEntry< ISyncObject, TClosedLoop >::m_next
privateinherited

Next entry in the list, or NULL (open list boundary) / first entry (closed loop).

Definition at line 204 of file stk_linked_list.h.

◆ m_prev

DLEntryType* stk::util::DListEntry< ISyncObject, TClosedLoop >::m_prev
privateinherited

Previous entry in the list, or NULL (open list boundary) / last entry (closed loop).

Definition at line 205 of file stk_linked_list.h.

◆ m_wait_list


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