Guide to DECthreads
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 threads. That is, use tis
routines to build thread-safe code libraries whose routines can be
called from either a single-threaded or multithreaded environment.
In the absence of threads, tis routines impose minimal
overhead on the calling program. For instance, tis
routines do not use interlocked instructions and memory barriers.
When threads are present, tis routines provide full
support for DECthreads synchronization, such as synchronization objects
and thread joining. Note that there are no tis
routines for creating threads or thread objects, because that 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
Some routines in the pthread interface have a
corresponding or similar routine in the tis interface.
|
Table 1-2 summarizies these groups of tis routines.
Table 1-2 DECthreads tis Routines Summary
Routine |
Description |
General Routines |
tis_once()
|
Calls a one-time initialization routine that can be executed.
|
tis_self()
|
Obtains the identifier of the calling thread.
|
Thread Cancelation Routines |
tis_setcancelstate()
|
Changes the calling thread's cancelability state.
|
tis_testcancel()
|
Creates a cancelation point in the calling thread.
|
Thread-Specific Data Key Routines |
tis_getspecific()
|
Obtains the data associated with the specified thread-specific data key.
|
tis_key_create()
|
Generates a unique thread-specific data key.
|
tis_key_delete()
|
Deletes a thread-specific data key.
|
tis_setspecific()
|
Changes the value associated with the specified thread-specific data
key.
|
Mutex Routines |
tis_lock_global()
|
Locks the DECthreads global mutex.
|
tis_mutex_destroy()
|
Destroys the specified tis mutex object.
|
tis_mutex_init()
|
Initializes a tis mutex object.
|
tis_mutex_lock()
|
Locks the specified tis mutex, if unlocked.
|
tis_mutex_trylock()
|
Tries to lock the specified tis mutex.
|
tis_mutex_unlock()
|
Unlocks the specified tis mutex.
|
tis_unlock_global()
|
Unlocks the DECthreads global mutex.
|
Condition Variable Routines |
tis_cond_broadcast()
|
Wakes all threads 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_wait()
|
Causes the calling thread to wait for the specified condition variable
to be signaled or broadcasted.
|
Read-Write Lock Routines |
tis_read_lock()
|
Acquires the specified read-write lock for read access.
|
tis_read_trylock()
|
Attempts to acquire 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.
|
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()
|
Attempts to acquire 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.
|
1.6.3 Undocumented and Obsolete DECthreads Interfaces
Previous versions of DECthreads offered interfaces that under this
DECthreads version are considered to be either undocumented but
supported, or obsolete.
This version of DECthreads supports the Compaq proprietary CMA (or
cma) interface. The cma interface
reports errors by raising exceptions. This interface is layered on top
of the DECthreads pthread interface. This interface is
usually available only on Compaq platforms.
Compaq will continue to support applications developed using the
DECthreads 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 DECthreads pthread
interface, to take advantage of its POSIX.1c standard features,
portability, and future enhancements.
Routines of the cma interface are not documented in
this guide, but are documented for previous DECthreads versions. In
this guide see Appendix E for information to help you migrate your
cma-based programs and applications to the latest
DECthreads pthread interface.
Note
An obsolete interface will be retired in a future DECthreads release.
After retirement, that interface will no longer be enhanced or
supported.
|
For backward compatibility only, this version of DECthreads retains
full binary support for the obsolete 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 DECthreads d4 interfaces are obsolete and Compaq
plans to retire them (that is, will not be provided) in the next
release of DECthreads. Thus, Compaq recommends that you migrate any
d4 code in your existing applications to the latest
DECthreads pthread interface, to take advantage of its
POSIX.1c standard features, portability, and future enhancements.
Routines of the d4 interfaces are not documented in
this guide, but are documented for previous DECthreads versions. In
this guide see Appendix F for information to help you migrate your
d4-based programs and applications to the latest
DECthreads pthread interface.
Chapter 2 DECthreads Objects and Operations
This chapter describes operations that act upon the objects supported
in the DECthreads pthread interface.
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, DECthreads uses it
to maintain information about the thread's state and its associated
attributes.
-
A mutex serves as a lock for a data object that is
shared among the program's threads. To access a data object that is
guarded by a mutex, a thread must acquire the mutex, then
access the data object, 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.
- When associated with a shared data object and its mutex, a
condition variable encapsulates a condition, or
predicate, that must be satisfied before a thread can access the data
object.
2.2 Attributes Objects
Before creating a thread object, mutex, or condition variable, your
program can create and initialize an attributes
object, which specifies the particular features of that
thread, mutex, or condition variable. There are distinct kinds of
attributes objects for threads, mutexes, and condition variables.
When your program creates a thread object, mutex, or condition
variable, it can accept the default attributes for that object or
specify an existing attributes object that contains particular
attribute values. For a thread object, you can change some of its
attributes after execution of the corresponding thread has begun---for
example, you can change the thread's priority.
To create 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 create an attributes object containing 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.
Creating an attributes object (or changing the values in an attributes
object) does not affect the attributes of existing thread objects,
mutexes, 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.
Operations on threads take place with respect to a thread object. A
thread object is a data structure maintained by DECthreads that
contains the attribute information and DECthreads state information
about a thread.
The following sections describe these operations on threads:
- Creating and starting a thread
- Setting the attributes of a new thread
- Terminating a thread
- Detaching and destroying a thread
- Joining with another thread
- Scheduling a thread
- Canceling a thread
2.3.1 Creating and Starting a Thread
Creating a thread means directing DECthreads to create a
thread object and to assign a unique thread identifier to the thread
object. The thread object encapsulates attribute information about the
thread and DECthreads' own state information about the thread. After a
thread has been created, DECthreads has all the information it requires
to start a distinct sequence of execution with this process.
Starting a thread means DECthreads causes a start
routine, with its argument, to be called on some CPU within
this system.
Your program creates a thread using the pthread_create()
routine. This routine creates a thread object based on the settings of
a specified thread attributes object, which your program must have
previously created and initialized. Otherwise, without specifying a
thread attributes object, you can create a new thread that has
DECthreads default attributes.
DECthreads 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 and priority attributes, the new
thread might start executing immediately. The new thread can also
preempt its creator, depending on the two threads' respective
scheduling and priority attributes. The caller of
pthread_create() can synchronize with the new thread using the
pthread_join() routine or using any mutually agreed upon
mutexes or condition variables.
For the duration of the new thread's existence, DECthreads maintains
and manages the thread object and other thread state overhead. A thread
exists until it is both terminated and
detached. (See Section 2.3.3 and Section 2.3.4 for more
information about terminating and detaching threads.)
DECthreads assigns each new thread a thread identifier, which
DECthreads writes into the address specified as the
pthread_create() routine's thread argument.
DECthreads writes the new thread's thread identifier before
the new thread executes.
By default, the new thread's scheduling policy and priority are
inherited from the creating thread---that is, by default, the
pthread_create() routine ignores the scheduling policy and
priority set in the specified thread attributes object. Thus, to create
a thread that is subject to the scheduling policy and priority set in
the specified thread attributes object, before calling
pthread_create() your program must use the
pthread_attr_setinheritsched() routine to set the inherit
thread attributes object's scheduling attribute to
PTHREAD_EXPLICIT_SCHED.
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_setdetach() routine, to
PTHREAD_CREATE_DETACHED. This is useful for creating a thread
that your program knows will not join with any other thread.
That is, when such a thread terminates, DECthreads automatically
destroys the thread and its thread object.
For more detailed information about thread creation, see the reference
description of the pthread_create() routine in Part 2.
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:
- Create a thread attributes object by calling the
pthread_attr_init() routine.
- Set values for the individual attributes of the thread attributes
object. (The POSIX.1c 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, that object 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_create() and
pthread_attr_delete() 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
The inherit scheduling attribute's value specifies whether the new
thread inherits the settings of its scheduling priority attribute and
scheduling parameters attribute from the creating thread (the default
behavior), or uses the scheduling attributes stored in the attributes
object. Inheriting these settings from the creating thread is the
default behavior, or you can specify the same by setting the thread
attributes object's inherit scheduling attribute to
PTHREAD_INHERIT_SCHED. To use the setting in the attributes
objects, set the inherit scheduling attribute to
PTHREAD_EXPLICIT_SCHED.
Use the pthread_attr_setinheritsched() routine to set the
thread attributes object's inherit scheduling attribute.
The scheduling policy attribute describes how DECthreads schedules the
new thread for execution relative to the other threads in the process.
A thread has one of the following scheduling policies:
-
SCHED_FG_NP (Foreground or "throughput"; also known
as SCHED_OTHER)---This is the default scheduling
policy. All threads are time sliced, and no thread is completely
denied execution time. (Time slicing is a mechanism
that ensures that every thread is allowed time to execute by preempting
running threads at fixed intervals.) However, higher-priority threads
receive more execution time than lower-priority threads.
Threads
with this scheduling policy can be denied execution time by
first-in/first-out (FIFO) or round-robin (RR) threads.
- SCHED_BG_NP (Background)---Like the default
(SCHED_FG_NP) scheduling policy, this policy ensures that all
threads, regardless of priority, receive some scheduling.
Threads
with this scheduling policy can be denied execution time by FIFO or RR
threads, and receive less execution time than threads with the
throughput scheduling policy.
- SCHED_FIFO (first-in/first-out or FIFO)---The
highest-priority thread runs until it blocks. If there is more than one
thread with the same priority and that priority is the highest among
other threads, the first thread to begin running continues until it
blocks. If a thread with this policy becomes ready, and it has a higher
priority than the currently running thread, then DECthreads preempts
the current thread and immediately begins running the higher priority
thread.
- SCHED_RR (round-robin or RR)---The highest-priority
thread runs until it blocks; however, threads of equal priority are
time sliced. If a thread with this policy becomes ready, and it has a
higher priority than the currently running thread, then DECthreads
preempts the current thread and immediately begins running the
higher-priority thread.
2.3.2.2.1 Techniques for Setting the Scheduling Policy Attribute
Use either of two techniques to set a thread attributes object's
scheduling policy attribute:
-
Set the scheduling policy attribute in the attributes object, which
establishes the scheduling policy of a new thread when it is created.
To do so, call the pthread_attr_setschedpolicy() routine. This
allows the creator of a thread to establish the created thread's
initial scheduling policy. (Note that this value is used only if the
attributes object is set so that the created thread does not inherit
its priority from the creating thread. Inheriting priority is the
default behavior.)
-
Change the scheduling policy of an existing thread (and, at the same
time, the scheduling parameters) by calling the
pthread_setschedparam() routine. This routine allows a thread
to change its own scheduling policy and/or scheduling priority, but has
no effect on the corresponding settings in the thread attributes object.
Section 2.3.6 describes and shows the effect of the scheduling policy on
thread scheduling.
|