home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Kernel / Em / invoke.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-17  |  55.5 KB  |  1,639 lines

  1.  
  2. /* Copyright 1986 Eric Jul.  May not be used for any purpose without    */
  3. /* written permission from the author.                            */
  4. /* The Emerald kernel for the Emerald programming language.             */
  5.  
  6. /* Version 5.2 started 1986-05-21, eric; forked off from kOps.c         */
  7.  
  8. /* This file contains the implementation of the Emerald kernel invoke   */
  9. /* operations as defined in the Kernel Interface Specification.         */
  10.  
  11. #include <stdio.h>
  12.  
  13. #include "Kernel/h/system.h"
  14. #include "Kernel/h/assert.h"
  15. #include "Kernel/h/macros.h"
  16. #include "Kernel/h/errMsgs.h"
  17. #include "Kernel/h/mmCodes.h"
  18. #include "Kernel/h/emTypes.h"
  19. #include "Kernel/h/timerTypes.h"
  20. #include "Kernel/h/kmdTypes.h"
  21. #include "Kernel/h/kEvents.h"
  22. #include "Kernel/h/emCodes.h"
  23. #include "Kernel/h/mmMsgTypes.h"
  24. #include "Kernel/h/lmTypes.h"
  25. #include "Kernel/h/emkDefs.h"
  26. #include "Kernel/h/lmCodes.h"
  27. #include "Kernel/h/hotsTypes.h"
  28. #include "Kernel/h/map.h"
  29. #include "Kernel/h/set.h"
  30. #include "Kernel/h/utils.h"
  31.  
  32. extern void                 OTInsert(), schedule();
  33. extern SSPtr                NewProcess(), NewStackSegment(),
  34.                 StdStackSegment();
  35. extern void                 StartProcessAtAddr(), DiscardStackSegment();
  36. extern ODP                  OTLookup();
  37. extern EmLocation           thisNodeLocation;
  38. extern SSPtr                preemptRunning();
  39. extern CodeAddr             FindEntryPointForOp();
  40. extern MoveMask            FindReturnByMoveMask();
  41. extern void                 fail(), unavail();
  42. extern void                 AddToTTable(), DigestTable(), AddVarToTTable(),
  43.                             MoveVarToTTable();
  44. extern Boolean              LoadRequest();
  45. extern void                 StartLocate();
  46. extern void                 TraverseAndTranslate(), DoTranslate();
  47. extern void                 MoveARs(), MoveToTTable();
  48.  
  49. /* Counters, see measure.c */
  50. extern int            cINVK_InvokeFaults, cINVK_RemoteInvokes;
  51. extern int            cINVK_RemoteReturns, cINVK_RemoteNoSuccessReturns;
  52. extern int            cINVK_RemoteInvokesBytesSent;
  53. extern int            cINVK_RemoteReturnsBytesSent;
  54. extern int            cINVK_RemoteInvokesPacketsSent;
  55. extern int            cINVK_RemoteReturnsPacketsSent;
  56. extern int            cINVK_CallByMovesDone;
  57. extern int             cINVK_CallByMovesBytesSent;
  58. extern int            cINVK_CallByVisitsDone;
  59. extern int             cINVK_CallByVisitsBytesSent;
  60. extern int            cINVK_CallByVisitReturnsDone;
  61. extern int            cINVK_CallByVisitReturnBytesSent;
  62. extern int            cINVK_CallByResultMovesDone;
  63. extern int            cINVK_CallByResultBytesSent;
  64.  
  65. /* Forward */
  66. void InvokeReturn();
  67. HResult InvokeCallBack(), InvokeHandlerCallBack();
  68. HResult InvokeReplyCallBack();
  69.  
  70. /************************************************************************/
  71. /*      Invocation                                                      */
  72. /************************************************************************/
  73.  
  74. /************************************************************************/
  75. /*      Ping-pong message protocol:                                     */
  76. /*      Ping messages can be sent kernel-kernel at anytime.             */
  77. /*      The receiving kernel merely responds with a pong message.       */
  78. /*      Usefullness: For testing the connection between kernels.        */
  79. /************************************************************************/
  80.  
  81. int                         nextPingId = 1;
  82. int                         nextLMPingId = 1;
  83. int                         vLMPingDataSize = 8;
  84.  
  85. HResult PingReqHandler(), PongReqHandler();
  86. void RIPing();
  87.  
  88. Map InitiallyMap;           /* Requests waiting for initially done      */
  89. Map FrozenMap;              /* Requests waiting for move or initially   */
  90.  
  91. /************************************************************************/
  92. /*      TryInvoke                                                       */
  93. /************************************************************************/
  94. void TryInvoke(fOpNumber, fAbConPtr, fCalleeGODP, fCallerSSP)
  95. int                fOpNumber;        /* operation number         */
  96. AbConPtr                    fAbConPtr;      /* AbConVector ptr          */
  97. GODP                        fCalleeGODP;    /* target                   */
  98. SSPtr                       fCallerSSP;     /* caller                   */
  99. /* Attempt to do an invocation, checking for all the possible conditions*/
  100. {
  101.     SSAddr                  returnAddr;
  102.     register SSPtr          callerSSP       = fCallerSSP;
  103.  
  104.     if (fCalleeGODP->tag.isResident && (!fCalleeGODP->tag.setUpDone)) {
  105.     register InitiallyReqPtr        p;
  106.     Map                             theMap;
  107.     KMDTrace("Invoke", 3, "%s blocking on invoke of %s\n",
  108.         PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID));
  109.     KMDTrace("Invoke", 3, "Initially not done yet; blocking in %s\n",
  110.         PPSSPlace(callerSSP));
  111.     p                       = mNewRequest(Initially);
  112.     p->calleeGODP           = fCalleeGODP;
  113.     p->theProcess           = callerSSP;
  114.     p->opNumber             = fOpNumber;
  115.     p->theAbConPtr          = fAbConPtr;
  116.         callerSSP->invokePtr    = (GenericPtr) p;
  117.         callerSSP->status.rs    = SSInitiallyWait;
  118.     KMDTrace("LineNumber", 4, "%s waiting for initially done in %s\n",
  119.         PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
  120.     theMap  = (Map) Map_Lookup(InitiallyMap, (int) fCalleeGODP);
  121.     if (IsNIL(theMap)) {
  122.         theMap = Map_Create();
  123.         KMDTrace("Invoke", 4, "Creating initially map for GODP 0x%05x\n",
  124.         fCalleeGODP);
  125.         Map_Insert(InitiallyMap, (int) fCalleeGODP, (int) theMap);
  126.         KMDTrace("FixMe", 5, "Ought to use Set or Bag\n");
  127.     }
  128.     Map_Insert(theMap, (int) p, NULL);
  129.     return;
  130.     }
  131.  
  132.     KMDTrace("Invoke", 3, "%s resident invoke of %s op #%d\n",
  133.     PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID),
  134.     fOpNumber);
  135.  
  136.     /* Prepare the stack */
  137.  
  138.     POPIT(callerSSP->regs.sp, returnAddr);
  139.     PUSHIT(callerSSP->regs.sp, callerSSP->regs.l);
  140.     PUSHIT(callerSSP->regs.sp, callerSSP->regs.g);
  141.     PUSHIT(callerSSP->regs.sp, callerSSP->regs.b);
  142.     callerSSP->regs.l   = (SSAddr) callerSSP->regs.sp;
  143.     PUSHIT(callerSSP->regs.sp, returnAddr);
  144.     PUSHIT(callerSSP->regs.sp, fAbConPtr->opVector[fOpNumber].opAddress);
  145.     callerSSP->regs.b   = fCalleeGODP;
  146.     callerSSP->regs.g   = fCalleeGODP->dataPtr;
  147.     KMDTrace("Invoke", 3, "%s unblocked in %s\n",
  148.     PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
  149.     schedule(callerSSP);
  150. }
  151.  
  152. /************************************************************************/
  153. /*      Invocation (trap on frozen)                                     */
  154. /************************************************************************/
  155.  
  156.  
  157. void Invoke(fOpNumber, fAbConPtr, fCalleeGODP)
  158. AbConPtr                    fAbConPtr;      /* AbConVector ptr          */
  159. int                fOpNumber;        /* operation number         */
  160. GODP                        fCalleeGODP;    /* target                   */
  161. /* The call should probably be renamed FrozenTrap since there can
  162.    be the following reasons for it:
  163.     1.  Remote invocation (handled here).
  164.     2.  Invoke of object when initially has not been done yet.
  165.     3.  Garbage Collection trap. (Not impl yet)
  166. */
  167. {
  168.     register InvokeReqPtr           req;
  169.     register AbConOpVectorEntryPtr  entryPtr;
  170.     register SSPtr                  callerSSP;
  171.     NodeNum                         nodeLNN;
  172.     Map                             theMap;
  173. #ifdef DONEBYSTUB
  174.     CodeAddr                        returnAddr;
  175.     DynamicLinkPtr                  dynLink;
  176. #endif DONEBYSTUB
  177.     
  178.     if (IsNIL(fCalleeGODP)) {
  179.         KMDTrace("LineNumber", 2, "Invoke of NIL\n");
  180.     ErrMsg("Invoke of NIL somewhere -- kernel cannot recover -- sorry\n");
  181.     abort();
  182.     }
  183.  
  184.     callerSSP  = preemptRunning();
  185.     callerSSP->status.rs = SSInvokeWait; /* assumed for now */
  186.     KMDTrace("LineNumber", 4, "%s invoke via kernel in %s\n",
  187.     PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
  188.  
  189. #ifdef DONEBYSTUB
  190.     /* Remove dynamic link from stack and set return addr */
  191.     dynLink = (DynamicLinkPtr) (callerSSP->regs.sp);
  192.     returnAddr = dynLink->ip;
  193.     callerSSP->regs.b = dynLink->b;
  194.     callerSSP->regs.sp = (SSAddr) (dynLink+1);
  195.     PUSHIT(callerSSP->regs.sp, returnAddr);
  196. #endif DONEBYSTUB
  197.     
  198.     KMDTrace("Invoke", 3, "%s invoking %s op #%d at %s\n",
  199.     PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID), fOpNumber,
  200.     PPSSPlace(callerSSP));
  201.  
  202.     /*
  203.      * cINVK_InvokeFaults counts how many times processes fault to this
  204.      * procedure.
  205.      */
  206.     cINVK_InvokeFaults++;
  207.     
  208.     if (fCalleeGODP->tag.isResident && (!fCalleeGODP->tag.setUpDone)) {
  209.     register InitiallyReqPtr        p;
  210.     KMDTrace("Invoke", 3, "%s blocking on invoke of %s\n",
  211.         PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID));
  212.     KMDTrace("Invoke", 3, "Initially for not done yet; blocking in %s\n",
  213.         PPSSPlace(callerSSP));
  214.     KMDTrace("LineNumber", 4, "%s waiting for initially done in %s\n",
  215.         PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
  216.     p   = mNewRequest(Initially);
  217.     p->calleeGODP           = fCalleeGODP;
  218.     p->theProcess           = callerSSP;
  219.     p->opNumber             = fOpNumber;
  220.     p->theAbConPtr          = fAbConPtr;
  221.         callerSSP->invokePtr    = (GenericPtr) p;
  222.         callerSSP->status.rs    = SSInitiallyWait;
  223.     KMDTrace("LineNumber", 4, "%s waiting for initially done in %s\n",
  224.         PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
  225.     theMap  = (Map) Map_Lookup(InitiallyMap, (int) fCalleeGODP);
  226.     if (IsNIL(theMap)) {
  227.         theMap = Map_Create();
  228.         KMDTrace("Invoke", 4, "Creating initially map for 0x%05x\n",
  229.         fCalleeGODP);
  230.         Map_Insert(InitiallyMap, (int) fCalleeGODP, (int) theMap);
  231.         KMDTrace("FixMe", 5, "Ought to use Set for theMap\n");
  232.     }
  233.     Map_Insert(theMap, (int) p, NULL);
  234.     return;
  235.     }
  236.  
  237.     if (fCalleeGODP->tag.isResident) {
  238.     ErrMsg("Found object frozen in %s\n", PPSSPlace(callerSSP));
  239.     fail(callerSSP);
  240.     return;
  241.     }
  242.     
  243.     
  244.     if (IsNULL(fCalleeGODP->ownOID)) {
  245.     OTInsert((ODP) fCalleeGODP);
  246.     }
  247.     
  248.     /* Build the InvokeRequest and wait for the invocation to return */
  249.     req                     =   mNewRequest(Invoke);
  250.     req->requestor          =   callerSSP;
  251.     req->targetGODP         =   fCalleeGODP;
  252.     req->theAbConPtr        =   fAbConPtr;
  253.  
  254.     /* Put the request reference into stack segment descriptor */
  255.     callerSSP->invokePtr        =   (GenericPtr) req;
  256.  
  257.     if (IsNULL(callerSSP->ownOID)) {
  258.     OTInsert((ODP) callerSSP->ownSSODP);
  259.     callerSSP->ownOID = callerSSP->ownSSODP->ownOID;
  260.     }
  261.  
  262.     req->i.hdr.itemTag         = InvokeITag;
  263.     req->i.hdr.size            = sizeof (req->i);
  264.     req->i.callerSSOID         = callerSSP->ownOID;
  265.     req->i.callerLoc           = thisNodeLocation;
  266.     req->i.processOID          = callerSSP->processOID;
  267.     req->i.targetOID           = fCalleeGODP->ownOID;
  268.     req->i.targetTryAtLoc      = fCalleeGODP->ownLoc;
  269.     req->i.abConTag            = fAbConPtr->tag;
  270.     req->i.abstractTypeOID     = fAbConPtr->ATOID;
  271.     req->i.concreteTypeOID     = fAbConPtr->CodeOID;
  272.     req->i.stackAvailable      = callerSSP->availStack + 
  273.     byteOffset(callerSSP->splimit, callerSSP->regs.sp);
  274.     entryPtr                   = &fAbConPtr->opVector[fOpNumber];
  275.     req->i.opOID               = entryPtr->operationNameOID;
  276.     req->i.opNumber            = fOpNumber;
  277.     req->i.argumentCount       = entryPtr->argumentCount;
  278.     req->i.resultCount         = entryPtr->resultCount;
  279.     req->i.resultMoveMask      = 0;
  280.     req->i.paramMoveMask       = 0;
  281.  
  282.     KMDTrace("Invoke", 5, "Op #%d, OpOID 0x%08x, %d arg%s, %d result%s\n",
  283.     fOpNumber, req->i.opOID, req->i.argumentCount,
  284.     mPLURAL(req->i.argumentCount), req->i.resultCount,
  285.     mPLURAL(req->i.resultCount));
  286.  
  287.     /* Fire up the location protocol, if necessary */
  288.     nodeLNN = mGetLocNodeNum(fCalleeGODP->ownLoc);
  289.     if (nodeLNN == NULL) {
  290.     KMDTrace("Invoke", 3, "Firing up location protocol\n");
  291.     req->status             = IRLocatingTarget;
  292.     req->hdr.callBack       = (GenericHandlerPtr) InvokeCallBack;
  293.     StartLocate((GenericReqPtr) req, (ODP) fCalleeGODP);
  294.     return;
  295.     }
  296.     InvokeCallBack(req, fCalleeGODP->ownOID);
  297. }
  298.  
  299. void InvokeWithMove(fOpNumber, fAbConPtr, fCalleeGODP)
  300. AbConPtr                    fAbConPtr;      /* AbConVector ptr          */
  301. int                fOpNumber;        /* operation number         */
  302. GODP                        fCalleeGODP;    /* target                   */
  303. /* The call should probably be renamed FrozenTrap since there can
  304.    be the following reasons for it:
  305.     1.  Remote invocation (handled here).
  306.     2.  Invoke of object when initially has not been done yet.
  307.     3.  Garbage Collection trap. (Not impl yet)
  308. */
  309. {
  310.     register InvokeReqPtr           req;
  311.     register AbConOpVectorEntryPtr  entryPtr;
  312.     register SSPtr                  callerSSP;
  313.     MoveMask                        theMoveMask, theVisitMask;
  314.     NodeNum                         nodeLNN;
  315.     Map                             theMap;
  316.  
  317.     /*
  318.      * cINVK_InvokeFaults counts how many times processes fault to this
  319.      * procedure.
  320.      */
  321.     cINVK_InvokeFaults++;
  322.  
  323.     callerSSP  = preemptRunning();
  324.     callerSSP->status.rs = SSInvokeWait; /* assumed for now */
  325.     /* Fetch masks from stack */
  326.     POPIT(callerSSP->regs.sp, theMoveMask);
  327.     POPIT(callerSSP->regs.sp, theVisitMask);
  328.  
  329.     if (IsNIL(fCalleeGODP)) {
  330.         KMDTrace("LineNumber", 2, "Invoke of NIL\n");
  331.     ErrMsg("Invoke of NIL somewhere -- kernel cannot recover -- sorry\n");
  332.     abort();
  333.     }
  334.     
  335.     KMDTrace("LineNumber", 4, "%s invoke via kernel in %s\n",
  336.     PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
  337.  
  338. #ifdef DONEBYSTUB
  339.  
  340.     CodeAddr                        returnAddr;
  341.     DynamicLinkPtr                  dynLink;
  342.  
  343.     /* This stuff is obsolete */
  344.     /* Remove dynamic link from stack and set return addr */
  345.     dynLink = (DynamicLinkPtr) (callerSSP->regs.sp);
  346.     returnAddr = dynLink->ip;
  347.     callerSSP->regs.b = dynLink->b;
  348.     callerSSP->regs.sp = (SSAddr) (dynLink+1);
  349.     PUSHIT(callerSSP->regs.sp, returnAddr);
  350. #endif DONEBYSTUB
  351.     
  352.     KMDTrace("Invoke", 3,
  353.     "%s invoking %s with move/visit params op #%d at %s\n",
  354.     PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID), fOpNumber,
  355.     PPSSPlace(callerSSP));
  356.  
  357.     KMDTrace("Invoke", 4, "Move Mask 0x%02x  Visit Mask 0x%02x\n",
  358.     theMoveMask, theVisitMask);
  359.     if (fCalleeGODP->tag.isResident && (!fCalleeGODP->tag.setUpDone)) {
  360.     register InitiallyReqPtr        p;
  361.     KMDTrace("Invoke", 3, "%s blocking on invoke of %s\n",
  362.         PPPOID(callerSSP->processOID), PPGOID(fCalleeGODP->ownOID));
  363.     KMDTrace("Invoke", 3, "Initially for not done yet; blocking in %s\n",
  364.         PPSSPlace(callerSSP));
  365.     KMDTrace("LineNumber", 4, "%s waiting for initially done in %s\n",
  366.         PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
  367.     p   = mNewRequest(Initially);
  368.     p->calleeGODP           = fCalleeGODP;
  369.     p->theProcess           = callerSSP;
  370.     p->opNumber             = fOpNumber;
  371.     p->theAbConPtr          = fAbConPtr;
  372.         callerSSP->invokePtr    = (GenericPtr) p;
  373.         callerSSP->status.rs    = SSInitiallyWait;
  374.     KMDTrace("LineNumber", 4, "%s waiting for initially done in %s\n",
  375.         PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
  376.     theMap  = (Map) Map_Lookup(InitiallyMap, (int) fCalleeGODP);
  377.     if (IsNIL(theMap)) {
  378.         theMap = Map_Create();
  379.         KMDTrace("Invoke", 4, "Creating initially map for 0x%05x\n",
  380.         fCalleeGODP);
  381.         Map_Insert(InitiallyMap, (int) fCalleeGODP, (int) theMap);
  382.         KMDTrace("FixMe", 5, "Ought to use Set for theMap\n");
  383.     }
  384.     Map_Insert(theMap, (int) p, NULL);
  385.     return;
  386.     }
  387.  
  388.     if (fCalleeGODP->tag.isResident) {
  389.     ErrMsg("Found object frozen in %s\n", PPSSPlace(callerSSP));
  390.     fail(callerSSP);
  391.     return;
  392.     }
  393.     if (IsNULL(fCalleeGODP->ownOID)) {
  394.     OTInsert((ODP) fCalleeGODP);
  395.     }
  396.     
  397.     /* Build the InvokeRequest and wait for the invocation to return */
  398.     req                     =   mNewRequest(Invoke);
  399.     req->requestor          =   callerSSP;
  400.     req->targetGODP         =   fCalleeGODP;
  401.     req->theAbConPtr        =   fAbConPtr;
  402.  
  403.     /* Put the request reference into stack segment descriptor */
  404.     callerSSP->invokePtr        =   (GenericPtr) req;
  405.  
  406.     if (IsNULL(callerSSP->ownOID)) {
  407.     OTInsert((ODP) callerSSP->ownSSODP);
  408.     callerSSP->ownOID = callerSSP->ownSSODP->ownOID;
  409.     }
  410.  
  411.     req->i.hdr.itemTag         = InvokeITag;
  412.     req->i.hdr.size            = sizeof (req->i);
  413.     req->i.callerSSOID         = callerSSP->ownOID;
  414.     req->i.callerLoc           = thisNodeLocation;
  415.     req->i.processOID          = callerSSP->processOID;
  416.     req->i.targetOID           = fCalleeGODP->ownOID;
  417.     req->i.targetTryAtLoc      = fCalleeGODP->ownLoc;
  418.     req->i.abConTag            = fAbConPtr->tag;
  419.     req->i.abstractTypeOID     = fAbConPtr->ATOID;
  420.     req->i.concreteTypeOID     = fAbConPtr->CodeOID;
  421.     req->i.stackAvailable      = callerSSP->availStack + 
  422.     byteOffset(callerSSP->splimit, callerSSP->regs.sp);
  423.     entryPtr                   = &fAbConPtr->opVector[fOpNumber];
  424.     req->i.opOID               = entryPtr->operationNameOID;
  425.     req->i.opNumber            = fOpNumber;
  426.     req->i.argumentCount       = entryPtr->argumentCount;
  427.     req->i.resultCount         = entryPtr->resultCount;
  428.     req->i.resultMoveMask      = theVisitMask;
  429.     req->i.paramMoveMask       = theMoveMask;
  430.  
  431.     KMDTrace("Invoke", 4, "Op #%d, OpOID 0x%08x, %d arg%s, %d result%s\n",
  432.     fOpNumber, req->i.opOID, req->i.argumentCount,
  433.     mPLURAL(req->i.argumentCount), req->i.resultCount,
  434.     mPLURAL(req->i.resultCount));
  435.  
  436.     /* Fire up the location protocol, if necessary */
  437.     nodeLNN = mGetLocNodeNum(fCalleeGODP->ownLoc);
  438.     if (nodeLNN == NULL) {
  439.     KMDTrace("Invoke", 3, "Firing up location protocol\n");
  440.     req->status             = IRLocatingTarget;
  441.     req->hdr.callBack       = (GenericHandlerPtr) InvokeCallBack;
  442.     StartLocate((GenericReqPtr) req, (ODP) fCalleeGODP);
  443.     return;
  444.     }
  445.     InvokeCallBack(req, fCalleeGODP->ownOID);
  446. }
  447.  
  448. /*ARGSUSED*/
  449. HResult InvokeCallBack(fReq, fOID)
  450. InvokeReqPtr                fReq;
  451. OID                         fOID;
  452. /* Call back is done when object has been located */
  453. {
  454.     register InvokeReqPtr           req;
  455.     register int                    i;
  456.     register AVariablePtr           paramAddr;
  457.     register SSPtr                  callerSSP;
  458.     NodeNum                         nodeLNN;
  459.     LMHandle                        myHandle;
  460.     int                             paramSize, opNumber;
  461.     ParamItem                       myParamItem;
  462.     Map                             m;
  463.     Set                             ar;
  464.     KKStatus                        kstat;
  465.     GODP                            targetGODP;
  466.     AbConPtr                        targetAbCon;
  467.     
  468.     req                 = fReq;
  469.     callerSSP           = req->requestor;
  470.     targetGODP          = req->targetGODP;
  471.     targetAbCon         = req->theAbConPtr;
  472.     nodeLNN             = mGetLocNodeNum(targetGODP->ownLoc);
  473.  
  474.     KMDTrace("Invoke", 4, "%s ready to invoke %s at node #%d\n",
  475.     PPPOID(callerSSP->processOID), PPGOID(targetGODP->ownOID), nodeLNN);
  476.  
  477.     if (nodeLNN == GetLNN()) {
  478.     /* It is here so just do a resident invoke */
  479.     KMDTrace("Invoke", 3, "InvokeCallBack found %s resident\n",
  480.         PPGOID(targetGODP->ownOID));
  481.     opNumber        = req->i.opNumber;
  482.     FreeRequest((GenericReqPtr) req);
  483.     callerSSP->invokePtr    = (GenericPtr) NULL;
  484.     TryInvoke(opNumber, targetAbCon, targetGODP, callerSSP);
  485.     return;
  486.     }
  487.  
  488.     /* Build invocation message request */
  489.     LMStartMsg(&myHandle, KMSG_EmKernel, EMKM_InvokeReq, nodeLNN);
  490.     LMPutData(&myHandle, &req->i, sizeof(req->i));
  491.  
  492.     /* Start on the translation map */
  493.     m           = Map_Create();
  494.     ar          = Set_Create();
  495.  
  496.     /* Put the stack segment into the translation table */
  497.  
  498.     /* Copy the arguments */
  499.     if (req->i.argumentCount > 0) {
  500.         int        pos;
  501.     
  502.     assert(req->i.argumentCount <= 32);
  503.     paramSize = req->i.argumentCount * sizeof(AVariable);
  504.     myParamItem.hdr.itemTag = ParamTag;
  505.     myParamItem.hdr.size = paramSize + sizeof(ItemHdr);
  506.     paramAddr = (AVariablePtr)
  507.         addOffset(callerSSP->regs.sp, sizeof(CodeAddr));
  508.     LMPutData(&myHandle, &myParamItem, sizeof(ItemHdr));
  509.     LMPutData(&myHandle, paramAddr, paramSize);
  510.     
  511.     /* Traverse parameter area and send translation info */
  512.     for (i = req->i.argumentCount; i ; i--, paramAddr++) {
  513.             if ((req->i.paramMoveMask >> (i-1)) & 0x1) {
  514.         KMDTrace("Invoke", 4, "Param #%d by move %s\n", i,
  515.             PPVar(paramAddr));
  516.         cINVK_CallByMovesDone++;
  517.         pos = LMCurrentPosition(&myHandle);
  518.         MoveVarToTTable(&myHandle, paramAddr, m, ar);
  519.         cINVK_CallByMovesBytesSent +=
  520.             (LMCurrentPosition(&myHandle) - pos);
  521.         } else  if ((req->i.resultMoveMask >> (i-1)) & 0x1) {
  522.         KMDTrace("Invoke", 4, "Param #%d by visit %s\n", i,
  523.             PPVar(paramAddr));
  524.         cINVK_CallByVisitsDone++;
  525.         pos = LMCurrentPosition(&myHandle);
  526.         MoveVarToTTable(&myHandle, paramAddr, m, ar);
  527.         cINVK_CallByVisitsBytesSent +=
  528.             (LMCurrentPosition(&myHandle) - pos);
  529.             } else {
  530.         KMDTrace("Invoke", 4, "Param #%d by ref %s\n", i,
  531.           PPVar(paramAddr));
  532.         AddVarToTTable(&myHandle, paramAddr, m, ar);
  533.         }
  534.     }
  535.     }
  536.     
  537.     /* Put the current stack segment into the translation table */
  538.     AddToTTable(&myHandle, (ODP) callerSSP->ownSSODP, m, ar);
  539.  
  540.     MoveARs(&myHandle, m, ar);
  541.  
  542.     /*
  543.      * cINVK_RemoteInvokes counts the number of times that we think that we
  544.      * need to do a remote invoke.
  545.      */
  546.     cINVK_RemoteInvokes++;
  547.     cINVK_RemoteInvokesBytesSent   += LMCurrentPosition(&myHandle);
  548.     cINVK_RemoteInvokesPacketsSent += LMPacketPosition(&myHandle);
  549.     
  550.     /* Ship the message */
  551.     kstat = LMSendMsg(&myHandle);
  552.  
  553.     req->status             = IRWaitingForInvokeReply;
  554.     
  555.     /* Clean up */
  556.     Map_Destroy(m);
  557.     Set_Destroy(ar);
  558.  
  559.  
  560.     /* Finally, check that we could send the msg */
  561.  
  562.     if (!mSUCCESS(kstat)) {
  563.     KMDTrace("Invoke", 2, "%s target object %s unavailable in %s\n",
  564.         PPPOID(callerSSP->processOID), PPGOID(targetGODP->ownOID),
  565.         PPSSPlace(callerSSP));
  566.     FreeRequest((GenericReqPtr) callerSSP->invokePtr);
  567.     callerSSP->invokePtr = (GenericPtr) NULL;
  568.     unavail(callerSSP, targetGODP, targetAbCon);
  569.     return;
  570.     }
  571. }
  572.  
  573. /************************************************************************/
  574. /*      Invocation message arrival                                      */
  575. /************************************************************************/
  576.  
  577. HResult InvokeHandler(fHandle)
  578. LMHandle           fHandle;
  579. /* Handles incoming invocation messages */
  580. {
  581.     register SSPtr              newSS;
  582.     register IncomingIReqPtr    req;
  583.     register int                i;
  584.     NodeNum                     srcNode;
  585.     int                         length, argumentSize;
  586.     SSODP                       callerSSODP;
  587.     ParamItem                   myParamItem;
  588.     OID                         theCTOID;
  589.     ODP                         theOldODP;
  590.  
  591.     srcNode = fHandle->mmMsgHdr.MsgSrc;
  592.     KMDTrace("Invoke", 3, "*** Invocation Message from %d ***\n", srcNode);
  593.     
  594.     /* Build incoming invocation request */
  595.     req = mNewRequest(IncomingI);
  596.  
  597.     req->visitorSet             = (Set) NULL;
  598.  
  599.     /* Get the request */
  600.     length = sizeof(req->i);
  601.     LMGetData(&fHandle, &req->i, &length);
  602.     assert(length == sizeof(req->i));
  603.     KMDTrace("Invoke", 3, "Caller SSOID 0x%05x target %s opOID #0x%08x\n",
  604.     req->i.callerSSOID, PPGOID(req->i.targetOID), req->i.opOID);
  605.     KMDTrace("Invoke", 4, "ATOID \t0x%05x\tstackAvail %5d\n",
  606.     req->i.abstractTypeOID, req->i.stackAvailable);
  607.     KMDTrace("Invoke", 4, "%d %s, %d %s\n", req->i.argumentCount,
  608.     req->i.argumentCount == 1 ? "argument" : "arguments",
  609.     req->i.resultCount, req->i.resultCount == 1 ? "result" : "results");
  610.     KMDTrace("Invoke", 4, "MoveMask 0x%01x  VisitMask 0x%01x\n",
  611.     req->i.paramMoveMask, req->i.resultMoveMask);
  612.     KMDTrace("FixMe", 5,
  613.     "(Fix me: should update target location before lookup - re move)\n");
  614.  
  615.     /* Lookup target */
  616.     req->targetGODP = (GODP) OTLookup(req->i.targetOID);
  617.     
  618.     /* HACK: delay processing of invoke request if the object has not
  619.        been set up properly in the hope that it will be later */
  620.     if (NonNULL(req->targetGODP) && (!req->targetGODP->tag.setUpDone)) {
  621.     KMDTrace("Invoke", 2, "HACK: delay processing of Invoke for 0x%06x\n",
  622.         req->targetGODP);
  623.     }
  624.     
  625.     /* Allocate a new SS to handle the request */
  626.     newSS = req->theProcess = StdStackSegment();
  627.     newSS->processOID       = req->i.processOID;
  628.     newSS->availStack       = req->i.stackAvailable - newSS->segmentSize;
  629.     newSS->rPtr             = (int *) req;
  630.  
  631.     callerSSODP             = (SSODP) OTLookup(req->i.callerSSOID);
  632.     if (IsNULL(callerSSODP)) {
  633.     /* Have not heard from this SS before */
  634.     KMDTrace("Invoke", 4,
  635.         "First time we have heard from SSOID 0x%08.8x\n",
  636.         req->i.callerSSOID);
  637.     /* Note, it will be inserted by Digest table */
  638.     }
  639.  
  640.     /* Make room on stack for results */
  641.     if (req->i.resultCount > 0) {
  642.     for (i = req->i.resultCount; i > 0; i--) {
  643.         PUSHIT(newSS->regs.sp, EMNIL);
  644.         PUSHIT(newSS->regs.sp, EMNIL);
  645.     }
  646.     KMDTrace("Invoke", 4,
  647.         "Allocating room for %d result%s;  new sp 0x%05x\n",
  648.         req->i.resultCount, mPLURAL(req->i.resultCount), newSS->regs.sp);
  649.     }
  650.     /* Copy parameters onto stack */
  651.  
  652.     if (req->i.argumentCount > 0) {
  653.     length = sizeof(ItemHdr);
  654.     LMGetData(&fHandle, &myParamItem, &length);
  655.     assert(length == sizeof(ItemHdr));
  656.     assert(myParamItem.hdr.itemTag == ParamTag);
  657.     argumentSize = myParamItem.hdr.size - length;
  658.     assert(argumentSize == req->i.argumentCount * sizeof(AVariable));
  659.     /* Allocate room for arguments on stack */
  660.     req->paramAddr = (AVariablePtr) (newSS->regs.sp = (SSAddr)
  661.         addOffset(newSS->regs.sp, -argumentSize) );
  662.     KMDTrace("Invoke", 4, "argument size %d, new sp: 0x%05x\n",
  663.         argumentSize, newSS->regs.sp);
  664.     /* Copy parameters to stack */
  665.     length = argumentSize;
  666.     LMGetData(&fHandle, newSS->regs.sp, &length);
  667.     KMDTrace("Invoke", 5,
  668.         "want argument size %d, got %d\n", argumentSize, length);
  669.     assert(length == argumentSize);
  670.     }
  671.     
  672.     /* Create translation map */
  673.     req->m              = Map_Create();
  674.     req->neededMap      = Map_Create();
  675.     req->newSet         = Set_Create();
  676.  
  677.     /* Digest translation table information */
  678.     DigestTable(&fHandle, req->m, req->neededMap, req->newSet, 0);
  679.  
  680.     LMClose(&fHandle);
  681.  
  682.     req->status         = IHLoadingCode;
  683.     
  684.     if (Map_Count(req->neededMap) > 0) {
  685.     Boolean                 didit;
  686.     Map                     gotLoaded; /* Holds the ones loaded now */
  687.     CodeODP                 newODP;
  688.  
  689.     gotLoaded       = Map_Create();
  690.     /* Have to load some code */
  691.  
  692.     Map_For(req->neededMap, theCTOID, theOldODP)
  693.         didit = LoadRequest(theCTOID, (GenericReqPtr) req);
  694.         if (didit) Map_Insert(gotLoaded, (int) theCTOID, (int) theOldODP);
  695.     Map_Next
  696.  
  697.     Map_For(gotLoaded, theCTOID, theOldODP)
  698.         /* Delete it since no call back will occur */
  699.         Map_Delete(req->neededMap, (int) theCTOID);
  700.         newODP      = (CodeODP) OTLookup(theCTOID);
  701.         assert(NonNULL(newODP));
  702.         Map_Insert(req->m, (int) theOldODP, (int) newODP->dataPtr);
  703.     Map_Next
  704.  
  705.     Map_Destroy(gotLoaded);
  706.  
  707.     if (Map_Count(req->neededMap) > 0) return;
  708.     }
  709.  
  710.     req->status         = IHCodeLoadDone;
  711.     InvokeHandlerCallBack((GenericReqPtr) req, (OID) NULL);
  712.     return;
  713. }
  714.  
  715. /**********************************************************************/
  716. /*      InvokeHandlerCallBack                                         */
  717. /**********************************************************************/
  718. HResult InvokeHandlerCallBack(fReq, fOID)
  719. GenericReqPtr           fReq;
  720. OID                     fOID;
  721. {
  722.     register IncomingIReqPtr    req;
  723.     register AVariablePtr       p;
  724.     register SSPtr              newSS;
  725.     CodeAddr                    theEntryPoint;
  726.     
  727.     req                         = (IncomingIReqPtr) fReq;
  728.     newSS                       = req->theProcess;
  729.     
  730.     KMDTrace("Invoke", 4, "InvokeHandlerCallBack; OID %s status %s\n",
  731.     PPOID(fOID),
  732.     req->status == IHLoadingCode ? "Loading Code" :
  733.     req->status == IHCodeLoadDone? "Code load done" :
  734.         req->status == IHObjectNonFrozen ? "Object Not Frozen" :
  735.     "BAD STATUS");
  736.  
  737.     switch (req->status) {
  738.     
  739.     case IHLoadingCode: {
  740.     ODP             oldODP;
  741.     CodeODP         newODP;
  742.     
  743.     /* Requested code has arrived */
  744.     oldODP          = (ODP) Map_Lookup(req->neededMap, (int) fOID);
  745.     if (IsNIL(oldODP)) {
  746.         ErrMsg("InvokeHandlerCallBack %s -- ignored\n");
  747.         return;
  748.     }
  749.     Map_Delete(req->neededMap, (int) fOID);
  750.  
  751.     newODP          = (CodeODP) OTLookup(fOID);
  752.     assert(NonNULL(newODP));
  753.     /* (Note, m uses the pointer to the code area.) */
  754.     Map_Insert(req->m, (int) oldODP, (int) newODP->dataPtr);
  755.     KMDTrace("Invoke", 5, "%s loaded, (0x%04x -> 0x%04x)\n", PPCOID(fOID),
  756.         oldODP, newODP->dataPtr);
  757.  
  758.     /* Check for completion of code loads */
  759.     if (Map_Count(req->neededMap) == 0) {
  760.         KMDTrace("Invoke", 3, "All needed code loaded\n");
  761.         req->status = IHCodeLoadDone;
  762.         InvokeHandlerCallBack((GenericReqPtr) req, (OID) NULL);
  763.     }
  764.     break;
  765.     }
  766.  
  767.     case IHCodeLoadDone: {
  768.     register int    i;
  769.         ODP             aVisitorODP;
  770.  
  771.     /* All needed code has been loaded, now translate */
  772.         DoTranslate(req->newSet, req->m, 0);
  773.  
  774.     if (req->i.argumentCount > 0) {
  775.         /* Translate parameters */
  776.         p = req->paramAddr;
  777.         for (i = req->i.argumentCount; i; p++, i--) {
  778.         if (p->myAbConPtr == (AbConPtr) EMNIL) {
  779.             KMDTrace("Invoke", 4, "Param #%d is NIL\n", i);
  780.         } else {
  781.             p->myAbConPtr =
  782.             (AbConPtr) Map_Lookup(req->m, (int) p->myAbConPtr);
  783.             assert(p->myAbConPtr != (AbConPtr) EMNIL);
  784.             KMDTrace("Invoke", 4, "new AbConPtr 0x%05x\n",
  785.             p->myAbConPtr);
  786.             if(p->myAbConPtr->tag.hasNoPointer) {
  787.             KMDTrace("Invoke", 4,
  788.                 "Param %d integer (or such) = %d, oldAB 0x%05x\n",
  789.                 i, p->myAddr, p->myAbConPtr);
  790.             } else if (p->myAddr == (DataAddr) EMNIL) {
  791.             KMDTrace("Invoke", 4,
  792.                 "Param #%d is NIL (with non-NIL AbCon)\n", i,
  793.                 p->myAddr);
  794.             } else {
  795.             KMDTrace("Invoke", 4,
  796.                 "Param #%d OldODP 0x%05x new AbConPtr 0x%05x\n",
  797.                 i, p->myAddr, p->myAbConPtr);
  798.             /* Translate ODP */
  799.             p->myAddr     =
  800.                 (DataAddr) Map_Lookup(req->m, (int) p->myAddr);
  801.             assert(p->myAddr != (DataAddr) EMNIL);
  802.                         aVisitorODP     = (ODP) p->myAddr;
  803.             if (aVisitorODP->G.tag.global &&
  804.                             ((req->i.resultMoveMask >> (i-1)) & 0x1)
  805.                         ) {
  806.                 KMDTrace("Move", 3, "Call-by-visit OID %s\n",
  807.                                 PPGOID(aVisitorODP->G.ownOID));
  808.                 if (IsNULL(req->visitorSet)) {
  809.                 KMDTrace("Move", 5,
  810.                     "Allocating visitor set\n");
  811.                 req->visitorSet = Set_Create();
  812.                 }
  813.                 Set_Insert(req->visitorSet,
  814.                 (int) aVisitorODP->G.ownOID);
  815.             }
  816.             }
  817.         }
  818.         KMDTrace("Invoke", 5, "After translate: (0x%05x, 0x%05x)\n",
  819.             p->myAbConPtr,p->myAddr);
  820.         }
  821.     }
  822.  
  823.     /* Cleanup */
  824.     Map_Destroy(req->m);
  825.     Map_Destroy(req->neededMap);
  826.     Set_Destroy(req->newSet);
  827.  
  828.     if (IsNULL(req->targetGODP) || (!req->targetGODP->tag.isResident)) {
  829.         InvokeReturn(newSS, INVOKEUNAVAILABLE);
  830.         DiscardStackSegment(newSS);
  831.         return;
  832.     }
  833.  
  834.     /* Check to see if there is enough stack left */
  835.     if (req->i.stackAvailable < newSS->segmentSize) {
  836.         KMDTrace("Invoke", 2, "%s too low on stack space; only %d left\n",
  837.         PPPOID(req->i.processOID), req->i.stackAvailable);
  838.         InvokeReturn(newSS, INVOKEFAILED);
  839.         DiscardStackSegment(newSS);
  840.         return;
  841.     }
  842.         
  843.         if (req->targetGODP->tag.frozen) {
  844.             Set                     reqSet;
  845.         
  846.         KMDTrace("Invoke", 3, "Invoke: OD frozen ODTag: %s\n",
  847.         PPODTag(req->targetGODP->tag));
  848.         if (req->targetGODP->tag.setUpDone) {
  849.         ErrMsg("Cannot handle frozen remote object ODTag %s\n",
  850.             PPODTag(req->targetGODP->tag));
  851.         abort();
  852.         }
  853.         req->status         = IHCodeLoadDone;
  854.         reqSet              = (Set)
  855.                 Map_Lookup(FrozenMap, (int) req->targetGODP->ownOID);
  856.         if (IsNIL(reqSet)) {
  857.         reqSet          = Set_Create();
  858.                 Map_Insert(FrozenMap, (int) req->targetGODP->ownOID,
  859.             (int) reqSet);
  860.         KMDTrace("Invoke", 5, "Creating frozen set for %s\n",
  861.             PPGOID(req->targetGODP->ownOID));
  862.         }
  863.             KMDTrace("Invoke", 3,
  864.         "Inserting 0x%06x process %s into frozen set\n", req,
  865.         PPPOID(req->theProcess->processOID));
  866.         Set_Insert(reqSet, (int) req);
  867.         return;
  868.     }
  869.     /* Fall through !! */
  870.     }
  871.  
  872.     case IHObjectNonFrozen: {
  873.     register CodePtr    theCodePtr;
  874.     theCodePtr         = req->targetGODP->dataPtr->myCodePtr;
  875.     theEntryPoint   = FindEntryPointForOp(theCodePtr, req->i.opOID);
  876.     if (req->i.resultCount > 0) {
  877.         req->returnByMoveMask = FindReturnByMoveMask(theCodePtr,
  878.         theEntryPoint);
  879.     } else {
  880.         req->returnByMoveMask = 0;
  881.     }
  882.     
  883.     StartProcessAtAddr(req->theProcess, req->targetGODP,
  884.         req->targetGODP->dataPtr, theEntryPoint);
  885.     break;
  886.     }
  887.     
  888.     default: {
  889.     ErrMsg("Bad move status %d in InvokeHandlerCallBack\n", req->status);
  890.     abort();
  891.     }
  892.     }
  893. }
  894.  
  895. /************************************************************************/
  896. /*      Invocation reply generation                                     */
  897. /************************************************************************/
  898.  
  899. /* NOT a kernel call -- called from Return off stack or upon failure */
  900. void InvokeReturn(fSSPtr, fResult)
  901. register SSPtr              fSSPtr;
  902. InvokeResult                fResult;
  903. /* Reply to an invocation */
  904. {
  905.     register IncomingIReqPtr        req;
  906.     register SSODP                  callerSSODP;
  907.     register int                    i;
  908.     register AVariablePtr           paramAddr;
  909.     InvokeReplyItem                 replyItem;
  910.     LMHandle                        replyHandle;
  911.     int                             paramSize;
  912.     ParamItem                       myParamItem;
  913.     Map                             m;              /* ODPs sent */
  914.     Set                             ar;             /* ARs to send */
  915.     GODP                            visitingGODP;
  916.     OID                             visitingOID;
  917.  
  918.     req = (IncomingIReqPtr) fSSPtr->rPtr;
  919.     callerSSODP = (SSODP) OTLookup(req->i.callerSSOID);
  920.     assert(NonNULL(callerSSODP));
  921.     KMDTrace("Invoke", 3, "%s replying to SSOID 0x%05x @ %s, result %s\n",
  922.     PPPOID(fSSPtr->processOID), callerSSODP->ownOID,
  923.     PPLoc(callerSSODP->ownLoc), PPInvokeResult(fResult));
  924.  
  925.     if (callerSSODP->tag.isResident) {
  926.         register SSPtr              callerSSP;
  927.         register InvokeReqPtr       invokeReq;
  928.     
  929.         KMDTrace("Invoke", 3, "Performing local return after remote call\n");
  930.         /* much code copied from InvokeReplyHandler */
  931.  
  932.         /* Find the original req */
  933.         callerSSP           = callerSSODP->dataPtr;
  934.         invokeReq           = (InvokeReqPtr) callerSSP->invokePtr;
  935.         assert(NonNULL(invokeReq));
  936.  
  937.         switch (fResult) {
  938.  
  939.     case INVOKEFAILED: {
  940.         /* The invocation failed and must be propagted */
  941.         KMDTrace("Invoke", 2, "Invoke failed\n");
  942.         /* Get rid of the old incoming request */
  943.         FreeRequest((GenericReqPtr) req);
  944.         fSSPtr->rPtr = (GenericPtr) NULL;
  945.         FreeRequest((GenericReqPtr) callerSSP->invokePtr);
  946.         callerSSP->invokePtr = (GenericPtr) NULL;
  947.         fail(callerSSP);
  948.         return;
  949.     }
  950.  
  951.     case INVOKEUNAVAILABLE: {
  952.         /* Make copies of vars since the request area will be freed */
  953.         GODP                    theGODP = req->targetGODP;
  954.         AbConPtr                theAbConPtr = req->theAbConPtr;
  955.         
  956.         KMDTrace("Invoke", 2, "%s target object %s unavailable in %s\n",
  957.         PPPOID(callerSSP->processOID), PPGOID(theGODP->ownOID),
  958.         PPSSPlace(callerSSP));
  959.         /* Get rid of the old incoming request */
  960.         FreeRequest((GenericReqPtr) req);
  961.         fSSPtr->rPtr = (GenericPtr) NULL;
  962.         /* cf. req = callerSSP->invokePtr earlier */
  963.         FreeRequest((GenericReqPtr) callerSSP->invokePtr);
  964.         callerSSP->invokePtr = (GenericPtr) NULL;
  965.         unavail(callerSSP, theGODP, theAbConPtr);
  966.         return;
  967.     }
  968.  
  969.  
  970.         case INVOKEDONE: {
  971.         KMDTrace("Invoke", 3, "%s Invocation Reply from own node in %s\n",
  972.         PPPOID(callerSSP->processOID), PPSSPlace(callerSSP));
  973.         /*
  974.          * At this point, there is a return addr and parameters on the stack.
  975.          * We need to simulate a return (including popping the arguments)
  976.          * and to copy the results onto the stack.
  977.          */
  978.     
  979.             /*  Save return address */
  980.         POPIT(callerSSP->regs.sp, invokeReq->returnAddr); 
  981.         if (invokeReq->i.argumentCount > 0) {
  982.         /* pop arguments off of stack */
  983.         callerSSP->regs.sp +=
  984.                     ((sizeof(AVariable) / sizeof(*callerSSP->regs.sp)) *
  985.             invokeReq->i.argumentCount);
  986.         }
  987.     
  988.         /* Now the sp points to the results, if any */
  989.         if (invokeReq->i.resultCount > 0) {
  990.                 int resultSize;
  991.         resultSize = invokeReq->i.resultCount * sizeof(AVariable);
  992.         invokeReq->paramAddr = (AVariablePtr) callerSSP->regs.sp;
  993.         KMDTrace("Invoke", 5,
  994.                     "result size %d, addr: 0x%06x to 0x%06x\n",
  995.             resultSize, fSSPtr->regs.sp, invokeReq->paramAddr);
  996.         /* Copy results to stack */
  997.                 bcopy((char *)fSSPtr->regs.sp, (char *)invokeReq->paramAddr,
  998.           resultSize);
  999.         }
  1000.         
  1001.  
  1002.             PUSHIT(callerSSP->regs.sp, invokeReq->returnAddr);
  1003.         
  1004.         /* Get rid of the old incoming request */
  1005.         FreeRequest((GenericReqPtr) req);
  1006.         fSSPtr->rPtr = (GenericPtr) NULL;
  1007.  
  1008.             schedule(callerSSP);
  1009.  
  1010.             return;
  1011.         
  1012.     }    
  1013.         
  1014.         default: {
  1015.         assert(fResult != fResult); /* crash */
  1016.             abort();
  1017.     }
  1018.     }
  1019.         /* This point never reached */
  1020.     }
  1021.     
  1022.     LMStartMsg(&replyHandle, KMSG_EmKernel, EMKM_InvokeReply,
  1023.     (NodeNum) mGetLocNodeNum(callerSSODP->ownLoc));
  1024.     replyItem.hdr.itemTag = ReplyITag;
  1025.     replyItem.hdr.size    = sizeof(replyItem);
  1026.     replyItem.callerSSOID = req->i.callerSSOID;
  1027.     replyItem.result      = fResult;
  1028.     LMPutData(&replyHandle, &replyItem, sizeof(replyItem));
  1029.     
  1030.     /* Initialize sets */
  1031.     m       = Map_Create();
  1032.     ar      = Set_Create();
  1033.  
  1034.     if (fResult != INVOKEDONE) {
  1035.     /* It failed */
  1036.     KMDTrace("Invoke", 2, "%s %s\n", PPPOID(fSSPtr->processOID),
  1037.         fResult == INVOKEFAILED ? " invocation failed":
  1038.         " object unavailable");
  1039.     KMDTrace("Failure", 3, "%s %s\n", PPPOID(fSSPtr->processOID),
  1040.         fResult == INVOKEFAILED ? " invocation failed":
  1041.         " object unavailable");
  1042.     if (fSSPtr->regs.b->ownLoc > req->i.targetTryAtLoc) {
  1043.         /* The callee has an out of date forwarding address, so tell him
  1044.            about the new one. */
  1045.         AddToTTable(&replyHandle, (ODP) fSSPtr->regs.b, m, ar);
  1046.     }
  1047.  
  1048.   
  1049.     /*
  1050.      * If any processes are to move then the set of activation records is
  1051.      * non-empty.
  1052.      */
  1053.     
  1054.     MoveARs(&replyHandle, m, ar);
  1055.  
  1056.     cINVK_RemoteNoSuccessReturns++;
  1057.     LMSendMsg(&replyHandle);
  1058.         
  1059.         KMDTrace("FixMe", 5, "Maybe the visitors set should be respected\n");
  1060.         if (NonNULL(req->visitorSet)) Set_Destroy(req->visitorSet);
  1061.  
  1062.     Set_Destroy(ar);
  1063.     Map_Destroy(m);
  1064.  
  1065.     FreeRequest((GenericReqPtr) req);
  1066.     fSSPtr->rPtr = (GenericPtr) NULL;
  1067.     return;
  1068.     }
  1069.     
  1070.     if (req->i.resultCount > 0) {
  1071.     /* Copy the results into reply msg */
  1072.     KMDTrace("Invoke", 4, "%d result%s, returnByMoveMask 0x%08x\n",
  1073.         req->i.resultCount, mPLURAL(req->i.resultCount),
  1074.         req->returnByMoveMask);
  1075.     paramSize = req->i.resultCount * sizeof(AVariable);
  1076.     paramAddr = (AVariablePtr) fSSPtr->regs.sp;
  1077.     myParamItem.hdr.itemTag = ParamTag;
  1078.     myParamItem.hdr.size = paramSize + sizeof(ItemHdr);
  1079.     LMPutData(&replyHandle, &myParamItem, sizeof(ItemHdr));
  1080.     LMPutData(&replyHandle, paramAddr, paramSize);
  1081.     if (req->returnByMoveMask == 0) {
  1082.         for (i = req->i.resultCount; i ; i--, paramAddr++) {
  1083.         KMDTrace("Invoke", 4, "Result #%d %s\n", i, PPVar(paramAddr));
  1084.         AddVarToTTable(&replyHandle, paramAddr, m, ar);
  1085.         }
  1086.     } else {
  1087.         int pos;
  1088.         for (i = req->i.resultCount; i ; i--, paramAddr++) {
  1089.             if ((req->returnByMoveMask >> (req->i.resultCount-i)) & 1) {
  1090.             KMDTrace("Invoke", 4, "Result #%d by move return %s\n", i,
  1091.             PPVar(paramAddr));
  1092.             pos = LMCurrentPosition(&replyHandle);
  1093.             cINVK_CallByResultMovesDone++;
  1094.             MoveVarToTTable(&replyHandle, paramAddr, m, ar);
  1095.             cINVK_CallByResultBytesSent +=
  1096.                 LMCurrentPosition(&replyHandle) - pos;
  1097.         } else {
  1098.             KMDTrace("Invoke", 4, "Result #%d by ref %s\n", i,
  1099.             PPVar(paramAddr));
  1100.             AddVarToTTable(&replyHandle, paramAddr, m, ar);
  1101.         }
  1102.         }
  1103.     }
  1104.     }
  1105.     
  1106.     /* Return any visiting objects */
  1107.     if (NonNULL(req->visitorSet)) {
  1108.         int             pos;
  1109.         KMDTrace("Move", 3, "There are %d visitors\n",
  1110.         Set_Count(req->visitorSet));
  1111.     Set_For(req->visitorSet, visitingOID)
  1112.             visitingGODP    = (GODP) OTLookup(visitingOID);
  1113.         if (IsNULL(visitingGODP)) {
  1114.         KMDTrace("Move", 2, "Lost visitor OID %s\n",
  1115.             PPGOID(visitingOID));
  1116.         continue;
  1117.         }
  1118.             if (!visitingGODP->tag.isResident) {
  1119.         KMDTrace("Move", 3, "Visitor has already left %s\n",
  1120.             PPGOID(visitingOID));
  1121.         continue;
  1122.         }
  1123.             KMDTrace("Move", 3, "Returning visitor OID %s\n",
  1124.         PPGOID(visitingOID));
  1125.         cINVK_CallByVisitReturnsDone++;
  1126.         pos = LMCurrentPosition(&replyHandle);
  1127.         MoveToTTable(&replyHandle, (ODP) visitingGODP, m, ar);
  1128.         cINVK_CallByVisitReturnBytesSent +=
  1129.             (LMCurrentPosition(&replyHandle) - pos);
  1130.     Set_Next;
  1131.         Set_Destroy(req->visitorSet);
  1132.     }
  1133.  
  1134.     if (fSSPtr->regs.b->ownLoc > req->i.targetTryAtLoc) {
  1135.     /* The callee has an out of date forwarding address, so tell him
  1136.        about the new one. */
  1137.     AddToTTable(&replyHandle, (ODP) fSSPtr->regs.b, m, ar);
  1138.     }
  1139.  
  1140.     /*
  1141.      * If any processes are to move then the set of activation records is
  1142.      * non-empty.
  1143.      */
  1144.  
  1145.     MoveARs(&replyHandle, m, ar);
  1146.  
  1147.     cINVK_RemoteReturns++;
  1148.     cINVK_RemoteReturnsBytesSent += LMCurrentPosition(&replyHandle);
  1149.     cINVK_RemoteReturnsPacketsSent += LMPacketPosition(&replyHandle);
  1150.     
  1151.     /*
  1152.      * Now actually send the message.
  1153.      */
  1154.     
  1155.     LMSendMsg(&replyHandle);
  1156.  
  1157.     /* Clean up */
  1158.     Map_Destroy(m);
  1159.     Set_Destroy(ar);
  1160.  
  1161.     FreeRequest((GenericReqPtr) req);
  1162.     fSSPtr->rPtr = (GenericPtr) NULL;
  1163.     return;
  1164. }
  1165.  
  1166. /************************************************************************/
  1167. /*      Invocation reply handling                                       */
  1168. /************************************************************************/
  1169.  
  1170. HResult InvokeReplyHandler(fHandle)
  1171. LMHandle                fHandle;
  1172. /* Handles incoming replies to previous invocation */
  1173. {
  1174.     register SSPtr                  s;
  1175.     register SSODP                  theSSODP;
  1176.     register InvokeReqPtr           req;
  1177.  
  1178.     InvokeReplyItem                 replyItem;
  1179.     ParamItem                       myParamItem;
  1180.     int                             length, resultSize;
  1181.     
  1182.     length = sizeof(replyItem);
  1183.     LMGetData(&fHandle, &replyItem, &length);
  1184.     assert(length == sizeof(replyItem));
  1185.  
  1186.     KMDTrace("Invoke", 4, "Invoke reply from %d\n", fHandle->mmMsgHdr.MsgSrc);
  1187.     theSSODP = (SSODP) OTLookup(replyItem.callerSSOID);
  1188.     assert (NonNULL(theSSODP));
  1189.     KMDTrace("FixMe", 3, "(Fix me: return SSODP cannot move!)\n");
  1190.     assert (mGetLocNodeNum(theSSODP->ownLoc) == GetLNN());
  1191.     s = theSSODP->dataPtr;
  1192.     KMDTrace("Invoke", 3, "%s Invocation Reply from LNN %d in %s\n",
  1193.     PPPOID(s->processOID), fHandle->mmMsgHdr.MsgSrc, PPSSPlace(s));
  1194.     req = (InvokeReqPtr) s->invokePtr;
  1195.     assert(NonNULL(req));
  1196.  
  1197.     switch (replyItem.result) {
  1198.     
  1199.     case INVOKEDONE: {
  1200.     break;
  1201.     }
  1202.  
  1203.     case INVOKEFAILED: {
  1204.     /* The invocation failed and the failure is propagating back here */
  1205.     KMDTrace("Invoke", 2, "Invoke failed\n");
  1206.     LMClose(&fHandle);
  1207.     FreeRequest((GenericReqPtr) s->invokePtr);
  1208.     s->invokePtr = (GenericPtr) NULL;
  1209.     fail(s);
  1210.     return;
  1211.     }
  1212.     
  1213.     case INVOKEUNAVAILABLE: {
  1214.     /* Make local copies since the request area will be freed */
  1215.     GODP                    theGODP = req->targetGODP;
  1216.     AbConPtr                theAbConPtr = req->theAbConPtr;
  1217.     
  1218.     LMClose(&fHandle);
  1219.     KMDTrace("Invoke", 2, "%s target object %s unavailable in %s\n",
  1220.         PPPOID(s->processOID), PPGOID(theGODP->ownOID),
  1221.         PPSSPlace(s));
  1222.     /* cf. req = s->invokePtr earlier */
  1223.     FreeRequest((GenericReqPtr) s->invokePtr);
  1224.     s->invokePtr = (GenericPtr) NULL;
  1225.     unavail(s, theGODP, theAbConPtr);
  1226.     return;
  1227.     }
  1228.     }
  1229.     
  1230.     /*
  1231.      * At this point, there is a return addr and parameters on the stack.
  1232.      * We need to simulate a return (including popping the arguments)
  1233.      * and to copy the results onto the stack.
  1234.      */
  1235.  
  1236.     POPIT(s->regs.sp, req->returnAddr); /* save return address */
  1237.     if (req->i.argumentCount > 0) {
  1238.     /* pop arguments off of stack */
  1239.     s->regs.sp += ((sizeof(AVariable) / sizeof(*s->regs.sp)) *
  1240.         req->i.argumentCount);
  1241.     }
  1242.  
  1243.     /* Now the sp points to the results, if any */
  1244.     if (req->i.resultCount > 0) {
  1245.     length = sizeof(myParamItem);
  1246.     LMGetData(&fHandle, &myParamItem, &length);
  1247.     assert(length == sizeof(myParamItem));
  1248.     assert(myParamItem.hdr.itemTag == ParamTag);
  1249.     resultSize = myParamItem.hdr.size - length;
  1250.     assert(resultSize == req->i.resultCount * sizeof(AVariable));
  1251.     req->paramAddr = (AVariablePtr) s->regs.sp;
  1252.     KMDTrace("Invoke", 4, "result size %d, addr: 0x%05x\n",
  1253.         resultSize, req->paramAddr);
  1254.     /* Copy results to stack */
  1255.     length = resultSize;
  1256.     LMGetData(&fHandle, s->regs.sp, &length);
  1257.     KMDTrace("Invoke", 5, "Want result size %d, got %d\n", resultSize,
  1258.         length);
  1259.     assert(length == resultSize);
  1260.     }
  1261.  
  1262.     /* Create translation map */
  1263.     req->m              = Map_Create();
  1264.     req->newSet         = Set_Create();
  1265.     req->neededMap      = Map_Create();
  1266.  
  1267.     /* Digest translation table information */
  1268.     DigestTable(&fHandle, req->m, req->neededMap, req->newSet, 0);
  1269.  
  1270.     LMClose(&fHandle);
  1271.  
  1272.     req->status         = IRLoadingCode;
  1273.  
  1274.     if (Map_Count(req->neededMap) > 0) {
  1275.     Boolean                 didit;
  1276.     Map                     gotLoaded; /* Holds the ones loaded now */
  1277.     CodeODP                 newODP;
  1278.     OID                     theCTOID;
  1279.     ODP                     theOldODP;
  1280.  
  1281.     gotLoaded       = Map_Create();
  1282.     /* Have to load some code */
  1283.  
  1284.     Map_For(req->neededMap, theCTOID, theOldODP)
  1285.         didit = LoadRequest(theCTOID, (GenericReqPtr) req);
  1286.         if (didit) Map_Insert(gotLoaded, (int) theCTOID, (int) theOldODP);
  1287.     Map_Next
  1288.  
  1289.     Map_For(gotLoaded, theCTOID, theOldODP)
  1290.         /* Delete it since no call back will occur */
  1291.         Map_Delete(req->neededMap, (int) theCTOID);
  1292.         newODP      = (CodeODP) OTLookup(theCTOID);
  1293.         assert(NonNULL(newODP));
  1294.         Map_Insert(req->m, (int) theOldODP, (int) newODP->dataPtr);
  1295.     Map_Next
  1296.  
  1297.     Map_Destroy(gotLoaded);
  1298.  
  1299.     if (Map_Count(req->neededMap) > 0) return;
  1300.     }
  1301.     req->status         = IRCodeLoadDone;
  1302.     InvokeReplyCallBack((GenericReqPtr) req, (OID) NULL);
  1303.     return;
  1304. }
  1305. /**********************************************************************/
  1306. /*      InvokeReplyCallBack                                           */
  1307. /**********************************************************************/
  1308. HResult InvokeReplyCallBack(fReq, fOID)
  1309. GenericReqPtr           fReq;
  1310. OID                     fOID;
  1311. {
  1312.     InvokeReqPtr        req = (InvokeReqPtr) fReq;
  1313.     
  1314.     KMDTrace("Invoke", 4, "InvokeReplyCallBack; OID %s status %s\n",
  1315.     PPOID(fOID),
  1316.     req->status == IRLocatingTarget ? "Locating Target" :
  1317.     req->status == IRWaitingForInvokeReply ? "Waiting for reply" :
  1318.     req->status == IRLoadingCode ? "Loading Code" :
  1319.     req->status == IRCodeLoadDone? "Code load done" :
  1320.     "BAD STATUS");
  1321.  
  1322.     switch (req->status) {
  1323.     
  1324.     case IRLoadingCode: {
  1325.     ODP             oldODP;
  1326.     CodeODP         newODP;
  1327.     
  1328.     /* Requested code has arrived */
  1329.     oldODP          = (ODP) Map_Lookup(req->neededMap, (int) fOID);
  1330.     if (IsNIL(oldODP)) {
  1331.         ErrMsg("InvokeReplyCallBack %s -- ignored\n");
  1332.         return;
  1333.     }
  1334.     Map_Delete(req->neededMap, (int) fOID);
  1335.  
  1336.     newODP          = (CodeODP) OTLookup(fOID);
  1337.     assert(NonNULL(newODP));
  1338.  
  1339.     /* (Note, m uses the pointer to the code area.) */
  1340.     Map_Insert(req->m, (int) oldODP, (int) newODP->dataPtr);
  1341.     KMDTrace("Invoke", 5, "%s loaded, (0x%04x -> 0x%04x)\n", PPCOID(fOID),
  1342.         oldODP, newODP->dataPtr);
  1343.  
  1344.     /* Check for completion of code loads */
  1345.     if (Map_Count(req->neededMap) == 0) {
  1346.         KMDTrace("Invoke", 3,
  1347.         "All needed code for invoke reply loaded\n");
  1348.         req->status = IRCodeLoadDone;
  1349.         InvokeHandlerCallBack((GenericReqPtr) req, (OID) NULL);
  1350.     }
  1351.     break;
  1352.     }
  1353.  
  1354.     case IRCodeLoadDone: {
  1355.     SSPtr           s;
  1356.     register int    i;
  1357.     register AVariablePtr
  1358.             p;
  1359.  
  1360.     s = req->requestor;
  1361.  
  1362.     /* All needed code has been loaded, now translate */
  1363.         DoTranslate(req->newSet, req->m, 0);
  1364.  
  1365.     if (req->i.resultCount > 0) {
  1366.         p = req->paramAddr;
  1367.         /* Translate results */
  1368.         for (i = req->i.resultCount; i; p++, i--) {
  1369.         if (p->myAbConPtr == (AbConPtr) EMNIL) {
  1370.             KMDTrace("Invoke", 4, "Result #%d is NIL\n", i);
  1371.         } else {
  1372.             p->myAbConPtr =
  1373.             (AbConPtr) Map_Lookup(req->m, (int) p->myAbConPtr);
  1374.             assert(p->myAbConPtr != (AbConPtr) EMNIL);
  1375.             KMDTrace("Invoke", 5, "new AbConPtr 0x%05x\n",
  1376.             p->myAbConPtr);
  1377.             if(p->myAbConPtr->tag.hasNoPointer) {
  1378.             KMDTrace("Invoke", 4,
  1379.                 "Result #%d integer (or such)  = %d (0x%04x), oldAbCon 0x%05x\n",
  1380.                 i, p->myAddr, p->myAddr, p->myAbConPtr);
  1381.             } else if (p->myAddr == (DataAddr) EMNIL) {
  1382.             KMDTrace("Invoke", 4,
  1383.             "Result #%d is NIL (with non-NIL AbCon)\n", i,
  1384.             p->myAddr);
  1385.             } else {
  1386.             KMDTrace("Invoke", 5,
  1387.                 "Result #%d OldODP 0x%05x  old AbConPtr 0x%05x\n",
  1388.                 i, p->myAddr, p->myAbConPtr);
  1389.             /* Translate ODP */
  1390.             p->myAddr     =
  1391.                 (DataAddr) Map_Lookup(req->m, (int) p->myAddr);
  1392.             assert(p->myAddr != (DataAddr) EMNIL);
  1393.             KMDTrace("Invoke", 5,
  1394.                 "After translate: (0x%05x, 0x%05x)\n",
  1395.                 p->myAbConPtr, p->myAddr);
  1396.             KMDTrace("Invoke", 4, "Result #%d Var %s\n", i,
  1397.                 PPVar((AVariablePtr) p));
  1398.             }
  1399.         }
  1400.         }
  1401.     }
  1402.     
  1403.     PUSHIT(s->regs.sp, req->returnAddr);
  1404.     
  1405.     KMDTrace("Invoke", 3, "%s Invoke Reply from %s\n",
  1406.         PPPOID(s->processOID), PPGOID(req->i.targetOID));
  1407.  
  1408.     /* Clean up */
  1409.  
  1410.     Map_Destroy(req->m);
  1411.     Map_Destroy(req->neededMap);
  1412.     Set_Destroy(req->newSet);
  1413.     
  1414.     FreeRequest((GenericReqPtr) s->invokePtr);
  1415.     s->invokePtr = (GenericPtr) NULL;
  1416.  
  1417.     schedule(s);
  1418.     
  1419.     break;
  1420.     }
  1421.     default: {
  1422.     ErrMsg("Bad move status %d in InvokeReplyCallBack\n", req->status);
  1423.     abort();
  1424.     }
  1425.     }
  1426. }
  1427.  
  1428. /************************************************************************/
  1429. /************************************************************************/
  1430.  
  1431. HResult PingReqHandler(fMsg)
  1432. EmMsgPtr            fMsg;
  1433. {
  1434.     PingReqItemPtr  pingPtr;
  1435.     PongReqItemPtr  pongPtr;
  1436.     EmMsgPtr        replyPtr;
  1437.     int             size = sizeof(MessageHeader) + sizeof(PingReqItem);
  1438.     KKStatus        kstat;
  1439.  
  1440.     pingPtr = (PingReqItemPtr) &(fMsg->itemHdr);
  1441.  
  1442.     if (pingPtr->hdr.itemTag != PingITag) {
  1443.     DebugMsg(1, "PingReq: Bad item tag = %d\n", pingPtr->hdr.itemTag);
  1444.     MMDeallocateMsg((MessagePtr) fMsg);
  1445.     return;
  1446.     }
  1447.     DebugMsg(2, "PingReq from LNN %d, reqId %d replying ...\n",
  1448.     pingPtr->pingLNN, pingPtr->reqId);
  1449.     kstat = MMAllocateMsg(size, (MessagePtr *)&replyPtr);
  1450.     assert(mSUCCESS(kstat));
  1451.     pongPtr = (PongReqItemPtr) &(replyPtr->itemHdr);
  1452.     pongPtr->hdr.itemTag = PongITag;
  1453.     pongPtr->hdr.size = sizeof(PongReqItem);
  1454.     pongPtr->reqId = pingPtr->reqId;
  1455.     pongPtr->pongLNN = GetLNN();
  1456.     MMBuildMsg((MessagePtr)replyPtr, KMSG_EmKernel, EMKM_PongReq,
  1457.       pingPtr->pingLNN, (unsigned)size);
  1458.     kstat = MMSendMsg((MessagePtr) replyPtr);
  1459.     if ( !mSUCCESS(kstat) ) {
  1460.     DebugMsg(1, "Could not send pong msg, status 0x%05x\n", kstat);
  1461.     PutEdenMsg((int)kstat, (FILE *)NULL, (char **)0);
  1462.     }
  1463.     MMDeallocateMsg((MessagePtr) fMsg);
  1464.     MMDeallocateMsg((MessagePtr) replyPtr);
  1465. }
  1466.  
  1467.  
  1468. HResult PongReqHandler(fMsg)
  1469. EmMsgPtr            fMsg;
  1470. {
  1471.     PongReqItemPtr  pongPtr = (PongReqItemPtr) &fMsg->itemHdr;
  1472.  
  1473.     if (pongPtr->hdr.itemTag != PongITag) {
  1474.     DebugMsg(1, "PongReq: Bad item tag = %d\n", pongPtr->hdr.itemTag);
  1475.     MMDeallocateMsg((MessagePtr) fMsg);
  1476.     return;
  1477.     }
  1478.     DebugMsg(1, "PongReply recieved from LNN %d, reqId %d\n",
  1479.         pongPtr->pongLNN, pongPtr->reqId);
  1480.     MMDeallocateMsg((MessagePtr) fMsg);
  1481. }
  1482.  
  1483.  
  1484. void RIPing(fLNN)
  1485. int fLNN;
  1486. {
  1487.     register PingReqItemPtr pingPtr;
  1488.     EmMsgPtr                pingMsg;
  1489.     int                     size = sizeof(MessageHeader)+sizeof(PingReqItem);
  1490.     KKStatus                kstat;
  1491.  
  1492.     KMDPrint("RIPing, sending ping to LNN %d\n", fLNN);
  1493.     kstat = MMAllocateMsg(size, (MessagePtr *)&pingMsg);
  1494.     assert(mSUCCESS(kstat));
  1495.     pingPtr = (PingReqItemPtr) &pingMsg->itemHdr;
  1496.     pingPtr->hdr.itemTag = PingITag;
  1497.     pingPtr->hdr.size = sizeof(PingReqItem);
  1498.     pingPtr->reqId = nextPingId++;
  1499.     pingPtr->pingLNN = GetLNN();
  1500.     MMBuildMsg((MessagePtr)pingMsg, KMSG_EmKernel, EMKM_PingReq, fLNN,
  1501.       (unsigned)size);
  1502.     kstat = MMSendMsg((MessagePtr) pingMsg);
  1503.     if ( !mSUCCESS(kstat) ) {
  1504.     KMDPrint("Could not send ping msg, status 0x%05x\n", kstat);
  1505.     }
  1506.     MMDeallocateMsg((MessagePtr) pingMsg);
  1507.     KMDPrint("The pong reply will be printed on the kernel stdout\n");
  1508. }
  1509.  
  1510. /************************************************************************/
  1511. /*      LM Ping-pong message protocol:                                  */
  1512. /*      Ping messages can be sent kernel-kernel at anytime.             */
  1513. /*      The receiving kernel merely responds with a pong message.       */
  1514. /*      Usefullness: For testing the connection between kernels.        */
  1515. /************************************************************************/
  1516.  
  1517. HResult LMPingReqHandler();
  1518. void LMPing();
  1519.  
  1520. HResult LMPingReqHandler(fHandle)
  1521. LMHandle              fHandle;
  1522. {
  1523.     LMHandle        myHandle = fHandle;
  1524.     int             length, i, sum;
  1525.  
  1526.     sum = 0;
  1527.     do {
  1528.     length = 4;
  1529.     LMGetData(&myHandle, &i, &length);
  1530.     if (length >0) {
  1531.         sum += length;
  1532.         printf(" %4d", i);
  1533.         if (i % 14 == 0) printf("\n");
  1534.     }    
  1535.     } while (length > 0);
  1536.     printf("\nLong Msg total data length = %d\n", sum);
  1537.     LMClose(&myHandle);
  1538. }
  1539.  
  1540. void LMPing(fLNN)
  1541. int fLNN;
  1542. {
  1543.     LMHandle                myHandle;
  1544.     int                     i;
  1545.     HOTSRecord             *HOTSPtr;
  1546.  
  1547.     KMDPrint("LMPing, sending LMping to LNN %d, size = %d\n", fLNN,
  1548.     vLMPingDataSize);
  1549.     if (!mSUCCESS(HOTSSearchPtr(fLNN, &HOTSPtr)) ||
  1550.     ((HOTSPtr->NodeStat != Alive) && (HOTSPtr->NodeStat != Booting))
  1551.     ) {
  1552.     KMDPrint("Node %d not alive\n", fLNN);
  1553.     return;
  1554.     }
  1555.     LMStartMsg(&myHandle, KMSG_EmKernel, EMKM_LMPingReq, fLNN);
  1556.     for (i = 0; i < vLMPingDataSize; i += 4) {
  1557.     LMPutData(&myHandle, &i, 4);
  1558.     }
  1559.     LMSendMsg(&myHandle);
  1560.     KMDPrint("There will not be a reply.\n");
  1561. }
  1562.  
  1563. void LMSetPingDataSize(fInt)
  1564. {
  1565.     KMDPrint("Changing PingDataSize to %d\n", fInt);
  1566.     vLMPingDataSize = fInt;
  1567. }
  1568.  
  1569. /**********************************************************************/
  1570. /* Snapshot */
  1571. void INVKInitiallyMap()
  1572. {
  1573.     InitiallyReqPtr             req;
  1574.     Map                         theMap;
  1575.     GODP                        theGODP;
  1576.     int                         dummy;
  1577.  
  1578.     Map_For(InitiallyMap, theGODP, theMap)
  1579.     KMDPrint("Initially map for 0x%05x (%s), %d entr%s\n", theGODP,
  1580.         PPGOID(theGODP->ownOID), Map_Count(theMap),
  1581.         mPLURALY(Map_Count(theMap)));
  1582.     Map_For(theMap, req, dummy);
  1583.         KMDPrint("%s in %s\n", PPPOID(req->theProcess->processOID),
  1584.         PPSSPlace(req->theProcess));
  1585.     Map_Next
  1586.     Map_Next
  1587. }
  1588.  
  1589. /**********************************************************************/
  1590. /* Snapshot */
  1591. void INVKFrozenMap()
  1592. {
  1593.     IncomingIReqPtr             req;
  1594.     Set                         reqSet;
  1595.     GODP                        theGODP;
  1596.     OID                         theOID;
  1597.     
  1598.     Map_For(FrozenMap, theOID, reqSet)
  1599.         theGODP                 = (GODP) OTLookup(theOID);
  1600.     KMDPrint("Initially map for 0x%05x (%s), %d entr%s\n", theGODP,
  1601.         PPGOID(theGODP->ownOID), Set_Count(reqSet),
  1602.         mPLURALY(Map_Count(reqSet)));
  1603.     Set_For(reqSet, req)
  1604.         KMDPrint("%s in %s\n", PPPOID(req->theProcess->processOID));
  1605.     Set_Next
  1606.     Map_Next
  1607. }
  1608.  
  1609. /**********************************************************************/
  1610.  
  1611. void InvokeInit()
  1612. {
  1613.     KMDTrace("Invoke", 5, "InvokeInit\n");
  1614.  
  1615.     MMDefineMsgHandler(KMSG_EmKernel, EMKM_InvokeReq, 
  1616.       (HandlerPtr)InvokeHandler, (HandlerPtr *)NULL);
  1617.     MMDefineMsgHandler(KMSG_EmKernel, EMKM_InvokeReply, 
  1618.       (HandlerPtr)InvokeReplyHandler, (HandlerPtr *)NULL);
  1619.     MMDefineMsgHandler(KMSG_EmKernel, EMKM_PingReq, 
  1620.       (HandlerPtr) PingReqHandler, (HandlerPtr *)NULL);
  1621.     MMDefineMsgHandler(KMSG_EmKernel, EMKM_PongReq, 
  1622.       (HandlerPtr)PongReqHandler, (HandlerPtr *)NULL);
  1623.     MMDefineMsgHandler(KMSG_EmKernel, EMKM_LMPingReq, 
  1624.       (HandlerPtr)LMPingReqHandler, (HandlerPtr *)NULL);
  1625.  
  1626.     KMDSetSnap(RIPing);  /* Define a snapshot to asynchronously send a ping */
  1627.     KMDSetSnap(LMPing);  /* Define a snapshot to asynchronously send a ping */
  1628.     KMDSetSnap(LMSetPingDataSize);
  1629.     KMDSetVar(vLMPingDataSize);
  1630.     KMDSetTrace(Invoke);
  1631.     
  1632.     InitiallyMap        = Map_Create();
  1633.     FrozenMap           = Map_Create();
  1634.     
  1635.     KMDSetSnap(INVKInitiallyMap);
  1636.     KMDSetSnap(INVKFrozenMap);
  1637. }
  1638.  
  1639.