Intro(THREAD)
Intro --
introduction to the Threads Library
Synopsis
cc [options] -Kthread file
#include <thread.h>
Description
Threads
The Threads Library supplies routines for thread management
that allow a programmer to implement parallel algorithms conveniently.
In addition, user-level synchronization routines
[see
synch(SYNCH)]
are provided that allow coordination
of threads either within a process or across processes.
The (3thread) and (3synch) man pages describe the UNIX
International Threads APIs.
The POSIX Threads APIs are described in the
(3pthread) man pages.
It is good practice to use either one or the other set
consistently in an application.
What is a thread?
A thread-of-control, or thread for short,
is a sequence of instructions and associated data
that is scheduled and executed as an independent entity.
Every UNIX process linked with the Threads Library
contains at least one, and possibly many, threads.
Threads within a process share the address space of the process.
Processes also contain one or more lightweight processes (LWPs),
which are independently scheduled by the operating system kernel,
and which share address space
and other resources.
[see
_lwp_create(S)].
LWPs are the execution entities for threads.
When a thread executes, it is bound to an LWP.
We also say that an LWP picks up a thread for execution.
Bound and multiplexed threads
By default, the Threads Library multiplexes threads onto LWPs.
That is, when a thread runs,
it will be temporarily bound to any LWP in a pool
of available LWPs within the process.
The number of LWPs available in the pool
is called the degree or the level of concurrency.
Users can request a change in the level of concurrency
with the THR_INCR_CONC flag to
thr_create(THREAD)
or with
thr_setconcurrency(THREAD).
A thread can also be bound to an LWP
for its lifetime [see
thr_create(THREAD)].
Bound threads have the properties of the underlying LWP,
therefore, a bound thread uses operating system scheduling.
The Threads Library schedules multiplexed threads
(see ``Thread Scheduling,'' below).
When a program is linked with the Threads Library,
an initial thread is created to execute the main function.
This initial thread is a multiplexed thread.
In certain cases, such as when competing for synchronization objects
[see
synch(SYNCH)],
bound threads are given scheduling priority over multiplexed threads
to make better use of system resources.
Thread creation
thr_create(THREAD)
creates new threads.
Both multiplexed and bound threads can be created.
The caller can supply a stack for the thread to run on,
or the library will supply one.
The library does not check for stack overflow
for stacks supplied by the user,
but a SIGSEGV signal can be generated
if a thread overflows a library-allocated stack.
Every thread has an ID,
which is recognized only within the current process.
thr_self(THREAD)
returns the ID of the calling thread.
Sibling threads
Threads within a process are siblings.
Unlike processes,
where a parent process creates a child process
for which it must
wait(S),
threads create siblings for which they do not have to wait.
Sibling threads can be awaited with
thr_join(THREAD)
(see below), but this is optional.
Daemon threads
An application creates daemon threads
to provide ongoing services,
for example asynchronous I/O,
for other threads.
Daemon threads do not need to exit explicitly;
when the last non-daemon thread terminates,
the process will exit, terminating any daemon threads.
Thread exit and process exit
thr_exit(THREAD)
causes the calling thread to terminate its execution.
A process containing threads will terminate
in any of the following four circumstances:
-
When the last non-daemon thread terminates,
the process exits.
-
If any thread calls
exit(S)
directly,
the process and all its threads and LWPs will exit immediately.
-
If the initial thread terminates without calling thr_exit,
exit will be called implicitly,
causing the entire process to exit.
-
If the thread receives a signal
whose disposition is to terminate the process,
the process will exit.
Joining or waiting for a thread
A thread uses
thr_join(THREAD)
to wait for another thread
to exit
and to retrieve its exit value.
The term ``join'' emphasizes the sibling relationship
between threads.
When one thread waits for another,
in effect they join control paths.
Threads are joinable by default,
but if they are created with the THR_DETACHED flag
[see
thr_create(THREAD)],
they cannot be joined.
If a thread will not be joined, it should be created with the
THR_DETACHED
flag to allow resources associated with the thread to be reused
after the thread terminates.
Thread scheduling
The Threads Library supports three scheduling policies:
-
time-sharing (SCHED_TS or SCHED_OTHER)
-
round-robin (SCHED_RR)
-
first-in-first-out (SCHED_FIFO)
Multiplexed threads must run under the time-sharing policy.
Bound threads can run under any of the policies.
See
thr_setscheduler(THREAD)
for details.
SCHED_TS does not alter the scheduling priority
within the process of a multiplexed thread.
A thread can set its scheduling policy and priority
with
thr_setscheduler(THREAD)
and its priority only with
thr_setprio(THREAD).
It can retrieve its scheduling policy and priority
with
thr_getscheduler(THREAD)
and its priority only with
thr_getprio(THREAD).
thr_yield(THREAD)
causes a thread to stop executing
to allow another eligible thread to run.
The Threads Library does not protect against priority inversion.
That is, it is possible for a thread to be blocked
waiting for a lower priority thread to release a resource.
Error handling
None of the Threads Library routines set errno;
most return an error number if an error is encountered.
This discourages use of errno, which is non-reentrant
and inefficient in a multithreaded environment.
The Threads Library does not guarantee to preserve errno across calls.
Signal handling
UNIX System signals were designed for inter-process communication.
They have been enhanced to work with multithreaded programs,
but their use here should be restricted.
We recommend that only a limited number of threads within a process
access and receive signals.
These threads can convert the notification provided by signals
into internal communication between threads.
Each thread in a process has its own signal mask,
which is inherited from its creator thread.
Threads can use
thr_sigsetmask(THREAD)
to modify their signal masks.
When a multithreaded process receives a signal,
the signal is delivered to one thread interested in the signal.
Threads express interest in a signal by calling
sigwait(S)
or by using
signal(S),
sigset [see
signal(S)],
or
sigaction(S)
to establish a handler for a signal.
Threads use
thr_kill(THREAD)
to send a signal
to a sibling thread.
Thread-Specific data
Thread-specific data routines provide a thread-safe alternative
to static or external data.
That is, they provide a way for threads to create and access private data
that persist across function calls.
The thread-specific data routines are:
thr_getspecific(THREAD),
thr_keycreate(THREAD),
thr_keydelete(THREAD),
and
thr_setspecific(THREAD).
Tracing mechanism
The Threads Library provides a mechanism
for tracing significant library events.
Calls to all Threads Library interfaces
[including the user synchronization interfaces, see
synch(SYNCH)]
can be traced.
Significant information, such as arguments, return values, lock contention,
and duration of execution are recorded.
To avoid a performance penalty on the Threads Library,
a separate library, libthreadT.so, contains the tracing routines.
To obtain trace data,
the application must be linked to libthreadT.so.
See
thread_trace(F)
for a description of trace data files.
Additional sources of information
These books discuss the use of the
Threads library (3thread) and (3synch) and the Pthreads library
(3pthread), and provide code examples.
As always, the UnixWare manual pages give
the definitive information on syntax and return values for
these interfaces should there be differences.
-
THREADtime - The Multithreaded Programming Guide, Scott J. Norton
and Mark D. DiPasquale; 538 pages; Prentice Hall PTR;
1997; ISBN 0-13-190067-6
A complete guide to programming with POSIX threads,
this book describes various thread and process models, POSIX,
threads programming and debugging, and includes a good
introduction to threads, a chapter on debugging,
chapters on thread programming models and guidelines,
and the pthread manual pages.
-
Programming with POSIX Threads, David R. Butenhof; 381 pages;
Addison-Wesley professional computing series; 1997; ISBN 0-201-63392-2
A complete guide to programming
with POSIX threads,
this book introduces threads programming,
describes how to use the interfaces,
discusses the routines that can be called safely in a signal handler,
and explains what features are standard and what features
may vary from one implementation to another.
Code examples include some
which implement barriers and read/write locks (features
in the UnixWare threads library but not currently provided in POSIX).
-
Programming with Threads, Steve Kleiman, Devang Shah,
and Bart Smaalders; 534 pages; SunSoft Press, 1996; ISBN 0-13-172389-8
A complete reference for POSIX threads,
from introduction to advanced programming,
this book may be most useful to someone already
familiar with multithreaded programming
because the introductory topics are brief and
it concentrates on advanced topics.
UNIX International threads are listed in an appendix.
-
Threads Primer - A Guide to Multithreaded Programming, Bil Lewis
and Daniel Berg; 319 pages; SunSoft Press, 1996; ISBN 0-13-443698-9
A good introductory text for
someone unfamiliar with threads programming,
this book has code examples that use the UNIX International
threads (3thread) and (3synch) interfaces.
These are the only interfaces available in UnixWare prior to the
introduction of POSIX threads (3pthread) interfaces in Release 7.0.1.
POSIX thread interfaces are listed in an appendix.
Warnings
The Threads Library does not guarantee to preserve errno
across calls.
References
exit(S),
_lwp_create(S),
sigaction(S),
signal(S),
sigwait(S),
synch(SYNCH),
thread_trace(F),
thr_continue(THREAD),
thr_create(THREAD),
thr_exit(THREAD),
thr_getconcurrency(THREAD),
thr_getprio(THREAD),
thr_get_rr_interval(THREAD),
thr_getscheduler(THREAD),
thr_getspecific(THREAD),
thr_join(THREAD),
thr_keycreate(THREAD),
thr_keydelete(THREAD),
thr_kill(THREAD),
thr_minstack(THREAD),
thr_self(THREAD),
thr_setconcurrency(THREAD),
thr_setprio(THREAD),
thr_setscheduler(THREAD),
thr_setspecific(THREAD),
thr_sigsetmask(THREAD),
thr_suspend(THREAD),
thr_yield(THREAD)
Standards compliance
The threads library is not part of any currently supported standard.
It was
developed by UNIX System Laboratories, Inc. and is used by permission.
© 2005 The SCO Group, Inc. All rights reserved.
SCO OpenServer Release 6.0.0 - 01 June 2005