546 lines
17 KiB
Groff
546 lines
17 KiB
Groff
'\"macro stdmacro
|
|
.\"
|
|
.\" ----------------
|
|
.TH pthreads 5
|
|
.\"
|
|
.\" ----------------
|
|
.SH NAME
|
|
pthreads
|
|
\- introduction to POSIX thread characteristics
|
|
.\"
|
|
.\" ----------------
|
|
.SH DESCRIPTION
|
|
This man page is intended as an overview of the POSIX thread model
|
|
as implemented in IRIX;
|
|
it is not an introduction to thread programming or a
|
|
detailed description of the IRIX implementation.
|
|
.PP
|
|
Thread programming is motivated by two concerns:
|
|
.\" ----------------
|
|
.TP 5
|
|
.B Application Performance
|
|
.PD 0
|
|
.RS
|
|
.IP \(bu 4
|
|
On a multiprocessor multiple threads may run at the same time.
|
|
.\"
|
|
.IP \(bu 4
|
|
Operations that cause the caller to wait do not prevent other
|
|
threads (in the same process) from making progress.
|
|
.RE
|
|
.PD
|
|
.\" ----------------
|
|
.TP
|
|
.B Programming Model
|
|
.PD 0
|
|
.RS
|
|
.IP \(bu 4
|
|
Complex applications can be structured more elegantly by partitioning
|
|
with threads.
|
|
.\"
|
|
.IP \(bu 4
|
|
Threads share many resources implicitly which can simplify co-operative
|
|
algorithms.
|
|
.RE
|
|
.PD
|
|
.\"
|
|
.PP
|
|
In the past a UNIX process has been thought of as having a single thread.
|
|
The POSIX thread programming model (known as
|
|
.IR pthreads )
|
|
introduces the concept of multiple threads within a single process.
|
|
A POSIX thread is an executable entity that belongs to a process.
|
|
It contains sufficient state to enable it to run on a processor
|
|
independently of its fellows.
|
|
In most other respects threads share state with their host process.
|
|
The vast majority of interfaces and features work
|
|
the same way in a multi-threaded process as an unthreaded one.
|
|
.PP
|
|
The POSIX threads API provides a set of interfaces and semantics
|
|
for creating and controlling threads.
|
|
Because the interfaces are defined by the ISO standards organisation
|
|
an application using them may enjoy the benefits of parallel programming
|
|
without sacrificing portability.
|
|
.\"
|
|
.\" ----------------
|
|
.SS Applications
|
|
To create a pthread process an application must be linked with the
|
|
pthread run-time library.
|
|
It is also recommended that the thread safe options be enabled at
|
|
compile time using the feature test macro,
|
|
.BR _POSIX_C_SOURCE .
|
|
.Ex
|
|
cc -D_POSIX_C_SOURCE=199506L app.c -llib0 -llib1 ... -lpthread
|
|
.Ee
|
|
See
|
|
.IR intro (3),
|
|
section 3P for further details.
|
|
.\"
|
|
.\" ----------------
|
|
.SS Components
|
|
POSIX threads introduces a number of thread components.
|
|
.\" ----------------
|
|
.TP 5
|
|
.B Attribute
|
|
An attribute is a characteristic of something that defines its behaviour.
|
|
Most of the objects introduced by pthreads have characteristics
|
|
which are set when it is created;
|
|
indeed some characteristics may only be set at that time.
|
|
A set of characteristics may be specified in an attribute object
|
|
which is passed to the creation interface.
|
|
An analogy is a mould or template that is used to shape
|
|
some artifact.
|
|
Every attribute has a default value and the attribute object itself
|
|
is optional.
|
|
.\" ----------------
|
|
.TP
|
|
.B Thread
|
|
A thread executes code.
|
|
It is created using
|
|
.IR pthread_create ()
|
|
and either inherits characteristics from its creator or has them
|
|
specified via creation attributes.
|
|
The
|
|
.IR pthread_attr_ *
|
|
interfaces may be used to create a thread attributes object.
|
|
.br
|
|
Many features of the process are shared by its threads, including
|
|
process and user ids (PID, UID), file descriptors,
|
|
memory (including text and data)
|
|
and signal handlers.
|
|
.br
|
|
Each thread has a unique identity which is used by a number of
|
|
pthread interfaces.
|
|
Thread ids may be compared using
|
|
.IR pthread_equal ().
|
|
.br
|
|
Threads terminate with an exit status [see
|
|
.IR pthread_exit ()].
|
|
By default the thread identity and exit status persist after the thread
|
|
has terminated until the status is retrieved using
|
|
.IR pthread_join ().
|
|
An application should either retrieve this status or arrange for
|
|
it to be automatically discarded on thread termination using
|
|
.IR pthread_detach ()
|
|
or setting the detach thread attribute.
|
|
.\" ----------------
|
|
.TP
|
|
.B Mutex Lock
|
|
A mutex lock facilitates exclusive access by a thread to a resource.
|
|
Only one thread may own a mutex at a time and is thus guaranteed
|
|
exclusive access.
|
|
.br
|
|
Mutex interfaces are described on the
|
|
.IR pthread_mutex_ *
|
|
man pages.
|
|
The
|
|
.IR pthread_mutexattr_ *
|
|
interfaces may be used to create a mutex attributes object.
|
|
Attributes include error checking, recursion and owner priority.
|
|
Mutexes are intended to be lightweight and only owned for
|
|
brief periods of time.
|
|
.\" ----------------
|
|
.TP
|
|
.B Condition Variable
|
|
A condition variable synchronises threads with an event of interest.
|
|
Condition variables allow a thread to wait for an event and be woken
|
|
up when the event occurs;
|
|
the nature of the event is determined by the application.
|
|
.br
|
|
Condition variable interfaces are described on the
|
|
.IR pthread_cond_ *
|
|
man pages.
|
|
The
|
|
.IR pthread_condattr_ *
|
|
interfaces may be used to create a condition variable attributes object.
|
|
.\" ----------------
|
|
.TP
|
|
.B Read-Write Lock
|
|
A read-write lock facilitates shared access for read and exclusive access for
|
|
write by threads to a resource.
|
|
They are used in conjunction with resources which are
|
|
frequently read but infrequently changed (written).
|
|
.br
|
|
Read-write lock interfaces are described on the
|
|
.IR pthread_rwlock_ *
|
|
man pages.
|
|
The
|
|
.IR pthread_rwlockattr_ *
|
|
interfaces may be used to create a read-write lock attributes object.
|
|
.\" ----------------
|
|
.TP
|
|
.B Semaphore
|
|
A semaphore synchronises threads with a counter.
|
|
Semaphores are not part of pthreads per se and do not have an
|
|
associated attributes object.
|
|
However anonymous semaphores provide a
|
|
.I pshared
|
|
flag (for semaphores which are private to the process) which
|
|
allows pthreads to optimise access [see
|
|
.IR sem_init (3C)].
|
|
Semaphore interfaces are described on the
|
|
.IR sem_ *
|
|
man pages.
|
|
.\"
|
|
.\" ----------------
|
|
.SS Semantics
|
|
POSIX threads introduces the following special semantics.
|
|
.\" ----------------
|
|
.TP 5
|
|
.B Cancellation
|
|
A cancellation request is a request for a thread to terminate.
|
|
Each thread specifies whether and when to act on cancellation requests
|
|
using its cancelability state and type.
|
|
A request is made with
|
|
.IR pthread_cancel ()
|
|
and the state and type are set with
|
|
.IR pthread_setcancelstate ()
|
|
and
|
|
.IR pthread_setcanceltype ().
|
|
Termination handlers may be established to execute code when a thread
|
|
terminates for some reason including acting on a cancellation request.
|
|
.\" ----------------
|
|
.TP
|
|
.B Signals
|
|
In the pthread signal model all threads share the signal disposition [see
|
|
.IR sigaction (2)]
|
|
but each thread has its own signal mask of blocked signals.
|
|
Signals may be sent to individual threads using the
|
|
.IR pthread_kill ()
|
|
interface.
|
|
Each thread may change its own mask using
|
|
.IR pthread_sigmask ().
|
|
In IRIX,
|
|
.IR sigprocmask (2)
|
|
is equivalent to
|
|
.IR pthread_sigmask ()
|
|
but a portable pthread application should only use the latter.
|
|
.br
|
|
A signal is delivered to at most one thread; it is not broadcast to all
|
|
threads.
|
|
.RS
|
|
.IP \(bu 4
|
|
When a signal is directed at a process the first eligible
|
|
thread is chosen to receive it.
|
|
An eligible thread is one that does not have the signal blocked in its
|
|
signal mask or is waiting in
|
|
.IR sigwait (3).
|
|
If there are no eligible threads then the signal remains pending
|
|
on the process until a thread becomes eligible.
|
|
This is called asynchronous signal delivery;
|
|
.IR kill (2)
|
|
causes this type of delivery.
|
|
.IP \(bu 4
|
|
When a signal is directed at a thread then that thread will receive it.
|
|
If the signal is blocked then it will remain pending on the target
|
|
thread; it will not be delivered to a different thread.
|
|
This is called synchronous signal delivery;
|
|
exceptions and program faults cause this type of delivery.
|
|
.IP \(bu 4
|
|
If the action of the signal is to stop, continue or terminate the
|
|
recipient then it will act on the process as a whole.
|
|
It is not possible to stop, continue or terminate a single
|
|
thread with a signal.
|
|
.RE
|
|
.\" ----------------
|
|
.TP
|
|
.B Notifications
|
|
An extension to signal handling for threads is the addition of
|
|
.B SIGEV_THREAD
|
|
which creates a thread instead of sending a signal as a means of
|
|
handling the occurrence of some event [see
|
|
.IR mq_notify (3C),
|
|
.IR aio_read (3)
|
|
and
|
|
.IR timer_create (3C)].
|
|
Creation of the thread takes place when the event occurs so
|
|
care should be taken to avoid any errors or else the notification may be lost.
|
|
.\" ----------------
|
|
.TP
|
|
.B Scheduling
|
|
When a processor executes instructions on behalf of a user it does so
|
|
according to a set of scheduling attributes
|
|
which are part of a kernel
|
|
.IR "execution vehicle" .
|
|
Every thread that executes on a processor or waits in the kernel
|
|
needs such a vehicle.
|
|
.IP
|
|
POSIX threads makes a distinction between system scope (kernel) scheduling
|
|
and process scope (run-time) scheduling.
|
|
In both scopes the individual thread scheduling policy and priority values
|
|
are set using the interfaces
|
|
.IR pthread_attr_setschedpolicy (),
|
|
.IR pthread_attr_setschedparam (),
|
|
and
|
|
.IR pthread_setschedparam ().
|
|
.br
|
|
Scope is defined when a thread is created using
|
|
.IR pthread_attr_setscope ():
|
|
.\" ----------------
|
|
.IP
|
|
.B system scope
|
|
threads are scheduled by the kernel;
|
|
the scheduling attributes of the thread and the kernel execution vehicle
|
|
are the same.
|
|
The kernel includes all system scope threads in its scheduling decisions.
|
|
These threads run at realtime policy and priority and may only be
|
|
created by privileged users.
|
|
.\" ----------------
|
|
.IP
|
|
.B process scope
|
|
threads are scheduled by the pthread run-time;
|
|
the scheduling attributes of the thread and the kernel execution vehicle
|
|
may be different.
|
|
The run-time makes scheduling decisions based only on the process scope
|
|
threads in the host process.
|
|
.IP
|
|
An advantage of system scope is that a thread can get
|
|
high performance and deterministic response.
|
|
A disadvantage is that kernel resources must be allocated to
|
|
each thread.
|
|
.IP
|
|
In contrast, process scope threads only require kernel state when
|
|
they are executing on a processor or waiting in the kernel.
|
|
The run-time scheduler multiplexes process scope threads onto a smaller
|
|
number of kernel execution vehicles.
|
|
This can produce faster scheduling because no kernel
|
|
state is involved.
|
|
.IP
|
|
The number of execution vehicles used for process scope threads
|
|
depends on application behaviour and system configuration.
|
|
By default, the run-time adjusts this number dynamically but the
|
|
.IR pthread_setconcurrency ()
|
|
interface gives a strong hint as to the desired value.
|
|
.\" ----------------
|
|
.IP
|
|
The execution vehicles used for process scope threads share
|
|
a set of kernel scheduling attributes which can
|
|
be changed using the
|
|
.IR sched_setscheduler ()
|
|
and
|
|
.IR sched_setparam ()
|
|
interfaces.
|
|
These interfaces do not affect system scope thread scheduling.
|
|
As with system scope threads changing these scheduling attributes
|
|
is a privileged operation.
|
|
.\" ----------------
|
|
.TP
|
|
.B Low-overhead Locking
|
|
In order to protect updates to internal pthread data structures, a
|
|
low-overhead locking mechanism is required.
|
|
This locking interface is not user-callable and is contained entirely
|
|
within the pthread library.
|
|
When pthreads are present, this locking mechanism is also used to ensure
|
|
that some routines in libc can be safely called from multiple threads.
|
|
Some examples of this are the
|
|
.IR stdio (3S)
|
|
routines and the
|
|
.IR malloc (3C)
|
|
routines.
|
|
.IP
|
|
By default, these locks spin/sleep for
|
|
.B process scope
|
|
threads on multiprocessor systems, and immediately block for
|
|
.B system scope
|
|
threads and on single processor systems.
|
|
In the spin/sleep lock path, the lock will be tried 1000 times, and then
|
|
.IR nanosleep (2)
|
|
will be called.
|
|
This process will be repeated until the lock can be obtained.
|
|
.IP
|
|
This process can be tuned for an individual application with the
|
|
.B PT_SPINS
|
|
environment variable.
|
|
This determines how many times the lock is tried before sleeping.
|
|
This environment variable is checked once at program startup time.
|
|
Different spin values may be used to improve application throughput;
|
|
however, higher values will probably increase user time while lower
|
|
values will probably increase system time.
|
|
In general, applications with more pthreads than processors will
|
|
probably benefit from setting
|
|
.B PT_SPINS
|
|
to a lower value, while applications with fewer pthreads may benefit
|
|
from setting the environment variable to a higher value.
|
|
If the environment variable is set to 0, these locks will all become
|
|
blocking locks.
|
|
.IR realtime (5)
|
|
applications and applications that create only
|
|
.B system scope
|
|
threads may benefit from setting
|
|
.B PT_SPINS
|
|
to 0.
|
|
This forces the locks to block immediately instead of having the lock
|
|
routine do a run-time check to determine if the caller is a
|
|
.B system scope
|
|
thread.
|
|
.\" ----------------
|
|
.TP
|
|
.B Thread Data
|
|
Pthreads share the address space; stacks, text and data are
|
|
accessible by all threads in the process.
|
|
This means that access to shared data is simpler than where multiple
|
|
processes use a shared memory region which each must map.
|
|
The cost is the potential for accidental corruption.
|
|
Individual thread data is provided using the notion of a shared
|
|
set of keys and unique thread values bound to each key.
|
|
The
|
|
.IR pthread_key_create ()
|
|
interface creates a new, shared key and
|
|
.IR pthread_setspecific ()
|
|
allows a thread to bind its own value to a key.
|
|
Conceptually, the key is an index to an array of values.
|
|
The same key used by different threads may retrieve a different values
|
|
because each thread has its own array.
|
|
.\" ----------------
|
|
.TP
|
|
.B Process Management
|
|
Some basic UNIX interfaces have particular semantics when
|
|
called from a POSIX threads process.
|
|
.\" ----------------
|
|
.IP
|
|
.B fork(2)
|
|
creates a new pthread process and follows the usual rules for
|
|
inherited state.
|
|
The new process has a single pthread (the one which made the call);
|
|
all other pthreads active prior to
|
|
.IR fork ()
|
|
are quietly destroyed
|
|
and their resources (stacks etc.) reclaimed by the pthread run-time.
|
|
A number of issues arise because
|
|
.IR fork ()
|
|
causes data to be copied from the parent to the child with no
|
|
synchronisation with threads that may be modifying that data.
|
|
To allow the application to perform its own synchronisation the
|
|
.IR pthread_atfork ()
|
|
interface can register handlers to be processed when
|
|
.IR fork ()
|
|
is used.
|
|
In general operations which are safe to perform
|
|
after a
|
|
.IR fork ()
|
|
are the same as those which are safe to perform in a signal handler.
|
|
.\" ----------------
|
|
.IP
|
|
.B exec(2)
|
|
overlays a new process image on the calling process;
|
|
all threads from the old image are destroyed.
|
|
Thread termination handlers and thread data destruction [see
|
|
.IR pthread_cleanup_push ()
|
|
and
|
|
.IR pthread_key_create ()]
|
|
are not performed.
|
|
The new process will only be a pthread process if the new image
|
|
is of a pthread process.
|
|
.\" ----------------
|
|
.IP
|
|
.B exit(2)
|
|
performs all the usual process clean up operations and then
|
|
destroys all threads in the process.
|
|
Thread termination handlers and thread data destruction [see
|
|
.IR pthread_cleanup_push ()
|
|
and
|
|
.IR pthread_key_create ()]
|
|
are not performed.
|
|
.\"
|
|
.\" ----------------
|
|
.SS Limitations
|
|
With POSIX threads there are some limitations and practices to avoid.
|
|
.\" ----------------
|
|
.TP
|
|
.B Not enough pthreads
|
|
Each pthread process has a resource limit called
|
|
.B RLIMIT_PTHREAD
|
|
on the number of threads it can create.
|
|
The value is inherited by child processes and may be set using
|
|
.IR setrlimit (2)
|
|
or the shell
|
|
.I limit
|
|
and
|
|
.I ulimit
|
|
commands.
|
|
The default limits can be changed using the
|
|
.IR systune (1M)
|
|
command on the
|
|
.I rlimit_pthread_cur
|
|
and
|
|
.I rlimit_pthread_max
|
|
variables.
|
|
.\" ----------------
|
|
.TP
|
|
.B Fatal exceptions
|
|
When a thread executes code in the pthread run-time scheduler it masks
|
|
signals so that signal handlers always run in a consistent environment.
|
|
A side effect of this is that if the thread raises an exception (for
|
|
example due to memory corruption) the kernel will terminate the process.
|
|
As an aid to debugging such problems the environment variable
|
|
.B PT_CORE
|
|
should be set prior to starting the application so that a core file
|
|
will be generated.
|
|
.\" ----------------
|
|
.TP
|
|
.B Stack overrun
|
|
Unlike the default stack in an unthreaded IRIX process, pthread stacks
|
|
are limited [see
|
|
.IR pthread_attr_setstacksize ()]
|
|
and a thread may overrun its stack.
|
|
By default pthread stacks have a protected region at the end of
|
|
the stack [see
|
|
.IR pthread_attr_setguardsize ()]
|
|
that can turn some of these overruns into a protection faults which is
|
|
generally preferable to overwriting data.
|
|
.\" ----------------
|
|
.TP
|
|
.B Dynamic loading
|
|
The pthread run-time relies on preempting some calls implemented by
|
|
the C run-time (libc).
|
|
This requirement means that the pthread DSO cannot safely be dynamically
|
|
loaded using
|
|
.IR dlopen (3C)
|
|
or
|
|
.IR sgidladd (3C).
|
|
.\" ----------------
|
|
.TP
|
|
.B Using sprocs
|
|
The
|
|
.IR sproc (2)
|
|
model of threading is incompatible with POSIX threads.
|
|
Attempts by an sproc process to create pthreads and vice-versa
|
|
will be rejected.
|
|
.\" ----------------
|
|
.TP
|
|
.B MAP_LOCAL memory
|
|
The POSIX thread memory model requires that memory be available to
|
|
all threads.
|
|
The
|
|
.B MAP_LOCAL
|
|
option to
|
|
.IR mmap (2)
|
|
is useful only to sproc processes and should not be used with pthreads.
|
|
.\" ----------------
|
|
.TP
|
|
.B Dynamic memory allocation
|
|
The
|
|
.IR sbrk (2)
|
|
call is not thread-safe.
|
|
It is used by the C run-time memory allocator,
|
|
.IR malloc (3C),
|
|
which is always used by the pthread run-time.
|
|
Safe use of
|
|
.IR sbrk (2)
|
|
outside of the run-time (for example by a third party memory allocator)
|
|
is not therefore possible.
|
|
.\"
|
|
.\" ----------------
|
|
.SS Documentation
|
|
Additional on-line documentation about pthreads is available in:
|
|
.PD 0
|
|
.IP
|
|
.I Topics in IRIX Programming: Chapter 13
|
|
.IP
|
|
.I SpeedShop User's Guide: Chapter 6
|
|
.PD
|
|
.\"
|
|
.\" ----------------
|
|
.SH "SEE ALSO"
|
|
pthread_*(3P)
|