On Dec 14, 2023, at 3:29 PM, Noel Chiappa <jnc(a)mercury.lcs.mit.edu> wrote:
From: Bakul Shah
Now I'd probably call them kernel threads as
they don't have a separate
address space.
Makes sense. One query about stacks, and blocking, there. Do kernel threads,
in general, have per-thread stacks; so that they can block (and later resume
exactly where they were when they blocked)?
Exactly! If blocking was not required, you can do the work in an
interrupt handler. If blocking is required, you can't just use the
stack of a random process (while in supervisor mode) unless you
are doing some work specifically on its behalf.
Interestingly, other early systems don't seem to
have thought of this
structuring technique.
I suspect IBM operating systems probably did use them. At least TSO
must have. Once you start *accounting* (and charging) for cpu time,
this idea must fall out naturally. You don't want to charge a process
for kernel time used for an unrelated work!
*Accounting* is an interesting thing to think about. In a microkernel
where most of the work is done by user mode services, how to you keep
track of time and resources used by a process (or user)? This can
matter for things like latency, which may be part of your service level
agreement (SLA). This should also have a bearing on modern network
based services.
It makes sense to have a kernel process do this;
having the page fault code
do it just makes that code more complicated. (The code in V6 to swap
processes in and out is beautifully simple.) But it's apparently only obvious
in retrospect (like many brilliant ideas :-).
There was a race condition in V7 swapping code. Once a colleague and I
spent two weeks of 16 hour debugging days! We were encrypting before
swapping out and decrypting before swapping in. This changed timing enough
that the bug manifested itself (in the end about 2-3 times a day when the
system was running 5 or 6 kernel builds in parallel!). This is when I
really understood "You are not expected to understand this." :-)