General
Application area: | Distributed Lock Manager (DLM); see "Distributed Lock Manager (DLM)" |
Macro type: | Type S, MF format 3: C/D/L/M/E form; see "S-type macros" |
Macro description
The LKENQ macro generates a lock. The lock is not generated again if it already exists, but the calling task is allocated to it. The lock request is enqueued in the specified lock mode.
A lock is identified by a lock name and a scope. The lock name is supplied to the DLM by the user.
A lock ID (LOCKID) is returned to the calling task; this must be specified to facilitate processing in subsequent calls (LKCVT, LKCAN, LKDEQ). The lock ID is a task-specific control for the lock.
If the lock has already been enqueued for this task, the lock ID of the previous LKENQ request is returned but the macro is not executed. The lock mode has not been changed!
Macro formats and description of operands
LKENQ |
MF=C / D / L / M / E ,ASYNCTL=*SYNCH / *ASYNCH / <var: enum-of _asyncctl_s:1> ,GRANTID=0 / <var: int:4> ,GRTEVTT=*SYNCH / *TUCONTI / *TUEVENT / <var: enum-of _evttype_s:1> ,HOLDTIM=*INFINITE / *SYSTEM / <var: int:2> / <integer 0..32767> ,LCKMODE=*NU / *CR / *CW / *PR / *PW / *EX / <var: enum-of _lckmode_s:1> ,LSBADR=<var: pointer> ,LVBCTL=*IGNORE / *MOVE / <var: enum-of _lvbctl_s:1> ,MULTENQ=*NO / *YES / <var: enum-of _multiple_s:1> ,NAMEADR=<var: pointer> ,NAMELEN=0 / <integer 8..48> / <var: int:2> ,NAMRNGE=*OWNSYSTEM / *CLUSTER / <var: enum-of _namerange_s:1> ,SCOPE=*NAMESPACEID / *USERID / *GROUPID / <var: emun-of_scope_s:1> ,RELEVTT=*NO / *TUCONTI / *TUEVENT / <var: enum-of _evttype_s:1> ,RELID=0 / <var: int:4> ,TERMNTE=*STD / *FIRST / *SECOND / *THIRD / <var: enum-of _terminate_s:1> ,USERPAR=0 / <var: int:4> ,WAITTIM=*STD / *INFINITE / <var: int:2> / <integer 0..32767> ,WAITTYP=*TIME / *IMMEDIATE / <var: enum-of _timetype_s:1> ,PARAM=<var: pointer> / (reg: pointer>) ,PREFIX=N / p ,MACID=LDE / mac |
The operands are described in alphabetical order below.
ASYNCTL=
Allocation control for an asynchronous lock request. If the lock request can be allocated immediately a contingency process or an event signal can be suppressed.
*SYNCH
If the lock request can be allocated immediately an allocation contingency or an event signal is suppressed.
*ASYNCH
An allocation contingency or an event signal is still generated by the DLM even if the lock request can be allocated immediately.
<var: enum-of _asyncctl_s:1>
Name of the field with the allocation control of the asynchronous lock request at the time of execution.
GRANTID=
ID for the lock allocation. Specifies, for asynchronous requests, which contingency ID or event ID is to be assigned to the information that the lock has now been allocated.
<var: int:4>
Default setting is 0.
The contingency ID or event ID.
GRTEVTT=
Describes the way in which information about the lock allocation is to be returned. There are three methods of control: one synchronous and two asynchronous. The specified ID (contingency ID or event ID) is valid for the current lock request. Other lock requests from other tasks may specify different IDs.
*SYNCH
Synchronous lock request. Return from the macro if the lock has been allocated or an error condition detected. The information is delivered in the return code.
*TUCONTI
Contingency process. This value must be specified to obtain confirmation of the allocation request during contingency processing. The user is notified of incompatible lock requests which have been enqueued by other users. The release contingency is started if the lock is in an incompatible lock mode.
*TUEVENT
Eventing. An event variable can be used to obtain allocation information. The allocation information is supplied by calling the SOLSIG macro. Incompatible allocation requests from other tasks are notified via the same event variable.
<var:enum-of _evttype_s:1>
Name of the field with the allocation event type at the time of execution
HOLDTIM=
The hold time is the time that the lock holder wants to hold the lock. When the hold time has expired, a release event is generated by the DLM so that the lock holder can weaken or release its lock request.
This can only be specified together with the RELEVTT operand.
*INFINITE
No hold time limit.
*SYSTEM
Hold time defined by the operating system.
<var: int:2>
Hold time defined by the user in seconds.
<integer 0..32767>
Direct specification of hold time in seconds.
LCKMODE=
Specifies the lock mode of the requested lock.
*NU
The lock is in Null Mode and is always allocated. It is compatible with all other lock requests. However, access to the resource is not allowed.
*CR
The lock is in Concurrent-Read Mode. Other locks are permitted only in Null Mode, Concurrent-Read Mode, Concurrent-Write Mode, Protected-Read Mode, and in Protected-Write Mode. The lock holder is granted unprotected read access to the resource.
*CW
The lock is in Concurrent-Write Mode. Other locks are permitted only in Null Mode, Concurrent-Write Mode, or in Concurrent-Read Mode. The lock holder is granted unprotected write access to the resource.
*PR
The lock is in Protected-Read Mode. Other locks are permitted only in Null Mode, Concurrent-Read Mode, or in Protected-Read Mode. The lock holder is granted protected read access to the resource.
*PW
The lock is in Protected-Write Mode. Other locks are permitted only in Null Mode and in Concurrent-Read Mode. The lock holder is granted protected write access to the resource.
*EX
The lock is in Exclusive Mode. Other locks are permitted only in Null Mode. Only the lock holder may access the resource.
<var: enum-of _lckmode_s:1>
Name of the field with the lock mode.
LSBADR=
Field with the address of the Lock Status Block. The Lock Value Block is part of the Lock Status Block.
<var: pointer>
Name of the field with the address of the Lock Status Block.
LVBCTL=
Specifies the handling of the Lock Value Block.
*IGNORE
The Lock Value Block is not used.
*MOVE
Read or write the Lock Value Block. The Lock Value Block can be read if the lock is allocated. It can be written if the lock is released.
<var: enum-of _lvbctl_s:1>
Name of the field with the handling of the Lock Value Block at the time of execution.
MF=
For a general description of the MF operand, its operand values and any subsequent operands (e.g. PREFIX, MACID, and PARAM), see "S-type macros". The valid MF values are given at the start of the macro description under “Macro type” and are included in the macro format.
A PREFIX can be specified in the C form, D form or M form of the macro and additionally a MACID in the C form or M form.
MULTENQ=
Multiple LKENQ requests are allowed.
Specifies whether the user is allowed to enqueue more than one lock request for the same lock name (= lock). Each of these lock requests is assigned its own lock ID (LOCKID) and each one must be dequeued individually.
*NO
If a lock request from this task already exists for the specified lock, this (the current) lock request is rejected.
*YES
This (the current) lock request is enqueued irrespective of existing lock requests from this task for this lock. This lock request is assigned its own unique lock ID.
<var: enum-of _multiple_s:1>
Name of the field with the value of MULTENQ at the time of execution.
NAMEADR=
Field with the address of the lock name.
<var: pointer>
Name of the field with the address of the lock name.
NAMELEN=
Default setting is 0.
Specifies the length of the lock name.
<integer 8..48>
Direct specification of the length of the lock name at the time of transfer.
<var: int:2>
Name of the field with the length of the lock name at the time of execution.
NAMRNGE=
Specifies the range within which the lock name is valid. If a LKENQ request is executed on a single system (which is not and never will be part of a cluster), the lock is handled as if it were the single-system part of a cluster. This feature allows programs to be ported from single non-clustered systems to cluster systems.
*OWNSYSTEM
The specified lock name is valid on the local system only.
*CLUSTER
The specified lock name is valid for the whole cluster.
<var: enum-of _namerange_s:1>
Name of the field with the range in which the lock name is valid, at the time of execution.
RELEVTT=
Describes the way in which information about the lock release is to be returned. There are three methods of control: one synchronous and two asynchronous. The specified ID (contingency ID or event ID) is valid for the current lock request. Other lock requests from other tasks may specify different IDs.
*NO
No information about other incompatible lock requests concerning this lock is output. This can lead to deadlock problems if the lock is not released. If the hold time specified for this lock has expired, the lock holder for this lock request is terminated without further notification.
*TUCONTI
Contingency process. This value must be specified in order to obtain the release event during contingency processing. Users are informed of incompatible lock requests which are entered in the queue by other users. The release contingency is started if the lock is in an incompatible mode.
*TUEVENT
Eventing. An event variable can be used to obtain the release event. The information is supplied when the SOLSIG macro is called. The incompatible lock requests from other tasks are reported via the same event variable.
<var:enum-of _evttype_s:1>
Name of the field with the release event type at the time of execution.
RELID=
ID for the lock release. Specifies which contingency ID or event ID is to be assigned to the information that the lock request is blocking another lock request from a different user.
<var: int:4>
Default setting is 0.
The contingency ID or event ID.
SCOPE=
Defines the local scope of the lock name.
*NAMESPACEID
Preset value: the specified lock name is used as the internal lock name. The first part (8 bytes) of the specified lock name implicitly forms the local scope. The local scope must be a character string. The valid characters are the letters “A..Z”, “a..z”; the digits “0..9” and the special characters “@” and “#”. The maximum length of the specified lock name is 48 characters.
*USERID
The user ID to which the calling task belongs is used to form the internal lock name. The DLM determines the user ID and places it at the start of the lock name. The first part of the specified lock name is not interpreted as the local scope. The maximum length of the specified lock name is reduced to 40 characters.
If the operand SCOPE=*USERID is specified, an application's locks can be easily protected against access by another application. The applications simply have to be started under different user IDs.
*GROUPID
The user group to which the calling task belongs is used to form the internal lock name. The DLM determines the user group and places it at the start of the lock name. The first part of the specified lock name is not interpreted as the local scope. The maximum length of the specified lock name is reduced to 40 characters.
The operand SCOPE=*GROUPID may only be specified if the software product
SECOS is operational as otherwise the LKENQ call results in an error.
<var: enum-of _scope_s:1>
Name of the field with the local scope of the lock name at runtime.
TERMNTE=
Specifies the sequence in which this lock is released during abnormal termination of the lock-holder process (task or program). The termination sequence is divided into three classes. The locks of the process that is being terminated are released in the sequence specified, or they are all released simultaneously (as seen from the other processes).
*STD
This lock is released in the termination sequence specified by the DLM.
*FIRST
This lock is released before or at the same time as the locks in the next class.
*SECOND
This lock is released after or at the same time as the locks in the previous class, and before or at the same time as the locks in the next class.
*THIRD
This lock is released after or at the same time as the locks in the previous class.
<var: enum-of _terminate_s:1>
Name of the field with the termination class at the time of execution.
USERPAR=
Contains the parameter for asynchronous messages. These are transferred to the contingency process or to eventing.
<var: int:4>
User-defined values. Default setting is 0.
WAITTIM=
The wait time is the length of time that must be waited until the lock is allocated.
*STD
Standard wait time. If WAITTYP=*TIME is specified, *INFINITA is assumed. If WAITTYP=*IMMEDIATE is specified the lock is allocated immediately or the job is terminated. If job processing is delayed (cluster, network) the wait time is 600 seconds.
*INFINITE
Infinite wait time. The request never times out. The lock request waits until the lock is allocated or a deadlock situation is detected.
<var: int:2>
Wait time defined by the user in seconds.
<integer 0..32767>
Direct specification of wait time in seconds.
WAITTYP
Specifies the wait time type for waiting lock requests.
*TIME
The timeout value is specified via the WAITTIM operand.
*IMMEDIATE
Immediate lock request. The lock request is not enqueued if it cannot be allocated immediately. The value for the timeout can be specified via the WAITTIM operand. This value is used if the handling of the lock request leads to a DLM-internal wait status. This may occur, for example, if a network connection is no longer available after the lock request has been sent to a different node for processing, with the result that the necessary response is never transferred from that other node. To prevent this, the user can specify a wait time via the WAITTIM operand.
<var: enum-of _timetype_s:1>
User-defined values.
Return information and error flags
Standard header:
+---------------+ | | | | | |c|c|b|b|a|a|a|a| +---------------+
The following return code relating to the execution of the
LKENQ macro is transferred in the standard header
(cc=Subcode2, bb=Subcode1, aaaa=Maincode):
X'cc' | X'bb' | X'aaaa' | Meaning |
X'00' | X'00' | X'0000' | The macro was executed normally. The lock was allocated or the lock |
X'00' | X'00' | X'0001' | The macro was executed normally. The lock request has been |
X'00' | X'00' | X'0002' | The macro was executed but the lock status is invalid. This information |
X'00' | X'01' | X'1001' | The lock name is too long. |
X'00' | X'01' | X'1002' | The address of the lock name is not available. |
X'00' | X'01' | X'1003' | The lock name is not allowed. |
X'00' | X'01' | X'1004' | The specified name space is invalid. |
X'00' | X'01' | X'1005' | The Lock Status Block is not available. |
X'00' | X'01' | X'1006' | The GRANTID operand type is not the same as that specified in the |
X'00' | X'01' | X'1007' | The RELID operand type is not the same as that specified in the |
X'00' | X'01' | X'1008' | Invalid combination of GRTEVTT and RELEVTT operands. |
X'00' | X'01' | X'1009' | Invalid specification in the WAITTIM operand. |
X'00' | X'01' | X'100A' | Invalid specification in the HOLDTIM operand. |
X'00' | X'01' | X'100B' | Invalid specification in the LCKTYPE operand. |
X'00' | X'01' | X'1010' | The lock has already been enqueued for this task. |
X'00' | X'01' | X'1015' | Invalid specification in the LCKMODE operand. |
X'00' | X'01' | X'10FF' | An incorrect parameter, which has no specific return code, was |
X'00' | X'20' | X'2001' | An internal error occurred. |
X'00' | X'20' | X'2003' | Internal error in connection with the resource block. |
X'00' | X'20' | X'2004' | Internal error in connection with a timeout. |
X'00' | X'20' | X'2005' | Internal error in connection with the lock request. |
X'00' | X'20' | X'2006' | Internal error in connection with XCS. |
X'00' | X'40' | X'4003' | The previous lock request has not yet been terminated. |
X'00' | X'82' | X'8001' | No further locks can be created. |
X'00' | X'82' | X'8002' | Timeout. |
X'00' | X'82' | X'8003' | It is not possible at present to specify locks with |
X'00' | X'82' | X'8005' | The lock request has already been canceled. |
X'00' | X'82' | X'8006' | Immediate lock requests are not possible due to the existence of |
Other return codes which, in accordance with conventions, apply to all macros are given in the table “Standard return codes” (Standard header).