home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 15 / 15.iso / s / s300 / 1.ddi / CHAP3 / TIME.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-05-02  |  26.5 KB  |  1,036 lines

  1. /***********************************************************************
  2.  
  3. FILE
  4.     time.c  -  timing routines
  5.  
  6. ENTRY ROUTINES
  7.     chronos      -  timer interrupt service routine
  8.  
  9.     NewDTimer    -  allocate new countdown timer
  10.     FreeDTimer   -  deallocate countdown timer
  11.     SetDTimer    -  set countdown timer
  12.     ReadDTimer   -  read countdown timer
  13.     StopDTimer   -  freeze timer
  14.     StartDTimer  -  unfreeze timer
  15.  
  16.     CisDTimer    -  set tm_isf field to 0
  17.  
  18.     NewITimer    -  allocate new interval timer
  19.     FreeITimer   -  deallocate interval timer
  20.     SetITimer    -  set interval timer
  21.     ReadITimer   -  read interval timer
  22.  
  23.     ReadClock    -  time telling
  24.  
  25. PRIVATE ROUTINES
  26.     reset_dtimer  -  reset countdown timer
  27.     reset_itimer  -  reset interval timer
  28.  
  29. INITIALIZATION ROUTINES
  30.     InitTime     -  initialize timer module
  31.     InitSysTime  -  system initialization for task scheduling
  32.  
  33. DESCRIPTION
  34.     These routines implement multiple timers in software, using a
  35.     single hardware clock as the real-time base.  Actual and
  36.     simulation routines are included.  
  37.     
  38.     Note the implementation of multiple prioritized timer interrupts 
  39.     in chronos().  Only countdown timers are associated with interrupt
  40.     service routines.
  41.  
  42.     The first two timers are reserved by the kernel for time telling
  43.     and task scheduling.
  44.  
  45. LAST UPDATE
  46.     03 May 1985
  47.         restructure allocation routines
  48.     04 February 1986
  49.         put enable() & disable() in #if BACKGROUND
  50.     1 December 1987
  51.         implement tm_flag[]
  52.     26 January 1988
  53.         use the new void types and add ANSI features
  54.  
  55.     Copyright (c) 1985-1988  D.M. Auslander  and  C.H. Tham
  56.  
  57. ***********************************************************************/
  58.  
  59. /***********************************************************************
  60.                             I M P O R T S
  61. ***********************************************************************/
  62.  
  63. #include <stdio.h>
  64.  
  65. #include "envir.h"          /* environment definitions */
  66.  
  67. #include "config.h"         /* system configuration header */
  68. #include "8259.h"           /* hardware dependent declarations */
  69. #include "time.h"           /* time module declarations */
  70.  
  71. #ifdef ANSI
  72. extern int  enable(void);   /* enable CPU interrupt response */
  73. extern int  disable(void);  /* disable CPU interrupt response */
  74. extern void seoi(int);      /* send specific EOI to 8259 */
  75. extern void panic(char *);  /* abort execution */
  76. #else
  77. extern int  enable();       /* enable CPU interrupt response */
  78. extern int  disable();      /* disable CPU interrupt response */
  79. extern void seoi();         /* send specific EOI to 8259 */
  80. extern void panic();        /* abort execution */
  81. #endif
  82.  
  83. /***********************************************************************
  84.               F O R W A R D    D E C L A R A T I O N S
  85. ***********************************************************************/
  86.  
  87. #ifdef ANSI
  88.  
  89. void    reset_dtimer(int);
  90. void    reset_itimer(int);
  91.  
  92. #else
  93.  
  94. void    reset_dtimer();
  95. void    reset_itimer();
  96.  
  97. #endif
  98.  
  99. /***********************************************************************
  100.                      P R I V A T E    D A T A
  101. ***********************************************************************/
  102.  
  103. #define MAXINT  0x7FFF              /* max. integer value */
  104. #define MAXLONG 0x7FFFFFFL          /* max. long integer value */
  105.  
  106. static long tm_dtime[MAXDTIMERS];   /* count down timers */
  107.  
  108. static int tm_used[MAXDTIMERS];     /* timer in use flag */
  109. static int tm_lock[MAXDTIMERS];     /* used for virtual time */
  110. static int tm_flag[MAXDTIMERS];     /* timeout flags */
  111. static int tm_pri[MAXDTIMERS];      /* priority (countdown only) */
  112.  
  113. static int tm_isf[MAXDTIMERS];      /* interrupt in service flag */
  114. static void (*tm_tsr[MAXDTIMERS])();    /* timeout service routines */
  115. static void *tm_argp[MAXDTIMERS];   /* ptr to arguments */
  116.  
  117. static long tm_itime[MAXITIMERS];   /* interval timers */
  118. static int tm_iused[MAXITIMERS];    /* interval timer in use flag */
  119.  
  120. static long clock;                  /* countdown since system started */
  121. static long mstick;                 /* milliseconds per tick */
  122.  
  123.  
  124. #define ISF         1               /* whether to use tm_isf field */
  125. #define AUTO_EOI    0               /* enable and send EOI to 8259 */
  126.  
  127. #define UNUSED      0               /* timer unused */
  128. #define USED        1               /* timer in use */
  129. #define UNLOCK      0               /* timer unlocked */
  130. #define LOCK        1               /* timer locked */
  131.  
  132.  
  133. /***********************************************************************
  134.                     E N T R Y    R O U T I N E S
  135. ***********************************************************************/
  136.  
  137. /*---------------------------------------------------------------------
  138. PROCEDURE
  139.     CHRONOS  -  Timer Interrupt Service Routine
  140.  
  141. DESCRIPTION
  142.     First decrements count down timers.  Count down timers are only 
  143.     decremented if they are in used (ie. allocated to a task) and
  144.     if the timer is not locked.  Interval timers are the exception 
  145.     and are all incremented irregardless since its probably faster to
  146.     do so than check if they are in use.
  147.  
  148.     Next, the countdown timer array, tm_dtime[], is scanned for zero 
  149.     or negative times.  If time is zero or negative, see if user has 
  150.     specified an interrupt service routine (tm_tsr not NULL).  If so, 
  151.     set the In Service Flag (tm_isf) and execute the routine, clearing
  152.     tm_isf on completion.
  153.  
  154.     If two or more service routines are due for service, the one with
  155.     the highest priority will be executed first.  Only service routines
  156.     with equal or higher priority can interrupt a currently in service
  157.     routine.  Priority is set by the user when the timer is allocated.
  158.     The larger the number, the higher the priority.
  159.  
  160.     Service routines are passed a pointer which may point to a scalar
  161.     argument or an aggregate argument block (eg. structures).  This
  162.     pointer is cast to a char type pointer.
  163.  
  164.     If this routine is run in a simulation environment, there may be
  165.     simulation routines that have to be executed at every time step,
  166.     regardless of whether a service routine is executed or not.  This 
  167.     is provided for by the external routine simintr() which is executed
  168.     at every "tick".
  169.  
  170.     Chronos() may be used in programs where the "interrupt" routine
  171.     never returns;  the "interrupt" service routine may be a task 
  172.     dispatcher or scheduler.  In such cases, two course of action are
  173.     possible depending on whether the dispatcher/scheduler.  In the
  174.     case of a background scheduler, we normally want to disable the 
  175.     in service flag and also reset the hardware interrupt controller.
  176.     This is to allow another timer interrupt to be generated and passed
  177.     to chronos() without the intervention of the dispatcher/scheduler.
  178.     For a foreground dispatcher/scheduler that uses the timer, it will
  179.     want to control exactly when it gives up control, so we do not want
  180.     to send EOI's or enable interrupts here, but allow the foreground
  181.     dispatcher/scheduler to do so with CisDTimer(). 
  182.     
  183.     The in-service-flag may be ignored by means of the ISF conditional
  184.     compilation switch.  The service routine has the task of reseting
  185.     the hardware interrupt controller.  CisDTimer() performs both actions.
  186.  
  187.     Chronos() functions like a level triggered interrupt controller.
  188.     As long as other conditions are satisfied, a zero or negative
  189.     count will result in execution of the associated service routine.
  190.  
  191.     Note the use of register pointers for speed.
  192.  
  193.     New:    A timeout service routine is only invoked once when the
  194.             count-down timer times out.  The timer must be reset by
  195.             SetDTimer() before the timeout handler can be invoked again.
  196.  
  197. LAST UPDATE
  198.     28 February 1985
  199.         add ISF test
  200.     04 February 1986
  201.         use enable() and disable() only if BACKGROUND
  202.     1 December 1987
  203.         lock timer when isr active, release on reset
  204.     26 January 1988
  205.         use the new void pointer types
  206. ----------------------------------------------------------------------*/
  207.  
  208. void chronos()
  209. {
  210.     int maxpri;                 /* max. pri. of in-service routine */
  211.     int index;                  /* index into timer array */
  212.     int istat;                  /* interrupt status on entry */
  213.     int i;                      /* iteration counter */
  214.     register long *p;           /* fast pointer to timer times */
  215.  
  216.  
  217.     istat = disable();          /* critical section, disable interrupts */
  218.  
  219.  
  220.     ++clock;                    /* update clock */
  221.  
  222.     /*---------------------------------------------------------------
  223.         Upon system clock interrupt, increment all interval timers.
  224.         May be faster than checking if they are used b4 incrementing.
  225.     ----------------------------------------------------------------*/
  226.  
  227.     for (p = tm_itime, i = 0; i < MAXITIMERS; i++, p++)
  228.         ++(*p);
  229.  
  230.     /*---------------------------------------------------------------
  231.         If a countdown timer is active and it is not locked, its 
  232.         time value is decremented.  Does not check if timer has
  233.         timed out since this is taken care of by tm_flag[] and to
  234.         do so here will increase the overheads.  The tm_lock[]
  235.         check is needed because we may need to stop certain timers.
  236.         Have to check if timer is in use because a timeout service
  237.         routine may be attached to a timer.
  238.     ----------------------------------------------------------------*/
  239.  
  240.     for (p = tm_dtime, i = 0; i < MAXDTIMERS; i++, p++)
  241.         if ((tm_used[i] == USED) && (tm_lock[i] == UNLOCK))
  242.             --(*p);
  243.  
  244. #if FOREGROUND      /* use timeout service routines */
  245.  
  246.     /*--------------------------------------------------------------
  247.         Find the highest priority of all timer interrupt routines
  248.         currently in service and set maxpri to that priority.
  249.     --------------------------------------------------------------*/
  250.  
  251.     maxpri = -MAXINT;
  252.  
  253.     for (i = 0; i < MAXDTIMERS; i++)
  254.         if ((tm_isf[i] > 0) && (tm_pri[i] > maxpri))
  255.             maxpri = tm_pri[i];
  256.  
  257.     /*--------------------------------------------------------------
  258.         Find any pending service routine with greater or equal
  259.         priority.  If index >= 0, such a routine exists and index
  260.         is its offset in tm_tsr[].
  261.     --------------------------------------------------------------*/
  262.  
  263.     index = -1;
  264.  
  265.     for (i = 0; i < MAXDTIMERS; i++)
  266.     {
  267.         if ((tm_dtime[i] <= 0L) && (tm_pri[i] >= maxpri)
  268.             && (tm_isf[i] == 0) && (tm_tsr[i] != (void(*)())NULL)
  269.             && (tm_lock[i] == UNLOCK) && (tm_flag[i] == 0))
  270.         {
  271.             index = i;
  272.             maxpri = tm_pri[i];
  273.         }
  274.     }
  275.  
  276.     if (index >= 0)
  277.     {
  278. #if ISF
  279.         tm_isf[index] += 1; /* indicate routine in service */
  280. #endif
  281. #if AUTO_EOI
  282.         enable();
  283.  
  284.         seoi(TMRVEC);           /* specific EOI to intrp. controller */
  285. #endif
  286.         tm_flag[index] = 1;     /* prevent further use until reset */
  287.  
  288.         (*(tm_tsr[index]))(tm_argp[index]);
  289.  
  290. #if AUTO_EOI
  291.         disable();
  292. #endif
  293. #if ISF
  294.         tm_isf[index] -= 1; /* indicate routine done */
  295. #endif
  296.     }
  297.  
  298. #endif  /* if FOREGROUND */
  299.  
  300.     if (istat)
  301.         enable();               /* release mutual exclusion */
  302.  
  303. }
  304.  
  305.  
  306.  
  307. /*----------------------------------------------------------------------
  308. FUNCTION
  309.     NewDTimer  -  allocate countdown timer
  310.  
  311. SYNOPSIS
  312.     int NewDTimer(func, argp, pri)
  313.     void (*func)(), *argp;
  314.     int pri;
  315.  
  316. PARAMETERS
  317.     func  -  pointer to service routine
  318.     argp  -  pointer to argument(s)
  319.     pri   -  priority
  320.  
  321. RETURNS
  322.     timer index if successful, -1 if not.
  323.  
  324. LAST UPDATE
  325.     26 January 1988
  326.         change func type to void
  327. ----------------------------------------------------------------------*/
  328.  
  329. int NewDTimer(func, argp, pri)
  330. void (*func)(), *argp;
  331. int pri;
  332. {
  333.     int i;                      /* iteration variable */
  334.     int istat;                  /* interrupt status */
  335.  
  336.  
  337.     istat = disable();      /* disable interrupts, critical section */
  338.  
  339.     for (i = 0; i < MAXDTIMERS; i++)
  340.         if (tm_used[i] != USED)
  341.             break;
  342.     
  343.     if (i < MAXDTIMERS)
  344.     {
  345.         tm_pri[i] = pri;
  346.         tm_tsr[i] = func;
  347.         tm_argp[i] = argp;
  348.         tm_lock[i] = UNLOCK;
  349.         tm_flag[i] = 0;
  350.         tm_used[i] = USED;
  351.     }
  352.     else
  353.         i = -1;
  354.  
  355.     if (istat)              /* exit critical section, re-enable intrp */
  356.         enable();
  357.  
  358.     return(i);
  359. }
  360.  
  361.  
  362.  
  363. /*----------------------------------------------------------------------
  364. PROCEDURE
  365.     FreeDTimer  -  free allocated timer
  366.  
  367. SYNOPSIS
  368.     void FreeITimer(timer)
  369.     int timer;
  370.  
  371. PARAMTERS
  372.     timer  -  timer index number
  373.  
  374. DESCRIPTION
  375.     Set associated used field to 0, indicating timer is free.  Note that
  376.     you MUST ensure that the timer you are returning is obtained with
  377.     NewDTimer.  Otherwise, you will screw-up the system for sure.
  378.  
  379. LAST UPDATE
  380.     3 May 1985
  381. ----------------------------------------------------------------------*/
  382.  
  383. void FreeDTimer(timer)
  384. int timer;
  385. {
  386.  
  387.     if ((timer < 0) || (timer >= MAXDTIMERS))
  388.     {
  389.         panic("FreeDTimer: nonexistant countdown timer");
  390.     }
  391.     else if (tm_used[timer] == USED)
  392.     {
  393.         reset_dtimer(timer);
  394.     }
  395.     else
  396.         panic("FreeDTimer: countdown timer not allocated");
  397.  
  398. }
  399.  
  400.  
  401.  
  402. /*----------------------------------------------------------------------
  403. PROCEDURE
  404.     SETDTIMER  -  set countdown timer
  405.  
  406. SYNOPSIS
  407.     void SetDTimer(n, ms)
  408.     int n;
  409.     long ms;
  410.  
  411. PARAMETERS
  412.     n   -  timer id
  413.     ms  -  time in milliseconds
  414.  
  415. DESCRIPTION
  416.     Set countdown timer 'n' for ms milliseconds.  If ms is less than
  417.     the resolution of the time-base, tm_dtime is set to zero.
  418.     A negative value of ms deallocates the timer.
  419.  
  420. LAST UPDATE
  421.     1 December 1987
  422.         reset tm_flag
  423. ----------------------------------------------------------------------*/
  424.  
  425. void SetDTimer(n, ms)
  426. int n; 
  427. long ms;
  428. {
  429.     int istat;      /* interrupt status */
  430.     long tmp;       /* temporary to hold tick calculations */
  431.     int flag;       /* temporary to hold flag state */
  432.  
  433.  
  434.     if ((n < 0) || (n >= MAXDTIMERS))
  435.         panic("SetDTimer: nonexistent timer");
  436.     else if (tm_used[n] == UNUSED)
  437.         panic("SetDTimer: timer not allocated");
  438.  
  439.     tmp = ms / mstick;
  440.     flag = (ms > 0L) ? 0 : 1;
  441.  
  442.     istat = disable();      /* guarantee mutual exclusion */
  443.  
  444.     if (ms >= 0L)
  445.     {
  446.         tm_dtime[n] = tmp;
  447.         tm_flag[n] = flag;
  448.     }
  449.     else        /* release timer */
  450.     {
  451.         tm_used[n] = UNUSED;
  452.         tm_tsr[n] = (void(*)())NULL;
  453.     }
  454.  
  455.     if (istat)
  456.         enable();           /* release mutual exclusion */
  457.  
  458. }
  459.  
  460.  
  461.  
  462. /*----------------------------------------------------------------------
  463. FUNCTION
  464.     ReadDTimer  -  read countdown timer
  465.  
  466. SYNOPSIS
  467.     long ReadDTimer(n)
  468.     int n;
  469.  
  470. PARAMETER
  471.     n  -  timer number
  472.  
  473. RETURNS
  474.     time in milliseconds
  475.  
  476. REMARKS
  477.     The time left is only accurate to the precision allowed by the
  478.     system clock rate.  If quantization is 10 ms, then ReadDTimer() 
  479.     will report 10 ms even if actual time left is 1 ms.
  480.  
  481. LAST UPDATE
  482.     12 February 1985  by  author
  483. ----------------------------------------------------------------------*/
  484.  
  485. long ReadDTimer(n)
  486. int n;
  487. {
  488.  
  489.     if ((n < 0) || (n >= MAXDTIMERS))
  490.         panic("ReadDTimer: nonexistant timer");
  491.  
  492.     return(tm_dtime[n] * mstick);
  493. }
  494.  
  495.  
  496.  
  497. /*----------------------------------------------------------------------
  498. PROCEDURE
  499.     STOPDTIMER  -  stop timer from counting down
  500.  
  501. SYNOPSIS
  502.     void StopDTimer(n)
  503.     int n;
  504.  
  505. PARAMETER
  506.     n  -  timer number
  507.  
  508. DESCRIPTION
  509.     This routine should only be used by the system to freeze timers
  510.     used by background process for virtual timing, ie. time proceeds
  511.     only when that process is running.  An important use is for
  512.     background scheduling.
  513.  
  514.     As this is an internal system routine, error checking is lax.
  515.  
  516. SEE ALSO
  517.     StartDTimer() to restart stopped timers
  518.  
  519. LAST UPDATE
  520.     12 February 1985
  521. ----------------------------------------------------------------------*/
  522.  
  523. void StopDTimer(n)
  524. int n;
  525. {
  526.     int istat;              /* interrupt status */
  527.  
  528.  
  529.     if ((n < 0) || (n >= MAXDTIMERS))
  530.         panic("StopDTimer: nonexistent timer");
  531.     
  532.     istat = disable();
  533.  
  534.     tm_lock[n] = LOCK;
  535.  
  536.     if (istat)
  537.         enable();
  538. }
  539.  
  540.  
  541.  
  542. /*----------------------------------------------------------------------
  543. PROCEDURE
  544.     STARTDTIMER  -  stop timer from counting down
  545.  
  546. SYNOPSIS
  547.     void StartDTimer(n)
  548.     int n;
  549.  
  550. PARAMETER
  551.     n  -  timer number
  552.  
  553. REMARKS
  554.     This routine should only be used by the system to restart timers
  555.     frozen by a StopDTimer call.
  556.  
  557. SEE ALSO
  558.     StopDTimer() to stop timers
  559.  
  560. LAST UPDATE
  561.     12 February 1985  by  author
  562. ----------------------------------------------------------------------*/
  563.  
  564. void StartDTimer(n)
  565. int n;
  566. {
  567.     int istat;          /* interrupt status */
  568.  
  569.  
  570.     if ((n < 0) || (n >= MAXDTIMERS))
  571.         panic("StartDTimer: nonexistent timer");
  572.     
  573.     istat = disable();
  574.  
  575.     tm_lock[n] = UNLOCK;
  576.  
  577.     if (istat)
  578.         enable();
  579.  
  580. }
  581.  
  582.  
  583.  
  584. /*----------------------------------------------------------------------
  585. PROCEDURE
  586.     CISDTIMER  -  clear in service flags (software and hardware)
  587.  
  588. SYNOPSIS
  589.     void CisDTimer(n)
  590.     int n;
  591.  
  592. PARAMTER
  593.     n  -  countdown timer number
  594.  
  595. REMARKS
  596.     The purpose is to allow another invokation of the timeout service
  597.     routine at the next timer interrupt.
  598.  
  599. LAST UPDATE
  600.     1 December 1987
  601.         clear tm_flag
  602. ----------------------------------------------------------------------*/
  603.  
  604. void CisDTimer(n)
  605. int n;
  606. {
  607.     int istat;          /* interrupt status */
  608.  
  609.     
  610.     if ((n < 0) || (n >= MAXDTIMERS))
  611.         panic("CisDTimer: nonexistant timer");
  612.     
  613.     istat = disable();
  614.  
  615.     tm_isf[n] = 0;
  616.     tm_flag[n] = 0;
  617.  
  618.     seoi(TMRVEC);   /* send specific EOI to interrupt controller */
  619.  
  620.     if (istat)
  621.         enable();
  622.  
  623. }
  624.  
  625.  
  626.  
  627. /*---------------------------------------------------------------------
  628. PROCEDURE
  629.     SETTSR  -  install timeout service routine
  630.  
  631. SYNOPSIS
  632.     void SetTsr(n, func, argp, pri)
  633.     void (*func)(), *argp;
  634.     int n, pri;
  635.  
  636. PARAMETERS
  637.     n     -  timer id
  638.     func  -  pointer to service routine
  639.     argp  -  pointer to argument structure
  640.     pri   -  priority
  641.  
  642. REMARKS
  643.     There had better be no mistakes when specifying timer.
  644.  
  645. LAST UPDATE
  646.     26 January 1988
  647.         use the new void types
  648. ----------------------------------------------------------------------*/
  649.  
  650. void SetTsr(n, func, argp, pri)
  651. void (*func)(), *argp;
  652. int n, pri;
  653. {
  654.     int istat;              /* interrupt status */
  655.  
  656.  
  657.     if ((n < 0) || (n >= MAXDTIMERS))
  658.         panic("SetTsr:  nonexistant timer");
  659.     
  660.     istat = disable();
  661.  
  662.     tm_pri[n] = pri;
  663.     tm_tsr[n] = func;
  664.     tm_argp[n] = argp;
  665.     tm_lock[n] = UNLOCK;
  666.     tm_flag[n] = 0;
  667.     tm_used[n] = USED;
  668.  
  669.     if (istat)
  670.         enable();
  671.  
  672. }
  673.  
  674.  
  675.  
  676. /*----------------------------------------------------------------------
  677. FUNCTION
  678.     TIMEUP  -  has timer run out?
  679.  
  680. SYNOPSIS
  681.     int TimeUp(n)
  682.     int n;
  683.  
  684. PARAMETER
  685.     n  -  timer number
  686.  
  687. RETURNS
  688.     0  if timer has not timed out
  689.     1  if it has timed out
  690.  
  691. LAST UPDATE
  692.     29 January 1988
  693.         created as this makes more sense than reading the timer
  694. ----------------------------------------------------------------------*/
  695.  
  696. int TimeUp(n)
  697. int n;
  698. {
  699.  
  700.     if ((n < 0) || (n >= MAXDTIMERS))
  701.         panic("TimeUp:  nonexistant timer");
  702.  
  703.     return(tm_dtime[n] <= 0L ? 1 : 0);
  704. }
  705.  
  706.  
  707.  
  708. /*----------------------------------------------------------------------
  709. FUNCTION
  710.     NewITimer  -  allocate interval timer
  711.  
  712. SYNOPSIS
  713.     int NewITimer()
  714.  
  715. RETURNS
  716.     timer index if successful, -1 if not.
  717.  
  718. LAST UPDATE
  719.     3 May 1985
  720. ----------------------------------------------------------------------*/
  721.  
  722. int NewITimer()
  723. {
  724.     int istat;                  /* interrupt status */
  725.     int i;                      /* iteration variable */
  726.  
  727.  
  728.     istat = disable();  /* disable interrupts, critical section */
  729.  
  730.     for (i = 0; i < MAXITIMERS; i++)
  731.         if (tm_iused[i] != USED)
  732.             break;
  733.     
  734.     if (i < MAXITIMERS)
  735.     {
  736.         reset_itimer(i);
  737.  
  738.         tm_iused[i] = USED;
  739.     }
  740.     else
  741.         i = -1;
  742.  
  743.     if (istat)          /* exit critical section, re-enable intrp */
  744.         enable();
  745.  
  746.     return(i);
  747. }
  748.  
  749.  
  750.  
  751. /*----------------------------------------------------------------------
  752. PROCEDURE
  753.     FreeITimer  -  free allocated interval timer
  754.  
  755. SYNOPSIS
  756.     void FreeITimer(timer)
  757.     int timer;
  758.  
  759. PARAMTERS
  760.     timer  -  timer index number
  761.  
  762. DESCRIPTION
  763.     Set associated used field to 0, indicating timer is free.  Note that
  764.     you MUST ensure that the timer you are returning is obtained with
  765.     NewITimer.  Otherwise, you will screw-up the system for sure.
  766.  
  767. LAST UPDATE
  768.     3 May 1985  by  author
  769. ----------------------------------------------------------------------*/
  770.  
  771. void FreeITimer(timer)
  772. int timer;
  773. {
  774.  
  775.     if ((timer < 0) || (timer >= MAXITIMERS))
  776.     {
  777.         panic("FreeITimer: nonexistant interval timer");
  778.     }
  779.     else if (tm_iused[timer] == USED)
  780.     {
  781.         reset_itimer(timer);
  782.     }
  783.     else
  784.         panic("FreeITimer: interval timer not allocated");
  785.  
  786. }
  787.  
  788.  
  789.  
  790. /*----------------------------------------------------------------------
  791. PROCEDURE
  792.     SetITimer  -  set interval timer
  793.  
  794. SYNOPSIS
  795.     void SetITimer(n);
  796.     int n;
  797.  
  798. PARAMETERS
  799.     n   -  timer id
  800.  
  801. REMARKS
  802.     Set interval time value to 0.
  803.  
  804. LAST UPDATE
  805.     13 October 1984
  806. ----------------------------------------------------------------------*/
  807.  
  808. void SetITimer(n)
  809. int n;
  810. {
  811.  
  812.     if ((n < 0) || (n >= MAXITIMERS))
  813.         panic("SetITimer: nonexistant timer");
  814.     
  815.     tm_itime[n] = 0;
  816.  
  817. }
  818.  
  819.  
  820.  
  821. /*----------------------------------------------------------------------
  822. FUNCTION
  823.     ReadITimer  -  read interval timer
  824.  
  825. SYNOPSIS
  826.     long ReadITimer(n);
  827.     int n;
  828.  
  829. PARAMETERS
  830.     n   -  timer id
  831.  
  832. RETURNS
  833.     interval value in milliseconds
  834.  
  835. LAST UPDATE
  836.     13 October 1984
  837. ----------------------------------------------------------------------*/
  838.  
  839. long ReadITimer(n)
  840. int n;
  841. {
  842.     
  843.     if ((n < 0) || (n >= MAXITIMERS))
  844.         panic("ReadITimer: nonexistant timer");
  845.     
  846.     return(tm_itime[n] * mstick);
  847. }
  848.  
  849.  
  850.  
  851. /*----------------------------------------------------------------------
  852. FUNCTION
  853.     ReadClock  -  read system time
  854.  
  855. SYNOPSIS
  856.     long ReadClock()
  857.  
  858. RETURNS
  859.     time elasped in milliseconds since system is born
  860.  
  861. LAST UPDATE
  862.     12 February 1985
  863. ----------------------------------------------------------------------*/
  864.  
  865. long ReadClock()
  866. {
  867.  
  868.     return(clock * mstick);
  869. }
  870.  
  871.  
  872.  
  873. /***********************************************************************
  874.                     P R I V A T E    R O U T I N E S 
  875. ***********************************************************************/
  876.  
  877. /*----------------------------------------------------------------------
  878. PROCEDURE
  879.     reset_dtimer  -  reset countdown timer
  880.  
  881. SYNOPSIS
  882.     static reset_dtimer(n)
  883.     int n;
  884.  
  885. PARAMETER
  886.     n  -  timer id
  887.  
  888. LAST UPDATE
  889.     1 December 1987
  890.         clear tm_flag
  891. ----------------------------------------------------------------------*/
  892.  
  893. static void reset_dtimer(n)
  894. int n;
  895. {
  896.  
  897.     tm_dtime[n] = MAXLONG;
  898.     tm_used[n] = UNUSED;
  899.     tm_lock[n] = UNLOCK;
  900.     tm_flag[n] = 0;
  901.     tm_pri[n] = PZERO - 1;
  902.     tm_isf[n] = 0;
  903.     tm_tsr[n] = (void(*)())NULL;
  904.     tm_argp[n] = (void *)NULL;
  905.  
  906. }
  907.  
  908.  
  909.  
  910. /*----------------------------------------------------------------------
  911. PROCEDURE
  912.     reset_itimer  -  reset interval timer
  913.  
  914. SYNOPSIS
  915.     static void reset_itimer(n)
  916.     int n;
  917.  
  918. PARAMETER
  919.     n  -  timer id
  920.  
  921. LAST UPDATE
  922.     12 February 1985
  923. ----------------------------------------------------------------------*/
  924.  
  925. static void reset_itimer(n)
  926. int n;
  927. {
  928.  
  929.     tm_itime[n] = 0L;
  930.     tm_iused[n] = UNUSED;
  931.  
  932. }
  933.  
  934.  
  935. /***********************************************************************
  936.             I N I T I A L I Z A T I O N    R O U T I N E S
  937. ***********************************************************************/
  938.  
  939. /*----------------------------------------------------------------------
  940. PROCEDURE
  941.     INITTIME  -  initialize this module
  942.  
  943. SYNOPSIS
  944.     void InitTime(ms)
  945.     long ms;
  946.  
  947. PARAMETER
  948.     ms  -  milliseconds per tick
  949.  
  950. LAST UPDATE
  951.     12 February 1985
  952.         separate countdown and interval timers.
  953. ----------------------------------------------------------------------*/
  954.  
  955. void InitTime(ms)
  956. long ms;
  957. {
  958.     int i;                  /* iteration variable */
  959.  
  960.  
  961.     mstick = ms;
  962.     clock = 0L;
  963.  
  964.  
  965.     for (i = 0; i < MAXDTIMERS; i++)
  966.     {
  967.         reset_dtimer(i);
  968.     }
  969.  
  970.     for (i = 0; i < MAXITIMERS; i++)
  971.     {
  972.         reset_itimer(i);
  973.     }
  974.  
  975. }
  976.  
  977.  
  978. #ifdef CLOTHO       /* used by clotho kernel only */
  979.  
  980. /*----------------------------------------------------------------------
  981. PROCEDURE
  982.     INITSYSTIME  -  allocate and initialize timers for system
  983.  
  984. SYNOPSIS
  985.     void InitSysTime(dispatcher)
  986.     void (*dispatcher)();
  987.  
  988. PARAMETER
  989.     dispatcher  -  pointer to clotho's scheduler/dispatcher
  990.  
  991. REMARKS
  992.     timer 0  -  reserved for normal dispatcher
  993.     timer 1  -  reserved for control-task dispatcher/scheduler
  994.  
  995. LAST UPDATE
  996.     12 February 1985
  997. ----------------------------------------------------------------------*/
  998.  
  999. void InitSysTime(dispatcher)
  1000. void (*dispatcher)();
  1001. {
  1002.  
  1003.     if ((SLC_TIMER >= MAXDTIMERS) || (STL_TIMER >= MAXDTIMERS))
  1004.         panic("InitSysTime: check SLC_TIMER & STL_TIMER < MAXDTIMERS");
  1005.  
  1006.     tm_used[SLC_TIMER] = USED;
  1007.     tm_lock[SLC_TIMER] = UNLOCK;
  1008.     tm_flag[SLC_TIMER] = 0;
  1009.  
  1010.     tm_used[STL_TIMER] = USED;
  1011.     tm_lock[STL_TIMER] = UNLOCK;
  1012.     tm_flag[STL_TIMER] = 0;
  1013.  
  1014. #if FOREGROUND
  1015.  
  1016.     /*****  set up timer for time-slice priority dispatcher  *****/
  1017.  
  1018.     tm_tsr[SLC_TIMER] = dispatcher;
  1019.     tm_argp[SLC_TIMER] = (void *)SLC_TIMER;
  1020.     tm_pri[SLC_TIMER] = PZERO + 1;  /* has low priority */
  1021.     tm_dtime[SLC_TIMER] = 0;        /* start background next */
  1022.  
  1023.  
  1024.     /*****  set up timer for control-task STL dispatcher  *****/
  1025.  
  1026.     tm_tsr[STL_TIMER] = dispatcher;
  1027.     tm_argp[STL_TIMER] = (void *)STL_TIMER;
  1028.     tm_pri[STL_TIMER] = MAXINT;     /* has very high priority */
  1029.     tm_dtime[STL_TIMER] = MAXLONG;
  1030.  
  1031. #endif
  1032.  
  1033. }
  1034.  
  1035. #endif  /* ifdef CLOTHO */
  1036.