The QNX microkernel generates events for more than just system calls. The following are some of the activities that generate events:
In addition, the Instrumented Kernel also inserts “artificial” events for:
Also, single kernel calls or system activities may actually generate more than one event.
One of the powerful features of the QNX RTOS is its ability to run multiple threads. Having more than one thread increases the level of complexity—the OS must handle threads of differing priorities competing with each other.
In our example we'll use two threads:
Thread | Priority |
---|---|
A | High |
B | Low |
Now we'll watch them run, assuming both “start” at the same time:
When logging starts, the Instrumented Kernel sends information about each thread. Existing processes will appear to be created during this procedure. |
Time | Thread | Action | Explanation |
---|---|---|---|
t1 | A | Create | Thread is created. |
t2 | A | Block | The thread is waiting for, say, I/O; it can't continue without it. |
t3 | B | Create | Rather than sit idle, the kernel runs next highest priority thread. |
t4 | B | Kernel Call | Thread B is working. |
t4.5 | n/a | n/a | I/O completed; Thread A is ready to run. |
t5 | B | Block | Thread A is now ready to run—it preempts thread B. |
t6 | A | Run | Thread A resumes. |
t7 | A | Dies | Its task complete, the thread terminates. |
t8 | B | Runs | Thread B continues from where it left off. |
t9 | ...and so on... | ...and so on... | ...and so on... |
Threads don't switch instantaneously—after one thread blocks or yields to another, the kernel must save the settings before running another thread. The time to save this state and restore another is known as thread context-switch time. This context-switch time between threads is small, but important.
In some cases, two or more threads (or processes) may switch back and forth without actually accomplishing much. This is akin to two overly polite people each offering to let the other pass through a narrow door first— neither of them gets to where they're going on time (two aggressive people encounter a similar problem). This type of problem is exactly what the SAT can quickly and easily highlight. By showing the context-switch operations in conjunction with thread state transitions, you can quickly see why otherwise fast systems seem to “crawl.”
In order to achieve maximum responsiveness, much of the QNX Neutrino microkernel is fully preemptible. In some cases, this means that when a thread is interrupted in a kernel call, it won't be able to restart exactly where it began. Instead, the kernel call will be restarted—it “rewinds” itself. The SAT tries to hide the spurious calls but may not succeed in suppressing them all. As a result, it's possible to see several events generated from a specific thread that has been preempted. If this occurs, the last event is the actual one.