{"id":19,"date":"2013-01-03T01:01:10","date_gmt":"2013-01-03T07:01:10","guid":{"rendered":"http:\/\/tommysprinkle.com\/mvssp\/?p=19"},"modified":"2013-05-22T08:35:17","modified_gmt":"2013-05-22T13:35:17","slug":"cross-memory-post","status":"publish","type":"post","link":"https:\/\/tommysprinkle.com\/mvssp\/2013\/01\/03\/cross-memory-post\/","title":{"rendered":"Cross Memory Post"},"content":{"rendered":"<p>MVS 3.8 does no have any of the modern cross memory services available software or hardware.\u00a0 In order to communicate between address spaces some system level code must be used.\u00a0 Shared data can be placed into Common Service Area (CSA) storage which can be accessed by all address spaces.\u00a0 If address space A wants to send a message to address space B, address space A could copy the message into an area of CSA known by both A and B.\u00a0 The problem is how address space B knows the data is available.\u00a0 We could loop looking for changes but that would consume a lot of CPU time and would not be very efficient.\u00a0 We could look for changes and upon finding none we could wait some time interval before loooking again.\u00a0 If the delay interval is set too low a large amount of CPU time would still be consumed.\u00a0 If the interval is set too high the program becomes unresponsive since a delay is built in.<\/p>\n<p>The normal way to synchronize between multiple tasks is to use the WAIT\/POST functionality.\u00a0 A task issues a WAIT supervisor call pointing to an Event Control Block (ECB).\u00a0 The signaling task issues a POST supervisor call pointing to the same ECB to wake up the waiting task.\u00a0 This works very well inside a single address space but does not work across address spaces.<\/p>\n<p>MVS does provide a way to POST and ECB in another address space.\u00a0 Is is a little more complicated than simply using the POST macro.\u00a0 In addition to the SVC interface to POST, MVS also provides a Branch Entry.\u00a0 Using Branch Entry is more complicated and requires the caller to be in supervisor mode and key zero.\u00a0 It does have the advantage of allowing us to post and ECB in an address space other than our own.<\/p>\n<p>Below is a summary of the registers used as input for Branch Entry POST.<\/p>\n<pre>R10 - POST Completion Code (to be placed into ECB)\r\nR11 - ECB Address (high order bit of register must be set to X'80')\r\nR12 - Error Return Address\r\nR13 - ASCB Address of address space containing ECB\r\nR14 - Linkage Return Address\r\nR15 - Entry Point (CVT0PT01)<\/pre>\n<p>The high order bit of register 11 determines if the request is a cross memory post.\u00a0 When calling the Branch Entry POST routine for a non-cross memory post we must hold the Local Lock.\u00a0 For a cross memory post we do not have to hold any locks but we must be aware that the contents all registers except register 9 will be destroyed.<\/p>\n<h2>SRB Cross Memory Post<\/h2>\n<p>We now have enough to modify our simple SRB routine to post an ECB to signal a waiting task in another address space.\u00a0 We will begin by expanding our CSA storage map to include a parmameter list to be passed to the SRB routine.<\/p>\n<pre>WKAREA   DSECT ,                                            \r\nPARMLIST DS    0F            PARAMETER LIST FOR SRB ROUTINE \r\nWAITECB  DS    A             ADDRESS OF LOCAL ECB                            \r\nWAITASCB DS    A             ADDRESS OF WAITING ASCB        \r\n*                                                           \r\nSRBAREA  DS    CL(44)                                       \r\nSRBCODE  DS    CL(ENDSRTN-SRBRTN)                           \r\n*                                                           \r\n*                                                           \r\nWKLEN    EQU   *-WKAREA<\/pre>\n<p>We will pass two parameters to the SRB routine. The first is the address of the waiting ECB located in the private area and the second is the address of the ASCB for the waiting address space.\u00a0 When our SRB routine is dispatched the address of the parmaeter list will be contained in register 1.<\/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*                                                     \r\n         LA    R10,X'7F'          POST                \r\n         SLL   R10,24                 COMPLETION CODE \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\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\n         LTORG ,<\/pre>\n<p>The first thing we do is copy the address of the parm list into register 4.\u00a0 Next we save the return address in register 9 (this is because register 9 is the only register preserved when we call Branch Entry POST).\u00a0 Next we set our post code into register 10.\u00a0 It can be anything we want so I chose X&#8217;7F000000&#8242; but it really doesn&#8217;t matter. Next we load the address of the ECB into register 11 and set the high order bit to X&#8217;80&#8217; to indicate a cross memory post.\u00a0 The address of our Post Error Routine goes into R12 and the address of the ASCB for the task that is waiting goes into R13.\u00a0 All the remains is to get the address of the Branch Entry Post routine into register 15 and then call it.\u00a0 Upon return the contents of all registers except R9 will be lost.\u00a0 Since all we need to do is exit all we need is the return address we saved in R9.\u00a0 We also added our Post Error Routine which immediately returns to the caller.<\/p>\n<p>That&#8217;s it for the SRB routine but we still need some changes in our code that sets up and schedules the SRB.<\/p>\n<pre>                                                               \r\n         L     R9,CVTPTR               CVT ADDRESS               \r\n         L     R9,CVTASVT-CVTMAP(,R9)  ASVT ADDRESS              \r\n         L     R9,ASVTENTY-ASVT(,R9)   FIRST ASCB POINTER        \r\n         L     R9,4(,R9)               ASCB FOR ASID=0002 (JES2)<\/pre>\n<p>We could continue to schedule the SRB into our own address space and call the cross memory post routine but we really should schedule the SRB routine into a different address space so we really are doing a cross memory post.\u00a0 I chose to use the JES2 address space since it is always active and I can be pretty confident it will be in ASID x&#8217;0002&#8242;.\u00a0 Again it really doesn&#8217;t matter for now and any valid address space could be used.\u00a0 To find the JES2 ASCB we get the Address Space Vector Table address from the CVT.\u00a0 We then offset to the list of pointers to ASCBs.\u00a0 The first entry is ASID x&#8217;0001&#8242;, the second ASID x&#8217;002&#8242;, and so on.\u00a0 We take the address of the second ASCB which should be the addres space for JES2.\u00a0 We save this address in R9.<\/p>\n<pre>         ST    R9,SRBASCB         TARGET ASCB TO SCHEDULE TO<\/pre>\n<p>Next we need to place the address of the ASCB\u00a0 for JES2 into the SRB so it will be scheduled there.<\/p>\n<pre>                                                               \r\n         LA    R1,PARMLIST                   PARM LIST               \r\n         ST    R1,SRBPARM                                            \r\n*                                                                    \r\n         ST    R8,WAITASCB        SAVE OUR ASCB ADDRESS INTO PARMLIST\r\n*                                                                    \r\n         LA    R1,LOCALECB                                           \r\n         ST    R1,WAITECB<\/pre>\n<p>Now we have to set up the parameter list for the SRB routine.\u00a0 We place the pointer to the parm list into the SRB control block.\u00a0 The address of the ASCB for our address space goes into the parameter list along with the address of an ecb.<\/p>\n<pre>         WAIT  1,ECB=LOCALECB     WAIT FOR SRB TO COMPLETE<\/pre>\n<p>Now instead of setting a delay we wait for our ECB to be posted by the SRB routine.<\/p>\n<pre>LOCALECB DC    F'0'<\/pre>\n<p>Here is the ECB we will wait on (located in our private storage).<\/p>\n<pre>         IHAASVT ,<\/pre>\n<p>Finally we need to include the mapping macro for the ASVT. With this we are done and our program can be compiled, link edited and we can run it. If everything goes as planned it should run very quickly.<\/p>\n<pre>JOB 6755  $HASP373 SRB02    STARTED - INIT 12 - CLASS A - SYS TCS3 \r\nJOB 6755  15.39.08   0.00.00   0.00.00  0000   SRB02     MVSSP     \r\nJOB 6755  15.39.08   0.00.00   0.00.00  0000   SRB02     ########  \r\nJOB 6755  $HASP395 SRB02    ENDED<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>MVS 3.8 does no have any of the modern cross memory services available software or hardware.\u00a0 In order to communicate between address spaces some system level code must be used.\u00a0 Shared data can be placed into Common Service Area (CSA) storage which can be accessed by all address spaces.\u00a0 If address space A wants to &#8230;<\/p>\n<p><a href=\"https:\/\/tommysprinkle.com\/mvssp\/2013\/01\/03\/cross-memory-post\/\" class=\"more-link\">Continue reading &lsquo;Cross Memory Post&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":[4],"tags":[],"class_list":["post-19","post","type-post","status-publish","format-standard","hentry","category-cross-memory-post"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3x7AW-j","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/posts\/19","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=19"}],"version-history":[{"count":6,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/posts\/19\/revisions"}],"predecessor-version":[{"id":66,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/posts\/19\/revisions\/66"}],"wp:attachment":[{"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/media?parent=19"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/categories?post=19"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tommysprinkle.com\/mvssp\/wp-json\/wp\/v2\/tags?post=19"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}