Document revision date: 30 March 2001

## Guide to the POSIX Threads Library

Previous | Contents | Index

## Appendix B
Considerations for OpenVMS Systems

This appendix discusses POSIX Threads Library issues and restrictions specific to the OpenVMS operating system.

## B.1 Overview

The OpenVMS Alpha operating system supports multiple concurrent "execution contexts" within a process. The Threads Library 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. Even without kernel threads, OpenVMS Alpha "upcalls" support smooth integration between the Threads Library and kernel scheduler. See Section B.12 for more information, including how to enable kernel threads and upcalls in your application. OpenVMS VAX supports neither kernel threads nor upcalls.

## B.2 Compiling Under OpenVMS

The C language header files shown in Table B-1 provide interface definitions for the pthread and tis interfaces.

Table B-1 Header Files
Header File | Interface
--- | ---
`pthread.h` | POSIX.1 style routines
`tis.h` | Compaq proprietary thread-independent services routines

Include only one of these header files in your module.

Special compiler definitions are not required when compiling threaded applications that use the pthread interface or the tis interface.

## B.3 Linking OpenVMS Images

The Threads Library is supplied only as shareable images. It is not supplied as object libraries.

When you link an image that calls Threads Library routines, you must link against the appropriate images listed in Table B-2.

Table B-2 Threads Library Images
Image | Routine Library
--- | ---
PTHREAD$RTL.EXE | POSIX.1 style interface
CMA$TIS_SHR.EXE | Thread-independent services

The image files PTHREAD$RTL.EXE, CMA$TIS_SHR.EXE, CMA$RTL.EXE, and CMA$LIB_SHR.EXE are included in the IMAGELIB library, making it unnecessary to specify those images (unless you are using the /NOSYSLIB switch with the linker) in a Linker options file.

When you link an image that uses the CMA$OPEN_LIB_SHR.EXE and CMA$OPEN_RTL.EXE images, you must specify them in a Linker options file.

Note While this version of the POSIX Threads Library for OpenVMS supports upward compatibility of source and binaries for the d4 interface, it does not support upward compability for object files. For instance, under OpenVMS V7.0 and higher, to link object files that were compiled under OpenVMS V6.2, follow these steps: Copy CMA$OPEN_RTL.EXE from SYS$SHARE for OpenVMS V6.2 into the directory with your object files compiled under the current OpenVMS version. During linking, it provides the locations of the transfer vector entries (OpenVMS VAX) or symbol vector entries (OpenVMS Alpha) in CMA$OPEN_RTL.EXE for the older OpenVMS version. Instead of specifying `SYS$SHARE:CMA$OPEN_RTL/SHARE` in your link options files, specify `CMA$OPEN_RTL/SHARE` . Be careful about the placement of this option in the options file---it should perhaps be placed at the beginning, or close to it, if you are including other images that link against PTHREAD$RTL. Link your program. Delete CMA$OPEN_RTL.EXE from your object directory for the current OpenVMS version.

## B.4 Using the Threads Library with AST Routines

An asynchronous system trap, or AST, is an OpenVMS mechanism for reporting an asynchronous event to a process. The following are restrictions concerning the use of ASTs with the Threads Library:

- Avoid blocking ASTs using any mechanism other than $SETAST.
- Be aware that blocking ASTs in one thread may prevent delivery of ASTs that are actually intended for other threads. Therefore, it is best to avoid blocking ASTs for an extended period of time. Also, it is best to avoid calling Threads Library functions that may block the thread while it has disabled ASTs.
- Do not call Threads Library routines, except those that have the `_int` (interrupt) suffix in their names, from within an AST routine. Calling any other Threads Library routines from code running in an AST can be unreliable or cause unexpected behavior.
- For OpenVMS Alpha, ASTs are handed off to the Threads Library by the operating system. This allows ASTs to be delivered in the context of the appropriate thread. On a multiprocessor machine it may be possible to have a thread executing an AST routine in parallel with another thread's execution. When a thread disables ASTs, not only does it block out its own ASTs, but it prevents delivery of any ASTs that do not specifically belong to a particular thread as well.
- For synchronous I/O completion, use the asynchronous variant of the system service routine and the `tis_io_complete()` and `tis_sync()` routines.

## B.5 Dynamic Activation

Certain run-time libraries use conditional synchronization mechanisms. These mechanisms typically are enabled during image initialization when the run-time library is loaded, and only if the process is multithreaded (that is, if the core run-time library PTHREAD$RTL has been linked in). If the process is not multithreaded, the synchronization is disabled.

If your application were to dynamically activate PTHREAD$RTL, any run-time library that uses conditional synchronization may not behave reliably. Thus, dynamic activation of the core run-time library PTHREAD$RTL is not supported.

If your application must dynamically activate an image that depends upon PTHREAD$RTL (that is, the image must run, or can be run, in a multithreaded environment), you must build the application by explicitly linking the image calling LIB$FIND_IMAGE_SYMBOL against PTHREAD$RTL.

Use the OpenVMS command ANALYZE/IMAGE to determine whether an image depends upon PTHREAD$RTL. For more information see your OpenVMS documentation.

Libraries that wish to use thread-safe synchronization only when threads are present should use the tis functions instead of dynamically activating `PTHREAD$RTL.EXE` .

## B.6 Default and Minimum Thread Stack Size

As of OpenVMS Version 7.2, the Threads Library has increased the default thread stack size for both OpenVMS Alpha and OpenVMS VAX. Applications that create threads using the default stack size (or a size calculated from the default) will be unaffected by this change.

As of OpenVMS Version 7.2, the Threads Library has increased the minimum thread stack size (based on the `PTHREAD_STACK_MIN` constant) for OpenVMS VAX only. Existing applications that were built using a version prior to OpenVMS Version 7.2 and that base their thread stack sizes on this minimum must be recompiled.

## B.7 Requesting a Specific, Absolute Thread Stack Size

Prior to OpenVMS Version 7.2, when an application requested to allocate a thread stack of a specific, absolute size, the Threads Library would increase the size by a certain quantity, then round up that sum to an integral number of pages. This process resulted in the actual stack size being considerably larger than the caller's request, possibly by more than one page.

Starting with OpenVMS Version 7.2, when an application requests the Threads Library to allocate a thread stack of a specific, absolute size, no additional space is added, but the allocation is still rounded up to an integral number of pages.

Any application that uses default-sized stacks is unlikely to experience problems due to this change. Similarly, any application that sets its thread stack allocations in terms of either the default or the allowable minimum stack size is unlikely to experience problems due to this change; however, depending on the allocation calculation used, the application might receive more memory for thread stacks.

Starting with OpenVMS Version 7.2, any thread that is created with a stack allocation of a specific, absolute size might fail during execution because of insufficient stack space. This failure indicates an existing bug in the application that was made manifest by the change in the Threads Library.

When the application requests to allocate a thread stack of a specific size, it must allow for not only the space that the application itself requires, but also sufficient stack space for context switches and other activity. The Threads Library only occasionally uses this additional stack space, such as during timeslice interruptions. A thread with inadequate stack space might not encounter problems during development and testing because of timing vagaries---for instance, a thread might not experience problems until a timeslice occurs while the thread is at its maximum stack utilization---and this situation might never arise during in-house testing. In a different system environment, such as in a production environment, the timing might be different, possibly resulting in occasional failures when certain conditions are met.

## B.8 Declaring an OpenVMS Condition Handler

This section discusses a restriction on declaring an OpenVMS condition handler while using exceptions, and behavior when a condition is signaled.

The following are three ways to declare an OpenVMS condition handler:

- Calling VAXC$ESTABLISH (from a program written in C)
- Calling LIB$ESTABLISH
- Placing the address of the condition handler directly into the stack frame (from a program written in VAX MACRO or VAX BLISS)

Do not declare an OpenVMS condition handler within a `TRY/ENDTRY` exception block. Doing so deletes without notification any handler that exists for the current procedure. If your code declares a condition handler within the `TRY/ENDTRY` block, exceptions will not be handled correctly until the next `TRY` statement is executed. The `TRY` statement restores the condition handler.

On OpenVMS VAX, you can declare a condition handler outside of a `TRY/ENDTRY` block with no restrictions. If a condition handler has already been declared when you execute a `TRY` statement, the Threads Library saves the previous handler address. When the Threads Library receives a condition it does not handle (including SS$_UNWIND, SS$_DEBUG, or a condition code that does not have a SEVERE severity), it invokes the saved condition handler. The condition handler will be reestablished when the `TRY` block exits.

## B.9 Thread Cancelability of System Services

On OpenVMS Alpha, system calls are not cancelation points for threads created using the POSIX 1003.1 style interface. System calls are not cancelation points for threads in legacy multithreaded applications that were created using the Compaq proprietary CMA (or cma) or POSIX 1003.4a/Draft 4 (d4 or DCEthreads) interfaces. None of the system calls should be called with asynchronous cancelation enabled. For more information, see Section 2.3.7.

## B.10 Using OpenVMS Alpha 64-Bit Addressing

On OpenVMS Alpha, the Threads Library supports the use of 64-bit addressing in the pthread interface only. When compiling with the following command, the `pthread_join()` function returns a 64-bit `void *` value as the result:

       $ CC/POINTER_SIZE=LONG

You can also use `pthread_join64()` or `pthread_join32()` to specify the length in bits of the return value.

Note that no other Threads Library functions have special 64-bit versions because the OpenVMS Alpha calling standard always supports 64-bit arguments and return values.

## B.11 Condition Values

Table B-3 lists the condition values for OpenVMS systems and provides an explanation and user action.

Table B-3 Condition Values
Condition Value | Explanation and User Action
--- | ---
CMA$_EXCCOP | Exception raised, OpenVMS condition code follows.
| Explanation: One of the exception commands (RAISE or RERAISE) raised or reraised an exception condition originating outside the Threads Library. The secondary condition code in the signal vector will be the original code.
| User Action: See the documentation for the software that your program is calling to determine the reason for this exception.
CMA$_EXCCOPLOS | Exception raised, some information lost.
| Explanation: CMA$_EXCCOPLOS is nearly the same as CMA$_EXCCOP except that the Threads Library determined that the copied signal vector may contain address arguments. However, the address arguments may not be valid when the stack is unwound and the condition is resignaled. Therefore, the Threads Library clears the condition codes' arguments in the resignaled vector. In most cases, the Threads Library knows that SS$_ code arguments are "safe" and will not clear them. Most other codes with arguments will result in CMA$_EXCCOPLOS.
| User Action: See the documentation for the software that your program is calling to determine the reason for this exception.
CMA$_EXCEPTION | Exception raised, address of exception object is object-address.
| Explanation: This condition is used as the primary condition to `RAISE` an address-type exception. The condition is signaled with a single argument containing the address of the `EXCEPTION` structure. There is no support for interpreting this value. It is only meaningful to the facility that defined the `EXCEPTION` . It is not good programming practice to let an address exception propagate outside the facility that raised it. There is no support for retrieving message text, and it cannot be interpreted by other facilities.
| User Action: None.

## B.12 Two-Level Scheduling on OpenVMS Alpha Systems

This section applies to OpenVMS Alpha systems only.

Under OpenVMS Alpha Version 7.0 and later, the Threads Library implements a two-level scheduling model. This model is based on the concept of virtual processors. Virtual processors are implemented as a result of using kernel thread technology in the OpenVMS Alpha operating system.

The Threads Library schedules threads onto virtual processors similar to the way that OpenVMS schedules processes onto the processors of a multiprocessing machine. Thus, to the runtime environment, a scheduled thread is executed on a virtual processor until it blocks or until it exhausts its timeslice quantum; then the Threads Library schedules a new thread to run.

While the Threads Library schedules threads onto virtual processors, the OpenVMS scheduler also schedules virtual processors to run on physical processors. The term "two-level scheduling" derives from this relationship.

The two-level scheduling model provides these advantages:

- It allows most thread scheduling to take place completely in user mode--that is, without the intervention of the OpenVMS scheduler. Because a thread context switch does not involve any privileged information (rather, only a swapping of registers), it can be done much more efficiently in user mode than a context switch involving the operating system.
- It allows the OpenVMS scheduler to schedule virtual processors onto separate processors of a multiprocessing machine. This allows a process using the Threads Library to take advantage of the full resources of a multiprocessor machine.

The key to making the two-level scheduling model work is the upcall mechanism. An upcall is a communication between the OpenVMS scheduler and the Threads Library scheduler. When an event occurs that affects the scheduling of a thread, such as blocking for a system service, the OpenVMS scheduler calls "up" to the Threads Library scheduler to notify it of the change in the thread's status.

This upcall gives the Threads Library the opportunity to schedule another thread to run on the virtual processor in place of the blocking thread, rather than to allow the virtual processor itself to block, which would deny that resource to other threads in the process.

Upcalls are typically arranged in pairs, with an "unblock" upcall corresponding to each "block" upcall. The unblock upcall notifies the Threads Library that a previously blocked thread is now eligible to run again. The Threads Library schedules that thread to run based on its scheduling policy and priority.

### B.12.1 Linker Options to Specify Image's Use of Kernel Threads

In OpenVMS Alpha Version 7.1 and later, the linker supports the /THREADS_ENABLE (or /NOTHREADS_ENABLE) qualifier for specifying the role of kernel threads in the resulting image. Use this qualifier to specify whether the process can create multiple kernel threads and whether the OpenVMS Alpha kernel's support for upcalls is enabled. If this qualifier is not specified, the default linker setting is /NOTHREADS_ENABLE, which results in an image that behaves as under OpenVMS Alpha Version 6.

The /THREADS_ENABLE qualifier takes two keyword arguments, MULTIPLE_KERNEL_THREADS and UPCALLS. Table B-4 summarizes the allowable combinations of these keywords and their effects. This qualifier must be applied to a "main" image. If used on a shared library image, it will be ignored.

The use of kernel threads and upcalls is also limited by the kernel sysgen parameter `MULTITHREAD` . If set to 0, no process may use upcalls or create kernel threads. A value of 1 allows upcalls, but not kernel threads. A higher value represents the maximum number of kernel threads each process may use. (You cannot have multiple kernel threads without upcalls.)

Table B-4 Results of Keyword Arguments to /THREADS_ENABLE Qualifier
Keywords Specified | Result
--- | ---
/NOTHREADS_ENABLE | No kernel threads support
/THREADS_ENABLE or: /THREADS_ENABLE=(MULTIPLE_KERNEL_THREADS,UPCALLS) | Full kernel threads support, including the ability to run multiple user threads simultaneously on different CPUs on a multiprocessor machine
/THREADS_ENABLE=MULTIPLE_KERNEL_THREADS | Same behavior as if /NOTHREADS_ENABLE is specified (without support for upcalls, the Threads Library cannot reliably use multiple kernel threads)
/THREADS_ENABLE=UPCALLS | Upcall support (such as making system calls thread-synchronous), but restricts the process' threads to one CPU on a multiprocessor machine

Note Under no circumstances should a process explicitly create kernel threads. The Threads Library creates them as needed when allowed to do so. Explicit creation of kernel threads by an application disrupts the operation of the runtime environment and causes incorrect and/or unreliable application behavior.

### B.12.2 Setting Kernel Threads Support in Existing Images

Under OpenVMS Alpha only, use the THREADCP tool to set or show the kernel threads features described earlier for an existing main image. The tool provides the ability to enable, disable, and show the state of the thread control bits in an image's header.

The THREADCP command verb is not part of the normal set of DCL commands. To use the tool, you must define the command verb before invoking it, as shown in Section B.12.2.1.

In a THREADCP command, an image file name is a required parameter for use with all supported qualifiers. THREADCP supports abbreviations to the first character for all qualifiers and parameters. When the SHOW qualifier is used alone with the THREADCP command, the file name can contain wildcard characters.

After you define the THREADCP command verb, an image's thread control bits can be set or cleared using the /ENABLE and /DISABLE qualifiers, respectively. To do so, specify the name of each thread control bit to be enabled, disabled, or shown. One or both thread control bits can be specified. The user must have write access to the image file.

If no thread control bit is specified, the THREADCP default is to operate on both bits. If the image is currently being executed or is installed, it cannot be modified.

Previous | Next | Contents | Index

| privacy and legal statement |
6101PRO_031.HTML