Scheduling priority

QNX SDP8.0System ArchitectureDeveloperUser

Every thread is assigned a priority. The thread scheduler selects the next thread to run by comparing the priorities of READY threads (i.e., those capable of using a processor).

Single-core ready queue

On a single-core system, the READY thread with the highest priority is selected to run.

The following diagram shows the ready queue for a single-core system with five threads (B–F) that are READY. Thread A is currently running. All other threads (G–Z) are BLOCKED. Threads A, B, and C are at the highest priority, so they'll share the processor based on their scheduling policies.

Figure 1The ready queue in a single-core system.

READY processes

Multicore (SMP) ready queue

On a multicore (SMP) system, the scheduler runs the highest-priority READY thread on one of the available processors (or CPUs, or cores). Additional processors run other threads in the system, though not necessarily the next highest-priority threads. Further details are given in the Thread displacement on multicore systems section of the Programmer's Guide.

For each scheduling decision on a given processor, the scheduler looks at the highest priority READY threads that can run on each cluster (i.e., group of associated processors) that the processor belongs to, and then selects the highest-priority thread from this set.

Threads on a cluster at the same priority are usually queued in FIFO, with the following exceptions:
  • If a high-priority thread preempts the running thread, then it becomes the head of the thread list for its priority.
  • When a thread changes priority. For more information, go to the pthread_setschedprio() entry in the QNX OS C Library Reference.

For information about clusters and configuring processor affinity for threads (i.e., associating threads with specific clusters), refer to the Processor affinity, clusters, runmasks, and inherit masks section of the QNX OS Programmer's Guide.

Scheduling priority levels

Every thread is assigned a priority. It can be explicitly set, but if it's not set explicitly, a thread inherits the priority of its parent thread by default.

The OS supports a total of 256 scheduling priority levels. Here's a summary, where priority is either 63 (the default) or a value you set with the -P option for procnto (see Setting the upper end of the range of unprivileged priorities):
Priority level Owner
0 Idle threads
1 through priority − 1 Unprivileged or privileged processes
priority through 253 Privileged processes with the PROCMGR_AID_PRIORITY ability (see procmgr_ability() in the C Library Reference)
254 Per-processor clock Interrupt Service Threads (ISTs) and other in-kernel ISTs
255 Per-processor InterProcessor (IPI) ISTs
Note:
To prevent priority inversion, the kernel may temporarily boost a thread's priority. For more information, see Priority inheritance and mutexes later in this chapter, and Priority inheritance and messages in the Interprocess Communication (IPC) chapter. The initial priority of the kernel's server threads is 10, but the first thing they all do is block in a MsgReceive(), so after that they operate at the priority of threads that send messages to them.

Setting the upper end of the range of unprivileged priorities

You can change the allowed priority range for unprivileged processes with the -P option for procnto:
procnto-smp-instr -P priority

You can append an s or S to this option if you want out-of-range priority requests by default to use the maximum allowed priority (reach a maximum saturation point) instead of resulting in an error. When you're setting a priority, you can wrap it in one these (non-POSIX) macros to specify how to handle out-of-range priority requests:

  • SCHED_PRIO_LIMIT_ERROR(priority)—indicate an error
  • SCHED_PRIO_LIMIT_SATURATE(priority)—use the maximum allowed priority

Setting the priority of a child process

When spawning a child process with a priority that's different than its parent, be aware that posix_spawn() and spawn() calls block until the initialization of the child process is complete. Because the child process’s main thread performs the initialization at the priority set for the child process, it may create a priority inversion if that priority is lower than the parent.

Page updated: