Previous | Contents | Index |
To enable multithreading, a client application must include initial calls to the multithreading functions in Table 3-2. The specific functions called by the application depend on the shared image(s) in use.
Function | In Image | Enables Multithreading For |
---|---|---|
DECW$LCN_THREAD_INIT | DECW$LCNLIBSHR | Transport Interface |
IceInitThreads | DECW$ICELIB | ICE and XSMP |
XInitThreads | DECW$XLIBSHR | Xlib and X Extensions |
XtToolkitThreadInitialize | DECW$XTLIBSHRR5 | Xt |
Note that IceInitThreads and XInitThreads implicitly call DECW$LCN_THREAD_INIT. The interface to DECW$LCN_THREAD_INIT is described in Section 3.2.
These functions have no arguments and return a success status upon successful initialization. To ensure successful initialization, be sure to:
In addition to calling one of the multithreading functions, a client application must also be linked against the POSIX Threads Library. For example:
$ LINK THREAD_ICO/THREADS SYS$INPUT/OPT SYS$LIBRARY:DECW$XLIBSHR/SHARE SYS$LIBRARY:PTHREAD$RTL/SHARE |
Explicit links against the threads library are not required if the
application calls POSIX thread functions (such as, pthread_create).
3.1.4 Developing Applications with Thread-Aware Images
If a thread-aware image is used in a multithreaded application, the image must not accept concurrent calls nor make calls to other images that could change the state of the thread-aware image.
Note that if a thread-aware application uses the XtAppMainLoop or XtMainLoop function for dispatch handling, calls to the image will be made from callback functions. Xt makes these callbacks with an exclusive lock held on the application context. To avoid conflicts and deadlocks, applications that use a thread-aware image should include calls to XtAppLock before and XtAppUnlock after each call, or sequence of calls, to the image. The application must also call XtProcessLock and XtProcessUnlock to protect the thread-aware image against changes made by Xt to process global data.
In the following example, an application contains a background thread that constantly checks for error situations and displays an error message when a problem occurs. The main program thread first initializes thread support, creates the application context, creates the background thread, and then enters the Xtmain loop:
static XtAppContext app_context; int main () { . . . MrmInitialize (); XInitThreads (); XtToolkitThreadInitialize(); XtToolkitInitialize(); app_context = XtCreateApplicationContext(); . . . pthread_create (&thread, 0, backgroundCode, 0); . . . XtAppMainLoop(app_context) } |
Code for the background thread is as follows:
void* backgroundCode (void* data) { . . . if (problem_detected) { XtAppLock (app_context); XtProcessLock(); if (! dlog ) dlog = XmcreateWarningDialog (...); XtManageChild(dlog); XSync(display, 0); XtProcessUnlock(); XtAppUnlock(app_context); } . . . } |
Callbacks for handling the main events of the application do not require changes for multithreading, since they are called with the application context already locked.
Each of the DECwindows Motif libraries can create worker threads to support multithreading. These threads are identified by their name, which begins with the string DECW$.
Worker threads typically operate at an elevated priority to prevent task inversion, where a high-priority application thread is waiting for the worker thread to complete its operation. Note that worker threads are typically used for short duration tasks, such as responding to an internal AST or sending a status broadcast to all threads waiting for a particular activity.
In general, HP DECwindows Motif for HP OpenVMS Alpha Version 1.3 supports client applications either with or without upcalls or multiple kernel threads enabled. However, to avoid problems with priority inversion, HP recommends that upcalls be enabled for all applications that use XtAppAddInput. If upcalls cannot be enabled, then HP recommends assigning the same priority to all threads that use DECwindows Motif.
For example, an application calls XtAppAddInput to request a response to an OpenVMS event flag. The worker thread executes a SYS$WFLOR system call to wait for the event flag. Without upcalls enabled, this thread remains available even though there is no event flag set. And as a result, lower priority threads would not be scheduled.
Although some calls in the thread-safe libraries include cancellation points, the action of canceling threads that are executing DECwindows Motif functions is not supported. Canceled threads may hold locks, which can block other threads.
Note that multiple application contexts should not be used with
multiple threads and thread-aware images. Thread-aware images may
contain process global data that requires a single lock to control the
data. However, multiple calls to thread-aware images may be made from
Xt event handling functions prior to acquiring the lock.
3.2 Support for the Logical Connection Number (LCN) Interface
HP DECwindows Motif for HP OpenVMS Alpha Version 1.3 introduces an interface for determining when an I/O channel is ready and available for use. The logical connection number (LCN) interface is now used to signal when DECwindows Motif I/O channels are available, including those for Inter-Client Exchange (ICE), local and remote X server, and for Input Method Server connections.
Previously, DECwindows Motif used an OpenVMS event flag number (EFN) to signal when input was received from the X server. However, EFNs cannot be used safely in a multithreaded environment. The LCN interface allows multiple threads to handle the same, or different, connections without any thrashing or unnecessary delays.
The following sections further describe the functions of the LCN
interface and provide detailed information about the supported routines.
3.2.1 LCN Functions
The principal function of the LCN interface is to test the readiness of an I/O channel. The design of the interface is based on the UNIX select function, which tests the state of UNIX file descriptors and returns when one of them is ready or a timeout occurs.
On OpenVMS, the LCN routines perform the following operations:
LCN routines can execute in a single-threaded environment using EFNs to signal input or in a multithreaded environment using POSIX Threads routines. Multithreading is enabled with the DECW$LCN_THREAD_INIT routine.
With multithreading enabled, the select routines (DECW$LCN_SELECT_ONE and DECW$LCN_SELECT) can be called concurrently from multiple kernel threads in user mode and one kernel thread in exec mode. Calls from user mode ASTs are not allowed.
With single threading, the select routines can be called from user mode
and exec mode ASTs. Note, however, that the only concurrent calls
allowed are one call from user mode followed by one call from an AST in
user mode.
3.2.1.2 Allocating Connection Numbers
LCNs are allocated to a connection using the DECW$LCN_ALLOCATE routine. Values for LCNs start at 64 to distinguish them from local event flags. The maximum number of concurrently allocated LCNs equals the open file limit of the process. If the quota is 0, a default value of 1023 is used. If the quota exceeds the maximum value, a value of 2047 is used.
Once an LCN is allocated, it is unavailable for reuse until freed by
the DECW$LCN_FREE routine.
3.2.1.3 Querying Status and Signaling Input
Each LCN has three status flags, which signify whether an LCN is ready and has received input from a particular operation. Each flag can be either set (1) using the DECW$LCN_SET_x_READY routine or cleared (0) using the DECW$LCN_CLEAR_x_READY routine.
Input is signaled by setting the appropriate ready flag. The following table lists each LCN flag and describes when it is typically set and cleared.
Flag | Description |
---|---|
read ready | Set when there is data available to read. |
write ready | Set when there is space in internal buffers to which data can be written. |
except ready | Set when there is high-priority (exceptional) input. |
Each flag can be set individually, and a select operation can test any combination of them. There are two routines that essentially mirror the UNIX select function, and test the ready state of an LCN. DECW$LCN_SELECT selects and tests the status of a range of LCNs or EFNs. DECW$LCN_SELECT_ONE performs the same function, however only tests the status of a single LCN.
3.2.2 LCN Routines
This section describes each of the LCN routines, which are available
from the library image DECW$LCNLIBSHR.EXE. To support use from
protected images that cannot use the client library, some functions are
also available as part of the X Transport system services
(DECW$XPORT_SERVICES).
3.2.2.1 DECW$LCN_ALLOCATE
Assigns an LCN.
Format
DECW$LCN_ALLOCATE lcn |
VMS usage: type: longword (unsigned) access: write mechanism: by value
Returns a longword condition value in R0. Condition values returned by this routine are listed under Condition Values Returned.
lcn
VMS usage: type: longword access: write only mechanism: by reference
The value of the allocated LCN.
Description
DECW$LCN_ALLOCATE assigns a logical connection number. Initially, each allocated LCN is assigned with all ready flags (read, write, and except) in the clear state (0). The state of these flags can be changed using the DECW$LCN_SET_x_READY routines.
Once allocated, the LCN cannot be reused until it is released by DECW$LCN_FREE. DECW$LCN_ALLOCATE must be called before any query, wait, or signaling operations can be performed.
DECW$LCN_ALLOCATE is both thread- and AST-reentrant and is callable from exec and lower modes.
The equivalent function of DECW$LCN_ALLOCATE is also available as a system service (DECW$XPORT_LCN_ALLOCATE) from the set of transport-common routines (DECW$XPORT_SERVICES.EXE).
Condition Values Returned
SS$_NORMAL | Routine successfully completed. |
DECW$_INSFMEM | There is insufficient memory to perform the operation. |
DECW$_NOFREELCN | All LCNs are currently allocated. |
Changes the ready bit for read, write, or except operations to the clear state.
Format
DECW$LCN_CLEAR_READ_READY lcn [, prior] |
DECW$LCN_CLEAR_WRITE_READY lcn [, prior] |
DECW$LCN_CLEAR_EXCEPT_READY lcn [, prior] |
VMS usage: type: longword (unsigned) access: write mechanism: by value
Returns a longword condition value in R0. Condition values returned by this routine are listed under Condition Values Returned.
lcn
VMS usage: type: longword access: read only mechanism: by value
The value of the LCN whose ready bit for read, write, and except operations will be changed to the clear state (0).[prior]
VMS usage: type: longword access: write only mechanism: by reference
The previous state of the associated ready flag, either clear (0) or set (1).
Description
DECW$LCN_CLEAR_x_READY clears the read, write, or except ready bit of an LCN. This indicates that the LCN is not available for input from the specified operations.
These routines are thread- and AST-reentrant and callable from exec and lower modes.
The equivalent functions of DECW$LCN_CLEAR_x_READY are also available as system services (DECW$XPORT_LCN_CLEAR_x) from the set of transport-common routines (DECW$XPORT_SERVICES.EXE). Note that when using the system service, the prior argument is required; use a 0 value to prevent the prior state from being returned.
Condition Values Returned
SS$_NORMAL | Routine successfully completed. |
DECW$_NOT_INITIALIZED | The LCN has not been initialized; DECW$LCN_ALLOCATE must be called prior to this operation. |
DECW$_INVLCN | The LCN has not been allocated. |
Deassigns an allocated LCN.
Format
DECW$LCN_FREE lcn |
VMS usage: type: longword (unsigned) access: write mechanism: by value
Returns a longword condition value in R0. Condition values returned by this routine are listed under Condition Values Returned.
lcn
VMS usage: type: longword access: read only mechanism: by value
The value of the LCN to be freed.
Description
DECW$LCN_FREE deassigns the specified LCN. Once freed, the LCN is available for immediate reallocation.
This routine is thread- and AST-reentrant and callable from exec and lower modes.
The equivalent function of DECW$LCN_FREE is also available as a system service (DECW$XPORT_LCN_FREE) from the set of transport-common routines (DECW$XPORT_SERVICES.EXE).
If either DECW$LCN_SELECT_ONE or DECW$LCN_SELECT has been called to test a state of the LCN which has been freed, then the status DECW$_INVLCN is returned from the select call. |
Condition Values Returned
SS$_NORMAL | Routine successfully completed. |
SS$_INSFMEM | There is insufficient memory to perform the operation. |
DECW$_NOT_INITIALIZED | The LCN has not been initialized; DECW$LCN_ALLOCATE must be called prior to this operation. |
DECW$_INVLCN | The LCN has not been allocated or is protected. |
3.2.2.4 DECW$LCN_SELECT
Tests the ready state(s) of one or more LCNs and returns when one of
the tested states is set, a timeout occurs, or a specified OpenVMS
event flag is set.
Format
DECW$LCN_SELECT retcount, rmask, wmask, emask, [timeout], [efn], [efn_mask] |
VMS usage: type: longword (unsigned) access: write mechanism: by value
Returns a longword condition value in R0. Condition values returned by this routine are listed under Condition Values Returned.
retcount
VMS usage: type: longword access: write only mechanism: by reference
The total number of entries set in the three mask structures (rmask, wmask, emask).rmask, wmask, emask
VMS usage: type: mask access: read,write mechanism: by reference
Specifies whether to check the read (rmask), write (wmask), or exception (emask) status of one or more LCNs. A value indicates that the status check be performed; a null value indicates that no check be made. On completion, the mask is updated to reflect which LCNs have their ready state set.The format of each mask is an array of word values. The first entry is the number of remaining entries in the array. Each subsequent entry represents an LCN value.
timeout
VMS usage: type: quadword access: read only mechanism: by reference
The time by which the select operation will timeout if no input is received. The time value is expressed in OpenVMS binary delta-time format. A null value indicates no timeout. A value of 0 indicates the operation is in polling mode and will timeout immediately if none of the specified status bits are set.efn
VMS usage: type: longword access: read only mechanism: by value
An event flag number (EFN) in the cluster to which the efn_mask argument applies. EFNs are typically used for single-threaded or inner-mode operations. In this environment, efn identifies an event flag for the wait operation.If no EFN value is provided in single-thread mode, SYS$HIBER and SYS$WAKE are used. In these instances, SYS$HIBER must not be used concurrently within the process. In particular, POSIX Threads must not be loaded into the image, even if not in use.
For multithreaded, user mode operations, this argument can be optional depending on whether an EFN has been provided previously to DECW$LCN_THREAD_INIT. If the EFN was specified and the value of efn_mask is 0, the argument is optional. Otherwise the value of this argument is required and will be used as if it had been provided to DECW$LCN_THREAD_INIT.
efn_mask
VMS usage: type: longword access: read only mechanism: by value
A mask of EFNs to be tested. Requires the efn argument.
Description
DECW$LCN_SELECT waits until one of the specified LCN ready states has been set, timed out, or until the event flag condition is met. This routine checks whether the selected LCNs have been allocated and returns an error (DECW$_INVLCN) if one or more LCNs have either not been allocated or freed for reuse.
With multithreading enabled, this routine is thread-reentrant and callable from exec or lower modes. Calls from ASTs are not supported.
With single threading, the select routines can be called from user mode and exec mode ASTs. Note, however, that the only concurrent calls allowed are one call from user mode followed by one call from an AST in user mode.
Condition Values Returned
SS$_NORMAL | Routine successfully completed. One or more LCNs have their ready bit set as indicated in the updated mask values. |
SS$_EXQUOTA | A process quota has been exceeded, this can be due to the timer entry or AST limit quota. |
SS$_INSFMEM | There is insufficient memory to perform the operation. |
SS$_UNASEFC | The process is not associated with the cluster that contains the specified event flag. |
DECW$_BAD_EFN_CLUSTER | An event flag was not provided to DECW$LCN_THREAD_INIT, or the specified flag resides in a different event flag cluster. |
DECW$_EFN_SET | One or more event flags in the mask have been set. |
DECW$_INVARG | The array count in a read, write, or exception mask, or the timeout value is not valid. |
DECW$_INVLCN | One or more LCNs have not been allocated or were freed during the operation. |
DECW$_NOHIBER | This call was made from inner-mode with multithreading enabled. No EFN was specified. |
DECW$_PTHREAD_INVALID | A POSIX Threads routine returned an unexpected error. |
DECW$_TIMEDOUT | The end of the timeout period was reached. |
Previous | Next | Contents | Index |