QXK/C eXtended (blocking) thread.
More...
Go to the source code of this file.
|
#define | QXTHREAD_START(me_, prio_, qSto_, qLen_, stkSto_, stkSize_, par_) |
| Polymorphically start an extended thread. More...
|
|
#define | QXTHREAD_POST_X(me_, e_, margin_, sender_) QACTIVE_POST_X(&(me_)->super, (e_), (margin_), (sender_)) |
|
#define | QXTHREAD_NO_TIMEOUT ((uint_fast16_t)0) |
| no-timeout special timeout value when blocking on queues or semaphores More...
|
|
QXK/C eXtended (blocking) thread.
Definition in file qxthread.h.
◆ QXSemaphore
Counting Semaphore of the QXK preemptive kernel.
- Description
- QXSemaphore is a blocking mechanism intended primarily for signaling extended threads. The semaphore is initialized with the maximum count (see QXSemaphore_init()), which allows you to create a binary semaphore (when the maximum count is 1) and counting semaphore when the maximum count is > 1.
- See also
-
- Usage
- The following example illustrates how to instantiate and use the semaphore in your application.
int main() {
. . .
0U,
1U);
. . .
}
void main_threadXYZ(
QXThread *
const me) {
while (1) {
. . .
. . .
}
}
void GPIO_Handler(void) {
. . .
. . .
}
bool QXSemaphore_signal(QXSemaphore *const me)
signal (unblock) the semaphore
void QXSemaphore_init(QXSemaphore *const me, uint_fast16_t count, uint_fast16_t max_count)
initialize the counting semaphore
bool QXSemaphore_wait(QXSemaphore *const me, uint_fast16_t const nTicks)
wait (block) on the semaphore
#define QXTHREAD_NO_TIMEOUT
no-timeout special timeout value when blocking on queues or semaphores
Counting Semaphore of the QXK preemptive kernel.
eXtended (blocking) thread of the QXK preemptive kernel
Definition at line 183 of file qxthread.h.
Data Fields |
QPSet |
waitSet |
set of extended-threads waiting on this semaphore |
uint16_t volatile |
count |
semaphore up-down counter |
uint16_t |
max_count |
maximum value of the semaphore counter |
◆ QXMutex
Blocking Mutex the QXK preemptive kernel.
- Description
- 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 QXMutex_init()). In that case, QXMutex requires its own uinque QP priority level, which cannot be used by any thread or any other QXMutex. If initialzied with zero ceiling priority, QXMutex does not use the priority ceiling protocol and does not require a unique QP priority (see QXMutex_init()). QXMutex is recursive (reentrant), which means that it can be locked mutiliple times (up to 255 levels) by the same thread without causing deadlock. QXMutex is primarily intended for the extened (blocking) threads, but can also be used by the basic threads through the non-blocking QXMutex_tryLock() API.
- Note
- 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 QXMutex_lock() and QXMutex_unlock() operations). If no blocking is needed while holding the mutex, the more efficient non-blocking mechanism of selective QXK scheduler locking should be used instead. Selective scheduler locking is available for both basic threads and extendedthreads", so it is applicable to situations where resources are shared among all these threads.
- See also
-
- Usage
- The following example illustrates how to instantiate and use the mutex in your application.
l_rnd = seed;
}
rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd;
return rnd;
}
unsigned long int uint32_t
exact-width 32-bit unsigned int
bool QXMutex_lock(QXMutex *const me, uint_fast16_t const nTicks)
lock the QXK priority-ceiling mutex QXMutex
void QXMutex_unlock(QXMutex *const me)
unlock the QXK priority-ceiling mutex QXMutex
void QXMutex_init(QXMutex *const me, uint_fast8_t ceiling)
initialize the QXK priority-ceiling mutex QXMutex
Blocking Mutex the QXK preemptive kernel.
Definition at line 245 of file qxthread.h.
Data Fields |
QPSet |
waitSet |
set of extended-threads waiting on this mutex |
uint8_t volatile |
lockNest |
lock-nesting up-down counter |
uint8_t volatile |
holderPrio |
priority of the lock holder thread |
uint8_t |
ceiling |
prioirty ceiling of this mutex |
◆ QXTHREAD_START
#define QXTHREAD_START |
( |
|
me_, |
|
|
|
prio_, |
|
|
|
qSto_, |
|
|
|
qLen_, |
|
|
|
stkSto_, |
|
|
|
stkSize_, |
|
|
|
par_ |
|
) |
| |
Value:do { \
Q_ASSERT((me_)->super.super.vptr); \
&(me_)->super, (prio_), (
QEvt const **)(qSto_), (qLen_), \
(stkSto_), (stkSize_), (par_))); \
} while (false)
Virtual table for the QActive class.
Polymorphically start an extended thread.
- Description
- Starts execution of the thread and registers the thread with the framework.
- Parameters
-
[in,out] | me_ | pointer (see Object Orientation) |
[in] | prio_ | priority of the extended-thread |
[in] | qSto_ | pointer to the storage for the ring buffer of the message queue (possibly NULL) |
[in] | qLen_ | length of the message queue [events] (possibly 0) |
[in] | stkSto_ | pointer to the stack storage (required) |
[in] | stkSize_ | stack size [bytes] |
[in] | par_ | pointer to the additional port-specific parameter(s) (might be NULL). |
- Usage
int main() {
. . .
Test_ctor();
BSP_init();
QXK_init(idleStackSto, sizeof(idleStackSto));
QF_poolInit(smlPoolSto,
sizeof(smlPoolSto),
sizeof(smlPoolSto[0]));
N_PHILO + 2U,
tableQueueSto,
tableStackSto,
sizeof(tableStackSto),
(void *)0);
. . .
10U,
testQueueSto,
testStackSto,
sizeof(testStackSto),
(void *)0);
}
unsigned long long uint64_t
exact-width 64-bit unsigned int
#define Q_DEFINE_THIS_FILE
Define the file name (with __FILE__) for assertions in this file.
#define Q_DIM(array_)
Helper macro to calculate static dimension of a 1-dim array_.
void QF_poolInit(void *const poolSto, uint_fast32_t const poolSize, uint_fast16_t const evtSize)
Event pool initialization for dynamic allocation of events.
void QF_psInit(QSubscrList *const subscrSto, enum_t const maxSignal)
Publish-subscribe initialization.
int_t QF_run(void)
Transfers control to QF to run the application.
void QF_init(void)
QF initialization.
QP/C public interface including backwards-compatibility layer.
#define QXTHREAD_START(me_, prio_, qSto_, qLen_, stkSto_, stkSize_, par_)
Polymorphically start an extended thread.
#define QACTIVE_START(me_, prio_, qSto_, qLen_, stkSto_, stkLen_, par_)
Polymorphically start an active object.
Definition at line 103 of file qxthread.h.
◆ QXTHREAD_POST_X
#define QXTHREAD_POST_X |
( |
|
me_, |
|
|
|
e_, |
|
|
|
margin_, |
|
|
|
sender_ |
|
) |
| QACTIVE_POST_X(&(me_)->super, (e_), (margin_), (sender_)) |
- Description
- This macro does not assert if the queue overflows and cannot accept the event with the specified margin of free slots remaining.
- Parameters
-
[in,out] | me_ | pointer (see Object Orientation) |
[in] | e_ | pointer to the event to post |
[in] | margin_ | the minimum free slots in the queue, which must still be available after posting the event. The special value QF_NO_MARGIN causes asserting failure in case event allocation fails. |
[in] | sender_ | pointer to the sender object (used in QS tracing) |
- Returns
- 'true' if the posting succeeded, and 'false' if the posting failed due to insufficient margin of free slots available in the queue.
- Note
- The
sender_
parameter is actually only used when QS tracing is enabled (macro Q_SPY is defined). When QS software tracing is disabled, the QXTHREAD_POST_X() macro does not pass the sender_
argument, so the overhead of passing this extra argument is entirely avoided.
-
The pointer to the sender object is not necessarily a pointer to an active object. In fact, if QXTHREAD_POST_X() is called from an interrupt or other context, you can create a unique object just to unambiguously identify the sender of the event.
- Usage
. . .
TableEvt *pe;
Q_NEW_X(pe, TableEvt, 5U, HUNGRY_SIG);
if (pe != (TableEvt *)0) {
pe->philNum = me->num;
}
. . .
#define Q_NEW_X(e_, evtT_, margin_, sig_)
Allocate a dynamic event (non-asserting version).
Active Object base class (based on QHsm implementation)
#define QACTIVE_POST_X(me_, e_, margin_, sender_)
Polymorphically posts an event to an active object (FIFO) without delivery guarantee.
Definition at line 147 of file qxthread.h.
◆ QXTHREAD_NO_TIMEOUT
no-timeout special timeout value when blocking on queues or semaphores
Definition at line 160 of file qxthread.h.
◆ QXThreadVtable
◆ QXThread_ctor()
constructor of an extended-thread
- Description
- Performs the first step of QXThread initialization by assigning the thread-handler function and the tick rate at which it will handle the timeouts.
- Parameters
-
[in,out] | me | pointer (see Object Orientation) |
[in] | handler | the thread-handler function |
[in] | tickRate | the ticking rate for timeouts in this thread |
- Note
- Must be called only ONCE before QXTHREAD_START().
- Usage
- The following example illustrates how to invoke QXThread_ctor() in the main() function
while (1) {
. . .
}
}
int main() {
. . .
5U,
(void *)0, 0,
stack_blinky, sizeof(stack_blinky),
(void *)0);
. . .
}
void QXThread_ctor(QXThread *const me, QXThreadHandler handler, uint_fast8_t tickRate)
constructor of an extended-thread
Definition at line 113 of file qxk_xthr.c.
◆ QXThread_delay()
delay (block) the current extended thread for a specified # ticks
delay (block) the current extended thread for a specified # ticks
- Precondition
- this function must:
- NOT be called from an ISR;
- be called from an extended thread;
- the thread must NOT be already blocked on any object.
-
also: the thread must NOT be holding a scheduler lock.
Definition at line 648 of file qxk_xthr.c.
◆ QXThread_delayCancel()
◆ QXThread_queueGet()
obtain a message from the private message queue (block if no messages)
- Description
- The QXThread_queueGet() operation allows the calling extended thread to receive QP events directly into its own built-in event queue from an ISR, basic thread (AO), or another extended thread.
If QXThread_queueGet() is called when no events are present in the thread's private event queue, the operation blocks the current extended thread until either an event is received, or a user-specified timeout expires.
- Parameters
-
[in] | nTicks | number of clock ticks (at the associated rate) to wait for the event to arrive. The value of QXTHREAD_NO_TIMEOUT indicates that no timeout will occur and the queue will block indefinitely. |
- Returns
- A pointer to the event. If the pointer is not NULL, the event was delivered. Otherwise the event pointer of NULL indicates that the queue has timed out.
- Precondition
- this function must:
- NOT be called from an ISR;
- be called from an extended thread;
- the thread must NOT be already blocked on any object.
-
also: the thread must NOT be holding a scheduler lock.
Definition at line 457 of file qxk_xthr.c.
◆ QXSemaphore_init()
initialize the counting semaphore
- Description
- Initializes a semaphore with the specified count and maximum count. If the semaphore is used for resource sharing, both the initial count and maximum count should be set to the number of identical resources guarded by the semaphore. If the semaphore is used as a signaling mechanism, the initial count should set to 0 and maximum count to 1 (binary semaphore).
- Parameters
-
[in,out] | me | pointer (see Object Orientation) |
[in] | count | initial value of the semaphore counter |
[in] | max_count | maximum value of the semaphore counter. The purpose of the max_count is to limit the counter so that the semaphore cannot unblock more times than the maximum. |
- Note
- QXSemaphore_init() must be called before the semaphore can be used (signaled or waited on).
- Precondition
- max_count must be greater than zero
Definition at line 79 of file qxk_sema.c.
◆ QXSemaphore_wait()
wait (block) on the semaphore
- Description
- When an extended thread calls QXSemaphore_wait() and the value of the semaphore counter is greater than 0, QXSemaphore_wait() decrements the semaphore counter and returns (true) to its caller. However, if the value of the semaphore counter is 0, the function places the calling thread in the waiting list for the semaphore. The thread waits until the semaphore is signaled by calling QXSemaphore_signal(), or the specified timeout expires. If the semaphore is signaled before the timeout expires, QXK resumes the highest-priority extended thread waiting for the semaphore.
- Parameters
-
[in,out] | me | pointer (see Object Orientation) |
[in] | nTicks | number 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 semaphore has been signaled and 'false' if a timeout occured.
- Note
- Multiple extended threads can wait for a given semahpre.
- Precondition
- this function must:
- NOT be called from an ISR;
- the semaphore must be initialized
- be called from an extended thread;
- the thread must NOT be already blocked on any object.
-
also: the thread must NOT be holding a scheduler lock.
Definition at line 114 of file qxk_sema.c.
◆ QXSemaphore_tryWait()
try wait on the semaphore (non-blocking)
- Description
- This function checks if the semaphore counter is greater than 0, in which case the counter is decremented.
- Parameters
-
- Returns
- 'true' if the semaphore has count available and 'false' NOT available.
- Note
- This function can be called from any context, including ISRs and basic threds (active objects).
- Precondition
- the semaphore must be initialized
Definition at line 199 of file qxk_sema.c.
◆ QXSemaphore_signal()
signal (unblock) the semaphore
- Description
- If the semaphore counter value is 0 or more, it is incremented, and this function returns to its caller. If the extended threads are waiting for the semaphore to be signaled, QXSemaphore_signal() removes the highest- priority thread waiting for the semaphore from the waiting list and makes this thread ready-to-run. The QXK scheduler is then called to determine if the awakened thread is now the highest-priority thread that is ready-to-run.
- Parameters
-
- Returns
- 'true' when the semaphore signaled and 'false' when the semaphore count exceeded the maximum.
- Note
- A semaphore can be signaled from many places, including from ISRs, basic threads (AOs), and extended threads.
- Precondition
- the semaphore must be initialized
Definition at line 240 of file qxk_sema.c.
◆ QXMutex_init()
initialize the QXK priority-ceiling mutex QXMutex
- Description
- Initialize the QXK priority ceiling mutex.
- Parameters
-
[in,out] | me | pointer (see Object Orientation) |
[in] | ceiling | the 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
l_rnd = seed;
}
rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd;
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 87 of file qxk_mutex.c.
◆ QXMutex_lock()
lock the QXK priority-ceiling mutex QXMutex
- Description
- Lock the QXK priority ceiling mutex QXMutex.
- Parameters
-
[in,out] | me | pointer (see Object Orientation) |
[in] | nTicks | number 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
l_rnd = seed;
}
rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd;
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 134 of file qxk_mutex.c.
◆ QXMutex_tryLock()
try to lock the QXK priority-ceiling mutex QXMutex
- Description
- Try to lock the QXK priority ceiling mutex QXMutex.
- Parameters
-
- 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 (<= 225). 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 269 of file qxk_mutex.c.
◆ QXMutex_unlock()
void QXMutex_unlock |
( |
QXMutex *const |
me | ) |
|
unlock the QXK priority-ceiling mutex QXMutex
- Description
- Unlock the QXK priority ceiling mutex.
- Parameters
-
- 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 (<= 225). However, each call to QXMutex_lock() or a successfull call to QXMutex_tryLock() must be ballanced by the matching call to QXMutex_unlock().
- Usage
l_rnd = seed;
}
rnd = l_rnd * (3U*7U*11U*13U*23U);
l_rnd = rnd;
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 358 of file qxk_mutex.c.