home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / diverses / text_cla / mos.c < prev    next >
Encoding:
Text File  |  1992-05-12  |  35.5 KB  |  1,726 lines

  1. /******************************************************************************
  2. *+
  3. ** Module Name:   MOS.C
  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. ** Written by:  John Tal
  14. **
  15. **
  16. **
  17. ** Modification History:
  18. **
  19. ** Date          Programmer      Mod#     Modification
  20. ** ---------------------------------------------------------------------------
  21. ** 04-JUL-1991   J. Tal          V1.0-000 New
  22. ** 01-DEC-1991   J. Tal          V2.0-000 New Version, enhanced semaphores,
  23. **                                        messaging, swapping control
  24. **    FEB-1992   J. Tal          V2.0-001 Revisions from C++ port.
  25. ** 25-APR-1992   J. Tal          V2.1-000 Event Procs
  26. **
  27. *-
  28. */
  29.  
  30.  
  31. /*
  32.  
  33.  
  34. Mos Revision Documentation
  35.  
  36.  
  37. VERSION 1.0-000
  38.  
  39.       Mos uses concepts which are familiar to various implementations of
  40.       multi-tasking operating systems.   It has a scheduler to select a
  41.       process (or job) to run from a list of waiting processes.   It has
  42.       inter-process-communication (IPC) and (currently) one semaphore.
  43.  
  44.       What it does not do is context switching.  Normally, when the
  45.       scheduler takes one job which was running and allows another
  46.       to have some cpu, it saves the current context of the process
  47.       which was running by saving the values of the important machine
  48.       (cpu) registers as used by the interrupted process.   When the
  49.       interrupted process is placed back in a running state, it has
  50.       no clue that it ever stopped running.   This version of Mos
  51.       does not perform context switching.   It simply services ready
  52.       processes (by priority order) and makes each process start at
  53.       the beginning of its code.
  54.  
  55.       Another major function of an operating system which is not 
  56.       implemented here is memory management.   This is management
  57.       not only of calloc, malloc, cfree, and free requests by
  58.       the applications, but it also deals with swapping inactive
  59.       applications out to disk until they run again.  This is
  60.       virtual memory management and is beyond the scope of the
  61.       humble goals of Mos.   
  62.  
  63.       The concepts used in Mos are a subset of any multi-tasking
  64.       operating system.   A recommended book for a detailed explanation
  65.       of the function of operating system design is 'Operating System
  66.       Design: The XINU Approach'  by Douglas Comer.  There is also
  67.       source code available in the public domain which implements XINU
  68.       on top of PcDos.   The source code is not recommended because
  69.       of serious mistakes made in the specific implemention of sitting
  70.       on top of dos (a non-multi-tasking operating system).  But the 
  71.       book is good reference material.
  72.  
  73.       Mos was written in a few hours on July 4, 1991 using the Brief 
  74.       editor and Microsoft C 5.1 on an AT clone.
  75.  
  76. VERSION 2.0-000
  77.  
  78.       The Moss name was changed to MOS for consistency with other members
  79.       of the Algorithms volumes.  The major changes/enhancements for this
  80.       version include:
  81.  
  82.                 o       Support of n-number of semaphores
  83.                         (1 was supported with v 1.0)
  84.  
  85.                 o       Enhanced messaging.  A process message waiting 
  86.                                queue is now supported.
  87.  
  88.                 o       Swap control is enhanced.   A process may
  89.                         specify exactly which function is to be
  90.                         called next when a process is swapped back
  91.                         into execution. 
  92.  
  93.      Version 2 is highly source code compatible with Version 1 and
  94.      most applications calling MOS will require only recompilation
  95.      and linking with Version 2 libraries.
  96.  
  97.      A number of weeks were spent working on a full-context swapping
  98.      implemention of MOS.  This involved using assembly language to
  99.      change the stack pointer as each process begins execution.
  100.      The current version of MOS has provided more than adequate 
  101.      execution and elementary multi-tasking in both DOS and UNIX
  102.      environments while maintaining the portability not possible
  103.      in assembly language.  If you are interested in extending MOS
  104.      into full context-swapping and/or interrept driven modes, there
  105.      is ample documentation in Dr. Dobbs Journal and C Users Group
  106.      magazines to do so.
  107.  
  108.  
  109. VERSION 2.0-001  C++ Port - February 1992
  110.  
  111.      The C++ port of MOS provided quite a number of suprises.
  112.      Once again, C++ has the ability to point out inefficiencies
  113.      in a seemingly effective design.  Specific tips which were
  114.      learned during the MOS port are provided in a document called
  115.      c_2_cpp.txt which is released with MOS on Volume 2 of the
  116.      Algorithms series.
  117.  
  118.  
  119. VERSION 2.1-000
  120.  
  121.       Event handling has been added to allow Mos to synchronize with
  122.       events outside of the Mos domain.  Mos event handling was tested
  123.       by assigning one Mos event to the serial port and another to the
  124.       keyboard and thereby creating a multi-tasking telecommunications
  125.       program.
  126.  
  127. */
  128.  
  129.  
  130. #ifdef C_ANSI
  131. #include <string.h>
  132. #include <stdlib.h>
  133. #endif
  134.  
  135. #include <stdio.h>
  136.  
  137. #include <sys/types.h>
  138. #include <memlib.h>
  139. #include <time.h>
  140.  
  141. #include <mos.h>
  142.  
  143.  
  144. /*
  145. **  MOS Defines
  146. */
  147.  
  148. #define  QUE_EMPTY(head) ((head) == NULL)
  149.  
  150.  
  151.  
  152.  
  153. CHAR     szProcStates[PROC_STATE_MSG_WAIT + 1][32] = 
  154.          { "Non Existant",
  155.            "Running",
  156.            "Ready",
  157.            "Sleeping",
  158.            "Waiting on Semaphore",
  159.            "Waiting on Message" };
  160.  
  161. #define  PROC_MAX_PROCS   16       /* 16 processes maximum */
  162.  
  163.  
  164. #include  <mos.h>
  165.  
  166.  
  167. /*
  168. **   Moss Variables
  169. */
  170.  
  171.    CHAR    fMosInitialized = C_FALSE;
  172.  
  173.    LONG    glNumProcs = 0;
  174.  
  175.    CHAR    fMosMemInit = C_FALSE;
  176.  
  177. /*
  178. **   Master counter for process ids
  179. */
  180.  
  181.    SHORT    sProcId = 0;   
  182.  
  183. /*
  184. **   There can only be one currently running process
  185. */
  186.  
  187.    PROC_P   pstRunProc;
  188.  
  189. /*
  190. **    Use a binary tree to track all processes
  191. **    This tree ordered by Process Name
  192. */
  193.  
  194.    TNODE_P   pstProcNameTree;
  195.  
  196.  
  197. /*
  198. **    Use a linked-list to track all processes by proc id
  199. */
  200.  
  201.    LLIST_P   pstProcIdList;
  202.  
  203.  
  204. /*
  205. **   The Ready Queue is ordered by priority so it is a heap
  206. */
  207.    
  208.    HEAP_P   pstQueReady;
  209.  
  210.  
  211. /*
  212. **    The Sleep Queue is ordered by wake-up time so can be a linked-list
  213. */
  214.  
  215.    LLIST_P  pstQueSleep;
  216.  
  217.  
  218. /*
  219. **    The Msg Wait Queue is ordered by priority.  But since we cant predict
  220. **    the order of events which waiting processes are waiting for, we
  221. **    will make it a linked-list for maximum flexibility.
  222. */
  223.  
  224.    LLIST_P  pstQueMsgWait;
  225.  
  226.  
  227.  
  228. /*    The Global Event List
  229. **
  230. */
  231.  
  232.    LLIST_P  pstEventList;
  233.  
  234.    SHORT    sEvents = 0;
  235.  
  236.  
  237.  
  238. /*
  239. **   Semaphore Control Data
  240. */
  241.  
  242.                                                                                       
  243.    
  244. #define  SEM_AVAIL  0
  245.  
  246.     SEM_P  pstSems;
  247.  
  248.  
  249. /*
  250. **  Init Moss Environment
  251. */
  252.  
  253. #ifdef C_ANSI
  254. SHORT
  255. MosInit(VOID)
  256. #else
  257. SHORT  MosInit()
  258. #endif
  259. {
  260.    C_DEF_MODULE("MosInit")
  261.    
  262.    INT  i;
  263.  
  264.  
  265.    fMosInitialized = C_TRUE;
  266.  
  267.    /*
  268.    **  Set up main data stores
  269.    */
  270.  
  271.    pstProcNameTree = NULL;
  272.  
  273.    pstProcIdList = NULL;
  274.  
  275.    pstQueSleep = NULL;
  276.  
  277.    pstQueMsgWait = NULL;
  278.  
  279.    pstSems = NULL;
  280.  
  281.    /*
  282.    **  Init semaphores
  283.    */
  284.  
  285.    pstSems = (SEM_P) calloc(MOS_MAX_SEMS,sizeof(SEM_T));
  286.  
  287.       
  288.    for(i = 0; i < MOS_MAX_SEMS; i++)
  289.    {
  290.       pstSems[i].fInUse = (CHAR) C_FALSE;
  291.       pstSems[i].sVal = SEM_AVAIL;
  292.    }
  293.    
  294.  
  295.    /*
  296.    **  Any heaps must be initialized before use, trees and linked list
  297.    **  families will do with a simple  = NULL, but not heaps, like the
  298.    **  ready queue
  299.    */
  300.  
  301.    C_STATUS = MemHepInit(&pstQueReady,PROC_MAX_PROCS);
  302.  
  303.  
  304.    /*
  305.    **  Must always have a process on the ready queue, the NULL process
  306.    **  does nothing.   In operating systems, nothing else can EVER
  307.    **  have access to the NULL process or the swapper process.
  308.    **  Noone or nothing can kill them or the system dies.
  309.    */
  310.  
  311.    C_STATUS = MosProcCreate(MosNullProc,"NULL_PROC",0);
  312.  
  313.  
  314.    C_RETURN
  315. }
  316.  
  317.  
  318. /*
  319. **  MosCompareProcId
  320. **
  321. **      Use for node to node comparision of binary tree, for MemTreInsertNode
  322. */
  323.  
  324. #ifdef C_ANSI
  325. SHORT
  326. MosCompareProcId(PVOID pvData1,PVOID pvData2)
  327. #else
  328. SHORT
  329. MosCompareProcId(pvData1,pvData2)
  330. PVOID pvData1;
  331. PVOID pvData2;
  332. #endif
  333. {
  334.    PROC_P   pstProc1;
  335.    PROC_P   pstProc2;
  336.  
  337.    pstProc1 = (PROC_P) pvData1;
  338.    pstProc2 = (PROC_P) pvData2;
  339.  
  340.    if(pstProc1 -> sProcId == pstProc2 -> sProcId)
  341.       return(C_EQUAL);
  342.    else if(pstProc1 -> sProcId < pstProc2 -> sProcId)
  343.       return(C_LOWER);
  344.    else
  345.       return(C_HIGHER);
  346. }
  347.  
  348. /*
  349. **  MosCompareProcName2
  350. **
  351. **      Use for node to node comparision of binary tree, for MemTreInsertNode
  352. */
  353.  
  354. #ifdef C_ANSI
  355. SHORT
  356. MosCompareProcName2(PVOID pvData1,PVOID pvData2)
  357. #else
  358. SHORT
  359. MosCompareProcName2(pvData1,pvData2)
  360. PVOID pvData1;
  361. PVOID pvData2;
  362. #endif
  363. {
  364.    PCHAR    pc1;
  365.    PROC_P   pstProc2;
  366.  
  367.    pc1 = (PCHAR) pvData1;
  368.    pstProc2 = (PROC_P) pvData2;
  369.  
  370.    return(strcmp(pc1,pstProc2 -> szName));
  371. }
  372.  
  373.  
  374. /*
  375. **  MosCompareProcName
  376. **
  377. **      Use for node to node comparision of binary tree, for MemTreInsertNode
  378. */
  379.  
  380. #ifdef C_ANSI
  381. SHORT
  382. MosCompareProcName(PVOID pvData1,PVOID pvData2)
  383. #else
  384. SHORT
  385. MosCompareProcName(pvData1,pvData2)
  386. PVOID pvData1;
  387. PVOID pvData2;
  388. #endif
  389. {
  390.    PROC_P   pstProc1;
  391.    PROC_P   pstProc2;
  392.  
  393.    pstProc1 = (PROC_P) pvData1;
  394.    pstProc2 = (PROC_P) pvData2;
  395.  
  396.    return(strcmp(pstProc1 -> szName,pstProc2 -> szName));
  397. }
  398.  
  399.  
  400.  
  401.  
  402. /*
  403. **    Create a new process = init and place on ready queue
  404. */
  405.  
  406. #ifdef C_ANSI
  407. SHORT
  408. MosProcCreate(SHORT (*pProc)(), PCHAR szProcName, SHORT sPriority)
  409. #else
  410. SHORT
  411. MosProcCreate(pProc,szProcName,sPriority)
  412. SHORT (*pProc)();
  413. PCHAR szProcName;
  414. SHORT sPriority;
  415. #endif
  416. {
  417.    C_DEF_MODULE("MosProcCreate")
  418.  
  419.  
  420.    PROC_P   pstProc;
  421.  
  422.  
  423.  
  424.    MosProcInit(pProc,szProcName,sPriority,&pstProc);
  425.  
  426.  
  427.    /*
  428.    **  Place this process on the ready queue
  429.    */
  430.  
  431.    C_STATUS = MosReschedReady(pstProc);
  432.  
  433.  
  434.    C_RETURN
  435. }
  436.  
  437. /*
  438. **   Internal call to init a new process
  439. */
  440.  
  441. #ifdef C_ANSI
  442. SHORT
  443. MosProcInit(SHORT (*pProc)(), PCHAR szProcName, SHORT sPriority, PROC_P * ppstProc)
  444. #else
  445. SHORT
  446. MosProcInit(pProc,szProcName,sPriority,ppstProc)
  447. SHORT (*pProc)();
  448. PCHAR szProcName;
  449. SHORT sPriority;
  450. PROC_P * ppstProc;
  451. #endif
  452. {
  453.    C_DEF_MODULE("MosProcCreate")
  454.  
  455.    TNODE_P  pstNode;
  456.    LLIST_P  pstMember;
  457.    PROC_P   pstProc;
  458.  
  459.  
  460.    if(!fMosInitialized)
  461.    {
  462.       printf("Error:  Mos has not been initialized via MosInit()\n");
  463.       exit(1);
  464.    }
  465.  
  466.    pstProc = (PROC_P) calloc(1,sizeof(PROC_T));
  467.  
  468.    pstProc -> sPriority = sPriority;        /* set priority */
  469.    strcpy(pstProc -> szName, szProcName);   /* set name */
  470.    pstProc -> sProcId = sProcId;            /* set proc id */
  471.    sProcId++;                               /* inc global proc id */ 
  472.    glNumProcs++;
  473.  
  474.    pstProc -> sState = PROC_STATE_READY;    /* It is ready */
  475.    pstProc -> sPrevState = PROC_STATE_NO_EXIST;  /* no prvious state */
  476.    pstProc -> pProc = pProc;                /* Point to proc to run */
  477.    pstProc -> pBlockedFunc = NULL;
  478.  
  479.    /*
  480.    **   Store this process in the global process tree
  481.    */
  482.  
  483.    C_STATUS = MemTreAllocNode(&pstNode);
  484.  
  485.    pstNode -> pvData = (PVOID) pstProc;
  486.  
  487.    C_STATUS = MemTreInsertNode(pstProcNameTree,
  488.                                pstNode,
  489.                                MosCompareProcName,
  490.                                &pstProcNameTree);
  491.  
  492.  
  493.    /*
  494.    **   Create member for process tracking by id 
  495.    */
  496.  
  497.    C_STATUS = MemLstAllocMember(&pstMember);
  498.  
  499.    pstMember -> pvData = (PVOID) pstProc;
  500.  
  501.    C_STATUS = MemLstInsertMember(pstProcIdList,
  502.                                  pstMember,
  503.                                  MosCompareProcId,
  504.                                  &pstProcIdList);
  505.  
  506.  
  507.  
  508.    *ppstProc = pstProc;
  509.  
  510.    C_RETURN
  511. }
  512.  
  513.  
  514. /*
  515. **    Terminate a Process
  516. */
  517.  
  518. #ifdef C_ANSI
  519. SHORT
  520. MosProcTerm(PROC_P pProc)
  521. #else
  522. SHORT
  523. MosProcTerm(pProc)
  524. PROC_P pProc;
  525. #endif
  526. {
  527.    C_DEF_MODULE("MosProcTerm")
  528.  
  529.    LLIST_P  pstList;
  530.  
  531.  
  532.    C_STATUS = MemTreDeleteNode(pstProcNameTree,
  533.                                (PVOID) pProc,
  534.                                MosCompareProcName,
  535.                                &pstProcNameTree);
  536.  
  537.    C_STATUS = MemLstFindMember(pstProcIdList,
  538.                                (PVOID) pProc,
  539.                                MosCompareProcName,
  540.                                &pstList);
  541.  
  542.    C_STATUS = MemLstDeleteMember(pstProcIdList,
  543.                                  pstList,
  544.                                  &pstProcIdList);
  545.  
  546.    pProc -> sState = PROC_STATE_NO_EXIST;   
  547.  
  548.    free(pProc);
  549.  
  550.    glNumProcs--;
  551.  
  552.    C_SET_STATUS(PROC_STATE_NO_EXIST);
  553.  
  554.    C_RETURN
  555.  
  556. }
  557.  
  558.  
  559. /*
  560. **   MosScheduler
  561. **       
  562. **       This is the central workhorse function
  563. */
  564.  
  565. #ifdef C_ANSI
  566. SHORT
  567. MosScheduler(VOID)
  568. #else
  569. SHORT
  570. MosScheduler()
  571. #endif
  572. {
  573.    C_DEF_MODULE("MosScheduler")
  574.  
  575.    
  576.    PROC_P  pstProc;
  577.  
  578.  
  579.    if(!fMosInitialized)
  580.    {
  581.       printf("Error:  Mos has not been initialized via MosInit()\n");
  582.       exit(1);
  583.    }
  584.  
  585.    while(1)
  586.    {
  587.  
  588.       /* if only NULL proc is running, terminate */
  589.  
  590.       if(glNumProcs == 1)
  591.         break;
  592.  
  593.  
  594.       /*
  595.       **  Run check on all events
  596.       */
  597.  
  598.       C_STATUS = MosEventCheckList();
  599.  
  600.  
  601.       /*
  602.       **  You may want to put a delay here or get a character from the
  603.       **  keyboard to see what Moss is doing on each iteration through
  604.       **  the code
  605.       */
  606.  
  607.       C_STATUS = MosCheckSleepQueue();
  608.  
  609.       C_STATUS = MosGetReadyProc(&pstProc);
  610.  
  611.       pstRunProc = pstProc;
  612.  
  613.       /*
  614.       **  Invoke the process
  615.       **
  616.       **  In a real multi-tasking operating system, the cpu would be restored
  617.       **  with the code segment and instruction pointer of the process where
  618.       **  execution should resume.   To simulate that, we call the function
  619.       **  which represents the process (essentially restarting the process) 
  620.       **  and it's up to the function to pick-up where it left off
  621.       */
  622.    
  623.       if(pstProc -> pBlockedFunc != NULL)
  624.          C_STATUS = (*(pstProc -> pBlockedFunc))(pstProc -> pvWorkArea);    
  625.       else   
  626.          C_STATUS = (*(pstProc -> pProc))(pstProc);    
  627.    
  628.    
  629.       /*
  630.       **  If we were running the NULL process, then MUST put it back on the
  631.       **  ready queue.   An empty ready queue = system crash
  632.       **
  633.       **  Also, if last process is still in running state, requeue back
  634.       **  to ready queue.
  635.       */
  636.    
  637.       if(C_STATUS != PROC_STATE_NO_EXIST)
  638.       {
  639.          if(pstProc -> sState == PROC_STATE_RUNNING)
  640.             C_STATUS = MosReschedReady(pstProc);
  641.       }
  642.            
  643.    }
  644.  
  645.    /*
  646.    **  Some compilers will tell you that the next statement is unreachable,
  647.    **  That is ok.
  648.    */
  649.  
  650.    C_RETURN
  651. }
  652.  
  653.  
  654. /*
  655. **  MosCheckSleepQueue
  656. **    
  657. **       Check the sleep queue.  If anything there and is ready to be 
  658. **       waked-up, place on the ready queue
  659. */
  660.  
  661. #ifdef C_ANSI
  662. SHORT
  663. MosCheckSleepQueue(VOID)
  664. #else
  665. SHORT
  666. MosCheckSleepQueue()
  667. #endif
  668. {
  669.    C_DEF_MODULE("MosCheckSleepQueue")
  670.  
  671.    LLIST_P   pstList;
  672.    PROC_P    pstProc;
  673.  
  674.  
  675.    while(1)
  676.    {
  677.       /*
  678.       **  Loop to free all jobs which we can
  679.       */
  680.  
  681.       if(!QUE_EMPTY(pstQueSleep))
  682.       {
  683.          pstList = pstQueSleep;
  684.    
  685.          pstProc = (PROC_P) pstList -> pvData;
  686.    
  687.          if(pstProc -> lWakeTime <= MosCurTime())
  688.          {
  689.  
  690. #ifdef ANNOUNCE
  691.             printf("Process %d: %s : Being awakened\n", pstProc -> sProcId,
  692.                                                         pstProc -> szName);
  693. #endif
  694.  
  695.             /*
  696.             **  This direct access to the linked list and assigning
  697.             **  it to the next member is legal.  It wont be possible to
  698.             **  do this in C++.  Would have to do a delete using the
  699.             **  process name or id as a key.   Whats here works for now.
  700.             */
  701.  
  702.             pstQueSleep = pstQueSleep -> psNext;
  703.              
  704.             free(pstList);
  705.    
  706.             C_STATUS = MosReschedReady(pstProc);
  707.          }
  708.          else 
  709.            break;
  710.       }
  711.       else
  712.          break;
  713.  
  714.    }
  715.       
  716.    C_RETURN
  717. }
  718.  
  719.  
  720.  
  721. /*
  722. **   MosReschedReady
  723. **       
  724. **       Places a process on the ready queue
  725. */
  726.  
  727. #ifdef C_ANSI
  728. SHORT
  729. MosReschedReady(PROC_P pstProc)
  730. #else
  731. SHORT
  732. MosReschedReady(pstProc)
  733. PROC_P pstProc;
  734. #endif
  735. {
  736.    C_DEF_MODULE("MosReschedReady")
  737.  
  738.    pstProc -> sPrevState = pstProc -> sState;
  739.  
  740.    pstProc -> sState = PROC_STATE_READY;    /* mark as ready */
  741.  
  742.    C_STATUS = MemHepEnque(pstQueReady,
  743.                           pstProc -> sPriority,
  744.                           (PVOID) pstProc);
  745.  
  746.    C_STATUS = MosProcAnnounce(pstProc);
  747.  
  748.    C_RETURN
  749. }
  750.  
  751.  
  752. /*
  753. **  MosGetReadyProc
  754. **
  755. **       It retrieves the process that should be run next from the ready queue
  756. */
  757.  
  758. #ifdef C_ANSI
  759. SHORT
  760. MosGetReadyProc(PROC_P * ppstProc)
  761. #else
  762. SHORT
  763. MosGetReadyProc(ppstProc)
  764. PROC_P * ppstProc;
  765. #endif
  766. {
  767.    C_DEF_MODULE("MosGetReadyProc")
  768.  
  769.    SHORT  sPriority;
  770.  
  771.    /*
  772.    **  Get a process
  773.    */
  774.  
  775.    C_STATUS = MemHepDeque(pstQueReady,
  776.                           &sPriority,
  777.                           (PVOID *) ppstProc);
  778.  
  779.  
  780.    /*
  781.    **  Set proc state to running
  782.    */
  783.  
  784.    (*ppstProc) -> sState = PROC_STATE_RUNNING;
  785.  
  786. #ifdef ANNOUNCE
  787.    printf("\n");
  788. #endif
  789.  
  790.    C_STATUS = MosProcAnnounce(*ppstProc);
  791.  
  792.    C_RETURN
  793. }
  794.  
  795. /*
  796. **  MosProcAnnounce
  797. **
  798. **       It is used for processes to announce when they have started running
  799. */
  800.  
  801. #ifdef C_ANSI
  802. SHORT
  803. MosProcAnnounce(PROC_P pstProc)
  804. #else
  805. SHORT
  806. MosProcAnnounce(pstProc)
  807. PROC_P pstProc;
  808. #endif
  809. {
  810.    C_DEF_MODULE("MosProcAnnounce")
  811.  
  812. #ifdef ANNOUNCE
  813.    printf("Process %d: %s : Is %s\n", 
  814.            pstProc -> sProcId,
  815.            pstProc -> szName,
  816.            szProcStates[pstProc -> sState]);
  817. #else
  818.    pstProc = pstProc;            /* silence compiler */
  819. #endif
  820.  
  821.    C_RETURN
  822. }
  823.  
  824. /*
  825. **  MosNullProc
  826. **
  827. **       The Null Process
  828. **
  829. **  Note:  If implementing on top of a 'real' multi-tasking operating system
  830. **         (e.g. Unix, OS/2, VMS), this process should sleep() for around
  831. **         1 or more seconds.  If it did nothing as it currently does,
  832. **         it would eat up the cpu.
  833. */
  834.  
  835. #ifdef C_ANSI
  836. SHORT
  837. MosNullProc(PROC_P pstProc)
  838. #else
  839. SHORT
  840. MosNullProc(pstProc)
  841. PROC_P pstProc;
  842. #endif
  843. {
  844.    C_DEF_MODULE("NullProc")
  845.  
  846.    C_STATUS = MosProcAnnounce(pstProc);
  847.  
  848. #ifdef C_UNIX
  849.         sleep(1);
  850. #endif
  851.  
  852.    C_RETURN
  853. }
  854.  
  855. /*
  856. **  MosSemInit
  857. **
  858. **       Called to initialize a new semaphore
  859. */
  860.  
  861. #ifdef C_ANSI
  862. SHORT
  863. MosSemInit(PROC_P pstProc,PCHAR pcSemName,PSHORT psSemHandle)
  864. #else
  865. SHORT
  866. MosSemInit(pstProc,pcSemName,psSemHandle)
  867. PROC_P pstProc;
  868. PCHAR  pcSemName;
  869. PSHORT psSemHandle;
  870. #endif
  871. {
  872.    C_DEF_MODULE("MosSemInit")
  873.  
  874.    SHORT   i;
  875.    CHAR    fDone = C_FALSE;
  876.    SHORT   iUseSlot;
  877.  
  878.    pstProc = pstProc;                /* silence compiler warning */
  879.  
  880.    for(i = 0; i < MOS_MAX_SEMS; i++)
  881.    {
  882.       if(strcmp(pcSemName,pstSems[i].szSemName) == 0)
  883.       {
  884.          *psSemHandle = i;
  885.  
  886.          /*
  887.          **  Is not already initialized, then do so
  888.          */
  889.  
  890.          if(!pstSems[i].fInUse)
  891.          {
  892.             pstSems[i].sVal = SEM_AVAIL;
  893.             pstSems[i].fInUse = C_TRUE;
  894.             fDone = C_TRUE;
  895.          }
  896.          break;
  897.        }
  898.        
  899.        if(!pstSems[i].fInUse)
  900.        {
  901.           iUseSlot = i;
  902.        }
  903.  
  904.     }
  905.  
  906.     if(!fDone)
  907.     {
  908.       if(iUseSlot != -1)
  909.       {
  910.          strcpy(pstSems[iUseSlot].szSemName,pcSemName);
  911.          pstSems[iUseSlot].fInUse = C_TRUE;
  912.          *psSemHandle = iUseSlot;
  913.          fDone = C_TRUE;
  914.       }
  915.     }
  916.  
  917.     if(!fDone)
  918.       *psSemHandle = -1;
  919.  
  920.  
  921.     C_RETURN
  922. }
  923.  
  924.  
  925. /*
  926. **  MosSemTerm
  927. **
  928. **     
  929. **  
  930. */
  931.  
  932. #ifdef C_ANSI
  933. SHORT
  934. MosSemTerm(PROC_P pstProc,PCHAR pcSemName,SHORT sSemHandle)
  935. #else
  936. SHORT
  937. MosSemTerm(pstProc,pcSemName,sSemHandle)
  938. PROC_P pstProc;
  939. PCHAR pcSemName;
  940. SHORT sSemHandle;
  941. #endif
  942. {
  943.    C_DEF_MODULE("MosSemTerm")
  944.  
  945.    pstProc = pstProc;               /* silence compiler */
  946.  
  947.    if(sSemHandle < MOS_MAX_SEMS)
  948.    {
  949.      if(strcmp(pcSemName,pstSems[sSemHandle].szSemName) == 0)
  950.      {
  951.          pstSems[sSemHandle].fInUse = C_FALSE;
  952.      }
  953.    }
  954.  
  955.    C_RETURN
  956. }
  957.  
  958.        
  959.  
  960.  
  961. /*
  962. **  MosSemWait
  963. **
  964. **       Called by a process when it wants exclusive ownership
  965. **       of a semaphore
  966. */
  967.  
  968. #ifdef C_ANSI
  969. SHORT
  970. MosSemWait(PROC_P pstProc,SHORT sSemHandle)
  971. #else
  972. SHORT
  973. MosSemWait(pstProc,sSemHandle)
  974. PROC_P pstProc;
  975. SHORT sSemHandle;
  976. #endif
  977. {
  978.    C_DEF_MODULE("MosSemWait")
  979.  
  980. #ifdef ANNOUNCE
  981.    printf("Process %d: %s : Requesting semaphore %s\n", pstProc -> sProcId,
  982.                                                         pstProc -> szName,
  983.                                                         pstSems[sSemHandle].szSemName);
  984. #endif
  985.  
  986.    if(pstSems[sSemHandle].sVal != SEM_AVAIL)
  987.    {
  988.  
  989. #ifdef ANNOUNCE
  990.       printf("Process %d: %s : Queued for semaphore\n", pstProc -> sProcId,
  991.                                                         pstProc -> szName);
  992. #endif
  993.  
  994.       C_STATUS = MemQueEnqMember(&pstSems[sSemHandle].pstQueHead,
  995.                                  &pstSems[sSemHandle].pstQueTail,
  996.                                  (PVOID) pstProc);
  997.  
  998.       pstProc -> sState = PROC_STATE_SEM_WAIT;
  999.  
  1000.       C_STATUS = MOS_PROC_SUSPEND;
  1001.  
  1002.    }
  1003.    else
  1004.    {
  1005.  
  1006. #ifdef ANNOUNCE
  1007.       printf("Process %d: %s : Obtained semaphore\n", pstProc -> sProcId,
  1008.                                                       pstProc -> szName);
  1009. #endif
  1010.  
  1011.  
  1012.       pstSems[sSemHandle].sVal++;
  1013.       pstProc -> fCritical = C_TRUE;  /* set to critical so will not swap and complete operation */
  1014.    }
  1015.  
  1016.  
  1017.    C_RETURN
  1018. }
  1019.  
  1020.  
  1021. /*
  1022. **  MosSemClear
  1023. **
  1024. **       Called by a process to clear a semaphore
  1025. **       Semaphore is then available for next process
  1026. */
  1027.  
  1028. #ifdef C_ANSI
  1029. SHORT
  1030. MosSemClear(PROC_P pstProc,SHORT sSemHandle)
  1031. #else
  1032. SHORT
  1033. MosSemClear(pstProc,sSemHandle)
  1034. PROC_P pstProc;
  1035. SHORT sSemHandle;
  1036. #endif
  1037. {
  1038.    C_DEF_MODULE("MosSemClear")
  1039.  
  1040.    PROC_P   pstReleasedProc;
  1041.  
  1042.  
  1043. #ifdef ANNOUNCE
  1044.    printf("Process %d: %s : Clearing semaphore %s\n", pstProc -> sProcId,
  1045.                                                       pstProc -> szName,
  1046.                                                       pstSems[sSemHandle].szSemName);
  1047. #endif
  1048.  
  1049.    pstProc = pstProc;         /* silence compiler */
  1050.   
  1051.    pstSems[sSemHandle].sVal = SEM_AVAIL;
  1052.  
  1053.    if(!QUE_EMPTY(pstSems[sSemHandle].pstQueHead))
  1054.    {
  1055.  
  1056.       /*
  1057.       **  Retrieve the process which was waiting for the semaphore
  1058.       */
  1059.  
  1060.       C_STATUS = MemQueDeqMember(&pstSems[sSemHandle].pstQueHead,
  1061.                                  &pstSems[sSemHandle].pstQueTail,
  1062.                                  (PVOID *) &pstReleasedProc);
  1063.  
  1064.       /*
  1065.       **  Give it the semaphore
  1066.       */
  1067.  
  1068.       C_STATUS = MosSemWait(pstReleasedProc,sSemHandle);
  1069.  
  1070.  
  1071.       /*
  1072.       **  Place it back on the ready queue
  1073.       */
  1074.  
  1075.       C_STATUS = MosReschedReady(pstReleasedProc);
  1076.    }
  1077.  
  1078.    C_RETURN
  1079. }
  1080.  
  1081.  
  1082. /*
  1083. **  MosSemSet
  1084. **
  1085. */
  1086.  
  1087. #ifdef C_ANSI
  1088. SHORT
  1089. MosSemSet(PROC_P pstProc,SHORT sSemHandle)
  1090. #else
  1091. SHORT
  1092. MosSemSet(pstProc,sSemHandle)
  1093. PROC_P pstProc;
  1094. SHORT sSemHandle;
  1095. #endif
  1096. {
  1097.    C_DEF_MODULE("MosSemSet")
  1098.  
  1099.  
  1100. #ifdef ANNOUNCE
  1101.    printf("Process %d: %s : Setting semaphore %s\n", pstProc -> sProcId,
  1102.                                                      pstProc -> szName,
  1103.                                                      pstSems[sSemHandle].szSemName);
  1104. #endif
  1105.  
  1106.    pstProc = pstProc;             /* silence compiler */
  1107.  
  1108.    pstSems[sSemHandle].sVal = 1;
  1109.  
  1110.    C_RETURN
  1111. }
  1112.  
  1113.  
  1114. /*
  1115. **  MosSemSignal
  1116. **
  1117. **       Called by a process when it releases exclusive access to
  1118. **       a semaphore
  1119. */
  1120.  
  1121. #ifdef C_ANSI
  1122. SHORT
  1123. MosSemSignal(PROC_P pstProc,SHORT sSemHandle)
  1124. #else
  1125. SHORT
  1126. MosSemSignal(pstProc,sSemHandle)
  1127. PROC_P pstProc;
  1128. SHORT sSemHandle;
  1129. #endif
  1130. {
  1131.    C_DEF_MODULE("MosSemSignal")
  1132.  
  1133.    PROC_P   pstReleasedProc;
  1134.  
  1135. #ifdef ANNOUNCE
  1136.    printf("Process %d: %s : Releasing semaphore %s\n", pstProc -> sProcId,
  1137.                                                        pstProc -> szName,
  1138.                                                        pstSems[sSemHandle].szSemName);
  1139. #endif
  1140.  
  1141.    
  1142.    pstProc -> fCritical = C_FALSE;
  1143.  
  1144.    pstSems[sSemHandle].sVal--;
  1145.  
  1146.    if(!QUE_EMPTY(pstSems[sSemHandle].pstQueHead))
  1147.    {
  1148.  
  1149.       /*
  1150.       **  Retrieve the process which was waiting for the semaphore
  1151.       */
  1152.  
  1153.       C_STATUS = MemQueDeqMember(&pstSems[sSemHandle].pstQueHead,
  1154.                                  &pstSems[sSemHandle].pstQueTail,
  1155.                                  (PVOID *) &pstReleasedProc);
  1156.  
  1157.       /*
  1158.       **  Give it the semaphore
  1159.       */
  1160.  
  1161.       C_STATUS = MosSemWait(pstReleasedProc,sSemHandle);
  1162.  
  1163.  
  1164.       /*
  1165.       **  Place it back on the ready queue
  1166.       */
  1167.  
  1168.       C_STATUS = MosReschedReady(pstReleasedProc);
  1169.    }
  1170.  
  1171.  
  1172.    C_RETURN
  1173. }
  1174.  
  1175.  
  1176. /*
  1177. **  MosCurTime
  1178. **
  1179. **       Mos function to get the current time
  1180. */
  1181.  
  1182. #ifdef C_ANSI
  1183. LONG
  1184. MosCurTime(VOID)
  1185. #else
  1186. LONG
  1187. MosCurTime()
  1188. #endif
  1189. {
  1190.    time_t  lTime;
  1191.  
  1192.    time(&lTime);
  1193.  
  1194.    return((LONG) lTime);
  1195. }
  1196.  
  1197.  
  1198. /*
  1199. **   MosSleep
  1200. **
  1201. **       Called by a process to setup for sleeping
  1202. */
  1203.  
  1204. #ifdef C_ANSI
  1205. SHORT
  1206. MosSleep(PROC_P pstProc)
  1207. #else
  1208. SHORT
  1209. MosSleep(pstProc)
  1210. PROC_P pstProc; 
  1211. #endif 
  1212. {
  1213.    C_DEF_MODULE("MosSleep")
  1214.  
  1215.    LLIST_P  pstList;
  1216.  
  1217.  
  1218.    pstProc -> sState = PROC_STATE_SLEEPING;
  1219.  
  1220. #ifdef ANNOUNCE
  1221.    printf("Process %d: %s : Sleeping till %d\n", pstProc -> sProcId,
  1222.                                                  pstProc -> szName,
  1223.                                                  pstProc -> lWakeTime);
  1224. #endif
  1225.  
  1226.    C_STATUS = MemLstAllocMember(&pstList);
  1227.  
  1228.    pstList -> pvData = (PVOID) pstProc;
  1229.  
  1230.    C_STATUS = MemLstInsertMember(pstQueSleep,
  1231.                                  pstList,
  1232.                                  MosCompareTime,
  1233.                                  &pstQueSleep);
  1234.  
  1235.    C_STATUS = MOS_PROC_SUSPEND;
  1236.  
  1237.    C_RETURN
  1238. }
  1239.  
  1240.  
  1241. /*
  1242. **   MosCompareTime
  1243. **       
  1244. **       Compare time of two PROC_P in binary tree
  1245. */
  1246.  
  1247. #ifdef C_ANSI
  1248. SHORT
  1249. MosCompareTime(PVOID pvData1,PVOID pvData2)
  1250. #else
  1251. SHORT
  1252. MosCompareTime(pvData1,pvData2)
  1253. PVOID pvData1;
  1254. PVOID pvData2;
  1255. #endif
  1256. {
  1257.    PROC_P   pstProc1;
  1258.    PROC_P   pstProc2;
  1259.  
  1260.    pstProc1 = (PROC_P) pvData1;
  1261.    pstProc2 = (PROC_P) pvData2;
  1262.  
  1263.    if(pstProc1 -> lWakeTime == pstProc2 -> lWakeTime)
  1264.       return(C_EQUAL);
  1265.    else if(pstProc1 -> lWakeTime < pstProc2 -> lWakeTime)
  1266.       return(C_LOWER);
  1267.    else if(pstProc1 -> lWakeTime > pstProc2 -> lWakeTime)
  1268.       return(C_HIGHER);
  1269.  
  1270. }
  1271.  
  1272.  
  1273. /*
  1274. **   MosCompareIdNode
  1275. **       
  1276. **       Compare a passed in proc id with one pointed
  1277. **       to by a binary tree node
  1278. */
  1279.  
  1280. #ifdef C_ANSI
  1281. SHORT
  1282. MosCompareIdNode(PVOID pvData1,PVOID pvData2)
  1283. #else
  1284. SHORT
  1285. MosCompareIdNode(pvData1,pvData2)
  1286. PVOID pvData1;
  1287. PVOID pvData2;
  1288. #endif
  1289. {
  1290.    PROC_P   pstProc;
  1291.    PSHORT   psProcId;
  1292.  
  1293.  
  1294.    psProcId = (PSHORT) pvData1;
  1295.    pstProc = (PROC_P) pvData2;
  1296.                             
  1297.    if(*psProcId == pstProc -> sProcId)
  1298.       return(C_EQUAL);
  1299.    else if(*psProcId < pstProc -> sProcId)
  1300.       return(C_LOWER);
  1301.    else if(*psProcId > pstProc -> sProcId)
  1302.       return(C_HIGHER);
  1303.  
  1304. }
  1305.  
  1306.  
  1307. /*
  1308. **   MosGetPidByName
  1309. **       
  1310. **       Get another processes procid by using their name
  1311. */
  1312.  
  1313. #ifdef C_ANSI
  1314. SHORT
  1315. MosGetPidByName(PCHAR pcName,PSHORT psPid)
  1316. #else
  1317. SHORT
  1318. MosGetPidByName(pcName,psPid)
  1319. PCHAR pcName;
  1320. PSHORT psPid;
  1321. #endif 
  1322. {
  1323.    C_DEF_MODULE("MosGetPidByName")
  1324.  
  1325.  
  1326.    TNODE_P  pstNode;
  1327.    PROC_P   pstDestProc;
  1328.  
  1329.  
  1330.    /*
  1331.    **  Find address of destination process
  1332.    */
  1333.  
  1334.    C_STATUS = MemTreFindNode(pstProcNameTree,
  1335.                              (PVOID) pcName,
  1336.                              MosCompareProcName2,
  1337.                              &pstNode);
  1338.  
  1339.    if(pstNode != NULL)
  1340.    {
  1341.        pstDestProc = (PROC_P) pstNode -> pvData;
  1342.  
  1343.        *psPid = pstDestProc -> sProcId;
  1344.    }
  1345.    else
  1346.        *psPid = MOS_PROC_NULL;
  1347.  
  1348.    C_RETURN
  1349.  
  1350. }
  1351.  
  1352.  
  1353. /*
  1354. **   MosMsgWrite
  1355. **       
  1356. **       Write a message to a target process
  1357. **       The message data is calloc'd here and should be dealloced by
  1358. **       reader after MsgRead()
  1359. */
  1360.  
  1361. #ifdef C_ANSI
  1362. SHORT
  1363. MosMsgWrite(PROC_P pstProc,PCHAR pcData, SHORT sLen, SHORT sTargetProcId)
  1364. #else
  1365. SHORT
  1366. MosMsgWrite(pstProc,pcData,sLen,sTargetProcId)
  1367. PROC_P pstProc; 
  1368. PCHAR  pcData;
  1369. SHORT  sLen;
  1370. SHORT  sTargetProcId;
  1371. #endif 
  1372. {
  1373.    C_DEF_MODULE("MosMsgWrite")
  1374.  
  1375.    PROC_P   pstDestProc;
  1376.    LLIST_P  pstList;
  1377.    MSG_P    pstMsg;
  1378.  
  1379.  
  1380. #ifdef ANNOUNCE
  1381.    printf("Process %d: %s : Sending message to procid %d\n", pstProc -> sProcId,
  1382.                                                              pstProc -> szName,
  1383.                                                              sTargetProcId);
  1384. #endif
  1385.  
  1386.    /*
  1387.    **  Setup message for sending
  1388.    */
  1389.  
  1390.  
  1391.    pstMsg = (MSG_P) calloc(1,sizeof(MSG_T));
  1392.  
  1393.  
  1394.    pstMsg -> pcData = (PCHAR) calloc(1,sLen);
  1395.  
  1396.    memcpy(pstMsg -> pcData,pcData,sLen);
  1397.  
  1398.    pstMsg -> sLen = sLen;
  1399.  
  1400.    pstMsg -> sSendPid = pstProc -> sProcId;
  1401.  
  1402.    pstMsg -> sDestPid = sTargetProcId;
  1403.  
  1404.    
  1405.    /*
  1406.    **  Find address of destination process
  1407.    */
  1408.  
  1409.  
  1410.    C_STATUS = MemLstFindMember(pstProcIdList,
  1411.                              (PVOID) &sTargetProcId,
  1412.                              MosCompareIdNode,
  1413.                              &pstList);
  1414.  
  1415.    if(pstList != NULL)
  1416.    {
  1417.        pstDestProc = (PROC_P) pstList -> pvData;
  1418.  
  1419.        C_STATUS = MemQueEnqMember(&(pstDestProc -> pstMsgQueHead),
  1420.                                   &(pstDestProc -> pstMsgQueTail),
  1421.                                   (PVOID) pstMsg);
  1422.  
  1423.  
  1424.        /*
  1425.        **  Check if process was sleeping, if so, wake it up.
  1426.        **
  1427.        **  Remove it from the sleeping queue and place on ready queue
  1428.        */  
  1429.  
  1430.        if(pstDestProc -> sState == PROC_STATE_SLEEPING)
  1431.        {
  1432.  
  1433.                 C_STATUS = MemLstFindMember(pstQueSleep,
  1434.                                                         &(pstDestProc -> sProcId),
  1435.                                                            MosCompareIdNode,
  1436.                                        &pstList);
  1437.  
  1438.            C_STATUS = MemLstDeleteMember(pstQueSleep,
  1439.                                          pstList,
  1440.                                          &pstQueSleep);
  1441.  
  1442.            C_STATUS = MosReschedReady(pstDestProc);
  1443.            
  1444.        }
  1445.  
  1446.        /*
  1447.        **  Check if process was waiting on message, if so
  1448.        **  Remove it from the msg wait queue and place on ready queue
  1449.        */  
  1450.  
  1451.        if(pstDestProc -> sState == PROC_STATE_MSG_WAIT)
  1452.        {
  1453.  
  1454.            C_STATUS = MemLstFindMember(pstQueMsgWait,
  1455.                                        &(pstDestProc -> sProcId),
  1456.                                        MosCompareIdNode,
  1457.                                        &pstList);
  1458.  
  1459.            C_STATUS = MemLstDeleteMember(pstQueMsgWait,
  1460.                                          pstList,
  1461.                                          &pstQueMsgWait);
  1462.  
  1463.            C_STATUS = MosReschedReady(pstDestProc);
  1464.            
  1465.        }
  1466.    }
  1467.  
  1468.    C_RETURN
  1469. }
  1470.  
  1471.  
  1472. /*
  1473. **   MosTellMsgRead
  1474. **
  1475. **       Display the message a process read
  1476. */
  1477.  
  1478. #ifdef C_ANSI
  1479. SHORT
  1480. MosTellMsgRead(PROC_P pstProc,PCHAR pcMsgBuf)
  1481. #else
  1482. SHORT
  1483. MosTellMsgRead(pstProc,pcMsgBuf)
  1484. PROC_P pstProc; 
  1485. PCHAR pcMsgBuf;
  1486. #endif 
  1487. {
  1488.    C_DEF_MODULE("MosTelMsgRead")
  1489.  
  1490. #ifdef ANNOUNCE
  1491.    printf("Process %d: %s : Received Message: %s\n", 
  1492.            pstProc -> sProcId,
  1493.            pstProc -> szName,
  1494.            pcMsgBuf);
  1495. #else
  1496.    pstProc = pstProc;    /* silence compiler */
  1497.    pcMsgBuf = pcMsgBuf;  /* silence compiler */
  1498. #endif
  1499.  
  1500.    
  1501.    C_RETURN
  1502. }
  1503.  
  1504. /*
  1505. **   MosMsgRead
  1506. **
  1507. **       Read a message
  1508. */
  1509.  
  1510. #ifdef C_ANSI
  1511. SHORT
  1512. MosMsgRead(PROC_P pstProc, MSG_P * ppstMsg)
  1513. #else
  1514. SHORT
  1515. MosMsgRead(pstProc,ppstMsg)
  1516. PROC_P pstProc;
  1517. MSG_P * ppstMsg;
  1518. #endif
  1519. {
  1520.    C_DEF_MODULE("MosMsgRead")
  1521.    LLIST_P  pstList;
  1522.  
  1523.  
  1524.    if(!QUE_EMPTY(pstProc -> pstMsgQueHead))
  1525.    {
  1526.       C_STATUS = MemQueDeqMember(&(pstProc -> pstMsgQueHead),
  1527.                                  &(pstProc -> pstMsgQueTail),
  1528.                                  (PVOID *) ppstMsg);
  1529.    }
  1530.    else 
  1531.    {
  1532.  
  1533.       /*
  1534.       **  Place in Msg Wait que (Added November 23, 1991)
  1535.       */
  1536.  
  1537.  
  1538.       pstProc -> sState = PROC_STATE_MSG_WAIT;
  1539.   
  1540.       C_STATUS = MemLstAllocMember(&pstList);
  1541.   
  1542.       pstList -> pvData = (PVOID) pstProc;
  1543.   
  1544.       C_STATUS = MemLstInsertMember(pstQueMsgWait,
  1545.                               pstList,
  1546.                               MosCompareTime,
  1547.                               &pstQueMsgWait);
  1548.  
  1549.  
  1550.       C_STATUS = MOS_PROC_SUSPEND;
  1551.    }
  1552.  
  1553.    C_RETURN
  1554. }
  1555.  
  1556.  
  1557.  
  1558.  
  1559. /*
  1560. **    Create a new event process
  1561. */
  1562.  
  1563. #ifdef C_ANSI
  1564. SHORT
  1565. MosEventCreate(SHORT (*pCheckFunc)(VOID), SHORT (*pProc)(PROC_P), PCHAR szProcName, SHORT sPriority)
  1566. #else
  1567. SHORT
  1568. MosEventCreate(pCheckFunc,pProc,szProcName,sPriority)
  1569. SHORT (*pCheckFunc)();
  1570. SHORT (*pProc)();
  1571. PCHAR szProcName;
  1572. SHORT sPriority;
  1573. #endif
  1574. {
  1575.    C_DEF_MODULE("MosEventCreate")
  1576.  
  1577.    EVENT_P  pstEvent;
  1578.    PROC_P   pstProc;
  1579.    LLIST_P  pstMember;
  1580.    LLIST_P  pstTailMember;
  1581.  
  1582.  
  1583.    MosProcInit(pProc,szProcName,sPriority,&pstProc);
  1584.  
  1585.    pstEvent = (EVENT_P) calloc(1,sizeof(EVENT_T));
  1586.  
  1587.    pstEvent -> pCheckFunc = pCheckFunc;
  1588.    pstEvent -> pstEventProc = pstProc; 
  1589.       
  1590.    /*
  1591.    **  Place this process in the event list
  1592.    */
  1593.  
  1594.    /*
  1595.    **   Create member for process tracking by id 
  1596.    */
  1597.  
  1598.    C_STATUS = MemLstAllocMember(&pstMember);
  1599.  
  1600.    pstMember -> pvData = (PVOID) pstEvent;
  1601.  
  1602.    if(pstEventList == NULL)
  1603.       pstEventList = pstMember;
  1604.    else
  1605.    {
  1606.       MemLstFindTailMember(pstEventList,&pstTailMember);
  1607.  
  1608.       MemLstAddAfterMember(pstTailMember, pstMember);
  1609.    }
  1610.  
  1611.    sEvents++;
  1612.  
  1613.    C_RETURN
  1614. }
  1615.  
  1616. /*
  1617. **    Terminate an Event Process
  1618. */
  1619. #ifdef C_ANSI
  1620. SHORT
  1621. MosEventTerm(PROC_P pstProc)
  1622. #else
  1623. SHORT
  1624. MosEventTerm(pstProc)
  1625. PROC_P pstProc;
  1626. #endif
  1627. {
  1628.    C_DEF_MODULE("MosProcTerm")
  1629.  
  1630.    LLIST_P  pstList;
  1631.    EVENT_P  pstEvent;
  1632.  
  1633.    /*
  1634.    **  Remove from event list first
  1635.    */
  1636.  
  1637.    pstList = pstEventList;
  1638.   
  1639.    while(pstList != NULL)
  1640.    {
  1641.       pstEvent = pstList -> pvData;
  1642.   
  1643.       if(pstEvent -> pstEventProc == pstProc)
  1644.       {
  1645.          MemLstDeleteMember(pstEventList,
  1646.                             pstList,
  1647.                             &pstEventList);
  1648.          break;
  1649.       }
  1650.  
  1651.       pstList = pstList -> psNext;
  1652.  
  1653.    }
  1654.  
  1655.    /*
  1656.    **  Now call normal process cleanup
  1657.    */
  1658.  
  1659.    C_STATUS = MosProcTerm(pstProc);
  1660.  
  1661.    sEvents--;
  1662.  
  1663.    C_RETURN
  1664.  
  1665. }
  1666.  
  1667. /*
  1668. **   MosEventCheckList
  1669. **       
  1670. **       Check Event List
  1671. */
  1672.  
  1673. #ifdef C_ANSI
  1674. SHORT
  1675. MosEventCheckList(VOID)
  1676. #else
  1677. SHORT
  1678. MosEventCheckList()
  1679. #endif
  1680. {
  1681.    C_DEF_MODULE("MosEventCheckList")
  1682.  
  1683.    LLIST_P  pstMember;
  1684.    EVENT_P  pstEvent;
  1685.    
  1686.    if(sEvents == 0)
  1687.       C_LEAVE(C_OK);
  1688.  
  1689.    pstMember = pstEventList;
  1690.  
  1691.    while(pstMember != NULL)
  1692.    {
  1693.      
  1694.       pstEvent = (EVENT_P) pstMember -> pvData;
  1695.  
  1696.       /* check for event occurance */
  1697.  
  1698.       C_STATUS = (*(pstEvent -> pCheckFunc))();
  1699.   
  1700.       if(C_STATUS)
  1701.       {
  1702.          /* 
  1703.          **  if event occurred, place back on ready/run queue
  1704.          **  processes awaiting events may be of higher priority than
  1705.          **  normal processes
  1706.          */
  1707.          
  1708.          C_STATUS = MosReschedReady(pstEvent->pstEventProc);
  1709.       }
  1710.  
  1711.       pstMember = pstMember -> psNext;
  1712.    }
  1713.  
  1714.  
  1715.    C_SET_STATUS(C_OK);
  1716.  
  1717.   
  1718. C_MODULE_EXIT:
  1719.  
  1720.    C_RETURN
  1721. }
  1722.  
  1723.  
  1724.  
  1725.  
  1726.