Guide to DECthreads

Previous | Contents

On DIGITAL UNIX systems only, DECthreads forms the bugcheck output file's name using the process ID number (PID) as the %d format item.

On DIGITAL UNIX systems only, PTHREAD_CONFIG can be the object of the export command.

D.2 Running DECthreads in Metered Mode

Metering tells DECthreads to collect statistical and historical information about the use of synchronization objects within your program. This affects all synchronization within the program, including that within DECthreads itself and any other libraries that use threads. Therefore, metering provides a very powerful tool for debugging multithreaded code.

To enable metering, define PTHREAD_CONFIG prior to running any threaded application. The variable should have a value of meter=all to enable metering. This causes DECthreads to gather and record statistics and history information for all synchronization operations. Additionally, when running in metered mode, DECthreads marks all thread stacks (except the main thread stack) with a specific pattern.

Programs running in metered mode are somewhat slower than unmetered programs. Also, normal mutexes that are metered can behave like errorcheck mutexes in many ways. This does not affect the behavior of correct programs, but you should be aware of some differences between normal and errorcheck mutexes. The most important difference is that normal mutexes do not report a number of usage errors, while errorcheck mutexes do.

Because it can be expensive to detect these conditions, a normal mutex may not always report these errors. Regardless of whether the program seems to work correctly under these circumstances, the operations are illegal. A metered normal mutex will report these errors under more circumstances than will an unmetered normal mutex.

D.3 Using Ladebug on DIGITAL UNIX

The DIGITAL Ladebug debugger provides commands to display the state of threads, mutexes, and condition variables, without using the built-in DECthreads debug facility.

Using the Ladebug commands, you can examine core files and remote debug sessions, as well as run processes.

The basic commands are:

Refer to the Ladebug documentation for further details.

D.4 Debugging Threads on OpenVMS Systems

This section presents particular topics that relate to debugging a multithreaded application under OpenVMS.

D.4.1 Display of Stack Trace from Unhandled Exception

When a program incurs an unhandled exception, a stack trace is produced that shows the call frames from the point where the exception was raised or, if DECthreads TRY/CATCH, TRY/FINALLY, or POSIX cleanup handlers are used, from the point where it was last reraised to the bottom of the stack.

D.5 Debugging Threads on Windows NT Systems

The WinDbg Debugger, provided with the Windows NT Software Development Kit (SDK), provides support for debugging a threaded program. When working with DECthreads in WinDbg, be aware that terminating a thread with pthread_exit() raises an exception as a normal part of the exiting process. Unless you explicitly tell WinDbg to ignore this exception, it catches the exception and stops execution. To allow the thread to exit properly and your application to continue, use the WinDbg gn (go not handled) command. This command tells WinDbg to ignore the exception.

WinDbg also stops at each DECthreads exception block for this exception and has to be continued using the WinDbg gn command until the thread's stack is completely unwound. The exception used by DECthreads for thread rundown is 0x177db052.

DECthreads also generates an exception in a thread as a normal part of thread cancelation. When canceling a thread with pthread_cancel(), an exception value of 0x177db048 is raised. This exception should be allowed to propagate all the way to the base of the thread's stack. If WinDbg halts execution of the program and indicates that this exception is being raised, use the WinDbg gn command to allow the exception to continue.

You can use the Microsoft Visual C++ debugger's graphical user interface to debug exceptions and to indicate how to handle various exceptions. In this case, choose "Stop if not handled" for the exception codes mentioned above.

However, be aware that you cannot fully debug an application that uses pthread_exit() to exit a Win32 thread or uses pthread_cancel() to cancel a Win32 thread. For a thread created using the Win32 API, using pthread_exit() to exit, or using pthread_cancel() to cancel, that thread causes a library-defined unhandled exception filter routine to be invoked. Unhandled exception filter routines cannot be executed in a debugger environment. Any unhandled exception causes the process to exit.

Appendix E
Migrating from the cma Interface

This appendix presents information that helps you migrate existing programs and applications that use the DIGITAL-proprietary DECthreads CMA (or cma) interface to use the DECthreads pthread interface, based on the IEEE POSIX 1003.1c-1995 standard.


In future DECthreads releases, the cma interface will continue to exist and be supported, but it will no longer be documented or enhanced. Therefore, it is recommended that you port your cma-based programs and applications to the pthread interface as soon as possible. The DECthreads pthread interface is the most portable, efficient, and robust multithreading run-time library offered by DIGITAL.

E.1 Overview

The DECthreads pthread interface differs significantly from the cma interface, though there are many similarities between the functions that individual routines perform. This section gives hints about the relationship between the two sets of routines, to assist you in migrating applications.

Note that routines whose names have the _np suffix are not portable---that is, the routine might not be available except in DECthreads.

You need not prototype the pthread routines if you include the C language pthread.h header file.

E.2 cma Handles

A cma handle is storage, similar to a pointer, that refers to a specific DECthreads object (thread, mutex, condition variable, queue, or attributes object).

Handles are allocated by the user application. They can be freely copied by the program and stored in any class of storage; objects are managed by DECthreads.

In the cma interface, because objects are accessed only by handles, you can think of the handle as if it were the object itself. DECthreads objects are accessed by handles (rather than pointers), because handles allow for greater robustness and portability. Handles allow DECthreads to detect the following types of run-time errors:

Handles are not supported in the DECthreads pthread interface. Although this provides less robustness due to more limited error checking, it allows better performance by decreasing memory use and memory access. (That is, handles result in pointers to pointers.)

E.3 Interface Routine Mapping

As summarized in Table E-1, many cma routines perform functions nearly identical to corresponding routines in the pthread interface. The syntax and semantics differ, but the similarities are also notable.

Table E-1 Corresponding cma and pthread Routines
cma Routine pthread Routine Notes
cma_alert_disable_asynch() pthread_setcancelstate()/ pthread_setcanceltype()
cma_alert_disable_general() pthread_setcancelstate()/ pthread_setcanceltype()
cma_alert_enable_asynch() pthread_setcancelstate()/ pthread_setcanceltype()
cma_alert_enable_general() pthread_setcancelstate()/ pthread_setcanceltype()
cma_alert_restore() pthread_setcancelstate()/ pthread_setcanceltype()
cma_alert_test() pthread_testcancel()
cma_attr_create() pthread_attr_init()
cma_attr_delete() pthread_attr_destroy()
cma_attr_get_guardsize() pthread_attr_getguardsize_np()
cma_attr_get_inherit_sched() pthread_attr_getinheritsched()
cma_attr_get_mutex_kind() pthread_mutexattr_gettype_np()
cma_attr_get_priority() pthread_attr_setsched_param()
cma_attr_get_sched() pthread_attr_getschedpolicy()
cma_attr_get_stacksize() pthread_attr_getstacksize()
cma_attr_set_guardsize() pthread_attr_setguardsize_np()
cma_attr_set_inherit_sched() pthread_attr_setinheritsched()
cma_attr_set_mutex_kind() pthread_mutexattr_settype_np()
cma_attr_set_priority() pthread_attr_setsched_param()
cma_attr_set_sched() pthread_attr_setschedpolicy()
cma_attr_set_stacksize() pthread_attr_setstacksize()
cma_cond_broadcast() pthread_cond_broadcast()
cma_cond_create() pthread_cond_init()
cma_cond_delete() pthread_cond_destroy()
cma_cond_signal() pthread_cond_signal()
cma_cond_signal_int() pthread_cond_signal_int_np()
cma_cond_timed_wait() pthread_cond_timedwait()
cma_cond_wait() pthread_cond_wait()
cma_delay() pthread_delay_np()
cma_handle_assign() none Use Language assignment operator.
cma_handle_equal() pthread_equal()
cma_init() none Not necessary.
cma_key_create() pthread_key_create()
(Note: pthread_key_delete() is available as well.)
cma_key_get_context() pthread_getspecific()
cma_key_set_context() pthread_setspecific()
cma_lock_global() pthread_lock_global_np()
cma_mutex_create() pthread_mutex_init()
cma_mutex_delete() pthread_mutex_delete()
cma_mutex_lock() pthread_mutex_lock()
cma_mutex_try_lock() pthread_mutex_trylock()
cma_mutex_unlock() pthread_mutex_unlock()
cma_once() pthread_once()
cma_thread_alert() pthread_cancel()
cma_thread_bind_to_cpu() none
cma_thread_create() pthread_create()
cma_thread_detach() pthread_detach()
cma_thread_exit_error() pthread_exit() With Status.
cma_thread_exit_normal() pthread_exit() With Status.
cma_thread_get_priority() pthread_getschedparam()
cma_thread_get_sched() pthread_setschedparam()
cma_thread_get_self() pthread_self()
cma_thread_join() pthread_join()
cma_thread_set_priority() pthread_setschedparam()
cma_thread_set_sched() pthread_setschedparam()
cma_time_get_expiration() pthread_get_expiration_np()
cma_unlock_global() pthread_unlock_global_np()
cma_yield() pthread_yield()

Notice that the cma routine cma_cond_timed_wait() requires the time argument expiration to be specified in local time; whereas the pthread routine pthread_cond_timedwait() requires the time argument abstime to be specified in Universal Coordinated Time (UTC).

E.4 New pthread Routines

The following are pthread interface routines that have no functional similarities in the cma interface:

Appendix F
Migrating from the d4 Interface

This appendix provides migration information for the routines in the DECthreads POSIX 1003.4a/Draft 4 (or d4) interface.


Applications that use the DECthreads d4 routines require significant modification to be migrated to the pthread interface described in Part 2.

F.1 Overview

Routines in the DECthreads pthread interface differ significantly from the original DECthreads POSIX 1003.4a/Draft 4 implementation. This section describes the major changes between the interfaces.

F.2 Error Status and Function Returns

The DECthreads pthread interface does not use the global variable errno. (Note that DECthreads provides a thread-specific errno for use by libraries and application code, but the DECthreads pthread interface does not write to it.)

If an error condition occurs, a pthread routine returns an integer value that indicates the type of error. For example, a call to the DECthreads d4 interface's implementation of pthread_cond_destroy() that returned a --1 and set errno to [EBUSY], returns [EBUSY] as the routine's return value in the pthread interface implementation.

On successful completion, most pthread interface routines return zero (0).

F.3 Replaced or Renamed Routines

Many routines in the DECthreads d4 interface have been replaced or renamed in the pthread interface, as shown in Table F-1.

Table F-1 pthread Routines That Replace d4 Routines
d4 Routine Replacement pthread Routine
pthread_attr_create() pthread_attr_init()
pthread_attr_delete() pthread_attr_destroy()
pthread_attr_set/getdetach_np() pthread_attr_set/getdetachstate()
pthread_attr_set/getprio() pthread_attr_set/getschedparam()
pthread_attr_set/getsched() pthread_attr_set/getschedpolicy()
pthread_condattr_create() pthread_condattr_init()
pthread_condattr_delete() pthread_condattr_destroy()
pthread_keycreate() pthread_key_create()
pthread_mutexattr_create() pthread_mutexattr_init()
pthread_mutexattr_delete() pthread_mutexattr_destroy()
pthread_mutexattr_get/setkind_np() pthread_mutexattr_get/settype_np()
pthread_setasynccancel() pthread_setcanceltype()
pthread_setcancel() pthread_setcancelstate()
pthread_set/getprio() pthread_set/getschedparam()
pthread_set/getscheduler() pthread_set/getschedparam()
pthread_yield() sched_yield()

F.4 Routines with No Changes to Syntax

Except for the return value, the following routines in the DECthreads d4 interface have no changes to syntax in the DECthreads pthread interface:

The following routines have no changes in syntax or return value:

Notice that the d4 routine pthread_cond_timedwait() requires the time argument abstime to be specified in local time; whereas the pthread routine pthread_cond_timedwait() requires the time argument abstime to be specified in Universal Coordinated Time (UTC).

F.5 Routines with Prototype or Syntax Changes

Table F-2 shows the routines in the DECthreads d4 interface that have changes to their argument syntax in the DECthreads pthread interface.

Table F-2 d4 Routines With Syntax Changes as pthread Routines
Old Syntax New Syntax
unsigned long pthread_attr_getguardsize_np(
pthread_attr_t attr)
int pthread_attr_getguardsize_np(
const pthread_attr_t * attr,
size_t * guardsize)
int pthread_attr_getinheritsched(
pthread_attr_t attr)
int pthread_attr_getinheritsched(
const pthread_attr_t * attr,
int * inheritsched)
unsigned long pthread_attr_getstacksize(
pthread_attr_t attr)
int pthread_attr_getstacksize(
const pthread_attr_t * attr,
size_t * stacksize)
unsigned long pthread_attr_setguardsize_np(
pthread_attr_t * attr, long guardsize)
int pthread_attr_setguardsize_np(
pthread_attr_t * attr,
size_t guardsize)
unsigned long pthread_attr_setstacksize(
pthread_attr_t * attr,
long stacksize)
int pthread_attr_setstacksize(
const pthread_attr_t * attr,
size_t stacksize)
int pthread_cleanup_pop(
int execute)
void pthread_cleanup_pop(
int execute)
int pthread_cond_init(
pthread_cond_t * cond,
pthread_condattr_t attr)
int pthread_cond_init(
pthread_cond_t * cond,
pthread_condattr_t * attr)
int pthread_create(
pthread_t * thread,
pthread_attr_t attr,
pthread_startroutine_t start_routine,
pthread_addr_t arg)
int pthread_create(
pthread_t * thread,
const pthread_attr_t * attr,
void* (* start_routine)(void *),
void * arg)
int pthread_detach(
pthread_t * thread)
int pthread_detach(
pthread_t thread)
int pthread_getspecific(
pthread_key_t key, void ** value)
void* pthread_getspecific(
pthread_key_t key)
void pthread_lock_global_np() int pthread_lock_global_np(void)
void pthread_unlock_global_np() int pthread_unlock_global_np(void)
int pthread_mutex_init(
pthread_mutex_t * mutex,
pthread_mutexattr_t attr)
int pthread_mutex_init(
pthread_mutex_t * mutex,
const pthread_mutexattr_t * attr)

Table F-3 shows routines in the DECthreads d4 interface that have a corresponding pthread routine that does not support the obsolete d4-style datatypes. These datatypes were documented for previous releases of DECthreads.

If your original code used the standard DECthreads datatypes, then this migration requirement might not impact your code.

Table F-3 d4 Routines Whose pthread Counterpart Uses Standard Datatypes
New Standard Datatype Syntax Nonstandard Datatype Syntax
void pthread_cleanup_push(
void (* routine)(void *), void * arg)
int pthread_cleanup_push(
pthread_cleanup_t * routine,
pthread_addr_t arg)
int pthread_create(
pthread_t * thread,
const pthread_attr_t * attr,
void *(* start_routine)(void *),
void * arg)
int pthread_create(
pthread_t * thread,
pthread_attr_t attr,
pthread_startroutine_t start_routine,
pthread_addr_t arg)
int pthread_exit(
void * value_ptr)
int pthread_exit(
pthread_addr_t status)
void * pthread_getspecific(
pthread_key_t key)
int pthread_getspecific(
pthread_key_t key,
pthread_addr_t * value)
int pthread_join(
pthread_t thread, void ** value_ptr)
int pthread_join(
pthread_t thread,
pthread_addr_t * status)
int pthread_once(
pthread_once_t * once_control,
void (* init_routine)(void))
int pthread_once(
pthread_once_t * once_block,
pthread_initroutine_t init_routine)
int pthread_setspecific(
pthread_key_t key, const void * value)
int pthread_setspecific(
pthread_key_t key,
pthread_addr_t value)

F.6 New Routines

The following are routines in the DECthreads pthread interface that did not exist at the time of the implementation of the d4 interface:

Previous | Next | Contents