home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / text_cla / mos.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-12  |  24.6 KB  |  1,179 lines

  1. //////////////////////////////////////////////////////////////////////////////*
  2. //
  3. // Module Name:   MOS.CPP
  4. // 
  5. // Description:   Multi-tasking
  6. //                Operating
  7. //                System
  8. //                Simulation
  9. //
  10. //                Moss is a simulation of a multi-tasking operating system
  11. //                which uses many of the C standard algorithms.
  12. //
  13. //
  14. // Written by:  John Tal
  15. //
  16. //
  17. //
  18. // Modification History:
  19. //
  20. // Date          Programmer      Mod#     Modification
  21. // ---------------------------------------------------------------------------
  22. // 04-JUL-1991   J. Tal          V1.0-000 New
  23. //
  24. // -
  25. //
  26.  
  27.  
  28. //    VERSION 1 - July 4, 1991
  29. //
  30. //    MOS uses concepts which are familiar to various implementations of
  31. //    multi-tasking operating systems.   It has a scheduler to select a
  32. //    process (or job) to run from a list of waiting processes.   It has
  33. //    inter-process-communication (IPC) and (currently) one semaphore.
  34.  
  35. //    What it does not do is context switching.  Normally, when the
  36. //    scheduler takes one job which was running and allows another
  37. //    to have some cpu, it saves the current context of the process
  38. //    which was running by saving the values of the important machine
  39. //    (cpu) registers as used by the interrupted process.   When the
  40. //    interrupted process is placed back in a running state, it has
  41. //    no clue that it ever stopped running.   This version of MOS
  42. //    does not perform context switching.   It simply services ready
  43. //    processes (by priority order) and makes each process start at
  44. //    the beginning of its code.
  45.  
  46. //    Another major function of an operating system which is not 
  47. //    implemented here is memory management.   This is management
  48. //    not only of calloc, malloc, cfree, and free requests by
  49. //    the applications, but it also deals with swapping inactive
  50. //    applications out to disk until they run again.  This is
  51. //    virtual memory management and is beyond the scope of the
  52. //    humble goals of MOS.   
  53.  
  54. //    The concepts used in MOS are a subset of any multi-tasking
  55. //    operating system.   A recommended book for a detailed explanation
  56. //    of the function of operating system design is 'Operating System
  57. //    Design: The XINU Approach'  by Douglas Comer.  There is also
  58. //    source code available in the public domain which implements XINU
  59. //    on top of PcDos.   The source code is not recommended because
  60. //    of serious mistakes made in the specific implemention of sitting
  61. //    on top of dos (a non-multi-tasking operating system).  But the 
  62. //    book is good reference material.
  63.  
  64. //    Mos was written in a few hours on July 4, 1991 using the Brief
  65. //    editor and Microsoft C 5.1 on an AT clone.
  66. //
  67.  
  68. //    VERSION 2 - Fall 1991
  69.  
  70. //    The Moss name was changed to MOS for consistency with other members
  71. //    of the Algorithms volumes.  The major changes/enhancements for this
  72. //    version include:
  73. //
  74. //              o       Support for unlimited number of semaphores
  75. //                      (1 was supported with v 1.0)
  76. //
  77. //              o       Enhanced messaging.   A process will now
  78. //                      wait for a message if one is not ready yet.
  79. //
  80. //              o       Swap control is enhanced.   A process may
  81. //                      specify exactly which function is to be
  82. //                      called next when a process is swapped back
  83. //                      into execution. 
  84. //
  85. //   Version 2 is highly source code compatible with Version 1 and
  86. //   most applications calling MOS will require only recompilation
  87. //   and linking with Version 2 libraries.
  88. //
  89. //   A number of weeks were spent researching a full-context swapping
  90. //   implemention of MOS.  This involved using assembly language to
  91. //   change the stack pointer as each process begins execution.
  92. //   The current version of MOS has provided more than adequate 
  93. //   execution and elementary multi-tasking in both DOS and UNIX
  94. //   environments while maintaining the portability not possible
  95. //   in assembly language.  If you are interested in extending MOS
  96. //   into full context-swapping and/or interrept driven modes, there
  97. //   is ample documentation in Dr. Dobbs Journal and C Users Group
  98. //   magazines to do so.
  99. //
  100.  
  101. //    VERSION 2 C++ - February 1992
  102.  
  103. //    The C++ port of MOS provided quite a number of suprises.
  104. //    Once again, C++ has the ability to point out inefficiencies
  105. //    in a seemingly effective design.  Specific tips which were
  106. //    learned during the MOS port are provided in a document called
  107. //    c_2_cpp.txt which is released with MOS on Volume 2 of the
  108. //    Algorithms series.
  109.  
  110.  
  111.  
  112. #include <string.h>
  113. #include <stdlib.h>
  114. #include <stdio.h>
  115.  
  116. #include <cmemlib.h>
  117. #include <time.h>
  118.  
  119. #include "mos.h"
  120.  
  121.  
  122.  
  123.  
  124.  
  125. #ifdef TEST
  126.  
  127.  
  128. SHORT MosTestProc(MOS_C *, PVOID);
  129.  
  130.  
  131. //
  132. //   Mos Main
  133. //
  134.  
  135.  
  136. int main()
  137. {
  138.    C_DEF_MODULE("MosMain")
  139.  
  140.    
  141.    MOS_C   Mos;
  142.  
  143.    //
  144.    //  Load up some processes, all use the MosGenericProc as their
  145.    //  code.   This could be modified for experimentation to
  146.    //  be other processes modeled after MosGenericProc but
  147.    //  with specialized functions
  148.    //
  149.  
  150.    C_STATUS = Mos.ProcCreate(MosTestProc,"Plankton",10,NULL);
  151.    C_STATUS = Mos.ProcCreate(MosTestProc,"Trilobite",10,NULL);
  152.    C_STATUS = Mos.ProcCreate(MosTestProc,"Volvox",5,NULL);
  153.    C_STATUS = Mos.ProcCreate(MosTestProc,"Tree",5,NULL);
  154.    C_STATUS = Mos.ProcCreate(MosTestProc,"Eagle",1,NULL);
  155.  
  156.    Mos.Scheduler();
  157.  
  158.    C_RETURN
  159. }
  160.  
  161. #endif
  162.  
  163.  
  164.  
  165. //
  166. //  Init Mos Environment
  167. //
  168.  
  169. SHORT
  170. MOS_C::Init(VOID)
  171. {
  172.    C_DEF_MODULE("MOS_C::Init")
  173.  
  174.    //
  175.    //  Init semaphore
  176.    //
  177.  
  178.    sProcId = 0;
  179.    sSemHandle = 0;
  180.  
  181. #if 0
  182.    strcpy(szProcStates[0],"Non Existant");
  183.    strcpy(szProcStates[1],"Running");
  184.    strcpy(szProcStates[2],"Ready");
  185.    strcpy(szProcStates[3],"Sleeping");
  186.    strcpy(szProcStates[4],"Waiting on Semaphore");
  187.    strcpy(szProcStates[5],"Waiting on Message");
  188. #endif
  189.  
  190.    //
  191.    //  Must always have a process on the ready queue, the NULL process
  192.    //  does nothing.   In operating systems, nothing else can EVER
  193.    //  have access to the NULL process or the swapper process.
  194.    //  Noone or nothing can kill them or the system dies.
  195.    //
  196.  
  197.    C_STATUS = ProcCreate(MosNullProc,"NULL_PROC",0,(PVOID) NULL);
  198.  
  199.    C_RETURN
  200. }
  201.  
  202.  
  203. //
  204. //  MosCompareTreProcId
  205. //
  206. //      Use for node to node comparision of binary tree, for InsertNode
  207. //
  208.  
  209. SHORT
  210. CompareTreProcId(PVOID pvData1,PVOID pvData2)
  211. {
  212.    PROC_P   pclProc1;
  213.    PROC_P   pclProc2;
  214.  
  215.    pclProc1 = (PROC_P) pvData1;
  216.    pclProc2 = (PROC_P) pvData2;
  217.  
  218.    if(pclProc1 -> GetId() == pclProc2 -> GetId())
  219.       return(C_EQUAL);
  220.    else if(pclProc1 -> GetId() < pclProc2 -> GetId())
  221.       return(C_LOWER);
  222.    else
  223.       return(C_HIGHER);
  224. }
  225.  
  226.  
  227. //
  228. //   MosCompareIdNode
  229. //
  230.  
  231. SHORT
  232. MosCompareIdNode(PVOID pvData1,PVOID pvData2)
  233. {
  234.    PROC_P   pclProc;
  235.    PSHORT   psProcId;
  236.  
  237.  
  238.    psProcId = (PSHORT) pvData1;
  239.    pclProc = (PROC_P) pvData2;
  240.                             
  241.    if(*psProcId == pclProc -> GetId())
  242.       return(C_EQUAL);
  243.    else if(*psProcId < pclProc -> GetId())
  244.       return(C_LOWER);
  245.    else if(*psProcId > pclProc -> GetId())
  246.       return(C_HIGHER);
  247.  
  248. }
  249.  
  250.  
  251. //
  252. //   MosCompareProcWakeTime
  253. //
  254.  
  255. SHORT
  256. MosCompareProcWakeTime(PVOID pvData1,PVOID pvData2)
  257. {
  258.    PROC_P   pclProc1;
  259.    PROC_P   pclProc2;
  260.  
  261.    pclProc1 = (PROC_P) pvData1;
  262.    pclProc2 = (PROC_P) pvData2;
  263.  
  264.    if(pclProc1 -> GetWakeTime() == pclProc2 -> GetWakeTime())
  265.       return(C_EQUAL);
  266.    else if(pclProc1 -> GetWakeTime() < pclProc2 -> GetWakeTime())
  267.       return(C_LOWER);
  268.    else
  269.       return(C_HIGHER);
  270. }
  271.  
  272.  
  273.  
  274.  
  275. //
  276. //    MOS APIs
  277. //
  278.  
  279. //
  280. //    Create a new process
  281. //
  282.  
  283. SHORT
  284. MOS_C::ProcCreate(SHORT (*pProc)(MOS_C *, PVOID), PCHAR szProcName, SHORT sPriority,PVOID pvWorkArea)
  285. {
  286.    C_DEF_MODULE("MOS_C::ProcCreate")
  287.  
  288.    PROC_P   pclProc;
  289.  
  290.    pclProc = (PROC_P) new PROC_C;
  291.  
  292.    pclProc -> SetPriority(sPriority);  // set priority
  293.    pclProc -> SetName(szProcName);     // set name
  294.    pclProc -> SetId(sProcId);          // set proc id
  295.    sProcId++;                          // inc global
  296.  
  297.    pclProc -> SetState(PROC_STATE_READY);         // It is ready 
  298.    pclProc -> SetPrevState(PROC_STATE_NO_EXIST);  // no prvious state
  299.    pclProc -> pProc = pProc;          // Point to proc to run
  300.    pclProc -> pBlockedFunc = NULL;
  301.    pclProc -> SetWorkArea(pvWorkArea);
  302.  
  303.    lNumProcs++;
  304.  
  305.    //
  306.    //   Store this process in the global process tree
  307.    //
  308.  
  309.    C_STATUS = clProcTree.SetCompareFunc(MosCompareProcName);
  310.    C_STATUS = clProcTree.Insert((PVOID) &pclProc);
  311.  
  312.    //
  313.    //   Store this process in proc id list
  314.    //
  315.  
  316.    C_STATUS = clPidList.SetCompareFunc(MosCompareProcId);
  317.    C_STATUS = clPidList.Insert((PVOID) &pclProc);
  318.  
  319.    //
  320.    //  Place this process on the ready queue
  321.    //
  322.  
  323.    C_STATUS = ReschedReady(pclProc);
  324.  
  325.    C_RETURN
  326. }
  327.  
  328.  
  329. //
  330. //    Terminate a process
  331. //
  332.  
  333. SHORT
  334. MOS_C::ProcTerm(VOID)
  335. {
  336.    C_DEF_MODULE("MOS_C::ProcTerm")
  337.  
  338.    PVOID    pvData;
  339.  
  340.    C_STATUS = clProcTree.SetCompareFunc(MosCompareProcName);
  341.    C_STATUS = clProcTree.Delete((PVOID) pclRunProc);
  342.  
  343.    C_STATUS = clPidList.SetCompareFunc(MosCompareProcId);
  344.    C_STATUS = clPidList.Find((PVOID) pclRunProc,&pvData);
  345.    C_STATUS = clPidList.DeleteCur();
  346.  
  347.    pclRunProc -> SetState(PROC_STATE_NO_EXIST);
  348.  
  349.    lNumProcs--;
  350.  
  351.    delete pclRunProc;
  352.  
  353.    C_RETURN
  354. }
  355.  
  356.  
  357. //
  358. //   MosScheduler
  359. //       
  360. //      This is the central workhorse function
  361. //
  362.  
  363. SHORT
  364. MOS_C::Scheduler(VOID)
  365. {
  366.    C_DEF_MODULE("MOS_C::Scheduler")
  367.    
  368.    PROC_P  pclProc;
  369.  
  370.    while(1)
  371.    {
  372.  
  373.       /* if only NULL proc is running, terminate */
  374.  
  375.       if(lNumProcs == 1)
  376.         break;
  377.  
  378.  
  379.       /*
  380.       **  Run check on all events
  381.       */
  382.  
  383.       C_STATUS = EventCheckList();
  384.  
  385.  
  386.       //
  387.       //  You may want to put a delay here or get a character from the
  388.       //  keyboard to see what Mos is doing on each iteration through
  389.       //  the code
  390.       //
  391.  
  392.       C_STATUS = CheckSleepQueue();
  393.  
  394.       C_STATUS = GetReadyProc(&pclProc);
  395.  
  396.       pclRunProc = pclProc;
  397.  
  398.       //
  399.       //  Invoke the process
  400.       //
  401.  
  402.       if(pclRunProc -> pBlockedFunc == NULL)
  403.      C_STATUS = (*pclRunProc -> pProc)(this,pclRunProc->GetWorkArea());
  404.       else
  405.      C_STATUS = (*pclRunProc -> pBlockedFunc)(this,pclRunProc->GetWorkArea());
  406.  
  407.  
  408.       //       The function   ^ ptr to MOS     ^ proc workarea
  409.    
  410.       //
  411.       //  If we were running the NULL process, then MUST put it back on the
  412.       //  ready queue.   An empty ready queue = system crash
  413.       //
  414.    
  415.       if(C_STATUS != PROC_STATE_NO_EXIST)
  416.       {
  417.      if(pclRunProc -> GetState() == PROC_STATE_RUNNING)
  418.         C_STATUS = ReschedReady(pclRunProc);
  419.       }
  420.            
  421.    }
  422.  
  423.    //
  424.    //  Some compilers will tell you that the next statement is unreachable,
  425.    //  That is ok.
  426.    //
  427.  
  428.    C_RETURN
  429. }
  430.  
  431.  
  432. //
  433. //  Mos CheckSleepQueue
  434. //    
  435. //      Check the sleep queue.  If anything there and is ready to be 
  436. //      waked-up, place on the ready queue
  437. //
  438.  
  439. SHORT
  440. MOS_C::CheckSleepQueue(VOID)
  441. {
  442.    C_DEF_MODULE("MOS_C::CheckSleepQueue")
  443.  
  444.    PROC_P    pclProc;
  445.  
  446.    while(1)
  447.    {
  448.       //
  449.       //  Loop to free all jobs which we can
  450.       //
  451.  
  452.       C_STATUS = clQueSleep.FindFirst((PVOID *) &pclProc);
  453.  
  454.       if(pclProc != NULL)
  455.       {
  456.      if(pclProc -> GetWakeTime() <= GetTime())
  457.          {
  458.             printf("Process %d: %s : Being awakened\n", pclProc -> GetId(),
  459.                                                         pclProc -> GetName());
  460.             //  Delete from Sleep list/queue
  461.    
  462.             C_STATUS = clQueSleep.DeleteCur();
  463.     
  464.             C_STATUS = ReschedReady(pclProc);
  465.          }
  466.          else 
  467.            break;
  468.       }
  469.       else
  470.          break;
  471.    }
  472.       
  473.    C_RETURN
  474. }
  475.  
  476.  
  477. //
  478. //   MosReschedReady
  479. //       
  480. //       Places a process on the ready queue
  481. //
  482.  
  483. SHORT
  484. MOS_C::ReschedReady(PROC_P pclProc)
  485. {
  486.    C_DEF_MODULE("MOS_C::ReschedReady")
  487.  
  488.    pclProc -> SetPrevState(pclProc -> GetState()); // save state
  489.    pclProc -> SetState(PROC_STATE_READY);          // set state
  490.    C_STATUS = clQueReady.Enq(pclProc -> GetPriority(),(PVOID) pclProc);
  491.  
  492. #ifdef ANNOUNCE
  493.    C_STATUS = ProcAnnounce(pclProc);
  494. #endif
  495.  
  496.    C_RETURN
  497. }
  498.  
  499.  
  500. //
  501. //  Mos GetReadyProc
  502. //
  503. //      It retrieves the process that should be run next from the ready queue
  504. //
  505.  
  506. SHORT
  507. MOS_C::GetReadyProc(PROC_P * ppclProc)
  508. {
  509.    C_DEF_MODULE("MOS_C::GetReadyProc")
  510.  
  511.    SHORT  sPriority;
  512.  
  513.    //
  514.    //  Get a process
  515.    //
  516.  
  517.    C_STATUS = clQueReady.Deq(&sPriority, (PVOID *) ppclProc);
  518.  
  519.    //
  520.    //  Set proc state to running
  521.    //
  522.  
  523.    (*ppclProc) -> SetState(PROC_STATE_RUNNING);
  524.  
  525. #ifdef ANNOUNCE
  526.    printf("\n");
  527.  
  528.    C_STATUS = ProcAnnounce(*ppclProc);
  529. #endif
  530.  
  531.    C_RETURN
  532. }
  533.  
  534.  
  535. //
  536. //  MosProcAnnounce
  537. //
  538. //       It is used for processes to announce when they have started running
  539. //
  540.  
  541. //SHORT
  542. //MOS_C::ProcAnnounce(PROC_P pclProc)
  543. //{
  544. //   C_DEF_MODULE("MOS_C::ProcAnnounce")
  545. //
  546. //   printf("Process %d: %s : Is %s\n",
  547. //           * pclProc -> GetProcId();
  548. //           * pclProc -> GetName(),
  549. //           szProcStates[pclProc -> sState]);
  550. //
  551. //   C_RETURN
  552. //}
  553.  
  554.  
  555. //
  556. //  MosNullProc
  557. //
  558. //       The Null Process
  559. //
  560.  
  561. SHORT
  562. MosNullProc(MOS_P pclMos,PVOID pvWorkArea)
  563. {
  564.    C_DEF_MODULE("MOS_C::NullProc")
  565.  
  566.    pvWorkArea = pvWorkArea;  // to keep compiler quiet
  567.    pclMos = pclMos;          // to keep compiler quiet
  568.  
  569. #ifdef ANNOUNCE
  570.    C_STATUS = ProcAnnounce();
  571. #endif
  572.  
  573.    //  If running under any multi-tasking/processing
  574.    //  operating system, sleep here so dont eat up CPU
  575.  
  576. #ifdef C_UNIX
  577.    sleep(1);
  578. #endif
  579.  
  580.    C_RETURN
  581. }
  582.  
  583.  
  584. //
  585. //  Semaphore
  586. //
  587.  
  588. //
  589. //  Mos  SemInit
  590. //
  591.  
  592. SEM_HANDLE
  593. MOS_C::SemInit(PCHAR pcSemName)
  594. {
  595.    C_DEF_VMODULE("MOS_C::SemInit")
  596.  
  597.    SEM_P   pclSem;
  598.    PVOID   pvTemp;
  599.    SEM_HANDLE  sRetSemHandle;
  600.  
  601.  
  602.    //  Check if exists already;
  603.  
  604.    clSemList.FindFirst((PVOID *) &pclSem);
  605.  
  606.    while(pclSem != NULL)
  607.    {
  608.        if(strcmp(pclSem -> GetName(),pcSemName) == 0)
  609.       return(pclSem -> GetHandle());
  610.    } 
  611.  
  612.    //  must be new one
  613.  
  614.    pclSem = new SEM_C;
  615.  
  616.    pclSem -> SetName(pcSemName);
  617.  
  618.    pclSem -> SetHandle(sSemHandle);
  619.  
  620.    sRetSemHandle = sSemHandle;
  621.  
  622.    sSemHandle++;   // inc global handle
  623.  
  624.    //  insert into list
  625.  
  626.    clSemList.FindLast(&pvTemp);
  627.  
  628.    clSemList.AddAfterCur((PVOID) pclSem);
  629.  
  630.    return(sRetSemHandle);
  631. }
  632.  
  633.  
  634. //
  635. //  Mos SemTerm
  636. //
  637.  
  638. SHORT
  639. MOS_C::SemTerm(SEM_HANDLE sSemHandle)
  640. {
  641.    C_DEF_MODULE("MOS_C::SemTerm")
  642.  
  643.    SEM_P   pclSem;
  644.    PVOID   pvTemp;
  645.    BOOL    fFound = C_FALSE;
  646.  
  647.    //  Check if exists already;
  648.  
  649.    clSemList.FindFirst((PVOID *) &pclSem);
  650.  
  651.    while(pclSem != NULL)
  652.    {
  653.        if(pclSem -> GetHandle() == sSemHandle)
  654.        {
  655.           fFound = C_TRUE;
  656.  
  657.       clSemList.DeleteCur();
  658.  
  659.           delete pclSem;
  660.  
  661.           break;
  662.        }
  663.    } 
  664.  
  665.    if(!fFound)
  666.      C_SET_STATUS(C_NOTOK)
  667.  
  668.    C_RETURN
  669. }
  670.  
  671. //
  672. //  Mos SemFindHandle
  673. //
  674.  
  675. VOID
  676. MOS_C::SemFindHandle(SEM_HANDLE sSemHandle, SEM_P * ppclSem, BOOL * pfFound)
  677. {
  678.    C_DEF_VMODULE("MOS_C::SemFindHandle")
  679.  
  680.    *pfFound = C_FALSE;
  681.  
  682.    //  Check if exists
  683.  
  684.    clSemList.FindFirst((PVOID *) ppclSem);
  685.  
  686.    while(*ppclSem != NULL)
  687.    {
  688.        if((*ppclSem) -> GetHandle() == sSemHandle)
  689.        {
  690.           *pfFound = C_TRUE;
  691.           break;
  692.        }
  693.    } 
  694. }
  695.  
  696.  
  697. //
  698. //  Mos SemNextProc
  699. //
  700.  
  701. VOID
  702. MOS_C::SemNextProc(SEM_P pclSem)
  703. {
  704.    C_DEF_MODULE("MOS_C::SemNextProc")
  705.  
  706.    LONG  lNumEntries;
  707.    PROC_P  pclReleasedProc;
  708.  
  709.    C_STATUS = pclSem -> clQueSemWait.GetEntries(&lNumEntries);
  710.  
  711.    if(lNumEntries != 0)
  712.    {  
  713.        //
  714.        //  Retrieve the process which was waiting for the semaphore
  715.        //
  716.  
  717.        C_STATUS = pclSem -> clQueSemWait.Deq((PVOID *) &pclReleasedProc);
  718.  
  719.        //
  720.        //  Place it back on the ready queue
  721.        //
  722.  
  723.        C_STATUS = ReschedReady(pclReleasedProc);
  724.  
  725.        //
  726.        //  Give it the semaphore
  727.        //
  728.  
  729.        C_STATUS = SemWait(pclSem -> GetHandle());
  730.     }
  731.  
  732.     C_SET_STATUS(C_STATUS)  // to make compiler be quiet
  733. }
  734.  
  735.  
  736.  
  737.  
  738. //
  739. //  Mos SemWait
  740. //
  741.  
  742. SHORT
  743. MOS_C::SemWait(SEM_HANDLE sSemHandle)
  744. {
  745.    C_DEF_MODULE("MOS_C::SemWait")
  746.  
  747.  
  748.    SEM_P   pclSem;
  749.    PVOID   pvTemp;
  750.    BOOL    fFound = C_FALSE;
  751.  
  752. #ifdef ANNOUNCE
  753.    printf("Process %d: %s : Requesting semaphore\n", 
  754.            pclRunProc -> GetId(), pclRunProc -> GetName());
  755. #endif
  756.  
  757.    SemFindHandle(sSemHandle,&pclSem,&fFound);
  758.  
  759.    if(fFound)
  760.    {
  761.       if(pclSem -> GetVal() != SEM_AVAIL)
  762.       {
  763. #ifdef ANNOUNCE
  764.       printf("Process %d: %s : Queued for semaphore\n", pclRunProc -> GetId(),
  765.                                                         pclRunProc -> GetName());
  766. #endif
  767.          //  Queue the process to wait for the semaphore
  768.  
  769.      pclSem -> clQueSemWait.Enq((PVOID) pclRunProc);
  770.  
  771.          pclRunProc -> SetState(PROC_STATE_SEM_WAIT);
  772.  
  773.      C_STATUS = PROC_STATE_SUSPENDED;
  774.       }
  775.       else
  776.       {
  777. #ifdef ANNOUNCE
  778.       printf("Process %d: %s : Obtained semaphore\n", pclRunProc -> GetId(),
  779.                                                       pclRunProc -> GetName());
  780. #endif
  781.  
  782.          pclSem -> SetVal(pclSem -> GetVal() + 1);
  783.      pclRunProc -> SetfCritical(C_TRUE);
  784.        }
  785.    }
  786.  
  787.    C_RETURN
  788. }
  789.  
  790.  
  791. //
  792. //  Sem Signal
  793. //
  794. //       Called by a process when it releases exclusive access to the 
  795. //       semaphore
  796. //
  797.  
  798. SHORT
  799. MOS_C::SemSignal(SEM_HANDLE sSemHandle)
  800. {
  801.    C_DEF_MODULE("MOS_C::SemSignal")
  802.  
  803.    SEM_P    pclSem;
  804.    BOOL     fFound;
  805.  
  806. #ifdef ANNOUNCE
  807.    printf("Process %d: %s : Releasing semaphore\n", pclRunProc -> GetId(),
  808.                                                     pclProc -> GetName());
  809. #endif
  810.    
  811.    pclRunProc -> SetfCritical(C_FALSE);
  812.  
  813.    SemFindHandle(sSemHandle,&pclSem,&fFound);
  814.  
  815.    if(fFound)
  816.    {
  817.       pclSem -> SetVal(pclSem -> GetVal() -1);
  818.  
  819.       SemNextProc(pclSem);
  820.    }
  821.  
  822.    C_RETURN
  823. }
  824.  
  825. //
  826. //  Sem Clear
  827. //
  828. //       Called by a process when it releases exclusive access to the 
  829. //       semaphore
  830. //
  831.  
  832. SHORT
  833. MOS_C::SemClear(SEM_HANDLE sSemHandle)
  834. {
  835.    C_DEF_MODULE("MOS_C::SemClear")
  836.  
  837.    SEM_P    pclSem;
  838.    BOOL     fFound;
  839.  
  840. #ifdef ANNOUNCE
  841.    printf("Process %d: %s : Clearing semaphore\n", pclRunProc -> GetId(),
  842.                                                    pclRunProc -> GetName());
  843. #endif
  844.    
  845.    pclRunProc -> SetfCritical(C_FALSE);
  846.  
  847.    SemFindHandle(sSemHandle,&pclSem,&fFound);
  848.  
  849.    if(fFound)
  850.    {
  851.       pclSem -> SetVal(SEM_AVAIL);
  852.  
  853.       SemNextProc(pclSem);
  854.    }
  855.  
  856.    C_RETURN
  857. }
  858.  
  859. //
  860. //  Mos SemSet
  861. //
  862.  
  863. SHORT
  864. MOS_C::SemSet(SEM_HANDLE sSemHandle)
  865. {
  866.    C_DEF_MODULE("MOS_C::SemSet")
  867.  
  868.  
  869.    SEM_P   pclSem;
  870.    PVOID   pvTemp;
  871.    BOOL    fFound = C_FALSE;
  872.  
  873. #ifdef ANNOUNCE
  874.    printf("Process %d: %s : Requesting semaphore\n", 
  875.            pclRunProc -> GetId(), pclRunProc -> GetName());
  876. #endif
  877.  
  878.    SemFindHandle(sSemHandle,&pclSem,&fFound);
  879.  
  880.    if(fFound)
  881.    {
  882. #ifdef ANNOUNCE
  883.       printf("Process %d: %s : Setting semaphore\n", pclRunProc -> GetId(),
  884.                                                      pclRunProc -> GetName());
  885. #endif
  886.  
  887.       pclSem -> SetVal(MOS_SEM_SET);
  888.    }
  889.  
  890.    C_RETURN
  891. }
  892.  
  893.  
  894. //
  895. //  MosCurTime
  896. //
  897. //       Mos function to get the current time
  898. //
  899.  
  900. LONG
  901. MOS_C::GetTime(VOID)
  902. {
  903.    time_t  lTime;
  904.  
  905.    time(&lTime);
  906.  
  907.    return((LONG) lTime);
  908. }
  909.  
  910.  
  911. //
  912. //   Mos Sleep
  913. //
  914. //       Called by a process to setup for sleeping
  915. //
  916.  
  917. SHORT
  918. MOS_C::Sleep(LONG lSecs)
  919. {
  920.    C_DEF_MODULE("MOS_C::Sleep")
  921.  
  922.    pclRunProc -> SetState(PROC_STATE_SLEEPING);
  923.  
  924.    pclRunProc -> SetWakeTime(GetTime() + lSecs);
  925.      
  926. #ifdef ANNOUNCE
  927.    printf("Process %d: %s : Sleeping till %d\n", pclProc -> GetId(),
  928.                                                  pclProc -> GetName(),
  929.                                                  pclProc -> GetWakeTime());
  930. #endif
  931.  
  932.    C_STATUS = clQueSleep.SetCompareFunc(MosCompareProcWakeTime);
  933.  
  934.    C_STATUS = clQueSleep.Insert((PVOID) pclRunProc);
  935.  
  936.    C_SET_STATUS(PROC_STATE_SUSPENDED)
  937.  
  938.    C_RETURN
  939. }
  940.  
  941.  
  942. //
  943. //   MosCompareProcId
  944. //
  945.  
  946. SHORT
  947. MosCompareProcId(PVOID pvData1,PVOID pvData2)
  948. {
  949.    PROC_P  pclProc1;
  950.    PROC_P  pclProc2;
  951.  
  952.  
  953.    pclProc1 = (PROC_P) pvData1;
  954.    pclProc2 = (PROC_P) pvData2;
  955.                             
  956.    if(pclProc1 -> GetId() == pclProc2 -> GetId())
  957.       return(C_EQUAL);
  958.    else if(pclProc1 -> GetId() < pclProc2 -> GetId())
  959.       return(C_LOWER);
  960.    else if(pclProc1 -> GetId() > pclProc2 -> GetId())
  961.       return(C_HIGHER);
  962.  
  963. }
  964.  
  965.  
  966. //
  967. //   MosCompareProcId
  968. //
  969.  
  970. SHORT
  971. MosCompareProcName(PVOID pvData1,PVOID pvData2)
  972. {
  973.    PROC_P  pclProc1;
  974.    PROC_P  pclProc2;
  975.  
  976.  
  977.    pclProc1 = (PROC_P) pvData1;
  978.    pclProc2 = (PROC_P) pvData2;
  979.                             
  980.    return(strcmp(pclProc1 -> GetName(),pclProc2 -> GetName()));
  981. }
  982.  
  983.  
  984.  
  985.  
  986. //
  987. //   MosMsgWrite
  988. //       
  989. //       Write a message (class) to a target process
  990. //
  991.  
  992. SHORT
  993. MOS_C::MsgWrite(MSG_P pclMsg)
  994. {
  995.    C_DEF_MODULE("MOS_C::MsgWrite")
  996.  
  997.    PROC_P   pclDestProc;
  998.    PROC_P   pclTempProc;
  999.    SHORT    sPid;
  1000.  
  1001. #ifdef ANNOUNCE
  1002.    printf("Process %d: %s : Sending message to procid %d\n", pclProc -> GetId(),
  1003.                                                              pclProc -> GetName(),
  1004.                                                              sTargetProcId);
  1005. #endif
  1006.  
  1007.    //
  1008.    //  Setup message for sending
  1009.    //
  1010.  
  1011.    pclMsg -> SetSendPid(pclRunProc -> GetId());
  1012.  
  1013.    //
  1014.    //  Find address of destination process
  1015.    //
  1016.  
  1017.    C_STATUS = clProcTree.SetCompareFunc(MosCompareIdNode);
  1018.  
  1019.    sPid = pclMsg -> GetDestPid();
  1020.  
  1021.    C_STATUS = clProcTree.Find((PVOID) &sPid, (PVOID *) &pclDestProc);
  1022.  
  1023.    if(pclDestProc != NULL)
  1024.    {
  1025.        C_STATUS = pclDestProc -> clMsgQue.Enq((PVOID) pclMsg);
  1026.  
  1027.        //
  1028.        //  Check if process was sleeping, if so, wake it up.
  1029.        //
  1030.        //  Remove it from the sleeping queue and place on ready queue
  1031.        //  
  1032.  
  1033.        if(pclDestProc -> GetState() == PROC_STATE_SLEEPING)
  1034.        {
  1035.  
  1036.        C_STATUS = clQueSleep.SetCompareFunc(MosCompareIdNode);
  1037.  
  1038.        sPid = pclDestProc -> GetId();
  1039.  
  1040.        C_STATUS = clQueSleep.Find((PVOID)   &sPid,
  1041.                       (PVOID *) &pclTempProc);
  1042.  
  1043.            C_STATUS = clQueSleep.DeleteCur();
  1044.  
  1045.            C_STATUS = ReschedReady(pclDestProc);
  1046.            
  1047.        }
  1048.  
  1049.        //
  1050.        //  Check if process was waiting on message, if so
  1051.        //  Remove it from the msg wait queue and place on ready queue
  1052.        //  
  1053.  
  1054.        if(pclDestProc -> GetState() == PROC_STATE_MSG_WAIT)
  1055.        {
  1056.  
  1057.        C_STATUS = clQueMsgWait.SetCompareFunc(MosCompareIdNode);
  1058.  
  1059.        sPid = pclDestProc -> GetId();
  1060.  
  1061.        C_STATUS = clQueMsgWait.Find((PVOID) &sPid,
  1062.                       (PVOID *) &pclTempProc);
  1063.  
  1064.            C_STATUS = clQueMsgWait.DeleteCur();
  1065.  
  1066.            C_STATUS = ReschedReady(pclDestProc);
  1067.            
  1068.        }
  1069.    }
  1070.  
  1071.    C_RETURN
  1072. }
  1073.  
  1074.  
  1075. //
  1076. //   Mos MsgWaiting
  1077. //
  1078.  
  1079. BOOL
  1080. MOS_C::MsgWaiting(VOID)
  1081. {
  1082.    C_DEF_VMODULE("MOS_C::MsgRead")
  1083.  
  1084.    LONG lEntries;
  1085.  
  1086.    pclRunProc -> clMsgQue.GetEntries(&lEntries);  // see if anything there
  1087.  
  1088.    if(lEntries)
  1089.       return((BOOL) C_TRUE);
  1090.    else
  1091.       return((BOOL) C_FALSE);
  1092. }
  1093.  
  1094. //
  1095. //   MosMsgRead
  1096. //
  1097. //       Read a message
  1098. //
  1099.  
  1100. SHORT
  1101. MOS_C::MsgRead(MSG_P ppclMsg)
  1102. {
  1103.    C_DEF_MODULE("MOS_C::MsgRead")
  1104.  
  1105.    LONG lEntries;
  1106.  
  1107.    pclRunProc -> clMsgQue.GetEntries(&lEntries);  // see if anything there
  1108.  
  1109.    if(lEntries)
  1110.    {
  1111.       C_STATUS = pclRunProc -> clMsgQue.Deq((PPVOID) ppclMsg);
  1112.    }
  1113.    else 
  1114.    {
  1115.       //
  1116.       //   Place in Msg Wait que (Added November 23, 1991)
  1117.       //
  1118.  
  1119.       pclRunProc -> SetState(PROC_STATE_MSG_WAIT);
  1120.  
  1121.       C_STATUS = clQueMsgWait.Insert((PVOID) pclRunProc);
  1122.  
  1123.       C_STATUS = PROC_STATE_SUSPENDED;
  1124.    }
  1125.  
  1126.    C_RETURN
  1127. }
  1128.  
  1129.  
  1130.  
  1131. /*
  1132. **   MosEventCheckList
  1133. **       
  1134. **       Check Event List
  1135. */
  1136.  
  1137. SHORT
  1138. MOS_C::EventCheckList(VOID)
  1139. {
  1140.    C_DEF_MODULE("MOS_C::EventCheckList")
  1141.  
  1142.    EVENT_P  pstEvent;
  1143.    
  1144.    if(sEvents == 0)
  1145.       C_LEAVE(C_OK);
  1146.  
  1147.    
  1148.    C_STATUS = pclEventList.FindFirst((PVOID *) &pstEvent);
  1149.  
  1150.    while(pstEvent != NULL)
  1151.    {
  1152.  
  1153.       /* check for event occurance */
  1154.  
  1155.       C_STATUS = (*(pstEvent -> pCheckFunc))();
  1156.   
  1157.       if(C_STATUS)
  1158.       {
  1159.          /* 
  1160.          **  if event occurred, place back on ready/run queue
  1161.          **  processes awaiting events may be of higher priority than
  1162.          **  normal processes
  1163.          */
  1164.          
  1165.          C_STATUS = ReschedReady(pstEvent->pclEventProc);
  1166.       }
  1167.  
  1168.       C_STATUS = pclEventList.GetNext((PVOID *) &pstEvent);
  1169.    }
  1170.  
  1171.  
  1172.    C_SET_STATUS(C_OK);
  1173.  
  1174.   
  1175. C_MODULE_EXIT:
  1176.  
  1177.    C_RETURN
  1178. }
  1179.