home *** CD-ROM | disk | FTP | other *** search
-
- /* 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. */
-
-
- /* This file contains the implementation of the Emerald kernel
- Node operations.
- */
-
- extern int cEmRunnable;
- extern float MachineLoadAvg();
-
- #include <sys/time.h>
- #include "Kernel/h/system.h"
- #include "Kernel/h/assert.h"
- #include "Kernel/h/emTypes.h"
- #include "Kernel/h/hotsTypes.h"
- #include "Kernel/h/emeraldTypes.h"
- #include "Kernel/h/timeops.h"
- #include "Kernel/h/timerTypes.h"
- #include "Kernel/h/consts.h"
- #include "Kernel/h/kmdTypes.h"
- #include "Kernel/h/builtins.h"
- #include "Kernel/h/emkDefs.h"
- #include "Kernel/h/map.h"
- #include "Kernel/h/errMsgs.h"
- #include "Kernel/h/utils.h"
- #include "Kernel/h/macros.h"
- #ifdef xkernel
- #include "userprocess.h"
- #endif xkernel
-
- #define NSStatus(x) x == Dead ? "Dead" : x == Alive ? "Alive" : \
- x == Deaf ? "Deaf" : x == Dumb ? "Dumb" : x == Booting ? "Booting" : \
- "Unknown status"
-
- extern ODTag stdLODataTag;
- extern GODP CreateGODEntry();
- extern OID thisNodeObjectOID;
- extern CodeODP thisNodeCTODP;
- extern CodePtr thisNodeCodePtr;
-
- extern OID nodeListCTOID, nodeListElementCTOID,
- nodeListElementATOID;
- extern CodeODP nodeListCTODP, nodeListElementCTODP,
- nodeListElementATODP;
- extern CodePtr nodeListCodePtr, nodeListElementCodePtr;
- extern AbConPtr nodeListElementAbCon, nodeAbCon,
- OIDOIDOIDToAbCon();
-
-
- extern CodeODP timeODP;
- extern AbConPtr timeAbCon;
-
- extern void schedule(), fail(), StartProcessAtAddr();
- extern SSPtr preemptRunning(), NewProcess();
-
- extern CodePtr timeCodePtr;
-
- extern GODP AllocateWithOID();
-
- extern ODP OTLookup();
- extern void OTInsert();
-
- extern void GlobalCreateVector();
-
- /**********************************************************************/
- /* Node listners are objects that want to be invoked when a node state*/
- /* change happens. */
- /**********************************************************************/
-
- Map nodeListners; /* ODP -> AbCon */
-
- /************************************************************************/
- Boolean IsNode(fODP)
- ODP fODP;
- /* Given an ODP, tell whether or not it is a reference to a node object */
- {
- /* Node objects have OID: LNN << 24 */
- if (fODP == (ODP) EMNIL) return FALSE;
- if (fODP->G.tag.tag != GODTag || !fODP->G.tag.global) return FALSE;
- if (fODP->G.ownOID == (OID) NULL) return FALSE;
- return ((fODP->G.ownOID & 0xFFFFFF) == 0) &&
- (((unsigned int) fODP->G.ownOID >> 24 & 0xFF) <= MAXNODENUMBER);
- }
-
- /**********************************************************************/
- /* GetNodeODPFromLNN */
- /**********************************************************************/
-
- GODP GetNodeODPFromLNN(fLNN)
- int fLNN;
- {
- OID nodeOID;
- GODP nodeGODP;
-
- nodeOID = mMakeNodeOIDFromLNN(fLNN);
- nodeGODP = (GODP) OTLookup(nodeOID);
- if (NonNULL(nodeGODP)) return nodeGODP;
- /* It is not in the OT, so create one */
- nodeGODP = (GODP) CreateGODEntry(nodeOID, thisNodeCodePtr->ownOID);
- nodeGODP->tag.isFixed = TRUE;
- nodeGODP->tag.isResident= (fLNN == GetLNN());
- nodeGODP->tag.setUpDone = TRUE;
- nodeGODP->tag.inTransit = FALSE;
- nodeGODP->tag.frozen = !nodeGODP->tag.isResident;
- nodeGODP->ownLoc = mMakeLocation(fLNN, 1);
- OTInsert((ODP) nodeGODP);
- return nodeGODP;
- }
-
- GODP GetNodeODPFromLocation(fLoc)
- EmLocation fLoc;
- {
- OID nodeOID;
- GODP nodeGODP;
-
- nodeOID = mMakeNodeOIDFromLoc(fLoc);
- nodeGODP = (GODP) OTLookup(nodeOID);
- if (NonNULL(nodeGODP)) return nodeGODP;
- /* It is not in the OT, so create one */
- nodeGODP = (GODP) CreateGODEntry(nodeOID, thisNodeCodePtr->ownOID);
- nodeGODP->tag.isResident= (mGetLocNodeNum(fLoc) == GetLNN());
- nodeGODP->tag.setUpDone = TRUE;
- nodeGODP->tag.inTransit = FALSE;
- nodeGODP->tag.frozen = !nodeGODP->tag.isResident;
- nodeGODP->tag.isFixed = TRUE;
- nodeGODP->ownLoc = mMakeLocation(mGetLocNodeNum(fLoc), 1);
- OTInsert((ODP) nodeGODP);
- return nodeGODP;
- }
-
- /************************************************************************/
-
- RODataPtr MakeNodeInfoFromHOTSRec(fEntry)
- HOTSRecord *fEntry;
- {
- GODP entryGODP;
- EmNodeListElementPtr elem;
-
- entryGODP = AllocateWithOID(nodeListElementCodePtr,
- (OID) NULL, nodeListElementCodePtr->instanceSize);
- entryGODP->tag.frozen = FALSE;
- entryGODP->tag.setUpDone = TRUE;
-
- elem = (EmNodeListElementPtr) entryGODP;
- elem->up = (fEntry->NodeStat == Alive);
- elem->LNN = fEntry->LNN;
- elem->theNode = GetNodeODPFromLNN(elem->LNN);
- elem->incarnationTime = (EmTimePtr)
- AllocateWithOID(timeCodePtr, (OID) NULL, timeCodePtr->instanceSize);
- elem->incarnationTime->ownOID = (OID) NULL;
- elem->incarnationTime->t.tv_sec = fEntry->NodeIncarnationId;
- elem->incarnationTime->t.tv_usec = 0;
- elem->tag.frozen = FALSE;
- elem->tag.setUpDone = TRUE;
- return (RODataPtr) entryGODP;
- }
-
- /* call_k */
- void Node_getActiveNodes()
- {
- register int i;
- int n;
- register struct HOTStr *np;
- time_t tmp;
- char incarnationTimeString[20];
- GODP theListGODP;
- RODataPtr entryRODP;
- EmNodeListPtr list;
- Map activeMap;
-
- activeMap = Map_Create();
- KMDTrace("Node", 3, "Node_getActiveNodes:\n");
- /* Traverse HOTS table and create list of entries */
- n = 0;
- for (i=0; i < HOTSIZE; i++) {
- for(np = HOTSTable[i]; np != NULL; np = np -> next) {
- if (np->ThisEntry.NodeStat != Alive) continue;
- tmp = np->ThisEntry.LastMsgTs;
- sprintf(incarnationTimeString, "%.15s",
- 4+ctime(&np->ThisEntry.NodeIncarnationId));
- KMDTrace("Node", 3, "%4d %.15s %-11.11s %-8.8s %-15.15s\n",
- np->ThisEntry.LNN,
- incarnationTimeString,
- mGetHostName(&(np->ThisEntry.EtherAddr)),
- NSStatus(np->ThisEntry.NodeStat),
- 4+ctime(&tmp));
-
- /* Create individual entry */
- entryRODP = MakeNodeInfoFromHOTSRec(&np->ThisEntry);
- Map_Insert(activeMap, n, (int) entryRODP);
- n++;
- }
- }
-
- KMDTrace("Node", 3, "Found %d active nodes.\n", n);
- GlobalCreateVector(nodeListCodePtr, (unsigned long) (n*sizeof(AVariable)),
- (unsigned long) (n-1));
- theListGODP = (GODP) currentSSP->regs.arg1;
- list = (EmNodeListPtr) theListGODP->dataPtr;
- /* Build from map */
- Map_For(activeMap, n, entryRODP)
- list->data[n].myAddr = (DataAddr) entryRODP;
- list->data[n].myAbConPtr = nodeListElementAbCon;
- Map_Next
- Map_Destroy(activeMap);
-
- currentSSP->resultBrand = VariableBrand;
- currentSSP->regs.arg1 = (int) theListGODP;
- currentSSP->regs.arg2 = (int) OIDOIDOIDToAbCon(
- OIDOfBuiltin(B_INSTAT, NODELISTINDEX),
- (OID) EMNIL,
- OIDOfBuiltin(B_INSTCT, NODELISTINDEX));
- }
-
- /* call_k */
- void Node_getAllNodes()
- {
- register int i, n;
- register struct HOTStr *np;
- time_t tmp;
- char incarnationTimeString[20];
- GODP theListGODP;
- RODataPtr entryRODP;
- EmNodeListPtr list;
-
- GlobalCreateVector(nodeListCodePtr,
- (unsigned long) (NoHOTSEntries*sizeof(AVariable)),
- (unsigned long) (NoHOTSEntries-1));
- theListGODP = (GODP) currentSSP->regs.arg1;
- list = (EmNodeListPtr) theListGODP->dataPtr;
-
- KMDTrace("Node", 3, "Node_getAllNodes:\n");
- /* Traverse HOTS table and create list of entries */
- n = 0;
- for (i=0; i < HOTSIZE; i++) {
- for(np = HOTSTable[i]; np != NULL; np = np -> next) {
- tmp = np->ThisEntry.LastMsgTs;
- sprintf(incarnationTimeString, "%.15s",
- 4+ctime(&np->ThisEntry.NodeIncarnationId));
- KMDTrace("Node", 3, "%4d %.15s %-11.11s %-8.8s %-15.15s\n",
- np->ThisEntry.LNN,
- incarnationTimeString,
- mGetHostName(&(np->ThisEntry.EtherAddr)),
- NSStatus(np->ThisEntry.NodeStat),
- 4+ctime(&tmp));
-
- /* Create individual entry */
- entryRODP = MakeNodeInfoFromHOTSRec(&np->ThisEntry);
- list->data[n].myAddr = (DataAddr) entryRODP;
- list->data[n].myAbConPtr = nodeListElementAbCon;
- n++;
- }
- }
- currentSSP->resultBrand = VariableBrand;
- currentSSP->regs.arg1 = (int) theListGODP;
- currentSSP->regs.arg2 = (int) OIDOIDOIDToAbCon(
- OIDOfBuiltin(B_INSTAT, NODELISTINDEX),
- (OID) EMNIL,
- OIDOfBuiltin(B_INSTCT, NODELISTINDEX));
- }
-
- /* call_k */
- void Node_getNodeInformation(fNode)
- GODP fNode;
- {
- int nodeLNN;
- HOTSRecord *entryPtr;
-
- if (IsNULL(fNode) ||
- (fNode->tag.tag != GODTag) ||
- (fNode->ownOID == (OID) NULL) ||
- ((fNode->ownOID & 0xFFFFFF) != 0) ||
- ((nodeLNN = ((unsigned int) fNode->ownOID >> 24) & 0xFF) == 0) ||
- (nodeLNN > MAXNODENUMBER))
- {
- fail(preemptRunning());
- return;
- }
-
- if (!mSUCCESS(HOTSSearchPtr(nodeLNN, &entryPtr))) {
- /* Could not find it */
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) EMNIL;
- return;
- }
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) MakeNodeInfoFromHOTSRec(entryPtr);
- }
-
- /************************************************************************/
-
- /* call_c */
- float Node_getLoadAverage()
- /* return current load average; since we do not keep track of the
- load average, return the UNIX load average plus the
- instantaneous Emerald process load (minus the process itself).
- */
- {
- float x = ((float) (cEmRunnable-1) + (float) MachineLoadAvg()) ;
- return x;
- }
-
- /* call_c */
- EmTimePtr Node_getTimeOfDay()
- {
- #ifndef xkernel
- struct timezone theZone;
- #endif xkernel
- register EmTimePtr theTime;
-
- theTime = (EmTimePtr) emalloc(sizeof(EmTime));
- theTime->tag = stdLODataTag;
- theTime->myCodePtr = timeCodePtr;
- theTime->ownOID = (OID) NULL;
- #ifndef xkernel
- gettimeofday(&theTime->t, &theZone);
- #else xkernel
- xgettime(&theTime->t);
- #endif xkernel
- return (theTime);
- }
-
- /**********************************************************************/
-
- /* call_c */
- int Node_getLNN()
- /* Just return our node LNN */
- {
- return(GetLNN());
- }
-
- /**********************************************************************/
-
- /* call_k */
- int Node_getName()
- /* return a string with our name in it */
- {
- register StringPtr x;
- char thename[128], *p;
- int sizeInBytes;
- extern CodePtr stringCodePtr;
- gethostname(thename, 128);
- for (p = thename; *p && *p != '.'; p++) ;
- *p = '\0';
- sizeInBytes = p - thename;
- x = (StringPtr) emalloc((int) sizeInBytes + String_data);
- x->tag = stdLODataTag;
- x->tag.replicated = TRUE;
- x->myCodePtr = stringCodePtr;
- x->ownOID = (OID) NULL;
- x->sizeInBytes = sizeInBytes;
- strncpy((char *)&x->data[0], thename, sizeInBytes);
- KMDTrace("Create", 3, "Create String 0x%05x, %d chars, code %s\n",
- x, sizeInBytes, PPCodePtr(stringCodePtr));
- currentSSP->resultBrand = ODPBrand;
- currentSSP->regs.arg1 = (int) x;
- }
-
- /**********************************************************************/
-
- /* call_k */
- /*ARGSUSED*/
- void Node_system(str, wantItsStdin, wantItsStdout)
- /*
- * Do a system of the given string, returning its stdin (as an OutStream)
- * and stdout (as an Instream)
- */
- StringPtr str;
- int wantItsStdin, wantItsStdout;
- {
- #ifdef undef
- if (IsNIL(str)) return;
- if (str->sizeInBytes == 0) return;
-
- do some pipes
- if ((pid = vfork()) == 0) {
- do some dup2s and closes
- execl("/bin/sh", "sh", "-c", s, 0);
- _exit(127);
- } else {
- do some dup2s and closes
- }
- create the streams
-
- The streams will be placed on the stack in the result spots (2 of
- them).
- #endif
- }
-
- /**********************************************************************/
-
- /* Handler routine passed to MMSetTimer */
- HResult TimePassed(fSSPtr)
- SSPtr fSSPtr;
- /* A timer has expired and the process waiting for it should be restarted */
- {
- schedule(fSSPtr);
- }
-
- /**********************************************************************/
- /* Delay */
- /**********************************************************************/
- /* Kernel call */
- void Delay(fDelayTime)
- register EmTimePtr fDelayTime;
- /* delay the process for the given amount of time */
- {
- SSPtr theProcess;
- if (IsNIL(fDelayTime)) {
- fail(preemptRunning());
- return;
- }
-
- theProcess = preemptRunning();
- theProcess->status.rs = SSTimerWait;
- KMDTrace("LineNumber", 4,
- "%s blocking on Timer for %d.%06d seconds in %s\n",
- PPPOID(theProcess->processOID), fDelayTime->t.tv_sec,
- fDelayTime->t.tv_usec, PPSSPlace(theProcess));
- MMSetMicroTimer((int)fDelayTime->t.tv_sec, (int)fDelayTime->t.tv_usec,
- (HandlerPtr)TimePassed, (int)theProcess, (TimerId *)NULL);
- }
- /**********************************************************************/
- /* WaitUntil */
- /**********************************************************************/
- /* Kernel call */
- void WaitUntil(fTime)
- register EmTimePtr fTime;
- /* delay the process until the time given */
- {
- struct timeval now, diff;
- #ifndef xkernel
- struct timezone theZone;
- #endif xkernel
- SSPtr theProcess;
-
- if (IsNIL(fTime)) {
- fail(preemptRunning());
- return;
- }
- #ifndef xkernel
- gettimeofday(&now, &theZone);
- #else xkernel
- xgettime(&now);
- #endif xkernel
- if (timeGtrEq(now, fTime->t)) return;
- timeSub(diff, fTime->t, now);
- theProcess = preemptRunning();
- theProcess->status.rs = SSTimerWait;
- KMDTrace("LineNumber", 4,
- "%s blocking on Timer for %d.%06d seconds in %s\n",
- PPPOID(theProcess->processOID), diff.tv_sec, diff.tv_usec,
- PPSSPlace(theProcess));
- MMSetMicroTimer((int)diff.tv_sec, (int)diff.tv_usec,
- (HandlerPtr)TimePassed, (int) theProcess, (TimerId *)NULL);
- }
-
- /**********************************************************************/
- /* SetNodeEventHandler */
- /**********************************************************************/
-
- /* call_c */
- void Node_setNodeEventHandler(fODP, fAbConPtr)
- ODP fODP;
- AbConPtr fAbConPtr;
- {
- AVariable theVar;
- theVar.myAddr = (DataAddr) fODP;
- theVar.myAbConPtr = fAbConPtr;
-
- KMDTrace("Node", 3, "Setting event handler, var: %s\n", PPVar(&theVar));
- if (IsNIL(fODP) || IsNIL(fAbConPtr)) {
- KMDTrace("Node", 3, "NIL\n");
- return;
- }
- Map_Insert(nodeListners, (int) fODP, (int) fAbConPtr);
- }
-
- /**********************************************************************/
- /* RemoveNodeEventHandler */
- /**********************************************************************/
-
- /* call_c */
- void Node_removeNodeEventHandler(fODP, fAbConPtr)
- ODP fODP;
- AbConPtr fAbConPtr;
- {
- AVariable theVar;
- theVar.myAddr = (DataAddr) fODP;
- theVar.myAbConPtr = fAbConPtr;
-
- KMDTrace("Node", 3, "Removing event handler, var: %s\n", PPVar(&theVar));
- if (IsNIL(fODP) || IsNIL(fAbConPtr)) {
- KMDTrace("Node", 3, "NIL\n");
- return;
- }
- Map_Delete(nodeListners, (int) fODP);
- }
-
- /**********************************************************************/
- /* NodeStateChanged */
- /**********************************************************************/
- void NodeStateChanged(fHOTS)
- HOTSRecord *fHOTS;
- /* There has been a state change for the given node */
- {
- GODP theODP;
- AbConPtr theAbConPtr;
-
- KMDTrace("Node", 3, "State changed for node #%d\n", fHOTS->LNN);
- /*
- * Traverse the list of objects that have requested notification of
- * node state changes and schedule a notification call.
- */
-
- /* If we are initialized then .... */
- if (NonNULL(nodeListners)) {
- Map_For(nodeListners, theODP, theAbConPtr)
- KMDTrace("Node", 4, "Node state invoke for 0x%08x\n", theODP);
- if (!theODP->tag.isResident) {
- KMDTrace("Node", 3, "Node state not told to 0x%08x\n", theODP);
- KMDTrace("Node", 3, "Remote invoke not implemented\n");
- } else {
- register SSPtr p;
- register EmTimePtr theTime;
- int opNum;
-
- p = NewProcess();
-
- /* Push arguments onto stack */
- PUSHIT(p->regs.sp, nodeAbCon);
- PUSHIT(p->regs.sp, GetNodeODPFromLNN(fHOTS->LNN));
-
- /* Push second argument onto stack */
- theTime = (EmTimePtr) AllocateWithOID(timeCodePtr,
- (OID) NULL, timeCodePtr->instanceSize);
- theTime->ownOID = (OID) NULL;
- theTime->t.tv_sec = fHOTS->NodeIncarnationId;
- theTime->t.tv_usec = 0;
- PUSHIT(p->regs.sp, timeAbCon);
- PUSHIT(p->regs.sp, theTime);
-
- opNum = ((fHOTS->NodeStat == Alive) ? 0 : 1);
- /* Note, the OpNum MUST agree with the AT handlerType */
- StartProcessAtAddr(p, theODP, theODP->dataPtr,
- (CodeAddr) theAbConPtr->opVector[opNum].opAddress);
- }
- Map_Next;
- }
- }
-
- void NodeInit()
- {
- KMDTrace("Node", 5, "Node initialization\n");
- nodeListners = Map_Create();
- }
-
- /* Copyright 1986 Eric Jul */
-