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.
Important: These user exit routines are presented here for example purposes only. These examples should not be assumed to be usable exit routines.

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
          END

Sample 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