Guide to DECthreads


Previous | Contents

int
tis_rwlock_destroy (
tis_rwlock_t *lock);


ARGUMENTS

lock

Address of the read-write lock object to be destroyed.

DESCRIPTION

This routine destroys the specified read-write lock object. Prior to calling this routine, ensure that there are no locks granted to the specified read-write lock and that there are no threads waiting for pending lock acquisitions on the specified read-write lock.

This routine should be called only after all reader threads (and perhaps one writer thread) have finished using the specified read-write lock.

Return Values If an error condition occurs, this routine returns an integer value indicating the type of error. Possible return values are as follows:
Return Description
0 Successful completion.
[EBUSY] The lock is in use.

Associated Routines


tis_rwlock_init

Initializes a read-write lock object.

Syntax

tis_rwlock_init(
lock );

Argument Data Type Access
lock opaque tis_rwlock_t write
C Binding #include <tis.h>

int
tis_rwlock_init (
tis_rwlock_t *lock);


ARGUMENTS

lock

Address of a read-write lock object.

DESCRIPTION

This routine initializes a read-write lock object. The routine initializes the tis_rwlock_t structure that holds the object's lock states.

To destroy a read-write lock object, call the tis_rwlock_destroy() routine.

Return Values If an error condition occurs, this routine returns an integer value indicating the type of error. Possible return values are as follows:
Return Description
0 Successful completion.
[EINVAL] The value specified by lock is invalid.
[ENOMEM] Insufficient memory exists to initialize lock.

Associated Routines


tis_self

Returns the identifier of the calling thread.

Syntax

tis_self(
void);

C Binding #include <tis.h>

pthread_t
tis_self (void);


ARGUMENTS

None

DESCRIPTION

This routine allows a thread to obtain its own thread identifier.

This value becomes meaningless when the thread is destroyed.

Note that the initial thread in a process can "change identity" when thread system initialization completes---that is, when the DECthreads multithreading run-time environment is loaded.

Return Values Returns the thread identifier of the calling thread.

Associated Routines


tis_setcancelstate

Changes the calling thread's cancelability state.

Syntax

tis_setcancelstate(
state ,
oldstate );

Argument Data Type Access
state integer read
oldstate integer write
C Binding #include <tis.h>

int
tis_setcancelstate (
int state,
int *oldstate );


ARGUMENTS

state

State of general cancelability to set for the calling thread. Valid state values are as follows:

oldstate

Receives the value of the calling thread's previous cancelability state.

DESCRIPTION

This routine sets the calling thread's cancelability state to the value specified in the state argument and returns the calling thread's previous cancelability state in the location referenced by the oldstate argument.

When the a thread's cancelability state is set to PTHREAD_CANCEL_DISABLE, a cancelation request cannot be delivered to the thread, even if a cancelable routine is called or asynchronous cancelability is enabled.

When a thread is created, its default cancelability state is PTHREAD_CANCEL_ENABLE. When this routine is called prior to loading threads, the cancelability state propagates to the initial thread in the executing program.

Possible Problems When Disabling Cancelability

The most important use of a cancelation request is to ensure that indefinite wait operations are terminated. For example, a thread waiting on some network connection, which might take days to respond (or might never respond), should be made cancelable.

When a thread's cancelability state is disabled, no routine called within that thread is cancelable. As a result, the user is unable to cancel the operation. When disabling cancelability, be sure that no long waits can occur or that it is necessary for other reasons to defer cancelation requests around that particular region of code.

Return Values On successful completion, this routine returns the calling thread's previous cancelability state in the oldstate argument.

If an error condition occurs, this routine returns an integer value indicating the type of error. Possible return values are as follows:
Return Description
0 Successful completion.
[EINVAL] The specified state is not PTHREAD_CANCEL_ENABLE or PTHREAD_CANCEL_DISABLE.

Associated Routines


tis_setspecific

Changes the value associated with the specified thread-specific data key.

Syntax

tis_setspecific(
key ,
value );

Argument Data Type Access
key opaque pthread_key_t read
value void * read
C Binding #include <tis.h>

int
tis_setspecific (
pthread_key_t key,
const void *value);


ARGUMENTS

key

Thread-specific data key that identifies the data to receive value. Must be obtained from a call to tis_key_create().

value

New value to associate with the specified key. Once set, this value can be retrieved using the same key in a call to tis_getspecific().

DESCRIPTION

This routine sets the value associated with the specified thread-specific data key. If a value is defined for the key (that is, the current value is not NULL), the new value is substituted for it. The key is obtained by a previous call to tis_key_create().

Do not call this routine from a data destructor function.

Return Values If an error condition occurs, this routine returns an integer indicating the type of error. Possible return values are as follows:
Return Description
0 Successful completion.
[EINVAL] The key value is invalid.
[ENOMEM] Insufficient memory exists to associate the value with the key.

Associated Routines


tis_testcancel

Creates a cancelation point in the calling thread.

Syntax

tis_testcancel( );

C Binding #include <tis.h>

void
tis_testcancel (void);


ARGUMENTS

None

DESCRIPTION

This routine requests delivery of a pending cancelation request to the calling thread. Thus, this routine creates a cancelation point in the calling thread. The cancelation request is delivered only if a request is pending for the calling thread and the calling thread's cancelability state is enabled. (A thread disables delivery of cancelation requests to itself by calling tis_setcancelstate().)

This routine, when called within very long loops, ensures that a pending cancelation request is noticed within a reasonable amount of time.

Return Values None

Associated Routines


tis_unlock_global

Unlocks the DECthreads global mutex.

Syntax

tis_unlock_global( );

C Binding #include <tis.h>

int
tis_unlock_global (void);


ARGUMENTS

None

DESCRIPTION

This routine unlocks the DECthreads global mutex. Because the global mutex is recursive, the unlock occurs when each call to tis_lock_global() has been matched by a call to this routine. For example, if your program called tis_lock_global() three times, tis_unlock_global() unlocks the global mutex when you call it the third time.

For more information about actions taken when threads are present, refer to the pthread_unlock_global_np() description.

Return Values If an error condition occurs, this routine returns an integer value indicating the type of error. Possible return values are as follows:
Return Description
0 Successful completion.
[EPERM] The DECthreads global mutex is unlocked or locked by another thread.

Associated Routines


tis_write_lock

Acquires a read-write lock for write access.

Syntax

tis_write_lock(
lock );

Argument Data Type Access
lock opaque tis_rwlock_t write
C Binding #include <tis.h>

int
tis_rwlock (
tis_rwlock_t *lock);


ARGUMENTS

lock

Address of the read-write lock to be acquired for write access.

DESCRIPTION

This routine acquires a read-write lock for write access. This routine waits for any other active locks (for either read or write access) to be unlocked before this acquisition request is granted.

This routine returns when the specified read-write lock is acquired for write access.

Return Values If an error condition occurs, this routine returns an integer value indicating the type of error. Possible return values are as follows:
Return Description
0 Successful completion.
[EINVAL] The value specified by lock is invalid.

Associated Routines


tis_write_trylock

Attempts to acquire a read-write lock for write access.

Syntax

tis_write_trylock(
lock );

Argument Data Type Access
lock opaque tis_rwlock_t write
C Binding #include <tis.h>

int
tis_write_trylock (
tis_rwlock_t *lock);


ARGUMENTS

lock

Address of the read-write lock to be acquired for write access.

DESCRIPTION

This routine attempts to acquire a read-write lock for write access. The routine attempts to immediately acquire the lock. If the lock is acquired, zero (0) is returned. If the lock is held by another thread (for either read or write access), [EBUSY] is returned and the calling thread does not wait for the write-access lock to be acquired.

Note that it is a coding error to attempt to acquire the lock for write access if the lock is already held by the calling thread. (However, this routine returns [EBUSY] anyway, because no ownership error-checking takes place.)

Return Values If an error condition occurs, this routine returns an integer value indicating the type of error. Possible return values are as follows:
Return Description
0 Successful completion; the lock is acquired for write access.
[EBUSY] The lock was not acquired for write access, as it is already held by another thread.

Associated Routines


tis_write_unlock

Unlocks a read-write lock that was acquired for write access.

Syntax

tis_write_unlock(
lock );

Argument Data Type Access
lock opaque tis_rwlock_t write
C Binding #include <tis.h>

int
tis_write_unlock (
tis_rwlock_t *lock);


ARGUMENTS

lock

Address of the read-write lock to be unlocked.

DESCRIPTION

This routine unlocks a read-write lock that was acquired for write access.

Upon completion of this routine, any thread waiting to acquire the lock for read access will have those acquisitions granted. If no threads are waiting to acquire the lock for read access, then a thread waiting to acquire it for write access will have that acquisition granted.

Return Values If an error condition occurs, this routine returns an integer value indicating the type error. Possible return values are as follows:
Return Description
0 Successful completion.
[EINVAL] The value specified by lock is invalid.

Associated Routines


Part 4
Appendixes

Part 4 contains appendixes that provide supporting information about DECthreads, such as operating system-specific information, debugging information, and additional reference information.


Appendix A
Considerations for DIGITAL UNIX Systems

This appendix discusses DECthreads issues specific to DIGITAL UNIX systems.

A.1 Overview

The DIGITAL UNIX operating system supports multiple concurrent "execution contexts" within a process. DECthreads uses these kernel execution contexts to implement user threads. One important benefit of this is that user threads can run simultaneously on separate processors in a multiprocessor system. Review Section 3.1 for tips for ensuring that your application will work correctly with kernel threads and multiprocessing.

A.2 Building DECthreads Applications

The following sections discuss points to consider when building using DECthreads.

A.2.1 Including DECthreads Header Files

Include one of the DECthreads header files shown in Table A-1 in your program to use the appropriate DECthreads library.

Table A-1 DECthreads Header Files
Header File Interface
pthread.h POSIX.1c routines
tis.h Thread-independent services routines

Do not include more than one of these header files in your module.

A.2.2 Building Multithreaded Applications from DECthreads Libraries

Multithreaded applications are built using shared libraries. For a description of shared libraries, see the DIGITAL UNIX Programmer's Guide.

Table A-2 contains the libraries supported for multithreaded programming.

Table A-2 DIGITAL UNIX Shared Libraries for Multithreaded Programs
libmach.so Shared version of threads support library. Direct use of mach interfaces is not supported.
libpthread.so Shared version of the base pthreads package. Requires libmach.so, libexc.so, and libc.so
libexc.so Shared version of DIGITAL UNIX exception support package.
libpthreads.so Shared version of DECthreads "legacy" package, implementing the DIGITAL-proprietary CMA (or cma) and POSIX 1003.4a/Draft 4 (or d4) interfaces.
libc.so Shared version of the C language run-time library ( libc.so).

Build a multithreaded application using shared versions of libexc, libmach, libpthread, and libc using this command:

% cc -o myprog myprog.c -pthread

If you use a compiler front-end or other (not C) language environment that does not support the -pthread compilation switch, you must use the -D_REENTRANT compilation switch.

A.2.3 Linking Multithreaded Shared Libraries

The ld command does not support the -pthread or -threads switch. Instead, you must list the individual libraries in the proper order.

For libraries that use only the pthread interface, use the following:

   ld <...> -lpthread -lexc 

If using the cma or d4 interfaces, use the following:

   ld <...> -lpthreads -lpthread -lexc 


Note

If you build software (whether applications or libraries) that links against the static version of a DECthreads library, you must not require developers who use your software to link against any library that dynamically loads any DECthreads shared library, such as libpthread.so.

A.2.4 Compiling Applications With the tis Interface

Applications that use the DIGITAL-proprietary thread-independent services (or tis) interface should include the tis.h header file and link against the shared C run-time library (libc.so).

A.3 Two-Level Scheduling on DIGITAL UNIX Systems

Under DIGITAL UNIX Version 4.0 and later, DECthreads implements a new scheduling model, referred to as two-level scheduling. DECthreads schedules "user threads" onto kernel execution contexts (often known as "kernel threads" or "virtual processors"), just as DIGITAL UNIX schedules processes onto the processors of a multiprocessing machine.

A user thread is executed on a kernel thread until it blocks or exhausts its timeslice quantum. Then, DECthreads schedules a new user thread to run. While DECthreads is scheduling user threads onto kernel threads, the DIGITAL UNIX kernel is independently scheduling those kernel threads to run on physical processors. The term two-level scheduling refers to this relationship.

This division allows most thread scheduling to take place completely in user mode, without the intervention of the kernel. Since a thread context switch does not involve any privileged information, it can be done much more efficiently in user mode.

The key to making the two-level scheduling model work is efficient two-way communication between DECthreads and the DIGITAL UNIX kernel. When a thread blocks in the kernel, the DECthreads scheduler is notified so that it can schedule another thread to take advantage of the idle kernel thread. This mechanism, sometimes referred to as an upcall, is inspired by original research on scheduler activations at the University of Washington. (See Scheduler Activations: Effective Kernel Support for the User-Level Management of Parallelism by Anderson, Bershad, Lazowska, and Levy; ACM Operating Systems Review Volume 25, Number 5, Proceedings of the Thirteenth ACM Symposium on Operating Systems Principles, October 13-16, 1991).

A.3.1 DECthreads Use of Kernel Threads

DIGITAL UNIX kernel threads are created as they are needed by the application. The number of kernel threads that DECthreads creates is limited by normal DIGITAL UNIX configuration limits regarding user and system thread creation. Normally, however, DECthreads creates one kernel thread for each actual processor on the system and the kernel creates an additional kernel thread on behalf of the process for bookkeeping operations.

DECthreads does not delete these kernel threads or let them terminate. Kernel threads not currently needed are retained in an idle state until they are needed again. When the process terminates, all kernel threads in the process are reclaimed by the kernel.

The DECthreads scheduler can schedule any user thread onto any kernel thread. Therefore, a user thread can run on different kernel threads at different times. Normally, this should pose no problem. However, for example, the kernel thread ID as reported by the dbx or Ladebug debuggers can change at any time.

A.3.2 Support for Real-Time Scheduling

DECthreads supports DIGITAL UNIX real-time scheduling. This allows you to set the scheduling policy and priority of threads. By default, threads are created using process contention scope. This means that the full range of POSIX.1c scheduling policy and priority is available. However, threads running in process contention scope do not preempt lower-priority threads in another process. For example, a thread in process contention scope with SCHED_FIFO policy and PRI_FIFO_MAX priority will not preempt a thread in another process running with SCHED_FIFO and PRI_FIFO_MIN.

In contrast, system contention scope means that each thread created by the program has a direct and unique binding to one kernel execution context. A system contention scope thread competes against all threads in the system and will preempt any thread with lower priority. For this reason, the priority range of threads in system contention scope is restricted unless running with root privilege.

Specifically, a thread with SCHED_FIFO policy cannot run at a priority higher than 18 without privilege, since doing so could lock out all other users on the system until the thread blocked. Threads at any other scheduling policy (including SCHED_RR) can run at priority 19 because they are subject to periodic timeslicing by the system. For more information, see the DIGITAL UNIX Realtime Programming Guide.

If your program lacks necessary privileges, attempting to call the following routines for a thread in system contention scope returns the error value [EPERM]:
pthread_attr_setschedpolicy() ( Error returned by pthread_create() at thread creation)
pthread_attr_setschedparam() ( Error returned by pthread_create() at thread creation)
pthread_setschedparam()


Previous | Next | Contents