[OpenVMS documentation]
[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
Updated: 11 December 1998

OpenVMS Programming Concepts Manual


Previous Contents Index

17.2.9.4 LOCKIDTBL System Parameter

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. On OpenVMS Alpha, the lock ID table is allowed to expand up to the LOCKIDTBL_MAX system parameter limit. When the table is filled with current locks, the lock request is rejected with an error of SS$_NOLOCKID. This usually results in a system failure (LCKMGRERR bugcheck) as soon as a privileged system application receives such an error.

On OpenVMS VAX, however, this behavior was modified to allow for continued expansion of the lock ID table and was not constrained by LOCKIDTBL_MAX, as on OpenVMS Alpha.

With OpenVMS Version 7.1, both Alpha and VAX platforms dynamically increase 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 now allow large single tables for lock IDs. The maximum number of locks is now regulated by the amount of available nonpaged pool instead of by both nonpaged pool and the LOCKIDTBL_MAX system parameter.

The LOCKIDTBL_MAX parameter is now obsolete. In its place, an appropriate maximum value based on the total available memory is calculated at boot time and stored as the value for the parameter. Inputs (via MODPARAMS or SYSGEN) are ignored.

In addition, the lock ID table itself is now located in S2 space for OpenVMS Alpha, to avoid using large amounts of S0 space in large memory systems.

There are no visible changes for these modifications except the avoidance of system failures previously caused by the inability to expand the lock ID table due to an artificial limit.

17.3 Queuing Lock Requests

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]
,[astprm] ,[blkast] ,[acmode] ,[rsdm_id] ,[nullarg])

The following example illustrates a call to SYS$ENQW:


 
#include <stdio.h> 
#include <descrip.h> 
#include <lckdef.h> 
 
/* Declare a lock status block */ 
 
struct lock_blk { 
                  unsigned short  condition,reserved; 
                  unsigned int lock_id; 
}lksb; 
 
   .
   .
   .
        unsigned int status, lkmode=LCK$K_PRMODE; 
        $DESCRIPTOR(resource,"STRUCTURE_1"); 
 
/* Queue a request for protected read mode lock */ 
        status = SYS$ENQW(0,     /* efn - event flag */ 
                 lkmode,         /* lkmode - lock mode requested */ 
                 &lksb,          /* lksb - lock status block */ 
                 0,              /* flags */ 
                 &resource,      /* resnam - name of resource */ 
                 0,              /* parid - parent lock id */ 
                 0,              /* astadr - AST routine */ 
                 0,              /* astprm - AST parameter */ 
                 0,              /* blkast - blocking AST */ 
                 0,              /* acmode - access mode */ 
                 0);             /* rsdm_id - resource domain id */ 
 
} 
 
 
 

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.

Table 17-3 shows the compatibility of lock modes.

17.3.1 Example of Requesting a Null Lock

The program segment in Example 17-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.)

Example 17-1 Requesting a Null Lock

! Define lock modes 
INCLUDE '($LCKDEF)' 
! Define lock status block 
STRUCTURE /STATUS_BLOCK/ 
 INTEGER*2 LOCK_STATUS, 
2          NULL 
 INTEGER*4 LOCK_ID 
END STRUCTURE 
RECORD /STATUS_BLOCK/ IOSTATUS 
   .
   .
   .
! Request a null lock 
STATUS = SYS$ENQW (, 
2                  %VAL(LCK$K_NLMODE), 
2                  IOSTATUS, 
2                  , 
2                  'TERMINAL', 
2                  ,,,,,) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) 
IF (.NOT. IOSTATUS.LOCK_STATUS) 
2    CALL LIB$SIGNAL (%VAL(IOSTATUS.LOCK_STATUS)) 
! Convert the lock to an exclusive lock 
STATUS = SYS$ENQW (, 
2                  %VAL(LCK$K_EXMODE), 
2                  IOSTATUS, 
2                  %VAL(LCK$M_CONVERT), 
2                  'TERMINAL', 
2                  ,,,,,) 
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) 
IF (.NOT. IOSTATUS.LOCK_STATUS) 
2    CALL LIB$SIGNAL (%VAL(IOSTATUS.LOCK_STATUS)) 

For more complete information on the use of SYS$ENQ, refer to the OpenVMS System Services Reference Manual.

17.4 Advanced Locking Techniques

The previous sections discuss locking techniques and concepts that are useful to all applications. The following sections discuss specialized features of the lock manager.

17.4.1 Synchronizing Locks

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

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.

17.4.2 Notification of Synchronous Completion

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

17.4.3 Expediting Lock Requests

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 SS$_UNSUPPORTED status.

17.4.4 Lock Status Block

The lock status block receives the final completion status and the lock identification, and optionally contains a lock value block (see Figure 17-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 17.5.

Figure 17-4 Lock Status Block


The status code is placed in the lock status block only when the lock is granted or when errors occur in granting the lock.

The uses of the lock value block are described in Section 17.6.1.

17.4.5 Blocking ASTs

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 is used to pass a parameter to the blocking AST. For more information about ASTs and AST service routines, see Chapter 5. Some uses of blocking ASTs are also described in that chapter.

17.4.6 Lock Conversions

Lock conversions perform three main functions:

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.

In order 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.

Note

If you specify the flag bit LCK$M_NOQUEUE on a lock conversion and the conversion fails, the new blocking AST address and parameter specified in the conversion request replace the blocking AST address and parameter specified in the previous SYS$ENQ request.

Queuing Lock Conversions

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.


 
#include <stdio.h> 
#include <descrip.h> 
#include <lckdef.h> 
 
/* Declare a lock status block */ 
 
struct lock_blk { 
                unsigned short lkstat, reserved; 
                unsigned int lock_id; 
}lksb; 
 
   .
   .
   .
        unsigned int status, lkmode, flags; 
        $DESCRIPTOR(resource,"STRUCTURE_1"); 
   .
   .
   .
        lkmode = LCK$K_NLMODE; 
 
/* Queue a request for protected read mode lock */ 
        status = SYS$ENQW(0,    /* efn - event flag */ 
                  lkmode,       /* lkmode - lock mode */ 
                  &lksb,        /* lksb - lock status block */ 
                  0,            /* flags */ 
                   &resource,   /* resnam - name of resource */ 
                  0, 0, 0, 0, 0, 0); 
   .
   .
   .
        lkmode = LCK$K_PWMODE; 
        flags = LCK$M_CONVERT; 
 
/* Queue a request for protected write mode lock */ 
        status = SYS$ENQW(0,     /* efn - event flag */ 
                  lkmode,        /* lkmode - lock mode */ 
                  &lksb,         /* lksb - lock status block */ 
                  flags,         /* flags */ 
                  0, 0, 0, 0, 0, 0, 0); 
   .
   .
   .
} 

17.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 17-4 defines the legal set of conversion requests for LCK$M_QUECVT. Illegal conversion requests fail with SS$_BADPARAM returned.

Table 17-4 Legal QUECVT Conversions
  Lock Mode to Which Lock Is Converted
Lock Mode
at Which
Lock Is Held
NL CR CW PR PW EX
NL No Yes Yes Yes Yes Yes
CR No No Yes Yes Yes Yes
CW No No No Yes Yes Yes
PR No No Yes No Yes Yes
PW No No No No No Yes
EX No No No No No No


Key to Lock Modes:

17.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 OpenVMS System Manager's Manual.

On Alpha systems, the number of levels of sublocks is limited by the size of the kernel stack. If the limit is exceeded, the error status SS$_EXDEPTH is returned. The size of the kernel stack is controlled by the SYSGEN parameter KSTACKPAGES.

17.4.9 Lock Value Blocks

The lock value block is an optional, 16-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.

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 a 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 17-5 shows how lock conversions affect the contents of the process's and the resource's lock value block.

Table 17-5 Effect of Lock Conversion on Lock Value Block
  Lock Mode to Which Lock Is Converted
Lock Mode
at Which
Lock Is Held
NL CR CW PR PW EX
NL Return Return Return Return Return Return
CR Neither Return Return Return Return Return
CW Neither Neither Return Return Return Return
PR Neither Neither Neither Return Return Return
PW Write Write Write Write Write Return
EX Write Write Write Write Write Write


Key to Lock Modes:

Key to Effects:


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.


Previous Next Contents Index

[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
[OpenVMS documentation]

Copyright © Compaq Computer Corporation 1998. All rights reserved.

Legal
5841PRO_051.HTML