QP/C++  8.0.0
Real-Time Embedded Framework
Loading...
Searching...
No Matches
Preemptive Dual-Mode Kernel

Preemptive Non-Blocking KernelNon-Functional Requirements

Concepts & Definitions

The Active Object model of computation can work with a wide range of real-time kernels. Among others, event-driven Active Objects can be executed by a traditional, blocking RTOS kernel, where each Active Object runs in its own RTOS thread structured as an event-loop. However, using a traditional, blocking RTOS to execute non-blocking Active Objects is wasteful. As demonstrated in the QK Preemptive Non-Blocking Kernel, non-blocking Active Objects can be executed more efficiently as one-shot, run-to-completion steps.

QXK Dual-Mode Kernel

QXK is a preemptive, fixed-priority, dual-mode (blocking / non-blocking) kernel that executes Active Objects like the QK kernel (basic tasks), but can also execute traditional blocking threads (extended tasks). In this respect, QXK behaves like a traditional RTOS.

Remarks
QXK adopts the "basic/extended tasks" terms from the OSEK/AUTOSAR Operating System↑ specification [OSEK:03]. Other real-time kernels might use different terminology for similar concepts.

QXK has been designed specifically for combining event-driven Active Objects with traditional code that requires blocking, such as commercial middleware (TCP/IP stacks, UDP stacks, embedded file systems, etc.) or legacy software. To this end, QXK is not only more efficient than running QP/C++ on top of a traditional 3rd-party RTOS (because non-blocking basic tasks take less stack space and CPU cycles for context switch than the much heavier extended tasks). But the biggest advantage of QXK is that it protects the application-level code from inadvertent mixing of blocking calls inside the event-driven Active Objects. Specifically, QXK "knows" the type of the task context (extended/basic) and asserts internally if a blocking call (e.g., semaphore-wait or a time-delay) is attempted in a basic task (Active Object).

Note
The QXK dual-mode kernel is significantly more complex than the QV non-preemptive kernel and the QK preemptive non-blocking kernel, and therefore it is not recommended for safety-critical applications.

Basic Tasks

Basic tasks are one-shot, non-blocking, run-to-completion activations. The basic-task can nest on the same stack. Also, context switching from a basic-task to another basic-task requires only activation of the basic-task, which is simpler and faster than full context-switch required for extended-tasks (that QXK also supports, see below).

Extended tasks

Extended tasks are endless loops allowed to block. Extended tasks require private per-task stacks, as in conventional RTOS kernels. Any switching from basic-to-extended task or extended-to-extended task requires full context switch.

Remarks
QXK is a unique dual-mode kernel on the market that supports interleaving the priorities of basic tasks and extended tasks. Other dual-mode kernels typically limit the priorities of basic tasks to be always higher (more urgent) than any of the extended tasks.

QXK Blocking Mechanisms

QXK provides most blocking mechanisms found in traditional blocking RTOS kernels:

  • Counting Semaphores with optional timeout that can block multiple extended-tasks;
  • Binary Semaphores (as a subset of counting semaphores);
  • Blocking Event Queue with optional timeout bound to each extended-task;
  • Priority-Ceiling, recursive Mutexes with optional timeout;

Selective Scheduler Locking

As all preemptive kernels, QXK requires the QP/C++ Application to be very careful with any resource sharing among Active Objects. Ideally, the Active Objects should communicate exclusively via events and otherwise should not share any resources. However, at the cost of increased coupling among Active Objects, QP/C++ Application might choose to share selected resources. However, such QP/C++ Application takes the burden on itself to apply a mutual exclusion mechanism while accessing any shared resources.

QXK kernel provides selective scheduler locking as a powerful mutual exclusion mechanism. Specifically, before accessing a shared resource, an Active Objects can lock the QXK scheduler up to the specified priority ceiling. This prevents Active Object preemption up to the specified priority ceiling, while not affecting Active Objects (or interrupts) of priority higher than the priority ceiling. After accessing the shared resource the Active Object must unlock the QXK scheduler.

Selective scheduling locking is a non-blocking mechanism. If an Active Object that needs to protect a shared resource is running, it means that all Active Objects of higher priority have no events to process. Consequently, simply preventing activation of higher-priority AOs that might access the resource is sufficient to guarantee the mutually exclusive access to the resource. Of course, you don't need to worry about any lower-priority AOs that might be preempted because they never resume until the current AO runs to completion.

Selective scheduler lock requests made by the same Active Object can nest. The nested lock requests can only increase the priority ceiling. Also, the nested lock requests must unlock the scheduler by restoring the previous priority ceiling.

Task-Level Response

As a fully preemptive, fixed-priority kernel, QXK always executes the highest-priority task that is ready to run (is not blocked). The scheduling algorithm used in QXK meets all the requirement of the Rate Monotonic Scheduling (a.k.a. Rate Monotonic Analysis — RMA) and can be used in hard real-time systems.

Requirements

Note
As stated above, due to its complexity the QXK dual-mode kernel is not recommended for safety-critical applications. Therefore, this section contains only high-level requirements for the QXK kernel without the details needed to verify and validate QXK for functional safety.

SRS_QP_QXK_00

SRS_QP_QXK_00 : QP/C++ Framework shall provide preemptive non-blocking QXK kernel as one of the built-in kernels.
Description
QP/C++ Framework shall provide QXK kernel implementation and ports to the supported CPU/compiler combinations as one of the optional software components. QP/C++ Application can then choose the QXK kernel to execute Active Objects and extended tasks. Such a selection is exclusive, meaning that when QP/C++ Application selects the QXK kernel, other kernels are excluded and cannot be used.
Description
QP/C++ Framework can implement the QXK kernel component by re-using already existing mechanisms, such as event queues for Active Objects, event delivery mechanisms, event memory management, etc.
Forward Traceability (truncated to 2 level(s))

SRS_QP_QXK_10

SRS_QP_QXK_10 : QXK kernel shall support basic tasks for execution of Active Objects and shall handle them like the QK kernel.
Description
QXK kernel shall provide API for designating an Active Object, which will require a unique priority and event queue, but not a private stack. Subsequently, QXK kernel shall execute thus designated Active Object as a basic-task by dispatching events to its state machine.
Forward Traceability (truncated to 2 level(s))

SRS_QP_QXK_11

SRS_QP_QXK_11 : QXK kernel shall support extended tasks for execution of blocking threads and shall execute them like a conventional RTOS kernel.
Description
QXK kernel shall provide API for designating an extended task (distinct from designating an Active Object), which will require a unique priority, optional event queue, and a private stack. Subsequently, QXK kernel shall execute thus designated object as an extended task. If an extended task is configured with an event queue, such an extened task can block on that queue and receive events through that queue.
Forward Traceability (truncated to 2 level(s))

SRS_QP_QXK_12

SRS_QP_QXK_12 : QXK kernel shall support mixing basic and extended tasks.
Description
QXK shall allow combining basic tasks (Active Objects) and extended tasks (threads) in a single application. QXK shall allow interleaving the unique priorities of basic tasks and extended tasks and prioritize them according to the same uniform prioritization scheme described in SRS_QP_AO_10.
Forward Traceability (truncated to 2 level(s))

SRS_QP_QXK_13

SRS_QP_QXK_13 : QXK kernel shall support interactions between basic and extended tasks.
Description
QXK shall support the following integrated mechanisms for communication between extended and basic tasks:
  • Extended tasks can post or publish events to Active Objects;
  • Extended tasks can post or publish events to other extended tasks (that provide an event queue);
  • Extended tasks that provide an event queue can subscribe to events and thus can participate in the publish/subscribe event delivery;
  • Basic tasks (Active Objects) can signal semaphores and post events to extended tasks (those that provide an event queue).
Forward Traceability (truncated to 2 level(s))

SRS_QP_QXK_20

SRS_QP_QXK_20 : QXK kernel shall support counting semaphores with optional timeout.
Description
QXK shall support counting semaphores as on of the standard blocking mechanisms. As a special case, counting semaphore with maximum 1 shall behave as a binary semaphore. The blocking semaphore-wait operation (with optional timeout) shall be allowed only inside the extended threads. However, signaling a semaphore is allowed both from Active Objects and ISRs.
Forward Traceability (truncated to 2 level(s))

SRS_QP_QXK_21

SRS_QP_QXK_21 : QXK kernel shall support blocking event queues with optional timeout.
Description
For extended tasks configured with an event queue, QXK shall support blocking on that event queue (with optional timeout) inside the endless loop of the extended task.
Forward Traceability (truncated to 2 level(s))

SRS_QP_QXK_22

SRS_QP_QXK_22 : QXK kernel shall support blocking recursive mutexes with optional timeout.
Description
QXK shall support mutexes as on of the standard mutual exclusion mechanisms. The blocking mutex-lock operation (with optional timeout) shall be allowed only inside the extended threads. The mutex shall support the priority-ceiling protocol to prevent unbounded priority inversion. The mutex shall also allow recursive locking (by the same extended task).
Forward Traceability (truncated to 2 level(s))

Preemptive Non-Blocking KernelNon-Functional Requirements