HP OpenVMS Systems Documentation
HP OpenVMS Programming Concepts Manual
18.104.22.168 Subresources and Sublocks
Subresources and sublocks greater than 65535 are allowed. OpenVMS supports sub-resource and sub-lock counts up to the current architectural limits of the lock manager. The maximum number of locks on a single resource is limited to 65,535. If your program attempts to exceed this limit, SS$_EXDEPTH is returned.
In a mixed-version OpenVMS Cluster, only nodes running OpenVMS Version
7.1 or higher are able to handle these large lock trees. Large scale
locking applications should be restricted to running on a subset of
nodes running OpenVMS Version 7.1 or higher, or the entire cluster
should be upgraded to OpenVMS Version 7.1 or higher to avoid
The resource hash table is an internal OpenVMS lock manager structure used to do quick lookups on resource names without a lengthy interactive search. Like all such tables, it results in a tradeoff of consuming memory in order to speed operation. A typical tuning goal is to have the resource hash table size (RESHASHTBL system parameter) about four times larger than the total number of resources in use on the system. Systems that have memory constraints or are not critically dependent on locking speed could set the table to a smaller size.
The maximum for the RESHASHTBL is 16,777,216 (224), which is the current architectural maximum for the total number of resources possible on the system.
Large memory systems that use very large resource namespaces can take
advantage of this value to gain a performance advantage in many locking
The lock ID table is an internal OpenVMS lock manager structure used to
find the relevant data structures for any given lock in the system.
OpenVMS dynamically increases the lock ID table as usage requires and
if sufficient physical memory is available. The default, minimum, and
maximum values for the LOCKIDTBL system parameter allow large single
tables for lock IDs. The maximum number of locks is regulated by the
amount of available nonpaged pool.
You use the SYS$ENQ or SYS$ENQW system service to queue lock requests. SYS$ENQ queues a lock request and returns; SYS$ENQW queues a lock request, waits until the lock is granted, and then returns. When you request new locks, the system service call must specify the lock mode, address of the lock status block, and resource name.
The format for SYS$ENQ and SYS$ENQW is as follows:
SYS$ENQ(W) ([efn] ,lkmode ,lksb ,[flags] ,[resnam] ,[parid] ,[astadr]
In this example, a number of processes access the STRUCTURE_1 data structure. Some processes read the data structure; others write to the structure. Readers must be protected from reading the structure while it is being updated by writers. The reader in the example queues a request for a protected read mode lock. Protected read mode is compatible with itself, so all readers can read the structure at the same time. A writer to the structure uses protected write or exclusive mode locks. Because protected write mode and exclusive mode are not compatible with protected read mode, no writers can write the data structure until the readers have released their locks, and no readers can read the data structure until the writers have released their locks.
The program segment in Example 7-1 requests a null lock for the resource named TERMINAL. After the lock is granted, the program requests that the lock be converted to an exclusive lock. Note that, after SYS$ENQW returns, the program checks the status of the system service and the status returned in the lock status block to ensure that the request completed successfully. (The lock mode symbols are defined in the $LCKDEF module of the system macro library.)
For more complete information on the use of SYS$ENQ, refer to the
HP OpenVMS System Services Reference Manual.
The previous sections discuss locking techniques and concepts that are
useful to all applications. The following sections discuss specialized
features of the lock manager.
The SYS$ENQ system service returns control to the calling program when the lock request is queued. The status code in R0 indicates whether the request was queued successfully. After the request is queued, the procedure cannot access the resource until the request is granted. A procedure can use three methods to check that a request has been granted:
These methods of synchronization are identical to the synchronization techniques used with the SYS$QIO system services (described in Chapter 23).
The $ENQW macro performs synchronization by combining the functions of
the SYS$ENQ system service and the Synchronize (SYS$SYNCH) system
service. The $ENQW macro has the same arguments as the $ENQ macro. It
queues the lock request and then places the program in an event flag
wait state (LEF) until the lock request is granted.
The lock management services provide a mechanism that allows processes to determine whether a lock request is granted synchronously, that is, if the lock is not placed on the conversion or waiting queue. This feature can be used to improve performance in applications where most locks are granted synchronously (as is normally the case).
If the flag bit LCK$M_SYNCSTS is set and a lock is granted synchronously, the status code SS$_SYNCH is returned in R0; no event flag is set, and no AST is delivered.
If the request is not completed synchronously, the success code
SS$_NORMAL is returned; event flags or AST routines are handled
normally (that is, the event flag is set, and the AST is delivered when
the lock is granted).
A request can be expedited (granted immediately) if its requested mode,
when granted, does not block any currently queued requests from being
granted. The LCK$M_EXPEDITE flag is specified in the SYS$ENQ operation
to expedite a request. Currently, only NLMODE requests can be
expedited. A request to expedite any other lock mode fails with
The lock status block receives the final completion status and the lock identification, and optionally contains a lock value block (see Figure 7-4). When a request is queued, the lock identification is stored in the lock status block even if the lock has not been granted. This allows a procedure to dequeue locks that have not been granted. For more information about the Dequeue Lock Request (SYS$DEQ) system service, see Section 7.5.
Figure 7-4 Lock Status Block
The status code is placed in the lock status block either when the lock is granted or when errors occur in granting the lock.
In some applications that use the lock management services, a process must know whether it is preventing another process from locking a resource. The lock management services inform processes of this through the use of blocking ASTs. When the lock prevents another lock from being granted, the blocking routine is delivered as an AST to the process. Blocking ASTs are not delivered when the state of the lock is either Conversion or Waiting.
To enable blocking ASTs, the blkast argument of the
SYS$ENQ system service must contain the address of a blocking AST
service routine. The astprm argument passes a
parameter to the blocking AST. For more information about ASTs and AST
service routines, see Chapter 8. Some uses of blocking ASTs are
also described in that chapter.
A procedure normally needs an exclusive (or protected write) mode lock while writing data. The procedure should not keep the resource exclusively locked all the time, however, because writing might not always be necessary. Maintaining an exclusive or protected write mode lock prevents other processes from accessing the resource. Lock conversions allow a process to request a low-level lock at first and convert the lock to a high-level lock mode (protected write mode, for example) only when it needs to write data.
Some applications of locks require the use of the lock value block. If a version number or other data is maintained in the lock value block, you need to maintain at least one lock on the resource so that the value block is not lost. In this case, processes convert their locks to null locks, rather than dequeuing them when they have finished accessing the resource.
To improve performance in some applications, all resources that might be locked are locked with null locks during initialization. You can convert the null locks to higher-level locks as needed. Usually a conversion request is faster than a new lock request because the necessary data structures have already been built. However, maintaining any lock for the life of a procedure uses system dynamic memory. Therefore, the approach of creating all necessary locks as null locks and converting them as needed improves performance at the expense of increased storage requirements.
To perform a lock conversion, a procedure calls the SYS$ENQ system service with the flag bit LCK$M_CONVERT. Lock conversions do not use the resnam, parid, acmode, or prot argument. The lock being converted is identified by the lock identification contained in the lock status block. The following program shows a simple lock conversion. Note that the lock must be granted before it can be converted.
7.4.7 Forced Queuing of Conversions
It is possible to force certain conversions to be queued that would otherwise be granted. A conversion request with the LCK$M_QUECVT flag set is forced to wait behind any already queued conversions.
The conversion request is granted immediately if no conversions are already queued.
The QUECVT behavior is valid only for a subset of all possible conversions. Table 7-4 defines the legal set of conversion requests for LCK$M_QUECVT. Illegal conversion requests fail with SS$_BADPARAM returned.
Key to Lock Modes:
NL = Null
7.4.8 Parent Locks
When a lock request is queued, you can declare a parent lock for the new lock. A lock that has a parent is called a sublock. To specify a parent lock, the lock identification of the parent lock is passed in the parid argument to the SYS$ENQ system service. A parent lock must be granted before the sublocks belonging to the parent can be granted.
The benefits of specifying parent locks are as follows:
The following paragraphs describe the use of parent locks.
Assume that a number of processes need to access a database. The database can be locked at two levels: the file and individual records. For updating all the records in a file, locking the whole file and updating the records without additional locking is faster and more efficient. But for updating selected records, locking each record as it is needed is preferable.
To use parent locks in this way, all processes request locks on the file. Processes that need to update all records must request protected write or exclusive mode locks on the file. Processes that need to update individual records request concurrent write mode locks on the file and then use sublocks to lock the individual records in protected write or exclusive mode.
In this way, the processes that need to access all records can do so by locking the file, while processes that share the file can lock individual records. A number of processes can share the file-level lock at concurrent write mode while their sublocks update selected records.
On VAX systems, the number of levels of sublocks is limited by the size of the interrupt stack. If the limit is exceeded, the error status SS$_EXDEPTH is returned. The size of the interrupt stack is controlled by the SYSGEN parameter INTSTKPAGES. The default value for INTSTKPAGES allows 32 levels of sublocks. For more information about SYSGEN and INTSTKPAGES, see the HP OpenVMS System Manager's Manual.
On Alpha systems, the number of levels of sublocks is fixed at 127. If
that limit is exceeded, the error status SS$_EXDEPTH is returned.
The lock value block is an optional, 16- or 64-byte extension of a lock status block. The first time a process associates a lock value block with a particular resource, the lock management services create a resource lock value block for that resource. The lock management services maintain the resource lock value block until there are no more locks on the resource.
To associate a lock value block with a resource, the process must set the flag bit LCK$M_VALBLK in calls to the SYS$ENQ system service. The lock status block lksb argument must contain the address of the lock status block for the resource. The LCK$M_XVALBLK flag, which a process can use only in conjunction with the LCK$M_VALBLK flag, specifies that a 64-byte lock value block is to be used. Without this flag (which is not valid on VAX systems), only the first 16 bytes of the value block are read or written.
When a process sets the flag bit LCK$M_VALBLK in a lock request (or conversion request) and the request (or conversion) is granted, the contents of the resource lock value block are written to the lock value block of the process.
When a process sets the flag bit LCK$M_VALBLK on a conversion from protected write or exclusive mode to an equal or lower mode, the contents of the process's lock value block are stored in the resource lock value block.
In this manner, processes can pass the value in the lock value block along with the ownership of a resource.
Table 7-5 shows how lock conversions affect the contents of the process's and the resource's lock value block.
Key to Lock Modes:
Key to Effects:
Return---The contents of the resource lock value block are returned to the lock value block of the process.
Note that when protected write or exclusive mode locks are dequeued using the Dequeue Lock Request (SYS$DEQ) system service and the address of a lock value block is specified in the valblk argument, the contents of that lock value block are written to the resource lock value block.