7.1 Multiplexing
Xv6 multiplexes by switching each CPU from one process to
another in two situations. First, xv6’s
sleep
and
wakeup
mechanism switches when a process makes a system
call that blocks (has to wait for an event), typically in read
,
wait
,
or
sleep
.
Second, xv6 periodically forces a switch to cope with
processes that compute for long periods without blocking.
The former are voluntary switches;
the latter are called involuntary.
This multiplexing creates the illusion that
each process has its own CPU.
Implementing multiplexing poses a few challenges. First, how to switch from one
process to another?
The basic idea is to save and restore CPU registers,
though the fact that this cannot be expressed in C makes it tricky.
Second, how to force
switches in a way that is transparent to user processes? Xv6 uses the
standard technique in which a hardware timer’s interrupts drive context switches.
Third, all of the CPUs switch among the same set of processes, so a
locking plan is necessary to avoid races. Fourth, a process’s
memory and other resources must be freed when the process exits,
but it cannot do all of this itself
because (for example) it can’t free its own kernel stack while still using it.
Fifth, each CPU of a multi-core machine must remember which
process it is executing so that system calls affect the correct
process’s kernel state.
Finally, sleep
and wakeup
allow a process to give up
the CPU and wait to be woken up by another process or interrupt.
Care is needed to avoid races that result in
the loss of wakeup notifications.