home *** CD-ROM | disk | FTP | other *** search
- //////////////////////////////////////////////////////////////////////////////*
- //
- // Module Name: MOS.CPP
- //
- // Description: Multi-tasking
- // Operating
- // System
- // Simulation
- //
- // Moss is a simulation of a multi-tasking operating system
- // which uses many of the C standard algorithms.
- //
- //
- // Written by: John Tal
- //
- //
- //
- // Modification History:
- //
- // Date Programmer Mod# Modification
- // ---------------------------------------------------------------------------
- // 04-JUL-1991 J. Tal V1.0-000 New
- //
- // -
- //
-
-
- // VERSION 1 - July 4, 1991
- //
- // MOS uses concepts which are familiar to various implementations of
- // multi-tasking operating systems. It has a scheduler to select a
- // process (or job) to run from a list of waiting processes. It has
- // inter-process-communication (IPC) and (currently) one semaphore.
-
- // What it does not do is context switching. Normally, when the
- // scheduler takes one job which was running and allows another
- // to have some cpu, it saves the current context of the process
- // which was running by saving the values of the important machine
- // (cpu) registers as used by the interrupted process. When the
- // interrupted process is placed back in a running state, it has
- // no clue that it ever stopped running. This version of MOS
- // does not perform context switching. It simply services ready
- // processes (by priority order) and makes each process start at
- // the beginning of its code.
-
- // Another major function of an operating system which is not
- // implemented here is memory management. This is management
- // not only of calloc, malloc, cfree, and free requests by
- // the applications, but it also deals with swapping inactive
- // applications out to disk until they run again. This is
- // virtual memory management and is beyond the scope of the
- // humble goals of MOS.
-
- // The concepts used in MOS are a subset of any multi-tasking
- // operating system. A recommended book for a detailed explanation
- // of the function of operating system design is 'Operating System
- // Design: The XINU Approach' by Douglas Comer. There is also
- // source code available in the public domain which implements XINU
- // on top of PcDos. The source code is not recommended because
- // of serious mistakes made in the specific implemention of sitting
- // on top of dos (a non-multi-tasking operating system). But the
- // book is good reference material.
-
- // Mos was written in a few hours on July 4, 1991 using the Brief
- // editor and Microsoft C 5.1 on an AT clone.
- //
-
- // VERSION 2 - Fall 1991
-
- // The Moss name was changed to MOS for consistency with other members
- // of the Algorithms volumes. The major changes/enhancements for this
- // version include:
- //
- // o Support for unlimited number of semaphores
- // (1 was supported with v 1.0)
- //
- // o Enhanced messaging. A process will now
- // wait for a message if one is not ready yet.
- //
- // o Swap control is enhanced. A process may
- // specify exactly which function is to be
- // called next when a process is swapped back
- // into execution.
- //
- // Version 2 is highly source code compatible with Version 1 and
- // most applications calling MOS will require only recompilation
- // and linking with Version 2 libraries.
- //
- // A number of weeks were spent researching a full-context swapping
- // implemention of MOS. This involved using assembly language to
- // change the stack pointer as each process begins execution.
- // The current version of MOS has provided more than adequate
- // execution and elementary multi-tasking in both DOS and UNIX
- // environments while maintaining the portability not possible
- // in assembly language. If you are interested in extending MOS
- // into full context-swapping and/or interrept driven modes, there
- // is ample documentation in Dr. Dobbs Journal and C Users Group
- // magazines to do so.
- //
-
- // VERSION 2 C++ - February 1992
-
- // The C++ port of MOS provided quite a number of suprises.
- // Once again, C++ has the ability to point out inefficiencies
- // in a seemingly effective design. Specific tips which were
- // learned during the MOS port are provided in a document called
- // c_2_cpp.txt which is released with MOS on Volume 2 of the
- // Algorithms series.
-
-
-
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
-
- #include <cmemlib.h>
- #include <time.h>
-
- #include "mos.h"
-
-
-
-
-
- #ifdef TEST
-
-
- SHORT MosTestProc(MOS_C *, PVOID);
-
-
- //
- // Mos Main
- //
-
-
- int main()
- {
- C_DEF_MODULE("MosMain")
-
-
- MOS_C Mos;
-
- //
- // Load up some processes, all use the MosGenericProc as their
- // code. This could be modified for experimentation to
- // be other processes modeled after MosGenericProc but
- // with specialized functions
- //
-
- C_STATUS = Mos.ProcCreate(MosTestProc,"Plankton",10,NULL);
- C_STATUS = Mos.ProcCreate(MosTestProc,"Trilobite",10,NULL);
- C_STATUS = Mos.ProcCreate(MosTestProc,"Volvox",5,NULL);
- C_STATUS = Mos.ProcCreate(MosTestProc,"Tree",5,NULL);
- C_STATUS = Mos.ProcCreate(MosTestProc,"Eagle",1,NULL);
-
- Mos.Scheduler();
-
- C_RETURN
- }
-
- #endif
-
-
-
- //
- // Init Mos Environment
- //
-
- SHORT
- MOS_C::Init(VOID)
- {
- C_DEF_MODULE("MOS_C::Init")
-
- //
- // Init semaphore
- //
-
- sProcId = 0;
- sSemHandle = 0;
-
- #if 0
- strcpy(szProcStates[0],"Non Existant");
- strcpy(szProcStates[1],"Running");
- strcpy(szProcStates[2],"Ready");
- strcpy(szProcStates[3],"Sleeping");
- strcpy(szProcStates[4],"Waiting on Semaphore");
- strcpy(szProcStates[5],"Waiting on Message");
- #endif
-
- //
- // Must always have a process on the ready queue, the NULL process
- // does nothing. In operating systems, nothing else can EVER
- // have access to the NULL process or the swapper process.
- // Noone or nothing can kill them or the system dies.
- //
-
- C_STATUS = ProcCreate(MosNullProc,"NULL_PROC",0,(PVOID) NULL);
-
- C_RETURN
- }
-
-
- //
- // MosCompareTreProcId
- //
- // Use for node to node comparision of binary tree, for InsertNode
- //
-
- SHORT
- CompareTreProcId(PVOID pvData1,PVOID pvData2)
- {
- PROC_P pclProc1;
- PROC_P pclProc2;
-
- pclProc1 = (PROC_P) pvData1;
- pclProc2 = (PROC_P) pvData2;
-
- if(pclProc1 -> GetId() == pclProc2 -> GetId())
- return(C_EQUAL);
- else if(pclProc1 -> GetId() < pclProc2 -> GetId())
- return(C_LOWER);
- else
- return(C_HIGHER);
- }
-
-
- //
- // MosCompareIdNode
- //
-
- SHORT
- MosCompareIdNode(PVOID pvData1,PVOID pvData2)
- {
- PROC_P pclProc;
- PSHORT psProcId;
-
-
- psProcId = (PSHORT) pvData1;
- pclProc = (PROC_P) pvData2;
-
- if(*psProcId == pclProc -> GetId())
- return(C_EQUAL);
- else if(*psProcId < pclProc -> GetId())
- return(C_LOWER);
- else if(*psProcId > pclProc -> GetId())
- return(C_HIGHER);
-
- }
-
-
- //
- // MosCompareProcWakeTime
- //
-
- SHORT
- MosCompareProcWakeTime(PVOID pvData1,PVOID pvData2)
- {
- PROC_P pclProc1;
- PROC_P pclProc2;
-
- pclProc1 = (PROC_P) pvData1;
- pclProc2 = (PROC_P) pvData2;
-
- if(pclProc1 -> GetWakeTime() == pclProc2 -> GetWakeTime())
- return(C_EQUAL);
- else if(pclProc1 -> GetWakeTime() < pclProc2 -> GetWakeTime())
- return(C_LOWER);
- else
- return(C_HIGHER);
- }
-
-
-
-
- //
- // MOS APIs
- //
-
- //
- // Create a new process
- //
-
- SHORT
- MOS_C::ProcCreate(SHORT (*pProc)(MOS_C *, PVOID), PCHAR szProcName, SHORT sPriority,PVOID pvWorkArea)
- {
- C_DEF_MODULE("MOS_C::ProcCreate")
-
- PROC_P pclProc;
-
- pclProc = (PROC_P) new PROC_C;
-
- pclProc -> SetPriority(sPriority); // set priority
- pclProc -> SetName(szProcName); // set name
- pclProc -> SetId(sProcId); // set proc id
- sProcId++; // inc global
-
- pclProc -> SetState(PROC_STATE_READY); // It is ready
- pclProc -> SetPrevState(PROC_STATE_NO_EXIST); // no prvious state
- pclProc -> pProc = pProc; // Point to proc to run
- pclProc -> pBlockedFunc = NULL;
- pclProc -> SetWorkArea(pvWorkArea);
-
- lNumProcs++;
-
- //
- // Store this process in the global process tree
- //
-
- C_STATUS = clProcTree.SetCompareFunc(MosCompareProcName);
- C_STATUS = clProcTree.Insert((PVOID) &pclProc);
-
- //
- // Store this process in proc id list
- //
-
- C_STATUS = clPidList.SetCompareFunc(MosCompareProcId);
- C_STATUS = clPidList.Insert((PVOID) &pclProc);
-
- //
- // Place this process on the ready queue
- //
-
- C_STATUS = ReschedReady(pclProc);
-
- C_RETURN
- }
-
-
- //
- // Terminate a process
- //
-
- SHORT
- MOS_C::ProcTerm(VOID)
- {
- C_DEF_MODULE("MOS_C::ProcTerm")
-
- PVOID pvData;
-
- C_STATUS = clProcTree.SetCompareFunc(MosCompareProcName);
- C_STATUS = clProcTree.Delete((PVOID) pclRunProc);
-
- C_STATUS = clPidList.SetCompareFunc(MosCompareProcId);
- C_STATUS = clPidList.Find((PVOID) pclRunProc,&pvData);
- C_STATUS = clPidList.DeleteCur();
-
- pclRunProc -> SetState(PROC_STATE_NO_EXIST);
-
- lNumProcs--;
-
- delete pclRunProc;
-
- C_RETURN
- }
-
-
- //
- // MosScheduler
- //
- // This is the central workhorse function
- //
-
- SHORT
- MOS_C::Scheduler(VOID)
- {
- C_DEF_MODULE("MOS_C::Scheduler")
-
- PROC_P pclProc;
-
- while(1)
- {
-
- /* if only NULL proc is running, terminate */
-
- if(lNumProcs == 1)
- break;
-
-
- /*
- ** Run check on all events
- */
-
- C_STATUS = EventCheckList();
-
-
- //
- // You may want to put a delay here or get a character from the
- // keyboard to see what Mos is doing on each iteration through
- // the code
- //
-
- C_STATUS = CheckSleepQueue();
-
- C_STATUS = GetReadyProc(&pclProc);
-
- pclRunProc = pclProc;
-
- //
- // Invoke the process
- //
-
- if(pclRunProc -> pBlockedFunc == NULL)
- C_STATUS = (*pclRunProc -> pProc)(this,pclRunProc->GetWorkArea());
- else
- C_STATUS = (*pclRunProc -> pBlockedFunc)(this,pclRunProc->GetWorkArea());
-
-
- // The function ^ ptr to MOS ^ proc workarea
-
- //
- // If we were running the NULL process, then MUST put it back on the
- // ready queue. An empty ready queue = system crash
- //
-
- if(C_STATUS != PROC_STATE_NO_EXIST)
- {
- if(pclRunProc -> GetState() == PROC_STATE_RUNNING)
- C_STATUS = ReschedReady(pclRunProc);
- }
-
- }
-
- //
- // Some compilers will tell you that the next statement is unreachable,
- // That is ok.
- //
-
- C_RETURN
- }
-
-
- //
- // Mos CheckSleepQueue
- //
- // Check the sleep queue. If anything there and is ready to be
- // waked-up, place on the ready queue
- //
-
- SHORT
- MOS_C::CheckSleepQueue(VOID)
- {
- C_DEF_MODULE("MOS_C::CheckSleepQueue")
-
- PROC_P pclProc;
-
- while(1)
- {
- //
- // Loop to free all jobs which we can
- //
-
- C_STATUS = clQueSleep.FindFirst((PVOID *) &pclProc);
-
- if(pclProc != NULL)
- {
- if(pclProc -> GetWakeTime() <= GetTime())
- {
- printf("Process %d: %s : Being awakened\n", pclProc -> GetId(),
- pclProc -> GetName());
- // Delete from Sleep list/queue
-
- C_STATUS = clQueSleep.DeleteCur();
-
- C_STATUS = ReschedReady(pclProc);
- }
- else
- break;
- }
- else
- break;
- }
-
- C_RETURN
- }
-
-
- //
- // MosReschedReady
- //
- // Places a process on the ready queue
- //
-
- SHORT
- MOS_C::ReschedReady(PROC_P pclProc)
- {
- C_DEF_MODULE("MOS_C::ReschedReady")
-
- pclProc -> SetPrevState(pclProc -> GetState()); // save state
- pclProc -> SetState(PROC_STATE_READY); // set state
- C_STATUS = clQueReady.Enq(pclProc -> GetPriority(),(PVOID) pclProc);
-
- #ifdef ANNOUNCE
- C_STATUS = ProcAnnounce(pclProc);
- #endif
-
- C_RETURN
- }
-
-
- //
- // Mos GetReadyProc
- //
- // It retrieves the process that should be run next from the ready queue
- //
-
- SHORT
- MOS_C::GetReadyProc(PROC_P * ppclProc)
- {
- C_DEF_MODULE("MOS_C::GetReadyProc")
-
- SHORT sPriority;
-
- //
- // Get a process
- //
-
- C_STATUS = clQueReady.Deq(&sPriority, (PVOID *) ppclProc);
-
- //
- // Set proc state to running
- //
-
- (*ppclProc) -> SetState(PROC_STATE_RUNNING);
-
- #ifdef ANNOUNCE
- printf("\n");
-
- C_STATUS = ProcAnnounce(*ppclProc);
- #endif
-
- C_RETURN
- }
-
-
- //
- // MosProcAnnounce
- //
- // It is used for processes to announce when they have started running
- //
-
- //SHORT
- //MOS_C::ProcAnnounce(PROC_P pclProc)
- //{
- // C_DEF_MODULE("MOS_C::ProcAnnounce")
- //
- // printf("Process %d: %s : Is %s\n",
- // * pclProc -> GetProcId();
- // * pclProc -> GetName(),
- // szProcStates[pclProc -> sState]);
- //
- // C_RETURN
- //}
-
-
- //
- // MosNullProc
- //
- // The Null Process
- //
-
- SHORT
- MosNullProc(MOS_P pclMos,PVOID pvWorkArea)
- {
- C_DEF_MODULE("MOS_C::NullProc")
-
- pvWorkArea = pvWorkArea; // to keep compiler quiet
- pclMos = pclMos; // to keep compiler quiet
-
- #ifdef ANNOUNCE
- C_STATUS = ProcAnnounce();
- #endif
-
- // If running under any multi-tasking/processing
- // operating system, sleep here so dont eat up CPU
-
- #ifdef C_UNIX
- sleep(1);
- #endif
-
- C_RETURN
- }
-
-
- //
- // Semaphore
- //
-
- //
- // Mos SemInit
- //
-
- SEM_HANDLE
- MOS_C::SemInit(PCHAR pcSemName)
- {
- C_DEF_VMODULE("MOS_C::SemInit")
-
- SEM_P pclSem;
- PVOID pvTemp;
- SEM_HANDLE sRetSemHandle;
-
-
- // Check if exists already;
-
- clSemList.FindFirst((PVOID *) &pclSem);
-
- while(pclSem != NULL)
- {
- if(strcmp(pclSem -> GetName(),pcSemName) == 0)
- return(pclSem -> GetHandle());
- }
-
- // must be new one
-
- pclSem = new SEM_C;
-
- pclSem -> SetName(pcSemName);
-
- pclSem -> SetHandle(sSemHandle);
-
- sRetSemHandle = sSemHandle;
-
- sSemHandle++; // inc global handle
-
- // insert into list
-
- clSemList.FindLast(&pvTemp);
-
- clSemList.AddAfterCur((PVOID) pclSem);
-
- return(sRetSemHandle);
- }
-
-
- //
- // Mos SemTerm
- //
-
- SHORT
- MOS_C::SemTerm(SEM_HANDLE sSemHandle)
- {
- C_DEF_MODULE("MOS_C::SemTerm")
-
- SEM_P pclSem;
- PVOID pvTemp;
- BOOL fFound = C_FALSE;
-
- // Check if exists already;
-
- clSemList.FindFirst((PVOID *) &pclSem);
-
- while(pclSem != NULL)
- {
- if(pclSem -> GetHandle() == sSemHandle)
- {
- fFound = C_TRUE;
-
- clSemList.DeleteCur();
-
- delete pclSem;
-
- break;
- }
- }
-
- if(!fFound)
- C_SET_STATUS(C_NOTOK)
-
- C_RETURN
- }
-
- //
- // Mos SemFindHandle
- //
-
- VOID
- MOS_C::SemFindHandle(SEM_HANDLE sSemHandle, SEM_P * ppclSem, BOOL * pfFound)
- {
- C_DEF_VMODULE("MOS_C::SemFindHandle")
-
- *pfFound = C_FALSE;
-
- // Check if exists
-
- clSemList.FindFirst((PVOID *) ppclSem);
-
- while(*ppclSem != NULL)
- {
- if((*ppclSem) -> GetHandle() == sSemHandle)
- {
- *pfFound = C_TRUE;
- break;
- }
- }
- }
-
-
- //
- // Mos SemNextProc
- //
-
- VOID
- MOS_C::SemNextProc(SEM_P pclSem)
- {
- C_DEF_MODULE("MOS_C::SemNextProc")
-
- LONG lNumEntries;
- PROC_P pclReleasedProc;
-
- C_STATUS = pclSem -> clQueSemWait.GetEntries(&lNumEntries);
-
- if(lNumEntries != 0)
- {
- //
- // Retrieve the process which was waiting for the semaphore
- //
-
- C_STATUS = pclSem -> clQueSemWait.Deq((PVOID *) &pclReleasedProc);
-
- //
- // Place it back on the ready queue
- //
-
- C_STATUS = ReschedReady(pclReleasedProc);
-
- //
- // Give it the semaphore
- //
-
- C_STATUS = SemWait(pclSem -> GetHandle());
- }
-
- C_SET_STATUS(C_STATUS) // to make compiler be quiet
- }
-
-
-
-
- //
- // Mos SemWait
- //
-
- SHORT
- MOS_C::SemWait(SEM_HANDLE sSemHandle)
- {
- C_DEF_MODULE("MOS_C::SemWait")
-
-
- SEM_P pclSem;
- PVOID pvTemp;
- BOOL fFound = C_FALSE;
-
- #ifdef ANNOUNCE
- printf("Process %d: %s : Requesting semaphore\n",
- pclRunProc -> GetId(), pclRunProc -> GetName());
- #endif
-
- SemFindHandle(sSemHandle,&pclSem,&fFound);
-
- if(fFound)
- {
- if(pclSem -> GetVal() != SEM_AVAIL)
- {
- #ifdef ANNOUNCE
- printf("Process %d: %s : Queued for semaphore\n", pclRunProc -> GetId(),
- pclRunProc -> GetName());
- #endif
- // Queue the process to wait for the semaphore
-
- pclSem -> clQueSemWait.Enq((PVOID) pclRunProc);
-
- pclRunProc -> SetState(PROC_STATE_SEM_WAIT);
-
- C_STATUS = PROC_STATE_SUSPENDED;
- }
- else
- {
- #ifdef ANNOUNCE
- printf("Process %d: %s : Obtained semaphore\n", pclRunProc -> GetId(),
- pclRunProc -> GetName());
- #endif
-
- pclSem -> SetVal(pclSem -> GetVal() + 1);
- pclRunProc -> SetfCritical(C_TRUE);
- }
- }
-
- C_RETURN
- }
-
-
- //
- // Sem Signal
- //
- // Called by a process when it releases exclusive access to the
- // semaphore
- //
-
- SHORT
- MOS_C::SemSignal(SEM_HANDLE sSemHandle)
- {
- C_DEF_MODULE("MOS_C::SemSignal")
-
- SEM_P pclSem;
- BOOL fFound;
-
- #ifdef ANNOUNCE
- printf("Process %d: %s : Releasing semaphore\n", pclRunProc -> GetId(),
- pclProc -> GetName());
- #endif
-
- pclRunProc -> SetfCritical(C_FALSE);
-
- SemFindHandle(sSemHandle,&pclSem,&fFound);
-
- if(fFound)
- {
- pclSem -> SetVal(pclSem -> GetVal() -1);
-
- SemNextProc(pclSem);
- }
-
- C_RETURN
- }
-
- //
- // Sem Clear
- //
- // Called by a process when it releases exclusive access to the
- // semaphore
- //
-
- SHORT
- MOS_C::SemClear(SEM_HANDLE sSemHandle)
- {
- C_DEF_MODULE("MOS_C::SemClear")
-
- SEM_P pclSem;
- BOOL fFound;
-
- #ifdef ANNOUNCE
- printf("Process %d: %s : Clearing semaphore\n", pclRunProc -> GetId(),
- pclRunProc -> GetName());
- #endif
-
- pclRunProc -> SetfCritical(C_FALSE);
-
- SemFindHandle(sSemHandle,&pclSem,&fFound);
-
- if(fFound)
- {
- pclSem -> SetVal(SEM_AVAIL);
-
- SemNextProc(pclSem);
- }
-
- C_RETURN
- }
-
- //
- // Mos SemSet
- //
-
- SHORT
- MOS_C::SemSet(SEM_HANDLE sSemHandle)
- {
- C_DEF_MODULE("MOS_C::SemSet")
-
-
- SEM_P pclSem;
- PVOID pvTemp;
- BOOL fFound = C_FALSE;
-
- #ifdef ANNOUNCE
- printf("Process %d: %s : Requesting semaphore\n",
- pclRunProc -> GetId(), pclRunProc -> GetName());
- #endif
-
- SemFindHandle(sSemHandle,&pclSem,&fFound);
-
- if(fFound)
- {
- #ifdef ANNOUNCE
- printf("Process %d: %s : Setting semaphore\n", pclRunProc -> GetId(),
- pclRunProc -> GetName());
- #endif
-
- pclSem -> SetVal(MOS_SEM_SET);
- }
-
- C_RETURN
- }
-
-
- //
- // MosCurTime
- //
- // Mos function to get the current time
- //
-
- LONG
- MOS_C::GetTime(VOID)
- {
- time_t lTime;
-
- time(&lTime);
-
- return((LONG) lTime);
- }
-
-
- //
- // Mos Sleep
- //
- // Called by a process to setup for sleeping
- //
-
- SHORT
- MOS_C::Sleep(LONG lSecs)
- {
- C_DEF_MODULE("MOS_C::Sleep")
-
- pclRunProc -> SetState(PROC_STATE_SLEEPING);
-
- pclRunProc -> SetWakeTime(GetTime() + lSecs);
-
- #ifdef ANNOUNCE
- printf("Process %d: %s : Sleeping till %d\n", pclProc -> GetId(),
- pclProc -> GetName(),
- pclProc -> GetWakeTime());
- #endif
-
- C_STATUS = clQueSleep.SetCompareFunc(MosCompareProcWakeTime);
-
- C_STATUS = clQueSleep.Insert((PVOID) pclRunProc);
-
- C_SET_STATUS(PROC_STATE_SUSPENDED)
-
- C_RETURN
- }
-
-
- //
- // MosCompareProcId
- //
-
- SHORT
- MosCompareProcId(PVOID pvData1,PVOID pvData2)
- {
- PROC_P pclProc1;
- PROC_P pclProc2;
-
-
- pclProc1 = (PROC_P) pvData1;
- pclProc2 = (PROC_P) pvData2;
-
- if(pclProc1 -> GetId() == pclProc2 -> GetId())
- return(C_EQUAL);
- else if(pclProc1 -> GetId() < pclProc2 -> GetId())
- return(C_LOWER);
- else if(pclProc1 -> GetId() > pclProc2 -> GetId())
- return(C_HIGHER);
-
- }
-
-
- //
- // MosCompareProcId
- //
-
- SHORT
- MosCompareProcName(PVOID pvData1,PVOID pvData2)
- {
- PROC_P pclProc1;
- PROC_P pclProc2;
-
-
- pclProc1 = (PROC_P) pvData1;
- pclProc2 = (PROC_P) pvData2;
-
- return(strcmp(pclProc1 -> GetName(),pclProc2 -> GetName()));
- }
-
-
-
-
- //
- // MosMsgWrite
- //
- // Write a message (class) to a target process
- //
-
- SHORT
- MOS_C::MsgWrite(MSG_P pclMsg)
- {
- C_DEF_MODULE("MOS_C::MsgWrite")
-
- PROC_P pclDestProc;
- PROC_P pclTempProc;
- SHORT sPid;
-
- #ifdef ANNOUNCE
- printf("Process %d: %s : Sending message to procid %d\n", pclProc -> GetId(),
- pclProc -> GetName(),
- sTargetProcId);
- #endif
-
- //
- // Setup message for sending
- //
-
- pclMsg -> SetSendPid(pclRunProc -> GetId());
-
- //
- // Find address of destination process
- //
-
- C_STATUS = clProcTree.SetCompareFunc(MosCompareIdNode);
-
- sPid = pclMsg -> GetDestPid();
-
- C_STATUS = clProcTree.Find((PVOID) &sPid, (PVOID *) &pclDestProc);
-
- if(pclDestProc != NULL)
- {
- C_STATUS = pclDestProc -> clMsgQue.Enq((PVOID) pclMsg);
-
- //
- // Check if process was sleeping, if so, wake it up.
- //
- // Remove it from the sleeping queue and place on ready queue
- //
-
- if(pclDestProc -> GetState() == PROC_STATE_SLEEPING)
- {
-
- C_STATUS = clQueSleep.SetCompareFunc(MosCompareIdNode);
-
- sPid = pclDestProc -> GetId();
-
- C_STATUS = clQueSleep.Find((PVOID) &sPid,
- (PVOID *) &pclTempProc);
-
- C_STATUS = clQueSleep.DeleteCur();
-
- C_STATUS = ReschedReady(pclDestProc);
-
- }
-
- //
- // Check if process was waiting on message, if so
- // Remove it from the msg wait queue and place on ready queue
- //
-
- if(pclDestProc -> GetState() == PROC_STATE_MSG_WAIT)
- {
-
- C_STATUS = clQueMsgWait.SetCompareFunc(MosCompareIdNode);
-
- sPid = pclDestProc -> GetId();
-
- C_STATUS = clQueMsgWait.Find((PVOID) &sPid,
- (PVOID *) &pclTempProc);
-
- C_STATUS = clQueMsgWait.DeleteCur();
-
- C_STATUS = ReschedReady(pclDestProc);
-
- }
- }
-
- C_RETURN
- }
-
-
- //
- // Mos MsgWaiting
- //
-
- BOOL
- MOS_C::MsgWaiting(VOID)
- {
- C_DEF_VMODULE("MOS_C::MsgRead")
-
- LONG lEntries;
-
- pclRunProc -> clMsgQue.GetEntries(&lEntries); // see if anything there
-
- if(lEntries)
- return((BOOL) C_TRUE);
- else
- return((BOOL) C_FALSE);
- }
-
- //
- // MosMsgRead
- //
- // Read a message
- //
-
- SHORT
- MOS_C::MsgRead(MSG_P ppclMsg)
- {
- C_DEF_MODULE("MOS_C::MsgRead")
-
- LONG lEntries;
-
- pclRunProc -> clMsgQue.GetEntries(&lEntries); // see if anything there
-
- if(lEntries)
- {
- C_STATUS = pclRunProc -> clMsgQue.Deq((PPVOID) ppclMsg);
- }
- else
- {
- //
- // Place in Msg Wait que (Added November 23, 1991)
- //
-
- pclRunProc -> SetState(PROC_STATE_MSG_WAIT);
-
- C_STATUS = clQueMsgWait.Insert((PVOID) pclRunProc);
-
- C_STATUS = PROC_STATE_SUSPENDED;
- }
-
- C_RETURN
- }
-
-
-
- /*
- ** MosEventCheckList
- **
- ** Check Event List
- */
-
- SHORT
- MOS_C::EventCheckList(VOID)
- {
- C_DEF_MODULE("MOS_C::EventCheckList")
-
- EVENT_P pstEvent;
-
- if(sEvents == 0)
- C_LEAVE(C_OK);
-
-
- C_STATUS = pclEventList.FindFirst((PVOID *) &pstEvent);
-
- while(pstEvent != NULL)
- {
-
- /* check for event occurance */
-
- C_STATUS = (*(pstEvent -> pCheckFunc))();
-
- if(C_STATUS)
- {
- /*
- ** if event occurred, place back on ready/run queue
- ** processes awaiting events may be of higher priority than
- ** normal processes
- */
-
- C_STATUS = ReschedReady(pstEvent->pclEventProc);
- }
-
- C_STATUS = pclEventList.GetNext((PVOID *) &pstEvent);
- }
-
-
- C_SET_STATUS(C_OK);
-
-
- C_MODULE_EXIT:
-
- C_RETURN
- }
-