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

  1.  
  2. /*
  3.  * @(#)kOps.c    1.8  2/23/90
  4.  */
  5.  
  6. /* Copyright 1986 Eric Jul.  May not be used for any purpose without    */
  7. /* written permission from the author.                            */
  8. /* The Emerald kernel for the Emerald programming language.             */
  9.  
  10. /* Version 5.0 started 1986-05-10, eric */
  11. /* Initial version started 1985-07-10, eric */
  12.  
  13. /* This file contains the implementation of the Emerald kernel operations
  14.    as defined in the Kernel Interface Specification.
  15.    Monitor and condition operations, process management.
  16.    Initialization.
  17. */
  18.  
  19. #include <sys/types.h>
  20. #include <stdio.h>
  21.  
  22. #ifdef xkernel
  23. #include "userupi.h"
  24. #include "userprocess.h"
  25. #endif
  26.  
  27. #include "Kernel/h/system.h"
  28. #include "Kernel/h/assert.h"
  29. #include <sys/time.h>
  30. #include <sys/dir.h>
  31. #include "Kernel/h/macros.h"
  32. #include "Kernel/h/expandArray.h"
  33. #include "Kernel/h/emTypes.h"
  34. #include "Kernel/h/timerTypes.h"
  35. #include "Kernel/h/kmdTypes.h"
  36. #include "Kernel/h/kEvents.h"
  37. #include "Kernel/h/mmTypes.h"
  38. #include "Kernel/h/mmMsgTypes.h"
  39. #include "Kernel/h/lmTypes.h"
  40. #include "Kernel/h/emkDefs.h"
  41. #include "Kernel/h/builtins.h"
  42. #include "Kernel/h/emeraldTypes.h"
  43. #include "Kernel/h/consts.h"
  44. #include "Kernel/h/map.h"
  45. #include "Kernel/h/set.h"
  46. #include "Kernel/h/regdefs.h"
  47. #include "Kernel/h/utils.h"
  48.  
  49. #include "ementryext.h"
  50.  
  51. #include "Kernel/Em/reqBuiltins.c"
  52.  
  53. #define NEWCREATERETURN
  54.  
  55. extern int etext;
  56.  
  57. extern void emPause(), QueueTask();
  58.  
  59. extern Map InitiallyMap, FrozenMap;
  60. extern void TryInvoke();
  61.  
  62. extern void MallocInit(), FLInit(), LocateInit(), InvokeInit(), OTInsert(),
  63.     IOInit(), CPInit(), ItemInit(), StreamInit(), MeasureInit(), MoveInit(),
  64.     TimeSlicerInit(), LMInit(), OIDInit(), TimingInit(), UnixStreamInit(),
  65.     RequestInit(),
  66.     ConformInit(), EmallocInit(), GCInit(), NodeInit(), UtilsInit(), XInit();
  67. #ifdef INCLUDE_MLP
  68. extern void MLPInit();
  69. #endif
  70.  
  71. extern ODP OTLookup(), getFreeOD();
  72.  
  73. extern int ReturnOffStack;  /* Label in assembly code (!) */
  74. extern char EMDIR[];
  75.  
  76. extern EmTimePtr Node_getTimeOfDay();
  77. extern void Node_system();
  78. extern float Node_getLoadAverage();
  79. extern int Node_getLNN(), Node_getName();
  80. extern void Node_setNodeEventHandler(), Node_removeNodeEventHandler(),
  81.     Node_getActiveNodes(), Node_getAllNodes(),
  82.     Node_getNodeInformation();
  83.  
  84. extern void IOPutString(), IOPutInt(), IOPutReal();
  85.  
  86. extern void InsertDQ();
  87.  
  88. extern ODP KernelCheatingCreate();
  89.  
  90. extern DQueuePtr RemoveDQ();
  91.  
  92. extern HResult InvokeHandlerCallBack();
  93.  
  94. void NotImplemented(), EmTrace();   /* Forward */
  95. void DoStackBreakReturn();          /* Forward */
  96.  
  97. /* Forward */ 
  98. void             DumpCondMap();
  99. /* Forward */ 
  100. void             LineNumber();
  101.  
  102. extern TemplatePtr      FindTemplate();
  103. extern OID              getNextOID();
  104.  
  105. extern void             SetHandler();
  106.  
  107. extern void             FixInvokeQueue();
  108.  
  109. extern AbConPtr         OIDOIDOIDToAbCon();
  110.  
  111. /*  Current execution environment
  112.     includes the ODPs for the combination.
  113. */
  114.  
  115.  
  116. /* The following describe the running process and the ready queue */
  117.  
  118. SSPtr                   currentSSP;         /* the current process */
  119. SSAddr                  splimit;            /* stack limit for ditto */
  120. Boolean                 preemptFlag;        /* true if kernel wants CPU */
  121. SSPtr            readyQ;             /* ready processes */
  122. SSPtr                   stoppedQ;           /* stopped processes */
  123. DQueue                  hasRunDQ;           /* has run lately */
  124. DQueue                  dormantDQ;          /* dormant lately */
  125.  
  126. int                     cEmRunnable;        /* # currently runnable */
  127. int                     cEmTimeSlicings;    /* # of process switch forced */
  128.  
  129. SSPtr                   standbyQueue;       /* stacks on hot standby */
  130. int                     cEmStandbyCount;    /* count of them */
  131. #define DEFAULTHOTSTANDBYMAX 20             /* Max stack segs to retain */
  132. int                     vEmStandbyMax =     DEFAULTHOTSTANDBYMAX;
  133. int                     vEmStdStackSize =   STDSTACKSIZE;
  134. int                     vEmMaxStackSize =   DEFAULTMAXSTACKSIZE;
  135.  
  136. #define INITIALCONDMAPSIZE  1024 /* Initial number of conditions*/
  137. /*
  138.  * CondMap:  For every MonitorLock this map contains a Set of all the
  139.  * Conditions that are tied to the MonitorLock.  It is used for mobility
  140.  * purposes only:  when moving a MonitorLock, the Condtion objects tied to it
  141.  * MUST also be moved.  This map enables the mobility code to find the
  142.  * Condition objects given a MonitorLock.
  143.  */
  144. Map                     condMap;
  145.  
  146. /*
  147.  * Debugging aids:
  148.  * lastJumpFrom         the compiler has a switch (-gd, I think) that makes it
  149.  *                      generate a store of the current IP into this variable
  150.  *                      before every computed jump.  (Used for debugging
  151.  *                      compiler/kernel.)
  152.  * emTracing            When set, enables line number tracing.
  153.  *                      Turned on and off by LineNumber trace.
  154.  *                      Code must have been compiled using the -gt switch.
  155.  * Both these variables are accessed by compiled code and thus they are part
  156.  * of the compiler/kernel interface.
  157.  */
  158.  
  159. int                     lastJumpFrom;       /* Last addr jumped from */
  160. int                     emTracing;          /* TRUE iff line number tracing*/
  161.  
  162. /* Local variables */
  163. DataAddr                kernelsp;           /* kernel sp on every entry */
  164.  
  165. /* Standard tags for creating new ODs */
  166. ODTag                   stdNULLTag;
  167. ODTag            stdGODTag, stdGODataTag, stdSSODTag, stdSSTag,
  168.             stdLODataTag, stdDotoODTag, stdAbConTag,
  169.             stdCodeTag, stdCodeODTag, stdProcessODTag;
  170.  
  171. /* For printing of the names (cf. utils.c) */
  172. extern char            *BasicTagName[], *BrandNames[];
  173.  
  174. extern float            MachineLoadAvg();
  175.  
  176. extern Boolean          LoadRequest();
  177.  
  178. extern Boolean         PPValidAddr();
  179.  
  180. EmLocation              thisNodeLocation; /* The location of our node   */
  181. OID                     thisNodeObjectOID;
  182. CodeODP                 thisNodeCTODP;
  183. CodePtr                 thisNodeCodePtr;
  184. GODP                    thisNodeODP;
  185.  
  186. OID                     nodeListCTOID, nodeListElementCTOID,
  187.             nodeListElementATOID;
  188. CodeODP                 nodeListCTODP, nodeListElementCTODP,
  189.             nodeListElementATODP;
  190. CodePtr                 nodeListCodePtr, nodeListElementCodePtr;
  191. AbConPtr                nodeListElementAbCon, nodeAbCon;
  192.  
  193. CodeODP                 timeODP;
  194. AbConPtr                timeAbCon;
  195.  
  196. CodePtr                 stringCodePtr, timeCodePtr;
  197.  
  198.  
  199. #define mDQPtrToSSP(fDQPtr) \
  200.     ((SSPtr) addOffset(fDQPtr, - SS_ssDQ))
  201.  
  202. /************************************************************************/
  203. /* Processes are timesliced on a round-robin basis every vEmTimeSlice   */
  204. /* milliseconds.  Time slicing is only active if there are more than    */
  205. /* two runnable processes.                                              */
  206. /************************************************************************/
  207.  
  208. #ifdef xkernel
  209. #define EMTIMESLICE    100                   /* in milliseconds        */
  210. #else
  211. #define EMTIMESLICE     10                   /* in milliseconds          */
  212. #endif
  213. #define MINTIMESLICE    1                    /* (Unix rounds up anyway)  */
  214. int            vEmTimeSlice = EMTIMESLICE;
  215. int                 TimeSlicerActive = 0;   /* TRUE iff time slicer runs*/
  216. struct itimerval    oldSliceVal;
  217. struct itimerval    timeSliceVal =          /* for setting timer */
  218.             { {0,0}, {EMTIMESLICE/1000,(EMTIMESLICE%1000)*1000}};
  219.  
  220. /* Save area for the line number call code */
  221. int registerSave[16];
  222.  
  223. /**********************************************************************/
  224. /*          E N D   O F   D A T A   D E F I N I T I O N S             */
  225. /**********************************************************************/
  226.  
  227.  
  228. /**********************************************************************/
  229. /*  EmeraldSigUpCall                                                  */
  230. /*  Called from the real Ultrix signal handler to inform the Emerald  */
  231. /*  kernel that an Ultrix signal has occurred.                        */
  232. /**********************************************************************/
  233.  
  234. /*ARGSUSED*/
  235. void EmeraldSigUpCall(sig)
  236. int sig;
  237. /* A real signal has arrived -- make the current preempt itself.      */
  238. {
  239.     
  240.     /* WARNING:  This routine is called even if signals are held */
  241.     /* Setting the preempt flag causes processes to preempt themselves*/
  242.     /* at the bottom of the next loop. */
  243.  
  244.     preemptFlag = 1;
  245.  
  246.     /* Setting splimit to kernelsp causes the current process to fail */
  247.     /* the next stackcheck (i.e., at the next invocation) and invoke  */
  248.     /* the kernel which may then preempt it.                          */
  249.     /* Note: kernelsp is a well-known address in the high part of     */
  250.     /* memory.  Any high address would do.                            */
  251.  
  252.     splimit = kernelsp;
  253. }
  254.  
  255. /**********************************************************************/
  256. /*  Queueing routines for Activation Records                          */
  257. /*  In the future, these routines will be replaced by assembly code   */
  258. /*  since the VAX has machine instructions for these operations.      */
  259. /*  The assembly routines are in utils.c                              */
  260. /*  The following routines may be used on SUNs                        */
  261. /**********************************************************************/
  262.  
  263. #define getNextAR(f) \
  264.     ( (f)->next)
  265.  
  266. #define setNextAR(f, newARLink) \
  267.     (f)->next = newARLink
  268.  
  269. #define getPrevAR(f) \
  270.     ( (f)->prev )
  271.  
  272. #define setPrevAR(f, newARLink) \
  273.     (f)->prev = newARLink
  274.  
  275.  
  276. #define initARListHead(headODP) \
  277.     headODP->ARListHead.next = headODP->ARListHead.prev = \
  278.     &headODP->ARListHead
  279.  
  280. #define enterAR(headODP, newElem) \
  281.     if (headODP->ARListHead.next == headODP->ARListHead.prev) { \
  282.     /* Insert into empty list */ \
  283.     headODP->ARListHead.next = headODP->ARListHead.prev = newElem; \
  284.     newElem->next = \
  285.     newElem->prev = & headODP->ARListHead; \
  286.     } else { \
  287.     /* Insert at front of non-empty list */ \
  288.     setNextAR(newElem, getNextAR(&headODP->ARListHead)); \
  289.     setPrevAR(newElem, & headODP->ARListHead); \
  290.     setPrevAR(getNextAR(&headODP->ARListHead), newElem); \
  291.     setNextAR(&headODP->ARListHead, newElem); \
  292.     }; \
  293.     DebugMsg(5, \
  294.     "enterAR: Head OID (0x%04x) = (0x%04x, 0x%04x); newelem(0x%04x) = (0x%04x, 0x%04x)\n", \
  295.     headODP->ownOID, &headODP->ARListHead, \
  296.     getNextAR(&headODP->ARListHead), getPrevAR(&headODP->ARListHead), \
  297.     newElem, getNextAR(newElem), getPrevAR(newElem));
  298.  
  299. #define removeAR(headODP, elem) \
  300.     { \
  301.     InvokeQueuePtr        next, prev; \
  302.     DebugMsg(5, "removeAR: 0x%04x from object 0x%05x\n", \
  303.         elem, headODP->ownOID); \
  304.     /* Remove from queue */ \
  305.     next = getNextAR(elem); \
  306.     prev = getPrevAR(elem); \
  307.     DebugMsg(5, "next 0x%04x, prev 0x%04x\n", next, prev); \
  308.     setNextAR(prev, next); \
  309.     setPrevAR(next, prev); \
  310.     DebugMsg(5, \
  311.     "removeAR: Head OID 0x%04x = (0x%04x, 0x%04x)\n", \
  312.     headODP->ownOID, &(headODP->ARListHead), \
  313.     headODP->ARListHead.next, headODP->ARListHead.prev ); \
  314.     }
  315.  
  316. /************************************************************************/
  317.  
  318. /* The following routines are probably obsolete, Jan. 1987, Eric Jul    */
  319. void DoEnqueue()
  320. {
  321.     InvokeQueuePtr actRecIQ;
  322.     actRecIQ = mInvokeQueuePtrFromL(currentSSP->regs.l);
  323.     DebugMsg(3,
  324.         "Entering ActRecord l=0x%06x into object OID 0x%05x list.\n",
  325.         currentSSP->regs.l, currentSSP->regs.b -> ownOID);
  326.     enterAR (currentSSP->regs.b, actRecIQ);
  327. }
  328.  
  329. void DoDequeue()
  330. {
  331.     InvokeQueuePtr    actRecIQ;
  332.     actRecIQ = mInvokeQueuePtrFromL(currentSSP->regs.l);
  333.     DebugMsg(3,
  334.     "Removing ActRecord l=0x%06x from global object OID %d list.\n",
  335.     currentSSP->regs.l, currentSSP->regs.b->ownOID);
  336.     removeAR(currentSSP->regs.b, actRecIQ);
  337. }
  338.  
  339. #ifdef OBSOLETEJAN1987
  340. void RmvFromInvkQueue(fGODP, fL)
  341. GODP        fGODP;
  342. SSAddr      fL;
  343. /* Remove the activation pointed to by fL from the invoke queue of fGODP,
  344.    if it is there */
  345. {
  346.    /* Note (Eric Jul, Jan. 1987) This procedure should be replaced
  347.     * by calls to EnsureRemovedFromInvokeQueue.
  348.     */
  349.  
  350.     register InvokeQueuePtr     p, thisOne, head;
  351.     thisOne = mInvokeQueuePtrFromL(fL);
  352.     head = &fGODP->ARListHead;
  353.     for (p=head->next; p != head && p != thisOne; p = p->next);
  354.     if (p == thisOne) {
  355.     KMDTrace("InvokeQueue", 3, "Removing AR 0x%06x from IQ of 0x%08x\n",
  356.         fL, fGODP);
  357.     removeAR(fGODP, thisOne);
  358.     }
  359. }
  360. #endif OBSOLETEJAN1987
  361.  
  362. /**********************************************************************/
  363. /*      EnsureRemovedFromInvokeQueue                                  */
  364. /**********************************************************************/
  365. void EnsureRemovedFromInvokeQueue(fL)
  366. SSAddr                  fL;
  367. /* If the given activation record is in an Invoke Queue then remove it */
  368. {
  369.     InvokeQueuePtr      iq;
  370.     
  371.     KMDTrace("InvokeQueue", 3, "Ensuring that AR 0x%04x is not in any IQ\n",
  372.     fL);
  373.     iq                  = mInvokeQueuePtrFromL(fL);
  374.     if ((int) iq->mySSPtr < 0) {
  375.         KMDTrace("InvokeQueue", 5, "Removed from IQ\n");
  376.     iq->mySSPtr = (SSPtr) ( - (int) iq->mySSPtr);
  377.     (void) RemoveDQ((DQueuePtr) iq);
  378.     }
  379. }
  380.  
  381. /**********************************************************************/
  382. /**********************************************************************/
  383.  
  384. /**********************************************************************/
  385. /*      FindParamSizes                                                */
  386. /**********************************************************************/
  387. void FindParamSizes(fRegsPtr, fIP, fArgCountPtr, fResultCountPtr)
  388. RegisterSavePtr         fRegsPtr;
  389. CodeAddr                fIP;
  390. int                    *fArgCountPtr, *fResultCountPtr; /* return values */
  391. /* Given a register area describing an AR, find the number of arguments
  392.  * and results.
  393.  */
  394. {
  395.     CodePtr                     cPtr;
  396.     Offset                      ipOffset, templateOffset;
  397.     IPMapPtr                    templateMap;
  398.     TemplatePtr                 tPtr;
  399.     register int                i, argCount, resultCount;
  400.     register TemplateEntryPtr   t;
  401.     
  402.     argCount = resultCount = 0;
  403.     
  404.     /* Find the template */
  405.     assert(NonNULL(fRegsPtr->g));
  406.     cPtr            = fRegsPtr->g->myCodePtr;
  407.     assert(NonNULL(cPtr));
  408.     ipOffset= (Offset) byteOffset(cPtr, fIP);
  409.     assert(NonNULL(cPtr->templateMapOffset));
  410.     templateMap     = (IPMapPtr) addOffset(cPtr, cPtr->templateMapOffset);
  411.     assert(NonNULL(templateMap));
  412.     templateOffset  = (Offset) IPMapLookup(templateMap, ipOffset);
  413.     assert(NonNULL(templateOffset));
  414.     tPtr            = (TemplatePtr) addOffset(cPtr, templateOffset);
  415.     assert(NonNULL(tPtr));
  416.  
  417.     t               = &tPtr->entry[0];
  418.     for (i = 0; i < tPtr->B.numEntries; i++) {
  419.  
  420.     switch (t->TE.SS.Format) {
  421.     
  422.     case ShortStaticF: {
  423.         KMDTrace("Stack", 5,
  424.         "\tShortStaticF\t(%s) %s\tcount =%4d\n", 
  425.         BrandNames[(int)t->TE.SS.theBrand],
  426.         t->TE.SS.paramInfo != IsNotParam ? "isParam" : " ",
  427.         t->TE.SS.count);
  428.         if (t->TE.SS.paramInfo != IsNotParam)
  429.         switch (t->TE.SS.theBrand) {
  430.  
  431.         case VariableBrand: {
  432.         if (t->TE.SS.paramInfo == IsArgument) {
  433.             argCount += t->TE.SS.count;
  434.         } else resultCount += t->TE.SS.count;
  435.         break;
  436.         }
  437.         
  438.         default: {
  439.         ErrMsg("Bad brand %d in FindParamSizes\n", t->TE.SS.theBrand);
  440.                 abort();
  441.         break;
  442.         }
  443.  
  444.         } /* end switch */
  445.  
  446.         t = (TemplateEntryPtr) addOffset(t, sizeof(ShortStatic));
  447.         break;
  448.     }
  449.  
  450.     case RegisterF: {
  451.             break;
  452.     } /* case RegisterF */
  453.     
  454.     default: {
  455.         ErrMsg("Bad format %d in FindParamSizes\n", t->TE.SS.Format);
  456.         abort();
  457.         break;
  458.     } /* default action */
  459.  
  460.     } /* switch on t->TE.SS.Format */
  461.     } /* for (i = 0; ...) */
  462.     
  463.     *fArgCountPtr           = argCount;
  464.     *fResultCountPtr        = resultCount;
  465.     
  466.     KMDTrace("Move", 5, "%d arg%s, %d result%s for AR at %s\n", argCount,
  467.         mPLURAL(argCount), resultCount, mPLURAL(resultCount),
  468.     PPRegsPlace(fRegsPtr, fIP));
  469. }
  470.  
  471. /**********************************************************************/
  472. /*      MoveDownStack                                                 */
  473. /**********************************************************************/
  474.  
  475. Boolean MoveDownStack(fRegsPtr, fCurrentIP)
  476. register RegisterSavePtr    fRegsPtr;
  477. CodeAddr                   *fCurrentIP;
  478. /*
  479.  * Move down the stack by going down one activation record
  480.  * Return false iff bottom reached
  481.  */
  482. {
  483.     /*
  484.      * This relatively simple procedure merely involves restoring the
  485.      * register from the DynamicLink.  Unfortunately, we must also
  486.      * restore the variables that have been allocated in registers.
  487.      * This complicates matters since we must traverse the template
  488.      * looking for registers that were saved in the AR.
  489.      * At the same time, we must keep track of the current address in
  490.      * the AR, since the register save area may appear anywhere.
  491.      */
  492.    
  493.     register DynamicLinkPtr     link;
  494.     CodePtr                     cPtr;
  495.     Offset                      unwindFromOffset, templateOffset;
  496.     IPMapPtr                    templateMap;
  497.     TemplatePtr                 tPtr;
  498.     int                         i;
  499.     SSAddr                      sAddr;
  500.     TemplateEntryPtr            t;
  501.     
  502.     link = mDynLinkPtrFromL(fRegsPtr->l);
  503.     if (IsNULL(link->l)) {
  504.     fRegsPtr->l = link->l;
  505.     fRegsPtr->b = link->b;
  506.     fRegsPtr->g = link->g;
  507.     fRegsPtr->sp= (SSAddr) (link+1);
  508.        *fCurrentIP  = link->ip;
  509.     return FALSE;
  510.     }
  511.     
  512.     /* Find the template */
  513.     cPtr            = fRegsPtr->g->myCodePtr;
  514.     assert(NonNULL(cPtr));
  515.     unwindFromOffset= (Offset) byteOffset(cPtr, *fCurrentIP);
  516.     assert(NonNULL(cPtr->templateMapOffset));
  517.     templateMap     = (IPMapPtr) addOffset(cPtr, cPtr->templateMapOffset);
  518.     assert(NonNULL(templateMap));
  519.     templateOffset  = (Offset) IPMapLookup(templateMap, unwindFromOffset);
  520.     assert(NonNULL(templateOffset));
  521.     tPtr            = (TemplatePtr) addOffset(cPtr, templateOffset);
  522.     assert(NonNULL(tPtr));
  523.  
  524.     sAddr           = (SSAddr) link;
  525.     t               = &tPtr->entry[0];
  526.     for (i = 0; i < tPtr->B.numEntries; i++) {
  527.  
  528.     switch (t->TE.SS.Format) {
  529.     
  530.     case ShortStaticF: {
  531.         KMDTrace("Stack", 5,
  532.         "\tShortStaticF\t(%s) %s\tcount =%4d\n", 
  533.         BrandNames[(int)t->TE.SS.theBrand],
  534.         t->TE.SS.paramInfo != IsNotParam ? "isParam" : " ",
  535.         t->TE.SS.count);
  536.         if (t->TE.SS.paramInfo == IsNotParam)
  537.         switch (t->TE.SS.theBrand) {
  538.  
  539.         case DataBrand: {
  540.         sAddr = (SSAddr)
  541.             addOffset(sAddr, -t->TE.SS.count);
  542.         break;
  543.         }
  544.         
  545.         case ODPBrand: {
  546.         sAddr = (SSAddr)
  547.             addOffset(sAddr, -sizeof(ODP)*t->TE.SS.count);
  548.         break;
  549.         }
  550.         
  551.         case AddrBrand:{
  552.         assert(t->TE.SS.theBrand != AddrBrand);
  553.         break;
  554.         }
  555.  
  556.         case VectorBrand: {
  557.         break;
  558.         } /* case Vector Brand */
  559.         
  560.         case VariableBrand: {
  561.         sAddr = (SSAddr)
  562.             addOffset(sAddr, -sizeof(AVariable)*t->TE.SS.count);
  563.         break;
  564.         }
  565.         
  566.         case MonitorBrand: {
  567.         sAddr = (SSAddr)
  568.             addOffset(sAddr, -sizeof(MonitorLock));
  569.         break;
  570.         }
  571.         
  572.         case InvokeQueueBrand: {
  573.         sAddr = (SSAddr) addOffset(sAddr, -sizeof(InvokeQueue));
  574.         break;
  575.         }
  576.         
  577.         default: {
  578.         ErrMsg("Bad brand %d in MoveDownStack\n", t->TE.SS.theBrand);
  579.         break;
  580.         }
  581.  
  582.         } /* end switch */
  583.  
  584.         t = (TemplateEntryPtr) addOffset(t, sizeof(ShortStatic));
  585.         break;
  586.     }
  587.  
  588.     case RegisterF: {
  589.         int             k;
  590.         
  591.         KMDTrace("Stack", 5,
  592.         "\tRegisterF\t(%s),\t%s, r%d, count %d\n",
  593.         BrandNames[(int)t->TE.R.theBrand], 
  594.         t->TE.R.storedWhere == InRegister ? "InRegister"
  595.         : "InSaveArea", t->TE.R.reg, t->TE.R.count);
  596.         if (t->TE.R.storedWhere == InSaveArea) {
  597.         for (k = t->TE.R.count - 1 ; k >= 0; k--) {
  598.             /* Registers are stored low number, low addr */
  599.             sAddr--; /* Since we are going backwards, do -- first */
  600.             /* The following check fails when the activation record
  601.             has only partially been allocated, e.g., before the
  602.             allocation phase of the operation preamble.  */
  603.             if (sAddr < fRegsPtr->sp) break;
  604.  
  605.             KMDTrace("Stack", 5,
  606.             "Restoring register r%d, was 0x%02x, new value 0x%02x\n", 
  607.             t->TE.R.reg+k,
  608.             mGetSavedReg(fRegsPtr, t->TE.R.reg+k), *sAddr);
  609.  
  610.             mSetSavedReg(fRegsPtr, t->TE.R.reg+k,  *sAddr);
  611.         }
  612.         }
  613.         t = (TemplateEntryPtr) addOffset(t, sizeof(t->TE.R));
  614.         break;
  615.     } /* case RegisterF */
  616.     
  617.     default: {
  618.         KMDPrint("Bad format %d in MoveDownStack\n", t->TE.SS.Format);
  619.         assert(FALSE);
  620.         break;
  621.     } /* default action */
  622.  
  623.     } /* switch on t->TE.SS.Format */
  624.     } /* for (i = 0; ...) */
  625.     
  626.     fRegsPtr->l  = link->l;
  627.     fRegsPtr->g  = link->g;
  628.     fRegsPtr->b  = link->b;
  629.     fRegsPtr->sp = (SSAddr) (link+1);
  630.     *fCurrentIP  = link->ip;
  631.     
  632.     return TRUE;
  633. }
  634.  
  635. /**********************************************************************/
  636. /**********************************************************************/
  637.  
  638. #ifndef xkernel
  639. /**********************************************************************/
  640. /*      Pauseing                                                      */
  641. /**********************************************************************/
  642. doPause()
  643. {
  644.     struct TaskQueue *event;
  645.     int             (*handler)();
  646.     char            *argument;
  647.  
  648.     shouldPause = dontPause;
  649. doMore:
  650.     HoldSigs();
  651.     event = TaskDequeue(&TaskQ);
  652.     if (event != (struct TaskQueue *) NULL) {
  653.         handler = event->handler;
  654.         argument = event->arg;
  655.         enqueue((struct Queue *) &FreeQ, (struct Queue *) event);
  656.         ReleaseSigs();
  657.         DebugMsg(7, "Calling handler 0x%06x\n", handler);
  658.         (*handler)(argument);
  659.         goto doMore;
  660.     } else {
  661.         shouldPause =
  662.         (IsNULL(currentSSP) && IsNULL(readyQ) )
  663.         ? reallyPause : dontPause;
  664.         /* Here: The task queue is empty so we will 
  665.             get emPause to actually pause UNLESS
  666.             a process can run OR
  667.             some signal handler puts something on 
  668.             the task queue in which case TaskQueue 
  669.             will essentially make emPause a noop 
  670.             by setting emPause to dontPause.
  671.         */
  672.     }
  673.     ReleaseSigs();
  674.  
  675.         /*
  676.          * emPause now calls sigpause(2). Sigpause
  677.          * requires an argument saying which signals
  678.          * should be BLOCKED.  Therefore, give it
  679.          * 0 rather than potluck.
  680.         */
  681.  
  682.     if ( shouldPause == reallyPause ) {
  683.         DebugMsg(5, " ... will pause\n");
  684.         emPause(0);
  685.     }
  686. }
  687. #endif
  688. /**********************************************************************/
  689.  
  690. /* Stack Segment queueing:  Used for singly linked process queues
  691.  * for the running queue, monitor entry queues, and condition variable
  692.  * queues.
  693. */
  694.  
  695. void insertQ(fHead, fElem)
  696. register SSPtr            *fHead;
  697. register SSPtr             fElem;
  698. /* Insert a Stack Segment into a singly circularly linked queue.
  699.    Elements are assumed to be Stack Segments which have a link field
  700.    called readyQLink. */
  701. /* The head points to the LAST element of the queue.  Each queue element
  702.    is a SSOD;  the readyQLink field is used to point to
  703.    the SSOD for the next Stack Segment in the queue.
  704. */
  705. {
  706.     if (IsNULL(*fHead)) {
  707.     /* Insert into an empty queue */
  708.     *fHead = fElem;
  709.     setRQLink(fElem, fElem); /* (Circular link) */
  710.     } else {
  711.     setRQLink(fElem, getRQLink((*fHead)));
  712.     setRQLink((*fHead), fElem);
  713.     *fHead = fElem;
  714.     };
  715. }
  716.  
  717. SSPtr removeQ(fHead)
  718. register SSPtr            *fHead;
  719. /* Remove an element from the front of the singly circularly linked queue
  720.     indicated by fHead.
  721.     If the queue is empty then return NULL.
  722. */
  723. {
  724.     register SSPtr        removed;
  725.  
  726.     if ( IsNULL(removed = *fHead) ) {
  727.     /* queue is empty, return null */
  728.     } else if (getRQLink(removed) == removed) {
  729.     /* removing the only process -- null the queue */
  730.     *fHead = (SSPtr) NULL;
  731.     } else {
  732.     /* removing a process leaving the list non-empty */
  733.     removed = getRQLink((*fHead));
  734.     setRQLink((*fHead), getRQLink(removed));
  735.     };
  736.     return(removed);
  737. }
  738. /************************************************************************/
  739. /************************************************************************/
  740.  
  741. void TimeSliceInterrupt();
  742. /************************************************************************/
  743. /*  Time Slicer                                                         */
  744. /************************************************************************/
  745.  
  746. void StartTimeSlicer()
  747. /* Start the time slicing */
  748. {
  749.   TimeSlicerActive = 1;
  750.   KMDTrace("ProcessSwitch", 6, "Starting time slicing %d milliseconds.\n",
  751.        vEmTimeSlice);
  752. #ifdef BSD
  753.   if (setitimer(ITIMER_VIRTUAL, &timeSliceVal, &oldSliceVal)) {
  754.     perror("setitimer:");
  755.     assert(FALSE);
  756.   }
  757. #else
  758. #ifdef xkernel
  759.   if (timeSliceVal.it_value.tv_sec == 0 && timeSliceVal.it_value.tv_usec == 0) return;
  760.   xeventregister(TimeSliceInterrupt, 0,
  761.          timeSliceVal.it_value.tv_sec*1000+
  762.          timeSliceVal.it_value.tv_usec/1000, EV_ONCE);
  763. #endif
  764. #endif
  765. }
  766.  
  767. /* Forward */
  768. void            schedule(), fail();
  769. SSPtr           preemptRunning();
  770.  
  771. HResult TimeSliceHandler()
  772. /* Implements round robin Time Slicing */
  773. {
  774.     KMDTrace("ProcessSwitch", 5, "TimeSliceHandler\n");
  775.     TimeSlicerActive = 0;
  776.     if (cEmRunnable > 1) {
  777.     /* Round robin by moving it to the back of the ready queue */
  778.     if (NonNULL(currentSSP)) {
  779.         KMDTrace("ProcessSwitch", 4,
  780.         "TimeSliceHandler causing process preemption\n");
  781.         cEmTimeSlicings++;
  782.         schedule(preemptRunning());
  783.         /* Note: schedule will ensure that TimeSlicer continues */
  784.     } else {
  785.         KMDTrace("ProcessSwitch", 6, "TimeSlicer rescheduled\n");
  786.         StartTimeSlicer();
  787.     };
  788.     }
  789. }
  790.  
  791.  
  792. void TimeSliceInterrupt()
  793. /* Schedule a handler for the SIGVTALRM signal */
  794. {
  795. #ifdef xkernel
  796.     xkhandlerstart();
  797. #endif xkernel
  798.     HoldSigs();
  799.     QueueTask((HandlerPtr)TimeSliceHandler, (char *)NULL);
  800.     ReleaseSigs();
  801. #ifdef xkernel
  802.     xkhandlerend();
  803. #endif xkernel
  804. }
  805.  
  806.  
  807.  
  808. /* Snapshot */
  809. void ResetTimeSlicer(fNewInterval)
  810. /* Reset the time slicer to the specified interval */
  811. {
  812.     if (fNewInterval==0) {
  813.     KMDPrint("Turning off Time Slicing\n");
  814.     } else if (fNewInterval < MINTIMESLICE) {
  815.     KMDPrint("Time slice too small, must be at least %d milliseconds.\n",
  816.         MINTIMESLICE);
  817.     return;
  818.     } else {
  819.     KMDPrint("Resetting Time Slicing interval to %d milliseconds\n",
  820.         fNewInterval);
  821.     }
  822.     
  823.     vEmTimeSlice = fNewInterval;
  824.     timeSliceVal.it_value.tv_sec         = vEmTimeSlice / 1000;
  825.     timeSliceVal.it_value.tv_usec        = (vEmTimeSlice % 1000) * 1000;
  826.     timeSliceVal.it_interval.tv_sec      = 0;
  827.     timeSliceVal.it_interval.tv_usec     = 0;
  828.     StartTimeSlicer();
  829. }
  830.  
  831. void CurrentLoad()
  832. /* Snapshot */
  833. {
  834.     KMDPrint("Current load %2d, total time slicings %4d\n",
  835.     cEmRunnable, cEmTimeSlicings);
  836. }
  837.  
  838.  
  839. void TimeSlicerInit()
  840. {
  841.     TimeSlicerActive = 0;
  842.     cEmTimeSlicings = 0;
  843.     KMDTrace("ProcessSwitch", 3,
  844.     "TimeSlicerInit: vEmTimeSlice = %d milliseconds.\n", vEmTimeSlice);
  845.     timeSliceVal.it_value.tv_sec         = vEmTimeSlice / 1000;
  846.     timeSliceVal.it_value.tv_usec        = (vEmTimeSlice % 1000) * 1000;
  847.     timeSliceVal.it_interval.tv_sec      = 0;
  848.     timeSliceVal.it_interval.tv_usec     = 0;
  849. #ifdef BSD
  850.     SetHandler(SIGVTALRM, TimeSliceInterrupt);
  851. #endif
  852.     KMDSetSnap(ResetTimeSlicer);
  853.     KMDSetSnap(CurrentLoad);
  854.     KMDSetTrace(ProcessSwitch);
  855.     KMDSetTrace(LineNumber);
  856.     KMDSetVar(vEmTimeSlice);
  857.     KMDSetVar(cEmTimeSlicings);
  858.     KMDSetVar(cEmRunnable);
  859. }
  860.  
  861.  
  862. /************************************************************************/
  863. /*  Process scheduling                                                  */
  864. /************************************************************************/
  865.  
  866. void schedule(f)
  867. register SSPtr                f;
  868. /* Schedule the Stack Segment "f" for execution */
  869. {
  870.     f->status.rs    = SSRunnable;
  871.  
  872.     if(f->tag.stopped) {
  873.     insertQ(&stoppedQ, f);
  874.     return;
  875.     }
  876.     KMDTrace("ProcessSwitch", 4, "%s runnable at %s\n",
  877.     PPPOID(f->processOID), PPSSPlace(f));
  878.     KMDTrace("LineNumber", 4, "%s runnable at %s\n",
  879.     PPPOID(f->processOID), PPSSPlace(f));
  880.     insertQ(&readyQ, f);
  881.     if (cEmRunnable++ && (!TimeSlicerActive)) StartTimeSlicer();
  882. }
  883.  
  884. void RunImmediately(f)
  885. SSPtr                f;
  886. /* Schedule the Stack Segment "f" for execution right now!!! */
  887. {
  888.     assert(IsNULL(currentSSP));
  889.     f->status.rs    = SSRunnable;
  890.  
  891.     if(f->tag.stopped) {
  892.     insertQ(&stoppedQ, f);
  893.     return;
  894.     }
  895.     currentSSP = f;
  896.     splimit = currentSSP->splimit;
  897.     if(f->tag.dormant) {
  898.     InsertDQ(&hasRunDQ, RemoveDQ(&f->ssDQ));
  899.     f->tag.dormant = FALSE;
  900.     }
  901.     KMDTrace("ProcessSwitch", 3, "%s made running at %s\n",
  902.     PPPOID(f->processOID), PPSSPlace(f));
  903.     KMDTrace("LineNumber", 5, "%s made running at %s\n",
  904.     PPPOID(f->processOID), PPSSPlace(f));
  905.     if (cEmRunnable++ && (!TimeSlicerActive)) StartTimeSlicer();
  906. }
  907.  
  908. SSPtr preemptRunning()
  909. /* Preempt the running process */
  910. {
  911.     register SSPtr        preempted;
  912.     if (NonNULL( preempted = currentSSP )) {
  913.     currentSSP = (SSPtr) NULL;
  914.     cEmRunnable--;
  915.     KMDTrace("ProcessSwitch", 3,
  916.         "%s preempted at \t%s\n", PPPOID(preempted->processOID),
  917.         PPSSPlace(preempted));
  918.     KMDTrace("LineNumber", 5,
  919.         "%s preempted at \t%s\n", PPPOID(preempted->processOID),
  920.         PPSSPlace(preempted));
  921.     FixInvokeQueue(preempted);
  922.     }
  923.     /* Assert:    currentSSP == NULL */
  924.     return(preempted);
  925. }
  926.  
  927. void preemptBrokenRunning()
  928. /* Preempt the running process, it is broken.  Drop references to it. */
  929. {
  930.     if (NonNULL( currentSSP )) {
  931.         currentSSP->status.rs = SSBroken;
  932.     KMDTrace("ProcessSwitch", 3,
  933.         "%s broken and preempted  at \t%s\n",
  934.         PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
  935.     registerSave[regs_g] = (int) currentSSP->regs.g;
  936.     registerSave[regs_sp] = (int) currentSSP->regs.sp;
  937.     KMDTrace("LineNumber", 3,
  938.         "*%s broken and preempted at \t%s\n",
  939.         PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
  940.     currentSSP = (SSPtr) NULL;
  941.     cEmRunnable--;
  942.     }
  943.     /* Assert:    currentSSP == NULL */
  944. }
  945.  
  946. /**********************************************************************/
  947. /*      ensureRunning                                                 */
  948. /**********************************************************************/
  949.  
  950. void ensureRunning()
  951. /* Will ensure that a process is running if there is any that want to */
  952. {
  953.     while (IsNULL(currentSSP)) {
  954.     if ( NonNULL( currentSSP = removeQ(&readyQ) ) ) {
  955.         KMDTrace("ProcessSwitch", 3, "%s running, \t\t%s\n",
  956.         PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
  957.         splimit = currentSSP->splimit;
  958.         break;
  959.     } else {
  960.         doPause();
  961.     }
  962.     }
  963.     if (currentSSP->tag.dormant) {
  964.     InsertDQ(&hasRunDQ, RemoveDQ(¤tSSP->ssDQ));
  965.     currentSSP->tag.dormant = FALSE;
  966.     }
  967. }
  968.  
  969. /************************************************************************/
  970. /*      The following snapshots start and stop a running process        */
  971. /************************************************************************/
  972.  
  973. /* Snapshot */
  974. void StopProcess(fOID)
  975. OID              fOID;
  976. {
  977.     register SSPtr      p, q, last;
  978.     register DQueuePtr  next;
  979.     
  980.     KMDPrint("Will try to stop process 0x%05x\n", fOID);
  981.     if (currentSSP->processOID == fOID) {
  982.     KMDPrint("Stopping the running process in %s\n",
  983.         PPSSPlace(currentSSP));
  984.     currentSSP->tag.stopped = TRUE;
  985.     insertQ(&stoppedQ, preemptRunning());
  986.     return;
  987.     }
  988.     /* check readyQ */
  989.     
  990.     if (NonNULL(readyQ)) {
  991.     last = p = q = readyQ;
  992.     do {
  993.             p = p->readyQLink;
  994.         if (p->processOID == fOID) {
  995.         /* Found it, now remove from readyQ and stop it */
  996.                 /* Delink the one pointed to by p */
  997.         q->readyQLink = p->readyQLink;
  998.                 if (p == q) {
  999.             /* removing the only entry */
  1000.                      readyQ = (SSPtr) NULL;
  1001.         } else if (p == last) {
  1002.                     /* removing the entry at the end of the queue */
  1003.             readyQ = q;
  1004.         }
  1005.  
  1006.         cEmRunnable--;
  1007.         KMDTrace("ProcessSwitch", 3, "%s stopped in %s\n",
  1008.             PPPOID(p->processOID), PPSSPlace(p));
  1009.         KMDPrint("Stopping ready process %s in %s\n",
  1010.             PPPOID(p->processOID), PPSSPlace(p));
  1011.         p->tag.stopped  = TRUE;
  1012.         insertQ(&stoppedQ, p);
  1013.         return;
  1014.         } else q = p;
  1015.     } while (last != p);
  1016.     }
  1017.     for (next = hasRunDQ.next; next != &hasRunDQ; next=next->next) {
  1018.     p = mDQPtrToSSP(next);
  1019.     if ( (p->status.rs == SSNotInUse) || (p->processOID != fOID) ) {
  1020.         continue;
  1021.     }
  1022.     KMDPrint("Stopping blocked process %s\n", PPSSPlace(p));
  1023.     p->tag.stopped = TRUE;
  1024.     return;
  1025.     }
  1026.     for (next = dormantDQ.next; next != &dormantDQ; next=next->next) {
  1027.     p = mDQPtrToSSP(next);
  1028.     if ( (p->status.rs == SSNotInUse) || (p->processOID != fOID) ) continue;
  1029.     KMDPrint("Stopping blocked process %s\n", PPSSPlace(p));
  1030.     p->tag.stopped = TRUE;
  1031.     return;
  1032.     }
  1033.     KMDPrint("Could not find process OID 0x%05x\n", fOID);
  1034. }
  1035.  
  1036. /* Snapshot */
  1037. void StartProcess(fOID)
  1038. OID               fOID;
  1039. {
  1040.     register SSPtr      p, q, last;
  1041.     register DQueuePtr  next;
  1042.  
  1043.     /* Search queue for it */
  1044.     if (NonNULL(stoppedQ)) {
  1045.     last = p = q = stoppedQ;
  1046.     do {
  1047.             p = p->readyQLink;
  1048.         if (p->processOID == fOID) {
  1049.         /* Found it, now remove from stoppedQ and stop it */
  1050.                 /* Delink the one pointed to by p */
  1051.         q->readyQLink = p->readyQLink;
  1052.                 if (p == q) {
  1053.             /* removing the only entry */
  1054.                      stoppedQ = (SSPtr) NULL;
  1055.         } else if (p == last) {
  1056.                     /* removing the entry at the end of the queue */
  1057.             stoppedQ = q;
  1058.         }
  1059.  
  1060.         if (!p->tag.stopped) {
  1061.             KMDPrint("%s has not been stopped\n",
  1062.             PPPOID(p->processOID));
  1063.             return;
  1064.         }
  1065.         p->tag.stopped = FALSE;
  1066.         KMDTrace("ProcessSwitch", 3, "%s restarted in %s\n",
  1067.             PPPOID(p->processOID), PPSSPlace(p));
  1068.         KMDPrint("Continuing %s in %s\n", PPPOID(fOID), PPSSPlace(p));
  1069.         schedule(p);
  1070.         return;
  1071.         } else q = p;
  1072.     } while (last != p);
  1073.     }
  1074.     
  1075.     for (next = hasRunDQ.next; next != &hasRunDQ; next=next->next) {
  1076.     p = mDQPtrToSSP(next);
  1077.     if ( (p->status.rs == SSNotInUse) || (p->processOID != fOID) ) continue;
  1078.     KMDPrint("Unstopping %s in %s\n", PPPOID(p->processOID),
  1079.         PPSSPlace(p));
  1080.     if (!p->tag.stopped) {
  1081.         KMDPrint("%s has not been stopped\n", PPPOID(p->processOID));
  1082.         return;
  1083.     }
  1084.     p->tag.stopped = FALSE;
  1085.     return;
  1086.     }
  1087.     for (next = dormantDQ.next; next != &dormantDQ; next=next->next) {
  1088.     p = mDQPtrToSSP(next);
  1089.     if ( (p->status.rs == SSNotInUse) || (p->processOID != fOID) ) {
  1090.         continue;
  1091.     }
  1092.     KMDPrint("Unstopping %s in %s\n", PPPOID(p->processOID),
  1093.         PPSSPlace(p));
  1094.     if (!p->tag.stopped) {
  1095.         KMDPrint("%s has not been stopped\n", PPPOID(p->processOID));
  1096.         return;
  1097.     }
  1098.     p->tag.stopped = FALSE;
  1099.     return;
  1100.     }
  1101.     
  1102.     KMDPrint("Could not find process OID 0x%05x\n", fOID);
  1103. }
  1104.  
  1105.  
  1106. /************************************************************************/
  1107. void LoopPreempt()
  1108. /* The current process has detected a preemption request at the end of a
  1109.    loop, so preempt it in favor of the kernel.
  1110.    Note:  Round robin process scheduling is handled by the TimeSlicing
  1111.    routine -- preemption in this context only means that the kernel
  1112.    regains the thread of control.
  1113. */
  1114. {
  1115.     /* Merely undo the effects of the preemption request */
  1116.     KMDTrace("ProcessSwitch", 6,
  1117.         " LoopPreempt: self preempt on loop, process 0x%05x\n",
  1118.     currentSSP->processOID);
  1119.     preemptFlag = 0;
  1120.     if (NonNULL(currentSSP)) splimit = currentSSP->splimit;
  1121. }
  1122.  
  1123. /**********************************************************************/
  1124. /*      NewStackSegment                                               */
  1125. /**********************************************************************/
  1126.  
  1127. SSPtr NewStackSegment(fSize)
  1128. int     fSize;
  1129. /* Create a new stack segment of the given Size */
  1130. {
  1131.     register int            allocSize;
  1132.     register SSODP        ssp;
  1133.     register SSPtr        newSS;
  1134.  
  1135.     /* Round up stack size to multiple of MINSTACKSIZE, if necessary */
  1136.     if (fSize < MINSTACKSIZE) {
  1137.     fSize           = MINSTACKSIZE;
  1138.     } else if ((fSize % MINSTACKSIZE) != 0) {
  1139.     fSize           += MINSTACKSIZE - fSize % MINSTACKSIZE;
  1140.     }
  1141.     ssp                 = (SSODP) getFreeOD();
  1142.     ssp->tag            = stdSSODTag;
  1143.     ssp->ownOID         = getNextOID();
  1144.     allocSize           = fSize + (sizeof(SS) + STACKSAFETY);
  1145.     ssp->dataPtr = newSS = (SSPtr) emalloc(allocSize);
  1146.     newSS->tag          = stdSSTag;
  1147.     ssp->ownLoc         = thisNodeLocation;
  1148.     ssp->tag.isResident = TRUE;
  1149.  
  1150.     newSS->ownOID    = ssp->ownOID;
  1151.     newSS->segmentSize  = fSize;
  1152.     newSS->endOfSS      = (SSAddr) addOffset(newSS, allocSize);
  1153.     newSS->readyQLink   = (SSPtr) NULL;
  1154.     newSS->ownSSODP     = ssp;
  1155.     /* Now set up sp and splimit */
  1156.     newSS->splimit      = (SSAddr)
  1157.     addOffset(newSS, sizeof(SS) + STACKSAFETY);
  1158.     newSS->regs.sp      = newSS->endOfSS;
  1159.     newSS->resultBrand  = DataBrand;
  1160.     
  1161.     InsertDQ(&hasRunDQ, &newSS->ssDQ);
  1162.  
  1163.     OTInsert((ODP) ssp);
  1164.  
  1165.     KMDTrace("StackSegment", 3,
  1166.     "New Stack Seg at 0x%06x SSOID: 0x%05x, size %d\n", newSS,
  1167.     ssp->ownOID, fSize);
  1168.  
  1169.     return(newSS);
  1170. }
  1171.  
  1172.  
  1173.  
  1174. /**********************************************************************/
  1175. /*      DiscardStackSegment                                           */
  1176. /**********************************************************************/
  1177. void DiscardStackSegment(fSSPtr)
  1178. register SSPtr           fSSPtr;
  1179. {
  1180.     register SSODP      newSSODP;
  1181.     
  1182.     assert(((int) fSSPtr->regs.sp % sizeof(int)) == 0);
  1183.  
  1184.     if (fSSPtr->segmentSize != vEmStdStackSize) {
  1185.     /* Unusual size segment, free it */
  1186.     KMDTrace("StackSegment", 3,
  1187.         "Discarding odd sized stack segment 0x%06x\n", fSSPtr);
  1188.     (void) RemoveDQ(&fSSPtr->ssDQ);
  1189.     emfree((char *)fSSPtr->ownSSODP);
  1190.     emfree((char *)fSSPtr);
  1191.     } else {
  1192.     /* Standard stack segment, if there are not too many save it */
  1193.     if (cEmStandbyCount >= vEmStandbyMax) {
  1194.         /* Too many, free it */
  1195.         KMDTrace("StackSegment", 3,
  1196.         "Too many on standby: discarding SS 0x%05x\n", fSSPtr);
  1197.         (void) RemoveDQ(&fSSPtr->ssDQ);
  1198.         emfree((char *)fSSPtr->ownSSODP);
  1199.         emfree((char *)fSSPtr);
  1200.         return;
  1201.     }        
  1202.     fSSPtr->status.rs       = SSNotInUse;
  1203.     newSSODP                = fSSPtr->ownSSODP;
  1204.     fSSPtr->tag             = stdSSTag;
  1205.     newSSODP->tag           = stdSSODTag;
  1206.     fSSPtr->processOID      =
  1207.     fSSPtr->ownOID          =
  1208.     newSSODP->ownOID        = (OID) NULL;
  1209.         newSSODP->ownLoc        = thisNodeLocation;
  1210.     fSSPtr->regs.sp         = fSSPtr->endOfSS;
  1211.         fSSPtr->resultBrand     = DataBrand;
  1212.         fSSPtr->rPtr            = (GenericPtr) NULL;
  1213.     fSSPtr->invokePtr       = (GenericPtr) NULL;
  1214.     bzero(addOffset(fSSPtr, sizeof(SS)), fSSPtr->segmentSize);
  1215.     KMDTrace("StackSegment", 3, "Recycling stack segment 0x%05x\n",
  1216.         fSSPtr);
  1217.     cEmStandbyCount++;
  1218.     insertQ(&standbyQueue, fSSPtr);    
  1219.     }
  1220. }
  1221.  
  1222. /**********************************************************************/
  1223. /*      FreeUpMovedStackSegment  (and ditto EventHandler)             */
  1224. /**********************************************************************/
  1225. HResult FreeUpMovedStackSegmentEventHandler(fSSPtr)
  1226. register SSPtr           fSSPtr;
  1227. {
  1228.     KMDTrace("StackSegment", 3,
  1229.     "%s: Freeing up moved stack segment 0x%06x (to 0x%06x)\n",
  1230.     PPPOID(fSSPtr->processOID), fSSPtr, fSSPtr->endOfSS);
  1231.     (void) RemoveDQ(&fSSPtr->ssDQ);
  1232.  
  1233.     /* Clean up */
  1234.     if (NonNULL(fSSPtr->rPtr)) {
  1235.     FreeRequest((GenericReqPtr) fSSPtr->rPtr);
  1236.     }
  1237.     if (NonNULL(fSSPtr->invokePtr)) {
  1238.     FreeRequest((GenericReqPtr) fSSPtr->invokePtr);
  1239.     }
  1240.     
  1241.     emfree((char *)fSSPtr);
  1242. }
  1243.  
  1244. void FreeUpMovedStackSegment(fSSPtr)
  1245. register SSPtr           fSSPtr;
  1246. {
  1247.     assert(((int) fSSPtr->regs.sp % sizeof(int)) == 0);
  1248.     
  1249.     KMDTrace("Move", 5,
  1250.     "%s: Scheduling freeing up of moved stack segment %s (0x%06x)\n",
  1251.     PPPOID(fSSPtr->processOID), PPOID(fSSPtr->ownOID), fSSPtr);
  1252.  
  1253.     QueueTask((HandlerPtr)FreeUpMovedStackSegmentEventHandler, (char *)fSSPtr);
  1254. }
  1255.  
  1256. /**********************************************************************/
  1257. /*      StdStackSegment                                               */
  1258. /*      Return a new standard sized stack segment                     */
  1259. /**********************************************************************/
  1260. SSPtr StdStackSegment()
  1261. {
  1262.     register SSPtr          theSSP;
  1263.     
  1264.     if (cEmStandbyCount > 0) {
  1265.     KMDTrace("StackSegment", 3,
  1266.         "Using a stack from the hot standby queue.\n");
  1267.     cEmStandbyCount--;
  1268.     theSSP = removeQ(&standbyQueue);
  1269.     return(theSSP);    
  1270.     } else {
  1271.     return(NewStackSegment(vEmStdStackSize));
  1272.     }
  1273. }
  1274.  
  1275.  
  1276. /**********************************************************************/
  1277. /*      NewProcess                                                    */
  1278. /**********************************************************************/
  1279.  
  1280. SSPtr NewProcess()
  1281. /* Create a new process and return the SSODP for it */
  1282. {
  1283.     register SSODP        ssp;
  1284.     register SSPtr        newSS;
  1285.     
  1286.     /* Set up Stack Segment for process */
  1287.     newSS                   = StdStackSegment();
  1288.     assert(((int) newSS->regs.sp % sizeof(int)) == 0);
  1289.     newSS->status.rs        = SSAllocated;
  1290.     ssp                     = newSS->ownSSODP;
  1291.     ssp->processOID         =
  1292.     newSS->processOID       = getNextOID();
  1293.     KMDTrace("ProcessSwitch", 3, "NewProcess: %s\n", PPPOID(ssp->processOID));
  1294.     
  1295.     newSS->availStack       = vEmMaxStackSize - newSS->segmentSize;
  1296.     newSS->rPtr             = (int *) NULL;
  1297.     newSS->invokePtr        = (GenericPtr) NULL;
  1298.     
  1299.     return(newSS);
  1300. }
  1301.  
  1302. /************************************************************************/
  1303. /*      StartProcessAtAddr                                              */
  1304. /************************************************************************/
  1305.  
  1306. void StartProcessAtAddr(fSSPtr, fB, fG, fEntry)
  1307. register SSPtr          fSSPtr;
  1308. GODP                    fB;
  1309. GODataPtr               fG;
  1310. CodeAddr                fEntry;
  1311. /* Start up the process indicated by fSSPtr by invoking fEntry in (fB, fG) */
  1312. /* Assumption:  The kernel has already pushed any parameters onto the stack */
  1313. /* Called only after doing a NewProcess */
  1314. {
  1315.     DebugMsg(2, "Start 0x%05x at 0x%05x with b=0x%05x, g=0x%05x\n",
  1316.     fSSPtr->processOID, fEntry, fB, fG);
  1317.     assert(((int) fSSPtr->regs.sp % sizeof(int)) == 0);
  1318.     fSSPtr->regs.b  = (GODP) fB;
  1319.     fSSPtr->regs.g  = (GODataPtr) fG;
  1320.     fSSPtr->resultBrand = DataBrand;
  1321.     
  1322.     PUSHIT(fSSPtr->regs.sp, 0);                 /* fake l */
  1323.     PUSHIT(fSSPtr->regs.sp, fSSPtr->regs.g);    /* g */
  1324.     PUSHIT(fSSPtr->regs.sp, fSSPtr->regs.b);    /* b */
  1325.     fSSPtr->regs.l  = fSSPtr->regs.sp;
  1326.     /* Note, ReturnOffStack is defined in the kernel stub */
  1327.     PUSHIT(fSSPtr->regs.sp, &ReturnOffStack);   /* Old PC */
  1328.     PUSHIT(fSSPtr->regs.sp, fEntry);
  1329.  
  1330.     /* It is ready to run now */
  1331.     fSSPtr->status.rs       = SSRunnable;
  1332.     registerSave[regs_g] = (int) fSSPtr->regs.g;
  1333.     registerSave[regs_sp] = (int) fSSPtr->regs.sp;
  1334.     KMDTrace("LineNumber", 3, "%s will start up in %s\n",
  1335.     PPPOID(fSSPtr->processOID), PPSSPlace(fSSPtr));
  1336.     schedule(fSSPtr);
  1337. }
  1338.  
  1339. /************************************************************************/
  1340.  
  1341. void DoReturnOffStack()
  1342. /* Called from the kernel stub when a process returns off the bottom of a
  1343.    stack */
  1344. {
  1345.     register SSPtr          theProcess;
  1346.     register GenericReqPtr  rPtr;
  1347.     
  1348.     theProcess = preemptRunning();
  1349.  
  1350.     assert(((int) theProcess->regs.sp % sizeof(int)) == 0);
  1351.  
  1352.     /* Find the return point */
  1353.     if (IsNULL(theProcess->rPtr)) {
  1354.     /* No request means that the process is done */
  1355.     KMDTrace("LineNumber", 4, "%s terminated\n",
  1356.         PPPOID(theProcess->processOID));
  1357.     DiscardStackSegment(theProcess);
  1358.     return;    
  1359.     };
  1360.     rPtr = (GenericReqPtr) theProcess->rPtr;
  1361.     if (rPtr->hdr.rTag == IncomingIRTag) {
  1362.     InvokeReturn(theProcess, INVOKEDONE);
  1363.     DiscardStackSegment(theProcess);
  1364.     return;
  1365.     };
  1366.     if (rPtr->hdr.rTag == StackBreakRTag) {
  1367.     DoStackBreakReturn(theProcess);
  1368.     DiscardStackSegment(theProcess);
  1369.     return;
  1370.     }
  1371.     ErrMsg("Got weird tag %d for return off stack\n", rPtr->hdr.rTag);
  1372. }
  1373.  
  1374. /*********************************************************************/
  1375. /*      MoreStack                                                    */
  1376. /*********************************************************************/
  1377.  
  1378. void MoreStack(fSSPtr, fRequest)
  1379. register SSPtr                  fSSPtr;
  1380. int                             fRequest;
  1381. {
  1382.     register SSPtr              new;
  1383.     register StackBreakReqPtr   req;
  1384.     register DynamicLinkPtr     oldDynLink, newDynLink;
  1385.     TemplatePtr                 tPtr;
  1386.     int                         paramSize, k;
  1387.     
  1388.     KMDTrace("Stack", 3, "Expanding stack process %s, request %d, avail %d\n",
  1389.     PPPOID(fSSPtr->processOID), fRequest, fSSPtr->availStack);
  1390.     assert(((int) fSSPtr->regs.sp % sizeof(int)) == 0);
  1391.     if ((fSSPtr->availStack < 0) || (fRequest >= fSSPtr->availStack)) {
  1392.     KMDTrace("Failure", 2, "%s out of stack space, request %d in %s\n",
  1393.         PPPOID(fSSPtr->processOID), fRequest, PPSSPlace(fSSPtr));
  1394.     fail(fSSPtr);
  1395.     return;
  1396.     } else {
  1397.     if ( fRequest <= vEmStdStackSize) {
  1398.         new = StdStackSegment();
  1399.     } else {
  1400.         new = NewStackSegment((int) (fRequest + vEmStdStackSize));
  1401.     }
  1402.     }
  1403.     new->ownSSODP->processOID =
  1404.     new->processOID     = fSSPtr->processOID;
  1405.     new->availStack     = fSSPtr->availStack - new->segmentSize;
  1406.     
  1407.     req = (StackBreakReqPtr) malloc(sizeof(StackBreakReq));
  1408.     req->hdr.rTag       = StackBreakRTag;
  1409.     req->oldSSPtr       = fSSPtr;
  1410.  
  1411.     tPtr = FindTemplate(fSSPtr->regs.g->myCodePtr, *fSSPtr->regs.sp);
  1412.     req->argumentCount = req->resultCount = 0;
  1413.     for (k = 0; k < tPtr->B.numEntries; k++) {
  1414.     if ((tPtr->entry[k].TE.SS.Format != ShortStaticF) ||
  1415.         (tPtr->entry[k].TE.SS.paramInfo == IsNotParam)) break;
  1416.     if (tPtr->entry[k].TE.SS.paramInfo >= IsResult) {
  1417.         req->resultCount += tPtr->entry[k].TE.SS.count;
  1418.     } else {
  1419.         req->argumentCount += tPtr->entry[k].TE.SS.count;
  1420.     }
  1421.     }
  1422.     
  1423.     KMDTrace("Stack", 3, "Stack extend in %s\n", PPSSPlace(fSSPtr));
  1424.     KMDTrace("Stack", 4, "%d arg%s, %d result%s\n", req->argumentCount,
  1425.     mPLURAL(req->argumentCount), req->resultCount,
  1426.     mPLURAL(req->resultCount));
  1427.  
  1428.     /* Link into both SS */
  1429.     new->rPtr = (GenericPtr) req;
  1430.     fSSPtr->invokePtr = (GenericPtr) req;
  1431.  
  1432.     /* Copy dynamicLink and any parameters to new stack */
  1433.     paramSize = (req->argumentCount + req->resultCount)*sizeof(AVariable);
  1434.     oldDynLink = mDynLinkPtrFromL(fSSPtr->regs.l);
  1435.     newDynLink = (DynamicLinkPtr)
  1436.     addOffset(new->regs.sp, -paramSize-sizeof(DynamicLink));
  1437.     new->regs.sp = (SSAddr) newDynLink;
  1438.     bcopy((char *)oldDynLink, (char *)newDynLink,
  1439.       paramSize+sizeof(DynamicLink));
  1440.  
  1441.     new->regs.l  = (SSAddr) addOffset(newDynLink, LOFFSETFROMDYNAMICLINK);
  1442.     newDynLink->ip = (CodeAddr) &ReturnOffStack;
  1443.     newDynLink->l  = (SSAddr) NULL;
  1444.     
  1445.     /* Set ip to continue invocation by copying over */
  1446.     PUSHIT(new->regs.sp, *fSSPtr->regs.sp);
  1447.     
  1448.     new->regs.b = fSSPtr->regs.b;
  1449.     new->regs.g = fSSPtr->regs.g;
  1450.     
  1451.     schedule(new);
  1452. }    
  1453.  
  1454. /**********************************************************************/
  1455. /*      DoStackBreakReturn                                            */
  1456. /**********************************************************************/
  1457.  
  1458. void DoStackBreakReturn(fSSPtr)
  1459. register SSPtr                   fSSPtr;
  1460. /* Cross back over a stack break */
  1461. {
  1462.     register SSPtr              old;
  1463.     register StackBreakReqPtr   req;
  1464.     register DynamicLinkPtr     dynLink;
  1465.     SSAddr                      argumentLowAddr, resultLowAddr, returnAddr;
  1466.     
  1467.     req                         = (StackBreakReqPtr) fSSPtr->rPtr;
  1468.     assert(NonNULL(req) && (req->hdr.rTag == StackBreakRTag));
  1469.     old                         = req->oldSSPtr;
  1470.     
  1471.     dynLink                     = mDynLinkPtrFromL(old->regs.l);
  1472.  
  1473.     old->regs.b                 = dynLink->b;
  1474.     old->regs.g                 = dynLink->g;
  1475.     old->regs.l                 = dynLink->l;
  1476.     assert(NonNULL(old->regs.l));
  1477.     returnAddr                  = dynLink->ip;
  1478.     
  1479.     argumentLowAddr             = (SSAddr) (dynLink+1);
  1480.     
  1481.     resultLowAddr               = (SSAddr) addOffset(argumentLowAddr,
  1482.     req->argumentCount * sizeof(AVariable));
  1483.     if (req->resultCount > 0) {
  1484.     /* Copy in results */
  1485.     bcopy((char *)fSSPtr->regs.sp, (char *)resultLowAddr,
  1486.         req->resultCount*sizeof(AVariable));
  1487.     }
  1488.     old->regs.sp                = (SSAddr) resultLowAddr;
  1489.     PUSHIT(old->regs.sp, returnAddr);
  1490.     fSSPtr->rPtr                = (GenericPtr) NULL;
  1491.     old->invokePtr              = (GenericPtr) NULL;
  1492.     KMDTrace("Stack", 3, "Cross stack segment return in %s\n",
  1493.     PPSSPlace(old));
  1494.     KMDTrace("Stack", 4, "%d arg%s, %d result%s\n", req->argumentCount,
  1495.     mPLURAL(req->argumentCount), req->resultCount,
  1496.     mPLURAL(req->resultCount));
  1497.     free((char *)req);
  1498.     /*
  1499.      * If the return is from an initially then return the
  1500.      * address of the object in arg1.  Since we do not know, then
  1501.      * just copy over arg1 everytime.
  1502.      */
  1503.     old->resultBrand    = fSSPtr->resultBrand;
  1504.     old->regs.arg1     = fSSPtr->regs.arg1; /* Tricky !!! */
  1505.     schedule(old);
  1506. }
  1507.  
  1508.  
  1509. /**********************************************************************/
  1510. /**********************************************************************/
  1511. /*      Object Creation                                               */
  1512. /**********************************************************************/
  1513. /**********************************************************************/
  1514.  
  1515.  
  1516. /**********************************************************************/
  1517. /*      AllocateWithOID                                               */
  1518. /**********************************************************************/
  1519.  
  1520. GODP AllocateWithOID(cType, fOID, fTotalBytes)
  1521. CodePtr            cType;
  1522. OID                     fOID;
  1523. int                     fTotalBytes;
  1524. /* Create an object of the specified type with the specified OID
  1525.    the instance size is given by fTotalbytes */
  1526. {
  1527.     register GODP            x;
  1528.     register GODataPtr            dataPtr;
  1529.  
  1530.     if (cType->instanceTag.replicated) {
  1531.     register RODataPtr      rDataPtr;
  1532.     /* Create data area     (filled in below) */
  1533.     rDataPtr = (RODataPtr) emallocnil(fTotalBytes + 0 /* Safety */);
  1534.     rDataPtr->myCodePtr  = cType;
  1535.     rDataPtr->tag        = cType->instanceTag;
  1536.         rDataPtr->tag.tag    = LOTag;
  1537.     rDataPtr->ownOID     = fOID;
  1538.     KMDTrace("Create", 4, "Allocating replicated local obj size %d\n",
  1539.         fTotalBytes);
  1540.  
  1541.     if (fOID != (OID) NULL) OTInsert((ODP) rDataPtr);
  1542.     return (GODP) rDataPtr;
  1543.     }
  1544.     
  1545.     KMDTrace("Create", 4, "Allocating %s, size %d\n", PPGOID(fOID),
  1546.     fTotalBytes);
  1547.     if (IsNULL(fOID) || IsNULL(x = (GODP) OTLookup(fOID))) {
  1548.     /* Allocate GOD and fill it in;  put return value into return arg.*/
  1549.     x            = (GODP) getFreeOD();
  1550.     x->tag                = stdGODTag;
  1551.     x->myCodeOID            = cType->ownOID;
  1552.     x->ownOID        = fOID;
  1553.     x->tag.xref        = (fOID != 0);
  1554.     } /* else the GODP already existed */
  1555.     
  1556.     /* Create data area     (filled in below) */
  1557.     dataPtr = x->dataPtr=
  1558.     (GODataPtr) emallocnil(fTotalBytes + 0 /* safety */);
  1559.     x->ownLoc        = thisNodeLocation;
  1560.     initARListHead(x);
  1561.  
  1562.     /* Fill-in GOData area */
  1563.     dataPtr->tag    = stdGODataTag;
  1564.     x->tag.replicated   = 
  1565.     dataPtr->tag.replicated = cType->instanceTag.replicated;
  1566.     dataPtr->myCodePtr    = cType;
  1567.     
  1568.     if (fOID != (OID) NULL) OTInsert((ODP) x);
  1569.     return x;
  1570. }
  1571.  
  1572. void SetCreateResult(fX, fCodePtr)
  1573. DataAddr        fX;
  1574. CodePtr            fCodePtr;
  1575. {
  1576.     register AVariablePtr    v;
  1577.     /* Hack search down stack */
  1578.     KMDTrace("Create", 5, "Setting create result 0x%06x for CT %s\n", fX,
  1579.     PPCodePtr(fCodePtr));
  1580.     v = (AVariablePtr) addOffset(currentSSP->regs.sp, sizeof(CodeAddr));
  1581.     
  1582.     for(; (byteOffset(v, currentSSP->endOfSS) > 0); v++) {
  1583.     if (PPValidAddr((SSAddr *) (v->myAbConPtr)) &&
  1584.         (v->myAbConPtr->tag.tag == AbConTag) &&
  1585.         (v->myAbConPtr->tag.otherstuff == OBSCUREVALUE) &&
  1586.         (v->myAbConPtr->cPtr == fCodePtr) &&
  1587.         (IsNIL(v->myAddr))
  1588.     ) {
  1589.         v->myAddr = fX;
  1590.         KMDTrace("Create", 5, "Found createresult at offset %d\n",
  1591.         byteOffset(currentSSP->regs.sp, v));
  1592.         break;
  1593.     }
  1594.     }
  1595. }
  1596.  
  1597. /**********************************************************************/
  1598. /*  MakeObject                                                        */
  1599. /**********************************************************************/
  1600.  
  1601. GODP MakeObject(cType, fOID, fTotalBytes)
  1602. CodePtr     cType;
  1603. int         fTotalBytes;
  1604. OID         fOID;
  1605. /* Create an object using fTotalBytes as the instance size */
  1606. {
  1607.     register GODP               x;
  1608.     register DynamicLinkPtr    nextDL;
  1609.     register RegisterSavePtr    regsPtr;
  1610.     SSPtr                       p;
  1611.  
  1612.     assert(cType != (CodePtr) -1); /* Victim of bad translation */
  1613.     x = AllocateWithOID(cType, fOID, fTotalBytes);
  1614.     KMDTrace("Create", 3, "Created %s, type %s, size %d\n",
  1615.     (fOID != (OID) NULL) ? PPGOID(fOID): "object", PPCodePtr(cType),
  1616.     fTotalBytes);
  1617. #ifdef NEWCREATERETURN
  1618.     SetCreateResult((DataAddr) x, cType);
  1619. #endif NEWCREATERETURN
  1620.     if (cType->initially.offset) {
  1621.     /* Now make a global call of the objects initially section */
  1622.     DebugMsg(4, "Initially of object 0x%04x invoked by process %s\n",
  1623.         x, PPPOID(currentSSP->processOID));
  1624.     
  1625.     /* The following pushes a new Dynamic link onto the stack and
  1626.        sets up the virtual registers to execute in a new
  1627.        activation record.
  1628.      */
  1629.     regsPtr = ¤tSSP->regs;
  1630.     nextDL = 
  1631.         (DynamicLinkPtr) addOffset(regsPtr->sp, 4-sizeof(DynamicLink) );
  1632.     /* Save old registers */
  1633.     nextDL->ip      = * ( (CodeAddr *) regsPtr->sp );
  1634.     nextDL->l       = regsPtr->l;
  1635.     nextDL->g       = regsPtr->g;
  1636.     nextDL->b       = regsPtr->b;
  1637.     /* Build new regs */
  1638.     regsPtr->l = (SSAddr) & nextDL->b;
  1639.     regsPtr->b = x;
  1640.     regsPtr->g = x->dataPtr;
  1641.     regsPtr->sp = (SSAddr) nextDL;
  1642.     PUSHIT(regsPtr->sp, addOffset(cType, cType->initially.offset));
  1643.     return x;
  1644.     }
  1645.     /* No initially */
  1646.     x->tag.setUpDone        = TRUE;
  1647.     x->tag.frozen           = FALSE;
  1648.     if (cType->process.offset) {
  1649.     /* A process, fire it up */
  1650.     p = NewProcess();
  1651.     StartProcessAtAddr(p, x, x->dataPtr,
  1652.          (CodeAddr) addOffset(cType,cType->process.offset));
  1653.     };
  1654.     /* return the new object to the caller */
  1655.     return x;
  1656. }
  1657.  
  1658. /**********************************************************************/
  1659. /*  Create                                                            */
  1660. /**********************************************************************/
  1661.  
  1662. /* Kernel call */
  1663. void Create(cType)
  1664. CodePtr     cType;
  1665. /* Create an instance of a type */
  1666. {
  1667.     currentSSP->resultBrand = ODPBrand;
  1668.     currentSSP->regs.arg1 = (int) MakeObject(cType, (OID) NULL,
  1669.     cType->instanceSize);
  1670.     
  1671. }
  1672.  
  1673. /**********************************************************************/
  1674. /*  CreateSized                                                       */
  1675. /**********************************************************************/
  1676.  
  1677. /* Kernel call */
  1678. void CreateSized(cType, fTotalBytes)
  1679. CodePtr     cType;
  1680. int         fTotalBytes;
  1681. /* Create an object using fTotalBytes as the instance size */
  1682. {
  1683.     currentSSP->resultBrand = ODPBrand;
  1684.     currentSSP->regs.arg1= (int) MakeObject(cType, (OID) NULL, fTotalBytes);
  1685. }
  1686.  
  1687. /**********************************************************************/
  1688. /*  MakeLocalObject                                                   */
  1689. /**********************************************************************/
  1690. LODataPtr MakeLocalObject(cType, fSize)
  1691. register CodePtr cType;
  1692. int              fSize;
  1693. /* Generate a new local object */
  1694. {
  1695.     register LODataPtr          x;
  1696.     register DynamicLinkPtr    nextDL;
  1697.     register RegisterSavePtr    regsPtr;
  1698.     SSPtr                       p;
  1699.  
  1700.     x = (LODataPtr) emallocnil(fSize);
  1701.     x->tag = stdLODataTag; 
  1702.     x->tag.replicated = cType->instanceTag.replicated;
  1703.     x->myCodePtr = cType;
  1704.     KMDTrace("Create", 3, "Local Create 0x%05x, size %d, code %s\n",
  1705.     x, fSize, PPCodePtr(cType));
  1706.  
  1707. #ifdef NEWCREATERETURN
  1708.     SetCreateResult((DataAddr) x, cType);
  1709. #endif NEWCREATERETURN
  1710.  
  1711.     if (cType->initially.offset) {
  1712.     /* Now make a local call of the objects initially section */
  1713.     KMDTrace("Create", 4,
  1714.         "Initially of local object 0x%04x invoked by  %s\n", x,
  1715.         PPPOID(currentSSP->processOID));
  1716.     
  1717.     /* The following pushes a new Dynamic link onto the stack and
  1718.        sets up the virtual registers to execute in a new
  1719.        activation record.
  1720.      */
  1721.     regsPtr = ¤tSSP->regs;
  1722.     nextDL = 
  1723.         (DynamicLinkPtr) addOffset(regsPtr->sp, 4-sizeof(DynamicLink) );
  1724.     /* Save old registers */
  1725.     nextDL->ip      = * ( (CodeAddr *) regsPtr->sp );
  1726.     nextDL->l       = regsPtr->l;
  1727.     nextDL->g       = regsPtr->g;
  1728.     nextDL->b       = regsPtr->b;
  1729.     /* Build new regs */
  1730.     regsPtr->l = (SSAddr) & nextDL->b;
  1731.     regsPtr->g = (GODataPtr) x;
  1732.     regsPtr->sp = (SSAddr) nextDL;
  1733.     PUSHIT(regsPtr->sp, addOffset(cType, cType->initially.offset));
  1734.     return (LODataPtr) x;  /* Initially done will return correct val */
  1735.     }
  1736.     /* No initially */
  1737.     if (cType->process.offset) {
  1738.     /* A process, fire it up */
  1739.     p = NewProcess();
  1740.     StartProcessAtAddr(p, currentSSP->regs.b, (GODataPtr) x,
  1741.         (CodeAddr) addOffset(cType, cType->process.offset));
  1742.     };
  1743.     /* return the new object to the caller */
  1744.     return x;
  1745. }
  1746.  
  1747. /**********************************************************************/
  1748. /*      MagicLocalCreate                                              */
  1749. /**********************************************************************/
  1750.  
  1751. LODataPtr MagicLocalCreate(cType, fSize)
  1752. register CodePtr cType;
  1753. int              fSize;
  1754. /* Generate a new local object for the kernel.  No initially nor process. */
  1755. {
  1756.     register LODataPtr          x;
  1757.  
  1758.     x = (LODataPtr) emallocnil(fSize);
  1759.     x->tag = stdLODataTag; 
  1760.     x->tag.replicated = cType->instanceTag.replicated;
  1761.     x->myCodePtr = cType;
  1762.     if (x->tag.replicated) ((RODataPtr) x)->ownOID = (OID) NULL;
  1763.     KMDTrace("Create", 3, "Magic Create 0x%05x, size %d, code %s\n",
  1764.     x, fSize, PPCodePtr(cType));
  1765.     /* Initially must be faked by the calling routine */
  1766.     /* No process allowed for magic creates */
  1767.     assert (IsNULL(cType->process.offset));
  1768.     /* return the new object to the caller */
  1769.     return x;
  1770. }
  1771.  
  1772. /**********************************************************************/
  1773. /*  LocalCreate                                                       */
  1774. /**********************************************************************/
  1775. void LocalCreate(cType)
  1776. register CodePtr     cType;
  1777. {
  1778.     currentSSP->resultBrand = ODPBrand;
  1779.     currentSSP->regs.arg1 = (int) MakeLocalObject(cType, cType->instanceSize);
  1780. }
  1781.  
  1782. /**********************************************************************/
  1783. /*  LocalCreateSized                                                  */
  1784. /**********************************************************************/
  1785. void LocalCreateSized(cType, fSize)
  1786. register CodePtr     cType;
  1787. int                  fSize;
  1788. {
  1789.     currentSSP->resultBrand = ODPBrand;
  1790.     currentSSP->regs.arg1 = (int) MakeLocalObject(cType, fSize);
  1791. }
  1792.  
  1793. /**********************************************************************/
  1794. /*  LocalQuickCreate                                                  */
  1795. /**********************************************************************/
  1796. void LocalQuickCreate(cType)
  1797. register CodePtr     cType;
  1798. {
  1799.     register LODataPtr x;
  1800.     x = (LODataPtr) emallocnil(cType->instanceSize);
  1801.     x->tag = stdLODataTag; 
  1802.     x->tag.replicated = cType->instanceTag.replicated;
  1803.     x->myCodePtr = cType;
  1804.     KMDTrace("Create", 3, "Local Quick Create 0x%05x, size %d, code %s\n",
  1805.     x, cType->instanceSize, PPCodePtr(cType));
  1806.  
  1807.     currentSSP->resultBrand = ODPBrand;
  1808.     currentSSP->regs.arg1 = (int) x;
  1809. }
  1810.  
  1811. /**********************************************************************/
  1812. /*  LocalQuickCreateSized                                             */
  1813. /**********************************************************************/
  1814. void LocalQuickCreateSized(cType, fSize)
  1815. register CodePtr     cType;
  1816. int                  fSize;
  1817. {
  1818.     register LODataPtr      x;
  1819.     
  1820.     x = (LODataPtr) emallocnil(fSize);
  1821.     x->tag = stdLODataTag; 
  1822.     x->tag.replicated = cType->instanceTag.replicated;
  1823.     x->myCodePtr = cType;
  1824.     KMDTrace("Create", 3, "Local Quick Create 0x%05x, size %d, code %s\n",
  1825.     x, fSize, PPCodePtr(cType));
  1826.  
  1827.     currentSSP->resultBrand = ODPBrand;
  1828.     currentSSP->regs.arg1 = (int) x;
  1829. }
  1830.  
  1831. /**********************************************************************/
  1832. /*  GlobalCreateVector                                                */
  1833. /**********************************************************************/
  1834. /* Kernel entry point */
  1835. void GlobalCreateVector(fCodePtr, fSizeInBytes, fupb)
  1836. CodePtr             fCodePtr;
  1837. unsigned long       fSizeInBytes;   /* of vector data */
  1838. unsigned long       fupb;
  1839. {
  1840.     register GODP               x;
  1841.     register VectorPtr          v;
  1842.  
  1843.     x = AllocateWithOID(fCodePtr, (OID) NULL, (int) fSizeInBytes+Vector_data);
  1844.     v                       = (VectorPtr) x->dataPtr;
  1845.     x->tag.frozen           = FALSE;
  1846.     x->tag.setUpDone        = TRUE;
  1847.     v->upb                  = fupb;
  1848.     v->sizeInBytes          = fSizeInBytes;
  1849.     currentSSP->resultBrand = ODPBrand;
  1850.     currentSSP->regs.arg1   = (int) x;
  1851.     KMDTrace("Create", 3,
  1852.     "Created glob vector 0x%05.5x, %d bytes, fupb %d, code %s\n",
  1853.     x, fSizeInBytes, fupb, PPCodePtr(fCodePtr));
  1854. #ifdef NEWCREATERETURN
  1855.     SetCreateResult((DataAddr) x, fCodePtr);
  1856. #endif NEWCREATERETURN
  1857. }
  1858.  
  1859. /**********************************************************************/
  1860. /*      GlobalCreateVectorLiteral                                     */
  1861. /**********************************************************************/
  1862.  
  1863. void GlobalCreateVectorLiteral(fCodePtr, fSizeOfEachElement, fNElements)
  1864. CodePtr             fCodePtr;
  1865. unsigned long       fSizeOfEachElement;   /* 1 or 4 or 8 */
  1866. unsigned long       fNElements;
  1867. {
  1868.     register GODP               x;
  1869.     register VectorPtr          v;
  1870.     int                sizeInBytes = fSizeOfEachElement * fNElements;
  1871.     CodeOffset            returnAddr;
  1872.     register int        i, *vectorElementPtr;
  1873.     register Bytes           *byteVectorElementPtr;
  1874.     register SSPtr        cssp = currentSSP;
  1875.     int                data, abcon;
  1876.  
  1877.     /* save the return address */
  1878.     POPIT(cssp->regs.sp, returnAddr);
  1879.  
  1880.     x = AllocateWithOID(fCodePtr, (OID) NULL, sizeInBytes + Vector_data);
  1881.     v                       = (VectorPtr) x->dataPtr;
  1882.     x->tag.frozen           = FALSE;
  1883.     x->tag.setUpDone        = TRUE;
  1884.     v->upb                  = fNElements - 1;
  1885.     v->sizeInBytes          = sizeInBytes;
  1886.     cssp->resultBrand         = ODPBrand;
  1887.     cssp->regs.arg1         = (int) x;
  1888.     byteVectorElementPtr    = &v->data[sizeInBytes];
  1889.     vectorElementPtr        = (int *) byteVectorElementPtr;
  1890.  
  1891.     KMDTrace("Create", 10,
  1892.     "Creating vector literal, eSize = %d, nElements = %d, dataPtr = 0x%08x\n",
  1893.     fSizeOfEachElement, fNElements, v);
  1894.     KMDTrace("Create", 10, "vectorElementPtr = 0x%08x\n", vectorElementPtr);
  1895.     for (i = 0; i < fNElements; i++) {
  1896.     POPIT(cssp->regs.sp, data);
  1897.     POPIT(cssp->regs.sp, abcon);
  1898.     if (fSizeOfEachElement == 8) {
  1899.         *--vectorElementPtr = abcon;
  1900.         KMDTrace("Create", 10, "Vector literal abcon[%2d] addr(0x%08x) = 0x%x\n",
  1901.         fNElements - i - 1, vectorElementPtr, abcon);
  1902.         *-- vectorElementPtr = data;
  1903.     } else if (fSizeOfEachElement == 4) {
  1904.         *-- vectorElementPtr = data;
  1905.     } else {
  1906.         assert(fSizeOfEachElement == 1);
  1907.         *--byteVectorElementPtr = data;
  1908.     }
  1909.     KMDTrace("Create", 10, "Vector literal[%2d] addr(0x%08x) = 0x%x\n",
  1910.         fNElements - i - 1, vectorElementPtr, data);
  1911.     }
  1912.     PUSHIT(cssp->regs.sp, returnAddr);
  1913.     KMDTrace("Create", 3,
  1914.     "Created glob vector literal 0x%05.5x, %d bytes, fupb %d, code %s\n",
  1915.     x, v->sizeInBytes, v->upb, PPCodePtr(fCodePtr));
  1916. #ifdef NEWCREATERETURN
  1917.     SetCreateResult((DataAddr) x, fCodePtr);
  1918. #endif NEWCREATERETURN
  1919. }
  1920.  
  1921.  
  1922.  
  1923. /**********************************************************************/
  1924. /*      LocalCreateVectorLiteral                                     */
  1925. /**********************************************************************/
  1926. void LocalCreateVectorLiteral(fCodePtr, fSizeOfEachElement, fNElements)
  1927. CodePtr             fCodePtr;
  1928. unsigned long       fSizeOfEachElement;   /* 1 or 4 or 8 */
  1929. unsigned long       fNElements;
  1930. {
  1931.     register VectorPtr          v;
  1932.     int                sizeInBytes = fSizeOfEachElement * fNElements;
  1933.     CodeOffset            returnAddr;
  1934.     register int        i, *vectorElementPtr;
  1935.     register Bytes           *byteVectorElementPtr;
  1936.     register SSPtr        cssp = currentSSP;
  1937.     int                data, abcon;
  1938.     
  1939.     /* save the return address */
  1940.     POPIT(cssp->regs.sp, returnAddr);
  1941.  
  1942.     v = (VectorPtr) MakeLocalObject(fCodePtr, sizeInBytes + Vector_data);
  1943.     v->upb          = fNElements - 1;
  1944.     v->sizeInBytes  = sizeInBytes;
  1945.     cssp->resultBrand = ODPBrand;
  1946.     cssp->regs.arg1 = (int) v;
  1947.     byteVectorElementPtr = &v->data[sizeInBytes];
  1948.     vectorElementPtr = (int *) byteVectorElementPtr;
  1949.  
  1950.     KMDTrace("Create", 10,
  1951.     "Creating local vector literal, eSize = %d, nElements = %d, dataPtr = 0x%08x\n",
  1952.       fSizeOfEachElement, fNElements, v);
  1953.     KMDTrace("Create", 10, "vectorElementPtr = 0x%08x\n", vectorElementPtr);
  1954.     for (i = 0; i < fNElements; i++) {
  1955.     POPIT(cssp->regs.sp, data);
  1956.     POPIT(cssp->regs.sp, abcon);
  1957.     if (fSizeOfEachElement == 8) {
  1958.         *--vectorElementPtr = abcon;
  1959.         KMDTrace("Create", 10, "Vector literal abcon[%2d] addr(0x%08x) = 0x%x\n",
  1960.         fNElements - i - 1, vectorElementPtr, abcon);
  1961.         *-- vectorElementPtr = data;
  1962.     } else if (fSizeOfEachElement == 4) {
  1963.         *-- vectorElementPtr = data;
  1964.     } else {
  1965.         assert(fSizeOfEachElement == 1);
  1966.         *--byteVectorElementPtr = data;
  1967.     }
  1968.     KMDTrace("Create", 10, "Vector literal[%2d] addr(0x%08x) = 0x%x\n",
  1969.         fNElements - i - 1, vectorElementPtr, data);
  1970.     }
  1971.     PUSHIT(cssp->regs.sp, returnAddr);
  1972.     KMDTrace("Create", 3,
  1973.     "Created local vector literal 0x%05.5x, %d bytes, fupb %d, code %s\n",
  1974.     v, v->sizeInBytes, v->upb, PPCodePtr(fCodePtr));
  1975. #ifdef NEWCREATERETURN
  1976.     SetCreateResult((DataAddr) v, fCodePtr);
  1977. #endif NEWCREATERETURN
  1978. }
  1979.  
  1980. /**********************************************************************/
  1981. /*      CreateImmutableVectorLiteral                                  */
  1982. /**********************************************************************/
  1983. void CreateImmutableVectorLiteral(fCodePtr, fSizeOfEachElement, fNElements)
  1984. CodePtr             fCodePtr;
  1985. unsigned long       fSizeOfEachElement;   /* 1 or 4 or 8 */
  1986. unsigned long       fNElements;
  1987. {
  1988.     register IMVectorPtr        v;
  1989.     int                sizeInBytes = fSizeOfEachElement * fNElements;
  1990.     CodeOffset            returnAddr;
  1991.     register int        i, *vectorElementPtr;
  1992.     register Bytes           *byteVectorElementPtr;
  1993.     register SSPtr        cssp = currentSSP;
  1994.     int                data, abcon;
  1995.     
  1996.     /* save the return address */
  1997.     POPIT(cssp->regs.sp, returnAddr);
  1998.  
  1999.     v = (IMVectorPtr) emallocnil(sizeInBytes + IMVector_data);
  2000.     v->tag = stdLODataTag; 
  2001.     v->tag.replicated = TRUE;
  2002.     v->myCodePtr = fCodePtr;
  2003.     v->ownOID        = (OID) NULL;
  2004.     v->upb          = fNElements - 1;
  2005.     v->sizeInBytes  = sizeInBytes;
  2006.     cssp->resultBrand = ODPBrand;
  2007.     cssp->regs.arg1 = (int) v;
  2008.     byteVectorElementPtr = &v->data[sizeInBytes];
  2009.     vectorElementPtr = (int *) byteVectorElementPtr;
  2010.  
  2011.     KMDTrace("Create", 10,
  2012.     "Creating immutable vector literal, eSize = %d, nElements = %d, dataPtr = 0x%08x\n",
  2013.       fSizeOfEachElement, fNElements, v);
  2014.     KMDTrace("Create", 10, "vectorElementPtr = 0x%08x\n", vectorElementPtr);
  2015.     for (i = 0; i < fNElements; i++) {
  2016.     POPIT(cssp->regs.sp, data);
  2017.     POPIT(cssp->regs.sp, abcon);
  2018.     if (fSizeOfEachElement == 8) {
  2019.         *--vectorElementPtr = abcon;
  2020.         KMDTrace("Create", 10, "Vector literal abcon[%2d] addr(0x%08x) = 0x%x\n",
  2021.         fNElements - i - 1, vectorElementPtr, abcon);
  2022.         *-- vectorElementPtr = data;
  2023.     } else if (fSizeOfEachElement == 4) {
  2024.         *-- vectorElementPtr = data;
  2025.     } else {
  2026.         assert(fSizeOfEachElement == 1);
  2027.         *--byteVectorElementPtr = data;
  2028.     }
  2029.     KMDTrace("Create", 10, "Vector literal[%2d] addr(0x%08x) = 0x%x\n",
  2030.         fNElements - i - 1, vectorElementPtr, data);
  2031.     }
  2032.     PUSHIT(cssp->regs.sp, returnAddr);
  2033.     KMDTrace("Create", 3,
  2034.     "Created immutable vector literal 0x%05.5x, %d bytes, fupb %d, code %s\n",
  2035.     v, v->sizeInBytes, v->upb, PPCodePtr(fCodePtr));
  2036. #ifdef NEWCREATERETURN
  2037.     SetCreateResult((DataAddr) v, fCodePtr);
  2038. #endif NEWCREATERETURN
  2039. }
  2040.  
  2041.  
  2042.  
  2043. /**********************************************************************/
  2044. /*  LocalCreateVector                                                */
  2045. /**********************************************************************/
  2046. /* Kernel entry point */
  2047. void LocalCreateVector(fCodePtr, fSizeInBytes, fupb)
  2048. CodePtr             fCodePtr;
  2049. unsigned long       fSizeInBytes;
  2050. unsigned long       fupb;
  2051. {
  2052.     register VectorPtr          v;
  2053.     v = (VectorPtr) MakeLocalObject(fCodePtr, (int) fSizeInBytes+Vector_data);
  2054.     v->upb          = fupb;
  2055.     v->sizeInBytes  = fSizeInBytes;
  2056.     currentSSP->resultBrand = ODPBrand;
  2057.     currentSSP->regs.arg1 = (int) v; 
  2058.     KMDTrace("Create", 3,
  2059.     "Created local vector 0x%04x, %d data bytes, fupb %d, code %s\n",
  2060.     v, fSizeInBytes, fupb, PPCodePtr(fCodePtr));
  2061. }
  2062.  
  2063.  
  2064. /**********************************************************************/
  2065. /*  CreateString                                                      */
  2066. /**********************************************************************/
  2067. /* Kernel entry point */
  2068. void CreateString(fSizeInBytes)
  2069. unsigned long       fSizeInBytes;
  2070. {
  2071.     register StringPtr  x;
  2072.  
  2073.     x = (StringPtr) emalloc((int) (fSizeInBytes + String_data));
  2074.     x->tag              = stdLODataTag; 
  2075.     x->tag.replicated   = TRUE;
  2076.     x->myCodePtr        = stringCodePtr;
  2077.     x->ownOID           = (OID) NULL;
  2078.     x->sizeInBytes      = fSizeInBytes;
  2079.     KMDTrace("Create", 3, "Create String 0x%05x, %d chars, code %s\n",
  2080.     x, fSizeInBytes, PPCodePtr(stringCodePtr));
  2081.     currentSSP->resultBrand = ODPBrand;
  2082.     currentSSP->regs.arg1 = (int) x;
  2083. }
  2084.  
  2085.  
  2086. /**********************************************************************/
  2087. /**********************************************************************/
  2088.  
  2089. /**********************************************************************/
  2090. /*  UnblockInitially (and now: recovery!)                             */
  2091. /**********************************************************************/
  2092. void UnblockInitially(fGODP)
  2093. GODP                        fGODP;
  2094. /* Check to see, if there are any processes waiting for initially/recovery
  2095.    to be done.  If so, unblock it and set it up for the invocation    */
  2096. {
  2097.     Map                         theMap;
  2098.     SSPtr                       theProcess;
  2099.     int                         dummy;
  2100.     Set                         reqSet;
  2101.     IncomingIReqPtr             req;
  2102.     
  2103.     theMap = (Map) Map_Lookup(InitiallyMap, (int) fGODP);
  2104.     if (NonNIL(theMap)) {
  2105.     InitiallyReqPtr             ireq;
  2106.     KMDTrace("Invoke", 3, "Unblocking %d processes on initially done\n",
  2107.         Map_Count(theMap));
  2108.     Map_For(theMap, ireq, dummy)
  2109.         theProcess = ireq->theProcess;
  2110.         theProcess->invokePtr   = (GenericPtr) NULL;
  2111.         theProcess->status.rs   = SSRunnable;
  2112.         KMDPrint("Invoke", 3, "%s unblocking on initially done\n",
  2113.         PPPOID(theProcess->processOID));
  2114.         KMDPrint("LineNumber", 4, "%s unblocking on initially done\n",
  2115.         PPPOID(theProcess->processOID));
  2116.         /* Now do the invoke */
  2117.         TryInvoke(ireq->opNumber, ireq->theAbConPtr, ireq->calleeGODP,
  2118.         ireq->theProcess);
  2119.     Map_Next
  2120.     Map_Destroy(theMap);
  2121.     Map_Delete(InitiallyMap, (int) fGODP);
  2122.     }
  2123.     
  2124.     if (IsNULL(fGODP->ownOID)) return;
  2125.     
  2126.     reqSet  = (Set) Map_Lookup(FrozenMap, (int) fGODP->ownOID);
  2127.     if (IsNIL(reqSet)) return;
  2128.     KMDTrace("Invoke", 3, "Unfreezing %s, %d remote invokes waiting\n",
  2129.     PPGOID(fGODP->ownOID), Set_Count(reqSet));
  2130.     Set_For(reqSet, req)
  2131.         KMDTrace("Invoke", 6, "Doing Invoke callback for req 0x%06x\n", req);
  2132.         req->status             = IHObjectNonFrozen;
  2133.     InvokeHandlerCallBack((GenericReqPtr) req, (OID) NULL);
  2134.     Set_Next;
  2135.     Set_Destroy(reqSet);
  2136.     Map_Delete(FrozenMap, (int) fGODP->ownOID);
  2137. }
  2138.  
  2139. /**********************************************************************/
  2140. /*  InitiallyDone                              */
  2141. /*  The process (if any) is started and the object can now be invoked */
  2142. /*  by any other object.                          */
  2143. /**********************************************************************/
  2144. void InitiallyDone()
  2145. {
  2146.     register CodePtr        c;
  2147.     register GODP           b;
  2148.     register LODataPtr      g;
  2149.     register SSPtr          theSSP;
  2150.  
  2151.     b                       = currentSSP->regs.b;
  2152.     g                       = (LODataPtr) currentSSP->regs.g;
  2153.     c                       = g->myCodePtr;
  2154.     if (g->tag.global) {
  2155.     b->tag.setUpDone    = TRUE;
  2156.     b->tag.frozen       = /* No */ FALSE;
  2157.         KMDTrace("FixMe", 2,
  2158.         "Initially done: Flags should be set properly!!!\n");
  2159.     UnblockInitially(b);
  2160.     /* The caller gets a reference to the newly created object */
  2161.     currentSSP->resultBrand = ODPBrand;
  2162.     currentSSP->regs.arg1  = (int) b;
  2163.     } else {
  2164.     /* The caller gets a reference to the newly created object */
  2165.     currentSSP->resultBrand = ODPBrand;
  2166.     currentSSP->regs.arg1  = (int) g;
  2167.     }
  2168.     
  2169.     /* Create process if necessary */
  2170.     if ( NonNULL(c->process.offset) ) {
  2171.     theSSP              = NewProcess();
  2172.     StartProcessAtAddr(theSSP, b, (GODataPtr) g,
  2173.         (CodeAddr) addOffset(c, c->process.offset));
  2174.     }
  2175. }
  2176.  
  2177. /************************************************************************/
  2178. /*  Stack Check                                                         */
  2179. /************************************************************************/
  2180.  
  2181. /* Kernel Entry -- special due to content of stack */
  2182. void StackCheck(fRequest)
  2183. int             fRequest;
  2184. /* StackCheck is called when a process fails a stack check on entry to
  2185.    an operation.  There can be two reasons:
  2186.    1.   The process has used up the current stack segment.
  2187.     If it has not used up all its stack quota then allocate it some
  2188.     more stack.  fRequest indicates how much more stack the process
  2189.     wants.
  2190.    2.   The kernel wants to preempt the running process and forces this
  2191.     by setting the preemptFlag and by setting the current stacklimit
  2192.     of the currently executing process to something which will
  2193.     make it fail the stack check.
  2194. */
  2195. {
  2196.     KMDTrace("Stack", 5, "%s StackCheck(%d) at %s\n",
  2197.     PPPOID(currentSSP->processOID), fRequest, PPSSPlace(currentSSP));
  2198.     /* Check for the case of a process failing a stack check */
  2199.     if (addOffset(currentSSP->regs.sp, - fRequest) <
  2200.         (char *) currentSSP->splimit
  2201.     ) {
  2202.     /* the process has used up the current stack segment --
  2203.        allocate a new one (if it has not used up its quota) */
  2204.     MoreStack(preemptRunning(), fRequest);
  2205.     };
  2206.     /* A process preemption may also have been requested */
  2207.     if (NonNULL(currentSSP) && preemptFlag) {
  2208.     KMDTrace("Stack", 5,
  2209.         "StackCheck: self preempt on operation entry, process %s\n",
  2210.         PPPOID(currentSSP->processOID));
  2211.     preemptFlag = 0;
  2212.     splimit = currentSSP->splimit;
  2213.     }
  2214. }
  2215.  
  2216.  
  2217. /************************************************************************/
  2218. /*  Monitor operations                                                  */
  2219. /************************************************************************/
  2220.  
  2221. void MonitorEntry(fMonitorLock)
  2222. MonitorLock            *fMonitorLock;
  2223. /* Enter a monitor.  The parameter indicate the monitor lock and the queue of
  2224.     processes waiting to enter.
  2225. */
  2226. {
  2227.     KMDTrace("Monitor", 3,
  2228.     "%s MonitorEntry %s in %s\n",
  2229.     PPPOID(currentSSP->processOID),
  2230.     (fMonitorLock->isLocked) ? "locked -> blocking" : "open",
  2231.     PPSSPlace(currentSSP));
  2232.     if (fMonitorLock->isLocked) {
  2233.     /* Locked, so queue the process */
  2234.         currentSSP->status.rs   = SSMonWait;
  2235.         KMDTrace("LineNumber", 4, "%s blocking on Monitor Entry in %s\n",
  2236.         PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
  2237.     insertQ(&fMonitorLock->waiting, preemptRunning());
  2238.     } else {
  2239.     /* Lock the monitor and continue */
  2240.     fMonitorLock->isLocked = TRUE;
  2241.     }
  2242. }
  2243.  
  2244. /************************************************************************/
  2245.  
  2246. void MonitorExit(fMonitorLock)
  2247. MonitorLock            *fMonitorLock;
  2248. {
  2249.     if (IsNULL(fMonitorLock->waiting)) {
  2250.     KMDTrace("Monitor", 3,
  2251.         "%s%sMonitorExit, unlocking monitor (0x%06x)\n",
  2252.         IsNULL(currentSSP) ? "" : PPPOID(currentSSP->processOID),
  2253.         IsNULL(currentSSP) ? "" : " ",
  2254.         fMonitorLock);
  2255.     fMonitorLock->isLocked = FALSE;
  2256.     } else {
  2257.     KMDTrace("Monitor", 3,
  2258.         "%s%sMonitorExit unblocking %s\n",
  2259.         IsNULL(currentSSP) ? "" : PPPOID(currentSSP->processOID),
  2260.         IsNULL(currentSSP) ? "" : " ",
  2261.         PPPOID(fMonitorLock->waiting->processOID)
  2262.     );
  2263.     schedule(removeQ(&fMonitorLock->waiting));
  2264.     };
  2265. }
  2266.  
  2267. /************************************************************************/
  2268. /*  Conditions                                                          */
  2269. /************************************************************************/
  2270.  
  2271. void ActivateCond(fMonitorLock, fCondODP)
  2272. MonitorLock            *fMonitorLock;
  2273. CondODP                 fCondODP;
  2274. {
  2275.     Set                      theSet;
  2276.     
  2277.     theSet      = (Set) Map_Lookup(condMap, (int) fMonitorLock);
  2278.     if (IsNIL(theSet)) {
  2279.     KMDTrace("Monitor", 5, "First condition for object\n");
  2280.     theSet  = Set_Create();
  2281.     Map_Insert(condMap, (int) fMonitorLock, (int) theSet);
  2282.         KMDTrace("Monitor", 4, "condMap insert <0x%06x, 0x%06x>\n",
  2283.         fMonitorLock, theSet);
  2284.     }
  2285.     Set_Insert(theSet, (int) fCondODP);
  2286.     fCondODP->theLock  =   fMonitorLock;
  2287.     KMDTrace("Monitor", 3,
  2288.     "ActivateCond: condtion 0x%06x tied to mon lock 0x%06x\n", fCondODP,
  2289.     fMonitorLock);
  2290. }
  2291.  
  2292. void DeActivateCond(fCondODP)
  2293. CondODP                 fCondODP;
  2294. {
  2295.     KMDTrace("Monitor", 3,
  2296.     "DeActivateCond: condtion 0x%06x, mon lock 0x%06x\n",
  2297.     fCondODP, fCondODP->theLock);
  2298.  
  2299.     /* The fCondODP is not removed from the Set of conditions tied
  2300.        to the monitor lock since that set is destroyed later
  2301.        anyway. */
  2302.     fCondODP->theLock  =   (MonitorLockPtr) NULL;
  2303.     fCondODP->waiting  =   (SSPtr) NULL;
  2304. }
  2305.  
  2306. /************************************************************************/
  2307.  
  2308. void WaitCond(fMonitorLock, fCondODP)
  2309. MonitorLock            *fMonitorLock;
  2310. CondODP                 fCondODP;
  2311. {
  2312.     KMDTrace("Monitor", 3, "%s WaitCond in %s\n",
  2313.     PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
  2314.     if (IsNIL(fCondODP)) {
  2315.     KMDTrace("Monitor", 2, "Waiting on NIL not allowed; failure in %s\n",
  2316.         PPSSPlace(currentSSP));
  2317.     KMDTrace("Failure", 3, "Waiting on NIL not allowed; failure in %s\n",
  2318.         PPSSPlace(currentSSP));
  2319.     fail(preemptRunning());
  2320.         return;
  2321.     }
  2322.     
  2323.     if (IsNIL(fCondODP->theLock)) ActivateCond(fMonitorLock, fCondODP);
  2324.     if (fCondODP->theLock != fMonitorLock) {
  2325.     KMDTrace("Monitor", 2,
  2326.         "Illgal attempt to wait on condition outside its monitor in %s\n",
  2327.         PPSSPlace(currentSSP));
  2328.     fail(preemptRunning());
  2329.     return;
  2330.     }
  2331.     currentSSP->status.rs   = SSCondWait;
  2332.     KMDTrace("LineNumber", 4, "%s waiting on condition in %s\n",
  2333.     PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
  2334.     insertQ(&fCondODP->waiting, preemptRunning());
  2335.     MonitorExit(fMonitorLock);
  2336. }
  2337.  
  2338. /************************************************************************/
  2339.  
  2340. void SignalCond(fMonitorLock, fCondODP)
  2341. MonitorLock            *fMonitorLock;
  2342. CondODP                 fCondODP;
  2343. {
  2344.     register SSPtr        awakened;
  2345.  
  2346.     KMDTrace("Monitor", 3,
  2347.     "%s SignalCond in %s\n",
  2348.     PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
  2349.  
  2350.     if (IsNIL(fCondODP)) {
  2351.     KMDTrace("Monitor", 2, "Signal on NIL not allowed; failure in %s\n",
  2352.         PPSSPlace(currentSSP));
  2353.     KMDTrace("Failure", 3, "Signal on NIL not allowed; failure in %s\n",
  2354.         PPSSPlace(currentSSP));
  2355.     fail(preemptRunning());
  2356.     }
  2357.  
  2358.     if (IsNIL(fCondODP->theLock)) ActivateCond(fMonitorLock, fCondODP);
  2359.     if (fCondODP->theLock != fMonitorLock) {
  2360.     KMDTrace("Monitor", 2,
  2361.         "Illgal attempt to signal condition outside its monitor\n");
  2362.     fail(preemptRunning());
  2363.     return;
  2364.     }
  2365.     if (NonNULL(awakened = removeQ(&fCondODP->waiting))) {
  2366.     /* Signal and wait sematics */
  2367.     KMDTrace("Monitor", 3,
  2368.         "Signalling process %s\n", PPPOID(awakened->processOID));
  2369.         currentSSP->status.rs   = SSMonWait;
  2370.     KMDTrace("LineNumber", 4, "%s signalled %s, awaiting reentry in %s\n",
  2371.         PPPOID(currentSSP->processOID), PPPOID(awakened->processOID),
  2372.             PPSSPlace(currentSSP));
  2373.     insertQ(&fMonitorLock->waiting, preemptRunning());
  2374.     /* Let the signalled process run inside the monitor */
  2375.     schedule(awakened);
  2376.     }
  2377. }
  2378.  
  2379. /************************************************************************/
  2380.  
  2381. void SignalAndExitCond(fMonitorLock, fCondODP)
  2382. MonitorLock            *fMonitorLock;
  2383. CondODP                 fCondODP;
  2384. {
  2385.     register SSPtr        awakened;
  2386.  
  2387.     KMDTrace("Monitor", 3,
  2388.     "%s SignalCond in %s\n",
  2389.     PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
  2390.  
  2391.     if (IsNIL(fCondODP)) {
  2392.     KMDTrace("Monitor", 2, "Signal on NIL not allowed; failure in %s\n",
  2393.         PPSSPlace(currentSSP));
  2394.     KMDTrace("Failure", 3, "Signal on NIL not allowed; failure in %s\n",
  2395.         PPSSPlace(currentSSP));
  2396.     fail(preemptRunning());
  2397.     }
  2398.  
  2399.  
  2400.     if (IsNIL(fCondODP->theLock)) ActivateCond(fMonitorLock, fCondODP);
  2401.     if (fCondODP->theLock != fMonitorLock) {
  2402.     KMDTrace("Monitor", 2,
  2403.         "Illgal attempt to signal condition outside its monitor\n");
  2404.     fail(preemptRunning());
  2405.     return;
  2406.     }
  2407.     if (NonNULL(awakened = removeQ(&fCondODP->waiting))) {
  2408.     /* Brinch Hansen s continue sematics */
  2409.     KMDTrace("Monitor", 3, "Signalling process %s\n",
  2410.         PPPOID(awakened->processOID));
  2411.     schedule(awakened);
  2412.     } else {
  2413.     /* No process to continue, so exit monitor. */
  2414.     MonitorExit(fMonitorLock);
  2415.     }
  2416. }
  2417.  
  2418. void CondInit(fCondODP)
  2419. CondODP         fCondODP;
  2420. {
  2421.     KMDTrace("Monitor", 3, "CondInit(0x%06x) in %s\n", fCondODP,
  2422.     PPSSPlace(currentSSP));
  2423.     fCondODP->tag.tag = CondTag;
  2424.     fCondODP->theLock = (MonitorLock *) EMNIL;
  2425.     fCondODP->waiting = (SSPtr) NULL;
  2426.     KMDTrace("FixMe", 5,
  2427.     "(Fix me: need to check that baptism of Cond is ok)\n");
  2428. }
  2429.  
  2430. /************************************************************************/
  2431. /************************************************************************/
  2432.  
  2433. /************************************************************************/
  2434. /*  Failure handling                                                    */
  2435. /************************************************************************/
  2436.  
  2437. /* Forward */
  2438. void fail();
  2439.  
  2440. /************************************************************************/
  2441. /*      UnwindStack                                                     */
  2442. /************************************************************************/
  2443.  
  2444. Boolean UnwindStack(fSSPtr, fHasInvokeQueue)
  2445. register SSPtr      fSSPtr;
  2446. Boolean             fHasInvokeQueue;
  2447. /* Unwind the stack by going down one activation record
  2448.    Return false iff bottom reached */
  2449. {
  2450.     /*
  2451.      * This relatively simple procedure merely involves restoring the
  2452.      * register from the DynamicLink.  Unfortunately, we must also
  2453.      * restore the variables that have been allocated in registers.
  2454.      * This complicates matters since we must traverse the template
  2455.      * looking for registers that were saved in the AR.
  2456.      */
  2457.      
  2458.    
  2459.     register DynamicLinkPtr     link;
  2460.     CodePtr                     cPtr;
  2461.     Offset                      unwindFromOffset, templateOffset;
  2462.     IPMapPtr                    templateMap;
  2463.     TemplatePtr                 tPtr;
  2464.     int                         i;
  2465.     SSAddr                      sAddr;
  2466.     TemplateEntryPtr            t;
  2467.     
  2468.     link = mDynLinkPtrFromL(fSSPtr->regs.l);
  2469.     if (fHasInvokeQueue && !mStoppedAtEntry(fSSPtr)) {
  2470.     /* It may or may not be in the invoke queue */
  2471.         EnsureRemovedFromInvokeQueue(fSSPtr->regs.l);
  2472.     }
  2473.  
  2474.     if (IsNULL(link->l)) return FALSE;
  2475.  
  2476.     /* Find the template */
  2477.     if (IsNIL(fSSPtr->regs.g)) {
  2478.         ErrMsg("NIL object invoked; attempting recovery\n");
  2479.         ErrMsg("<< WARNING >> no register restoring for process %s\n",
  2480.         PPPOID(fSSPtr->processOID));
  2481.         KMDTrace("FixMe", 3,
  2482.         "<< WARNING >> no register restoring for process %s\n",
  2483.         PPPOID(fSSPtr->processOID));
  2484.         /* Problem: we cannot get ahold of the code ptr and must
  2485.         give up on register restoring */
  2486.     goto AFTERREGISTERRESTORE;
  2487.     }
  2488.     
  2489.     cPtr            = fSSPtr->regs.g->myCodePtr;
  2490.     assert(NonNULL(cPtr));
  2491.     unwindFromOffset= (Offset) byteOffset(cPtr, *fSSPtr->regs.sp);
  2492.     assert(NonNULL(cPtr->templateMapOffset));
  2493.     templateMap     = (IPMapPtr) addOffset(cPtr, cPtr->templateMapOffset);
  2494.     assert(NonNULL(templateMap));
  2495.     templateOffset  = (Offset) IPMapLookup(templateMap, unwindFromOffset);
  2496.     assert(NonNULL(templateOffset));
  2497.     tPtr            = (TemplatePtr) addOffset(cPtr, templateOffset);
  2498.     assert(NonNULL(tPtr));
  2499.  
  2500.     sAddr           = (SSAddr) link;
  2501.     t               = &tPtr->entry[0];
  2502.     for (i = 0; i < tPtr->B.numEntries; i++) {
  2503.  
  2504.     switch (t->TE.SS.Format) {
  2505.  
  2506.     case ShortStaticF: {
  2507.         KMDTrace("Failure", 5,
  2508.         "\tShortStaticF\t(%s) %s\tcount =%4d\n", 
  2509.         BrandNames[(int)t->TE.SS.theBrand],
  2510.         t->TE.SS.paramInfo != 0 ? "isParam" : " ",
  2511.         t->TE.SS.count);
  2512.  
  2513.         if (t->TE.SS.paramInfo == IsNotParam)
  2514.         switch (t->TE.SS.theBrand) {
  2515.  
  2516.         case DataBrand: {
  2517.         sAddr = (SSAddr)
  2518.             addOffset(sAddr, -t->TE.SS.count);
  2519.         break;
  2520.         }
  2521.         
  2522.         case ODPBrand: {
  2523.         sAddr = (SSAddr)
  2524.             addOffset(sAddr, -sizeof(ODP)*t->TE.SS.count);
  2525.         break;
  2526.         }
  2527.         
  2528.         case AddrBrand:{
  2529.         assert(t->TE.SS.theBrand != AddrBrand);
  2530.         break;
  2531.         }
  2532.  
  2533.         case VectorBrand: {
  2534.         break;
  2535.         } /* case Vector Brand */
  2536.         
  2537.         case VariableBrand: {
  2538.         sAddr = (SSAddr)
  2539.             addOffset(sAddr, -sizeof(AVariable)*t->TE.SS.count);
  2540.         break;
  2541.         }
  2542.         
  2543.         case MonitorBrand: {
  2544.         sAddr = (SSAddr)
  2545.             addOffset(sAddr, -sizeof(MonitorLock));
  2546.         break;
  2547.         }
  2548.         
  2549.         case InvokeQueueBrand: {
  2550.         sAddr = (SSAddr) addOffset(sAddr, -sizeof(InvokeQueue));
  2551.         break;
  2552.         }
  2553.         
  2554.         default: {
  2555.         ErrMsg("Bad brand in UnwindStack\n");
  2556.         break;
  2557.         }
  2558.  
  2559.         } /* end switch */
  2560.  
  2561.         t = (TemplateEntryPtr) addOffset(t, sizeof(ShortStatic));
  2562.         break;
  2563.     }
  2564.  
  2565.     case RegisterF: {
  2566.         int             k;
  2567.         
  2568.         KMDTrace("Failure", 5,
  2569.         "\tRegisterF\t(%s),\t%s, r%d, count %d\n",
  2570.         BrandNames[(int)t->TE.R.theBrand], 
  2571.         t->TE.R.storedWhere == InRegister ? "InRegister"
  2572.         : "InSaveArea", t->TE.R.reg, t->TE.R.count);
  2573.         if (t->TE.R.storedWhere == InSaveArea) {
  2574.         for (k = t->TE.R.count - 1 ; k >= 0; k--) {
  2575.             /* Registers are stored low number, low addr */
  2576.             sAddr--; /* Since we are going backwards, do -- first */
  2577.             if (sAddr < fSSPtr->regs.sp) break;
  2578.             
  2579.             KMDTrace("Failure", 5,
  2580.             "Restoring register r%d, was 0x%02x, new value 0x%02x\n", 
  2581.             t->TE.R.reg+k,
  2582.             mGetSavedReg(&fSSPtr->regs, t->TE.R.reg+k), *sAddr);
  2583.  
  2584.             mSetSavedReg(&fSSPtr->regs, t->TE.R.reg+k,  *sAddr);
  2585.         }
  2586.         }
  2587.         t = (TemplateEntryPtr) addOffset(t, sizeof(t->TE.R));
  2588.         break;
  2589.     } /* case RegisterF */
  2590.     
  2591.     default: {
  2592.         KMDPrint("Bad format %d in UnwindStack\n", t->TE.SS.Format);
  2593.         abort();
  2594.         break;
  2595.     } /* default action */
  2596.  
  2597.     } /* switch on t->TE.SS.Format */
  2598.     } /* for (i = 0; ...) */
  2599.  
  2600. AFTERREGISTERRESTORE:    
  2601.     fSSPtr->regs.l  = link->l;
  2602.     fSSPtr->regs.g  = link->g;
  2603.     fSSPtr->regs.b  = link->b;
  2604.     fSSPtr->regs.sp = (SSAddr) (link+1);
  2605.     
  2606.     PUSHIT(fSSPtr->regs.sp, link->ip);
  2607.  
  2608.     KMDTrace("Failure", 3, "Unwinding stack to %s\n", PPSSPlace(fSSPtr));
  2609.     return TRUE;
  2610. }
  2611.  
  2612. /**********************************************************************/
  2613. /*      BreakObject                                                   */
  2614. /**********************************************************************/
  2615.  
  2616. void BreakObject(fB, fG)
  2617. GODP            fB;
  2618. GODataPtr       fG;
  2619. {
  2620.     KMDTrace("Failure", 3, "Breaking Object 0x%05x, 0x%05x\n", fB, fG);
  2621.     KMDTrace("FixMe", 3, "(Fix me: need to break object)\n");
  2622.     /* cannot do it */
  2623.     return;
  2624. #ifdef BROKEN
  2625.     fG->tag.frozen = fG->tag.broken = TRUE;
  2626.     if (fG->tag.global) {
  2627.     fB->tag.broken = TRUE;
  2628.     fB->tag.frozen = TRUE;
  2629.     }
  2630. #endif BROKEN
  2631. }
  2632.  
  2633. void unavail(fSSPtr, fGODP, fAbConPtr)
  2634. register SSPtr      fSSPtr;
  2635. GODP                fGODP;
  2636. AbConPtr            fAbConPtr;
  2637. /* Called when an unavailable exception occurs */
  2638. {
  2639.     GODataPtr           g;
  2640.     CodeAddr            ip;
  2641.     CodePtr             cPtr;
  2642.     Offset              unavailAtOffset, handlerOffset, mapOffset;
  2643.     IPMapPtr            unavailMapPtr;
  2644.  
  2645.     g = fSSPtr->regs.g;
  2646.     if (g->tag.broken) goto failit;
  2647.  
  2648.     ip = (CodeAddr) *fSSPtr->regs.sp;
  2649.     cPtr = g->myCodePtr;
  2650.     unavailAtOffset = (Offset) byteOffset(cPtr, ip);
  2651.     KMDTrace("Failure", 3, "%s found %s unavailable at offset %d in %s\n",
  2652.     PPPOID(fSSPtr->processOID), PPGOID(fGODP->ownOID), unavailAtOffset,
  2653.     PPSSPlace(fSSPtr));
  2654.     mapOffset = cPtr->unavailableHandlerMapOffset;
  2655.     if (0 == mapOffset) goto failit;
  2656.     unavailMapPtr = (IPMapPtr) addOffset(cPtr, mapOffset);
  2657.     handlerOffset = IPMapLookup(unavailMapPtr, unavailAtOffset);
  2658.     if (0 == handlerOffset) goto failit;
  2659.  
  2660.     /* Found a handler */
  2661.     fSSPtr->resultBrand = VariableBrand;
  2662.     fSSPtr->regs.arg1 = (int) fGODP;
  2663.     fSSPtr->regs.arg2 = (int) fAbConPtr;
  2664.     * (fSSPtr->regs.sp) = (int) addOffset(cPtr, handlerOffset);
  2665.     KMDTrace("Failure", 3, "Calling unavailable handler in %s\n",
  2666.     PPSSPlace(fSSPtr));
  2667.     schedule(fSSPtr);
  2668.     return;
  2669.  
  2670. failit:
  2671.     fail(fSSPtr);
  2672. }
  2673.  
  2674. /**********************************************************************/
  2675. /*      dofail                                                        */
  2676. /**********************************************************************/
  2677. void dofail(fSSPtr, fDoReturnAndFail)
  2678. register SSPtr     fSSPtr;
  2679. Boolean            fDoReturnAndFail;
  2680. /* Called when a process failure has been detected.
  2681.    The process must not be the running process */
  2682. {
  2683.     register CodePtr        cPtr;
  2684.     Offset                  failedAtOffset, handlerOffset, mapOffset;
  2685.     Offset                  tOffset;
  2686.     IPMapPtr                failMapPtr, map;
  2687.     TemplatePtr             tPtr;
  2688.     register GODataPtr      g;
  2689.     GODP                    b;
  2690.     Boolean                 keepGoing;
  2691.     CodeAddr                ip;
  2692.  
  2693. refail:         /* recursion removed to avoid excessive stack usage */
  2694.     KMDTrace("Failure", 5,
  2695.         "Propogating failure b=0x%06x, g=0x%06x, l=0x%06x\n", fSSPtr->regs.b,
  2696.     fSSPtr->regs.g, fSSPtr->regs.l);
  2697.     keepGoing = fSSPtr->regs.l != (SSAddr) NULL;
  2698.     /* Invariant:  keepGoing iff there are more ARs in this SS */
  2699.     while (keepGoing) {
  2700.     g = fSSPtr->regs.g;
  2701.     b = fSSPtr->regs.b;
  2702.     ip = (CodeAddr) *fSSPtr->regs.sp;
  2703.     if (IsNIL(g) || IsNIL(b) || g->tag.broken) {
  2704.         KMDTrace("Failure", 3,
  2705.         "Failure propagating past broken object (or invalid b/g)\n");
  2706.         keepGoing = UnwindStack(fSSPtr, FALSE);
  2707.             fDoReturnAndFail = FALSE; /* we have done (at least one) return */
  2708.         continue;
  2709.     }
  2710.     cPtr = g->myCodePtr;
  2711.     failedAtOffset = (Offset) byteOffset(cPtr, ip);
  2712.     registerSave[regs_sp] = (int) fSSPtr->regs.sp;
  2713.     registerSave[regs_l] = (int) fSSPtr->regs.l;
  2714.     registerSave[regs_g] = (int) fSSPtr->regs.g;
  2715.     registerSave[regs_b] = (int) fSSPtr->regs.b;
  2716.     registerSave[4] = (int) fSSPtr->regs.r4;
  2717.     registerSave[5] = (int) fSSPtr->regs.r5;
  2718.     registerSave[6] = (int) fSSPtr->regs.r6;
  2719.     registerSave[7] = (int) fSSPtr->regs.r7;
  2720.     registerSave[8] = (int) fSSPtr->regs.r8;
  2721.     registerSave[9] = (int) fSSPtr->regs.r9;
  2722.     KMDTrace("LineNumber", 3, "*Process %s failed\n",
  2723.       PPPOID(fSSPtr->processOID));
  2724.     KMDTrace("Failure", 3, "Process %s failed at offset %d in %s\n",
  2725.         PPPOID(fSSPtr->processOID), failedAtOffset, PPSSPlace(fSSPtr));
  2726.     map = (IPMapPtr) addOffset(cPtr, cPtr->templateMapOffset);
  2727.     tOffset = IPMapLookup(map, failedAtOffset);
  2728.     assert(0 != tOffset);
  2729.     tPtr = (TemplatePtr) addOffset(cPtr, tOffset);
  2730.  
  2731.     if (fDoReturnAndFail) {
  2732.         KMDTrace("Failure", 5, "Return and fail\n");
  2733.         keepGoing = UnwindStack(fSSPtr, tPtr->B.hasInvokeQueue);
  2734.         fDoReturnAndFail = FALSE; /* Real fail from now on */         
  2735.         continue;
  2736.     }
  2737.     
  2738.     if (mStoppedAtEntry(fSSPtr)) {
  2739.         KMDTrace("Failure", 5, "Stopped at entry\n");
  2740.         keepGoing = UnwindStack(fSSPtr, tPtr->B.hasInvokeQueue);
  2741.         continue;
  2742.     }
  2743.     
  2744.     /* Attempt to find a failure handler for the object */
  2745.     mapOffset = cPtr->failureHandlerMapOffset;
  2746.     if (0 == mapOffset) {
  2747.         /* No handlers at all */
  2748.         keepGoing = UnwindStack(fSSPtr, tPtr->B.hasInvokeQueue);
  2749.         if (tPtr->B.exclusiveAccess) {
  2750.         BreakObject(b, g);
  2751.         }
  2752.         continue;
  2753.     }
  2754.  
  2755.     failMapPtr = (IPMapPtr) addOffset(cPtr, mapOffset);
  2756.     handlerOffset = IPMapLookup(failMapPtr, failedAtOffset);
  2757.     if (0 == handlerOffset) {
  2758.         /* No handler for this instruction */
  2759.         keepGoing = UnwindStack(fSSPtr, tPtr->B.hasInvokeQueue);
  2760.         if (tPtr->B.exclusiveAccess) {
  2761.         BreakObject(b, g);
  2762.         }
  2763.         continue;
  2764.     }
  2765.     
  2766.     /* Found a handler */
  2767.     * (fSSPtr->regs.sp) = (int) addOffset(cPtr, handlerOffset);
  2768.     KMDTrace("Failure", 3, "Calling failure handler in %s\n",
  2769.         PPSSPlace(fSSPtr));
  2770.     schedule(fSSPtr);
  2771.     return;
  2772.     }
  2773.  
  2774.     /* We have now unwound all the ARs in the current SS.
  2775.        Propogate failure across a stack segment break */
  2776.  
  2777.     if (NonNULL(fSSPtr->rPtr))
  2778.     switch (((GenericReqPtr)(fSSPtr->rPtr))->hdr.rTag) {
  2779.     
  2780.     case StackBreakRTag: {
  2781.     register SSPtr              old;
  2782.     register StackBreakReqPtr   req;
  2783.     register DynamicLinkPtr     dynLink;
  2784.     SSAddr                      argumentLowAddr, resultLowAddr,
  2785.                         returnAddr;
  2786.  
  2787.     req = (StackBreakReqPtr) fSSPtr->rPtr;
  2788.  
  2789.     old = req->oldSSPtr;
  2790.         
  2791.     dynLink                     = (DynamicLinkPtr)
  2792.         addOffset(old->regs.sp, sizeof(SSAddr));
  2793.     old->regs.b                 = dynLink->b;
  2794.     old->regs.g                 = dynLink->g;
  2795.     old->regs.l                 = dynLink->l;
  2796.     returnAddr                  = dynLink->ip;
  2797.     
  2798.     argumentLowAddr             = (SSAddr) (dynLink+1);
  2799.     
  2800.     resultLowAddr               = (SSAddr) addOffset(argumentLowAddr,
  2801.         req->argumentCount * sizeof(AVariable));
  2802.     if (req->resultCount > 0) {
  2803.         /* Copy in results */
  2804.         bcopy((char *)fSSPtr->regs.sp, (char *)resultLowAddr,
  2805.         req->resultCount*sizeof(AVariable));
  2806.     }
  2807.     fSSPtr->regs.sp             = (SSAddr) resultLowAddr;
  2808.     PUSHIT(fSSPtr->regs.sp, returnAddr);
  2809.     fSSPtr->rPtr                = (GenericPtr) NULL;
  2810.     old->invokePtr              = (GenericPtr) NULL;
  2811.     free((char *)req);
  2812.     DiscardStackSegment(fSSPtr);
  2813.     fSSPtr = old;
  2814.     goto refail;
  2815.     }
  2816.     
  2817.     case IncomingIRTag: {
  2818.     InvokeReturn(fSSPtr, INVOKEFAILED);
  2819.     DiscardStackSegment(fSSPtr);
  2820.     return;
  2821.     }
  2822.     default: {
  2823.     break;
  2824.     }
  2825.     }
  2826.     
  2827.     KMDTrace("Failure", 3, "Cannot propagate failure\n");
  2828.     KMDTrace("Failure", 3, "halting process %s in %s\n",
  2829.     PPPOID(fSSPtr->processOID), PPSSPlace(fSSPtr));
  2830.     ErrMsg("Process %s broke and died at offset %d in %s\n",
  2831.     PPPOID(fSSPtr->processOID), failedAtOffset,
  2832.     PPSSPlace(fSSPtr));
  2833.     DiscardStackSegment(fSSPtr);
  2834. }
  2835.  
  2836. /**********************************************************************/
  2837. /*      fail                                                          */
  2838. /**********************************************************************/
  2839.  
  2840. void fail(fSSPtr)
  2841. SSPtr       fSSPtr;
  2842. /* The  process is declared to have failed and the failure is propogated */
  2843. {
  2844.     dofail(fSSPtr, FALSE);
  2845. }
  2846.  
  2847. /**********************************************************************/
  2848. /* Kernel Entry */
  2849. void AssertFailed()
  2850. /* Called when a process asserts FALSE */
  2851. {
  2852.     KMDTrace("Failure", 2, "%s Assertion failed in %s\n",
  2853.     PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
  2854.     fail(preemptRunning());
  2855. }
  2856.  
  2857. /* Kernel Entry */
  2858. void ReturnAndFail()
  2859. {
  2860.     KMDTrace("Failure", 3, "%s ReturnAndFail in %s\n",
  2861.     PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
  2862.     dofail(preemptRunning(), TRUE);
  2863. }
  2864.  
  2865. /* Kernel Entry */
  2866. void NotImplemented()
  2867. {
  2868.     ErrMsg("NotImplemented;  process %d\n", currentSSP->processOID);
  2869.     ErrMsg("  ***** NOT IMPLEMENTED, DIE DIE *****\n");
  2870.     fail(preemptRunning());
  2871. }
  2872.  
  2873. /* Kernel Entry */
  2874. void InvokeAssumptionFailed(fG, fAbConPtr, fB)
  2875. GODataPtr               fG;
  2876. AbConPtr                fAbConPtr;
  2877. GODP                    fB;
  2878. {
  2879.     ErrMsg("Invoke Assumption failed g=0x%05x, b=0x%05x\n", fG, fB);
  2880.     if (PPValidAddr((SSAddr *) fB)) ErrMsg("B tag: %s\n", PPODTag(fB->tag));
  2881.     if (PPValidAddr((SSAddr *) fAbConPtr)) {
  2882.     ErrMsg("AbCon   AT: %s\n", PPCOID(fAbConPtr->ATOID));
  2883.     ErrMsg("AbCon   CT: %s\n", PPCOID(fAbConPtr->CodeOID));
  2884.     }
  2885.     preemptBrokenRunning();
  2886. }
  2887.  
  2888. /************************************************************************/
  2889. /************************************************************************/
  2890. /************************************************************************/
  2891. /*      OwnCallBack                                                     *
  2892. /************************************************************************/
  2893.  
  2894. /* Call back for ct or at loaded for ownName or ownType */
  2895. HResult OwnCallBack(fReq, fOID)
  2896. OwnReqPtr   fReq;
  2897. OID             fOID;
  2898. {
  2899.   register CodePtr ctype;
  2900.   CodeODP theCodeODP;
  2901.   KMDTrace("Own", 1,
  2902.     "Code object %s loaded, re-starting own%s\n",
  2903.     PPCOID(fOID), fReq->wanted == 1 ? "Name" : "Type");
  2904.  
  2905.   theCodeODP = (CodeODP) OTLookup(fReq->codeOID);
  2906.   assert(NonNULL(theCodeODP));
  2907.   ctype = (CodePtr) theCodeODP->dataPtr;
  2908.   switch (fReq->wanted) {
  2909.     case 1:
  2910.       /* name */
  2911.       fReq->waiting->resultBrand = ODPBrand;
  2912.       fReq->waiting->regs.arg1 = (int) addOffset(ctype, ctype->codeNameOffset);
  2913.       schedule(fReq->waiting);
  2914.       FreeRequest((GenericReqPtr) fReq);
  2915.       KMDTrace("Own", 5, "OwnName done.\n");
  2916.       break;
  2917.     case 2:
  2918.       theCodeODP = (CodeODP) OTLookup(ctype->ownAbstractType);
  2919.       if (IsNULL(theCodeODP) || IsNULL(theCodeODP->dataPtr)) {
  2920.     /* Load the abstract type */
  2921.     KMDTrace("Own", 1, "OwnType waiting for AT %s\n",
  2922.       PPCOID(ctype->ownAbstractType));
  2923.     fReq->ATOID = ctype->ownAbstractType;
  2924.     if (! LoadRequest(fReq->ATOID, (GenericReqPtr) fReq)) {
  2925.       return;
  2926.     } else {
  2927.       theCodeODP = (CodeODP) OTLookup(ctype->ownAbstractType);
  2928.       assert(NonNULL(theCodeODP) && NonNULL(theCodeODP->dataPtr));
  2929.     }
  2930.       }
  2931.       fReq->waiting->resultBrand = ODPBrand;
  2932.       fReq->waiting->regs.arg1 = (int) theCodeODP->dataPtr;
  2933.       schedule(fReq->waiting);
  2934.       FreeRequest((GenericReqPtr) fReq);
  2935.       KMDTrace("Own", 5, "OwnType done.\n");
  2936.       break;
  2937.     case 3:
  2938.       KMDTrace("Own", 5, "loaded of restricted AT %s\n", theCodeODP->ownOID);
  2939.       assert(NonNULL(theCodeODP) && NonNULL(theCodeODP->dataPtr));
  2940.       fReq->waiting->resultBrand = ODPBrand;
  2941.       fReq->waiting->regs.arg1 = (int) theCodeODP->dataPtr;
  2942.       schedule(fReq->waiting);
  2943.       FreeRequest((GenericReqPtr) fReq);
  2944.       KMDTrace("Own", 5, "OwnType done.\n");
  2945.       break;
  2946.       
  2947.     default:
  2948.       break;
  2949.   }
  2950. }
  2951.  
  2952. /* Kernel Entry */
  2953. void OwnName(fAbConPtr)
  2954. AbConPtr                fAbConPtr;
  2955. {
  2956.     register CodePtr ctype;
  2957.     OwnReqPtr req = NULL;
  2958.     ctype = fAbConPtr->cPtr;
  2959.     KMDTrace("Own", 5, "OwnName called for CTOID %s\n",
  2960.       PPCOID(fAbConPtr->CodeOID));
  2961.     
  2962.     if (IsNULL(ctype)) {
  2963.     /* no code pointer, load it */
  2964.     req = mNewRequest(Own);
  2965.     req->wanted = 1 /* ownName */;
  2966.     req->codeOID = fAbConPtr->CodeOID;
  2967.     req->hdr.callBack = OwnCallBack;
  2968.     if (! LoadRequest(req->codeOID, (GenericReqPtr) req)) {
  2969.         req->waiting = preemptRunning();
  2970.         req->waiting->status.rs = SSOwnWait;
  2971.         KMDTrace("Own", 3, "OwnName waiting for CT %s\n",
  2972.           PPCOID(req->codeOID));
  2973.             KMDTrace("LineNumber", 4,
  2974.         "%s delayed by Own Name code loading in %s\n",
  2975.         PPPOID(req->waiting->processOID), PPSSPlace(req->waiting));
  2976.             return;
  2977.     } else {
  2978.         ctype = fAbConPtr->cPtr;
  2979.         assert(NonNULL(ctype));
  2980.     }
  2981.     }
  2982.     currentSSP->resultBrand = ODPBrand;
  2983.     currentSSP->regs.arg1 = (int) addOffset(ctype, ctype->codeNameOffset);
  2984.     KMDTrace("Own", 5, "OwnName done.\n");
  2985. }
  2986.  
  2987. /* Kernel Entry */
  2988. void OwnType(fAbConPtr)
  2989. AbConPtr                fAbConPtr;
  2990. {
  2991.     register CodePtr    ctype;
  2992.     CodeODP             theCodeODP;
  2993.     OwnReqPtr           req = NULL;
  2994.  
  2995.     KMDTrace("Own", 5, "OwnType called for CTOID %s\n",
  2996.       PPCOID(fAbConPtr->CodeOID));
  2997.  
  2998.     if (NonNIL(fAbConPtr->restrictOID)) {
  2999.     /*
  3000.      * The type is restricted.
  3001.      */
  3002.         KMDTrace("Own", 5, "OwnType: ref restricted to %s\n",
  3003.         PPCOID(fAbConPtr->restrictOID));
  3004.     
  3005.         theCodeODP = (CodeODP) OTLookup(fAbConPtr->restrictOID);
  3006.     if (!theCodeODP->tag.setUpDone) {
  3007.         /* restrict AT not here -- load it */
  3008.             
  3009.         req = mNewRequest(Own);
  3010.         req->wanted = 3 /* ownType, resticted AT */;
  3011.         req->codeOID = fAbConPtr->restrictOID;
  3012.         req->hdr.callBack = OwnCallBack;
  3013.         if (! LoadRequest(req->codeOID, (GenericReqPtr) req)) {
  3014.         req->waiting = preemptRunning();
  3015.         req->waiting->status.rs = SSOwnWait;
  3016.         KMDTrace("LineNumber", 4,
  3017.             "%s delayed by Own Type loading in %s\n",
  3018.             PPPOID(req->waiting->processOID),
  3019.             PPSSPlace(req->waiting));
  3020.         KMDTrace("Own", 3, "OwnType waiting for rAT %s in %s\n",
  3021.           PPCOID(req->codeOID), PPSSPlace(req->waiting));
  3022.         return;
  3023.         }
  3024.         theCodeODP = (CodeODP) OTLookup(fAbConPtr->restrictOID);
  3025.         assert(NonNULL(theCodeODP) && NonNULL(theCodeODP->dataPtr));
  3026.         FreeRequest((GenericReqPtr) req);
  3027.     }
  3028.     
  3029.     currentSSP->resultBrand = ODPBrand;
  3030.     currentSSP->regs.arg1   = (int) theCodeODP->dataPtr;
  3031.     return;
  3032.     }
  3033.     
  3034.     /*
  3035.      * The reference is unrestricted.
  3036.      */
  3037.     ctype = fAbConPtr->cPtr;
  3038.     if (ctype == 0) {
  3039.     /* no code pointer, load it */
  3040.     req = mNewRequest(Own);
  3041.     req->wanted = 2 /* ownType */;
  3042.     req->codeOID = fAbConPtr->CodeOID;
  3043.     req->hdr.callBack = OwnCallBack;
  3044.     if (! LoadRequest(req->codeOID, (GenericReqPtr) req)) {
  3045.         req->waiting = preemptRunning();
  3046.         req->waiting->status.rs = SSOwnWait;
  3047.             KMDTrace("LineNumber", 4,
  3048.         "%s delayed by Own Type code loading in %s\n",
  3049.         PPPOID(req->waiting->processOID), PPSSPlace(req->waiting));
  3050.         KMDTrace("Own", 3, "OwnType waiting for CT %s\n",
  3051.           PPCOID(req->codeOID));
  3052.         return;
  3053.     } else {
  3054.         ctype = fAbConPtr->cPtr;
  3055.         assert(NonNULL(ctype));
  3056.     }
  3057.     }
  3058.     theCodeODP = (CodeODP) OTLookup(ctype->ownAbstractType);
  3059.     if (IsNULL(theCodeODP) || IsNULL(theCodeODP->dataPtr)) {
  3060.     /* Load the abstract type */
  3061.     if (IsNULL(req)) {
  3062.         req = mNewRequest(Own);
  3063.         req->wanted = 2;
  3064.         req->codeOID = fAbConPtr->CodeOID;
  3065.         req->hdr.callBack = OwnCallBack;
  3066.     }
  3067.     req->ATOID = ctype->ownAbstractType;
  3068.     if (! LoadRequest(req->ATOID, (GenericReqPtr) req)) {
  3069.         req->waiting = preemptRunning();
  3070.         req->waiting->status.rs = SSOwnWait;
  3071.             KMDTrace("LineNumber", 4,
  3072.         "%s delayed by Own Type code loading in %s\n",
  3073.         PPPOID(req->waiting->processOID), PPSSPlace(req->waiting));
  3074.         KMDTrace("Own", 3, "OwnType waiting for AT %s\n",
  3075.           PPCOID(req->ATOID));
  3076.         return;
  3077.     } else {
  3078.         theCodeODP = (CodeODP) OTLookup(ctype->ownAbstractType);
  3079.         assert(NonNULL(theCodeODP) && NonNULL(theCodeODP->dataPtr));
  3080.     }
  3081.     }
  3082.     currentSSP->resultBrand = ODPBrand;
  3083.     currentSSP->regs.arg1 = (int) theCodeODP->dataPtr;
  3084.     KMDTrace("Own", 5, "OwnType done.\n");
  3085.     if (NonNULL(req)) {
  3086.     FreeRequest((GenericReqPtr) req);
  3087.     }
  3088. }
  3089.  
  3090.  
  3091. #if defined(xkernel) && defined(NODISK)
  3092. Semaphore *builtinsSem;
  3093. int outstandingBuiltinLoadRequests = 0, doingBuiltins = 1;
  3094.  
  3095. void doneLoadingBuiltins()
  3096. {
  3097.   CodeODP             stringODP;
  3098.   KMDTrace("Code", 3, "All required builtins loaded.\n");
  3099.   stringODP = (CodeODP) OTLookup(OIDOfBuiltin(B_INSTCT, STRINGINDEX));
  3100.   assert(NonNULL(stringODP));
  3101.   stringCodePtr = stringODP->dataPtr;
  3102.  
  3103.   timeODP = (CodeODP) OTLookup(OIDOfBuiltin(B_INSTCT, TIMEINDEX));
  3104.   assert(NonNULL(timeODP));
  3105.   timeCodePtr = timeODP->dataPtr;
  3106.   timeAbCon = OIDOIDOIDToAbCon(OIDOfBuiltin(B_INSTAT, TIMEINDEX), 
  3107.                    (OID) NIL,
  3108.                    OIDOfBuiltin(B_INSTCT, TIMEINDEX));
  3109.   xkv(builtinsSem);
  3110. }
  3111.  
  3112. /************************************************************************/
  3113. /************************************************************************/
  3114.  
  3115. HResult doNothing()
  3116. {
  3117. }
  3118.  
  3119. void BuiltinsInit()
  3120. /* Define all the builtin types.                                        */
  3121. {
  3122.   int                 i;
  3123.   int delayed = 0, this;
  3124.   register CompilerLoadReqPtr req;
  3125.   req = mNewRequest(CompilerLoad);
  3126.   req->status = Loading;
  3127.   req->hdr.callBack = doNothing;
  3128.   
  3129.   builtinsSem = xcreatesemaphore(0);
  3130.   for (i = 0; requiredBuiltins[i].id; i++) {
  3131.     this = LoadRequest(requiredBuiltins[i].id, req);
  3132.     delayed = delayed || !this;
  3133.   }
  3134.   if (delayed) {
  3135.     xkp(builtinsSem);
  3136.     xkv(builtinsSem);
  3137.   }
  3138. }
  3139. #else
  3140. /************************************************************************/
  3141. /************************************************************************/
  3142.  
  3143. #define BUILTINSDIRNAME "Builtins"
  3144. extern DotoFilePtr      FLReadInDoto();
  3145. extern void             FLTranslateAndActivateDoto();
  3146.  
  3147. DotoFilePtr        *builtinlist;
  3148.  
  3149. void BuiltinsInit()
  3150. /* Define all the builtin types.                                        */
  3151. {
  3152.     register Builtin   *p;
  3153.     CodeODP             theCodeODP, stringODP;
  3154.     char                builtinDirName[200], fileName[400];
  3155.     char        oldCurrentDirectory[200];
  3156.     DIR                *dirp;
  3157.     struct direct      *dp;
  3158.     int                 i;
  3159.     int                 listsize = 120*sizeof(DotoFilePtr);
  3160.     int                 nextFree = 0;
  3161.     
  3162.     CreateArray((int **)&builtinlist, listsize);
  3163.     
  3164.     /*
  3165.      * Change the current working directory, while in this function.
  3166.      */
  3167.     getwd(oldCurrentDirectory);
  3168.     (void) sprintf(builtinDirName, "%s%s", EMDIR, BUILTINSDIRNAME);
  3169.     KMDTrace("Code", 3, "Loading Builtins from %s\n", builtinDirName);
  3170.     chdir(builtinDirName);
  3171.     dirp    = opendir(".");
  3172.     assert(NonNULL(dirp));
  3173.     for (dp=readdir(dirp); dp != NULL; dp = readdir(dirp)){
  3174.     if (strcmp(&dp->d_name[dp->d_namlen-2], ".o")) continue;
  3175.     (void) sprintf(fileName, "./%s", dp->d_name);
  3176.     if ((nextFree) * sizeof(DotoFilePtr) >= listsize) {
  3177.         EnsureArray((int **)&builtinlist, listsize, listsize*2);
  3178.         listsize += listsize;
  3179.     }
  3180.     
  3181.     builtinlist[nextFree] = FLReadInDoto(fileName);
  3182.     if (IsNULL(builtinlist[nextFree])) {
  3183.         ErrMsg("Could not read file %s\n", fileName);
  3184.         continue;
  3185.     }
  3186.     nextFree++;
  3187.     }
  3188.  
  3189.     chdir(oldCurrentDirectory);
  3190.     
  3191.     /* Check that the required builtins are there */
  3192.     for (p = & requiredBuiltins[0]; p->id != (OID) NULL; p++) {
  3193.     theCodeODP = (CodeODP) OTLookup(p->id);
  3194.     if (IsNULL(theCodeODP) || (theCodeODP->tag.tag != CodeODTag)) {
  3195.         ErrMsg("Missing required builtin %s, OID 0x%05x\n", p->name,
  3196.         p->id);
  3197.         assert(FALSE);
  3198.     }
  3199.     }
  3200.     /* Translate the code (also fires up processes) */
  3201.     for (i = 0; i < nextFree; i++) {
  3202.     FLTranslateAndActivateDoto(builtinlist[i]);
  3203.     }
  3204.     KMDTrace("Code", 3, "%d files containing builtins loaded.\n", nextFree);
  3205.     KMDTrace("Code", 3, "All required builtins present.\n");
  3206.     stringODP = (CodeODP) OTLookup(OIDOfBuiltin(B_INSTCT, STRINGINDEX));
  3207.     assert(NonNULL(stringODP));
  3208.     stringCodePtr = stringODP->dataPtr;
  3209.  
  3210.     timeODP = (CodeODP) OTLookup(OIDOfBuiltin(B_INSTCT, TIMEINDEX));
  3211.     assert(NonNULL(timeODP));
  3212.     timeCodePtr = timeODP->dataPtr;
  3213.     timeAbCon = OIDOIDOIDToAbCon(OIDOfBuiltin(B_INSTAT, TIMEINDEX), 
  3214.                               (OID) NIL,
  3215.                   OIDOfBuiltin(B_INSTCT, TIMEINDEX));
  3216. }
  3217. #endif
  3218. /************************************************************************/
  3219. /************************************************************************/
  3220. /*ARGSUSED*/
  3221. void GetBuiltinsRootSet(fRootSet)
  3222. Set             fRootSet;
  3223. {
  3224. }
  3225.  
  3226. /************************************************************************/
  3227. /*      NodeObjectInit                                                  */
  3228. /************************************************************************/
  3229.  
  3230. void NodeObjectInit()
  3231. {
  3232.     nodeListCTOID = OIDOfBuiltin(B_INSTCT, NODELISTINDEX);
  3233.     nodeListCTODP = (CodeODP) OTLookup(nodeListCTOID);
  3234.     assert(NonNULL(nodeListCTODP));
  3235.     nodeListCodePtr = nodeListCTODP->dataPtr;
  3236.  
  3237.     nodeListElementCTOID = OIDOfBuiltin(B_INSTCT, NODELISTELEMENTINDEX);
  3238.     nodeListElementCTODP = (CodeODP) OTLookup(nodeListElementCTOID);
  3239.     assert(NonNULL(nodeListElementCTODP));
  3240.     nodeListElementCodePtr = nodeListElementCTODP->dataPtr;
  3241.     
  3242.     nodeListElementATOID = OIDOfBuiltin(B_INSTAT, NODELISTELEMENTINDEX);
  3243.     nodeListElementATODP = (CodeODP) OTLookup(nodeListElementATOID);
  3244.  
  3245.     nodeListElementAbCon = OIDOIDOIDToAbCon(nodeListElementATODP->ownOID,
  3246.         (OID) EMNIL, nodeListElementCTODP->ownOID);
  3247.  
  3248.     thisNodeObjectOID = mMakeNodeOIDFromLoc(thisNodeLocation);
  3249.     KMDTrace("Node", 5, "Initializing own node object, OID 0x%05x\n",
  3250.     thisNodeObjectOID);
  3251.     thisNodeCTODP = (CodeODP) OTLookup(OIDOfBuiltin(B_INSTCT, NODEINDEX));
  3252.     assert(NonNULL(thisNodeCTODP));
  3253.     thisNodeCodePtr = thisNodeCTODP->dataPtr;
  3254.     thisNodeODP = (GODP) KernelCheatingCreate(thisNodeObjectOID,
  3255.     thisNodeCTODP->ownOID, 0, (AVariable *) NULL);
  3256.     nodeAbCon = OIDOIDOIDToAbCon(OIDOfBuiltin(B_INSTAT, NODEINDEX),
  3257.         (OID) NIL,
  3258.     OIDOfBuiltin(B_INSTCT, NODEINDEX));
  3259.     OTInsert((ODP) thisNodeODP);
  3260. }
  3261.  
  3262. /************************************************************************/
  3263. /************************************************************************/
  3264. /*ARGSUSED*/
  3265. void GetProcessRootSet(fRootSet)
  3266. Set             fRootSet;
  3267. {
  3268.     /*
  3269.      * Traverse processes data structures and find the processes that are to
  3270.      * go into the root set.
  3271.      */
  3272. }
  3273.  
  3274. /************************************************************************/
  3275. /************************************************************************/
  3276.  
  3277. /************************************************************************/
  3278. /*      Snapshot to shut down kernel                                    */
  3279. /************************************************************************/
  3280.  
  3281. /* Snapshot */
  3282. void Shutdown()
  3283. {
  3284.     time_t              theTime = time((time_t *) 0);
  3285.     KMDPrint("Emerald node #%d will shut down\n", GetLNN());
  3286.     
  3287.     ErrMsg("Request for voluntary shutdown arrived at %s\n", ctime(&theTime));
  3288. #ifdef xsimul
  3289.     ErrMsg("Committing suicide by sending interrupt signal to self.\n");
  3290.     (void) kill(getpid(), SIGINT);
  3291. #else
  3292.     ErrMsg("Committing suicide by calling exit().\n");
  3293.     exit(1);
  3294. #endif
  3295. }
  3296.  
  3297. /************************************************************************/
  3298. /*      Snapshots for dumping processes                                 */
  3299. /************************************************************************/
  3300.  
  3301. /* snapshot */
  3302. void ps()
  3303. {
  3304.     time_t              theTime = time((time_t *) 0);
  3305.     register SSPtr      p;
  3306.     register DQueuePtr  q;
  3307.     Set                 seen;
  3308.  
  3309.     seen = Set_Create();
  3310.     
  3311.     KMDPrint(
  3312.         "Ready processes on node %d, %s\nRunnable:   %4d\t  Load avg %8.4f\n\n",
  3313.     GetLNN(), ctime(&theTime), cEmRunnable, MachineLoadAvg() +
  3314.         (cEmRunnable > 0 ? cEmRunnable-1 : 0));
  3315.     
  3316.     KMDPrint("Process    State          In object\n");
  3317.     if (NonNULL(currentSSP)) {
  3318.     Set_Insert(seen, (int) currentSSP);
  3319.     KMDPrint("%-9.9s  %-13.13s  %s\n", PPPOID(currentSSP->processOID),
  3320.         "Running",  PPSSPlace(currentSSP));
  3321.     }
  3322.  
  3323.     p = readyQ;
  3324.     if (NonNULL(p)) do {
  3325.     p = p->readyQLink;
  3326.     Set_Insert(seen, (int) p);
  3327.     KMDPrint("%-9.9s  %-13.13s  %s\n", PPPOID(p->processOID),
  3328.         "Ready", PPSSPlace(p));
  3329.     } while (p != readyQ);
  3330.  
  3331.     p = stoppedQ;
  3332.     if (NonNULL(p)) do {
  3333.     p = p->readyQLink;
  3334.     Set_Insert(seen, (int) p);
  3335.     KMDPrint("%-9.9s  %-13.13s  STOPPED in %s\n",
  3336.         PPPOID(p->processOID), PPSSRunStatus((int)p->status.rs),
  3337.         PPSSPlace(p));
  3338.     } while (p != stoppedQ);
  3339.     
  3340.     for (q = hasRunDQ.next; q != &hasRunDQ; q = q->next) {
  3341.     p = mDQPtrToSSP(q);
  3342.     if ((Set_Lookup(seen, (int) p) != NIL) || p->status.rs== SSNotInUse) {
  3343.          continue;
  3344.     }
  3345.     Set_Insert(seen, (int) p);
  3346.     KMDPrint("%-9.9s  %-13.13s  %s%s\n", PPPOID(p->processOID),
  3347.             PPSSRunStatus((int)p->status.rs),
  3348.         (p->tag.stopped ? "STOPPED in " : ""),  PPSSPlace(p));
  3349.     }
  3350.  
  3351.     for (q = dormantDQ.next; q != &dormantDQ; q = q->next) {
  3352.     p = mDQPtrToSSP(q);
  3353.     if ((Set_Lookup(seen, (int) p) != NIL) || p->status.rs== SSNotInUse) {
  3354.          continue;
  3355.     }
  3356.     Set_Insert(seen, (int) p);
  3357.     KMDPrint("%-9.9s  %-13.13s  %s%s\n", PPPOID(p->processOID),
  3358.             PPSSRunStatus((int)p->status.rs),
  3359.         (p->tag.stopped ? "STOPPED in " : ""),  PPSSPlace(p));
  3360.     }
  3361.  
  3362.     Set_Destroy(seen);
  3363. }
  3364.  
  3365. /************************************************************************/
  3366. /*      EmInit                                                          */
  3367. /************************************************************************/
  3368.  
  3369. void EmInit()
  3370. /* Em kernel initialization */
  3371. {
  3372.     printf("  Emerald kernel code  : Copyright 1986 Eric Jul\n");
  3373.  
  3374.     /* In order to make file loading and the ensuing dynamic linking
  3375.        faster, the following puts the address of a number of symbols
  3376.        into the KMD translation table thus avoiding a nlist operation
  3377.        for each.
  3378.      */
  3379. #include "ementryset.c"
  3380.  
  3381.     UtilsInit();
  3382.  
  3383.     KMDSetVar(splimit);
  3384.     KMDSetVar(preemptFlag);
  3385.     KMDSetVar(currentSSP);
  3386.     KMDSetVar(kernelsp);
  3387.     KMDSetVar(lastJumpFrom);
  3388.     KMDSetVar(emTracing);
  3389.  
  3390.     KMDSetProcedure(Node_getTimeOfDay);
  3391.     KMDSetProcedure(Node_getLNN);
  3392.     KMDSetProcedure(Node_getName);
  3393.     KMDSetProcedure(Node_system);
  3394.     KMDSetProcedure(Node_getLoadAverage);
  3395.     KMDSetProcedure(Node_setNodeEventHandler);
  3396.     KMDSetProcedure(Node_removeNodeEventHandler);
  3397.     KMDSetProcedure(Node_getActiveNodes);
  3398.     KMDSetProcedure(Node_getAllNodes);
  3399.     KMDSetProcedure(Node_getNodeInformation);
  3400.  
  3401.     KMDSetProcedure(IOPutString);
  3402.     KMDSetProcedure(IOPutInt);
  3403.     KMDSetProcedure(IOPutReal);
  3404.  
  3405.     KMDSetTrace(Failure);
  3406.     KMDSetTrace(Monitor);
  3407.     KMDSetTrace(FixMe);
  3408.     KMDSetTrace(Create);
  3409.     KMDSetTrace(StackSegment);
  3410.     KMDSetTrace(Stack);
  3411.     KMDSetTrace(Node);
  3412.     KMDSetTrace(Own);
  3413.     KMDSetTrace(Portability);
  3414.     KMDSetTrace(Vector);
  3415.  
  3416. #define printSizeof(xx) DebugMsg(8, "%-20.20s %5d\n", "xx", sizeof (xx));
  3417.  
  3418.     printSizeof(ODTag);
  3419.     printSizeof(TemplateEntry);
  3420.     printSizeof(Template);
  3421.     printSizeof(SS);
  3422.     printSizeof(GOD);
  3423.     printSizeof(CondOD)
  3424.     printSizeof(SSOD);
  3425.     printSizeof(LOData);
  3426.     printSizeof(GOData);
  3427.     printSizeof(Code);
  3428.     printSizeof(Vector);
  3429.     printSizeof(String);
  3430.     printSizeof(MonitorLock);
  3431.  
  3432.     /* Set standard tag values; Note, reset all fields, then set
  3433.        only the relevant ones that are TRUE.
  3434.        For further information, see UtilsInit and PPODTag() in utils.c
  3435.      */
  3436.  
  3437.     bzero((char *) &stdNULLTag, sizeof(stdNULLTag));
  3438.  
  3439.     stdGODTag                   = stdNULLTag;
  3440.     stdGODTag.tag            = GODTag;
  3441.     stdGODTag.global            = /* Global */ 1;
  3442.     stdGODTag.isResident        = /* Yes */ 1;
  3443.     stdGODTag.frozen            = /* Yes */ 1;
  3444.     stdGODTag.otherstuff        = OBSCUREVALUE;
  3445.     
  3446.     stdLODataTag                = stdNULLTag;
  3447.     stdLODataTag.tag            = LOTag;
  3448.     stdLODataTag.isResident     = /* Yes */ 1;
  3449.     stdLODataTag.otherstuff     = OBSCUREVALUE;
  3450.     
  3451.  
  3452.     stdProcessODTag             = stdGODTag;
  3453.     stdProcessODTag.tag         = ProcessODTag;
  3454.  
  3455.     stdGODataTag                = stdNULLTag;
  3456.     stdGODataTag.tag            = GODataTag;
  3457.     stdGODataTag.global            = /* Global */ 1;
  3458.     stdGODataTag.frozen         = /* Yes */ 1;
  3459.     stdGODataTag.otherstuff     = OBSCUREVALUE;
  3460.  
  3461.     stdSSODTag                  = stdNULLTag;
  3462.     stdSSODTag.tag            = SSODTag;
  3463.     stdSSODTag.isResident       = /* Yes */ 1;
  3464.     stdSSODTag.otherstuff       = OBSCUREVALUE;
  3465.  
  3466.  
  3467.     stdSSTag                    = stdNULLTag;
  3468.     stdSSTag.tag            = SSTag;
  3469.     stdSSTag.global            = /* Global */ 1;
  3470.     stdSSTag.otherstuff            = OBSCUREVALUE;
  3471.  
  3472.     stdCodeTag                  = stdNULLTag;
  3473.     stdCodeTag.tag            = CodeTag;
  3474.     stdCodeTag.global            = /* Global */ 0;
  3475.     stdCodeTag.replicated       = /* Yes */ 1;
  3476.     stdCodeTag.isResident       = /* Yes */ 1;
  3477.     stdCodeTag.otherstuff       = OBSCUREVALUE;
  3478.  
  3479.     stdCodeODTag                = stdNULLTag;
  3480.     stdCodeODTag.tag            = CodeODTag;
  3481.     stdCodeODTag.global            = /* Global */ 0;
  3482.     stdCodeODTag.replicated     = /* Yes */ 1;
  3483.     stdCodeODTag.isResident     = /* Yes */ 1;
  3484.     stdCodeODTag.otherstuff     = OBSCUREVALUE;
  3485.     
  3486.     stdAbConTag                 = stdNULLTag;
  3487.     stdAbConTag.tag            = AbConTag;
  3488.     stdAbConTag.otherstuff      = OBSCUREVALUE;
  3489.     
  3490.     stdDotoODTag                = stdNULLTag;
  3491.     stdDotoODTag.tag            = DotoTag;
  3492.     stdDotoODTag.replicated     = /* Yes */ 1;
  3493.     stdDotoODTag.isResident     = /* Yes */ 1;
  3494.     stdDotoODTag.otherstuff     = OBSCUREVALUE;
  3495.  
  3496.     /* Initialize Stack segment administration and ready queue */
  3497.     readyQ        = (SSPtr) NULL;
  3498.     currentSSP        = (SSPtr) NULL;
  3499.     cEmRunnable         = 0; /* cEmRunnable = card(readyQ)+card(currentSSP) */
  3500.     hasRunDQ.next       = &hasRunDQ;
  3501.     hasRunDQ.prev       = &hasRunDQ;
  3502.     dormantDQ.next      = &dormantDQ;
  3503.     dormantDQ.prev      = &dormantDQ;
  3504.  
  3505.     condMap             = Map_CreateSized(INITIALCONDMAPSIZE);
  3506.     KMDSetSnap(DumpCondMap);
  3507.  
  3508.     /* Initialize own location */
  3509.     thisNodeLocation    = mMakeLocation(GetLNN(), 1);
  3510.     
  3511.     
  3512.     KMDSetSnap(Shutdown);
  3513.  
  3514.     KMDSetSnap(ps);
  3515.     KMDSetSnap(StopProcess);
  3516.     KMDSetSnap(StartProcess);
  3517.     
  3518.     /* Initialize everything else */
  3519.  
  3520.     RequestInit();
  3521.     OIDInit();
  3522.     LMInit();
  3523.     ItemInit();
  3524.     TimeSlicerInit();
  3525.     InvokeInit();
  3526.     LocateInit();
  3527.     MoveInit();
  3528.     ConformInit();
  3529.     IOInit();
  3530.     UnixStreamInit();
  3531.     MeasureInit();
  3532.     BuiltinsInit();
  3533.     StreamInit();
  3534.     NodeObjectInit();
  3535.     TimingInit();
  3536.     NodeInit();
  3537.     CPInit(); /* MUST COME AFTER OIDInit() */
  3538. #ifdef INCLUDE_X_WINDOWS
  3539.     XInit();
  3540. #endif
  3541. #ifdef INCLUDE_MLP
  3542.     MLPInit();
  3543. #endif
  3544.  
  3545. #if defined(xkernel) && 0
  3546.     /* Hack to init kmdtraces */
  3547.     KMDStartTrace("Code", 5, -1, TRUE);
  3548.     KMDStartTrace("ProcessSwitch", 5, -1, TRUE);
  3549.     KMDStartTrace("OT", 5, -1, TRUE);
  3550.     KMDStartTrace("Translate", 5, -1, TRUE);
  3551.     KMDStartTrace("LM", 5, -1, TRUE);
  3552.     {
  3553.       extern int traceprocessswitch;
  3554.       extern int tracetcpp;
  3555.       traceprocessswitch=5;
  3556.       tracetcpp = 5;
  3557.     }
  3558. #endif
  3559.     printf("\n");
  3560. #ifdef xkernel
  3561.     startAnEmeraldScheduler();
  3562. #else    
  3563.     /* Exit the kernel -- this will start executing the process. */
  3564.     /* Capture kernel sp; used for all C-routines of the kernel.
  3565.        Let them execute on this stack. */
  3566.     asm("   movl    sp,_kernelsp    ");
  3567.     asm("   jmp     kernel_exit     ");
  3568. #endif xkernel
  3569. }
  3570.  
  3571. /* Snapshot */
  3572. void LineNumber()
  3573. {
  3574.     KMDTrace("LineNumber", 3, "%s in %s", PPPOID(currentSSP->processOID),
  3575.     PPGetPos((unsigned int) registerSave[regs_g],
  3576.         * (unsigned int *) registerSave[regs_sp]));
  3577. }
  3578.  
  3579. /************************************************************************/
  3580.  
  3581. /**********************************************************************/
  3582. /*      DumpCondMap                                                   */
  3583. /**********************************************************************/
  3584.  
  3585. /* Snapshot */
  3586. void DumpCondMap()
  3587. {
  3588.     Set                     theSet;
  3589.     MonitorLock            *theLock;
  3590.     CondODP                 aCondODP;
  3591.     ODP                     theODP;
  3592.     time_t                  theTime = time((time_t *) 0);
  3593.  
  3594.     KMDPrint("DumpCondMap for node #%d at %s\n", GetLNN(), ctime(&theTime));
  3595.  
  3596.     if (Map_Count(condMap) == 0) {
  3597.     KMDPrint("No Conditions defined at this time.\n");
  3598.     return;
  3599.     }
  3600.     KMDPrint("MonitorLock\n");
  3601.     
  3602.     Map_For(condMap, theLock, theSet);
  3603.  
  3604.     /* HACK:  The ODP for the object is found in a not very acceptable
  3605.      * way, search for comments regarding MONITOROFFSETWITHINOBJECT.
  3606.      * (Look in ../h/*.h too.)
  3607.      */
  3608.     theODP = mODPFromMonLockPtr(theLock);
  3609.     assert(NonNULL(theODP) && (theODP->G.tag.otherstuff == OBSCUREVALUE));
  3610.     assert((theODP->G.tag.tag==GODataTag) || (theODP->G.tag.tag==LOTag));
  3611.     KMDPrint("Monintor Lock 0x%06x in object 0x%06x, one of %s\n",
  3612.         theLock, theODP, PPCodePtr(theODP->L.myCodePtr));
  3613.         Set_For(theSet, aCondODP);
  3614.             KMDPrint("  Condition @ 0x%06x, OID: %s\n", aCondODP,
  3615.         PPGOID(aCondODP->ownOID));
  3616.             if (NonNULL(aCondODP->waiting)){
  3617.         KMDPrint("  ->\tAt least one process waiting, last is in %s\n",
  3618.             PPSSPlace(aCondODP->waiting));
  3619.         } else KMDPrint("  ->\tNo processes waiting in condition\n");
  3620.     Set_Next
  3621.     Map_Next
  3622. }
  3623.  
  3624.  
  3625. /* Copyright 1986 Eric Jul */
  3626.