A Service Request Block (SRB) defines a dispatchable unit of work (Service Routine) in MVS. A dispatchable unit of work is just a fancy way of saying some code that will be run by the dispatcher. A SRB as opposed to a Task Control Block is considered a lightweight task. This simply means it has less overhead associated with creating and dispatching it. It also means that the capabilities are more limited. SRB routines always run in supervisor mode. They may not issue SVC calls and they are nonpreemptiable – meaning a higher priority task cannot preempt them.
SRB routines can be scheduled to run in any Address Space. This makes them very useful for cross memory access in a pre-XA environment. This is exactly what we will ultimately do with our SRB routine. We will schedule it into an address space to allow us to copy local memory into a Common Service Area (CSA) storage (shared memory location).
SRB routines are fairly simple but we do have to be careful since we are writing code that executes in supervisor mode and key zero. When I was initially testing my SRB code I did manage to crash my MVS system a few times due to simple coding mistakes. Fortunately, with Hercules I can IPL and be back up and running quickly. It also helps that I am the only user on the system.
A SRB routine is created by allocating some memory to hold the SRB and then using the SCHEDULE macro to schedule it for execution. The SRB must reside in fixed, commonly-addressable storage.
SRB Control Block
The SRB is defined by the macro IHASRB in SYS1.MACLIB.
SRBSECT DSECT SRB DS 0A SRBID DS CL4 EBCDIC ACRONYM FOR SRB SRBFLNK DS A FORWARD CHAIN FIELD SRBASCB DS A PTR TO ASCB OF ADDRESS SPACE * SRB IS TO BE DISPATCHED TO SRBFLC DS 0CL8 SRB AREA MOVED TO LOW CORE SRBCPAFF DS BL2 CPU AFFINITY MASK SRBPASID DS H PURGEDQ ASID IDENTIFIER SRBPTCB DS A PURGEDQ TCB IDENTIFIER SRBEP DS A ENTRY POINT OF ROUTINE SRBRMTR DS A ADDRESS OF RESOURCE MGR RTN SRBPARM DS A USER PARAMETER SRBSAVE DS A SAVE AREA POINTER SRBPKF DS B PROTECT KEY INDICATION SRBPRIOR DS B PRIORITY LEVEL INDICATION SRBPSYS EQU 0 SYSTEM PRIORITY LEVEL SRBPNONQ EQU 4 NON-QUIESCEABLE PRIORITY DS BL2 RESERVED DS A RESERVED SRBEND EQU * END OF SRB SRBSIZE EQU SRBEND-SRBSECT SIZE OF SRB
SRBID is the eyeball identifier for the block and should contain ‘SRB .
SRBFLNK if the forward chain pointer and should be initialized to binary zeros.
SRBASCB is the address of the ASCB for the address space this SRB is to be dispatched into.
SRBCPAFF is a bitmask that indicates which CPUs may dispatch this SRB. If it is binary zero or all ones the SRB can be dispatched to any CPU. Since MVS 3.8 usually only runs on single CPU systems we can set it to zeros.
SRBPASID may contain a pointer to the ASCB of the address space associated withthis SRB. It may be set to zero if SRBPTCB is also zero otherwise it must be specified.
SRBPTCB may contain a pointer to the TCB associated with this SRB. If it is specified the SRBPASID field must also be set. If these fields are set and a double failure occurs then the associated TCB will be scheduled for abnormal termination (ABEND). A double failure occurs when an error has been trapped by a recovery routine and the recovery routine also fails. Setting this field also allows the SRB to be purged if the associated TCB is terminated. This field may be set to zero if not needed.
SRBEP is the entry point of the SRB routine.
SRBRMTR is the address of a Resource Manager Termination Routine that is called if the SRB is purged before it is scheduled. The RMTR is responsible for any cleanup.
SRBPARM is a fullword parameter value that is passed to the SRB routine when it is dispatched.
SRBSAVE is the address of the status save area and must be initialized to zeros.
SRBPKF specifies the PSW protect key for the SRB routine. The high-order four bits specify the protect key and the low-order four bits must be zero.
SRBPRIOR is the priority of a GLOBAL SRB. GLOBAL SRBs are dispatched at a higher priority than any address space. LOCAL SRBs are dispatched at the priority of the address space they run in but at a higher priority than any TCB. GLOBAL SRBs have an additional priority level that indicates if they are for general system usage or a special priority necessary to quiesce SRBs. A value of zero indicates a general system SRB. A value of four indicates a priority of NONQ (nonquiesceable). We can always set this value to zero.
The additional reserved fields should be set to binary zeros.
CSA – Global Storage
The SRB must be located in Fixed, Global storage. When system storage is allocated by GETMAIN the type of stroage is specified by the subpool. Each system subpool has a set of characteristics associated with it. We will place our SRB in Common Service Area (CSA) stroage. There are several subpools that are associated with CSA, each haveing different characteristics.
Subpool | Pageable | Protect Key | Fetch Protect |
227 | Fixed | Requester Key | Yes |
228 | Fixed | Requester Key | No |
231 | Pageable | Requester Key | Yes |
239 | Fixed | Zero | Yes |
241 | Pageable | User Key | No |
For our purposes we will use subpool 228 as it meets our requirements of being fixed (nonpageable) CSA. Now is proabably a good time to mention that CSA storage is explicitly freed. Once it is allocated by a GETMAIN request it remains allocated untill a FREEMAIN is issued, or until the next IPL. If we allocate CSA we should always have a plan to free it.
APF Authorization
Before we can allocate CSA storage we must be authorized. There are various ways to accomplish this goal. We can run from an authorized library and set the AC flag at linkedit. When the program specified on the EXEC statement in JCL is in an APF authorized library and the AC flag is set in the load module a bit will be set in the JSCB indicating the program is APF authorized. Since I am interested in poking around inside MVS and since I am not too concerned about security on my personal MVS system I have installed a user SVC that will set or clear the APF bit in the JFCB. By calling the SVC to set the bit it appars to MVS that I am running from an APF authorized library.
Once we have the APF bit set we can use the MODESET macro to get into supervisor state and key zero. The MODESET macro has two parameters: MODE= and KEY=. MODE is used to set the PSW to either supervisor state (MODE=SUP) or problem program stat (MODE=PROB). The KEY parameter can be used to set the PSW protection key to zero (KEY=ZERO) or the protect key associated with the TCB (KEY=NZERO). It should be noted that once we are in supervisor mode we can also switch PSW keys using the SPKA privledged instruction.
A Simple Program To Schedule A SRB
We now know enough to write a simple program to schedule a SRB. Our initial SRB routine will not do anything except immediately exit but it will allow us to get through the basics of creating, scheduling and running a SRB routine.
SRB01 CSECT , STM R14,R12,12(R13) LR R12,R15 USING SRB01,R12 * LA R1,SAVEA CHAIN ST R13,4(,R1) ON ST R1,8(,R13) SAVE LR R13,R1 AREA
We begin by saving the caller’s registers, establishing a base register, and setting up a new register save area.
* ****************************************************** * GET INTO SUP STATE, KEY ZERO ****************************************************** * LA R1,=C'AUTH' << GET APF AUTH >> SVC 245 << AC = 1 >> * MODESET MODE=SUP,KEY=ZERO * LA R1,0 << RESET APF AUTH >> SVC 245 << AC = 0 >>
Next I invoke my user SVC to establish APF authorization. On my system I use SVC 245. If you run from an APF authorized library you can remove the SVC 245 calls. If you have a similar SVC installed on your system you may need to modify the code to work.
Next we issue the MODESET macro to set our PSW to supervisor state and protect key zero. Once we are in supervisor state I usually call my SVC 245 to turn off the APF bit in the JSCB. As long as we are in supervisor state or in PSW protect key of 0 through 7 we are considered APF authorized by MVS.
***************************************************** * SET UP CSA STORAGE ***************************************************** * LA R4,WKLEN LENGTH OF WORK AERA * GETMAIN R,LV=(R4),SP=228 * LR R6,R1 USING WKAREA,R6 MAP CSA STORAGE * XC WKAREA(WKLEN),WKAREA
Now that we are in supervisor state and key zero we can allocate our CSA storage. WKLEN is an equated symbol that represents the lenght of our DSECT used to map our CSA storage. We can then issue a GETMAIN request for subpool 228 to get CSA storage that is globally accessable from all address spaces. This storage is fixed, non-pageable and will not be fetch protected. We then save the address of our CSA storage in register 6 and map it with our DSECT. Finally the storage area is cleared to binary zeros using the exclusive or characters instruction.
WKAREA DSECT , SRBAREA DS CL(44) SRBCODE DS CL(ENDSRTN-SRBRTN) * * WKLEN EQU *-WKAREA
Here is our DSECT for our common storage. First we need 44 bytes to contain the SRB control block. Next we need a place to copy our SRB routine executable code into CSA. Since we ultimately plan to schedule a SRB into another address space the code in our private storage area would be unavailable.
* L R8,CVTPTR CVT ADDRESS L R8,0(,R8) PSATNEW L R8,12(,R8) CURRENT ASCB (OURS)
Next we get the address of the ASCB for the address space we are currently located. First we get the address of the CVT which is always located in low memory at location X’10’ . I often simply would code L R8,16 but here I use the label generated by the CVT mapping macro. The first word of the CVT points to an area that contains the address of our TCB and our ASCB that is currently dispatched. We get the ASCB address in register 8 and save it for later.
LA R2,SRBCODE SRB CODE IN CSA LA R3,ENDSRTN-SRBRTN LENGTH OF SRB ROUTINE LA R4,SRBRTN MODEL CODE TO COPY LR R5,R3 MVCL R2,R4 COPY INTO CSA
Now we need to copy our SRB routine into CSA. Here it set up the registers and use the MVCL instruction to copy the code. You could also use one or more MVC instructions depending on the length of the code. The advantage of using MVCL is we don’t have to keep checking the size of the SRB executable routine and add an additional MVC instruction when we exceede a 256 byte boundary.
LA R7,SRBAREA SRB STORAGE AREA USING SRB,R7 XC 0(SRBSIZE,R7),0(R7) CLEAR
Next I clear the SRB control block to binary zeros. This is not really necessary since I cleared the entire area after the GETMAIN but I include it here so when we later reuse the SRB control block I am reminded to clear it first.
MVC SRBID,=CL4'SRB ' SRB ID * ST R8,SRBASCB TARGET ASCB TO SCHEDULE TO * * LA R1,SRBCODE SRB ENTRY POINT ST R1,SRBEP * LA R1,SRBCLEAN-SRBRTN(,R1) SRB PURGE ROUTINE ST R1,SRBRMTR * LA R1,0 PARM LIST ST R1,SRBPARM
Now we can fill in the required fileds for the SRB control block. First we move in the eyeball identifier ‘SRB ‘. For now we will schedule the SRB into our own address space. We set the entry point address to the location in CSA where we copied the SRB routine executable code. We also set the entry point of a purge routnie. Since our SRB routine will immediately exit we don’t need to pass any parameters for now. This completes our SRB control block and it is now ready for scheduling.
************************************************* * SCHEDULE SRB AND WAIT ************************************************* * SCHEDULE SRB=(R7),SCOPE=LOCAL
We can now use the SCHEDULE macro to schedule to add our SRB to the dispatcher queue. To issue the SCHEDULE macro we must be in key zero and supervisor state. We must also include the mapping macros for the CVT and SRB data areas. We must provide the address of our SRB in CSA and we set our priority to LOCAL or address space priority.
* STIMER WAIT,DINTVL=WAITTIME WAIT FOR SRB TO COMPLETE *
Now we can issue a WAIT macro to pause and give the SRB time to execute. Since our SRB does not do anything we don’t have any indication of when it is complete. By waiting 10 seconds (which is a very long time) our SRB should have plenty of time to be dispatched and to complete execution before we clean up.
DS 0D WAITTIME DC C'00001000' WAIT 10 SECONDS * HHMMSSTH
Our wait time value must be in a double word in unpacked format.
CLEANUP DS 0H LA R4,WKLEN * FREEMAIN R,LV=(R4),A=(R6),SP=228 * MODESET MODE=PROB,KEY=NZERO
When we exit from our wait we can cleanup and exit. First it is important to free the CSA stroage we allocated. If we fail to free the CSA it will remain allocated until the next IPL. Failure to free CSA storage can result if running out of CSA and make an IPL necessary. It is always good practice to make every effort to clean up any system resources we use. For production quality code we would include some error recovery code to free the CSA in the event our program abnormally terminated. Since we are testing in a non-production environment it is not a necessity.
As part of our cleanup we also reset the PSW back to problem program state and TCB storage protect key.
EXIT DS 0H SLR R15,R15 SET RETURN CODE L R13,4(,R13) UNCHAIN SAVE AREA L R14,12(,R13) RESTORE R14 LM R0,R12,20(R13) RESTORE REGS 0-12 BR R14 RETURN TO CALLER
Now all that is left is to restore the caller’s registers and exit back to the caller.
Constants and Data Areas
We need to define one constant, our wait time. We also need to generate any literal constants using LTORG. We also have one data area, our register save area.
DS 0D WAITTIME DC C'00001000' WAIT 10 SECONDS * HHMMSSTH * * LTORG , * * SAVEA DS 18F SAVE AREA
SRB Routine Code
Now all we need is the code for the SRB routine. For now we can keep it very simple and as soon as our SRB routine is dispatched it will immediately exit.
SRBRTN DS 0H LR R6,R15 SRB ROUTINE EP USING SRBRTN,R6 * LR R4,R1 SAVE PARM REGISTER * LR R5,R14 SAVE RETURN ADDRESS * BR R5 DONE - EXIT * * SRBCLEAN DS 0H SRB PURGE ROUTINE BR R14 * * LTORG , * * DROP R6 * * ENDSRTN EQU *
CSA Storage Area Dsect
Now we need our DSECT that maps our CSA storage.
WKAREA DSECT , SRBAREA DS CL(44) SRBCODE DS CL(ENDSRTN-SRBRTN) * * WKLEN EQU *-WKAREA
Finishing Touches
All that is missing to complete our program is a few system data area mapping macros and the register equates.
* PRINT OFF CVT DSECT=YES IHASRB , IHAPSA , * * R0 EQU 0 R1 EQU 1 R2 EQU 2 R3 EQU 3 R4 EQU 4 R5 EQU 5 R6 EQU 6 R7 EQU 7 R8 EQU 8 R9 EQU 9 R10 EQU 10 R11 EQU 11 R12 EQU 12 R13 EQU 13 R14 EQU 14 R15 EQU 15 * END ,
Now we can compile and link edit our program. When we run the program it should wait for ten seconds and then exit.
JOB 6757 $HASP373 SRB01 STARTED - INIT 12 - CLASS A - SYS TCS3 JOB 6757 15.42.10 0.00.10 0.00.00 0000 SRB01 MVSSP JOB 6757 15.42.10 0.00.10 0.00.00 0000 SRB01 ######## JOB 6757 $HASP395 SRB01 ENDED
If we did something wrong it is very possible running this program will crash MVS. If that happens we can simply restart with an IPL and try to fix the problem.