NEXT UP previous
 

Next: Libary Calls

Example Threads - Case Study

You have seen that in Linux the main unit of concurrency is the process. In order to switch between executing one process and the next quite a lot of work is involved. This context switch overhead is necessary because, in general, Linux needs to make sure that any pair of processes are protected from interfering with each other, especially when you consider that the processes may not even belong to the same user.

Very often, however, you will want to write programs that are aware of the existence of each other and which can co-operate with each other towards some common goal. The standard solution to this problem is interprocess communication mechanisms.

It doesn't matter which of the IPC mechanisms you choose to use; there is still the context switch overhead to contend with whenever normal processes need to work together.

The way to overcome this is to use the concept of threads. Each Linux process has its own text, data and system memory areas and data structures, and its own time slices on the processor so that each process can proceed independently at its own pace. The idea behind threads is that each process can have its processor time slices shared between several concurrent threads, each of which also shares the memory and data structures of the process to which it belongs.

The amount of effort involved in context switching between two co-operating threads within a single process is much smaller than the effort of switching between two processes. This is mainly because the threads within a process are all sharing the same text, data and system memory areas and data structures so that no effort is expended in rearranging these things.

Since the threads are specifically designed to be cooperative and not antagonistic, nothing needs to be done by the kernel to protect the threads within a single process from each other.

Threads may, therefore, be considered as lightweight processes; light in the amount of effort required to context switch between them when compared to the effort involved with context switching standard (heavyweight) processes. Threads can generally be implemented in one of two different ways:

When threads are implemented within the kernel, the scheduling of the threads can be preemptive, in a similar way to the scheduling of processes themselves. This means that, whatever a thread is doing, when its time is up the kernel will interrupt it and pass control to the next thread to run.

In the case of threads provided in user space, the implementation is very much simpler, though now the thread scheduling becomes non-preemptive. This mehns that a context switch between threads can only take place when the current thread voluntarily releases control of the processor itself.

Non-preemptive scheduling is usually avoided in multi-user environments because it allows one user to hog the processor by refusing to give up control to allow other users to take a turn.

In the case of threads, however, non-preemptive scheduling does not present this problem as the threads are supposed to be co-operating on some task, not fighting over the processor.

The only real problem that does occur with user level threads, which can be avoided by kernel level threads, is with blocking I/O. With a non-preemptive scheduler, if one of the threads was to block on I/O (waiting for keyboard input, for instance), then that thread would be unable to release its control of the processor to allow another thread to run. This would effectively bring all the threads within that particular process to a halt until the blocked I/O was complete and control could be transferred. This just means that care must be taken when using user level threads to ensure that blocking a thread on I/O does not take place.

There are one or two packages available for Linux which implement threads in various ways. In general, they seem to be rather complex for our purposes so I will present a new, and very simple, user level threads library that you can easily incorporate into your own programs to experiment with the ideas behind threads.


NEXT UP previous
Next: Libary Calls