home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / TIMER.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  6KB  |  264 lines

  1. /* General purpose software timer facilities
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4.  
  5. /****************************************************************************
  6. *    $Id: timer.c 1.4 93/07/16 11:51:33 ROOT_DOS Exp $
  7. *    04 Jul 93    1.4        GT    Fix warnings.                                    *
  8. ****************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include "global.h"
  12. #include "timer.h"
  13. #include "proc.h"
  14. #include "mbuf.h"
  15. #include "commands.h"
  16. #include "daemon.h"
  17. #include "hardware.h"
  18. #include "socket.h"
  19.  
  20. /* Head of running timer chain.
  21.  * The list of running timers is sorted in increasing order of expiration;
  22.  * i.e., the first timer to expire is always at the head of the list.
  23.  */
  24. struct timer *Timers;
  25.  
  26. static void t_alarm __ARGS((void *x));
  27.  
  28. /* Process that handles clock ticks */
  29. void
  30. timerproc(i,v1,v2)
  31. int i;
  32. void *v1,*v2;
  33. {
  34.     register struct timer *t;
  35.     register struct timer *expired;
  36.     char i_state;
  37.     void (**vf) __ARGS((void));
  38.  
  39.     for(;;){
  40.         i_state = dirps();    /* Tick is modified by an interrupt */
  41.         while(Tick == 0)
  42.             pwait(&Tick);
  43.         Tick = 0;
  44.         restore(i_state);
  45.  
  46.         if(!istate()){
  47.             restore(1);
  48.             printf("timer: ints were off!\n");
  49.         }
  50.  
  51.         /* Call the functions listed in config.c */
  52.         for(vf = Cfunc;*vf != NULL;vf++)
  53.             (*vf)();
  54.  
  55.         tflush();    /* Flush current session output */
  56.         pwait(NULL);    /* Let them all do their writes */
  57.         rflush();    /* Flush out buffered console stuff */
  58.         fflush(stdout);    /* And flush out stdout too */
  59.  
  60.         if(Timers == NULLTIMER)
  61.             continue;    /* No active timers, all done */
  62.  
  63.         /* Initialize null expired timer list */
  64.         expired = NULLTIMER;
  65.  
  66.         /* Move expired timers to expired list. Note use of
  67.          * subtraction and comparison to zero rather than the
  68.          * more obvious simple comparison; this avoids
  69.          * problems when the clock count wraps around.
  70.          */
  71.         while(Timers != NULLTIMER && (Clock - Timers->expiration) >= 0){
  72.             if(Timers->next == Timers){
  73.                 printf("PANIC: Timer loop at %lx\n",
  74.                  (long)Timers);
  75.                 iostop();
  76.                 exit(1);
  77.             }
  78.             /* Save Timers since stop_timer will change it */
  79.             t = Timers;
  80.             stop_timer(t);
  81.             t->state = TIMER_EXPIRE;
  82.             /* Add to expired timer list */
  83.             t->next = expired;
  84.             expired = t;
  85.         }
  86.         /* Now go through the list of expired timers, removing each
  87.          * one and kicking the notify function, if there is one
  88.          */
  89.         while((t = expired) != NULLTIMER){
  90.             expired = t->next;
  91.             if(t->func){
  92.                 (*t->func)(t->arg);
  93.             }
  94.         }
  95.         pwait(NULL);    /* Let them run before handling more ticks */
  96.     }
  97. }
  98. /* Start a timer */
  99. void
  100. start_timer(t)
  101. struct timer *t;
  102. {
  103.     register struct timer *tnext;
  104.     struct timer *tprev = NULLTIMER;
  105.  
  106.     if(t == NULLTIMER)
  107.         return;
  108.     if(t->state == TIMER_RUN)
  109.         stop_timer(t);
  110.     if(t->duration == 0)
  111.         return;        /* A duration value of 0 disables the timer */
  112.  
  113.     t->expiration = Clock + t->duration;
  114.     t->state = TIMER_RUN;
  115.  
  116.     /* Find right place on list for this guy. Once again, note use
  117.      * of subtraction and comparison with zero rather than direct
  118.      * comparison of expiration times.
  119.      */
  120.     for(tnext = Timers;tnext != NULLTIMER;tprev=tnext,tnext = tnext->next){
  121.         if((tnext->expiration - t->expiration) >= 0)
  122.             break;
  123.     }
  124.     /* At this point, tprev points to the entry that should go right
  125.      * before us, and tnext points to the entry just after us. Either or
  126.      * both may be null.
  127.      */
  128.     if(tprev == NULLTIMER)
  129.         Timers = t;        /* Put at beginning */
  130.     else
  131.         tprev->next = t;
  132.  
  133.     t->next = tnext;
  134. }
  135. /* Stop a timer */
  136. void
  137. stop_timer(timer)
  138. struct timer *timer;
  139. {
  140.     register struct timer *t;
  141.     struct timer *tlast = NULLTIMER;
  142.  
  143.     if(timer == NULLTIMER || timer->state != TIMER_RUN)
  144.         return;
  145.  
  146.     /* Verify that timer is really on list */
  147.     for(t = Timers;t != NULLTIMER;tlast = t,t = t->next)
  148.         if(t == timer)
  149.             break;
  150.  
  151.     if(t == NULLTIMER)
  152.         return;        /* Should probably panic here */
  153.  
  154.     /* Delete from active timer list */
  155.     if(tlast != NULLTIMER)
  156.         tlast->next = t->next;
  157.     else
  158.         Timers = t->next;    /* Was first on list */
  159.  
  160.     t->state = TIMER_STOP;
  161. }
  162. /* Return milliseconds remaining on this timer */
  163. int32
  164. read_timer(t)
  165. struct timer *t;
  166. {
  167.     int32 remaining;
  168.  
  169.     if(t == NULLTIMER || t->state != TIMER_RUN)
  170.         return 0;
  171.     remaining = t->expiration - Clock;
  172.     if(remaining <= 0)
  173.         return 0;    /* Already expired */
  174.     else
  175.         return remaining * MSPTICK;
  176. }
  177. void
  178. set_timer(t,interval)
  179. struct timer *t;
  180. int32 interval;
  181. {
  182.     if(t == NULLTIMER)
  183.         return;
  184.     /* Round the interval up to the next full tick, and then
  185.      * add another tick to guarantee that the timeout will not
  186.      * occur before the interval is up. This is necessary because
  187.      * we're asynchronous with the system clock.
  188.      */    
  189.     if(interval != 0)
  190.         t->duration = 1 + (interval + MSPTICK - 1)/MSPTICK;
  191.     else
  192.         t->duration = 0;
  193. }
  194. /* Delay process for specified number of milliseconds.
  195.  * Normally returns 0; returns -1 if aborted by alarm.
  196.  */
  197. int
  198. pause(ms)
  199. int32 ms;
  200. {
  201.     int val;
  202.  
  203.     if(Curproc == NULLPROC || ms == 0)
  204.         return 0;
  205.     alarm(ms);
  206.     /* The actual event doesn't matter, since we'll be alerted */
  207.     while(Curproc->alarm.state == TIMER_RUN){
  208.         if((val = pwait(Curproc)) != 0)
  209.             break;
  210.     }
  211.     alarm(0L); /* Make sure it's stopped, in case we were killed */    
  212.     return (val == EALARM) ? 0 : -1;
  213. }
  214. static void
  215. t_alarm(x)
  216. void *x;
  217. {
  218.     alert((struct proc *)x,EALARM);
  219. }
  220. /* Send signal to current process after specified number of milliseconds */
  221. void
  222. alarm(ms)
  223. int32 ms;
  224. {
  225.     if(Curproc != NULLPROC){
  226.         set_timer(&Curproc->alarm,ms);
  227.         Curproc->alarm.func = t_alarm;
  228.         Curproc->alarm.arg = (char *)Curproc;
  229.         start_timer(&Curproc->alarm);
  230.     }
  231. }
  232. /* Convert time count in seconds to printable days:hr:min:sec format */
  233. char *
  234. tformat(t)
  235. int32 t;
  236. {
  237.     static char buf[17],*cp;
  238.     unsigned int days,hrs,mins,secs;
  239.     int minus;
  240.  
  241.     if(t < 0){
  242.         t = -t;
  243.         minus = 1;
  244.     } else
  245.         minus = 0;
  246.  
  247.     secs = (unsigned int) (t % 60);
  248.     t /= 60;
  249.     mins = (unsigned int) (t % 60);
  250.     t /= 60;
  251.     hrs = (unsigned int) (t % 24);
  252.     t /= 24;
  253.     days = (unsigned int) t;
  254.     if(minus){
  255.         cp = buf+1;
  256.         buf[0] = '-';
  257.     } else
  258.         cp = buf;
  259.     sprintf(cp,"%u:%02u:%02u:%02u",days,hrs,mins,secs);
  260.     
  261.     return buf;
  262. }
  263.     
  264.