POSIX Thread Libraries

The authors have studied five libraries that can be used for multi-thread applications and herein present the results.

Recent years have seen an increase in the
popularity of threads, because there are many applications in which
threads are useful. In many aspects, threads operate in the same
manner as processes, but can execute more efficiently. All modern
operating systems today include some kind of support for thread
management. Moreover, threads have been standardized by the IEEE
Technical Committee on Operating Systems. This standard allows
users to write portable multi-thread programs.

As with other operating systems, Linux includes
multi-threading capability, and some multi-threading libraries are
available for Linux. We will describe a comparative study of five
threads packages for Linux: CLthreads, LinuxThreads, FSU Pthreads,
PC threads and Provenzano Pthreads. All libraries evaluated make
use of POSIX-compliant functionality. The main objective of this
study is to evaluate and compare the performance of some
multi-thread features to analyze the suitability of these libraries
for use in multi-thread applications. Also, we make a comparison
with Solaris threads.

The Notion of Threads

A thread is an independent flow of control within a process.
A traditional UNIX process has a single thread that has sole
possession of the process' memory and other resources. Threads
within the same process share global data (global variables, files,
etc.), but each thread has its own stack, local variables and
program counter. Threads are referred to as lightweight processes,
because their context is smaller than the context of a process.
This feature makes context switches between threads cheaper than
context switches between traditional processes.

Threads are useful for improving application performance. A
program with only one thread of control must wait each time it
requests a service from the operating system. Using more than one
thread lets a process overlap processing with one or more I/O
requests (see Figure 1). In multiprocessor machines, multiple
threads are an efficient way for application developers to utilize
the parallelism of the hardware.

This feature is especially important for client/server
applications. Server programs in client/server applications may get
multiple requests from independent clients simultaneously. If the
server has only one thread of control, client requests must be
served in a serial fashion. Using multi-thread servers, when a
client attempts to connect to the server, a new thread can be
created to manage the request.

Figure 1. Overlapping Processing and I/O Requests

In general, multi-threading capabilities are of great benefit
to certain classes of applications, typically server or parallel
processing applications, allowing them to make significant
performance gains on multiprocessor hardware, increase application
throughput even on uniprocessor hardware, and make efficient use of
system resources. Threads, however, are not appropriate for all
programs. For example, an application that must accelerate a single
compute-bound algorithm will not benefit from multi-threading when
the program is executed on uniprocessor hardware.

There are two traditional models of thread control:
user-level threads and kernel-level threads.

User-level thread packages usually run on top of an existing
operating system. The threads within the process are invisible to
the kernel. Threads are scheduled by a runtime system which is part
of the process code. Switching between user-level threads can be
done independently of the operating system. User-level threads,
however, have a problem: when a thread becomes blocked while making
a system call, all other threads within the process must wait until
the system call returns. This restriction limits the ability to use
the parallelism provided by multiprocessor platforms.

Kernel-level threads are supported by the kernel. The kernel
is aware of each thread as a scheduled entity. In this case, a set
of system calls similar to those for processes is provided, and the
threads are scheduled by the kernel. Kernel threads can take
advantage of multiple processors; however, switching among threads
is more time-consuming because the kernel is involved.

There are also hybrid models, supporting
user-level and kernel-level threads. This gives the advantages of
both models to the running process. Solaris offers this kind of
model.

POSIX Threads

Threads have been standardized by the IEEE Technical
Committee on Operating Systems. The base for the POSIX standard
(POSIX 1003.1), The Portable Operating Systems
Interface, defines an application program interface
which is derived from UNIX but may as well be provided by any other
operating system. This standard includes a set of Thread
Extensions (POSIX 1003.1c). These thread extensions
provide the base standard with interfaces and functionality to
support multiple flows of control within a process. The facilities
provided represent a small set of syntactic and semantic extensions
to POSIX 1003.1 in order to support a convenient interface for
multi-threading functions.

The interfaces in this standard are specifically targeted at
supporting tightly coupled multitasking environments, including
multiprocessor systems and advanced language constructs. The
specific functional areas covered by this standard and their scopes
include:

Thread management:
creation, control and termination of multiple flows of control in
the same process under the assumption of a common shared address
space.

Synchronization
primitives: mutual exclusion and condition variables,
optimized for tightly coupled operation of multiple control flows
within a process.