Guide to the POSIX Threads Library
1.6.1.1 Optionally Implemented POSIX.1 Routines
In this version of the Threads Library, the pthread
interface does not support the following features that are specified in
the POSIX.1 standard:
- Reported by the POSIX.1
_POSIX_THREAD_PRIO_PROTECT
macro:
pthread_mutex_getprioceiling()
pthread_mutex_setprioceiling()
pthread_mutexattr_getprioceiling()
pthread_mutexattr_setprioceiling()
- Reported by the POSIX.1
_POSIX_THREAD_PRIO_PROTECT
and
_POSIX_THREAD_PRIO_INHERIT
macros:
pthread_mutexattr_getprotocol()
pthread_mutexattr_setprotocol()
- (Not supported for OpenVMS systems) Reported by the POSIX.1
_POSIX_THREAD_PROCESS_SHARED
macro:
pthread_condattr_getpshared()
pthread_condattr_setpshared()
pthread_mutexattr_getpshared()
pthread_mutexattr_setpshared()
pthread_rwlockattr_getpshared()
pthread_rwlockattr_setpshared()
The POSIX.1 standard directs the Threads Library to provide the macros
named
_POSIX_THREAD_PROCESS_SHARED
,
_POSIX_THREAD_PRIO_PROTECT
, and
_POSIX_THREAD_PRIO_INHERIT
to report whether optionally implemented routines are present.
The Threads Library does provide the following macros specified in the
POSIX.1 standard:
_POSIX_THREADS
: threads are supported
_POSIX_THREAD_SAFE_FUNCTIONS
: thread-safe libraries are supported
_POSIX_THREAD_ATTR_STACKSIZE
: can specify stack size
_POSIX_THREAD_ATTR_STACKADDR
: can specify stack address
_POSIX_THREAD_PRIORITY_SCHEDULING
: real-time scheduling control is supported
_POSIX_THREAD_PROCESS_SHARED
: cross-process synchronization is supported (Tru64 UNIX only)
1.6.2 Thread-Independent Services Interface
The Compaq proprietary tis interface offers a set of
thread-independent services. Use these routines to build software that
performs processing that requires synchronization, but without
requiring the use of pthreads. That is, use tis
routines to build thread-safe code libraries whose routines can be
called from either a single-threaded or a multithreaded environment.
In the absence of threads, tis routines impose minimal
overhead on the calling program. For instance, tis
routines avoid the use of interlocked instructions and memory barriers.
When threads are present, tis routines provide full
support for synchronization. Note that there are no
tis routines for creating threads or thread objects,
because these routines would have no meaning if called from a
single-threaded environment.
The tis routines can be classified into these
functional categories:
- General routines
- Thread cancelation routines
- Thread-specific data key routines
- Mutex routines
- Condition variable routines
- Read-write lock routines
Note
Unlike the other tis interfaces, the read-write lock
functions work on a data type different from that used by the
pthread read-write lock functions.
|
Table 1-2 summarizes these groups of tis routines.
Table 1-2 tis Routines Summary
Routine |
Description |
General Routines |
tis_once()
|
Calls an initialization routine to be executed only once
|
tis_self()
|
Obtains the identifier of the calling thread
|
tis_yield()
|
Notifies the scheduler that the calling thread is willing to release
its processor to other threads of the same or higher priority
|
Thread Cancelation Routines |
tis_setcancelstate()
|
Sets the calling thread's cancelability state to enable or disable the
delivery of cancelation requests
|
tis_testcancel()
|
Requests delivery of any pending cancelation request to the calling
thread
|
Thread-Specific Data Key Routines |
tis_getspecific()
|
Obtains the thread-specific data associated with the specified key for
the calling thread
|
tis_key_create()
|
Generates a unique thread-specific data key
|
tis_key_delete()
|
Deletes a thread-specific data key
|
tis_setspecific()
|
Changes the thread-specific data value associated with the specified
key for the calling thread
|
Mutex Routines |
tis_lock_global()
|
Locks the global mutex
|
tis_mutex_destroy()
|
Destroys the specified mutex object
|
tis_mutex_init()
|
Initializes a mutex object
|
tis_mutex_lock()
|
Locks the specified mutex, if unlocked
|
tis_mutex_trylock()
|
Tries to lock the specified mutex
|
tis_mutex_unlock()
|
Unlocks the specified mutex when locked by the calling thread
|
tis_unlock_global()
|
Unlocks the global mutex
|
Condition Variable Routines |
tis_cond_broadcast()
|
Wakes all threads currently waiting on the specified condition variable
|
tis_cond_destroy()
|
Destroys the specified condition variable object
|
tis_cond_init()
|
Initializes a condition variable object
|
tis_cond_signal()
|
Wakes at least one thread that is waiting on the specified condition
variable
|
tis_cond_timedwait()
|
Causes a thread to wait a specified period of time for a condition
variable to be signaled or broadcast
|
tis_cond_wait()
|
Causes the calling thread to wait for the specified condition variable
to be signaled or broadcast
|
tis_get_expiration()
|
Calculates a timeout for a timed condition variable wait
|
OpenVMS I/O Completion Routines |
tis_io_complete()
|
Completion AST service routine
|
tis_sync()
|
Thread-synchronous replacement for
$SYNC
system service
|
Read-Write Lock Routines |
tis_read_lock()
|
Acquires the specified read-write lock for read access
|
tis_read_trylock()
|
Acquires the specified read-write lock for read access; returns
immediately if already locked
|
tis_read_unlock()
|
Unlocks the specified read-write lock already acquired for read access
by the calling thread
|
tis_rwlock_destroy()
|
Destroys the specified read-write lock object
|
tis_rwlock_init()
|
Initializes the specified read-write lock object
|
tis_write_lock()
|
Acquires the specified read-write lock for write access
|
tis_write_trylock()
|
Acquires the specified read-write lock for write access; returns
immediately if already locked
|
tis_write_unlock()
|
Unlocks the specified read-write lock already acquired for write access
by the calling thread
|
1.6.3 Undocumented and Obsolete Interfaces
Previous versions of the Threads Library offered interfaces that under
this version are no longer documented.
1.6.3.1 The cma Interface
This version of the Threads Library supports the Compaq proprietary CMA
(or cma) interface. The cma interface
reports errors by raising exceptions. This interface is layered on top
of the pthread interface. This interface is usually
available only on Compaq platforms.
Compaq will continue to support existing applications that were
developed using the cma interface. Binary
compatibility will be supported indefinitely. Nonetheless, Compaq
recommends that, as soon as possible, you migrate any
cma code in your existing applications to the latest
pthread interface, to take advantage of its standard
features, portability, and future enhancements.
Routines of the cma interface are not documented in
this guide. In this guide see Appendix D for information to help you
migrate your cma-based programs and applications to
the latest pthread interface.
1.6.3.2 The d4 (DCEthread) Interfaces
Note
These obsolete interfaces will be removed in a future Compaq POSIX
Threads release. As of that release, both source and binary code using
the d4 (DCEthread) interfaces will no longer compile or execute.
|
For backward compatibility only, this version of the Threads Library
retains full binary support for the d4 interfaces.
These interfaces are implementations of the IEEE POSIX 1003.4a/Draft 4
document, and are also known as "DCE threads".
These interfaces include both a "standard" interface that
reports errors by setting errno and returning a value of -1,
and an "exception-returning" interface that, like the
cma interface, reports errors by raising exceptions.
The d4 interfaces will not be provided in a future
release of the Threads Library. Compaq recommends that you migrate any
d4 code in your existing applications to the latest
pthread interface, to take advantage of its standard
features, portability, and future enhancements.
Routines of the d4 interfaces are not documented in
this guide. In this guide see Appendix E for information to help you
migrate your d4-based programs and applications to the
latest pthread interface.
Chapter 2 Objects and Operations
This chapter describes operations that act upon the objects supported
in the pthread interface.
2.1 Threads and Synchronization Objects
A multithreaded program typically manipulates these objects:
- A thread object describes a
thread, which refers to a distinct flow of control
within a process. After a thread object is created, the Threads Library
uses it to maintain information about the thread's state and its
associated attributes.
-
A mutex serves as a lock for data that is shared among
the program's threads. To access data that is guarded by a mutex, a
thread must acquire the mutex, access the data, and then
release the mutex. Each instance of acquiring a mutex is
called a lock acquisition. While a mutex is locked, if
other threads attempt to acquire that mutex, those threads must wait
for the mutex to be released.
- For data that is shared among a program's threads but is more
frequently read than written, use a read-write lock to
guard access to the data. Unlike a mutex, more than one thread can
acquire the same read-write lock for read access at the same time.
- When associated with a shared data object and its mutex, a
condition variable provides a mechanism that allows a
thread to wait until a piece of shared data protected by a mutex is
placed into a particular state.
2.2 Attributes Objects
When your program creates a thread, mutex, read-write lock or condition
variable, it can accept the default attributes for that object or
specify an existing attributes object (previously created by your
program) that contains particular attribute values. You can also change
some of the attributes of a thread after it has begun execution---for
example, you can change the thread's priority. However, other
attributes, such as stack size, are fixed at execution.
To initialize an attributes object, you can use one of the following
routines, depending on the type of object to which the attributes apply:
-
pthread_attr_init()
for thread attributes
-
pthread_mutexattr_init()
for mutex attributes
-
pthread_rwlockattr_init()
for read-write lock attributes
-
pthread_condattr_init()
for condition variable attributes
These routines initialize an attributes object with default values for
the individual attributes. To modify any attribute values in an
attributes object, use one of the "
attr_set
" routines, such as
pthread_attr_setinheritsched()
, described in later sections.
Initializing an attributes object (or changing the values in an
attributes object) does not affect the attributes of existing threads,
mutexes, read-write locks and condition variables.
To destroy an attributes object, use one of the following routines:
-
pthread_attr_destroy()
for thread attributes objects
-
pthread_condattr_destroy()
for condition variable attributes objects
-
pthread_mutexattr_destroy()
for mutex attributes objects
-
pthread_rwlockattr_destroy()
for read-write lock attributes objects
Deleting an attributes object does not affect the attributes of objects
previously created with that attributes object.
2.3 Thread Operations
The following sections describe these operations on threads:
- Creating a thread
- Setting the attributes for a new thread
- Terminating a thread
- Detaching and destroying a thread
- Joining with another thread
- Controlling how a thread is scheduled
- Canceling a thread
2.3.1 Creating a Thread
Your program creates a thread using the
pthread_create()
routine. This routine creates a thread based on the settings of the
thread attributes object if specified, which your program must have
previously initialized. If called without a specified thread attributes
object,
pthread_create
creates a new thread that has the default attributes.
The Threads Library creates a thread in the ready state and
prepares the thread to begin executing its start routine, the function
passed to the
pthread_create()
routine. Depending on the presence of other threads and their
scheduling attributes, the new thread might preempt its creator (that
is, it might start before the call to
pthread_create()
returns). The caller of
pthread_create()
can synchronize with the new thread using any mutually agreed upon
mechanism or await its termination using
pthread_join()
.
The Threads Library assigns each new thread a thread identifier, which
is written into the address specified as the
pthread_create()
routine's thread argument. The new thread's identifier is
written before the new thread executes.
You can create a thread that is detached. To do so, create a
thread using a thread attributes object whose detachstate attribute has
been set, using the
pthread_attr_setdetachstate()
routine, to
PTHREAD_CREATE_DETACHED
. This is useful for creating a thread that your program knows will
not be joined by any other thread. That is, when such a thread
terminates, the thread and its thread object are automatically
destroyed.
For more detailed information about thread creation, see the reference
description of the
pthread_create()
routine in Part 2.
2.3.2 Setting the Attributes of a New Thread
When creating a thread, your program can optionally specify the
attributes of the new thread using a thread attributes
object. To do so, your program must:
- Allocate a thread attributes object and then initialize it by
calling the
pthread_attr_init()
routine. (Normally, you will initialize an extern or local variable of
the appropriate type.)
- Set values for the individual attributes of the thread attributes
object. (The POSIX standard provides a separate routine for setting
each attribute in the thread attributes object.)
- When ready to create the new thread, pass the address of the
thread attributes object as an argument to the
pthread_create()
routine.
After your program creates a thread attributes object, it can be reused
for each new thread that the program creates. For the details about
creating and deleting a thread attributes object, see the descriptions
in Part 2 of the
pthread_attr_init()
and
pthread_attr_destroy()
routines.
Using the thread attributes object, your program can specify these
attributes of a new thread:
- Scheduling inheritance
- Scheduling policy
- Scheduling parameters
- Stack size
- Stack location
- Stack guard size
- Contention scope
2.3.2.1 Setting the Inherit Scheduling Attribute
By default, a new thread is created with the scheduling attributes
(policy, parameters and contention scope) of its creator. If an
attributes object is specified, the scheduling attribute values are
ignored. When you want to create a thread with different scheduling
attributes, you must set the attribute values, and also set the value
of the inheritsched attribute to
PTHREAD_EXPLICIT_SCHED
. You do this by calling the
pthread_attr_setinheritsched()
routine. The default value is
PTHREAD_INHERIT_SCHED
.
|