Previous | Contents | Index |
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.
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 |
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" |
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:
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.
This appendix provides migration information for the routines in the POSIX 1003.4a/Draft 4 (or d4) interface.
Applications that use the d4 routines require significant modification to be migrated to the pthread interface described in Part 2. |
Routines in the pthread interface differ significantly
from the original POSIX 1003.4a/Draft 4 implementation. This section
describes the major changes between the interfaces.
D.2 Error Status and Function Returns
The pthread interface does not use the global variable errno. (Note that the Threads Library provides a thread-specific errno for use by libraries and application code, but the 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 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).
D.3 Replaced or Renamed Routines
Many routines in the d4 interface have been replaced or renamed in the pthread interface, as shown in Table D-1.
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/getguardsize_np() | pthread_attr_set/getguardsize() |
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() |
pthread_setasynccancel() | pthread_setcanceltype() |
pthread_setcancel() | pthread_setcancelstate() |
pthread_set/getprio() | pthread_set/getschedparam() |
pthread_set/getscheduler() | pthread_set/getschedparam() |
pthread_yield() | sched_yield() |
Except for the return value, the following routines in the d4 interface have no changes to syntax in the pthread interface:
pthread_attr_setinheritsched()
pthread_cancel()
pthread_cond_broadcast()
pthread_cond_destroy()
pthread_cond_signal()
pthread_cond_signal_int_np()
pthread_cond_timedwait()
pthread_cond_wait()
pthread_delay_np()
pthread_equal()
pthread_exit()
pthread_get_expiration_np()
pthread_join() (now detaches the thread)
pthread_mutex_destroy()
pthread_mutex_lock()
pthread_mutex_trylock()
pthread_mutex_unlock()
pthread_once()
The following routines have no changes in syntax or return value:
pthread_self()
pthread_testcancel()
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).
D.5 Routines with Prototype or Syntax Changes
Table D-2 shows the routines in the d4 interface that have changes to their argument syntax in the pthread interface.
Old Syntax | New Syntax |
---|---|
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_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 D-3 shows routines in the 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 the Threads Library.
If your original code used the standard Threads Library datatypes, then this migration requirement might not impact your code.
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) |
The following are routines in the pthread interface that did not exist at the time of the implementation of the d4 interface:
pthread_atfork() (Tru64 UNIX only)
pthread_attr_getscope()
pthread_attr_setscope()
pthread_key_delete()
pthread_kill() (Tru64 UNIX only)
All pthread_rwlockattr_ and pthread_rwlock_ routines
pthread_sigmask() (Tru64 UNIX only)
All _getpshared and _setpshared routines
Previous | Next | Contents | Index |