SRB – Service Request Block Overview

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.