Part of the kernel's job is to determine which thread runs and when.
First, let's look at when the kernel makes its scheduling decisions.
The execution of a running thread is temporarily suspended
whenever the microkernel is entered as the result of a
kernel call, exception, or hardware interrupt. A scheduling
decision is made whenever the execution state of any thread
changes—it doesn't matter which processes the
threads might reside within. Threads are scheduled globally
across all processes.
Normally, the execution of the suspended thread will resume,
but the thread scheduler will perform a context switch from one
thread to another whenever the running thread:
- is blocked
- is preempted
- yields
- When is a thread blocked?
- The running thread is blocked when it must wait for some
event to occur (response to an IPC request, wait on a mutex,
etc.). The blocked thread is removed from the running array
and the highest-priority ready thread is then run. When the
blocked thread is subsequently unblocked, it's placed on
the end of the ready queue for that priority level.
- When is a thread preempted?
- The running thread is preempted when a higher-priority
thread is placed on the ready queue (it becomes READY, as
the result of its block condition being resolved). The
preempted thread is put at the beginning of the ready queue for
that priority and the higher-priority thread runs.
- When is a thread yielded?
- The running thread voluntarily yields the processor
(sched_yield())
and is placed on the end of the
ready queue for that priority. The highest-priority thread
then runs (which may still be the thread that just yielded).