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 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.
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 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).
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 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.
QXK provides most blocking mechanisms found in traditional blocking RTOS kernels:
As all preemptive kernels, QXK requires the QP 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 Application might choose to share selected resources. However, such QP 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.
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.
QP Framework shall provide preemptive non-blocking QXK kernel as one of the built-in kernels.
QXK kernel shall support basic tasks for execution of Active Objects and shall handle them like the QK kernel.
QXK kernel shall support extended tasks for execution of blocking threads and shall execute them like a conventional RTOS kernel.
QXK kernel shall support mixing basic and extended tasks.
QXK kernel shall support interactions between basic and extended tasks.
QXK kernel shall support counting semaphores with optional timeout.
QXK kernel shall support blocking event queues with optional timeout.
QXK kernel shall support blocking recursive mutexes with optional timeout.