Document revision date: 30 March 2001

## OpenVMS System Services Reference Manual

Previous | Contents | Index

Getting information about another process is an asynchronous operation because the information might be contained in the virtual address space of the target process, and that process might be running at a lower priority, be outswapped, or be suspended in a miscellaneous or resource wait state. To allow your program to overlap other functions with the time needed to access the data in the other process, $GETJPI returns immediately after it has queued its information-gathering request to the other process. You can use the JPI$_GETJPI item code to control the processing of the $GETJPI call and the information-gathering interprocess request itself.

When performing an asynchronous system service call such as $GETJPI, the specifications of the iosb argument and a unique event flag are used in conjunction with mechanisms such as the $SYNCH system service to synchronize the final completion of the asynchronous system service call.

Required Access or Privileges

The calling process must have GROUP privilege to obtain information about other processes with the same group UIC number as the calling process. The calling process must have WORLD privilege to obtain information about other processes on the system that are not in the same group as the calling process.

Required Quota

None

Related Services

$GETJPIW, $HIBER, $PROCESS_SCAN, $RESUME, $SYNCH

### Condition Values Returned

> SS$_NORMAL | The service completed successfully.
> SS$_ACCVIO | The item list cannot be read by the caller, or the buffer length or buffer cannot be written by the caller.
> SS$_BADPARAM | The item list contains an invalid identifier. Or, an item list containing both 32-bit and 64-bit item list entries was found.
> SS$_INCOMPAT | The remote node is running an incompatible version of the operating system.
> SS$_IVLOGNAM | The process name string has a length of 0 or has more than 15 characters.
> SS$_NOMOREPROC | In a wildcard operation, $GETJPI found no more processes.
> SS$_NOMORETHREAD | The search for kernel threads within a process is complete. This condition value is returned by $GETJPIW if you set the JPI$M_THREAD bit in JPI$_GETJPI_CONTROL_FLAGS.
> SS$_NONEXPR | The specified process does not exist, or an invalid process identification was specified.
> SS$_NOPRIV | The process does not have the privilege to obtain information about the specified process.
> SS$_NOSUCHNODE | The specified node is not currently a member of the cluster.
> SS$_REMRSRC | The remote node has insufficient resources to respond to the request. (Bring this error to the attention of your system manager.)
> SS$_SUSPENDED | The specified process is suspended or in a miscellaneous wait state, and the requested information cannot be obtained.
> SS$_UNREACHABLE | The remote node is a member of the cluster but is not accepting requests. This is normal for a brief period early in the system boot process.

### Condition Values Returned in the I/O Status Block

1

> Same as those returned in R0.

### Example

    // COPYRIGHT (c) 1999 BY
    // DIGITAL EQUIPMENT CORPORATION, NASHUA, NEW HAMPSHIRE.
    // ALL RIGHTS RESERVED.
    //
    // THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
    // ONLY  IN  ACCORDANCE  OF  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
    // INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR  ANY  OTHER
    // COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
    // OTHER PERSON.  NO TITLE TO AND  OWNERSHIP OF THE  SOFTWARE IS  HEREBY
    // TRANSFERRED.
    //
    // THE INFORMATION IN THIS SOFTWARE IS  SUBJECT TO CHANGE WITHOUT NOTICE
    // AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
    // CORPORATION.
    //
    // DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE  OR  RELIABILITY OF ITS
    // SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
    //
    // FACILITY:
    //
    //      OpenVMS Documentation
    //
    //
    // Compile and link instructions:
    //
    //    $ cc/decc getjpi_demo
    //    $ link getjpi_demo
    //    $ run getjpi_demo
    //
    //

    #pragma module getjpi_demo "V1.0-000"

    // The various external definitions and prototypes...

    #include <descrip.h>           // static and dynamic string descriptor defs
    #include <efndef.h>            // for the No Event Flag Event Flag
    #include <jpidef.h>            // sys$getjpi item codes
    #include <lib$routines.h>      // run-time library function prototypes
    #include <pscandef.h>          // sys$process_scan item codes
    #include <ssdef.h>             // System service message codes
    #include <starlet.h>           // Function prototypes for system services
    #include <stdio.h>             // C standard I/O functions
    #include <stsdef.h>            // condition value definitions

    // Constants used in this module

    #define     MAX_ITEMLIST_IL3_ENTRIES  10
    #define     PROCESSNAME_LENGTH        16
    #define     USERNAME_LENGTH           12
    #define     IMAGE_LENGTH              255
    #define     TRIMAGE_LENGTH            38

    main()
      {
      char ImageBuf[IMAGE_LENGTH+1];
      char ProcessBuf[PROCESSNAME_LENGTH+1];
      char UsernameBuf[USERNAME_LENGTH+1];
      int Count = 0;
      int ProcessId;
      int RetStat;
      int i;
      unsigned long int JpiCtx;
      unsigned short int TrimageLength = TRIMAGE_LENGTH;
      unsigned short int ImageLength;
      unsigned short int ProcessLength;
      unsigned short int UsernameLength;
      unsigned short int iosb[4];
      struct dsc$descriptor TrimageDsc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_D, NULL };
      struct dsc$descriptor ImageDsc = { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL };
      struct itemlist3
        {
        unsigned short int il_siz;
        unsigned short int il_cod;
        void *il_buf;
        unsigned short int *il_rla;
        } il3[MAX_ITEMLIST_IL3_ENTRIES];
      char *CtlFmtT = "%-8.8s %-12s %-16s %-*.*s\n";
      char *CtlFmtD = "%08X %-12s %-16s %-*.*s\n";

      // Set up the static string descriptor...

      ImageDsc.dsc$a_pointer = ImageBuf;

      // Set up to scan only the interactive processes...

      i = 0;
      il3[i].il_siz   = 0;
      il3[i].il_cod   = PSCAN$_MODE;
      il3[i].il_buf   = (void *) JPI$K_INTERACTIVE;
      il3[i++].il_rla = NULL;
      il3[i].il_siz   = 0;
      il3[i].il_cod   = 0;
      il3[i].il_buf   = NULL;
      il3[i++].il_rla = NULL;

      // the sys$process_scan service sets up the sys$getjpi context...

      RetStat = sys$process_scan( &JpiCtx, il3 );
      if (!$VMS_STATUS_SUCCESS( RetStat ))
        return RetStat;

      i = 0;
      il3[i].il_siz   = USERNAME_LENGTH;
      il3[i].il_cod   = JPI$_USERNAME;
      il3[i].il_buf   = UsernameBuf;
      il3[i++].il_rla = &UsernameLength;
      il3[i].il_siz   = PROCESSNAME_LENGTH;
      il3[i].il_cod   = JPI$_PRCNAM;
      il3[i].il_buf   = ProcessBuf;
      il3[i++].il_rla = &ProcessLength;
      il3[i].il_siz   = IMAGE_LENGTH;
      il3[i].il_cod   = JPI$_IMAGNAME;
      il3[i].il_buf   = ImageBuf;
      il3[i++].il_rla = &ImageLength;
      il3[i].il_siz   = sizeof( int );
      il3[i].il_cod   = JPI$_PID;
      il3[i].il_buf   = &ProcessId;
      il3[i++].il_rla = NULL;
      il3[i].il_siz   = 0;
      il3[i].il_cod   = 0;
      il3[i].il_buf   = NULL;
      il3[i++].il_rla = NULL;

      // Display the header...

      printf( CtlFmtT, "PID","Username","Process name", 6, 6, "Image");

      // Loop through the available processes...

      while ( TRUE )
        {

        // Find the next process...

        RetStat = sys$getjpiw( EFN$C_ENF, &JpiCtx, NULL,
          il3, iosb, NULL, 0);
        if ((RetStat == SS$_NOPRIV) || (RetStat == SS$_SUSPENDED))
          continue;
        if ( RetStat == SS$_NOMOREPROC )
          break;
        if (!$VMS_STATUS_SUCCESS( RetStat ))
          return RetStat;

        Count++;

        // Zero-terminate the username, process and image name strings...

        UsernameBuf[UsernameLength] = '\0';
        ProcessBuf[ProcessLength] = '\0';
        ImageBuf[ImageLength] = '\0';

        // Trim the image filename to fit...

        ImageDsc.dsc$w_length = ImageLength;
        RetStat = lib$trim_filespec( &ImageDsc, &TrimageDsc, &TrimageLength );
        if (!$VMS_STATUS_SUCCESS( RetStat ))
          return RetStat;

        printf( CtlFmtD, ProcessId, UsernameBuf, ProcessBuf,
          TrimageDsc.dsc$w_length, TrimageDsc.dsc$w_length,
          TrimageDsc.dsc$a_pointer );
        }

      printf("Interactive process count: %d\n", Count );

      // Free up the dynamic descriptor allocated by lib$trim_filespec

      RetStat = lib$sfree1_dd( &TrimageDsc );
      if (!$VMS_STATUS_SUCCESS( RetStat ))
        return RetStat;

      return SS$_NORMAL;
      }

> This is a simple program that demonstrates calling various OpenVMS system services and run-time library routines. This example uses the available process privileges to display as many interactive processes as it can---when the WORLD privilege is available, all of the interactive processes will be displayed.

> This example was built with OpenVMS (VAX and Alpha) V7.2, using the Compaq C V6.0 compiler.

## $GETJPIW

> Returns information about one or more processes on the system.

> The $GETJPIW service completes synchronously; that is, it returns to the caller with the requested information. Compaq recommends that you use an IOSB with this service. An IOSB prevents the service from completing prematurely. In addition, the IOSB contains status information.

> For asynchronous completion, use the Get Job/Process Information ($GETJPI) service; $GETJPI returns to the caller after queuing the information request, without waiting for the information to be returned.

> In all other respects, $GETJPIW is identical to $GETJPI. For all other information about the $GETJPIW service, refer to the description of $GETJPI in this manual.

> On Alpha systems, this service accepts 64-bit addresses.

### Format

> SYS$GETJPIW [efn] ,[pidadr] ,[prcnam] ,itmlst ,[iosb] ,[astadr] ,[astprm]

### C Prototype

> int sys$getjpiw (unsigned int efn, unsigned int *pidadr, void *prcnam, void *itmlst, struct _iosb *iosb, void (*astadr)(__unknown_params), int astprm);

## $GETLKI

> Returns information about the lock database on a system.

> The $GETLKI service completes asynchronously; for synchronous completion, use the Get Lock Information and Wait ($GETLKIW) service.

> The $GETLKI, $GETLKIW, $ENQ, $ENQW, and $DEQ services together provide the user interface to the Lock Management facility.

### Format

> SYS$GETLKI [efn] ,lkidadr ,itmlst [,iosb] [,astadr] [,astprm] [,nullarg]

### C Prototype

> int sys$getlki (unsigned int efn, unsigned int *lkidadr, void *itmlst, struct _iosb *iosb, void (*astadr)(__unknown_params), int astprm, unsigned int reserved);

### Arguments

> #### efn

> OpenVMS usage: | ef_number
> type: | longword (unsigned)
> access: | read only
> mechanism: | by value

> Number of the event flag to be set when $GETLKI completes. The efn argument is a longword containing this number; however, $GETLKI uses only the low-order byte. If you do not specify efn, $GETLKI sets event flag 0.

> #### lkidadr

> OpenVMS usage: | lock_id
> type: | longword (unsigned)
> access: | modify
> mechanism: | by reference

> Lock identification (lock ID) for the lock about which information is to be returned. The lock ID is the second longword in the lock status block, which was created when the lock was granted. The lkidadr argument is the address of this longword.

> If the value specified by lkidadr is 0 or --1, $GETLKI assumes a wildcard operation and returns information about each lock to which the calling process has access, one lock per call.

> To use the $GETLKI service, you must have read/write access to the lock ID.

> #### itmlst

> OpenVMS usage: | item_list_3
> type: | longword (unsigned)
> access: | read only
> mechanism: | by reference

> Item list specifying the lock information that $GETLKI is to return. The itmlst argument is the address of a list of item descriptors, each of which describes an item of information. The list of item descriptors is terminated by a longword of 0.

> The following diagram depicts the format of a single item descriptor:

The following table defines the item descriptor fields:

Descriptor Field | Definition
--- | ---
Buffer length | A word containing a user-supplied integer specifying the length (in bytes) of the buffer in which $GETLKI is to write the information. The length of the buffer needed depends on the item code specified in the item code field of the item descriptor. If the value of the buffer length field is too small, $GETLKI truncates the data and returns the success condition value SS$_NORMAL.
Item code | A word containing a user-specified symbolic code specifying the item of information that $GETLKI is to return. The $LKIDEF macro defines these codes. Each item code is described in the list of $GETLKI item codes that follows the argument descriptions.
Buffer address | A longword containing a user-supplied address of the buffer in which $GETLKI is to write the information.
Return length address | A longword containing the user-supplied address of a longword in which $GETLKI writes return length information. This longword contains the following three bit fields:
Bits 0 to 15 | In this field, $GETLKI writes the length in bytes of the data actually written to the buffer specified by the buffer address field in the item descriptor.
Bits 16 to 30 | $GETLKI uses this field only when the item code field of the item descriptor specifies LKI$_BLOCKEDBY, LKI$_BLOCKING, or LKI$_LOCKS, each of which requests information about a list of locks. $GETLKI writes in this field the length in bytes of the information returned for a single lock on the list. You can divide this length into the total length returned for all locks (bits 0 to 15) to determine the number of locks located by that item code request.
Bit 31 | $GETLKI sets this bit if the user-supplied buffer length argument specifies too small a buffer to contain the information returned. Note that in such a case, $GETLKI will return the SS$_NORMAL condition value in R0. Therefore, to locate any faulty item descriptor, you need to check the state of bit 31 in the longword specified by the return length field of each item descriptor.

#### iosb

OpenVMS usage: | io_status_block
type: | quadword (unsigned)
access: | write only
mechanism: | by reference

I/O status block that is to receive the final completion status. The iosb argument is the address of a quadword.

When $GETLKI is called, it sets the I/O status block to 0. When $GETLKI completes, it writes a condition value to the first longword in the quadword. The remaining two words in the quadword are unused.

Although this argument is optional, Compaq strongly recommends that you specify it, for the following reasons:

- If you are using an event flag to signal the completion of the service, you can test the I/O status block for a condition value to be sure that the event flag was not set by an event other than service completion.
- If you are using the $SYNCH service to synchronize completion of the service, the I/O status block is a required argument for $SYNCH.
- The condition value returned in R0 and the condition value returned in the I/O status block provide information about different aspects of the call to the $GETLKI service. The condition value returned in R0 gives you information about the success or failure of the service call itself; the condition value returned in the I/O status block gives you information about the success or failure of the service operation. Therefore, to accurately assess the success or failure of the call to $GETLKI, you must check the condition values returned in both R0 and the I/O status block.

#### astadr

OpenVMS usage: | ast_procedure
type: | procedure value
access: | call without stack unwinding
mechanism: | by reference

AST service routine to be executed when the service completes. The astadr argument is the address of this routine.

If you specify this argument, the AST routine executes at the same access mode as the caller of the $GETLKI service.

#### astprm

OpenVMS usage: | user_arg
type: | longword (unsigned)
access: | read only
mechanism: | by value

AST parameter to be passed to the AST service routine specified by the astadr argument. The astprm argument is the longword parameter.

#### nullarg

OpenVMS usage: | null_arg
type: | longword (unsigned)
access: | read only
mechanism: | by value

Placeholding argument reserved by Compaq.

### Item Codes

> #### LKI$_BLOCKEDBY

> Returns information about all locks that are currently blocked by the lock specified by lkidadr. The $GETLKI service returns eight items of information about each blocked lock.

> The $LKIDEF macro defines the following symbolic names that refer to the eight items in the buffer:

> Symbolic Name | Description
> --- | ---
> LKI$L_MSTLKID | Lock ID of the blocking lock on the system maintaining the resource (4 bytes)
> LKI$L_PID | Process ID (PID) of the process that took out the blocked lock (4 bytes)
> LKI$L_MSTCSID | OpenVMS Cluster system identifier (CSID) of the node maintaining the resource that is locked by the blocked lock (4 bytes)
> LKI$B_RQMODE | Lock mode requested for the blocked lock; this lock mode was specified by the lkmode argument in the call to $ENQ (1 byte)
> LKI$B_GRMODE | Lock mode granted to the blocked lock; this lock mode is written to the lock value block (1 byte)
> LKI$B_QUEUE | Name of the queue on which the blocked lock currently resides (1 byte)
> LKI$L_LKID | Lock ID of the lock on the system where the lock was requested (4 bytes)
> LKI$L_CSID | OpenVMS Cluster system identifier (CSID) of the system where the lock was requested (4 bytes)

> The values that $GETLKI can write into the LKI$B_RQMODE, LKI$B_GRMODE, and LKI$B_QUEUE items have symbolic names; these symbolic names specify the six lock modes and the three types of queue in which a lock can reside. The Description section describes these names.

> Thus, the buffer specified by the buffer address field in the item descriptor will contain the eight items of information, repeated in sequence, for each blocked lock.

> The length of the information returned for each blocked lock is returned in bits 16 to 30 of the longword specified by the return length address field in the item descriptor, while the total length of information returned for all blocked locks is returned in bits 0 to 15. Therefore, to determine the number of blocked locks, you divide the value of bits 16 to 30 into the value of bits 0 to 15.

> #### LKI$_BLOCKING

> Returns information about all locks that are currently blocking the lock specified by lkidadr. The $GETLKI service returns eight items of information about each blocking lock.

> The $LKIDEF macro defines the following symbolic names that refer to the eight items in the buffer:

> Symbolic Name | Description
> --- | ---
> LKI$L_MSTLKID | Lock ID of the blocked lock on the system maintaining the resource (4 bytes)
> LKI$L_PID | Process ID (PID) of the process that took out the blocking lock (4 bytes)
> LKI$L_MSTCSID | OpenVMS Cluster system identifier (CSID) of the node maintaining the resource that is locked by the blocking lock (4 bytes)
> LKI$B_RQMODE | Lock mode requested for the blocking lock; this lock mode was specified by the lkmode argument in the call to $ENQ (1 byte)
> LKI$B_GRMODE | Lock mode granted to the blocking lock; this lock mode is written to the lock value block (1 byte)
> LKI$B_QUEUE | Name of the queue on which the blocking lock currently resides (1 byte)
> LKI$L_LKID | Lock ID of the lock on the system where the lock was requested (4 bytes)
> LKI$L_CSID | OpenVMS Cluster system identifier (CSID) of the system where the lock was requested (4 bytes)

> The values that $GETLKI can write into the LKI$B_RQMODE, LKI$B_GRMODE, and LKI$B_QUEUE items have symbolic names; these symbolic names specify the six lock modes and the three types of queue in which a lock can reside. The Description section describes these names.

> Thus, the buffer specified by the buffer address field in the item descriptor will contain the eight items of information, repeated in sequence, for each blocking lock.

> The length of the information returned for each blocking lock is returned in bits 16 to 30 of the longword specified by the return length address field in the item descriptor, while the total length of information returned for all blocking locks is returned in bits 0 to 15. Therefore, to determine the number of blocking locks, you divide the value of bits 16 to 30 into the value of bits 0 to 15.

> #### LKI$_CSID

> Returns the Cluster System ID (CSID) of the system where the process owning the lock resides. LKI$_CSID returns the CSID of the node where the $GETLKI system service is issued when the resource is mastered on that node. When the processor is not part of a cluster, LKI$_CSID returns 0.

> The buffer length field in the item descriptor should specify 4 (bytes).

> #### LKI$_CVTCOUNT

> Returns the total number of locks that are currently on the conversion queue of the resource associated with the lock. These locks are granted at one mode and are waiting to be converted to another.

> The buffer length field in the item descriptor should specify 4 (bytes).

> #### LKI$_GRANTCOUNT

> Returns the total number of locks that are currently on the grant queue of the resource associated with the lock. Note that the total number of granted locks on the resource is equal to the sum of LKI$_CVTCOUNT and LKI$_GRANTCOUNT.

> The buffer length field in the item descriptor should specify 4 (bytes).

> #### LKI$_LCKREFCNT

> Returns the number of locks that have this lock as a parent lock. When these locks were created, the parid argument in the call to $ENQ or $ENQW specified the lock ID of this lock.

> The buffer length field in the item descriptor should specify 4 (bytes).

> #### LKI$_LKID

> Returns the lock ID of the lock on the system where the process owning the lock resides. The lock ID returned by this item code is meaningful only on the system specified in the value returned by the LKI$_CSID item code.

> The buffer length field in the item descriptor should specify 4 (bytes).

> #### LKI$_LOCKID

> Returns the lock ID of the current lock. The current lock is the one specified by the lkidadr argument unless lkidadr is specified as --1 or 0, which indicates a wildcard operation. Thus, this item code is usually specified only in wildcard operations where it is useful to know the lock IDs of the locks that $GETLKI has discovered in the wildcard operation.

> The lock ID is a longword value, so the buffer length field in the item descriptor should specify 4 (bytes).

> #### LKI$_LOCKS

> Returns information about all locks on the resource associated with the lock specified by lkidadr.

> The $LKIDEF macro defines the following symbolic names that refer to the eight items in the buffer:

> Symbolic Name | Description
> --- | ---
> LKI$L_MSTLKID | Lock ID of the blocked lock on the system maintaining the resource (4 bytes)
> LKI$L_PID | Process ID (PID) of the process that took out the lock (4 bytes)
> LKI$L_MSTCSID | OpenVMS Cluster system identifier (CSID) of the node maintaining the resource that is locked by the lock (4 bytes)
> LKI$B_RQMODE | Lock mode requested for the lock; this lock mode was specified by the lkmode argument in the call to $ENQ (1 byte)
> LKI$B_GRMODE | Lock mode granted to the lock; this lock mode is written to the lock value block (1 byte)
> LKI$B_QUEUE | Name of the queue on which the lock currently resides (1 byte)
> LKI$L_LKID | Lock ID of the lock on the system where the lock was requested (4 bytes)
> LKI$L_CSID | OpenVMS Cluster system identifier (CSID) of the system where the lock was requested (4 bytes)

> Previous | Next | Contents | Index

> | privacy and legal statement |
> 4527PRO_047.HTML