The example in Figure 11 illustrates the use of the XPI and storage in a global user exit program. It is not a complete program, but merely an example of entry and exit code for any global user exit program, and the use of the XPI function.
The options of the DFHSMMCX macro used in the example are described in Storage control XPI functions.
The example uses the technique of obtaining some storage for this invocation of the program using the XPI GETMAIN call, and then saving the address of this storage in the first 4 bytes of the LIFO storage addressed by UEPXSTOR. In this example, the initialization of the parameter list (using the CLEAR option), the building of the parameter list, and the GETMAIN call occur in a single macro. For details of how to build the parameter list incrementally, and how to separate the CLEAR and the GETMAIN call, refer to An example showing how to build a parameter list incrementally.
TITLE 'GUEXPI - GLOBAL USER EXIT PROGRAM WITH XPI'
*************************************************************************
* The first three instructions set up the global user exit *
* environment, identify the user exit point, prepare for the use of *
* the exit programming interface, and copy in the definitions that *
* are to be used by the XPI function. *
*************************************************************************
*
DFHUEXIT TYPE=EP,ID=XFCREQ PROVIDE DFHUEPAR PARAMETER
* LIST FOR XFCREQ IN THE FILE
* CONTROL PROGRAM AND LIST
* OF EXITID EQUATES
*
DFHUEXIT TYPE=XPIENV SET UP ENVIRONMENT FOR
* EXIT PROGRAMMING INTERFACE --
* MUST BE ISSUED BEFORE ANY
* XPI MACROS ARE ISSUED
*
COPY DFHSMMCY DEFINE PARAMETER LIST FOR
* USE BY DFHSMMCX MACRO
*
*************************************************************************
* The following DSECT maps a storage area you can use to make the *
* exit program reentrant by storing the address of the storage you *
* acquire in the first four bytes of the 260-byte area provided by *
* the user exit handler (DFHUEH) and addressed by UEPXSTOR. *
*************************************************************************
*
TRANSTOR DSECT DSECT FOR STORAGE OBTAINED BY
* GETMAIN
·
·
·
storage declarations
·
·
·
*
*************************************************************************
* The next seven instructions form the normal start of a global user *
* exit program, setting the program addressing mode to 31-bit, saving *
* the calling program's registers, establishing base addressing, and *
* establishing the addressing of the user exit parameter list. *
*************************************************************************
*
GXPI CSECT
GXPI AMODE 31 SET TO 31-BIT ADDRESSING
*
SAVE (14,12) SAVE CALLING PROGRAM'S REGISTERS
*
LR R11,R15 SET UP USER EXIT PROGRAM'S
USING GXPI,R11 BASE REGISTER
*
LR R2,R1 SET UP ADDRESSING FOR USER
USING DFHUEPAR,R2 EXIT PARAMETER LIST -- USE
* REGISTER 2 AS XPI CALLS USE
* REGISTER 1
*
**************************************************************************
* Before issuing an XPI function call, set up addressing to XPI *
* parameter list. *
*************************************************************************
*
L R5,UEPXSTOR SET UP ADDRESSING FOR XPI
* PARAMETER LIST
*
USING DFHSMMC_ARG,R5 MAP PARAMETER LIST
*
*************************************************************************
* Before issuing an XPI function call, you must ensure that register *
* 13 addresses the kernel stack. *
*************************************************************************
*
L R13,UEPSTACK ADDRESS KERNEL STACK
*
*************************************************************************
* Issue the DFHSMMCX macro call, specifying: *
* *
* CALL -- the macro is to be called immediately *
* *
* CLEAR -- initialize the parameter list before inserting values. *
* *
* IN -- input values follow. *
* *
* FUNCTION(GETMAIN) -- acquire storage *
* GET_LENGTH(120) -- 120 bytes of it *
* SUSPEND(NO) -- don't suspend if storage not available *
* INITIAL_IMAGE(X'00') -- clear acquired storage *
* to hex zero throughout. *
* STORAGE_CLASS(USER) -- class of storage to be *
* acquired is user storage *
* above the 16MB line. *
* *
* OUT -- output values follow *
* *
* ADDRESS((R6)) -- put address of acquired storage in *
* register 6. *
* RESPONSE(*) -- put response at SMMC_RESPONSE in *
* macro parameter list. *
* REASON(*) -- put reason at SMMC_REASON in macro *
* parameter list. *
* *
*************************************************************************
*
DFHSMMCX CALL, *
CLEAR, *
IN, *
FUNCTION(GETMAIN), *
GET_LENGTH(120), *
SUSPEND(NO), *
INITIAL_IMAGE(X'00'), *
STORAGE_CLASS(USER), *
OUT, *
ADDRESS((R6)), *
RESPONSE(*), *
REASON(*)
* *
*************************************************************************
* Test SMMC_RESPONSE -- if OK, then branch round error handling. *
*************************************************************************
* *
CLI SMMC_RESPONSE,SMMC_OK CHECK RESPONSE AND...
BE STOK ...IF OK, BYPASS ERROR ROUTINES
* *
·
·
·
error-handling routines
·
·
·
**************************************************************************
* The next section maps TRANSTOR on the acquired storage. *
**************************************************************************
STOK DS 0H
USING TRANSTOR,R6 MAP ACQUIRED STORAGE
ST R6,0(R5) SAVE STORAGE ADDRESS IN FIRST
* 4 BYTES OF STORAGE ADDRESSED
* BY UEPXSTOR
*
LA R5,4(R5) ADDRESS 4-BYTE OFFSET
DROP R5 REUSE REGISTER 5 TO BASE ALL
USING DFHxxyy_ARG,R5 FOLLOWING XPI PARAMETER LISTS
* AT 4-BYTE OFFSET INTO STORAGE
* ADDRESSED BY UEPXSTOR
·
·
·
rest of user exit program
·
·
·
*
*************************************************************************
* When the rest of the exit program is completed, free the storage
* and return.
*************************************************************************
*
DROP R5 REUSE REGISTER 5 TO MAP DFHSMMC
USING DFHSMMC_ARG,R5 XPI PARAMETER LIST
*
L R13,UEPSTACK ADDRESS KERNEL STACK
*
*************************************************************************
* Issue the DFHSMMCX macro call, specifying: *
* *
* CALL -- the macro is to be called immediately. *
* *
* CLEAR -- initialize the parameter list before inserting values. *
* *
* IN -- input values follow. *
* *
* FUNCTION(FREEMAIN) -- release storage *
* ADDRESS((R6)) -- address of storage is in register 6. *
* STORAGE_CLASS(USER) -- class of acquired storage was *
* 31-bit user storage. *
* *
* OUT -- output values follow *
* *
* RESPONSE(*) -- put response at SMMC_RESPONSE in *
* macro parameter list. *
* REASON(*) -- put reason at SMMC_REASON in macro *
* parameter list. *
* *
*************************************************************************
*
DFHSMMCX CALL, +
CLEAR, +
IN, +
FUNCTION(FREEMAIN), +
ADDRESS((R6)), +
STORAGE_CLASS(USER), +
OUT, +
RESPONSE(*), +
REASON(*)
* *
*************************************************************************
* Test SMMC_RESPONSE -- if OK, then branch round error handling. *
*************************************************************************
* *
CLI SMMC_RESPONSE,SMMC_OK CHECK RESPONSE AND...
BE STEND ...IF OK, BYPASS ERROR ROUTINES
* *
·
·
·
error-handling routines
·
·
·
*
*************************************************************************
* Restore registers, set return code, and return to user exit handler *
*************************************************************************
* *
STEND DS 0H
L R13,UEPEPSA
RETURN (14,12),RC=UERCNORM
LTORG
END GXPI
In the following example, the parameter list is built incrementally. The initialization of the parameter list (using the CLEAR option), the building of the parameter list, and the GETMAIN call are separated into discrete steps.
DFHSMMCX CLEAR
·
·
·
DFHSMMCX GET_LENGTH(100)
·
·
·
DFHSMMCX CALL, *
IN, *
FUNCTION(GETMAIN), *
GET_LENGTH(*), *
SUSPEND(NO), *
INITIAL_IMAGE(X'00'), *
STORAGE_CLASS(USER), *
OUT, *
ADDRESS((R6)), *
RESPONSE(*), *
REASON(*)
You must set your parameters using only the XPI functions.