Technical Capabilities
Having trouble finding what you need?
Get in touch with us, so we can answer your specific questions directly.
Get In Touch

VX/LCKMGR: OpenVMS Lock Manager

Overview

VX/LCKMGR is Sector7's reimplementation of the OpenVMS lock manager for Linux: the SYS$ENQ, SYS$DEQ, and SYS$GETLKI system-service family together with the arbitration daemon behind them. Migrated OpenVMS applications keep their locking logic unchanged. They call the same SYS$ services, and a local lock-manager daemon arbitrates every request and delivers grants and blocking notifications through ASTs, exactly as the VMS lock manager does.

It ships as a single-node lock manager. One server process owns the resource and lock databases, and client processes reach it over a System V IPC message queue. All six OpenVMS lock modes, the full grant and conversion queues, 16-byte and 64-byte lock value blocks, resource domains, and an audit log with replay are supported. Cluster-wide lock mastering is out of scope for the current build.

Architecture and components

VX/LCKMGR is a client/server pair, not a library the application links its locking logic into. The application calls the SYS$ wrappers on the client side; those marshal a request packet onto the daemon's well-known IPC queue; the daemon owns the resource and lock databases, arbitrates the request, and calls back asynchronously through ASTs delivered as reply messages. The table maps each OpenVMS lock-manager concept to its VX/LCKMGR counterpart.

OpenVMS conceptVX/LCKMGR componentRoleStatus
Lock manager (LOCKMGR)lckmgr daemonThe arbitration daemon: owns the resource and lock databases and fires grant and blocking ASTs.live
SYS$ENQ / SYS$DEQ / SYS$GETLKIClient library wrappersMarshal request packets and run a per-process AST-dispatch thread that invokes the caller's completion and blocking ASTs.live
SDA SHOW LOCK, operator controllckctlStart, stop, statistics, status, and queue maintenance for the daemon.live
(no VMS analog)AuditHistoryGenerates a post-run report over a recorded audit log.live
One local daemon, no cluster transport. The resource master is always the local host and there is no cluster interconnect wired into the shipping build. Clients and the daemon communicate over a System V IPC message queue on the same node.

In-memory data model

The daemon keeps one Lock Block (LKB) per outstanding request and one Resource Block (RSB) per named resource. Each RSB holds the three queues that drive arbitration: the grant queue, the conversion queue, and the wait queue. A Lock Holder record tracks each client session, and a sparse lock table indexed by a 24-bit slot plus an 8-bit generation counter turns a lock id back into its LKB. Named resources live in a ResourceDomain hierarchy so unrelated applications can share the daemon without colliding.

Request lifecycle

Every lock operation follows the same round trip between the client wrappers and the daemon:

Application processSYS$ENQ, SYS$DEQ, and SYS$GETLKI wrappersThe client marshals requests and its AST-dispatch thread receives asynchronous replies.
lckmgr daemonResource and lock databasesThe daemon arbitrates the grant, conversion, and wait queues.
Client to daemonRequest packet travels over the System V IPC message queue.
Daemon to clientGrant or blocking AST returns as a reply message to the AST-dispatch thread.

A synchronous grant can be collapsed into the acknowledgement packet, so a lock that is immediately grantable returns without a separate AST round trip. A queued lock is granted later, when the resource frees up, by a reply message that the client's AST-dispatch thread turns into the caller's completion AST.

Lock modes and compatibility

VX/LCKMGR implements all six OpenVMS lock modes with the same symbol values and the same grant rules as the VMS lock manager. Modes range from the null placeholder used during conversions up to the exclusive lock that excludes every other holder.

SymbolValueAbbr.Meaning
LCK$K_NLMODE0NLNull: grants no access. Used as an interest marker or a placeholder for a lock conversion.
LCK$K_CRMODE1CRConcurrent read: shared read, other readers and writers allowed.
LCK$K_CWMODE2CWConcurrent write: shared, unprotected write.
LCK$K_PRMODE3PRProtected read: the traditional share lock, no writers.
LCK$K_PWMODE4PWProtected write: the traditional update lock, shares with CR.
LCK$K_EXMODE5EXExclusive: excludes every mode except NL.

Compatibility matrix

A new request is granted immediately only if its mode is compatible with every lock already granted on the resource (and no conversion or wait is queued ahead of it). Rows are the mode of a currently granted lock; columns are the mode of the new request.

Granted \ RequestedNLCRCWPRPWEX
NLYesYesYesYesYesYes
CRYesYesYesYesYesNo
CWYesYesYesNoNoNo
PRYesYesNoYesNoNo
PWYesYesNoNoNoNo
EXYesNoNoNoNoNo
Reading the grid. NL is compatible with everything, which is why it is safe as a conversion placeholder. EX is compatible only with NL. CR is the most permissive real access mode: it coexists with every mode except EX.

Grant and conversion rules

A request on a new resource is granted at once. On an existing resource it is granted only when the conversion and wait queues are empty and the mode is compatible with all granted locks; an NL request with the expedite option can jump the wait queue. Otherwise the request either returns SS$_NOTQUEUED when the no-queue option is set, or is appended to the wait queue. Conversions to a less restrictive mode are granted synchronously; conversions to a more restrictive mode are granted synchronously when compatible, and otherwise join the conversion queue while the lock stays granted at its current mode. When a lock is released or converted down, the conversion queue is re-evaluated up to the first incompatible entry, and the wait queue is evaluated once the conversion queue empties.

Request flags

Lock requests carry the same option flags as OpenVMS. The header defines them in the mask form (LCK$M_*); older application code often spells the same options in the bit-position form (LCK$V_*). Both refer to the identical OpenVMS options. Several bit positions are deliberately overloaded by call context, exactly as on VMS: the value is the same, but its meaning differs between an enqueue (SYS$ENQ) and a dequeue (SYS$DEQ).

Flag (mask form)HexMeaning
LCK$M_VALBLK0x00000001Read or write the lock value block at grant time.
LCK$M_DEQALL0x00000001On dequeue: release all locks held by the caller.
LCK$M_CONVERT0x00000002The request converts the mode of an existing lock id.
LCK$M_CANCEL0x00000002On dequeue: cancel a pending conversion.
LCK$M_NOQUEUE0x00000004Do not queue if not immediately grantable; return SS$_NOTQUEUED.
LCK$M_SYNCSTS0x00000008Return SS$_SYNCH on a synchronous grant and skip the completion AST.
LCK$M_SYSTEM0x00000010System-wide lock (resource group 0).
LCK$M_NOQUOTA0x00000020Bypass quota checks.
LCK$M_EXPEDITE0x00000800An NL-mode request jumps the wait queue.
LCK$M_XVALBLK0x00010000Request the 64-byte extended lock value block.
LCK$M_AUDITED0x00080000Sector7 extension: mark the request for audit tracing.
Overloaded bits. LCK$M_CONVERT, LCK$M_CANCEL, and LCK$M_DEQALL share bit values because VMS assigns them to the same bit in mutually exclusive service contexts. VX/LCKMGR preserves that encoding so existing code that sets these options keeps working unchanged.

Client API: the SYS$ routines

Applications call the same system services as on OpenVMS. Each routine has an asynchronous form and a synchronous form that blocks until the request completes. The synchronous forms are the ones that end in W.

RoutinePurposeStatus
SYS$ENQAsynchronous enqueue or convert; returns a request acknowledgement, with the grant delivered by AST.live
SYS$ENQWSynchronous enqueue: blocks until the lock is granted or SS$_SYNCH is returned.live
SYS$DEQAsynchronous dequeue by lock id, with optional value block and flags.live
SYS$DEQWSynchronous dequeue.live
SYS$GETLKIQuery lock information by lock id or wildcard, through an item list.live
SYS$GETLKIWSynchronous GETLKI.live
SYS$SET_RESOURCE_DOMAINJoin or leave a resource domain.live
SYS$RUNDOWNRelease the locks held by an image at exit.live

Example: enqueue, convert up, release

This is the common lock lifecycle for a shared resource. The example takes a system-wide lock on a banking account resource at NL mode, converts it up to EX to make an exclusive change, then releases it and writes the lock value block back. It checks both the routine return code and the lock status block after each step.

/* new NL-mode lock on a system-wide resource (async request, then wait) */
rc = sys$enq(efn, LCK$K_NLMODE, &lksb, LCK$M_SYSTEM,
             &resnam, 0, ast_granted, ctx, ast_blocked, PSL$C_USER, 0);
rc = sys$waitfr(efn);
if (!(rc & 1))            { request_error++; }
if (!(lksb.status & 1))   { grant_error++; }        /* not granted */

/* convert the same lock up to EX; LCK$M_CONVERT names the held lock id */
rc = sys$enqw(efn, LCK$K_EXMODE, &lksb,
              LCK$M_SYSTEM | LCK$M_VALBLK | LCK$M_CONVERT,
              0, 0, 0, 0, 0, PSL$C_USER, 0);

/* release; the value block is written back from lksb.valblk */
rc = sys$deq(lksb.lkid, &lksb.valblk, PSL$C_USER, 0);

The completion AST and the blocking AST are ordinary functions passed by address. The client-side AST-dispatch thread invokes them when the daemon publishes the matching reply on the process's AST channel, so the asynchronous behaviour of the VMS lock manager is preserved without the application changing how it waits.

Lock information and status codes

SYS$GETLKI returns detailed information about a lock through an item list: the caller supplies item codes and receives the matching values. It is important to keep three things separate, because migrated code sometimes conflates them: the lock-state constants, the GETLKI item codes, and the completion status codes a request returns.

Lock-state constants

These describe where a lock currently sits, and are returned for the state item code.

ConstantValueMeaning
LKI$C_WAITING-1Lock is on the wait queue.
LKI$C_CONVERT0Lock is on the conversion queue.
LKI$C_GRANTED1Lock is granted.

GETLKI item codes

The item codes select which field to return. Per-lock identity and state codes fall in the 256 to 264 range; namespace, resource, value block, and counter fields fall in the 512 to 524 range.

Item codeValueItem codeValue
LKI$_PID256LKI$_LKID263
LKI$_STATE257LKI$_CSID264
LKI$_PARENT258LKI$_NAMSPACE512
LKI$_LCKREFCNT259LKI$_RESNAM513
LKI$_LOCKID260LKI$_VALBLK515
LKI$_REMLKID261LKI$_LCKCOUNT517
LKI$_MSTLKID262LKI$_BLOCKEDBY518
LKI$_BLOCKING519LKI$_WAITCOUNT522
LKI$_LOCKS520LKI$_GRANTCOUNT523
LKI$_CVTCOUNT521LKI$_MSTCSID524
Single-node degeneracy. Because there is no cluster mastering, the cluster-relative fields collapse: the master lock id equals the local lock id (LKI$_MSTLKID equals LKI$_LKID) and the cluster system ids are always zero (LKI$_CSID equals LKI$_MSTCSID equals 0). The node is always the local host.

Return and completion status codes

These are the status values a lock request returns, in the routine return code or in the lock status block. They are distinct from the GETLKI item codes above.

StatusMeaning
SS$_NORMALRequest completed normally.
SS$_SYNCHSynchronous grant; no completion AST will be delivered.
SS$_NOTQUEUEDNo-queue request could not be granted immediately.
SS$_CANCELA pending conversion was cancelled.
SS$_ABORTThe request was aborted.
SS$_VALNOTVALIDThe lock value block is marked invalid.
SS$_IVLOCKIDInvalid lock id supplied.
SS$_NOLOCKIDNo lock id available.
SS$_PARNOTGRANTParent lock is not granted.
VX/LCKMGR lock-status and return-code reference chart for SYS$ENQ, SYS$DEQ and SYS$GETLKI on Linux

Single-node transport

The shipping client and server communicate over a System V IPC message queue on the same host. The daemon derives a well-known queue key from its configured system value, attaches to the queue, and both sides exchange packets with the standard msgget, msgsnd, and msgrcv calls. Per-process statistics are read the same single-host way, out of a shared status file in the daemon's temporary directory.

Client AApplication processPublishes lock requests and receives AST replies.
Client BApplication processUses the same host-local transport.
Client CApplication processConverges on the shared queue and daemon.
All clients converge through one host-local IPC queue
System V message queueKey = SYSTEM value + 3Request packets flow to the daemon. Grant and blocking AST replies flow back to the originating process.
One queue converges on one arbitration service
lckmgr daemonResource database, lock database, and AST reply dispatchThe single local daemon coordinates all attached client processes.
Why single-node. The resource master is always the local host and cluster system ids are zero, because the transport is a local message queue rather than a cluster interconnect. This is a deliberate scope boundary: multi-node and cluster-wide lock mastering are out of scope for the current build. Applications that lock only within a single node run unchanged; applications that depend on cluster-wide lock coordination should be reviewed against this boundary during migration planning.

Operator control, statistics, and audit

The lckctl utility starts and stops the daemon and reports on its state. It is the VX/LCKMGR equivalent of using SDA and operator commands to inspect the VMS lock manager.

CommandAction
lckctl startLaunch the lckmgr daemon.
lckctl stopSend a shutdown request to the daemon.
lckctl stats / statusDump the daemon statistics block.
lckctl reset-statsZero and rewrite the statistics block.
lckctl vacuumDrain orphaned packets from the IPC queue: republish those whose target process is still alive, discard the rest.

Statistics

The statistics block reports service timestamps and a running set of counters: packets received, dispatched, and replied; blocking ASTs and grant ASTs fired; enqueue, dequeue, and query counts; how many requests took the grant, conversion, and wait paths; and outcome counters for no-queue rejections and deadlock-search cases. It also reports object counts (lock blocks, resource blocks, resource names, and active sessions) and per-arena memory use, with a memory-to-request ratio for capacity planning.

Audit log and replay

The daemon can record every lock request to an audit log and later replay it. Each record captures the operation, direction, timestamp, and the full request message, in a 32-bit-portable format so a recording made by one build can be read by another. Replay can be driven back through the daemon to reproduce a workload for tuning, or reported offline with the AuditHistory tool, which tallies enqueue, dequeue, and query volumes and prints an operations-per-second summary. Because replay reconstructs the request stream directly, bottlenecks can be isolated without re-running the original application.

Status and divergences from the OpenVMS lock manager

VX/LCKMGR reproduces the lock-manager surface that migrated applications actually call. The matrix below is explicit about what is live, what is stubbed, and what is deliberately out of scope, so migration planning has no surprises.

CapabilityStatus
SYS$ENQ(W) / SYS$DEQ(W) / SYS$GETLKI(W)live
Six lock modes and the full compatibility matrixlive
Grant, conversion, and wait queues; 16-byte and 64-byte value blockslive
Resource domains (SYS$SET_RESOURCE_DOMAIN)live
Audit log record, replay, and reportinglive
lckctl start, stop, stats, status, vacuumlive
Runtime debug-mask add and remove in lckctlstubbed
Deadlock detectionnot implemented
ENQLM and sublock-depth quota enforcementout of scope
Cluster and multi-node lock masteringout of scope
No deadlock detection. The daemon does not currently run a deadlock search. The counters and status plumbing exist, but applications that rely on the VMS lock manager raising a deadlock condition should be reviewed during migration. Where deadlock avoidance matters, design lock ordering into the application rather than depending on detection.

Deliberate divergences

DivergenceReason
Single-node only; cluster system ids degenerate to 0The transport is a local System V message queue, not a cluster interconnect.
No deadlock detectionThe deadlock search is not implemented in the current build.
ENQLM and sublock-depth limits never raisedThese quota limits are not imposed.
Client-side pre-validation of argumentsThe daemon never touches client memory, so access-violation and bad-parameter checks are the client library's responsibility.
LCK$M_AUDITED option addedA Sector7 extension for audit tracing, not present in the original lock manager.
Maximum of 80,000 concurrent lock idsThe lock table is sized for up to 80,000 active locks per daemon.

Quick reference

Lock modes

NL = 0
CR = 1
CW = 2
PR = 3
PW = 4
EX = 5

EX excludes all but NL; NL is compatible with every mode.

Client routines

SYS$ENQ
SYS$ENQW
SYS$DEQ
SYS$DEQW
SYS$GETLKI
SYS$GETLKIW
SYS$SET_RESOURCE_DOMAIN
SYS$RUNDOWN

Common request flags

LCK$M_VALBLK
LCK$M_CONVERT
LCK$M_NOQUEUE
LCK$M_SYNCSTS
LCK$M_SYSTEM
LCK$M_EXPEDITE
LCK$M_XVALBLK
LCK$M_AUDITED

Lock states

LKI$C_WAITING = -1
LKI$C_CONVERT = 0
LKI$C_GRANTED = 1

Operator commands

lckctl start
lckctl stop
lckctl stats
lckctl status
lckctl reset-stats
lckctl vacuum

Scope

Single node, one lckmgr daemon per node, clients reached over a System V message queue. Up to 80,000 concurrent lock ids. No cluster mastering and no deadlock detection in the current build.

Frequently Asked Questions

Curious about how Sector7 can facilitate your application migration? Explore our FAQs for expert insights.

What is VX/LCKMGR and how does it help with OpenVMS migrations?

VX/LCKMGR is a fully compatible OpenVMS lock management system designed for Linux environments. It ensures identical functionality to OpenVMS lock management while leveraging Sector7's high-speed AST backplane for enhanced performance.

This solution supports core OpenVMS lock manager functions like SYS$ENQ(W), SYS$DEQ(W), and SYS$GETLKI(), enabling seamless integration with existing OpenVMS applications during migration to Linux. Contact us to discuss your OpenVMS lock manager migration requirements.

What lock modes does VX/LCKMGR support?

VX/LCKMGR supports all major OpenVMS lock modes including Protected Read (LCK$K_PRMODE), Protected Write (LCK$K_PWMODE), Concurrent Read (LCK$K_CRMODE), Concurrent Write (LCK$K_CWMODE), Exclusive (LCK$K_EXMODE), and NULL (LCK$K_NLMODE).

How fast can VX/LCKMGR process lock operations?

In stress testing, VX/LCKMGR demonstrated exceptional performance by handling 80,000 lock conversions per second on a 1997-era quad-core Opteron server.

What $ENQ and $DEQ codes are supported?

VX/LCKMGR supports essential $ENQ/$DEQ codes including LCK$V_VALBLK (Value Block), LCK$V_CONVERT (Convert Lock), LCK$V_NOQUEUE (No Queue), LCK$V_SYNCSTS (Sync Status), LCK$V_SYSTEM (System Lock), and LCK$V_RECOVER (Recovery Mode).

How does VX/LCKMGR handle lock diagnostics and monitoring?

VX/LCKMGR provides comprehensive diagnostic capabilities including real-time lock request logging and replay functionality. The system can log all lock requests and replay them for performance tuning and diagnostic purposes.

Additionally, it offers real-time display of all lock requests, making it easier for system administrators to track lock statuses and manage resources effectively. Companies like Telstra have benefited from similar real-time monitoring capabilities during their OpenVMS migrations.

What $GETLKI information can be retrieved?

VX/LCKMGR supports $GETLKI codes for retrieving lock information including LKI$C_LENGTH (Lock Length), LKI$_BLOCKEDBY (Blocked By Lock), LKI$_BLOCKING (Blocking Lock), LKI$_LCKCOUNT (Lock Count), and LKI$_LOCKID (Lock ID).

Are there any limitations with VX/LCKMGR implementation?

VX/LCKMGR fully supports OpenVMS lock management functions but is limited to single-node environments. It does not operate across multiple nodes, which is important to consider when planning implementation in distributed systems.

What are the key benefits of migrating to VX/LCKMGR?

VX/LCKMGR reimplements the OpenVMS lock manager on Linux. It supports all six OpenVMS lock modes, the grant and conversion queues, value blocks and resource domains, so migrated applications keep their existing locking logic.

It also provides an audit log with replay, which lets you reproduce a workload for tuning and isolate bottlenecks without re-running the original application, plus status and statistics through lckctl. Cluster-wide lock mastering and deadlock detection are not part of the current build. To explore how VX/LCKMGR can support your migration, contact our team for a detailed consultation.

What is VX/LCKMGR and how does it help with an OpenVMS migration?

VX/LCKMGR is Sector7's reimplementation of the OpenVMS lock manager for Linux. It provides the SYS$ENQ, SYS$DEQ and SYS$GETLKI system services and the arbitration daemon behind them, so migrated OpenVMS applications keep their existing locking logic and coordinate access to shared resources on modern Linux without a rewrite. Contact our team to review how it fits your estate.

Does VX/LCKMGR require rewriting our application's locking code?

No. Applications call the same SYS$ services with the same arguments and option flags as on OpenVMS. The lock modes, flag encodings and completion behaviour are preserved, so existing code that enqueues, converts and dequeues locks links and runs unchanged.

Can VX/LCKMGR run across multiple nodes or an OpenVMS cluster?

No. VX/LCKMGR is a single-node lock manager. One daemon on a node owns the resource and lock databases, and client processes reach it over a local message queue. It supports every OpenVMS lock mode on that node but does not perform cluster-wide lock mastering, so applications that depend on cluster coordination should be reviewed during migration planning.

Which lock modes does VX/LCKMGR support?

All six OpenVMS lock modes: null (NL), concurrent read (CR), concurrent write (CW), protected read (PR), protected write (PW) and exclusive (EX). The full compatibility matrix and the grant, conversion and wait queue behaviour match the OpenVMS lock manager.

What lock information can we query at runtime?

SYS$GETLKI returns detailed lock information through an item list, including the process, lock id, state, resource name, value block, and blocking and waiting relationships. This supports the same troubleshooting, monitoring and diagnostic workflows teams rely on with the OpenVMS lock manager.

How does VX/LCKMGR help diagnose locking performance issues?

The daemon can record every lock request to an audit log and replay it later for tuning and diagnostics, and it reports live statistics on request volumes and queue activity through the lckctl utility. Because replay reconstructs the request stream directly, bottlenecks can be investigated without re-running the original application.

Does VX/LCKMGR perform deadlock detection?

The current build does not run a deadlock search. Applications that rely on the OpenVMS lock manager signalling a deadlock should be reviewed during migration, and where deadlock avoidance matters we recommend designing consistent lock ordering into the application. Our team can advise on the right approach for your workload.

What platforms and scale does VX/LCKMGR support?

VX/LCKMGR runs on Linux and supports up to 80,000 concurrent lock ids per daemon, with 16-byte and 64-byte lock value blocks and resource domains so unrelated applications can share one daemon safely. It is delivered as part of Sector7's OpenVMS to Linux migration toolset.

Transform Your Legacy Software Today!

Get In Touch
Unlock the potential of your legacy software with our expert migration services.