Now that we've defined what a thread context is and how we can synchronize
its environment, we need a way to switch between contexts. Fortunately,
``C'' provides a way to save and replace the current context using the
setjmp and longjmp commands. By using the two in conjunction (see
mpthd.c), we can switch between threads quickly and portably.
However, a context switch must be one of those autonomous operations: we
cannot be interrupted right after we have saved the old context yet have
not yet jumped into the new. Therefore, I protect the operation in a
mpsem (see code) to insure that interrupts are disabled and
the processor has control of a new context before releasing its old
one. You will notice the call checks if new context to be switched to is
valid (detecting stack overflow) and if it is already the current context
(detouring self deadlock). But perhaps least conspicuous is
mpthd
return of the id of the previous thread; it must be
returned from a switch if it is ever to be obtained reliably, so it is
copied into oldmpthd so the receiving thread can read it before it
restores its interrupt status.
Thus the
mpthd isolates and encapsulates the complications
of context switching into one safe and convenient procedure call.