home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * @(#)kOps.c 1.8 2/23/90
- */
-
- /* Copyright 1986 Eric Jul. May not be used for any purpose without */
- /* written permission from the author. */
- /* The Emerald kernel for the Emerald programming language. */
-
- /* Version 5.0 started 1986-05-10, eric */
- /* Initial version started 1985-07-10, eric */
-
- /* This file contains the implementation of the Emerald kernel operations
- as defined in the Kernel Interface Specification.
- Monitor and condition operations, process management.
- Initialization.
- */
-
- #include <sys/types.h>
- #include <stdio.h>
-
- #ifdef xkernel
- #include "userupi.h"
- #include "userprocess.h"
- #endif
-
- #include "Kernel/h/system.h"
- #include "Kernel/h/assert.h"
- #include <sys/time.h>
- #include <sys/dir.h>
- #include "Kernel/h/macros.h"
- #include "Kernel/h/expandArray.h"
- #include "Kernel/h/emTypes.h"
- #include "Kernel/h/timerTypes.h"
- #include "Kernel/h/kmdTypes.h"
- #include "Kernel/h/kEvents.h"
- #include "Kernel/h/mmTypes.h"
- #include "Kernel/h/mmMsgTypes.h"
- #include "Kernel/h/lmTypes.h"
- #include "Kernel/h/emkDefs.h"
- #include "Kernel/h/builtins.h"
- #include "Kernel/h/emeraldTypes.h"
- #include "Kernel/h/consts.h"
- #include "Kernel/h/map.h"
- #include "Kernel/h/set.h"
- #include "Kernel/h/regdefs.h"
- #include "Kernel/h/utils.h"
-
- #include "ementryext.h"
-
- #include "Kernel/Em/reqBuiltins.c"
-
- #define NEWCREATERETURN
-
- extern int etext;
-
- extern void emPause(), QueueTask();
-
- extern Map InitiallyMap, FrozenMap;
- extern void TryInvoke();
-
- extern void MallocInit(), FLInit(), LocateInit(), InvokeInit(), OTInsert(),
- IOInit(), CPInit(), ItemInit(), StreamInit(), MeasureInit(), MoveInit(),
- TimeSlicerInit(), LMInit(), OIDInit(), TimingInit(), UnixStreamInit(),
- RequestInit(),
- ConformInit(), EmallocInit(), GCInit(), NodeInit(), UtilsInit(), XInit();
- #ifdef INCLUDE_MLP
- extern void MLPInit();
- #endif
-
- extern ODP OTLookup(), getFreeOD();
-
- extern int ReturnOffStack; /* Label in assembly code (!) */
- extern char EMDIR[];
-
- extern EmTimePtr Node_getTimeOfDay();
- extern void Node_system();
- extern float Node_getLoadAverage();
- extern int Node_getLNN(), Node_getName();
- extern void Node_setNodeEventHandler(), Node_removeNodeEventHandler(),
- Node_getActiveNodes(), Node_getAllNodes(),
- Node_getNodeInformation();
-
- extern void IOPutString(), IOPutInt(), IOPutReal();
-
- extern void InsertDQ();
-
- extern ODP KernelCheatingCreate();
-
- extern DQueuePtr RemoveDQ();
-
- extern HResult InvokeHandlerCallBack();
-
- void NotImplemented(), EmTrace(); /* Forward */
- void DoStackBreakReturn(); /* Forward */
-
- /* Forward */
- void DumpCondMap();
- /* Forward */
- void LineNumber();
-
- extern TemplatePtr FindTemplate();
- extern OID getNextOID();
-
- extern void SetHandler();
-
- extern void FixInvokeQueue();
-
- extern AbConPtr OIDOIDOIDToAbCon();
-
- /* Current execution environment
- includes the ODPs for the combination.
- */
-
-
- /* The following describe the running process and the ready queue */
-
- SSPtr currentSSP; /* the current process */
- SSAddr splimit; /* stack limit for ditto */
- Boolean preemptFlag; /* true if kernel wants CPU */
- SSPtr readyQ; /* ready processes */
- SSPtr stoppedQ; /* stopped processes */
- DQueue hasRunDQ; /* has run lately */
- DQueue dormantDQ; /* dormant lately */
-
- int cEmRunnable; /* # currently runnable */
- int cEmTimeSlicings; /* # of process switch forced */
-
- SSPtr standbyQueue; /* stacks on hot standby */
- int cEmStandbyCount; /* count of them */
- #define DEFAULTHOTSTANDBYMAX 20 /* Max stack segs to retain */
- int vEmStandbyMax = DEFAULTHOTSTANDBYMAX;
- int vEmStdStackSize = STDSTACKSIZE;
- int vEmMaxStackSize = DEFAULTMAXSTACKSIZE;
-
- #define INITIALCONDMAPSIZE 1024 /* Initial number of conditions*/
- /*
- * CondMap: For every MonitorLock this map contains a Set of all the
- * Conditions that are tied to the MonitorLock. It is used for mobility
- * purposes only: when moving a MonitorLock, the Condtion objects tied to it
- * MUST also be moved. This map enables the mobility code to find the
- * Condition objects given a MonitorLock.
- */
- Map condMap;
-
- /*
- * Debugging aids:
- * lastJumpFrom the compiler has a switch (-gd, I think) that makes it
- * generate a store of the current IP into this variable
- * before every computed jump. (Used for debugging
- * compiler/kernel.)
- * emTracing When set, enables line number tracing.
- * Turned on and off by LineNumber trace.
- * Code must have been compiled using the -gt switch.
- * Both these variables are accessed by compiled code and thus they are part
- * of the compiler/kernel interface.
- */
-
- int lastJumpFrom; /* Last addr jumped from */
- int emTracing; /* TRUE iff line number tracing*/
-
- /* Local variables */
- DataAddr kernelsp; /* kernel sp on every entry */
-
- /* Standard tags for creating new ODs */
- ODTag stdNULLTag;
- ODTag stdGODTag, stdGODataTag, stdSSODTag, stdSSTag,
- stdLODataTag, stdDotoODTag, stdAbConTag,
- stdCodeTag, stdCodeODTag, stdProcessODTag;
-
- /* For printing of the names (cf. utils.c) */
- extern char *BasicTagName[], *BrandNames[];
-
- extern float MachineLoadAvg();
-
- extern Boolean LoadRequest();
-
- extern Boolean PPValidAddr();
-
- EmLocation thisNodeLocation; /* The location of our node */
- OID thisNodeObjectOID;
- CodeODP thisNodeCTODP;
- CodePtr thisNodeCodePtr;
- GODP thisNodeODP;
-
- OID nodeListCTOID, nodeListElementCTOID,
- nodeListElementATOID;
- CodeODP nodeListCTODP, nodeListElementCTODP,
- nodeListElementATODP;
- CodePtr nodeListCodePtr, nodeListElementCodePtr;
- AbConPtr nodeListElementAbCon, nodeAbCon;
-
- CodeODP timeODP;
- AbConPtr timeAbCon;
-
- CodePtr stringCodePtr, timeCodePtr;
-
-
- #define mDQPtrToSSP(fDQPtr) \
- ((SSPtr) addOffset(fDQPtr, - SS_ssDQ))
-
- /************************************************************************/
- /* Processes are timesliced on a round-robin basis every vEmTimeSlice */
- /* milliseconds. Time slicing is only active if there are more than */
- /* two runnable processes. */
- /************************************************************************/
-
- #ifdef xkernel
- #define EMTIMESLICE 100 /* in milliseconds */
- #else
- #define EMTIMESLICE 10 /* in milliseconds */
- #endif
- #define MINTIMESLICE 1 /* (Unix rounds up anyway) */
- int vEmTimeSlice = EMTIMESLICE;
- int TimeSlicerActive = 0; /* TRUE iff time slicer runs*/
- struct itimerval oldSliceVal;
- struct itimerval timeSliceVal = /* for setting timer */
- { {0,0}, {EMTIMESLICE/1000,(EMTIMESLICE%1000)*1000}};
-
- /* Save area for the line number call code */
- int registerSave[16];
-
- /**********************************************************************/
- /* E N D O F D A T A D E F I N I T I O N S */
- /**********************************************************************/
-
-
- /**********************************************************************/
- /* EmeraldSigUpCall */
- /* Called from the real Ultrix signal handler to inform the Emerald */
- /* kernel that an Ultrix signal has occurred. */
- /**********************************************************************/
-
- /*ARGSUSED*/
- void EmeraldSigUpCall(sig)
- int sig;
- /* A real signal has arrived -- make the current preempt itself. */
- {
-
- /* WARNING: This routine is called even if signals are held */
- /* Setting the preempt flag causes processes to preempt themselves*/
- /* at the bottom of the next loop. */
-
- preemptFlag = 1;
-
- /* Setting splimit to kernelsp causes the current process to fail */
- /* the next stackcheck (i.e., at the next invocation) and invoke */
- /* the kernel which may then preempt it. */
- /* Note: kernelsp is a well-known address in the high part of */
- /* memory. Any high address would do. */
-
- splimit = kernelsp;
- }
-
- /**********************************************************************/
- /* Queueing routines for Activation Records */
- /* In the future, these routines will be replaced by assembly code */
- /* since the VAX has machine instructions for these operations. */
- /* The assembly routines are in utils.c */
- /* The following routines may be used on SUNs */
- /**********************************************************************/
-
- #define getNextAR(f) \
- ( (f)->next)
-
- #define setNextAR(f, newARLink) \
- (f)->next = newARLink
-
- #define getPrevAR(f) \
- ( (f)->prev )
-
- #define setPrevAR(f, newARLink) \
- (f)->prev = newARLink
-
-
- #define initARListHead(headODP) \
- headODP->ARListHead.next = headODP->ARListHead.prev = \
- &headODP->ARListHead
-
- #define enterAR(headODP, newElem) \
- if (headODP->ARListHead.next == headODP->ARListHead.prev) { \
- /* Insert into empty list */ \
- headODP->ARListHead.next = headODP->ARListHead.prev = newElem; \
- newElem->next = \
- newElem->prev = & headODP->ARListHead; \
- } else { \
- /* Insert at front of non-empty list */ \
- setNextAR(newElem, getNextAR(&headODP->ARListHead)); \
- setPrevAR(newElem, & headODP->ARListHead); \
- setPrevAR(getNextAR(&headODP->ARListHead), newElem); \
- setNextAR(&headODP->ARListHead, newElem); \
- }; \
- DebugMsg(5, \
- "enterAR: Head OID (0x%04x) = (0x%04x, 0x%04x); newelem(0x%04x) = (0x%04x, 0x%04x)\n", \
- headODP->ownOID, &headODP->ARListHead, \
- getNextAR(&headODP->ARListHead), getPrevAR(&headODP->ARListHead), \
- newElem, getNextAR(newElem), getPrevAR(newElem));
-
- #define removeAR(headODP, elem) \
- { \
- InvokeQueuePtr next, prev; \
- DebugMsg(5, "removeAR: 0x%04x from object 0x%05x\n", \
- elem, headODP->ownOID); \
- /* Remove from queue */ \
- next = getNextAR(elem); \
- prev = getPrevAR(elem); \
- DebugMsg(5, "next 0x%04x, prev 0x%04x\n", next, prev); \
- setNextAR(prev, next); \
- setPrevAR(next, prev); \
- DebugMsg(5, \
- "removeAR: Head OID 0x%04x = (0x%04x, 0x%04x)\n", \
- headODP->ownOID, &(headODP->ARListHead), \
- headODP->ARListHead.next, headODP->ARListHead.prev ); \
- }
-
- /************************************************************************/
-
- /* The following routines are probably obsolete, Jan. 1987, Eric Jul */
- void DoEnqueue()
- {
- InvokeQueuePtr actRecIQ;
- actRecIQ = mInvokeQueuePtrFromL(currentSSP->regs.l);
- DebugMsg(3,
- "Entering ActRecord l=0x%06x into object OID 0x%05x list.\n",
- currentSSP->regs.l, currentSSP->regs.b -> ownOID);
- enterAR (currentSSP->regs.b, actRecIQ);
- }
-
- void DoDequeue()
- {
- InvokeQueuePtr actRecIQ;
- actRecIQ = mInvokeQueuePtrFromL(currentSSP->regs.l);
- DebugMsg(3,
- "Removing ActRecord l=0x%06x from global object OID %d list.\n",
- currentSSP->regs.l, currentSSP->regs.b->ownOID);
- removeAR(currentSSP->regs.b, actRecIQ);
- }
-
- #ifdef OBSOLETEJAN1987
- void RmvFromInvkQueue(fGODP, fL)
- GODP fGODP;
- SSAddr fL;
- /* Remove the activation pointed to by fL from the invoke queue of fGODP,
- if it is there */
- {
- /* Note (Eric Jul, Jan. 1987) This procedure should be replaced
- * by calls to EnsureRemovedFromInvokeQueue.
- */
-
- register InvokeQueuePtr p, thisOne, head;
- thisOne = mInvokeQueuePtrFromL(fL);
- head = &fGODP->ARListHead;
- for (p=head->next; p != head && p != thisOne; p = p->next);
- if (p == thisOne) {
- KMDTrace("InvokeQueue", 3, "Removing AR 0x%06x from IQ of 0x%08x\n",
- fL, fGODP);
- removeAR(fGODP, thisOne);
- }
- }
- #endif OBSOLETEJAN1987
-
- /**********************************************************************/
- /* EnsureRemovedFromInvokeQueue */
- /**********************************************************************/
- void EnsureRemovedFromInvokeQueue(fL)
- SSAddr fL;
- /* If the given activation record is in an Invoke Queue then remove it */
- {
- InvokeQueuePtr iq;
-
- KMDTrace("InvokeQueue", 3, "Ensuring that AR 0x%04x is not in any IQ\n",
- fL);
- iq = mInvokeQueuePtrFromL(fL);
- if ((int) iq->mySSPtr < 0) {
- KMDTrace("InvokeQueue", 5, "Removed from IQ\n");
- iq->mySSPtr = (SSPtr) ( - (int) iq->mySSPtr);
- (void) RemoveDQ((DQueuePtr) iq);
- }
- }
-
- /**********************************************************************/
- /**********************************************************************/
-
- /**********************************************************************/
- /* FindParamSizes */
- /**********************************************************************/
- void FindParamSizes(fRegsPtr, fIP, fArgCountPtr, fResultCountPtr)
- RegisterSavePtr fRegsPtr;
- CodeAddr fIP;
- int *fArgCountPtr, *fResultCountPtr; /* return values */
- /* Given a register area describing an AR, find the number of arguments
- * and results.
- */
- {
- CodePtr cPtr;
- Offset ipOffset, templateOffset;
- IPMapPtr templateMap;
- TemplatePtr tPtr;
- register int i, argCount, resultCount;
- register TemplateEntryPtr t;
-
- argCount = resultCount = 0;
-
- /* Find the template */
- assert(NonNULL(fRegsPtr->g));
- cPtr = fRegsPtr->g->myCodePtr;
- assert(NonNULL(cPtr));
- ipOffset= (Offset) byteOffset(cPtr, fIP);
- assert(NonNULL(cPtr->templateMapOffset));
- templateMap = (IPMapPtr) addOffset(cPtr, cPtr->templateMapOffset);
- assert(NonNULL(templateMap));
- templateOffset = (Offset) IPMapLookup(templateMap, ipOffset);
- assert(NonNULL(templateOffset));
- tPtr = (TemplatePtr) addOffset(cPtr, templateOffset);
- assert(NonNULL(tPtr));
-
- t = &tPtr->entry[0];
- for (i = 0; i < tPtr->B.numEntries; i++) {
-
- switch (t->TE.SS.Format) {
-
- case ShortStaticF: {
- KMDTrace("Stack", 5,
- "\tShortStaticF\t(%s) %s\tcount =%4d\n",
- BrandNames[(int)t->TE.SS.theBrand],
- t->TE.SS.paramInfo != IsNotParam ? "isParam" : " ",
- t->TE.SS.count);
- if (t->TE.SS.paramInfo != IsNotParam)
- switch (t->TE.SS.theBrand) {
-
- case VariableBrand: {
- if (t->TE.SS.paramInfo == IsArgument) {
- argCount += t->TE.SS.count;
- } else resultCount += t->TE.SS.count;
- break;
- }
-
- default: {
- ErrMsg("Bad brand %d in FindParamSizes\n", t->TE.SS.theBrand);
- abort();
- break;
- }
-
- } /* end switch */
-
- t = (TemplateEntryPtr) addOffset(t, sizeof(ShortStatic));
- break;
- }
-
- case RegisterF: {
- break;
- } /* case RegisterF */
-
- default: {
- ErrMsg("Bad format %d in FindParamSizes\n", t->TE.SS.Format);
- abort();
- break;
- } /* default action */
-
- } /* switch on t->TE.SS.Format */
- } /* for (i = 0; ...) */
-
- *fArgCountPtr = argCount;
- *fResultCountPtr = resultCount;
-
- KMDTrace("Move", 5, "%d arg%s, %d result%s for AR at %s\n", argCount,
- mPLURAL(argCount), resultCount, mPLURAL(resultCount),
- PPRegsPlace(fRegsPtr, fIP));
- }
-
- /**********************************************************************/
- /* MoveDownStack */
- /**********************************************************************/
-
- Boolean MoveDownStack(fRegsPtr, fCurrentIP)
- register RegisterSavePtr fRegsPtr;
- CodeAddr *fCurrentIP;
- /*
- * Move down the stack by going down one activation record
- * Return false iff bottom reached
- */
- {
- /*
- * This relatively simple procedure merely involves restoring the
- * register from the DynamicLink. Unfortunately, we must also
- * restore the variables that have been allocated in registers.
- * This complicates matters since we must traverse the template
- * looking for registers that were saved in the AR.
- * At the same time, we must keep track of the current address in
- * the AR, since the register save area may appear anywhere.
- */
-
- register DynamicLinkPtr link;
- CodePtr cPtr;
- Offset unwindFromOffset, templateOffset;
- IPMapPtr templateMap;
- TemplatePtr tPtr;
- int i;
- SSAddr sAddr;
- TemplateEntryPtr t;
-
- link = mDynLinkPtrFromL(fRegsPtr->l);
- if (IsNULL(link->l)) {
- fRegsPtr->l = link->l;
- fRegsPtr->b = link->b;
- fRegsPtr->g = link->g;
- fRegsPtr->sp= (SSAddr) (link+1);
- *fCurrentIP = link->ip;
- return FALSE;
- }
-
- /* Find the template */
- cPtr = fRegsPtr->g->myCodePtr;
- assert(NonNULL(cPtr));
- unwindFromOffset= (Offset) byteOffset(cPtr, *fCurrentIP);
- assert(NonNULL(cPtr->templateMapOffset));
- templateMap = (IPMapPtr) addOffset(cPtr, cPtr->templateMapOffset);
- assert(NonNULL(templateMap));
- templateOffset = (Offset) IPMapLookup(templateMap, unwindFromOffset);
- assert(NonNULL(templateOffset));
- tPtr = (TemplatePtr) addOffset(cPtr, templateOffset);
- assert(NonNULL(tPtr));
-
- sAddr = (SSAddr) link;
- t = &tPtr->entry[0];
- for (i = 0; i < tPtr->B.numEntries; i++) {
-
- switch (t->TE.SS.Format) {
-
- case ShortStaticF: {
- KMDTrace("Stack", 5,
- "\tShortStaticF\t(%s) %s\tcount =%4d\n",
- BrandNames[(int)t->TE.SS.theBrand],
- t->TE.SS.paramInfo != IsNotParam ? "isParam" : " ",
- t->TE.SS.count);
- if (t->TE.SS.paramInfo == IsNotParam)
- switch (t->TE.SS.theBrand) {
-
- case DataBrand: {
- sAddr = (SSAddr)
- addOffset(sAddr, -t->TE.SS.count);
- break;
- }
-
- case ODPBrand: {
- sAddr = (SSAddr)
- addOffset(sAddr, -sizeof(ODP)*t->TE.SS.count);
- break;
- }
-
- case AddrBrand:{
- assert(t->TE.SS.theBrand != AddrBrand);
- break;
- }
-
- case VectorBrand: {
- break;
- } /* case Vector Brand */
-
- case VariableBrand: {
- sAddr = (SSAddr)
- addOffset(sAddr, -sizeof(AVariable)*t->TE.SS.count);
- break;
- }
-
- case MonitorBrand: {
- sAddr = (SSAddr)
- addOffset(sAddr, -sizeof(MonitorLock));
- break;
- }
-
- case InvokeQueueBrand: {
- sAddr = (SSAddr) addOffset(sAddr, -sizeof(InvokeQueue));
- break;
- }
-
- default: {
- ErrMsg("Bad brand %d in MoveDownStack\n", t->TE.SS.theBrand);
- break;
- }
-
- } /* end switch */
-
- t = (TemplateEntryPtr) addOffset(t, sizeof(ShortStatic));
- break;
- }
-
- case RegisterF: {
- int k;
-
- KMDTrace("Stack", 5,
- "\tRegisterF\t(%s),\t%s, r%d, count %d\n",
- BrandNames[(int)t->TE.R.theBrand],
- t->TE.R.storedWhere == InRegister ? "InRegister"
- : "InSaveArea", t->TE.R.reg, t->TE.R.count);
- if (t->TE.R.storedWhere == InSaveArea) {
- for (k = t->TE.R.count - 1 ; k >= 0; k--) {
- /* Registers are stored low number, low addr */
- sAddr--; /* Since we are going backwards, do -- first */
- /* The following check fails when the activation record
- has only partially been allocated, e.g., before the
- allocation phase of the operation preamble. */
- if (sAddr < fRegsPtr->sp) break;
-
- KMDTrace("Stack", 5,
- "Restoring register r%d, was 0x%02x, new value 0x%02x\n",
- t->TE.R.reg+k,
- mGetSavedReg(fRegsPtr, t->TE.R.reg+k), *sAddr);
-
- mSetSavedReg(fRegsPtr, t->TE.R.reg+k, *sAddr);
- }
- }
- t = (TemplateEntryPtr) addOffset(t, sizeof(t->TE.R));
- break;
- } /* case RegisterF */
-
- default: {
- KMDPrint("Bad format %d in MoveDownStack\n", t->TE.SS.Format);
- assert(FALSE);
- break;
- } /* default action */
-
- } /* switch on t->TE.SS.Format */
- } /* for (i = 0; ...) */
-
- fRegsPtr->l = link->l;
- fRegsPtr->g = link->g;
- fRegsPtr->b = link->b;
- fRegsPtr->sp = (SSAddr) (link+1);
- *fCurrentIP = link->ip;
-
- return TRUE;
- }
-
- /**********************************************************************/
- /**********************************************************************/
-
- #ifndef xkernel
- /**********************************************************************/
- /* Pauseing */
- /**********************************************************************/
- doPause()
- {
- struct TaskQueue *event;
- int (*handler)();
- char *argument;
-
- shouldPause = dontPause;
- doMore:
- HoldSigs();
- event = TaskDequeue(&TaskQ);
- if (event != (struct TaskQueue *) NULL) {
- handler = event->handler;
- argument = event->arg;
- enqueue((struct Queue *) &FreeQ, (struct Queue *) event);
- ReleaseSigs();
- DebugMsg(7, "Calling handler 0x%06x\n", handler);
- (*handler)(argument);
- goto doMore;
- } else {
- shouldPause =
- (IsNULL(currentSSP) && IsNULL(readyQ) )
- ? reallyPause : dontPause;
- /* Here: The task queue is empty so we will
- get emPause to actually pause UNLESS
- a process can run OR
- some signal handler puts something on
- the task queue in which case TaskQueue
- will essentially make emPause a noop
- by setting emPause to dontPause.
- */
- }
- ReleaseSigs();
-
- /*
- * emPause now calls sigpause(2). Sigpause
- * requires an argument saying which signals
- * should be BLOCKED. Therefore, give it
- * 0 rather than potluck.
- */
-
- if ( shouldPause == reallyPause ) {
- DebugMsg(5, " ... will pause\n");
- emPause(0);
- }
- }
- #endif
- /**********************************************************************/
-
- /* Stack Segment queueing: Used for singly linked process queues
- * for the running queue, monitor entry queues, and condition variable
- * queues.
- */
-
- void insertQ(fHead, fElem)
- register SSPtr *fHead;
- register SSPtr fElem;
- /* Insert a Stack Segment into a singly circularly linked queue.
- Elements are assumed to be Stack Segments which have a link field
- called readyQLink. */
- /* The head points to the LAST element of the queue. Each queue element
- is a SSOD; the readyQLink field is used to point to
- the SSOD for the next Stack Segment in the queue.
- */
- {
- if (IsNULL(*fHead)) {
- /* Insert into an empty queue */
- *fHead = fElem;
- setRQLink(fElem, fElem); /* (Circular link) */
- } else {
- setRQLink(fElem, getRQLink((*fHead)));
- setRQLink((*fHead), fElem);
- *fHead = fElem;
- };
- }
-
- SSPtr removeQ(fHead)
- register SSPtr *fHead;
- /* Remove an element from the front of the singly circularly linked queue
- indicated by fHead.
- If the queue is empty then return NULL.
- */
- {
- register SSPtr removed;
-
- if ( IsNULL(removed = *fHead) ) {
- /* queue is empty, return null */
- } else if (getRQLink(removed) == removed) {
- /* removing the only process -- null the queue */
- *fHead = (SSPtr) NULL;
- } else {
- /* removing a process leaving the list non-empty */
- removed = getRQLink((*fHead));
- setRQLink((*fHead), getRQLink(removed));
- };
- return(removed);
- }
- /************************************************************************/
- /************************************************************************/
-
- void TimeSliceInterrupt();
- /************************************************************************/
- /* Time Slicer */
- /************************************************************************/
-
- void StartTimeSlicer()
- /* Start the time slicing */
- {
- TimeSlicerActive = 1;
- KMDTrace("ProcessSwitch", 6, "Starting time slicing %d milliseconds.\n",
- vEmTimeSlice);
- #ifdef BSD
- if (setitimer(ITIMER_VIRTUAL, &timeSliceVal, &oldSliceVal)) {
- perror("setitimer:");
- assert(FALSE);
- }
- #else
- #ifdef xkernel
- if (timeSliceVal.it_value.tv_sec == 0 && timeSliceVal.it_value.tv_usec == 0) return;
- xeventregister(TimeSliceInterrupt, 0,
- timeSliceVal.it_value.tv_sec*1000+
- timeSliceVal.it_value.tv_usec/1000, EV_ONCE);
- #endif
- #endif
- }
-
- /* Forward */
- void schedule(), fail();
- SSPtr preemptRunning();
-
- HResult TimeSliceHandler()
- /* Implements round robin Time Slicing */
- {
- KMDTrace("ProcessSwitch", 5, "TimeSliceHandler\n");
- TimeSlicerActive = 0;
- if (cEmRunnable > 1) {
- /* Round robin by moving it to the back of the ready queue */
- if (NonNULL(currentSSP)) {
- KMDTrace("ProcessSwitch", 4,
- "TimeSliceHandler causing process preemption\n");
- cEmTimeSlicings++;
- schedule(preemptRunning());
- /* Note: schedule will ensure that TimeSlicer continues */
- } else {
- KMDTrace("ProcessSwitch", 6, "TimeSlicer rescheduled\n");
- StartTimeSlicer();
- };
- }
- }
-
-
- void TimeSliceInterrupt()
- /* Schedule a handler for the SIGVTALRM signal */
- {
- #ifdef xkernel
- xkhandlerstart();
- #endif xkernel
- HoldSigs();
- QueueTask((HandlerPtr)TimeSliceHandler, (char *)NULL);
- ReleaseSigs();
- #ifdef xkernel
- xkhandlerend();
- #endif xkernel
- }
-
-
-
- /* Snapshot */
- void ResetTimeSlicer(fNewInterval)
- /* Reset the time slicer to the specified interval */
- {
- if (fNewInterval==0) {
- KMDPrint("Turning off Time Slicing\n");
- } else if (fNewInterval < MINTIMESLICE) {
- KMDPrint("Time slice too small, must be at least %d milliseconds.\n",
- MINTIMESLICE);
- return;
- } else {
- KMDPrint("Resetting Time Slicing interval to %d milliseconds\n",
- fNewInterval);
- }
-
- vEmTimeSlice = fNewInterval;
- timeSliceVal.it_value.tv_sec = vEmTimeSlice / 1000;
- timeSliceVal.it_value.tv_usec = (vEmTimeSlice % 1000) * 1000;
- timeSliceVal.it_interval.tv_sec = 0;
- timeSliceVal.it_interval.tv_usec = 0;
- StartTimeSlicer();
- }
-
- void CurrentLoad()
- /* Snapshot */
- {
- KMDPrint("Current load %2d, total time slicings %4d\n",
- cEmRunnable, cEmTimeSlicings);
- }
-
-
- void TimeSlicerInit()
- {
- TimeSlicerActive = 0;
- cEmTimeSlicings = 0;
- KMDTrace("ProcessSwitch", 3,
- "TimeSlicerInit: vEmTimeSlice = %d milliseconds.\n", vEmTimeSlice);
- timeSliceVal.it_value.tv_sec = vEmTimeSlice / 1000;
- timeSliceVal.it_value.tv_usec = (vEmTimeSlice % 1000) * 1000;
- timeSliceVal.it_interval.tv_sec = 0;
- timeSliceVal.it_interval.tv_usec = 0;
- #ifdef BSD
- SetHandler(SIGVTALRM, TimeSliceInterrupt);
- #endif
- KMDSetSnap(ResetTimeSlicer);
- KMDSetSnap(CurrentLoad);
- KMDSetTrace(ProcessSwitch);
- KMDSetTrace(LineNumber);
- KMDSetVar(vEmTimeSlice);
- KMDSetVar(cEmTimeSlicings);
- KMDSetVar(cEmRunnable);
- }
-
-
- /************************************************************************/
- /* Process scheduling */
- /************************************************************************/
-
- void schedule(f)
- register SSPtr f;
- /* Schedule the Stack Segment "f" for execution */
- {
- f->status.rs = SSRunnable;
-
- if(f->tag.stopped) {
- insertQ(&stoppedQ, f);
- return;
- }
- KMDTrace("ProcessSwitch", 4, "%s runnable at %s\n",
- PPPOID(f->processOID), PPSSPlace(f));
- KMDTrace("LineNumber", 4, "%s runnable at %s\n",
- PPPOID(f->processOID), PPSSPlace(f));
- insertQ(&readyQ, f);
- if (cEmRunnable++ && (!TimeSlicerActive)) StartTimeSlicer();
- }
-
- void RunImmediately(f)
- SSPtr f;
- /* Schedule the Stack Segment "f" for execution right now!!! */
- {
- assert(IsNULL(currentSSP));
- f->status.rs = SSRunnable;
-
- if(f->tag.stopped) {
- insertQ(&stoppedQ, f);
- return;
- }
- currentSSP = f;
- splimit = currentSSP->splimit;
- if(f->tag.dormant) {
- InsertDQ(&hasRunDQ, RemoveDQ(&f->ssDQ));
- f->tag.dormant = FALSE;
- }
- KMDTrace("ProcessSwitch", 3, "%s made running at %s\n",
- PPPOID(f->processOID), PPSSPlace(f));
- KMDTrace("LineNumber", 5, "%s made running at %s\n",
- PPPOID(f->processOID), PPSSPlace(f));
- if (cEmRunnable++ && (!TimeSlicerActive)) StartTimeSlicer();
- }
-
- SSPtr preemptRunning()
- /* Preempt the running process */
- {
- register SSPtr preempted;
- if (NonNULL( preempted = currentSSP )) {
- currentSSP = (SSPtr) NULL;
- cEmRunnable--;
- KMDTrace("ProcessSwitch", 3,
- "%s preempted at \t%s\n", PPPOID(preempted->processOID),
- PPSSPlace(preempted));
- KMDTrace("LineNumber", 5,
- "%s preempted at \t%s\n", PPPOID(preempted->processOID),
- PPSSPlace(preempted));
- FixInvokeQueue(preempted);
- }
- /* Assert: currentSSP == NULL */
- return(preempted);
- }
-
- void preemptBrokenRunning()
- /* Preempt the running process, it is broken. Drop references to it. */
- {
- if (NonNULL( currentSSP )) {
- currentSSP->status.rs = SSBroken;
- KMDTrace("ProcessSwitch", 3,
- "%s broken and preempted at \t%s\n",
- PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
- registerSave[regs_g] = (int) currentSSP->regs.g;
- registerSave[regs_sp] = (int) currentSSP->regs.sp;
- KMDTrace("LineNumber", 3,
- "*%s broken and preempted at \t%s\n",
- PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
- currentSSP = (SSPtr) NULL;
- cEmRunnable--;
- }
- /* Assert: currentSSP == NULL */
- }
-
- /**********************************************************************/
- /* ensureRunning */
- /**********************************************************************/
-
- void ensureRunning()
- /* Will ensure that a process is running if there is any that want to */
- {
- while (IsNULL(currentSSP)) {
- if ( NonNULL( currentSSP = removeQ(&readyQ) ) ) {
- KMDTrace("ProcessSwitch", 3, "%s running, \t\t%s\n",
- PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
- splimit = currentSSP->splimit;
- break;
- } else {
- doPause();
- }
- }
- if (currentSSP->tag.dormant) {
- InsertDQ(&hasRunDQ, RemoveDQ(¤tSSP->ssDQ));
- currentSSP->tag.dormant = FALSE;
- }
- }
-
- /************************************************************************/
- /* The following snapshots start and stop a running process */
- /************************************************************************/
-
- /* Snapshot */
- void StopProcess(fOID)
- OID fOID;
- {
- register SSPtr p, q, last;
- register DQueuePtr next;
-
- KMDPrint("Will try to stop process 0x%05x\n", fOID);
- if (currentSSP->processOID == fOID) {
- KMDPrint("Stopping the running process in %s\n",
- PPSSPlace(currentSSP));
- currentSSP->tag.stopped = TRUE;
- insertQ(&stoppedQ, preemptRunning());
- return;
- }
- /* check readyQ */
-
- if (NonNULL(readyQ)) {
- last = p = q = readyQ;
- do {
- p = p->readyQLink;
- if (p->processOID == fOID) {
- /* Found it, now remove from readyQ and stop it */
- /* Delink the one pointed to by p */
- q->readyQLink = p->readyQLink;
- if (p == q) {
- /* removing the only entry */
- readyQ = (SSPtr) NULL;
- } else if (p == last) {
- /* removing the entry at the end of the queue */
- readyQ = q;
- }
-
- cEmRunnable--;
- KMDTrace("ProcessSwitch", 3, "%s stopped in %s\n",
- PPPOID(p->processOID), PPSSPlace(p));
- KMDPrint("Stopping ready process %s in %s\n",
- PPPOID(p->processOID), PPSSPlace(p));
- p->tag.stopped = TRUE;
- insertQ(&stoppedQ, p);
- return;
- } else q = p;
- } while (last != p);
- }
- for (next = hasRunDQ.next; next != &hasRunDQ; next=next->next) {
- p = mDQPtrToSSP(next);
- if ( (p->status.rs == SSNotInUse) || (p->processOID != fOID) ) {
- continue;
- }
- KMDPrint("Stopping blocked process %s\n", PPSSPlace(p));
- p->tag.stopped = TRUE;
- return;
- }
- for (next = dormantDQ.next; next != &dormantDQ; next=next->next) {
- p = mDQPtrToSSP(next);
- if ( (p->status.rs == SSNotInUse) || (p->processOID != fOID) ) continue;
- KMDPrint("Stopping blocked process %s\n", PPSSPlace(p));
- p->tag.stopped = TRUE;
- return;
- }
- KMDPrint("Could not find process OID 0x%05x\n", fOID);
- }
-
- /* Snapshot */
- void StartProcess(fOID)
- OID fOID;
- {
- register SSPtr p, q, last;
- register DQueuePtr next;
-
- /* Search queue for it */
- if (NonNULL(stoppedQ)) {
- last = p = q = stoppedQ;
- do {
- p = p->readyQLink;
- if (p->processOID == fOID) {
- /* Found it, now remove from stoppedQ and stop it */
- /* Delink the one pointed to by p */
- q->readyQLink = p->readyQLink;
- if (p == q) {
- /* removing the only entry */
- stoppedQ = (SSPtr) NULL;
- } else if (p == last) {
- /* removing the entry at the end of the queue */
- stoppedQ = q;
- }
-
- if (!p->tag.stopped) {
- KMDPrint("%s has not been stopped\n",
- PPPOID(p->processOID));
- return;
- }
- p->tag.stopped = FALSE;
- KMDTrace("ProcessSwitch", 3, "%s restarted in %s\n",
- PPPOID(p->processOID), PPSSPlace(p));
- KMDPrint("Continuing %s in %s\n", PPPOID(fOID), PPSSPlace(p));
- schedule(p);
- return;
- } else q = p;
- } while (last != p);
- }
-
- for (next = hasRunDQ.next; next != &hasRunDQ; next=next->next) {
- p = mDQPtrToSSP(next);
- if ( (p->status.rs == SSNotInUse) || (p->processOID != fOID) ) continue;
- KMDPrint("Unstopping %s in %s\n", PPPOID(p->processOID),
- PPSSPlace(p));
- if (!p->tag.stopped) {
- KMDPrint("%s has not been stopped\n", PPPOID(p->processOID));
- return;
- }
- p->tag.stopped = FALSE;
- return;
- }
- for (next = dormantDQ.next; next != &dormantDQ; next=next->next) {
- p = mDQPtrToSSP(next);
- if ( (p->status.rs == SSNotInUse) || (p->processOID != fOID) ) {
- continue;
- }
- KMDPrint("Unstopping %s in %s\n", PPPOID(p->processOID),
- PPSSPlace(p));
- if (!p->tag.stopped) {
- KMDPrint("%s has not been stopped\n", PPPOID(p->processOID));
- return;
- }
- p->tag.stopped = FALSE;
- return;
- }
-
- KMDPrint("Could not find process OID 0x%05x\n", fOID);
- }
-
-
- /************************************************************************/
- void LoopPreempt()
- /* The current process has detected a preemption request at the end of a
- loop, so preempt it in favor of the kernel.
- Note: Round robin process scheduling is handled by the TimeSlicing
- routine -- preemption in this context only means that the kernel
- regains the thread of control.
- */
- {
- /* Merely undo the effects of the preemption request */
- KMDTrace("ProcessSwitch", 6,
- " LoopPreempt: self preempt on loop, process 0x%05x\n",
- currentSSP->processOID);
- preemptFlag = 0;
- if (NonNULL(currentSSP)) splimit = currentSSP->splimit;
- }
-
- /**********************************************************************/
- /* NewStackSegment */
- /**********************************************************************/
-
- SSPtr NewStackSegment(fSize)
- int fSize;
- /* Create a new stack segment of the given Size */
- {
- register int allocSize;
- register SSODP ssp;
- register SSPtr newSS;
-
- /* Round up stack size to multiple of MINSTACKSIZE, if necessary */
- if (fSize < MINSTACKSIZE) {
- fSize = MINSTACKSIZE;
- } else if ((fSize % MINSTACKSIZE) != 0) {
- fSize += MINSTACKSIZE - fSize % MINSTACKSIZE;
- }
- ssp = (SSODP) getFreeOD();
- ssp->tag = stdSSODTag;
- ssp->ownOID = getNextOID();
- allocSize = fSize + (sizeof(SS) + STACKSAFETY);
- ssp->dataPtr = newSS = (SSPtr) emalloc(allocSize);
- newSS->tag = stdSSTag;
- ssp->ownLoc = thisNodeLocation;
- ssp->tag.isResident = TRUE;
-
- newSS->ownOID = ssp->ownOID;
- newSS->segmentSize = fSize;
- newSS->endOfSS = (SSAddr) addOffset(newSS, allocSize);
- newSS->readyQLink = (SSPtr) NULL;
- newSS->ownSSODP = ssp;
- /* Now set up sp and splimit */
- newSS->splimit = (SSAddr)
- addOffset(newSS, sizeof(SS) + STACKSAFETY);
- newSS->regs.sp = newSS->endOfSS;
- newSS->resultBrand = DataBrand;
-
- InsertDQ(&hasRunDQ, &newSS->ssDQ);
-
- OTInsert((ODP) ssp);
-
- KMDTrace("StackSegment", 3,
- "New Stack Seg at 0x%06x SSOID: 0x%05x, size %d\n", newSS,
- ssp->ownOID, fSize);
-
- return(newSS);
- }
-
-
-
- /**********************************************************************/
- /* DiscardStackSegment */
- /**********************************************************************/
- void DiscardStackSegment(fSSPtr)
- register SSPtr fSSPtr;
- {
- register SSODP newSSODP;
-
- assert(((int) fSSPtr->regs.sp % sizeof(int)) == 0);
-
- if (fSSPtr->segmentSize != vEmStdStackSize) {
- /* Unusual size segment, free it */
- KMDTrace("StackSegment", 3,
- "Discarding odd sized stack segment 0x%06x\n", fSSPtr);
- (void) RemoveDQ(&fSSPtr->ssDQ);
- emfree((char *)fSSPtr->ownSSODP);
- emfree((char *)fSSPtr);
- } else {
- /* Standard stack segment, if there are not too many save it */
- if (cEmStandbyCount >= vEmStandbyMax) {
- /* Too many, free it */
- KMDTrace("StackSegment", 3,
- "Too many on standby: discarding SS 0x%05x\n", fSSPtr);
- (void) RemoveDQ(&fSSPtr->ssDQ);
- emfree((char *)fSSPtr->ownSSODP);
- emfree((char *)fSSPtr);
- return;
- }
- fSSPtr->status.rs = SSNotInUse;
- newSSODP = fSSPtr->ownSSODP;
- fSSPtr->tag = stdSSTag;
- newSSODP->tag = stdSSODTag;
- fSSPtr->processOID =
- fSSPtr->ownOID =
- newSSODP->ownOID = (OID) NULL;
- newSSODP->ownLoc = thisNodeLocation;
- fSSPtr->regs.sp = fSSPtr->endOfSS;
- fSSPtr->resultBrand = DataBrand;
- fSSPtr->rPtr = (GenericPtr) NULL;
- fSSPtr->invokePtr = (GenericPtr) NULL;
- bzero(addOffset(fSSPtr, sizeof(SS)), fSSPtr->segmentSize);
- KMDTrace("StackSegment", 3, "Recycling stack segment 0x%05x\n",
- fSSPtr);
- cEmStandbyCount++;
- insertQ(&standbyQueue, fSSPtr);
- }
- }
-
- /**********************************************************************/
- /* FreeUpMovedStackSegment (and ditto EventHandler) */
- /**********************************************************************/
- HResult FreeUpMovedStackSegmentEventHandler(fSSPtr)
- register SSPtr fSSPtr;
- {
- KMDTrace("StackSegment", 3,
- "%s: Freeing up moved stack segment 0x%06x (to 0x%06x)\n",
- PPPOID(fSSPtr->processOID), fSSPtr, fSSPtr->endOfSS);
- (void) RemoveDQ(&fSSPtr->ssDQ);
-
- /* Clean up */
- if (NonNULL(fSSPtr->rPtr)) {
- FreeRequest((GenericReqPtr) fSSPtr->rPtr);
- }
- if (NonNULL(fSSPtr->invokePtr)) {
- FreeRequest((GenericReqPtr) fSSPtr->invokePtr);
- }
-
- emfree((char *)fSSPtr);
- }
-
- void FreeUpMovedStackSegment(fSSPtr)
- register SSPtr fSSPtr;
- {
- assert(((int) fSSPtr->regs.sp % sizeof(int)) == 0);
-
- KMDTrace("Move", 5,
- "%s: Scheduling freeing up of moved stack segment %s (0x%06x)\n",
- PPPOID(fSSPtr->processOID), PPOID(fSSPtr->ownOID), fSSPtr);
-
- QueueTask((HandlerPtr)FreeUpMovedStackSegmentEventHandler, (char *)fSSPtr);
- }
-
- /**********************************************************************/
- /* StdStackSegment */
- /* Return a new standard sized stack segment */
- /**********************************************************************/
- SSPtr StdStackSegment()
- {
- register SSPtr theSSP;
-
- if (cEmStandbyCount > 0) {
- KMDTrace("StackSegment", 3,
- "Using a stack from the hot standby queue.\n");
- cEmStandbyCount--;
- theSSP = removeQ(&standbyQueue);
- return(theSSP);
- } else {
- return(NewStackSegment(vEmStdStackSize));
- }
- }
-
-
- /**********************************************************************/
- /* NewProcess */
- /**********************************************************************/
-
- SSPtr NewProcess()
- /* Create a new process and return the SSODP for it */
- {
- register SSODP ssp;
- register SSPtr newSS;
-
- /* Set up Stack Segment for process */
- newSS = StdStackSegment();
- assert(((int) newSS->regs.sp % sizeof(int)) == 0);
- newSS->status.rs = SSAllocated;
- ssp = newSS->ownSSODP;
- ssp->processOID =
- newSS->processOID = getNextOID();
- KMDTrace("ProcessSwitch", 3, "NewProcess: %s\n", PPPOID(ssp->processOID));
-
- newSS->availStack = vEmMaxStackSize - newSS->segmentSize;
- newSS->rPtr = (int *) NULL;
- newSS->invokePtr = (GenericPtr) NULL;
-
- return(newSS);
- }
-
- /************************************************************************/
- /* StartProcessAtAddr */
- /************************************************************************/
-
- void StartProcessAtAddr(fSSPtr, fB, fG, fEntry)
- register SSPtr fSSPtr;
- GODP fB;
- GODataPtr fG;
- CodeAddr fEntry;
- /* Start up the process indicated by fSSPtr by invoking fEntry in (fB, fG) */
- /* Assumption: The kernel has already pushed any parameters onto the stack */
- /* Called only after doing a NewProcess */
- {
- DebugMsg(2, "Start 0x%05x at 0x%05x with b=0x%05x, g=0x%05x\n",
- fSSPtr->processOID, fEntry, fB, fG);
- assert(((int) fSSPtr->regs.sp % sizeof(int)) == 0);
- fSSPtr->regs.b = (GODP) fB;
- fSSPtr->regs.g = (GODataPtr) fG;
- fSSPtr->resultBrand = DataBrand;
-
- PUSHIT(fSSPtr->regs.sp, 0); /* fake l */
- PUSHIT(fSSPtr->regs.sp, fSSPtr->regs.g); /* g */
- PUSHIT(fSSPtr->regs.sp, fSSPtr->regs.b); /* b */
- fSSPtr->regs.l = fSSPtr->regs.sp;
- /* Note, ReturnOffStack is defined in the kernel stub */
- PUSHIT(fSSPtr->regs.sp, &ReturnOffStack); /* Old PC */
- PUSHIT(fSSPtr->regs.sp, fEntry);
-
- /* It is ready to run now */
- fSSPtr->status.rs = SSRunnable;
- registerSave[regs_g] = (int) fSSPtr->regs.g;
- registerSave[regs_sp] = (int) fSSPtr->regs.sp;
- KMDTrace("LineNumber", 3, "%s will start up in %s\n",
- PPPOID(fSSPtr->processOID), PPSSPlace(fSSPtr));
- schedule(fSSPtr);
- }
-
- /************************************************************************/
-
- void DoReturnOffStack()
- /* Called from the kernel stub when a process returns off the bottom of a
- stack */
- {
- register SSPtr theProcess;
- register GenericReqPtr rPtr;
-
- theProcess = preemptRunning();
-
- assert(((int) theProcess->regs.sp % sizeof(int)) == 0);
-
- /* Find the return point */
- if (IsNULL(theProcess->rPtr)) {
- /* No request means that the process is done */
- KMDTrace("LineNumber", 4, "%s terminated\n",
- PPPOID(theProcess->processOID));
- DiscardStackSegment(theProcess);
- return;
- };
- rPtr = (GenericReqPtr) theProcess->rPtr;
- if (rPtr->hdr.rTag == IncomingIRTag) {
- InvokeReturn(theProcess, INVOKEDONE);
- DiscardStackSegment(theProcess);
- return;
- };
- if (rPtr->hdr.rTag == StackBreakRTag) {
- DoStackBreakReturn(theProcess);
- DiscardStackSegment(theProcess);
- return;
- }
- ErrMsg("Got weird tag %d for return off stack\n", rPtr->hdr.rTag);
- }
-
- /*********************************************************************/
- /* MoreStack */
- /*********************************************************************/
-
- void MoreStack(fSSPtr, fRequest)
- register SSPtr fSSPtr;
- int fRequest;
- {
- register SSPtr new;
- register StackBreakReqPtr req;
- register DynamicLinkPtr oldDynLink, newDynLink;
- TemplatePtr tPtr;
- int paramSize, k;
-
- KMDTrace("Stack", 3, "Expanding stack process %s, request %d, avail %d\n",
- PPPOID(fSSPtr->processOID), fRequest, fSSPtr->availStack);
- assert(((int) fSSPtr->regs.sp % sizeof(int)) == 0);
- if ((fSSPtr->availStack < 0) || (fRequest >= fSSPtr->availStack)) {
- KMDTrace("Failure", 2, "%s out of stack space, request %d in %s\n",
- PPPOID(fSSPtr->processOID), fRequest, PPSSPlace(fSSPtr));
- fail(fSSPtr);
- return;
- } else {
- if ( fRequest <= vEmStdStackSize) {
- new = StdStackSegment();
- } else {
- new = NewStackSegment((int) (fRequest + vEmStdStackSize));
- }
- }
- new->ownSSODP->processOID =
- new->processOID = fSSPtr->processOID;
- new->availStack = fSSPtr->availStack - new->segmentSize;
-
- req = (StackBreakReqPtr) malloc(sizeof(StackBreakReq));
- req->hdr.rTag = StackBreakRTag;
- req->oldSSPtr = fSSPtr;
-
- tPtr = FindTemplate(fSSPtr->regs.g->myCodePtr, *fSSPtr->regs.sp);
- req->argumentCount = req->resultCount = 0;
- for (k = 0; k < tPtr->B.numEntries; k++) {
- if ((tPtr->entry[k].TE.SS.Format != ShortStaticF) ||
- (tPtr->entry[k].TE.SS.paramInfo == IsNotParam)) break;
- if (tPtr->entry[k].TE.SS.paramInfo >= IsResult) {
- req->resultCount += tPtr->entry[k].TE.SS.count;
- } else {
- req->argumentCount += tPtr->entry[k].TE.SS.count;
- }
- }
-
- KMDTrace("Stack", 3, "Stack extend in %s\n", PPSSPlace(fSSPtr));
- KMDTrace("Stack", 4, "%d arg%s, %d result%s\n", req->argumentCount,
- mPLURAL(req->argumentCount), req->resultCount,
- mPLURAL(req->resultCount));
-
- /* Link into both SS */
- new->rPtr = (GenericPtr) req;
- fSSPtr->invokePtr = (GenericPtr) req;
-
- /* Copy dynamicLink and any parameters to new stack */
- paramSize = (req->argumentCount + req->resultCount)*sizeof(AVariable);
- oldDynLink = mDynLinkPtrFromL(fSSPtr->regs.l);
- newDynLink = (DynamicLinkPtr)
- addOffset(new->regs.sp, -paramSize-sizeof(DynamicLink));
- new->regs.sp = (SSAddr) newDynLink;
- bcopy((char *)oldDynLink, (char *)newDynLink,
- paramSize+sizeof(DynamicLink));
-
- new->regs.l = (SSAddr) addOffset(newDynLink, LOFFSETFROMDYNAMICLINK);
- newDynLink->ip = (CodeAddr) &ReturnOffStack;
- newDynLink->l = (SSAddr) NULL;
-
- /* Set ip to continue invocation by copying over */
- PUSHIT(new->regs.sp, *fSSPtr->regs.sp);
-
- new->regs.b = fSSPtr->regs.b;
- new->regs.g = fSSPtr->regs.g;
-
- schedule(new);
- }
-
- /**********************************************************************/
- /* DoStackBreakReturn */
- /**********************************************************************/
-
- void DoStackBreakReturn(fSSPtr)
- register SSPtr fSSPtr;
- /* Cross back over a stack break */
- {
- register SSPtr old;
- register StackBreakReqPtr req;
- register DynamicLinkPtr dynLink;
- SSAddr argumentLowAddr, resultLowAddr, returnAddr;
-
- req = (StackBreakReqPtr) fSSPtr->rPtr;
- assert(NonNULL(req) && (req->hdr.rTag == StackBreakRTag));
- old = req->oldSSPtr;
-
- dynLink = mDynLinkPtrFromL(old->regs.l);
-
- old->regs.b = dynLink->b;
- old->regs.g = dynLink->g;
- old->regs.l = dynLink->l;
- assert(NonNULL(old->regs.l));
- returnAddr = dynLink->ip;
-
- argumentLowAddr = (SSAddr) (dynLink+1);
-
- resultLowAddr = (SSAddr) addOffset(argumentLowAddr,
- req->argumentCount * sizeof(AVariable));
- if (req->resultCount > 0) {
- /* Copy in results */
- bcopy((char *)fSSPtr->regs.sp, (char *)resultLowAddr,
- req->resultCount*sizeof(AVariable));
- }
- old->regs.sp = (SSAddr) resultLowAddr;
- PUSHIT(old->regs.sp, returnAddr);
- fSSPtr->rPtr = (GenericPtr) NULL;
- old->invokePtr = (GenericPtr) NULL;
- KMDTrace("Stack", 3, "Cross stack segment return in %s\n",
- PPSSPlace(old));
- KMDTrace("Stack", 4, "%d arg%s, %d result%s\n", req->argumentCount,
- mPLURAL(req->argumentCount), req->resultCount,
- mPLURAL(req->resultCount));
- free((char *)req);
- /*
- * If the return is from an initially then return the
- * address of the object in arg1. Since we do not know, then
- * just copy over arg1 everytime.
- */
- old->resultBrand = fSSPtr->resultBrand;
- old->regs.arg1 = fSSPtr->regs.arg1; /* Tricky !!! */
- schedule(old);
- }
-
-
- /**********************************************************************/
- /**********************************************************************/
- /* Object Creation */
- /**********************************************************************/
- /**********************************************************************/
-
-
- /**********************************************************************/
- /* AllocateWithOID */
- /**********************************************************************/
-
- GODP AllocateWithOID(cType, fOID, fTotalBytes)
- CodePtr cType;
- OID fOID;
- int fTotalBytes;
- /* Create an object of the specified type with the specified OID
- the instance size is given by fTotalbytes */
- {
- register GODP x;
- register GODataPtr dataPtr;
-
- if (cType->instanceTag.replicated) {
- register RODataPtr rDataPtr;
- /* Create data area (filled in below) */
- rDataPtr = (RODataPtr) emallocnil(fTotalBytes + 0 /* Safety */);
- rDataPtr->myCodePtr = cType;
- rDataPtr->tag = cType->instanceTag;
- rDataPtr->tag.tag = LOTag;
- rDataPtr->ownOID = fOID;
- KMDTrace("Create", 4, "Allocating replicated local obj size %d\n",
- fTotalBytes);
-
- if (fOID != (OID) NULL) OTInsert((ODP) rDataPtr);
- return (GODP) rDataPtr;
- }
-
- KMDTrace("Create", 4, "Allocating %s, size %d\n", PPGOID(fOID),
- fTotalBytes);
- if (IsNULL(fOID) || IsNULL(x = (GODP) OTLookup(fOID))) {
- /* Allocate GOD and fill it in; put return value into return arg.*/
- x = (GODP) getFreeOD();
- x->tag = stdGODTag;
- x->myCodeOID = cType->ownOID;
- x->ownOID = fOID;
- x->tag.xref = (fOID != 0);
- } /* else the GODP already existed */
-
- /* Create data area (filled in below) */
- dataPtr = x->dataPtr=
- (GODataPtr) emallocnil(fTotalBytes + 0 /* safety */);
- x->ownLoc = thisNodeLocation;
- initARListHead(x);
-
- /* Fill-in GOData area */
- dataPtr->tag = stdGODataTag;
- x->tag.replicated =
- dataPtr->tag.replicated = cType->instanceTag.replicated;
- dataPtr->myCodePtr = cType;
-
- if (fOID != (OID) NULL) OTInsert((ODP) x);
- return x;
- }
-
- void SetCreateResult(fX, fCodePtr)
- DataAddr fX;
- CodePtr fCodePtr;
- {
- register AVariablePtr v;
- /* Hack search down stack */
- KMDTrace("Create", 5, "Setting create result 0x%06x for CT %s\n", fX,
- PPCodePtr(fCodePtr));
- v = (AVariablePtr) addOffset(currentSSP->regs.sp, sizeof(CodeAddr));
-
- for(; (byteOffset(v, currentSSP->endOfSS) > 0); v++) {
- if (PPValidAddr((SSAddr *) (v->myAbConPtr)) &&
- (v->myAbConPtr->tag.tag == AbConTag) &&
- (v->myAbConPtr->tag.otherstuff == OBSCUREVALUE) &&
- (v->myAbConPtr->cPtr == fCodePtr) &&
- (IsNIL(v->myAddr))
- ) {
- v->myAddr = fX;
- KMDTrace("Create", 5, "Found createresult at offset %d\n",
- byteOffset(currentSSP->regs.sp, v));
- break;
- }
- }
- }
-
- /**********************************************************************/
- /* MakeObject */
- /**********************************************************************/
-
- GODP MakeObject(cType, fOID, fTotalBytes)
- CodePtr cType;
- int fTotalBytes;
- OID fOID;
- /* Create an object using fTotalBytes as the instance size */
- {
- register GODP x;
- register DynamicLinkPtr nextDL;
- register RegisterSavePtr regsPtr;
- SSPtr p;
-
- assert(cType != (CodePtr) -1); /* Victim of bad translation */
- x = AllocateWithOID(cType, fOID, fTotalBytes);
- KMDTrace("Create", 3, "Created %s, type %s, size %d\n",
- (fOID != (OID) NULL) ? PPGOID(fOID): "object", PPCodePtr(cType),
- fTotalBytes);
- #ifdef NEWCREATERETURN
- SetCreateResult((DataAddr) x, cType);
- #endif NEWCREATERETURN
- if (cType->initially.offset) {
- /* Now make a global call of the objects initially section */
- DebugMsg(4, "Initially of object 0x%04x invoked by process %s\n",
- x, PPPOID(currentSSP->processOID));
-
- /* The following pushes a new Dynamic link onto the stack and
- sets up the virtual registers to execute in a new
- activation record.
- */
- regsPtr = ¤tSSP->regs;
- nextDL =
- (DynamicLinkPtr) addOffset(regsPtr->sp, 4-sizeof(DynamicLink) );
- /* Save old registers */
- nextDL->ip = * ( (CodeAddr *) regsPtr->sp );
- nextDL->l = regsPtr->l;
- nextDL->g = regsPtr->g;
- nextDL->b = regsPtr->b;
- /* Build new regs */
- regsPtr->l = (SSAddr) & nextDL->b;
- regsPtr->b = x;
- regsPtr->g = x->dataPtr;
- regsPtr->sp = (SSAddr) nextDL;
- PUSHIT(regsPtr->sp, addOffset(cType, cType->initially.offset));
- return x;
- }
- /* No initially */
- x->tag.setUpDone = TRUE;
- x->tag.frozen = FALSE;
- if (cType->process.offset) {
- /* A process, fire it up */
- p = NewProcess();
- StartProcessAtAddr(p, x, x->dataPtr,
- (CodeAddr) addOffset(cType,cType->process.offset));
- };
- /* return the new object to the caller */
- return x;
- }
-
- /**********************************************************************/
- /* Create */
- /**********************************************************************/
-
- /* Kernel call */
- void Create(cType)
- CodePtr cType;
- /* Create an instance of a type */
- {
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) MakeObject(cType, (OID) NULL,
- cType->instanceSize);
-
- }
-
- /**********************************************************************/
- /* CreateSized */
- /**********************************************************************/
-
- /* Kernel call */
- void CreateSized(cType, fTotalBytes)
- CodePtr cType;
- int fTotalBytes;
- /* Create an object using fTotalBytes as the instance size */
- {
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1= (int) MakeObject(cType, (OID) NULL, fTotalBytes);
- }
-
- /**********************************************************************/
- /* MakeLocalObject */
- /**********************************************************************/
- LODataPtr MakeLocalObject(cType, fSize)
- register CodePtr cType;
- int fSize;
- /* Generate a new local object */
- {
- register LODataPtr x;
- register DynamicLinkPtr nextDL;
- register RegisterSavePtr regsPtr;
- SSPtr p;
-
- x = (LODataPtr) emallocnil(fSize);
- x->tag = stdLODataTag;
- x->tag.replicated = cType->instanceTag.replicated;
- x->myCodePtr = cType;
- KMDTrace("Create", 3, "Local Create 0x%05x, size %d, code %s\n",
- x, fSize, PPCodePtr(cType));
-
- #ifdef NEWCREATERETURN
- SetCreateResult((DataAddr) x, cType);
- #endif NEWCREATERETURN
-
- if (cType->initially.offset) {
- /* Now make a local call of the objects initially section */
- KMDTrace("Create", 4,
- "Initially of local object 0x%04x invoked by %s\n", x,
- PPPOID(currentSSP->processOID));
-
- /* The following pushes a new Dynamic link onto the stack and
- sets up the virtual registers to execute in a new
- activation record.
- */
- regsPtr = ¤tSSP->regs;
- nextDL =
- (DynamicLinkPtr) addOffset(regsPtr->sp, 4-sizeof(DynamicLink) );
- /* Save old registers */
- nextDL->ip = * ( (CodeAddr *) regsPtr->sp );
- nextDL->l = regsPtr->l;
- nextDL->g = regsPtr->g;
- nextDL->b = regsPtr->b;
- /* Build new regs */
- regsPtr->l = (SSAddr) & nextDL->b;
- regsPtr->g = (GODataPtr) x;
- regsPtr->sp = (SSAddr) nextDL;
- PUSHIT(regsPtr->sp, addOffset(cType, cType->initially.offset));
- return (LODataPtr) x; /* Initially done will return correct val */
- }
- /* No initially */
- if (cType->process.offset) {
- /* A process, fire it up */
- p = NewProcess();
- StartProcessAtAddr(p, currentSSP->regs.b, (GODataPtr) x,
- (CodeAddr) addOffset(cType, cType->process.offset));
- };
- /* return the new object to the caller */
- return x;
- }
-
- /**********************************************************************/
- /* MagicLocalCreate */
- /**********************************************************************/
-
- LODataPtr MagicLocalCreate(cType, fSize)
- register CodePtr cType;
- int fSize;
- /* Generate a new local object for the kernel. No initially nor process. */
- {
- register LODataPtr x;
-
- x = (LODataPtr) emallocnil(fSize);
- x->tag = stdLODataTag;
- x->tag.replicated = cType->instanceTag.replicated;
- x->myCodePtr = cType;
- if (x->tag.replicated) ((RODataPtr) x)->ownOID = (OID) NULL;
- KMDTrace("Create", 3, "Magic Create 0x%05x, size %d, code %s\n",
- x, fSize, PPCodePtr(cType));
- /* Initially must be faked by the calling routine */
- /* No process allowed for magic creates */
- assert (IsNULL(cType->process.offset));
- /* return the new object to the caller */
- return x;
- }
-
- /**********************************************************************/
- /* LocalCreate */
- /**********************************************************************/
- void LocalCreate(cType)
- register CodePtr cType;
- {
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) MakeLocalObject(cType, cType->instanceSize);
- }
-
- /**********************************************************************/
- /* LocalCreateSized */
- /**********************************************************************/
- void LocalCreateSized(cType, fSize)
- register CodePtr cType;
- int fSize;
- {
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) MakeLocalObject(cType, fSize);
- }
-
- /**********************************************************************/
- /* LocalQuickCreate */
- /**********************************************************************/
- void LocalQuickCreate(cType)
- register CodePtr cType;
- {
- register LODataPtr x;
- x = (LODataPtr) emallocnil(cType->instanceSize);
- x->tag = stdLODataTag;
- x->tag.replicated = cType->instanceTag.replicated;
- x->myCodePtr = cType;
- KMDTrace("Create", 3, "Local Quick Create 0x%05x, size %d, code %s\n",
- x, cType->instanceSize, PPCodePtr(cType));
-
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) x;
- }
-
- /**********************************************************************/
- /* LocalQuickCreateSized */
- /**********************************************************************/
- void LocalQuickCreateSized(cType, fSize)
- register CodePtr cType;
- int fSize;
- {
- register LODataPtr x;
-
- x = (LODataPtr) emallocnil(fSize);
- x->tag = stdLODataTag;
- x->tag.replicated = cType->instanceTag.replicated;
- x->myCodePtr = cType;
- KMDTrace("Create", 3, "Local Quick Create 0x%05x, size %d, code %s\n",
- x, fSize, PPCodePtr(cType));
-
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) x;
- }
-
- /**********************************************************************/
- /* GlobalCreateVector */
- /**********************************************************************/
- /* Kernel entry point */
- void GlobalCreateVector(fCodePtr, fSizeInBytes, fupb)
- CodePtr fCodePtr;
- unsigned long fSizeInBytes; /* of vector data */
- unsigned long fupb;
- {
- register GODP x;
- register VectorPtr v;
-
- x = AllocateWithOID(fCodePtr, (OID) NULL, (int) fSizeInBytes+Vector_data);
- v = (VectorPtr) x->dataPtr;
- x->tag.frozen = FALSE;
- x->tag.setUpDone = TRUE;
- v->upb = fupb;
- v->sizeInBytes = fSizeInBytes;
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) x;
- KMDTrace("Create", 3,
- "Created glob vector 0x%05.5x, %d bytes, fupb %d, code %s\n",
- x, fSizeInBytes, fupb, PPCodePtr(fCodePtr));
- #ifdef NEWCREATERETURN
- SetCreateResult((DataAddr) x, fCodePtr);
- #endif NEWCREATERETURN
- }
-
- /**********************************************************************/
- /* GlobalCreateVectorLiteral */
- /**********************************************************************/
-
- void GlobalCreateVectorLiteral(fCodePtr, fSizeOfEachElement, fNElements)
- CodePtr fCodePtr;
- unsigned long fSizeOfEachElement; /* 1 or 4 or 8 */
- unsigned long fNElements;
- {
- register GODP x;
- register VectorPtr v;
- int sizeInBytes = fSizeOfEachElement * fNElements;
- CodeOffset returnAddr;
- register int i, *vectorElementPtr;
- register Bytes *byteVectorElementPtr;
- register SSPtr cssp = currentSSP;
- int data, abcon;
-
- /* save the return address */
- POPIT(cssp->regs.sp, returnAddr);
-
- x = AllocateWithOID(fCodePtr, (OID) NULL, sizeInBytes + Vector_data);
- v = (VectorPtr) x->dataPtr;
- x->tag.frozen = FALSE;
- x->tag.setUpDone = TRUE;
- v->upb = fNElements - 1;
- v->sizeInBytes = sizeInBytes;
- cssp->resultBrand = ODPBrand;
- cssp->regs.arg1 = (int) x;
- byteVectorElementPtr = &v->data[sizeInBytes];
- vectorElementPtr = (int *) byteVectorElementPtr;
-
- KMDTrace("Create", 10,
- "Creating vector literal, eSize = %d, nElements = %d, dataPtr = 0x%08x\n",
- fSizeOfEachElement, fNElements, v);
- KMDTrace("Create", 10, "vectorElementPtr = 0x%08x\n", vectorElementPtr);
- for (i = 0; i < fNElements; i++) {
- POPIT(cssp->regs.sp, data);
- POPIT(cssp->regs.sp, abcon);
- if (fSizeOfEachElement == 8) {
- *--vectorElementPtr = abcon;
- KMDTrace("Create", 10, "Vector literal abcon[%2d] addr(0x%08x) = 0x%x\n",
- fNElements - i - 1, vectorElementPtr, abcon);
- *-- vectorElementPtr = data;
- } else if (fSizeOfEachElement == 4) {
- *-- vectorElementPtr = data;
- } else {
- assert(fSizeOfEachElement == 1);
- *--byteVectorElementPtr = data;
- }
- KMDTrace("Create", 10, "Vector literal[%2d] addr(0x%08x) = 0x%x\n",
- fNElements - i - 1, vectorElementPtr, data);
- }
- PUSHIT(cssp->regs.sp, returnAddr);
- KMDTrace("Create", 3,
- "Created glob vector literal 0x%05.5x, %d bytes, fupb %d, code %s\n",
- x, v->sizeInBytes, v->upb, PPCodePtr(fCodePtr));
- #ifdef NEWCREATERETURN
- SetCreateResult((DataAddr) x, fCodePtr);
- #endif NEWCREATERETURN
- }
-
-
-
- /**********************************************************************/
- /* LocalCreateVectorLiteral */
- /**********************************************************************/
- void LocalCreateVectorLiteral(fCodePtr, fSizeOfEachElement, fNElements)
- CodePtr fCodePtr;
- unsigned long fSizeOfEachElement; /* 1 or 4 or 8 */
- unsigned long fNElements;
- {
- register VectorPtr v;
- int sizeInBytes = fSizeOfEachElement * fNElements;
- CodeOffset returnAddr;
- register int i, *vectorElementPtr;
- register Bytes *byteVectorElementPtr;
- register SSPtr cssp = currentSSP;
- int data, abcon;
-
- /* save the return address */
- POPIT(cssp->regs.sp, returnAddr);
-
- v = (VectorPtr) MakeLocalObject(fCodePtr, sizeInBytes + Vector_data);
- v->upb = fNElements - 1;
- v->sizeInBytes = sizeInBytes;
- cssp->resultBrand = ODPBrand;
- cssp->regs.arg1 = (int) v;
- byteVectorElementPtr = &v->data[sizeInBytes];
- vectorElementPtr = (int *) byteVectorElementPtr;
-
- KMDTrace("Create", 10,
- "Creating local vector literal, eSize = %d, nElements = %d, dataPtr = 0x%08x\n",
- fSizeOfEachElement, fNElements, v);
- KMDTrace("Create", 10, "vectorElementPtr = 0x%08x\n", vectorElementPtr);
- for (i = 0; i < fNElements; i++) {
- POPIT(cssp->regs.sp, data);
- POPIT(cssp->regs.sp, abcon);
- if (fSizeOfEachElement == 8) {
- *--vectorElementPtr = abcon;
- KMDTrace("Create", 10, "Vector literal abcon[%2d] addr(0x%08x) = 0x%x\n",
- fNElements - i - 1, vectorElementPtr, abcon);
- *-- vectorElementPtr = data;
- } else if (fSizeOfEachElement == 4) {
- *-- vectorElementPtr = data;
- } else {
- assert(fSizeOfEachElement == 1);
- *--byteVectorElementPtr = data;
- }
- KMDTrace("Create", 10, "Vector literal[%2d] addr(0x%08x) = 0x%x\n",
- fNElements - i - 1, vectorElementPtr, data);
- }
- PUSHIT(cssp->regs.sp, returnAddr);
- KMDTrace("Create", 3,
- "Created local vector literal 0x%05.5x, %d bytes, fupb %d, code %s\n",
- v, v->sizeInBytes, v->upb, PPCodePtr(fCodePtr));
- #ifdef NEWCREATERETURN
- SetCreateResult((DataAddr) v, fCodePtr);
- #endif NEWCREATERETURN
- }
-
- /**********************************************************************/
- /* CreateImmutableVectorLiteral */
- /**********************************************************************/
- void CreateImmutableVectorLiteral(fCodePtr, fSizeOfEachElement, fNElements)
- CodePtr fCodePtr;
- unsigned long fSizeOfEachElement; /* 1 or 4 or 8 */
- unsigned long fNElements;
- {
- register IMVectorPtr v;
- int sizeInBytes = fSizeOfEachElement * fNElements;
- CodeOffset returnAddr;
- register int i, *vectorElementPtr;
- register Bytes *byteVectorElementPtr;
- register SSPtr cssp = currentSSP;
- int data, abcon;
-
- /* save the return address */
- POPIT(cssp->regs.sp, returnAddr);
-
- v = (IMVectorPtr) emallocnil(sizeInBytes + IMVector_data);
- v->tag = stdLODataTag;
- v->tag.replicated = TRUE;
- v->myCodePtr = fCodePtr;
- v->ownOID = (OID) NULL;
- v->upb = fNElements - 1;
- v->sizeInBytes = sizeInBytes;
- cssp->resultBrand = ODPBrand;
- cssp->regs.arg1 = (int) v;
- byteVectorElementPtr = &v->data[sizeInBytes];
- vectorElementPtr = (int *) byteVectorElementPtr;
-
- KMDTrace("Create", 10,
- "Creating immutable vector literal, eSize = %d, nElements = %d, dataPtr = 0x%08x\n",
- fSizeOfEachElement, fNElements, v);
- KMDTrace("Create", 10, "vectorElementPtr = 0x%08x\n", vectorElementPtr);
- for (i = 0; i < fNElements; i++) {
- POPIT(cssp->regs.sp, data);
- POPIT(cssp->regs.sp, abcon);
- if (fSizeOfEachElement == 8) {
- *--vectorElementPtr = abcon;
- KMDTrace("Create", 10, "Vector literal abcon[%2d] addr(0x%08x) = 0x%x\n",
- fNElements - i - 1, vectorElementPtr, abcon);
- *-- vectorElementPtr = data;
- } else if (fSizeOfEachElement == 4) {
- *-- vectorElementPtr = data;
- } else {
- assert(fSizeOfEachElement == 1);
- *--byteVectorElementPtr = data;
- }
- KMDTrace("Create", 10, "Vector literal[%2d] addr(0x%08x) = 0x%x\n",
- fNElements - i - 1, vectorElementPtr, data);
- }
- PUSHIT(cssp->regs.sp, returnAddr);
- KMDTrace("Create", 3,
- "Created immutable vector literal 0x%05.5x, %d bytes, fupb %d, code %s\n",
- v, v->sizeInBytes, v->upb, PPCodePtr(fCodePtr));
- #ifdef NEWCREATERETURN
- SetCreateResult((DataAddr) v, fCodePtr);
- #endif NEWCREATERETURN
- }
-
-
-
- /**********************************************************************/
- /* LocalCreateVector */
- /**********************************************************************/
- /* Kernel entry point */
- void LocalCreateVector(fCodePtr, fSizeInBytes, fupb)
- CodePtr fCodePtr;
- unsigned long fSizeInBytes;
- unsigned long fupb;
- {
- register VectorPtr v;
- v = (VectorPtr) MakeLocalObject(fCodePtr, (int) fSizeInBytes+Vector_data);
- v->upb = fupb;
- v->sizeInBytes = fSizeInBytes;
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) v;
- KMDTrace("Create", 3,
- "Created local vector 0x%04x, %d data bytes, fupb %d, code %s\n",
- v, fSizeInBytes, fupb, PPCodePtr(fCodePtr));
- }
-
-
- /**********************************************************************/
- /* CreateString */
- /**********************************************************************/
- /* Kernel entry point */
- void CreateString(fSizeInBytes)
- unsigned long fSizeInBytes;
- {
- register StringPtr x;
-
- x = (StringPtr) emalloc((int) (fSizeInBytes + String_data));
- x->tag = stdLODataTag;
- x->tag.replicated = TRUE;
- x->myCodePtr = stringCodePtr;
- x->ownOID = (OID) NULL;
- x->sizeInBytes = fSizeInBytes;
- KMDTrace("Create", 3, "Create String 0x%05x, %d chars, code %s\n",
- x, fSizeInBytes, PPCodePtr(stringCodePtr));
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) x;
- }
-
-
- /**********************************************************************/
- /**********************************************************************/
-
- /**********************************************************************/
- /* UnblockInitially (and now: recovery!) */
- /**********************************************************************/
- void UnblockInitially(fGODP)
- GODP fGODP;
- /* Check to see, if there are any processes waiting for initially/recovery
- to be done. If so, unblock it and set it up for the invocation */
- {
- Map theMap;
- SSPtr theProcess;
- int dummy;
- Set reqSet;
- IncomingIReqPtr req;
-
- theMap = (Map) Map_Lookup(InitiallyMap, (int) fGODP);
- if (NonNIL(theMap)) {
- InitiallyReqPtr ireq;
- KMDTrace("Invoke", 3, "Unblocking %d processes on initially done\n",
- Map_Count(theMap));
- Map_For(theMap, ireq, dummy)
- theProcess = ireq->theProcess;
- theProcess->invokePtr = (GenericPtr) NULL;
- theProcess->status.rs = SSRunnable;
- KMDPrint("Invoke", 3, "%s unblocking on initially done\n",
- PPPOID(theProcess->processOID));
- KMDPrint("LineNumber", 4, "%s unblocking on initially done\n",
- PPPOID(theProcess->processOID));
- /* Now do the invoke */
- TryInvoke(ireq->opNumber, ireq->theAbConPtr, ireq->calleeGODP,
- ireq->theProcess);
- Map_Next
- Map_Destroy(theMap);
- Map_Delete(InitiallyMap, (int) fGODP);
- }
-
- if (IsNULL(fGODP->ownOID)) return;
-
- reqSet = (Set) Map_Lookup(FrozenMap, (int) fGODP->ownOID);
- if (IsNIL(reqSet)) return;
- KMDTrace("Invoke", 3, "Unfreezing %s, %d remote invokes waiting\n",
- PPGOID(fGODP->ownOID), Set_Count(reqSet));
- Set_For(reqSet, req)
- KMDTrace("Invoke", 6, "Doing Invoke callback for req 0x%06x\n", req);
- req->status = IHObjectNonFrozen;
- InvokeHandlerCallBack((GenericReqPtr) req, (OID) NULL);
- Set_Next;
- Set_Destroy(reqSet);
- Map_Delete(FrozenMap, (int) fGODP->ownOID);
- }
-
- /**********************************************************************/
- /* InitiallyDone */
- /* The process (if any) is started and the object can now be invoked */
- /* by any other object. */
- /**********************************************************************/
- void InitiallyDone()
- {
- register CodePtr c;
- register GODP b;
- register LODataPtr g;
- register SSPtr theSSP;
-
- b = currentSSP->regs.b;
- g = (LODataPtr) currentSSP->regs.g;
- c = g->myCodePtr;
- if (g->tag.global) {
- b->tag.setUpDone = TRUE;
- b->tag.frozen = /* No */ FALSE;
- KMDTrace("FixMe", 2,
- "Initially done: Flags should be set properly!!!\n");
- UnblockInitially(b);
- /* The caller gets a reference to the newly created object */
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) b;
- } else {
- /* The caller gets a reference to the newly created object */
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) g;
- }
-
- /* Create process if necessary */
- if ( NonNULL(c->process.offset) ) {
- theSSP = NewProcess();
- StartProcessAtAddr(theSSP, b, (GODataPtr) g,
- (CodeAddr) addOffset(c, c->process.offset));
- }
- }
-
- /************************************************************************/
- /* Stack Check */
- /************************************************************************/
-
- /* Kernel Entry -- special due to content of stack */
- void StackCheck(fRequest)
- int fRequest;
- /* StackCheck is called when a process fails a stack check on entry to
- an operation. There can be two reasons:
- 1. The process has used up the current stack segment.
- If it has not used up all its stack quota then allocate it some
- more stack. fRequest indicates how much more stack the process
- wants.
- 2. The kernel wants to preempt the running process and forces this
- by setting the preemptFlag and by setting the current stacklimit
- of the currently executing process to something which will
- make it fail the stack check.
- */
- {
- KMDTrace("Stack", 5, "%s StackCheck(%d) at %s\n",
- PPPOID(currentSSP->processOID), fRequest, PPSSPlace(currentSSP));
- /* Check for the case of a process failing a stack check */
- if (addOffset(currentSSP->regs.sp, - fRequest) <
- (char *) currentSSP->splimit
- ) {
- /* the process has used up the current stack segment --
- allocate a new one (if it has not used up its quota) */
- MoreStack(preemptRunning(), fRequest);
- };
- /* A process preemption may also have been requested */
- if (NonNULL(currentSSP) && preemptFlag) {
- KMDTrace("Stack", 5,
- "StackCheck: self preempt on operation entry, process %s\n",
- PPPOID(currentSSP->processOID));
- preemptFlag = 0;
- splimit = currentSSP->splimit;
- }
- }
-
-
- /************************************************************************/
- /* Monitor operations */
- /************************************************************************/
-
- void MonitorEntry(fMonitorLock)
- MonitorLock *fMonitorLock;
- /* Enter a monitor. The parameter indicate the monitor lock and the queue of
- processes waiting to enter.
- */
- {
- KMDTrace("Monitor", 3,
- "%s MonitorEntry %s in %s\n",
- PPPOID(currentSSP->processOID),
- (fMonitorLock->isLocked) ? "locked -> blocking" : "open",
- PPSSPlace(currentSSP));
- if (fMonitorLock->isLocked) {
- /* Locked, so queue the process */
- currentSSP->status.rs = SSMonWait;
- KMDTrace("LineNumber", 4, "%s blocking on Monitor Entry in %s\n",
- PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
- insertQ(&fMonitorLock->waiting, preemptRunning());
- } else {
- /* Lock the monitor and continue */
- fMonitorLock->isLocked = TRUE;
- }
- }
-
- /************************************************************************/
-
- void MonitorExit(fMonitorLock)
- MonitorLock *fMonitorLock;
- {
- if (IsNULL(fMonitorLock->waiting)) {
- KMDTrace("Monitor", 3,
- "%s%sMonitorExit, unlocking monitor (0x%06x)\n",
- IsNULL(currentSSP) ? "" : PPPOID(currentSSP->processOID),
- IsNULL(currentSSP) ? "" : " ",
- fMonitorLock);
- fMonitorLock->isLocked = FALSE;
- } else {
- KMDTrace("Monitor", 3,
- "%s%sMonitorExit unblocking %s\n",
- IsNULL(currentSSP) ? "" : PPPOID(currentSSP->processOID),
- IsNULL(currentSSP) ? "" : " ",
- PPPOID(fMonitorLock->waiting->processOID)
- );
- schedule(removeQ(&fMonitorLock->waiting));
- };
- }
-
- /************************************************************************/
- /* Conditions */
- /************************************************************************/
-
- void ActivateCond(fMonitorLock, fCondODP)
- MonitorLock *fMonitorLock;
- CondODP fCondODP;
- {
- Set theSet;
-
- theSet = (Set) Map_Lookup(condMap, (int) fMonitorLock);
- if (IsNIL(theSet)) {
- KMDTrace("Monitor", 5, "First condition for object\n");
- theSet = Set_Create();
- Map_Insert(condMap, (int) fMonitorLock, (int) theSet);
- KMDTrace("Monitor", 4, "condMap insert <0x%06x, 0x%06x>\n",
- fMonitorLock, theSet);
- }
- Set_Insert(theSet, (int) fCondODP);
- fCondODP->theLock = fMonitorLock;
- KMDTrace("Monitor", 3,
- "ActivateCond: condtion 0x%06x tied to mon lock 0x%06x\n", fCondODP,
- fMonitorLock);
- }
-
- void DeActivateCond(fCondODP)
- CondODP fCondODP;
- {
- KMDTrace("Monitor", 3,
- "DeActivateCond: condtion 0x%06x, mon lock 0x%06x\n",
- fCondODP, fCondODP->theLock);
-
- /* The fCondODP is not removed from the Set of conditions tied
- to the monitor lock since that set is destroyed later
- anyway. */
- fCondODP->theLock = (MonitorLockPtr) NULL;
- fCondODP->waiting = (SSPtr) NULL;
- }
-
- /************************************************************************/
-
- void WaitCond(fMonitorLock, fCondODP)
- MonitorLock *fMonitorLock;
- CondODP fCondODP;
- {
- KMDTrace("Monitor", 3, "%s WaitCond in %s\n",
- PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
- if (IsNIL(fCondODP)) {
- KMDTrace("Monitor", 2, "Waiting on NIL not allowed; failure in %s\n",
- PPSSPlace(currentSSP));
- KMDTrace("Failure", 3, "Waiting on NIL not allowed; failure in %s\n",
- PPSSPlace(currentSSP));
- fail(preemptRunning());
- return;
- }
-
- if (IsNIL(fCondODP->theLock)) ActivateCond(fMonitorLock, fCondODP);
- if (fCondODP->theLock != fMonitorLock) {
- KMDTrace("Monitor", 2,
- "Illgal attempt to wait on condition outside its monitor in %s\n",
- PPSSPlace(currentSSP));
- fail(preemptRunning());
- return;
- }
- currentSSP->status.rs = SSCondWait;
- KMDTrace("LineNumber", 4, "%s waiting on condition in %s\n",
- PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
- insertQ(&fCondODP->waiting, preemptRunning());
- MonitorExit(fMonitorLock);
- }
-
- /************************************************************************/
-
- void SignalCond(fMonitorLock, fCondODP)
- MonitorLock *fMonitorLock;
- CondODP fCondODP;
- {
- register SSPtr awakened;
-
- KMDTrace("Monitor", 3,
- "%s SignalCond in %s\n",
- PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
-
- if (IsNIL(fCondODP)) {
- KMDTrace("Monitor", 2, "Signal on NIL not allowed; failure in %s\n",
- PPSSPlace(currentSSP));
- KMDTrace("Failure", 3, "Signal on NIL not allowed; failure in %s\n",
- PPSSPlace(currentSSP));
- fail(preemptRunning());
- }
-
- if (IsNIL(fCondODP->theLock)) ActivateCond(fMonitorLock, fCondODP);
- if (fCondODP->theLock != fMonitorLock) {
- KMDTrace("Monitor", 2,
- "Illgal attempt to signal condition outside its monitor\n");
- fail(preemptRunning());
- return;
- }
- if (NonNULL(awakened = removeQ(&fCondODP->waiting))) {
- /* Signal and wait sematics */
- KMDTrace("Monitor", 3,
- "Signalling process %s\n", PPPOID(awakened->processOID));
- currentSSP->status.rs = SSMonWait;
- KMDTrace("LineNumber", 4, "%s signalled %s, awaiting reentry in %s\n",
- PPPOID(currentSSP->processOID), PPPOID(awakened->processOID),
- PPSSPlace(currentSSP));
- insertQ(&fMonitorLock->waiting, preemptRunning());
- /* Let the signalled process run inside the monitor */
- schedule(awakened);
- }
- }
-
- /************************************************************************/
-
- void SignalAndExitCond(fMonitorLock, fCondODP)
- MonitorLock *fMonitorLock;
- CondODP fCondODP;
- {
- register SSPtr awakened;
-
- KMDTrace("Monitor", 3,
- "%s SignalCond in %s\n",
- PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
-
- if (IsNIL(fCondODP)) {
- KMDTrace("Monitor", 2, "Signal on NIL not allowed; failure in %s\n",
- PPSSPlace(currentSSP));
- KMDTrace("Failure", 3, "Signal on NIL not allowed; failure in %s\n",
- PPSSPlace(currentSSP));
- fail(preemptRunning());
- }
-
-
- if (IsNIL(fCondODP->theLock)) ActivateCond(fMonitorLock, fCondODP);
- if (fCondODP->theLock != fMonitorLock) {
- KMDTrace("Monitor", 2,
- "Illgal attempt to signal condition outside its monitor\n");
- fail(preemptRunning());
- return;
- }
- if (NonNULL(awakened = removeQ(&fCondODP->waiting))) {
- /* Brinch Hansen s continue sematics */
- KMDTrace("Monitor", 3, "Signalling process %s\n",
- PPPOID(awakened->processOID));
- schedule(awakened);
- } else {
- /* No process to continue, so exit monitor. */
- MonitorExit(fMonitorLock);
- }
- }
-
- void CondInit(fCondODP)
- CondODP fCondODP;
- {
- KMDTrace("Monitor", 3, "CondInit(0x%06x) in %s\n", fCondODP,
- PPSSPlace(currentSSP));
- fCondODP->tag.tag = CondTag;
- fCondODP->theLock = (MonitorLock *) EMNIL;
- fCondODP->waiting = (SSPtr) NULL;
- KMDTrace("FixMe", 5,
- "(Fix me: need to check that baptism of Cond is ok)\n");
- }
-
- /************************************************************************/
- /************************************************************************/
-
- /************************************************************************/
- /* Failure handling */
- /************************************************************************/
-
- /* Forward */
- void fail();
-
- /************************************************************************/
- /* UnwindStack */
- /************************************************************************/
-
- Boolean UnwindStack(fSSPtr, fHasInvokeQueue)
- register SSPtr fSSPtr;
- Boolean fHasInvokeQueue;
- /* Unwind the stack by going down one activation record
- Return false iff bottom reached */
- {
- /*
- * This relatively simple procedure merely involves restoring the
- * register from the DynamicLink. Unfortunately, we must also
- * restore the variables that have been allocated in registers.
- * This complicates matters since we must traverse the template
- * looking for registers that were saved in the AR.
- */
-
-
- register DynamicLinkPtr link;
- CodePtr cPtr;
- Offset unwindFromOffset, templateOffset;
- IPMapPtr templateMap;
- TemplatePtr tPtr;
- int i;
- SSAddr sAddr;
- TemplateEntryPtr t;
-
- link = mDynLinkPtrFromL(fSSPtr->regs.l);
- if (fHasInvokeQueue && !mStoppedAtEntry(fSSPtr)) {
- /* It may or may not be in the invoke queue */
- EnsureRemovedFromInvokeQueue(fSSPtr->regs.l);
- }
-
- if (IsNULL(link->l)) return FALSE;
-
- /* Find the template */
- if (IsNIL(fSSPtr->regs.g)) {
- ErrMsg("NIL object invoked; attempting recovery\n");
- ErrMsg("<< WARNING >> no register restoring for process %s\n",
- PPPOID(fSSPtr->processOID));
- KMDTrace("FixMe", 3,
- "<< WARNING >> no register restoring for process %s\n",
- PPPOID(fSSPtr->processOID));
- /* Problem: we cannot get ahold of the code ptr and must
- give up on register restoring */
- goto AFTERREGISTERRESTORE;
- }
-
- cPtr = fSSPtr->regs.g->myCodePtr;
- assert(NonNULL(cPtr));
- unwindFromOffset= (Offset) byteOffset(cPtr, *fSSPtr->regs.sp);
- assert(NonNULL(cPtr->templateMapOffset));
- templateMap = (IPMapPtr) addOffset(cPtr, cPtr->templateMapOffset);
- assert(NonNULL(templateMap));
- templateOffset = (Offset) IPMapLookup(templateMap, unwindFromOffset);
- assert(NonNULL(templateOffset));
- tPtr = (TemplatePtr) addOffset(cPtr, templateOffset);
- assert(NonNULL(tPtr));
-
- sAddr = (SSAddr) link;
- t = &tPtr->entry[0];
- for (i = 0; i < tPtr->B.numEntries; i++) {
-
- switch (t->TE.SS.Format) {
-
- case ShortStaticF: {
- KMDTrace("Failure", 5,
- "\tShortStaticF\t(%s) %s\tcount =%4d\n",
- BrandNames[(int)t->TE.SS.theBrand],
- t->TE.SS.paramInfo != 0 ? "isParam" : " ",
- t->TE.SS.count);
-
- if (t->TE.SS.paramInfo == IsNotParam)
- switch (t->TE.SS.theBrand) {
-
- case DataBrand: {
- sAddr = (SSAddr)
- addOffset(sAddr, -t->TE.SS.count);
- break;
- }
-
- case ODPBrand: {
- sAddr = (SSAddr)
- addOffset(sAddr, -sizeof(ODP)*t->TE.SS.count);
- break;
- }
-
- case AddrBrand:{
- assert(t->TE.SS.theBrand != AddrBrand);
- break;
- }
-
- case VectorBrand: {
- break;
- } /* case Vector Brand */
-
- case VariableBrand: {
- sAddr = (SSAddr)
- addOffset(sAddr, -sizeof(AVariable)*t->TE.SS.count);
- break;
- }
-
- case MonitorBrand: {
- sAddr = (SSAddr)
- addOffset(sAddr, -sizeof(MonitorLock));
- break;
- }
-
- case InvokeQueueBrand: {
- sAddr = (SSAddr) addOffset(sAddr, -sizeof(InvokeQueue));
- break;
- }
-
- default: {
- ErrMsg("Bad brand in UnwindStack\n");
- break;
- }
-
- } /* end switch */
-
- t = (TemplateEntryPtr) addOffset(t, sizeof(ShortStatic));
- break;
- }
-
- case RegisterF: {
- int k;
-
- KMDTrace("Failure", 5,
- "\tRegisterF\t(%s),\t%s, r%d, count %d\n",
- BrandNames[(int)t->TE.R.theBrand],
- t->TE.R.storedWhere == InRegister ? "InRegister"
- : "InSaveArea", t->TE.R.reg, t->TE.R.count);
- if (t->TE.R.storedWhere == InSaveArea) {
- for (k = t->TE.R.count - 1 ; k >= 0; k--) {
- /* Registers are stored low number, low addr */
- sAddr--; /* Since we are going backwards, do -- first */
- if (sAddr < fSSPtr->regs.sp) break;
-
- KMDTrace("Failure", 5,
- "Restoring register r%d, was 0x%02x, new value 0x%02x\n",
- t->TE.R.reg+k,
- mGetSavedReg(&fSSPtr->regs, t->TE.R.reg+k), *sAddr);
-
- mSetSavedReg(&fSSPtr->regs, t->TE.R.reg+k, *sAddr);
- }
- }
- t = (TemplateEntryPtr) addOffset(t, sizeof(t->TE.R));
- break;
- } /* case RegisterF */
-
- default: {
- KMDPrint("Bad format %d in UnwindStack\n", t->TE.SS.Format);
- abort();
- break;
- } /* default action */
-
- } /* switch on t->TE.SS.Format */
- } /* for (i = 0; ...) */
-
- AFTERREGISTERRESTORE:
- fSSPtr->regs.l = link->l;
- fSSPtr->regs.g = link->g;
- fSSPtr->regs.b = link->b;
- fSSPtr->regs.sp = (SSAddr) (link+1);
-
- PUSHIT(fSSPtr->regs.sp, link->ip);
-
- KMDTrace("Failure", 3, "Unwinding stack to %s\n", PPSSPlace(fSSPtr));
- return TRUE;
- }
-
- /**********************************************************************/
- /* BreakObject */
- /**********************************************************************/
-
- void BreakObject(fB, fG)
- GODP fB;
- GODataPtr fG;
- {
- KMDTrace("Failure", 3, "Breaking Object 0x%05x, 0x%05x\n", fB, fG);
- KMDTrace("FixMe", 3, "(Fix me: need to break object)\n");
- /* cannot do it */
- return;
- #ifdef BROKEN
- fG->tag.frozen = fG->tag.broken = TRUE;
- if (fG->tag.global) {
- fB->tag.broken = TRUE;
- fB->tag.frozen = TRUE;
- }
- #endif BROKEN
- }
-
- void unavail(fSSPtr, fGODP, fAbConPtr)
- register SSPtr fSSPtr;
- GODP fGODP;
- AbConPtr fAbConPtr;
- /* Called when an unavailable exception occurs */
- {
- GODataPtr g;
- CodeAddr ip;
- CodePtr cPtr;
- Offset unavailAtOffset, handlerOffset, mapOffset;
- IPMapPtr unavailMapPtr;
-
- g = fSSPtr->regs.g;
- if (g->tag.broken) goto failit;
-
- ip = (CodeAddr) *fSSPtr->regs.sp;
- cPtr = g->myCodePtr;
- unavailAtOffset = (Offset) byteOffset(cPtr, ip);
- KMDTrace("Failure", 3, "%s found %s unavailable at offset %d in %s\n",
- PPPOID(fSSPtr->processOID), PPGOID(fGODP->ownOID), unavailAtOffset,
- PPSSPlace(fSSPtr));
- mapOffset = cPtr->unavailableHandlerMapOffset;
- if (0 == mapOffset) goto failit;
- unavailMapPtr = (IPMapPtr) addOffset(cPtr, mapOffset);
- handlerOffset = IPMapLookup(unavailMapPtr, unavailAtOffset);
- if (0 == handlerOffset) goto failit;
-
- /* Found a handler */
- fSSPtr->resultBrand = VariableBrand;
- fSSPtr->regs.arg1 = (int) fGODP;
- fSSPtr->regs.arg2 = (int) fAbConPtr;
- * (fSSPtr->regs.sp) = (int) addOffset(cPtr, handlerOffset);
- KMDTrace("Failure", 3, "Calling unavailable handler in %s\n",
- PPSSPlace(fSSPtr));
- schedule(fSSPtr);
- return;
-
- failit:
- fail(fSSPtr);
- }
-
- /**********************************************************************/
- /* dofail */
- /**********************************************************************/
- void dofail(fSSPtr, fDoReturnAndFail)
- register SSPtr fSSPtr;
- Boolean fDoReturnAndFail;
- /* Called when a process failure has been detected.
- The process must not be the running process */
- {
- register CodePtr cPtr;
- Offset failedAtOffset, handlerOffset, mapOffset;
- Offset tOffset;
- IPMapPtr failMapPtr, map;
- TemplatePtr tPtr;
- register GODataPtr g;
- GODP b;
- Boolean keepGoing;
- CodeAddr ip;
-
- refail: /* recursion removed to avoid excessive stack usage */
- KMDTrace("Failure", 5,
- "Propogating failure b=0x%06x, g=0x%06x, l=0x%06x\n", fSSPtr->regs.b,
- fSSPtr->regs.g, fSSPtr->regs.l);
- keepGoing = fSSPtr->regs.l != (SSAddr) NULL;
- /* Invariant: keepGoing iff there are more ARs in this SS */
- while (keepGoing) {
- g = fSSPtr->regs.g;
- b = fSSPtr->regs.b;
- ip = (CodeAddr) *fSSPtr->regs.sp;
- if (IsNIL(g) || IsNIL(b) || g->tag.broken) {
- KMDTrace("Failure", 3,
- "Failure propagating past broken object (or invalid b/g)\n");
- keepGoing = UnwindStack(fSSPtr, FALSE);
- fDoReturnAndFail = FALSE; /* we have done (at least one) return */
- continue;
- }
- cPtr = g->myCodePtr;
- failedAtOffset = (Offset) byteOffset(cPtr, ip);
- registerSave[regs_sp] = (int) fSSPtr->regs.sp;
- registerSave[regs_l] = (int) fSSPtr->regs.l;
- registerSave[regs_g] = (int) fSSPtr->regs.g;
- registerSave[regs_b] = (int) fSSPtr->regs.b;
- registerSave[4] = (int) fSSPtr->regs.r4;
- registerSave[5] = (int) fSSPtr->regs.r5;
- registerSave[6] = (int) fSSPtr->regs.r6;
- registerSave[7] = (int) fSSPtr->regs.r7;
- registerSave[8] = (int) fSSPtr->regs.r8;
- registerSave[9] = (int) fSSPtr->regs.r9;
- KMDTrace("LineNumber", 3, "*Process %s failed\n",
- PPPOID(fSSPtr->processOID));
- KMDTrace("Failure", 3, "Process %s failed at offset %d in %s\n",
- PPPOID(fSSPtr->processOID), failedAtOffset, PPSSPlace(fSSPtr));
- map = (IPMapPtr) addOffset(cPtr, cPtr->templateMapOffset);
- tOffset = IPMapLookup(map, failedAtOffset);
- assert(0 != tOffset);
- tPtr = (TemplatePtr) addOffset(cPtr, tOffset);
-
- if (fDoReturnAndFail) {
- KMDTrace("Failure", 5, "Return and fail\n");
- keepGoing = UnwindStack(fSSPtr, tPtr->B.hasInvokeQueue);
- fDoReturnAndFail = FALSE; /* Real fail from now on */
- continue;
- }
-
- if (mStoppedAtEntry(fSSPtr)) {
- KMDTrace("Failure", 5, "Stopped at entry\n");
- keepGoing = UnwindStack(fSSPtr, tPtr->B.hasInvokeQueue);
- continue;
- }
-
- /* Attempt to find a failure handler for the object */
- mapOffset = cPtr->failureHandlerMapOffset;
- if (0 == mapOffset) {
- /* No handlers at all */
- keepGoing = UnwindStack(fSSPtr, tPtr->B.hasInvokeQueue);
- if (tPtr->B.exclusiveAccess) {
- BreakObject(b, g);
- }
- continue;
- }
-
- failMapPtr = (IPMapPtr) addOffset(cPtr, mapOffset);
- handlerOffset = IPMapLookup(failMapPtr, failedAtOffset);
- if (0 == handlerOffset) {
- /* No handler for this instruction */
- keepGoing = UnwindStack(fSSPtr, tPtr->B.hasInvokeQueue);
- if (tPtr->B.exclusiveAccess) {
- BreakObject(b, g);
- }
- continue;
- }
-
- /* Found a handler */
- * (fSSPtr->regs.sp) = (int) addOffset(cPtr, handlerOffset);
- KMDTrace("Failure", 3, "Calling failure handler in %s\n",
- PPSSPlace(fSSPtr));
- schedule(fSSPtr);
- return;
- }
-
- /* We have now unwound all the ARs in the current SS.
- Propogate failure across a stack segment break */
-
- if (NonNULL(fSSPtr->rPtr))
- switch (((GenericReqPtr)(fSSPtr->rPtr))->hdr.rTag) {
-
- case StackBreakRTag: {
- register SSPtr old;
- register StackBreakReqPtr req;
- register DynamicLinkPtr dynLink;
- SSAddr argumentLowAddr, resultLowAddr,
- returnAddr;
-
- req = (StackBreakReqPtr) fSSPtr->rPtr;
-
- old = req->oldSSPtr;
-
- dynLink = (DynamicLinkPtr)
- addOffset(old->regs.sp, sizeof(SSAddr));
- old->regs.b = dynLink->b;
- old->regs.g = dynLink->g;
- old->regs.l = dynLink->l;
- returnAddr = dynLink->ip;
-
- argumentLowAddr = (SSAddr) (dynLink+1);
-
- resultLowAddr = (SSAddr) addOffset(argumentLowAddr,
- req->argumentCount * sizeof(AVariable));
- if (req->resultCount > 0) {
- /* Copy in results */
- bcopy((char *)fSSPtr->regs.sp, (char *)resultLowAddr,
- req->resultCount*sizeof(AVariable));
- }
- fSSPtr->regs.sp = (SSAddr) resultLowAddr;
- PUSHIT(fSSPtr->regs.sp, returnAddr);
- fSSPtr->rPtr = (GenericPtr) NULL;
- old->invokePtr = (GenericPtr) NULL;
- free((char *)req);
- DiscardStackSegment(fSSPtr);
- fSSPtr = old;
- goto refail;
- }
-
- case IncomingIRTag: {
- InvokeReturn(fSSPtr, INVOKEFAILED);
- DiscardStackSegment(fSSPtr);
- return;
- }
- default: {
- break;
- }
- }
-
- KMDTrace("Failure", 3, "Cannot propagate failure\n");
- KMDTrace("Failure", 3, "halting process %s in %s\n",
- PPPOID(fSSPtr->processOID), PPSSPlace(fSSPtr));
- ErrMsg("Process %s broke and died at offset %d in %s\n",
- PPPOID(fSSPtr->processOID), failedAtOffset,
- PPSSPlace(fSSPtr));
- DiscardStackSegment(fSSPtr);
- }
-
- /**********************************************************************/
- /* fail */
- /**********************************************************************/
-
- void fail(fSSPtr)
- SSPtr fSSPtr;
- /* The process is declared to have failed and the failure is propogated */
- {
- dofail(fSSPtr, FALSE);
- }
-
- /**********************************************************************/
- /* Kernel Entry */
- void AssertFailed()
- /* Called when a process asserts FALSE */
- {
- KMDTrace("Failure", 2, "%s Assertion failed in %s\n",
- PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
- fail(preemptRunning());
- }
-
- /* Kernel Entry */
- void ReturnAndFail()
- {
- KMDTrace("Failure", 3, "%s ReturnAndFail in %s\n",
- PPPOID(currentSSP->processOID), PPSSPlace(currentSSP));
- dofail(preemptRunning(), TRUE);
- }
-
- /* Kernel Entry */
- void NotImplemented()
- {
- ErrMsg("NotImplemented; process %d\n", currentSSP->processOID);
- ErrMsg(" ***** NOT IMPLEMENTED, DIE DIE *****\n");
- fail(preemptRunning());
- }
-
- /* Kernel Entry */
- void InvokeAssumptionFailed(fG, fAbConPtr, fB)
- GODataPtr fG;
- AbConPtr fAbConPtr;
- GODP fB;
- {
- ErrMsg("Invoke Assumption failed g=0x%05x, b=0x%05x\n", fG, fB);
- if (PPValidAddr((SSAddr *) fB)) ErrMsg("B tag: %s\n", PPODTag(fB->tag));
- if (PPValidAddr((SSAddr *) fAbConPtr)) {
- ErrMsg("AbCon AT: %s\n", PPCOID(fAbConPtr->ATOID));
- ErrMsg("AbCon CT: %s\n", PPCOID(fAbConPtr->CodeOID));
- }
- preemptBrokenRunning();
- }
-
- /************************************************************************/
- /************************************************************************/
- /************************************************************************/
- /* OwnCallBack *
- /************************************************************************/
-
- /* Call back for ct or at loaded for ownName or ownType */
- HResult OwnCallBack(fReq, fOID)
- OwnReqPtr fReq;
- OID fOID;
- {
- register CodePtr ctype;
- CodeODP theCodeODP;
- KMDTrace("Own", 1,
- "Code object %s loaded, re-starting own%s\n",
- PPCOID(fOID), fReq->wanted == 1 ? "Name" : "Type");
-
- theCodeODP = (CodeODP) OTLookup(fReq->codeOID);
- assert(NonNULL(theCodeODP));
- ctype = (CodePtr) theCodeODP->dataPtr;
- switch (fReq->wanted) {
- case 1:
- /* name */
- fReq->waiting->resultBrand = ODPBrand;
- fReq->waiting->regs.arg1 = (int) addOffset(ctype, ctype->codeNameOffset);
- schedule(fReq->waiting);
- FreeRequest((GenericReqPtr) fReq);
- KMDTrace("Own", 5, "OwnName done.\n");
- break;
- case 2:
- theCodeODP = (CodeODP) OTLookup(ctype->ownAbstractType);
- if (IsNULL(theCodeODP) || IsNULL(theCodeODP->dataPtr)) {
- /* Load the abstract type */
- KMDTrace("Own", 1, "OwnType waiting for AT %s\n",
- PPCOID(ctype->ownAbstractType));
- fReq->ATOID = ctype->ownAbstractType;
- if (! LoadRequest(fReq->ATOID, (GenericReqPtr) fReq)) {
- return;
- } else {
- theCodeODP = (CodeODP) OTLookup(ctype->ownAbstractType);
- assert(NonNULL(theCodeODP) && NonNULL(theCodeODP->dataPtr));
- }
- }
- fReq->waiting->resultBrand = ODPBrand;
- fReq->waiting->regs.arg1 = (int) theCodeODP->dataPtr;
- schedule(fReq->waiting);
- FreeRequest((GenericReqPtr) fReq);
- KMDTrace("Own", 5, "OwnType done.\n");
- break;
- case 3:
- KMDTrace("Own", 5, "loaded of restricted AT %s\n", theCodeODP->ownOID);
- assert(NonNULL(theCodeODP) && NonNULL(theCodeODP->dataPtr));
- fReq->waiting->resultBrand = ODPBrand;
- fReq->waiting->regs.arg1 = (int) theCodeODP->dataPtr;
- schedule(fReq->waiting);
- FreeRequest((GenericReqPtr) fReq);
- KMDTrace("Own", 5, "OwnType done.\n");
- break;
-
- default:
- break;
- }
- }
-
- /* Kernel Entry */
- void OwnName(fAbConPtr)
- AbConPtr fAbConPtr;
- {
- register CodePtr ctype;
- OwnReqPtr req = NULL;
- ctype = fAbConPtr->cPtr;
- KMDTrace("Own", 5, "OwnName called for CTOID %s\n",
- PPCOID(fAbConPtr->CodeOID));
-
- if (IsNULL(ctype)) {
- /* no code pointer, load it */
- req = mNewRequest(Own);
- req->wanted = 1 /* ownName */;
- req->codeOID = fAbConPtr->CodeOID;
- req->hdr.callBack = OwnCallBack;
- if (! LoadRequest(req->codeOID, (GenericReqPtr) req)) {
- req->waiting = preemptRunning();
- req->waiting->status.rs = SSOwnWait;
- KMDTrace("Own", 3, "OwnName waiting for CT %s\n",
- PPCOID(req->codeOID));
- KMDTrace("LineNumber", 4,
- "%s delayed by Own Name code loading in %s\n",
- PPPOID(req->waiting->processOID), PPSSPlace(req->waiting));
- return;
- } else {
- ctype = fAbConPtr->cPtr;
- assert(NonNULL(ctype));
- }
- }
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) addOffset(ctype, ctype->codeNameOffset);
- KMDTrace("Own", 5, "OwnName done.\n");
- }
-
- /* Kernel Entry */
- void OwnType(fAbConPtr)
- AbConPtr fAbConPtr;
- {
- register CodePtr ctype;
- CodeODP theCodeODP;
- OwnReqPtr req = NULL;
-
- KMDTrace("Own", 5, "OwnType called for CTOID %s\n",
- PPCOID(fAbConPtr->CodeOID));
-
- if (NonNIL(fAbConPtr->restrictOID)) {
- /*
- * The type is restricted.
- */
- KMDTrace("Own", 5, "OwnType: ref restricted to %s\n",
- PPCOID(fAbConPtr->restrictOID));
-
- theCodeODP = (CodeODP) OTLookup(fAbConPtr->restrictOID);
- if (!theCodeODP->tag.setUpDone) {
- /* restrict AT not here -- load it */
-
- req = mNewRequest(Own);
- req->wanted = 3 /* ownType, resticted AT */;
- req->codeOID = fAbConPtr->restrictOID;
- req->hdr.callBack = OwnCallBack;
- if (! LoadRequest(req->codeOID, (GenericReqPtr) req)) {
- req->waiting = preemptRunning();
- req->waiting->status.rs = SSOwnWait;
- KMDTrace("LineNumber", 4,
- "%s delayed by Own Type loading in %s\n",
- PPPOID(req->waiting->processOID),
- PPSSPlace(req->waiting));
- KMDTrace("Own", 3, "OwnType waiting for rAT %s in %s\n",
- PPCOID(req->codeOID), PPSSPlace(req->waiting));
- return;
- }
- theCodeODP = (CodeODP) OTLookup(fAbConPtr->restrictOID);
- assert(NonNULL(theCodeODP) && NonNULL(theCodeODP->dataPtr));
- FreeRequest((GenericReqPtr) req);
- }
-
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) theCodeODP->dataPtr;
- return;
- }
-
- /*
- * The reference is unrestricted.
- */
- ctype = fAbConPtr->cPtr;
- if (ctype == 0) {
- /* no code pointer, load it */
- req = mNewRequest(Own);
- req->wanted = 2 /* ownType */;
- req->codeOID = fAbConPtr->CodeOID;
- req->hdr.callBack = OwnCallBack;
- if (! LoadRequest(req->codeOID, (GenericReqPtr) req)) {
- req->waiting = preemptRunning();
- req->waiting->status.rs = SSOwnWait;
- KMDTrace("LineNumber", 4,
- "%s delayed by Own Type code loading in %s\n",
- PPPOID(req->waiting->processOID), PPSSPlace(req->waiting));
- KMDTrace("Own", 3, "OwnType waiting for CT %s\n",
- PPCOID(req->codeOID));
- return;
- } else {
- ctype = fAbConPtr->cPtr;
- assert(NonNULL(ctype));
- }
- }
- theCodeODP = (CodeODP) OTLookup(ctype->ownAbstractType);
- if (IsNULL(theCodeODP) || IsNULL(theCodeODP->dataPtr)) {
- /* Load the abstract type */
- if (IsNULL(req)) {
- req = mNewRequest(Own);
- req->wanted = 2;
- req->codeOID = fAbConPtr->CodeOID;
- req->hdr.callBack = OwnCallBack;
- }
- req->ATOID = ctype->ownAbstractType;
- if (! LoadRequest(req->ATOID, (GenericReqPtr) req)) {
- req->waiting = preemptRunning();
- req->waiting->status.rs = SSOwnWait;
- KMDTrace("LineNumber", 4,
- "%s delayed by Own Type code loading in %s\n",
- PPPOID(req->waiting->processOID), PPSSPlace(req->waiting));
- KMDTrace("Own", 3, "OwnType waiting for AT %s\n",
- PPCOID(req->ATOID));
- return;
- } else {
- theCodeODP = (CodeODP) OTLookup(ctype->ownAbstractType);
- assert(NonNULL(theCodeODP) && NonNULL(theCodeODP->dataPtr));
- }
- }
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) theCodeODP->dataPtr;
- KMDTrace("Own", 5, "OwnType done.\n");
- if (NonNULL(req)) {
- FreeRequest((GenericReqPtr) req);
- }
- }
-
-
- #if defined(xkernel) && defined(NODISK)
- Semaphore *builtinsSem;
- int outstandingBuiltinLoadRequests = 0, doingBuiltins = 1;
-
- void doneLoadingBuiltins()
- {
- CodeODP stringODP;
- KMDTrace("Code", 3, "All required builtins loaded.\n");
- stringODP = (CodeODP) OTLookup(OIDOfBuiltin(B_INSTCT, STRINGINDEX));
- assert(NonNULL(stringODP));
- stringCodePtr = stringODP->dataPtr;
-
- timeODP = (CodeODP) OTLookup(OIDOfBuiltin(B_INSTCT, TIMEINDEX));
- assert(NonNULL(timeODP));
- timeCodePtr = timeODP->dataPtr;
- timeAbCon = OIDOIDOIDToAbCon(OIDOfBuiltin(B_INSTAT, TIMEINDEX),
- (OID) NIL,
- OIDOfBuiltin(B_INSTCT, TIMEINDEX));
- xkv(builtinsSem);
- }
-
- /************************************************************************/
- /************************************************************************/
-
- HResult doNothing()
- {
- }
-
- void BuiltinsInit()
- /* Define all the builtin types. */
- {
- int i;
- int delayed = 0, this;
- register CompilerLoadReqPtr req;
- req = mNewRequest(CompilerLoad);
- req->status = Loading;
- req->hdr.callBack = doNothing;
-
- builtinsSem = xcreatesemaphore(0);
- for (i = 0; requiredBuiltins[i].id; i++) {
- this = LoadRequest(requiredBuiltins[i].id, req);
- delayed = delayed || !this;
- }
- if (delayed) {
- xkp(builtinsSem);
- xkv(builtinsSem);
- }
- }
- #else
- /************************************************************************/
- /************************************************************************/
-
- #define BUILTINSDIRNAME "Builtins"
- extern DotoFilePtr FLReadInDoto();
- extern void FLTranslateAndActivateDoto();
-
- DotoFilePtr *builtinlist;
-
- void BuiltinsInit()
- /* Define all the builtin types. */
- {
- register Builtin *p;
- CodeODP theCodeODP, stringODP;
- char builtinDirName[200], fileName[400];
- char oldCurrentDirectory[200];
- DIR *dirp;
- struct direct *dp;
- int i;
- int listsize = 120*sizeof(DotoFilePtr);
- int nextFree = 0;
-
- CreateArray((int **)&builtinlist, listsize);
-
- /*
- * Change the current working directory, while in this function.
- */
- getwd(oldCurrentDirectory);
- (void) sprintf(builtinDirName, "%s%s", EMDIR, BUILTINSDIRNAME);
- KMDTrace("Code", 3, "Loading Builtins from %s\n", builtinDirName);
- chdir(builtinDirName);
- dirp = opendir(".");
- assert(NonNULL(dirp));
- for (dp=readdir(dirp); dp != NULL; dp = readdir(dirp)){
- if (strcmp(&dp->d_name[dp->d_namlen-2], ".o")) continue;
- (void) sprintf(fileName, "./%s", dp->d_name);
- if ((nextFree) * sizeof(DotoFilePtr) >= listsize) {
- EnsureArray((int **)&builtinlist, listsize, listsize*2);
- listsize += listsize;
- }
-
- builtinlist[nextFree] = FLReadInDoto(fileName);
- if (IsNULL(builtinlist[nextFree])) {
- ErrMsg("Could not read file %s\n", fileName);
- continue;
- }
- nextFree++;
- }
-
- chdir(oldCurrentDirectory);
-
- /* Check that the required builtins are there */
- for (p = & requiredBuiltins[0]; p->id != (OID) NULL; p++) {
- theCodeODP = (CodeODP) OTLookup(p->id);
- if (IsNULL(theCodeODP) || (theCodeODP->tag.tag != CodeODTag)) {
- ErrMsg("Missing required builtin %s, OID 0x%05x\n", p->name,
- p->id);
- assert(FALSE);
- }
- }
- /* Translate the code (also fires up processes) */
- for (i = 0; i < nextFree; i++) {
- FLTranslateAndActivateDoto(builtinlist[i]);
- }
- KMDTrace("Code", 3, "%d files containing builtins loaded.\n", nextFree);
- KMDTrace("Code", 3, "All required builtins present.\n");
- stringODP = (CodeODP) OTLookup(OIDOfBuiltin(B_INSTCT, STRINGINDEX));
- assert(NonNULL(stringODP));
- stringCodePtr = stringODP->dataPtr;
-
- timeODP = (CodeODP) OTLookup(OIDOfBuiltin(B_INSTCT, TIMEINDEX));
- assert(NonNULL(timeODP));
- timeCodePtr = timeODP->dataPtr;
- timeAbCon = OIDOIDOIDToAbCon(OIDOfBuiltin(B_INSTAT, TIMEINDEX),
- (OID) NIL,
- OIDOfBuiltin(B_INSTCT, TIMEINDEX));
- }
- #endif
- /************************************************************************/
- /************************************************************************/
- /*ARGSUSED*/
- void GetBuiltinsRootSet(fRootSet)
- Set fRootSet;
- {
- }
-
- /************************************************************************/
- /* NodeObjectInit */
- /************************************************************************/
-
- void NodeObjectInit()
- {
- nodeListCTOID = OIDOfBuiltin(B_INSTCT, NODELISTINDEX);
- nodeListCTODP = (CodeODP) OTLookup(nodeListCTOID);
- assert(NonNULL(nodeListCTODP));
- nodeListCodePtr = nodeListCTODP->dataPtr;
-
- nodeListElementCTOID = OIDOfBuiltin(B_INSTCT, NODELISTELEMENTINDEX);
- nodeListElementCTODP = (CodeODP) OTLookup(nodeListElementCTOID);
- assert(NonNULL(nodeListElementCTODP));
- nodeListElementCodePtr = nodeListElementCTODP->dataPtr;
-
- nodeListElementATOID = OIDOfBuiltin(B_INSTAT, NODELISTELEMENTINDEX);
- nodeListElementATODP = (CodeODP) OTLookup(nodeListElementATOID);
-
- nodeListElementAbCon = OIDOIDOIDToAbCon(nodeListElementATODP->ownOID,
- (OID) EMNIL, nodeListElementCTODP->ownOID);
-
- thisNodeObjectOID = mMakeNodeOIDFromLoc(thisNodeLocation);
- KMDTrace("Node", 5, "Initializing own node object, OID 0x%05x\n",
- thisNodeObjectOID);
- thisNodeCTODP = (CodeODP) OTLookup(OIDOfBuiltin(B_INSTCT, NODEINDEX));
- assert(NonNULL(thisNodeCTODP));
- thisNodeCodePtr = thisNodeCTODP->dataPtr;
- thisNodeODP = (GODP) KernelCheatingCreate(thisNodeObjectOID,
- thisNodeCTODP->ownOID, 0, (AVariable *) NULL);
- nodeAbCon = OIDOIDOIDToAbCon(OIDOfBuiltin(B_INSTAT, NODEINDEX),
- (OID) NIL,
- OIDOfBuiltin(B_INSTCT, NODEINDEX));
- OTInsert((ODP) thisNodeODP);
- }
-
- /************************************************************************/
- /************************************************************************/
- /*ARGSUSED*/
- void GetProcessRootSet(fRootSet)
- Set fRootSet;
- {
- /*
- * Traverse processes data structures and find the processes that are to
- * go into the root set.
- */
- }
-
- /************************************************************************/
- /************************************************************************/
-
- /************************************************************************/
- /* Snapshot to shut down kernel */
- /************************************************************************/
-
- /* Snapshot */
- void Shutdown()
- {
- time_t theTime = time((time_t *) 0);
- KMDPrint("Emerald node #%d will shut down\n", GetLNN());
-
- ErrMsg("Request for voluntary shutdown arrived at %s\n", ctime(&theTime));
- #ifdef xsimul
- ErrMsg("Committing suicide by sending interrupt signal to self.\n");
- (void) kill(getpid(), SIGINT);
- #else
- ErrMsg("Committing suicide by calling exit().\n");
- exit(1);
- #endif
- }
-
- /************************************************************************/
- /* Snapshots for dumping processes */
- /************************************************************************/
-
- /* snapshot */
- void ps()
- {
- time_t theTime = time((time_t *) 0);
- register SSPtr p;
- register DQueuePtr q;
- Set seen;
-
- seen = Set_Create();
-
- KMDPrint(
- "Ready processes on node %d, %s\nRunnable: %4d\t Load avg %8.4f\n\n",
- GetLNN(), ctime(&theTime), cEmRunnable, MachineLoadAvg() +
- (cEmRunnable > 0 ? cEmRunnable-1 : 0));
-
- KMDPrint("Process State In object\n");
- if (NonNULL(currentSSP)) {
- Set_Insert(seen, (int) currentSSP);
- KMDPrint("%-9.9s %-13.13s %s\n", PPPOID(currentSSP->processOID),
- "Running", PPSSPlace(currentSSP));
- }
-
- p = readyQ;
- if (NonNULL(p)) do {
- p = p->readyQLink;
- Set_Insert(seen, (int) p);
- KMDPrint("%-9.9s %-13.13s %s\n", PPPOID(p->processOID),
- "Ready", PPSSPlace(p));
- } while (p != readyQ);
-
- p = stoppedQ;
- if (NonNULL(p)) do {
- p = p->readyQLink;
- Set_Insert(seen, (int) p);
- KMDPrint("%-9.9s %-13.13s STOPPED in %s\n",
- PPPOID(p->processOID), PPSSRunStatus((int)p->status.rs),
- PPSSPlace(p));
- } while (p != stoppedQ);
-
- for (q = hasRunDQ.next; q != &hasRunDQ; q = q->next) {
- p = mDQPtrToSSP(q);
- if ((Set_Lookup(seen, (int) p) != NIL) || p->status.rs== SSNotInUse) {
- continue;
- }
- Set_Insert(seen, (int) p);
- KMDPrint("%-9.9s %-13.13s %s%s\n", PPPOID(p->processOID),
- PPSSRunStatus((int)p->status.rs),
- (p->tag.stopped ? "STOPPED in " : ""), PPSSPlace(p));
- }
-
- for (q = dormantDQ.next; q != &dormantDQ; q = q->next) {
- p = mDQPtrToSSP(q);
- if ((Set_Lookup(seen, (int) p) != NIL) || p->status.rs== SSNotInUse) {
- continue;
- }
- Set_Insert(seen, (int) p);
- KMDPrint("%-9.9s %-13.13s %s%s\n", PPPOID(p->processOID),
- PPSSRunStatus((int)p->status.rs),
- (p->tag.stopped ? "STOPPED in " : ""), PPSSPlace(p));
- }
-
- Set_Destroy(seen);
- }
-
- /************************************************************************/
- /* EmInit */
- /************************************************************************/
-
- void EmInit()
- /* Em kernel initialization */
- {
- printf(" Emerald kernel code : Copyright 1986 Eric Jul\n");
-
- /* In order to make file loading and the ensuing dynamic linking
- faster, the following puts the address of a number of symbols
- into the KMD translation table thus avoiding a nlist operation
- for each.
- */
- #include "ementryset.c"
-
- UtilsInit();
-
- KMDSetVar(splimit);
- KMDSetVar(preemptFlag);
- KMDSetVar(currentSSP);
- KMDSetVar(kernelsp);
- KMDSetVar(lastJumpFrom);
- KMDSetVar(emTracing);
-
- KMDSetProcedure(Node_getTimeOfDay);
- KMDSetProcedure(Node_getLNN);
- KMDSetProcedure(Node_getName);
- KMDSetProcedure(Node_system);
- KMDSetProcedure(Node_getLoadAverage);
- KMDSetProcedure(Node_setNodeEventHandler);
- KMDSetProcedure(Node_removeNodeEventHandler);
- KMDSetProcedure(Node_getActiveNodes);
- KMDSetProcedure(Node_getAllNodes);
- KMDSetProcedure(Node_getNodeInformation);
-
- KMDSetProcedure(IOPutString);
- KMDSetProcedure(IOPutInt);
- KMDSetProcedure(IOPutReal);
-
- KMDSetTrace(Failure);
- KMDSetTrace(Monitor);
- KMDSetTrace(FixMe);
- KMDSetTrace(Create);
- KMDSetTrace(StackSegment);
- KMDSetTrace(Stack);
- KMDSetTrace(Node);
- KMDSetTrace(Own);
- KMDSetTrace(Portability);
- KMDSetTrace(Vector);
-
- #define printSizeof(xx) DebugMsg(8, "%-20.20s %5d\n", "xx", sizeof (xx));
-
- printSizeof(ODTag);
- printSizeof(TemplateEntry);
- printSizeof(Template);
- printSizeof(SS);
- printSizeof(GOD);
- printSizeof(CondOD)
- printSizeof(SSOD);
- printSizeof(LOData);
- printSizeof(GOData);
- printSizeof(Code);
- printSizeof(Vector);
- printSizeof(String);
- printSizeof(MonitorLock);
-
- /* Set standard tag values; Note, reset all fields, then set
- only the relevant ones that are TRUE.
- For further information, see UtilsInit and PPODTag() in utils.c
- */
-
- bzero((char *) &stdNULLTag, sizeof(stdNULLTag));
-
- stdGODTag = stdNULLTag;
- stdGODTag.tag = GODTag;
- stdGODTag.global = /* Global */ 1;
- stdGODTag.isResident = /* Yes */ 1;
- stdGODTag.frozen = /* Yes */ 1;
- stdGODTag.otherstuff = OBSCUREVALUE;
-
- stdLODataTag = stdNULLTag;
- stdLODataTag.tag = LOTag;
- stdLODataTag.isResident = /* Yes */ 1;
- stdLODataTag.otherstuff = OBSCUREVALUE;
-
-
- stdProcessODTag = stdGODTag;
- stdProcessODTag.tag = ProcessODTag;
-
- stdGODataTag = stdNULLTag;
- stdGODataTag.tag = GODataTag;
- stdGODataTag.global = /* Global */ 1;
- stdGODataTag.frozen = /* Yes */ 1;
- stdGODataTag.otherstuff = OBSCUREVALUE;
-
- stdSSODTag = stdNULLTag;
- stdSSODTag.tag = SSODTag;
- stdSSODTag.isResident = /* Yes */ 1;
- stdSSODTag.otherstuff = OBSCUREVALUE;
-
-
- stdSSTag = stdNULLTag;
- stdSSTag.tag = SSTag;
- stdSSTag.global = /* Global */ 1;
- stdSSTag.otherstuff = OBSCUREVALUE;
-
- stdCodeTag = stdNULLTag;
- stdCodeTag.tag = CodeTag;
- stdCodeTag.global = /* Global */ 0;
- stdCodeTag.replicated = /* Yes */ 1;
- stdCodeTag.isResident = /* Yes */ 1;
- stdCodeTag.otherstuff = OBSCUREVALUE;
-
- stdCodeODTag = stdNULLTag;
- stdCodeODTag.tag = CodeODTag;
- stdCodeODTag.global = /* Global */ 0;
- stdCodeODTag.replicated = /* Yes */ 1;
- stdCodeODTag.isResident = /* Yes */ 1;
- stdCodeODTag.otherstuff = OBSCUREVALUE;
-
- stdAbConTag = stdNULLTag;
- stdAbConTag.tag = AbConTag;
- stdAbConTag.otherstuff = OBSCUREVALUE;
-
- stdDotoODTag = stdNULLTag;
- stdDotoODTag.tag = DotoTag;
- stdDotoODTag.replicated = /* Yes */ 1;
- stdDotoODTag.isResident = /* Yes */ 1;
- stdDotoODTag.otherstuff = OBSCUREVALUE;
-
- /* Initialize Stack segment administration and ready queue */
- readyQ = (SSPtr) NULL;
- currentSSP = (SSPtr) NULL;
- cEmRunnable = 0; /* cEmRunnable = card(readyQ)+card(currentSSP) */
- hasRunDQ.next = &hasRunDQ;
- hasRunDQ.prev = &hasRunDQ;
- dormantDQ.next = &dormantDQ;
- dormantDQ.prev = &dormantDQ;
-
- condMap = Map_CreateSized(INITIALCONDMAPSIZE);
- KMDSetSnap(DumpCondMap);
-
- /* Initialize own location */
- thisNodeLocation = mMakeLocation(GetLNN(), 1);
-
-
- KMDSetSnap(Shutdown);
-
- KMDSetSnap(ps);
- KMDSetSnap(StopProcess);
- KMDSetSnap(StartProcess);
-
- /* Initialize everything else */
-
- RequestInit();
- OIDInit();
- LMInit();
- ItemInit();
- TimeSlicerInit();
- InvokeInit();
- LocateInit();
- MoveInit();
- ConformInit();
- IOInit();
- UnixStreamInit();
- MeasureInit();
- BuiltinsInit();
- StreamInit();
- NodeObjectInit();
- TimingInit();
- NodeInit();
- CPInit(); /* MUST COME AFTER OIDInit() */
- #ifdef INCLUDE_X_WINDOWS
- XInit();
- #endif
- #ifdef INCLUDE_MLP
- MLPInit();
- #endif
-
- #if defined(xkernel) && 0
- /* Hack to init kmdtraces */
- KMDStartTrace("Code", 5, -1, TRUE);
- KMDStartTrace("ProcessSwitch", 5, -1, TRUE);
- KMDStartTrace("OT", 5, -1, TRUE);
- KMDStartTrace("Translate", 5, -1, TRUE);
- KMDStartTrace("LM", 5, -1, TRUE);
- {
- extern int traceprocessswitch;
- extern int tracetcpp;
- traceprocessswitch=5;
- tracetcpp = 5;
- }
- #endif
- printf("\n");
- #ifdef xkernel
- startAnEmeraldScheduler();
- #else
- /* Exit the kernel -- this will start executing the process. */
- /* Capture kernel sp; used for all C-routines of the kernel.
- Let them execute on this stack. */
- asm(" movl sp,_kernelsp ");
- asm(" jmp kernel_exit ");
- #endif xkernel
- }
-
- /* Snapshot */
- void LineNumber()
- {
- KMDTrace("LineNumber", 3, "%s in %s", PPPOID(currentSSP->processOID),
- PPGetPos((unsigned int) registerSave[regs_g],
- * (unsigned int *) registerSave[regs_sp]));
- }
-
- /************************************************************************/
-
- /**********************************************************************/
- /* DumpCondMap */
- /**********************************************************************/
-
- /* Snapshot */
- void DumpCondMap()
- {
- Set theSet;
- MonitorLock *theLock;
- CondODP aCondODP;
- ODP theODP;
- time_t theTime = time((time_t *) 0);
-
- KMDPrint("DumpCondMap for node #%d at %s\n", GetLNN(), ctime(&theTime));
-
- if (Map_Count(condMap) == 0) {
- KMDPrint("No Conditions defined at this time.\n");
- return;
- }
- KMDPrint("MonitorLock\n");
-
- Map_For(condMap, theLock, theSet);
-
- /* HACK: The ODP for the object is found in a not very acceptable
- * way, search for comments regarding MONITOROFFSETWITHINOBJECT.
- * (Look in ../h/*.h too.)
- */
- theODP = mODPFromMonLockPtr(theLock);
- assert(NonNULL(theODP) && (theODP->G.tag.otherstuff == OBSCUREVALUE));
- assert((theODP->G.tag.tag==GODataTag) || (theODP->G.tag.tag==LOTag));
- KMDPrint("Monintor Lock 0x%06x in object 0x%06x, one of %s\n",
- theLock, theODP, PPCodePtr(theODP->L.myCodePtr));
- Set_For(theSet, aCondODP);
- KMDPrint(" Condition @ 0x%06x, OID: %s\n", aCondODP,
- PPGOID(aCondODP->ownOID));
- if (NonNULL(aCondODP->waiting)){
- KMDPrint(" ->\tAt least one process waiting, last is in %s\n",
- PPSSPlace(aCondODP->waiting));
- } else KMDPrint(" ->\tNo processes waiting in condition\n");
- Set_Next
- Map_Next
- }
-
-
- /* Copyright 1986 Eric Jul */
-