{"id":24,"date":"2013-01-05T01:01:58","date_gmt":"2013-01-05T07:01:58","guid":{"rendered":"http:\/\/tommysprinkle.com\/mvssp\/?p=24"},"modified":"2013-05-22T08:35:37","modified_gmt":"2013-05-22T13:35:37","slug":"srb-error-recovery","status":"publish","type":"post","link":"https:\/\/tommysprinkle.com\/mvssp\/2013\/01\/05\/srb-error-recovery\/","title":{"rendered":"SRB Error Recovery"},"content":{"rendered":"<p>Now that we can schedule a SRB into another address space and use cross memory post to synchronize between the scheduling task and the SRB it is almost time to start writing some more complex code in our SRB routine. Before doing this we should probably consider what happens when our SRB routine encounters an error.<\/p>\n<p>A Simple Test<\/p>\n<p>We can start with a simple experiment to see what happens when our SRB routine fails.\u00a0 All we need to do is cause an error condition which can easily be done by inserting the line:<\/p>\n<pre>         DC    X'0000'<\/pre>\n<p>into our SRB routine. It can be placed anywhere before the BALR to the POST routine. I placed it immediately after the LR to save the address of the parameter list.<\/p>\n<p>When our program is compiled, link edited, and run we see nothing happen.\u00a0 The SRB is scheduled, the task waits on the ECB, the SRB is dispatched and immediately fails with a S0C1 (or program interruption x&#8217;01&#8217; to be more specific) and the ECB is never posted.\u00a0 The scheduling task has no way of knowing the SRB failed and continues to wait.\u00a0 If the job is not cancelled by an operator command it should eventually fail with a S522 ABEND.<\/p>\n<p>This is probably not the behaviour we want when our SRB routine fails.\u00a0 It would probably be better if the scheduling task failed when the SRB routine failed. This can be done with just a few more lines of code.\u00a0 There are two fields in the SRB control block we need to fill in.\u00a0 SRBPASID is a two byte field where we place the ASID (not the ASCB address) of the task associated with the SRB.\u00a0 SRBPTCB is a pointer to the TCB associated with the SRB.\u00a0 When these fields are specified and the SRB routine fails the failure will be propagated back to the TCB.<\/p>\n<p>We already have the address of our ASCB so it is pretty simple to get the ASID value.\u00a0 It is also pretty simple to get the address of our TCB at the same time we are finding our ASCB address.<\/p>\n<pre>          L     R8,CVTPTR          CVT ADDRESS         \r\n          L     R8,0(,R8)          PSATNEW             \r\n          L     R10,4(,R8)         CURRENT TCB ADDRESS  &lt;------ Insert This Line\r\n          L     R8,12(,R8)         CURRENT ASCB (OURS)<\/pre>\n<p>Now register 10 will contain the address of our TCB.<\/p>\n<pre>         ST    R10,SRBPTCB        PURGE TCB ADDRESS       \r\n         SLR   R1,R1                                      \r\n         ICM   R1,B'0011',ASCBASID-ASCB(R8)  GET OUR ASID \r\n         STH   R1,SRBPASID        PURGE ASID<\/pre>\n<p>By adding the above lines in our SRB setup code we now should be able to detect SRB errors.\u00a0 Now we assemble, link edit, and run our test program.<\/p>\n<pre>JOB 6771  $HASP100 SRB03    ON INTRDR      RUN TEST PGM            \r\nJOB 6771  $HASP373 SRB03    STARTED - INIT 12 - CLASS A - SYS TCS3 \r\nJOB 6771  IEF450I SRB03 MVSSP - ABEND S0C1 U0000 - TIME=08.33.41   \r\nJOB 6771   8.33.42   0.00.00   0.00.00  S0C1   SRB03     MVSSP     \r\nJOB 6771   8.33.42   0.00.00   0.00.00  S0C1   SRB03     ########  \r\nJOB 6771  $HASP395 SRB03    ENDED<\/pre>\n<p>And there we are!\u00a0 When the SRB routine abnormally terminates our job ABENDs with a SoC1.\u00a0 This is much better than waiting for the eventual S522 ABEND.<\/p>\n<h2>Functional Recovery Routines<\/h2>\n<p>Now we can deal with how to recover from an error while running a SRB routine.\u00a0 We can&#8217;t use ESTAE to trap errors since ESTAE doesn&#8217;t work when running under a SRB.\u00a0 Instead we have to use a Functional Recovery Routine (FRR) to trap the error.\u00a0 If you are familiar with ESTAE then using a FRR should be pretty familiar.\u00a0 When a FRR has been established and and error occurs, the FRR will be given control and then decide what action to take.<\/p>\n<p>A FRR is established using the SETFRR macro.<\/p>\n<pre>         SETFRR A,FRRAD=(R3),WRKREGS=(R7,R8),RELATED=(DELETE)<\/pre>\n<p>This will add a FRR, the address of the FRR is contained in register 3, and we supply two work registers to the macro (registers 7 and 8).\u00a0 The RELATED parameter is provided to allow a method of associating comments directly with the macro.\u00a0 It must be specified but the value doesn&#8217;t matter to the expansion of the macro.\u00a0 To use this macro we must include the mapping macros IHAFRRS and IHAPSA.<\/p>\n<p>Now when an error occurs during execution of our SRB the FRR will be given control.\u00a0 On entry to the FRR register 0 contains the address of a 200 byte FRR work area.\u00a0 Register 1 contains the address of the SDWA.\u00a0 Unlike an ESTAE routine where there are conditions where a SDWA may not be available, a SDWA is always passed to the FRR.<\/p>\n<p>Here is a simple FRR that will resume execution of our SRB at a recovery point.\u00a0 This type of recovery is good when we want to try an action that may fail and recover from that failure.<\/p>\n<pre>FRREXIT  DS    0H\r\n         USING FRREXIT,R15\r\n*\r\n         L     R7,RETADDR\r\n         SETRP RC=4,RETREGS=YES,RETADDR=(R7)\r\n         BR    R14\r\n*\r\nRETADDR  DC    A(0)<\/pre>\n<p>We use the SETRP macro to set recovery options in the SDWA.\u00a0 A return code of 4 specifys a retry action.\u00a0 We indicate that the registers should be restored and that the retry address is contained in register 7.\u00a0 We then return using register 14 to initiate the retry.<\/p>\n<p>Note that the retry address (RETADDR) must be set before establishing the FRR environment.\u00a0 We can&#8217;t specify it using something like A(RETRY) because we relocate the SRB code from our private area into CSA.\u00a0 Instead we need to use something like this.<\/p>\n<pre>        LA    R1,RETRY\r\n        ST    R1,RETADDR<\/pre>\n<p>We now have enough to implement a FRR in our SRB routine.\u00a0 Here is the updated SRB routine.<\/p>\n<pre>SRBRTN   DS    0H                                            \r\n         LR    R6,R15             SRB ROUTINE EP             \r\n         USING SRBRTN,R6                                     \r\n*                                                            \r\n         LR    R4,R1              SAVE PARM REGISTER         \r\n         USING PARMLIST,R4                                   \r\n*                                                            \r\n         LR    R9,R14             SAVE RETURN ADDRESS        \r\n*                                                            \r\n         LA    R1,RTRYRTN         ADDRESS OF RETRY POINT     \r\n         ST    R1,RETADDR         SAVE FOR FRR               \r\n*                                                            \r\n         LA    R3,FRREXIT         ADDRESS OF FRR             \r\n         SETFRR A,FRRAD=(R3),WRKREGS=(R7,R8),RELATED=(DELETE)\r\n*                                                            \r\n         LA    R10,X'41'          POST                       \r\n         SLL   R10,24                 COMPLETION CODE        \r\n*                                                            \r\n         DC    X'0000'            SOC1 ABEND                 \r\n*                                                            \r\n         LA    R10,X'7F'          POST                       \r\n         SLL   R10,24                 COMPLETION CODE        \r\n*                                                            \r\nRTRYRTN  DS    0H                                            \r\n         SETFRR D,WRKREGS=(R7,R8),RELATED=(ADD)              \r\n*                                                            \r\n         L     R11,WAITECB        ECB ADDRESS                \r\n         LA    R1,X'80'           SET                        \r\n         SLL   R1,24                 HIGH-ORDER              \r\n         OR    R11,R1                          BIT           \r\n*                                                            \r\n         LA    R12,POSTERR        ERROR ROUTINE              \r\n         L     R13,WAITASCB       ASCB ADDRESS               \r\n*                                                            \r\n         L     R15,CVTPTR         CVT ADDRESS                \r\n         L     R15,CVT0PT01-CVTMAP(,R15)   POST BRANCH-ENTRY \r\n         BALR  R14,R15                                       \r\n*                                                            \r\n*                                                            \r\n         BR    R9                  DONE - EXIT               \r\n*                                                        \r\nSRBCLEAN DS    0H                  SRB PURGE ROUTINE     \r\n         XC    0(SRBSIZE,R1),0(R1)                       \r\n         BR    R14                                       \r\n*                                                        \r\n*                                                        \r\nPOSTERR  DS    0H                  POST ERROR ROUTINE    \r\n         BR    R14                                       \r\n*                                                        \r\n*                                                        \r\nFRREXIT  DS    0H                                        \r\n         USING FRREXIT,R15                               \r\n*                                                        \r\n         L     R7,RETADDR                                \r\n         SETRP RC=4,RETREGS=YES,RETADDR=(R7)             \r\n         BR    R14                                       \r\n*                                                        \r\nRETADDR  DC    A(0)                                      \r\n*                            \r\n         LTORG ,             \r\n*                            \r\n*                            \r\n         DROP  R4,R6         \r\n*                            \r\n*                            \r\nENDSRTN  EQU   *<\/pre>\n<p>Notice we included a SETFRR macro with the D or delete option to remove our FRR environment once we were past the\u00a0 section of code where we wanted to trap errors.\u00a0 If we did not delete our FRR and an error occured after our retry point a endless loop could occur.<\/p>\n<h2>Checking The Post Code<\/h2>\n<p>Now we have two different post codes used by our SRB routine.\u00a0 A value of x&#8217;7F000000&#8242; indicates success and a value of x&#8217;41000000&#8242; indicates a failure.\u00a0 There is nothing magic about these codes and they only have meaning withing our program.\u00a0 We can update our scheduling program to report on the post code status.<\/p>\n<pre>         CLI   LOCALECB,X'7F'     CHECK FOR GOOD COMPLETION CODE \r\n         BE    SUCCESS                                           \r\n*                                                                \r\n         CLI   LOCALECB,X'41'     CHECK FOR FAIL COMPLETION CODE \r\n         BE    FAIL                                              \r\n*                                                                \r\n         WTO   '*** UNKNOWN POST CODE ***',ROUTCDE=(1,11)        \r\n         B     CLEANUP                                           \r\n*                                                                \r\n*                                                                \r\nSUCCESS  DS    0H                                                \r\n         WTO   '*** SUCCESS POST CODE ***',ROUTCDE=(1,11)        \r\n         B     CLEANUP                                           \r\n*                                                                \r\n*                                                                \r\nFAIL     DS    0H                                                \r\n         WTO   '*** FAIL POST CODE ***',ROUTCDE=(1,11)           \r\n         B     CLEANUP<\/pre>\n<p>Now with these updates in place we can assemble, linkedit and execute our program.<\/p>\n<pre>JOB 6775  $HASP100 SRB04    ON INTRDR      RUN TEST PGM              \r\nJOB 6775  $HASP373 SRB04    STARTED - INIT 12 - CLASS A - SYS TCS3   \r\nJOB 6775  *** FAIL POST CODE ***                                     \r\nJOB 6775   7.39.43   0.00.00   0.00.00  0000   SRB04     MVSSP       \r\nJOB 6775   7.39.43   0.00.00   0.00.00  0000   SRB04     ########    \r\nJOB 6775  $HASP395 SRB04    ENDED<\/pre>\n<p>We can remove our abend by commenting out the line<\/p>\n<pre>*-------&gt;DC    X'0000'            SOC1 ABEND<\/pre>\n<p>and then we assemble, linkedit and execute.<\/p>\n<pre>6778  $HASP100 SRB04    ON INTRDR      RUN TEST PGM            \r\n6778  $HASP373 SRB04    STARTED - INIT 12 - CLASS A - SYS TCS3 \r\n6778  *** SUCCESS POST CODE ***                                \r\n6778   8.43.04   0.00.00   0.00.00  0000   SRB04     MVSSP     \r\n6778   8.43.04   0.00.00   0.00.00  0000   SRB04     ########  \r\n6778  $HASP395 SRB04    ENDED<\/pre>\n<p>An this proves we can capture and report on an error contition in our SRB routine.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Now that we can schedule a SRB into another address space and use cross memory post to synchronize between the scheduling task and the SRB it is almost time to start writing some more complex code in our SRB routine. Before doing this we should probably consider what happens when our SRB routine encounters an &#8230;<\/p>\n<p><a href=\"https:\/\/tommysprinkle.com\/mvssp\/2013\/01\/05\/srb-error-recovery\/\" class=\"more-link\">Continue reading &lsquo;SRB Error Recovery&rsquo; &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[5],"tags":[],"class_list":["post-24","post","type-post","status-publish","format-standard","hentry","category-srb-error-recovery-frr"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3x7AW-o","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/posts\/24","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/comments?post=24"}],"version-history":[{"count":10,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/posts\/24\/revisions"}],"predecessor-version":[{"id":67,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/posts\/24\/revisions\/67"}],"wp:attachment":[{"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/media?parent=24"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/categories?post=24"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/tags?post=24"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}