In previous sections the concept of context switch has been differentiated from that of process switch, and it has been remarked that performing an OS service, while usually requiring a context switch, not always makes a process switch necessary, depending on the scheduling policy adopted by the OS.
A different way to regard the same issue consists in differentiating between two independent attributes involved by the concept of process, namely:
The former refers to the fact that the management of a process involves, on the OS side, the ``investing'' of resources in terms of allocated main memory, OS table update, availability of I/O streams and devices.
The latter points at the process as being the execution of a program, which may be interleaved with that of other processes in a multiprogramming environment, and involves the management of process states, priority, queues, etc.
Now it should be noted that, even if in traditional operating systems the above attributes uniquely coexist within one process, nothing in the above forbids considering a collection of programs, all sharing resources, as a unit of dispatching. The recognition of the independence of these two aspects has lead to the invention of threads or lightweight processes.
Though the relatively recent concept of thread has found different implementation in various operating system, the most common one in an arrangement in which multiple threads coexist within one process. In this case threads can be easily visualized as as parallel traces of the same process independently executed (think of something like having multiple program counters on the same instruction list - that of the process). This approach has been implemented in OS/2, Sun OS, Lynx and, most notably, Mach.
In Lynx, a real-time, Posix abiding OS, processes are implemented in much the same way as is usual in UNIX family: each process is allowed an address space in (virtual) memory which is protected from other processes' interference, the kernel executes mostly in the user process context and keeps in the user area of a process all the process-related information that is needed only when the process is running - most notably the kernel stack. However there are two major differences with other ``traditional'' unices (e.g BSD, System V, Ultrix, USD, etc.): Lynx is a real-time operating system and allows for the spawning of ``parallel threads'', or pthreads, within a process (because this is about the only way to be real-time for real).
Real-time means essentially that the OS guarantees that it'll honor an interrupt request within a fixed response time, which is comparable to a context-switch delay. This is essential for most application involving automatic control, where a computer (really a controller program sitting on top of the OS) is put in a feedback loop between some machinery controlling a plant and devices sensing the plant's behaviour. An unpredictable response time for the controller makes the control design problem very difficult, if not altogether impossible. Yet traditional unices cannot be interrupted while executing in kernel mode (disabling the CPU's interrupt pins is about the first thing that both system calls and system utilities do when they gain control), and hence the interrupt response time can be as long as the execution time of the longest system routine. Lynx can be interrupted in kernel mode, instead, and also offers some quite sophisticated ``timer'' system calls for finely tuning the timing of the application's operations.
Since fast controller's are always welcome in control application (you can always slow them down if you want, while boosting a FIAT into a Ferrari is still the subject of basic research...), Lynx also offer pthreads, which allow a designer to nicely decompose the control application in parallel time-bound tasks (maybe operating at radically different time scales), without incurring in a process switch overhead, and with the bonus of fast inter-thread communication through a shared memory area. Each pthread has the following attributes:
Note that operations like suspension (i.e. swapping to disk) are still performed at the process level, and they affect all the pthreads within a process when they occur.
A very common application of threads outside real-time control is on the server side of client-server application over computer networks. In a typical scenario for these applications, a server program sits idle listening to a communication port, waiting for service requests from remote clients. When one arrives, according to how it's designed, it can: