Once the additional processors have been released and are
running, all processors are considered peers for the
scheduling of threads.
- Scheduling
- The scheduling policy follows the same rules as on a uniprocessor system.
That is, the highest-priority thread
will be running on an available processor. If a new thread
becomes ready to run as the highest-priority thread in the
system, it will be dispatched to the appropriate processor. If
more than one processor is selected as a potential target,
then the microkernel will try to dispatch the thread to the
processor where it last ran. This affinity is used as an
attempt to reduce thread migration from one processor to
another, which can affect cache performance.
In an SMP system, the scheduler has some flexibility in
deciding exactly how to schedule the other threads,
with an eye towards optimizing cache usage and minimizing thread migration.
This could mean that some processors will be running lower-priority threads
while a higher-priority thread is waiting to run on the processor it last
ran on.
The next time a processor that's running a lower-priority thread makes
a scheduling decision, it will choose the higher-priority one.
In QNX Neutrino 7.0.1 or later, you can use
SchedCtl()
with the SCHED_CONFIGURE command to tune this behavior.
In any case, the realtime
scheduling rules that were in place on a uniprocessor system
are guaranteed to be upheld on an SMP system.
- Kernel locking
- In a uniprocessor system, only one thread is allowed to
execute within the microkernel at a time. Most kernel
operations are short in duration (typically a few
microseconds on a Pentium-class processor). The microkernel
is also designed to be completely preemptible and
restartable for those operations that take more time. This
design keeps the microkernel lean and fast without the need
for large numbers of fine-grained locks. It is interesting
to note that placing many locks in the main code path
through a kernel will noticeably slow the kernel down. Each
lock typically involves processor bus transactions, which can
cause processor stalls.
In an SMP system, QNX Neutrino maintains this philosophy of only
one thread in a preemptible and restartable kernel. The
microkernel may be entered on any processor, but only one
processor will be granted access at a time.
For most systems, the time spent in the microkernel
represents only a small fraction of the processor's
workload. Therefore, while conflicts will occur, they should
be more the exception than the norm. This is especially true
for a microkernel where traditional OS services like
filesystems are separate processes and not part of the
kernel itself.
- Interprocessor interrupts (IPIs)
- The processors communicate with each other through IPIs
(interprocessor interrupts). IPIs can effectively schedule
and control threads over multiple processors. For example,
an IPI to another processor is often needed when:
- a higher-priority thread becomes ready
- a thread running on another processor is hit with a signal
- a thread running on another processor is canceled
- a thread running on another processor is destroyed