QP/C++  7.0.1
Real-Time Embedded Framework
QXMutex Class Reference

Priority Ceiling Mutex the QXK preemptive kernel. More...

#include <qxthread.hpp>

Public Member Functions

void init (std::uint_fast8_t const ceiling) noexcept
 initialize the QXK priority-ceiling mutex QP::QXMutex More...
 
bool lock (std::uint_fast16_t const nTicks=QXTHREAD_NO_TIMEOUT) noexcept
 lock the QXK priority-ceiling mutex QP::QXMutex More...
 
bool tryLock (void) noexcept
 try to lock the QXK priority-ceiling mutex QP::QXMutex More...
 
void unlock (void) noexcept
 unlock the QXK priority-ceiling mutex QP::QXMutex More...
 

Private Attributes

QPSet m_waitSet
 set of extended-threads waiting on this mutex More...
 
std::uint8_t volatile m_lockNest
 lock-nesting up-down counter More...
 
std::uint8_t volatile m_holderPrio
 prio of the lock holder thread More...
 
std::uint8_t m_ceiling
 prioirty ceiling of this mutex More...
 

Detailed Description

Description
QP::QXMutex is a blocking mutual exclusion mechanism that can also apply the priority ceiling protocol to avoid unbounded priority inversion (if initialized with a non-zero ceiling priority, see QP::QXMutex::init()). In that case, QP::QXMutex requires its own uinque QP priority level, which cannot be used by any thread or any other QP::QXMutex. If initialzied with zero ceiling priority, QP::QXMutex does not use the priority ceiling protocol and does not require a unique QP priority (see QP::QXMutex::init()). QP::QXMutex is recursive (reentrant), which means that it can be locked mutiliple times (up to 255 levels) by the same thread without causing deadlock. QP::QXMutex is primarily intended for the extened (blocking) threads, but can also be used by the basic threads through the non-blocking QP::QXMutex::tryLock() API.
Note
QP::QXMutex should be used in situations when at least one of the extended threads contending for the mutex blocks while holding the mutex (between the QP::QXMutex::lock() and QP::QXMutex::unlock() operations). If no blocking is needed while holding the mutex, the more efficient non-blocking mechanism of selective QXKscheduler locking" should be used instead. @ref QP::QXK::schedLock() "Selective scheduler locking" is available for both @ref QP::QActive "basic threads" and @ref QP::QXThread "extended threads", so it is applicable to situations where resources are shared among all these threads.
Usage
The following example illustrates how to instantiate and use the mutex in your application.
QXMutex l_rndMutex; // mutex to protect the random number generator
void BSP::randomSeed(uint32_t seed) {
l_rndMutex.init(N_PHILO + 1); // <--- initialize the mutex
l_rnd = seed;
}
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
uint32_t rnd;
l_rndMutex.lock(); // <--- lock the shared random seed
// "Super-Duper" Linear Congruential Generator (LCG)
rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // <--- unlock the shared random seed
return rnd;
}
Priority Ceiling Mutex the QXK preemptive kernel.
Definition: qxthread.hpp:202
void init(std::uint_fast8_t const ceiling) noexcept
initialize the QXK priority-ceiling mutex QP::QXMutex
Definition: qxk_mutex.cpp:82
void unlock(void) noexcept
unlock the QXK priority-ceiling mutex QP::QXMutex
Definition: qxk_mutex.cpp:341
bool lock(std::uint_fast16_t const nTicks=QXTHREAD_NO_TIMEOUT) noexcept
lock the QXK priority-ceiling mutex QP::QXMutex
Definition: qxk_mutex.cpp:127

Definition at line 202 of file qxthread.hpp.

Member Function Documentation

◆ init()

void init ( std::uint_fast8_t const  ceiling)
noexcept
Description
Initialize the QXK priority ceiling mutex.
Parameters
[in]ceilingthe ceiling-priotity of this mutex or zero.
Note
ceiling == 0 means that the priority-ceiling protocol shall not be used by this mutex. Such mutex will not change (boost) the priority of the holding thread.
ceiling > 0 means that the priority-ceiling protocol shall be used by this mutex. Such mutex will boost the priority of the holding thread to the ceiling level for as long as the thread holds this mutex.
Attention
When the priority-ceiling protocol is used (ceiling > 0), the ceiling priority must be unused by any other thread or mutex. Also, the ceiling priority must be higher than priority of any thread that uses this mutex.
Usage
QXMutex l_rndMutex; // mutex to protect the random number generator
void BSP::randomSeed(uint32_t seed) {
l_rndMutex.init(N_PHILO + 1); // <--- initialize the mutex
l_rnd = seed;
}
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
uint32_t rnd;
l_rndMutex.lock(); // <--- lock the shared random seed
// "Super-Duper" Linear Congruential Generator (LCG)
rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // <--- unlock the shared random seed
return rnd;
}
Precondition
the celiling priority of the mutex must:
  • cannot exceed the maximum QF_MAX_ACTIVE;
  • the ceiling priority of the mutex must not be already in use; (QF requires priority to be unique).

Definition at line 82 of file qxk_mutex.cpp.

◆ lock()

bool lock ( std::uint_fast16_t const  nTicks = QXTHREAD_NO_TIMEOUT)
noexcept
Description
Lock the QXK priority ceiling mutex QP::QXMutex.
Parameters
[in]nTicksnumber of clock ticks (at the associated rate) to wait for the semaphore. The value of QXTHREAD_NO_TIMEOUT indicates that no timeout will occur and the semaphore will wait indefinitely.
Returns
'true' if the mutex has been acquired and 'false' if a timeout occured.
Note
The mutex locks are allowed to nest, meaning that the same extended thread can lock the same mutex multiple times (< 255). However, each call to QXMutex::lock() must be ballanced by the matching call to QXMutex::unlock().
Usage
QXMutex l_rndMutex; // mutex to protect the random number generator
void BSP::randomSeed(uint32_t seed) {
l_rndMutex.init(N_PHILO + 1); // <--- initialize the mutex
l_rnd = seed;
}
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
uint32_t rnd;
l_rndMutex.lock(); // <--- lock the shared random seed
// "Super-Duper" Linear Congruential Generator (LCG)
rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // <--- unlock the shared random seed
return rnd;
}
Precondition
this function must:
  • NOT be called from an ISR;
  • be called from an extended thread;
  • the ceiling priority must not be used; or if used
    • the thread priority must be below the ceiling of the mutex;
  • the ceiling must be in range
  • the thread must NOT be already blocked on any object.
also: the thread must NOT be holding a scheduler lock.

Definition at line 127 of file qxk_mutex.cpp.

◆ tryLock()

bool tryLock ( void  )
noexcept
Description
Try to lock the QXK priority ceiling mutex QP::QXMutex.
Returns
'true' if the mutex was successfully locked and 'false' if the mutex was unavailable and was NOT locked.
Note
This function can be called from both basic threads (active objects) and extended threads.
The mutex locks are allowed to nest, meaning that the same extended thread can lock the same mutex multiple times (< 255). However, each successful call to QXMutex::tryLock() must be ballanced by the matching call to QXMutex::unlock().
Precondition
this function must:
  • NOT be called from an ISR;
  • the calling thread must be valid;
  • the ceiling must be not used; or
    • the thread priority must be below the ceiling of the mutex;
  • the ceiling must be in range
also: the thread must NOT be holding a scheduler lock.

Definition at line 254 of file qxk_mutex.cpp.

◆ unlock()

void unlock ( void  )
noexcept
Description
Unlock the QXK priority ceiling mutex.
Note
This function can be called from both basic threads (active objects) and extended threads.
The mutex locks are allowed to nest, meaning that the same extended thread can lock the same mutex multiple times (< 255). However, each call to QXMutex::lock() or a successfull call to QXMutex::tryLock() must be ballanced by the matching call to QXMutex::unlock().
Usage
QXMutex l_rndMutex; // mutex to protect the random number generator
void BSP::randomSeed(uint32_t seed) {
l_rndMutex.init(N_PHILO + 1); // <--- initialize the mutex
l_rnd = seed;
}
uint32_t BSP::random(void) { // a very cheap pseudo-random-number generator
uint32_t rnd;
l_rndMutex.lock(); // <--- lock the shared random seed
// "Super-Duper" Linear Congruential Generator (LCG)
rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd; // set for the next time
l_rndMutex.unlock(); // <--- unlock the shared random seed
return rnd;
}
Precondition
this function must:
  • NOT be called from an ISR;
  • the calling thread must be valid;
  • the ceiling must not be used or
    • the current thread must have priority equal to the mutex ceiling;
  • the ceiling must be in range
also: the mutex must be already locked at least once.
also: the mutex must be held by this thread.

Definition at line 341 of file qxk_mutex.cpp.

Field Documentation

◆ m_waitSet

QPSet m_waitSet
private

Definition at line 217 of file qxthread.hpp.

◆ m_lockNest

std::uint8_t volatile m_lockNest
private

Definition at line 218 of file qxthread.hpp.

◆ m_holderPrio

std::uint8_t volatile m_holderPrio
private

Definition at line 219 of file qxthread.hpp.

◆ m_ceiling

std::uint8_t m_ceiling
private

Definition at line 220 of file qxthread.hpp.


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