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

Non-recursive (binary) mutex primitive with ownership tracking. More...

#include <stk_sync_fastmutex.h>

Inheritance diagram for stk::sync::FastMutex:
Collaboration diagram for stk::sync::FastMutex:

Public 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.

Public Member Functions

 FastMutex ()
 Constructor.
 ~FastMutex ()
 Destructor.
EWaitResult TimedLockEx (Timeout timeout_ticks)
 Acquire lock, preserving the full wait outcome.
bool TimedLock (Timeout timeout_ticks)
 Acquire lock.
void Lock () override
 Acquire lock.
bool TryLock ()
 Try to acquire the lock without blocking.
void Unlock () override
 Release lock.
TId GetOwner () const
 Get owner of the mutex.
bool IsLocked () const
 Check if the mutex is currently locked.
void AddWaitObject (IWaitObject *wobj) override
 Called by kernel when a new task starts waiting on this event.
void RemoveWaitObject (IWaitObject *wobj) override
 Called by kernel when a waiting task is being removed (timeout expired, wait aborted, task terminated etc.).
const IWaitObject::ListHeadType & GetWaitList () const override
 Get list of tasks blocked on this object.
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.
TId GetFirstWaiterTid () const
 Get id of the task which is first in the wait list (FIFO order), i.e. the one that WakeOne() would wake next.
DLHeadType * GetHead ()
 Get the list head this entry currently belongs to.
DLEntryType * GetNext ()
 Get the next entry in the list.
DLEntryType * GetPrev ()
 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 SetTraceName (const char *name)
 Set name.
const char * GetTraceName () const
 Get name.

Static Public 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.

Protected Member Functions

void WakeOne () override
 Wake the first task in the wait list (FIFO order).
void WakeAll () override
 Wake all tasks currently in the wait list.
IWaitObject::ListHeadType & GetMutableWaitList () override
 Get list of tasks blocked on this object.

Protected Attributes

IWaitObject::ListHeadType m_wait_list
 Tasks blocked on this object.

Private Member Functions

 FastMutex (const FastMutex &)=delete
FastMutex & operator= (const FastMutex &)=delete
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.

Private Attributes

TId m_owner_tid
 thread id of the current owner (TID_NONE if free)
DLHeadType * m_head
 Owning list head, or NULL when the entry is not linked.
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).

Detailed Description

Non-recursive (binary) mutex primitive with ownership tracking.

Unlike stk::sync::Mutex, FastMutex does not keep a recursion counter: the only state is the owner thread id (TID_NONE means the mutex is free). This makes the lock/unlock paths shorter and reduces the object size.

A thread that already owns the mutex must not lock it again. Doing so is an unrecoverable contract violation: the kernel panics with KERNEL_PANIC_SYNC_DEADLOCK (in all build configurations, from Lock(), TryLock() and TimedLock()) instead of dead-locking on itself or failing silently.

Ownership is handed over directly to the first waiter (FIFO) on Unlock(), and priority inheritance is supported in the same way as in stk::sync::Mutex.

stk::sync::FastMutex g_ResourceMtx;
void Task_Func() {
if (g_ResourceMtx.TimedLock(100)) {
// ... access shared resource, do NOT call Lock() again here ...
g_ResourceMtx.Unlock();
}
}
Non-recursive (binary) mutex primitive with ownership tracking.
bool TimedLock(Timeout timeout_ticks)
Acquire lock.
void Unlock() override
Release lock.
Note
Only available when kernel is compiled with KERNEL_SYNC mode enabled.
See also
Mutex, ISyncObject, IWaitObject, IKernelService::Wait
Examples
D:/SVN/private/stk/interop/c/include/stk_c.h.

Definition at line 51 of file stk_sync_fastmutex.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 625 of file stk_common.h.

◆ ListHeadType

List head type for ISyncObject elements.

Definition at line 620 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

◆ FastMutex() [1/2]

stk::sync::FastMutex::FastMutex ( )
inlineexplicit

Constructor.

Definition at line 56 of file stk_sync_fastmutex.h.

57 {}
static constexpr TId TID_NONE
Reserved task/thread id representing zero/none thread id.
Definition stk_common.h:222
TId m_owner_tid
thread id of the current owner (TID_NONE if free)

References m_owner_tid, and stk::TID_NONE.

Referenced by FastMutex().

Here is the caller graph for this function:

◆ ~FastMutex()

stk::sync::FastMutex::~FastMutex ( )
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 64 of file stk_sync_fastmutex.h.

65 {
66 STK_ASSERT(m_wait_list.IsEmpty()); // API contract: must not be destroyed with waiting tasks
67 }
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
Definition stk_defs.h:516
IWaitObject::ListHeadType m_wait_list
Tasks blocked on this object.
Definition stk_helper.h:312

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

◆ FastMutex() [2/2]

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

References FastMutex().

Here is the call graph for this function:

Member Function Documentation

◆ AddWaitObject() [1/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 631 of file stk_common.h.

632 {
633 STK_ASSERT(wobj->GetHead() == nullptr);
634 wlist.LinkBack(wobj);
635 }

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

Referenced by stk::SyncObjectBase::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:

◆ AddWaitObject() [2/2]

void stk::SyncObjectBase::AddWaitObject ( IWaitObject * wobj)
inlineoverridevirtualinherited

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).

Implements stk::ISyncObject.

Definition at line 256 of file stk_helper.h.

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

References stk::ISyncObject::AddWaitObject(), and m_wait_list.

Here is the call 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 351 of file stk_helper.h.

352{
353 Weight max_weight = NO_WEIGHT;
354 const IWaitObject *itr = util::DListCast::ListEntryToParent<const IWaitObject>(GetWaitList().GetFirst());
355
356 while (itr != nullptr)
357 {
358 const Weight w = GetUserTaskFromTid(itr->GetTid())->GetWeight();
359 if (w > max_weight)
360 {
361 max_weight = w;
362 }
363
365 }
366
367 return ((max_weight > comp) ? max_weight : NO_WEIGHT);
368}
static constexpr ITask * GetUserTaskFromTid(TId task_id) noexcept
Get task instance from its identifier.
Definition stk_arch.h:725
static constexpr Weight NO_WEIGHT
Weight value: weight is not set.
Definition stk_common.h:239
int32_t Weight
Weight value (aka priority).
Definition stk_common.h:190
virtual const IWaitObject::ListHeadType & GetWaitList() const =0
Get list of tasks blocked on this object.
virtual Weight GetWeight() const
Get static base weight of the task.
Definition stk_common.h:928
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(), GetWaitList(), stk::ITask::GetWeight(), stk::util::DListCast::ListEntryToParent(), and stk::NO_WEIGHT.

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

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

◆ GetFirstWaiterTid()

TId stk::ISyncObject::GetFirstWaiterTid ( ) const
inlineinherited

Get id of the task which is first in the wait list (FIFO order), i.e. the one that WakeOne() would wake next.

Returns
TId of the first waiter, or TID_NONE if no tasks are currently waiting.
Note
Read-only introspection for diagnostics / telemetry.
The result is a snapshot: call inside the critical section (see hw::CriticalSection, sync::ScopedCrticalSection) if the list may change concurrently.
See also
GetWaitList

Definition at line 726 of file stk_common.h.

727 {
728 const IWaitObject *const obj = util::DListCast::ListEntryToParent<const IWaitObject>(
729 GetWaitList().GetFirst());
730
731 return ((obj != nullptr) ? obj->GetTid() : TID_NONE);
732 }

References stk::IWaitObject::GetTid(), GetWaitList(), stk::util::DListCast::ListEntryToParent(), and stk::TID_NONE.

Referenced by anonymous_namespace{threadx_stk.cpp}::FillSuspended().

Here is the call graph for this function:
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; }

Referenced by stk::SyncObjectBase::~SyncObjectBase().

Here is the caller graph for this function:

◆ GetMutableWaitList()

IWaitObject::ListHeadType & stk::SyncObjectBase::GetMutableWaitList ( )
inlineoverrideprotectedvirtualinherited

Get list of tasks blocked on this object.

Implements stk::ISyncObject.

Definition at line 307 of file stk_helper.h.

308 {
309 return m_wait_list;
310 }

References m_wait_list.

◆ 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; }

◆ GetOwner()

TId stk::sync::FastMutex::GetOwner ( ) const
inline

Get owner of the mutex.

Warning
ISR-safe.
Returns
Thread id of the owner, or TID_NONE if the mutex is free.

Definition at line 120 of file stk_sync_fastmutex.h.

120{ return m_owner_tid; }

References m_owner_tid.

◆ 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 582 of file stk_common.h.

583 {
584 #if STK_SYNC_DEBUG_NAMES
585 return m_trace_name;
586 #else
587 return nullptr;
588 #endif
589 }

◆ GetWaitList()

const IWaitObject::ListHeadType & stk::SyncObjectBase::GetWaitList ( ) const
inlineoverridevirtualinherited

Get list of tasks blocked on this object.

Note
Read-only access for diagnostics / telemetry.
The result is a snapshot: call inside the critical section (see hw::CriticalSection, sync::ScopedCrticalSection) if the list may change concurrently.

Implements stk::ISyncObject.

Definition at line 266 of file stk_helper.h.

267 {
268 return m_wait_list;
269 }

References m_wait_list.

Referenced by tx_semaphore_ceiling_put().

Here is the caller graph for this function:

◆ 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); }

◆ IsLocked()

bool stk::sync::FastMutex::IsLocked ( ) const
inline

Check if the mutex is currently locked.

Note
Snapshot only, may be stale immediately for a non-owner.
Warning
ISR-safe.

Definition at line 126 of file stk_sync_fastmutex.h.

126{ return (m_owner_tid != TID_NONE); }

References m_owner_tid, and stk::TID_NONE.

◆ 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).

◆ Lock()

void stk::sync::FastMutex::Lock ( )
inlineoverridevirtual

Acquire lock.

Note
Not cancelable: a void Lock() cannot report failure and must return with the lock held, so a cancellation (IKernel::CancelTaskWait()) is absorbed and the wait is retried. This also keeps the mutex re-acquisition at the end of ConditionVariable::Wait() reliable (the kernel re-locks via this method). Use TimedLockEx() if cancellation must be observed. Panics (KERNEL_PANIC_ASSERT) on any other failure.
Warning
ISR-unsafe.

Implements stk::IMutex.

Definition at line 215 of file stk_sync_fastmutex.h.

216{
217 EWaitResult result;
218
219 do
220 {
221 result = TimedLockEx(WAIT_INFINITE);
222 }
223 while (result == WAIT_RESULT_CANCELED);
224
225 if (result != WAIT_RESULT_SIGNAL)
226 {
228 }
229}
EWaitResult
Wait result (see IKernelService::Wait).
Definition stk_common.h:137
@ WAIT_RESULT_CANCELED
The wait was cancelled by another task via IKernel::CancelTaskWait(), independent of signal/timeout.
Definition stk_common.h:141
@ WAIT_RESULT_SIGNAL
The wake was caused by a signal.
Definition stk_common.h:139
@ KERNEL_PANIC_ASSERT
Internal assertion failed (maps from STK_ASSERT).
Definition stk_common.h:64
static void STK_KERNEL_PANIC(stk::EKernelPanicId id)
Called when the kernel detects an unrecoverable internal fault.
Definition stk_arch.h:183
static constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
Definition stk_common.h:228
EWaitResult TimedLockEx(Timeout timeout_ticks)
Acquire lock, preserving the full wait outcome.

References stk::KERNEL_PANIC_ASSERT, stk::STK_KERNEL_PANIC(), TimedLockEx(), stk::WAIT_INFINITE, stk::WAIT_RESULT_CANCELED, and stk::WAIT_RESULT_SIGNAL.

Referenced by stk_fastmutex_lock().

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

◆ 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=()

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

◆ RemoveWaitObject() [1/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 647 of file stk_common.h.

648 {
649 STK_ASSERT(wobj->GetHead() == &wlist);
650 wlist.Unlink(wobj);
651 }

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

Referenced by stk::SyncObjectBase::RemoveWaitObject().

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

◆ RemoveWaitObject() [2/2]

void stk::SyncObjectBase::RemoveWaitObject ( IWaitObject * wobj)
inlineoverridevirtualinherited

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).

Implements stk::ISyncObject.

Definition at line 261 of file stk_helper.h.

262 {
264 }
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:647

References m_wait_list, and stk::ISyncObject::RemoveWaitObject().

Referenced by 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 570 of file stk_common.h.

571 {
572 #if STK_SYNC_DEBUG_NAMES
573 m_trace_name = name;
574 #else
575 STK_UNUSED(name);
576 #endif
577 }
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
Definition stk_defs.h:715

References STK_UNUSED.

Referenced by stk::memory::BlockMemoryPool::BlockMemoryPool(), stk::memory::BlockMemoryPool::BlockMemoryPool(), stk::memory::BytePool::BytePool(), stk::memory::BytePool::BytePool(), tx_block_pool_create(), tx_event_flags_create(), tx_mutex_create(), tx_queue_create(), and tx_semaphore_create().

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 316 of file stk_helper.h.

317{
319
320 // note: ScopedCriticalSection usage
321 //
322 // Single-core: no critical section needed - Tick() runs inside the
323 // SysTick ISR which already executes with interrupts disabled, making
324 // re-entrancy impossible on the local core.
325 //
326 // Multi-core: critical section is required because the tick handler on
327 // each core may call Tick() concurrently for the same Semaphore instance,
328 // and ISyncObject::Tick() is not re-entrant.
329#if (STK_ARCH_CPU_COUNT > 1)
330 const hw::CriticalSection::ScopedLock cs_;
331#endif
332
333 IWaitObject *itr = util::DListCast::ListEntryToParent<IWaitObject>(wlist.GetFirst());
334
335 while (itr != nullptr)
336 {
337 IWaitObject *const next = util::DListCast::ListEntryToParent<IWaitObject>(itr->GetNext());
338
339 if (!itr->Tick(elapsed_ticks))
340 {
341 itr->Wake(true);
342 }
343
344 itr = next;
345 }
346
347 return !wlist.IsEmpty();
348}
DLHeadType ListHeadType
List head type for IWaitObject elements.
Definition stk_common.h:502
virtual IWaitObject::ListHeadType & GetMutableWaitList()=0
Get list of tasks blocked on this object.

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

Here is the call graph for this function:

◆ TimedLock()

bool stk::sync::FastMutex::TimedLock ( Timeout timeout_ticks)
inline

Acquire lock.

Parameters
[in]timeout_ticksMaximum time to wait (ticks).
Note
Not recursive: locking a mutex already owned by the caller is a contract violation that triggers STK_KERNEL_PANIC(KERNEL_PANIC_SYNC_DEADLOCK) in all build configurations.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.
Returns
True if lock acquired, false otherwise (timeout, cancellation or NO_WAIT on a busy mutex). Use TimedLockEx() to tell these apart.

Definition at line 91 of file stk_sync_fastmutex.h.

91{ return (TimedLockEx(timeout_ticks) == WAIT_RESULT_SIGNAL); }

References TimedLockEx(), and stk::WAIT_RESULT_SIGNAL.

Referenced by stk_fastmutex_timed_lock(), and TryLock().

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

◆ TimedLockEx()

EWaitResult stk::sync::FastMutex::TimedLockEx ( Timeout timeout_ticks)
inline

Acquire lock, preserving the full wait outcome.

Parameters
[in]timeout_ticksMaximum time to wait (ticks).
Note
Not recursive: locking a mutex already owned by the caller is a contract violation that triggers STK_KERNEL_PANIC(KERNEL_PANIC_SYNC_DEADLOCK) in all build configurations.
Warning
ISR-safe only with timeout_ticks = NO_WAIT, ISR-unsafe otherwise.
Returns
WAIT_RESULT_SIGNAL if the lock was acquired (note: here "signal" means "lock acquired", including the immediate path where no notification was involved), WAIT_RESULT_TIMEOUT if the lock was busy and the timeout expired (or NO_WAIT was passed), WAIT_RESULT_CANCELED if the wait was cancelled via IKernel::CancelTaskWait(), WAIT_RESULT_FAIL if the kernel rejected the wait.

Definition at line 138 of file stk_sync_fastmutex.h.

139{
141 const TId current_tid = svc->GetTid();
142
143 ScopedCriticalSection cs_;
144
145 const TId owner_tid = m_owner_tid;
146
147 // NO_WAIT on a busy mutex is reported as an immediately-expired timeout
149
150 STK_ASSERT(current_tid != TID_NONE); // API contract: must be called inside STK task
151
152 // fast path: mutex is free
153 if (owner_tid == TID_NONE)
154 {
155 m_owner_tid = current_tid;
156 __stk_full_memfence();
157
158 result = WAIT_RESULT_SIGNAL;
159 }
160 // self-lock: non-recursive mutex, the caller would dead-lock on itself (or silently continue without
161 // owning a fresh lock): unrecoverable API contract violation, FastMutex is not recursive
162 else if (owner_tid == current_tid)
163 {
165 }
166 // slow path: block until available or timeout expires
167 else if (timeout_ticks != NO_WAIT)
168 {
169 STK_ASSERT(!hw::IsInsideISR()); // API contract: caller must not be in ISR for a blocking call
170
171 // boost priority of the owner to avoid priority inversion (in case of SwitchStrategyFixedPriority,
172 // otherwise ignored by the kernel), noop if ISwitchStrategy::PRIORITY_INHERITANCE_API = 0
173 svc->InheritWeight(owner_tid, GetUserTaskFromTid(current_tid)->GetWeight());
174
175 // mutex owned by another thread (slow path/blocking)
176 result = svc->Wait(this, &cs_, timeout_ticks);
177
178 if (result != WAIT_RESULT_SIGNAL)
179 {
180 // kernel invariant: a wait that did not end in a signal must not leave this thread as the
181 // owner (Unlock() hands over ownership only together with a signal), otherwise the caller
182 // would be told it failed while owning a lock nobody will release
183 STK_ASSERT(m_owner_tid != current_tid);
184
185 // if owner did not change, undo priority boost to avoid stuck elevated priority: lookup for a
186 // higher weight within existing wait objects, noop if ISwitchStrategy::PRIORITY_INHERITANCE_API = 0
187 if (owner_tid == m_owner_tid)
188 {
189 svc->RestoreWeight(owner_tid, this);
190 }
191 }
192 else
193 {
194 // kernel invariant: ownership must have been transferred to this thread by Unlock(),
195 // otherwise this is an internal defect, not a caller error
196 if (m_owner_tid != current_tid)
197 {
199 }
200 }
201 }
202 // try-lock variant: owned by someone else, but no-wait requested
203 else
204 {
205 // result is WAIT_RESULT_TIMEOUT already, noop
206 }
207
208 return result;
209}
static constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
Definition stk_common.h:234
@ WAIT_RESULT_TIMEOUT
The wake was caused by a timeout expiry.
Definition stk_common.h:140
@ KERNEL_PANIC_SYNC_DEADLOCK
Deadlock caused by a synchronization primitive: a task tried to acquire a non-recursive primitive (e....
Definition stk_common.h:74
Word TId
Task (thread) id.
Definition stk_common.h:165
bool IsInsideISR()
Check whether the CPU is currently executing inside a hardware interrupt service routine (ISR).
friend class IKernelService
Definition stk_common.h:613
static IKernelService * GetInstance()
Get CPU-local instance of the kernel service.

References stk::IKernelService::GetInstance(), stk::IKernelService::GetTid(), stk::GetUserTaskFromTid(), stk::SyncObjectBase::IKernelService, stk::IKernelService::InheritWeight(), stk::hw::IsInsideISR(), stk::KERNEL_PANIC_ASSERT, stk::KERNEL_PANIC_SYNC_DEADLOCK, m_owner_tid, stk::NO_WAIT, stk::IKernelService::RestoreWeight(), STK_ASSERT, stk::STK_KERNEL_PANIC(), stk::TID_NONE, stk::IKernelService::Wait(), stk::WAIT_RESULT_SIGNAL, and stk::WAIT_RESULT_TIMEOUT.

Referenced by Lock(), stk_fastmutex_timed_lock_ex(), and TimedLock().

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

◆ TryLock()

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

Try to acquire the lock without blocking.

Warning
ISR-safe.
Note
Panics (KERNEL_PANIC_SYNC_DEADLOCK) if the caller already owns the lock.
Returns
True if lock acquired, false if the lock is owned by another thread.

Definition at line 109 of file stk_sync_fastmutex.h.

109{ return TimedLock(NO_WAIT); }

References stk::NO_WAIT, and TimedLock().

Referenced by stk_fastmutex_trylock().

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 }

◆ Unlock()

void stk::sync::FastMutex::Unlock ( )
inlineoverridevirtual

Release lock.

Warning
ISR-safe.

Implements stk::IMutex.

Definition at line 235 of file stk_sync_fastmutex.h.

236{
237 const ScopedCriticalSection cs_;
238
240 (m_owner_tid != TID_NONE)); // API contract: caller must own the lock
241
242 if (!m_wait_list.IsEmpty())
243 {
244 // slow path: contended unlock, hand over to the first waiter
246
247 // restore priority of the owner (it could have been boosted by waiters of this mutex),
248 // noop if ISwitchStrategy::PRIORITY_INHERITANCE_API = 0; not needed if there are no waiters
249 // because a boost is undone by the waiter itself on timeout/cancellation
250 if (m_owner_tid != TID_NONE)
251 {
252 svc->RestoreWeight(m_owner_tid);
253 }
254
255 // pass ownership directly to the first waiter (FIFO order)
256 IWaitObject *const waiter = util::DListCast::ListEntryToParent<IWaitObject>(m_wait_list.GetFirst());
257
258 // transfer ownership to the waiter
259 m_owner_tid = waiter->GetTid();
260 __stk_full_memfence();
261
262 // wake up
263 waiter->Wake(false);
264
265 // boost priority from the highest-priority task still in wait list, skip the lookup if none left,
266 // noop if ISwitchStrategy::PRIORITY_INHERITANCE_API = 0
267 if (!m_wait_list.IsEmpty())
268 {
269 svc->InheritWeight(m_owner_tid,
271 }
272 }
273 else
274 {
275 // fast path: free completely if there are no waiters
277 __stk_full_memfence();
278 }
279}
static TId GetTid()
Get task/thread Id of the calling task.
Definition stk_helper.h:376
Weight FindWeightHigherThan(Weight comp) const
Find higher weight within linked wait objects.
Definition stk_helper.h:351

References stk::ISyncObject::FindWeightHigherThan(), stk::IKernelService::GetInstance(), stk::GetTid(), stk::IWaitObject::GetTid(), stk::GetUserTaskFromTid(), stk::SyncObjectBase::IKernelService, stk::IKernelService::InheritWeight(), stk::util::DListCast::ListEntryToParent(), m_owner_tid, stk::SyncObjectBase::m_wait_list, stk::IKernelService::RestoreWeight(), STK_ASSERT, stk::TID_NONE, and stk::IWaitObject::Wake().

Referenced by stk_fastmutex_unlock().

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

◆ WakeAll() [1/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 701 of file stk_common.h.

702 {
703 for (IWaitObject *obj = util::DListCast::ListEntryToParent<IWaitObject>(wlist.GetFirst());
704 obj != nullptr;
706 {
707 obj->Wake(false);
708 }
709 }

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

Here is the call graph for this function:

◆ WakeAll() [2/2]

void stk::SyncObjectBase::WakeAll ( )
inlineoverrideprotectedvirtualinherited

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).

Implements stk::ISyncObject.

Definition at line 302 of file stk_helper.h.

303 {
304 IKernelService::GetInstance()->Wake(this, true);
305 }
virtual void Wake(ISyncObject *sobj, bool all)=0
Wake one or all tasks currently waiting on a synchronization object.

References stk::IKernelService::GetInstance(), and stk::IKernelService::Wake().

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

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

◆ WakeOne() [1/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 686 of file stk_common.h.

687 {
688 IWaitObject *const obj = util::DListCast::ListEntryToParent<IWaitObject>(wlist.GetFirst());
689 if (obj != nullptr)
690 {
691 obj->Wake(false);
692 }
693 }

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

Here is the call graph for this function:

◆ WakeOne() [2/2]

void stk::SyncObjectBase::WakeOne ( )
inlineoverrideprotectedvirtualinherited

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).

Implements stk::ISyncObject.

Definition at line 297 of file stk_helper.h.

298 {
299 IKernelService::GetInstance()->Wake(this, false);
300 }

References stk::IKernelService::GetInstance(), and stk::IKernelService::Wake().

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

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

Member Data Documentation

◆ 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_owner_tid

TId stk::sync::FastMutex::m_owner_tid
private

thread id of the current owner (TID_NONE if free)

Definition at line 131 of file stk_sync_fastmutex.h.

Referenced by FastMutex(), GetOwner(), IsLocked(), TimedLockEx(), and Unlock().

◆ 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: