Document revision date: 30 March 2001

## Guide to the POSIX Threads Library

Previous | Contents | Index

## Appendix C
Debugging Multithreaded Applications

The debugging information in this appendix is specific to applications that use the POSIX Threads Library.

## C.1 Using PTHREAD_CONFIG

During initialization of the Threads Library run-time environment, the `PTHREAD_CONFIG` environment variable (on Tru64 UNIX systems) or logical symbol (on OpenVMS systems), if defined, is used to set static options for the multithreaded program. You can set `PTHREAD_CONFIG` to assist you in debugging a Threads Library application.

### C.1.1 Major and Minor Keywords

As summarized in Table C-1, `PTHREAD_CONFIG` takes "major keywords" as arguments. Use a "minor keyword" to specify a value for each major keyword.

Table C-1 PTHREAD_CONFIG Settings
Major keyword | Minor keyword | Meaning
--- | --- | ---
`dump=` | file-path | Path of bugcheck file (OpenVMS only)
`meter=` | `condition` | Meter condition variable operations
| `mutex` | Meter mutex operations
| `stack` | Record thread greatest stack extent
| `all` | Meter all available operations
| `none` | No metering
`width=` | bugcheck_output_width | Width of output from bugcheck output

### C.1.2 Specifying Multiple Values

When setting `PTHREAD_CONFIG` , use a semicolon to separate major keyword expressions and use a comma to separate minor keyword values. For example, using DCL under OpenVMS, you can set `PTHREAD_CONFIG` as follows:

       $ define PTHREAD_CONFIG "meter=(stack,mutex);dump=/tmp/dump-d.dmp;width=132"

## C.2 Running in Metered Mode

Metering tells the Threads Library 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 the Threads Library 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 the Threads Library to gather and record statistics and history information for all synchronization operations.

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.

## C.3 Visual Threads

We recommend Visual Threads to debug Threads Library applications on Tru64 UNIX and OpenVMS systems. Visual Threads can be used to automatically diagnose common problems associated with multithreading, including deadlock, protection of shared data (on Tru64 UNIX systems only), and thread usage errors. It can also be used to monitor the thread-related performance of an application, helping you to identify bottlenecks or locking granularity problems. It is a unique debugging tool because it can be used to identify problem areas even if an application does not show any specific symptoms.

See the online Visual Threads documentation at `www.compaq.com/visualthreads/` for more information.

## C.4 Using Ladebug on Tru64 UNIX Systems

The Compaq Ladebug debugger provides commands to display the state of threads, mutexes, and condition variables.

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

The basic commands are:

- `thread n` --- Sets the current thread context to n.
- `show thread [n ...]` --- Displays thread state (more information displayed if `$verbose=1` )
- `show mutex [n ...]` --- Displays mutex state.
- `show condition [n ...]` --- Displays condition variable state.

Refer to the Ladebug documentation for further details.

## C.5 Debugging Threads on OpenVMS Systems

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

### C.5.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 `TRY` / `CATCH` , `TRY` / `FINALLY` , or POSIX cleanup handlers are used, from the point where it was last reraised to the bottom of the stack.

## Appendix D
Migrating from the cma Interface

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

Note In future 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 pthread interface is the most portable, efficient, and robust multithreading run-time library offered by Compaq.

## D.1 Overview

The 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 the POSIX Threads Library.

You should include the C language `pthread.h` header file for prototypes of the pthread routines.

## D.2 cma Handles

A cma handle is storage, similar to a pointer, that refers to a specific Threads Library 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 the Threads Library.

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

- Using an uninitialized handle
- Using a corrupted handle
- Using a handle whose object no longer exists (a dangling handle)

Handles are not supported in the 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.)

## D.3 Interface Routine Mapping

As summarized in Table D-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 D-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_stack_check_limit_np()` |  |
`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_np()` |

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).

## D.4 New pthread Routines

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

> `pthread_atfork()` (Tru64 UNIX only)
> `pthread_attr_getdetachstate()`
> `pthread_attr_getscope()`
> `pthread_attr_setdetachstate()`
> `pthread_attr_setscope()`
> `pthread_condattr_getpshared()`
> `pthread_condattr_setpshared()`
> `pthread_key_delete()`
> `pthread_kill()` (Tru64 UNIX only)
> `pthread_mutexattr_getpshared()`
> `pthread_mutexattr_setpshared()`
> All `pthread_rwlockattr_` and `pthread_rwlock_` routines
> `pthread_sigmask()` (Tru64 UNIX only)
> `sigwait()`

Previous | Next | Contents | Index

| privacy and legal statement |
6101PRO_033.HTML