BPE callable service example: Sharing data among exit routines
As an example of the use of callable services, consider the case where you have a set of user exit routines of varying types that all need to share some common information.
For this example, assume that the following three types of exit routines are being used:
- An initialization exit routine that gets control when the address space is first started. Assume that this exit routine runs before any mainline processing is done (so you can be sure that the other two exit routines will not be called until the initialization exit routine has returned).
- A processing exit routine that gets control whenever a particular event occurs in the address space that needs user exit routine provided information.
- A termination exit routine that gets control when the address space is ending.
Sample initialization exit routine
The initialization exit routine uses the create named storage service to obtain a 16-byte area of storage with the name ZZZ_EXIT_AREA. The storage is mapped by the following DSECT (which is assumed to be available in all of the modules).
ZZZ_EXIT_AREA DSECT ,
ZZZ_TABLE_NAME DS CL8 Name of table module
ZZZ_TABLE_ADDR DS A Address of table module
DS F Available
ZZZ_EXIT_AREA_L EQU *-ZZZ_EXIT_AREA The initialization exit routine then uses the load module service to load a module named ZZZUXTB0 (a table that is needed in this example to pass information to the other user exit routines). The initialization exit routine stores the name of the table module in the named storage area field ZZZ_TABLE_NAME, and the address of the loaded table in field ZZZ_TABLE_ADDR. A routine using a table may not be required for your application.
A sample initialization exit routine that performs these functions is shown in the following example. The code shown in the following examples is mainline path only. For simplicity, error paths and exception handling code are not shown.
INITEXIT CSECT ,
INITEXIT AMODE 31
INITEXIT RMODE ANY
STM 14,12,12(13) Save caller's registers
LR 12,15 Move module entry pt to R12
USING INITEXIT,12 Address module base register
L 13,8(,13) Chain to 2nd provided save area
LR 11,1 Move exit parmlist to R11
USING BPEUXPL,11 Address std BPE user exit PL
L 10,UXPL_DYNAMICWAP Get 512-byte dynamic storage ptr
USING DYNSTG,10 Address module's dynamic storage
BPEUXCSV SERVICECODE=BPEUXCSV_NSCREATE, Create named stg X
PARMS=(NSNAME,ZZZ_EXIT_AREA_L), for the exits X
TOKEN=UXPL_CSTOKENP, X
SL=UXCSVPL
LTR 15,15 Did NSCreate work?
BNZ ERROR1 No, go handle error
LR 9,1 Yes, named storage ptr to R9
USING ZZZ_EXIT_AREA,9 Address using "ZZZ" DSECT
MVC ZZZ_TABLE_NAME,TBLNAME Set name of table module
BPEUXCSV SERVICECODE=BPEUXCSV_LOAD, Load the table X
PARMS=(TBLNAME,0,0), module for the X
TOKEN=UXPL_CSTOKENP, exits X
SL=UXCSVPL
LTR 15,15 Did LOAD work?
BNZ ERROR2 No, go handle error
ST 1,ZZZ_TABLE_ADDR Yes, save table ptr in named stg
. . . Do any other init exit functions
XR 15,15 Set zero return code
L 13,4(,13) Back up to caller's save area
L 14,12(,13) Restore caller's R14
LM 0,12,20(13) Restore caller's R0-R12
BR 14 Return to caller
DROP 9,10,11,12 Release USING registers
NSNAME DC CL16'ZZZ_EXIT_AREA ' Const for named storage
TBLNAME DC CL8'ZZZUXTB0' Const for table module name
LTORG ,
DYNSTG DSECT , Dynamic storage DSECT
UXCSVPL DS XL(BPEUXCSV_MAXSL) Space for BPEUXCSV parmlist
. . . Other dynamic storage fields
BPEUXPL FUNC=DSECT Include user exit parmlist
BPEUXCSV FUNC=DSECT Include BPEUXCSV symbols
END Sample processing exit routine
The processing exit routine obtains the address of the table module that was loaded by the initialization exit routine. For optimum performance, the processing exit routine uses the first word of the static work area that BPE passes to save the address of the shared storage area.
On entry, the processing exit routine checks this word of storage. If this word is non-zero, the processing routine uses this address as the shared storage area pointer. If the first word is zero, the processing exit routine invokes the named storage retrieve service to get the address of the shared storage. The processing exit routine then saves the address in the static storage area. This technique minimizes the number of BPE requests for callable services that this exit routine must make (because it needs to do the retrieve only once; on subsequent calls, the address of the shared storage area is available in the static work area).
A sample processing exit routine that performs these functions is shown in the following example.
PROCEXIT CSECT ,
PROCEXIT AMODE 31
PROCEXIT RMODE ANY
STM 14,12,12(13) Save caller's registers
LR 12,15 Move module entry pt to R12
USING PROCEXIT,12 Address module base register
L 13,8(,13) Chain to 2nd provided save area
LR 11,1 Move exit parmlist to R11
USING BPEUXPL,11 Address std BPE user exit PL
L 10,UXPL_DYNAMICWAP Get 512-byte dynamic storage ptr
USING DYNSTG,10 Address module's dynamic storage
L 9,UXPL_STATICWAP Get 256-byte static storage ptr
ICM 8,15,0(9) Is shared stg ptr set?
BNZ GOTSHRD Yes, continue
BPEUXCSV SERVICECODE=BPEUXCSV_NSRETRIEVE, Get named stg addr X
PARMS=(NSNAME), X
TOKEN=UXPL_CSTOKENP, X
SL=UXCSVPL
LTR 15,15 Did NSRetrieve work?
BNZ ERROR1 No, go handle error
LR 8,1 Yes, set shrd stg ptr in R8
ST 8,0(,9) Save in static stg for next time
GOTSHRD DS 0H
USING ZZZ_EXIT_AREA,8 Address using "ZZZ" DSECT
L 7,ZZZ_TABLE_ADDR Get table address
. . . Do process exit functions
XR 15,15 Set zero return code
L 13,4(,13) Back up to caller's save area
L 14,12(,13) Restore caller's R14
LM 0,12,20(13) Restore caller's R0-R12
BR 14 Return to caller
DROP 8,10,11,12 Release USING registers
NSNAME DC CL16'ZZZ_EXIT_AREA ' Const for named storage
LTORG ,
DYNSTG DSECT , Dynamic storage DSECT
UXCSVPL DS XL(BPEUXCSV_MAXSL) Space for BPEUXCSV parmlist
. . . Other dynamic storage fields
BPEUXPL FUNC=DSECT Include user exit parmlist
BPEUXCSV FUNC=DSECT Include BPEUXCSV symbols
ENDSample termination exit routine
The termination exit routine locates the shared storage area, deletes the loaded table module using the name that was saved in the shared storage area, and then destroys the shared area.
A sample termination exit routine that performs these functions is shown in the following example.
TERMEXIT CSECT ,
TERMEXIT AMODE 31
TERMEXIT RMODE ANY
STM 14,12,12(13) Save caller's registers
LR 12,15 Move module entry pt to R12
USING TERMEXIT,12 Address module base register
L 13,8(,13) Chain to 2nd provided save area
LR 11,1 Move exit parmlist to R11
USING BPEUXPL,11 Address std BPE user exit PL
L 10,UXPL_DYNAMICWAP Get 512-byte dynamic storage ptr
USING DYNSTG,10 Address module's dynamic storage
BPEUXCSV SERVICECODE=BPEUXCSV_NSRETRIEVE, Get named stg addr X
PARMS=(NSNAME), X
TOKEN=UXPL_CSTOKENP, X
SL=UXCSVPL
LTR 15,15 Did NSRetrieve work?
BNZ ERROR1 No, go handle error
LR 8,1 Yes, set shrd stg ptr in R8
USING ZZZ_EXIT_AREA,8 Address using "ZZZ" DSECT
BPEUXCSV SERVICECODE=BPEUXCSV_DELETE, Delete table X
PARMS=(ZZZ_TABLE_NAME), module X
TOKEN=UXPL_CSTOKENP, X
SL=UXCSVPL
LTR 15,15 Did DELETE work?
BNZ ERROR2 No, go handle error
BPEUXCSV SERVICECODE=BPEUXCSV_NSDESTROY, Destroy named stg X
PARMS=(NSNAME), X
TOKEN=UXPL_CSTOKENP, X
SL=UXCSVPL
DROP 8 R8 no longer is "ZZZ" area
LTR 15,15 Did NSDestroy work?
BNZ ERROR3 No, go handle error
. . . Do other term exit functions
XR 15,15 Set zero return code
L 13,4(,13) Back up to caller's save area
L 14,12(,13) Restore caller's R14
LM 0,12,20(13) Restore caller's R0-R12
BR 14 Return to caller
DROP 10,11,12 Release USING registers
NSNAME DC CL16'ZZZ_EXIT_AREA ' Const for named storage
LTORG ,
DYNSTG DSECT , Dynamic storage DSECT
UXCSVPL DS XL(BPEUXCSV_MAXSL) Space for BPEUXCSV parmlist
. . . Other dynamic storage fields
BPEUXPL FUNC=DSECT Include user exit parmlist
BPEUXCSV FUNC=DSECT Include BPEUXCSV symbols
END