Information Technology Reference
In-Depth Information
What about interrupts and exceptions? Can we implement something like a timer
interrupt so that we can suspend a long-running thread so that it does not monopolize
the processor? Yes; on most operating systems, we can. Most operating systems
implement signal handlers or something similar, which allows the operating system to
trigger execution of specified handler code within a user-level process when a specified
event like a timer interrupt or memory exception occurs.
So, first the user-level threads library for some process P uses a system call to reg-
ister a signal handler with the kernel. When a hardware timer interrupt occurs, the hard-
ware and kernel software save P's register state and run the kernel's handler. Rather
than restoring P's register state and resuming P where it was interrupted, kernel's han-
dler copies P's saved registers into P's address space (e.g., onto a signal stack that P
has registered or onto P's existing stack) and restore a slightly modified state with the a
stack pointer changed to point to where this state was saved and the instruction pointer
changed to point to the signal handler code that P registered. Thus, P's signal handler
is invoked with the state of the previously running thread stored on its stack. It can then
save that state to a TCB within the process and restore the state of some other TCB on
the process's ready list.
This approach essentially virtualizes interrupts and exceptions, providing a user-
level process with a very similar picture to the one the kernel gets when these events
occur.
Why would you do this? Early libraries for threads often took this pure user-level
approach for the simple reason that few operating systems supported multi-threaded
processes. Even once operating system support for threads became widespread, pure
user-level threads were sometimes used to minimize dependencies on the operating
systems and to maximize portability; for example the earliest implementations of Sun's
Java Virtual Machine (JVM) implemented what were called green threads, a pure user-
level implementation of threads.
Why wouldn't you do this? From the kernel's point of view, a process that uses a
library to implement pure user-level threads appears to be single-threaded no matter
how many threads the user-level library creates.
As a result, pure user-level threads do not meet all of the goals of threads outlined
at the start of this chapter. In particular, although pure user-level threads can be used
for program structure, they do not help with performance (parallel processing) because
the kernel only sees one “thread” that it can schedule. Similarly, they do not help with
performance (coping with high-latency I/O) because if one thread blocks due to a long-
running system call, the kernel does not have access to (and is unaware of) other TCBs
that it could enable.
Today, most programs make use of kernel-supported threads rather than pure user-
level threads. Major operating systems support threads and support them using fairly
standard abstractions, so the past motivations are seldom compelling enough to com-
pensate for the significant performance disadvantages.
Hybrid implementations. Although today few threads packages operate completely at
user level, many split their work between the user-level library and the operating system
kernel to reduce overheads by avoiding mode switches into the kernel for some of their
operations.
Search WWH ::




Custom Search