1: # include "sendmail.h"
   2: # include <signal.h>
   3: 
   4: SCCSID(@(#)clock.c	4.1		7/25/83);
   5: 
   6: /*
   7: **  SETEVENT -- set an event to happen at a specific time.
   8: **
   9: **	Events are stored in a sorted list for fast processing.
  10: **	An event only applies to the process that set it.
  11: **
  12: **	Parameters:
  13: **		intvl -- intvl until next event occurs.
  14: **		func -- function to call on event.
  15: **		arg -- argument to func on event.
  16: **
  17: **	Returns:
  18: **		none.
  19: **
  20: **	Side Effects:
  21: **		none.
  22: */
  23: 
  24: EVENT *
  25: setevent(intvl, func, arg)
  26:     time_t intvl;
  27:     int (*func)();
  28:     int arg;
  29: {
  30:     register EVENT **evp;
  31:     register EVENT *ev;
  32:     auto time_t now;
  33:     extern tick();
  34: 
  35: # ifdef DEBUG
  36:     if (intvl <= 0)
  37:     {
  38:         syserr("setevent: intvl=%ld\n", intvl);
  39:         return (NULL);
  40:     }
  41: # endif DEBUG
  42: 
  43:     (void) time(&now);
  44: 
  45:     /* search event queue for correct position */
  46:     for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link)
  47:     {
  48:         if (ev->ev_time >= now + intvl)
  49:             break;
  50:     }
  51: 
  52:     /* insert new event */
  53:     ev = (EVENT *) xalloc(sizeof *ev);
  54:     ev->ev_time = now + intvl;
  55:     ev->ev_func = func;
  56:     ev->ev_arg = arg;
  57:     ev->ev_pid = getpid();
  58:     ev->ev_link = *evp;
  59:     *evp = ev;
  60: 
  61: # ifdef DEBUG
  62:     if (tTd(5, 5))
  63:         printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n",
  64:             intvl, now + intvl, func, arg, ev);
  65: # endif DEBUG
  66: 
  67:     tick();
  68:     return (ev);
  69: }
  70: /*
  71: **  CLREVENT -- remove an event from the event queue.
  72: **
  73: **	Parameters:
  74: **		ev -- pointer to event to remove.
  75: **
  76: **	Returns:
  77: **		none.
  78: **
  79: **	Side Effects:
  80: **		arranges for event ev to not happen.
  81: */
  82: 
  83: clrevent(ev)
  84:     register EVENT *ev;
  85: {
  86:     register EVENT **evp;
  87: 
  88: # ifdef DEBUG
  89:     if (tTd(5, 5))
  90:         printf("clrevent: ev=%x\n", ev);
  91: # endif DEBUG
  92:     if (ev == NULL)
  93:         return;
  94: 
  95:     /* find the parent event */
  96:     (void) signal(SIGALRM, SIG_IGN);
  97:     for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
  98:     {
  99:         if (*evp == ev)
 100:             break;
 101:     }
 102: 
 103:     /* now remove it */
 104:     if (*evp != NULL)
 105:     {
 106:         *evp = ev->ev_link;
 107:         free((char *) ev);
 108:     }
 109: 
 110:     /* restore clocks and pick up anything spare */
 111:     tick();
 112: }
 113: /*
 114: **  TICK -- take a clock tick
 115: **
 116: **	Called by the alarm clock.  This routine runs events as needed.
 117: **
 118: **	Parameters:
 119: **		none.
 120: **
 121: **	Returns:
 122: **		none.
 123: **
 124: **	Side Effects:
 125: **		calls the next function in EventQueue.
 126: */
 127: 
 128: tick()
 129: {
 130:     register time_t now;
 131:     register EVENT *ev;
 132: 
 133:     (void) signal(SIGALRM, SIG_IGN);
 134:     (void) alarm(0);
 135:     now = curtime();
 136: 
 137: # ifdef DEBUG
 138:     if (tTd(5, 4))
 139:         printf("tick: now=%ld\n", now);
 140: # endif DEBUG
 141: 
 142:     while ((ev = EventQueue) != NULL &&
 143:            (ev->ev_time <= now || ev->ev_pid != getpid()))
 144:     {
 145:         int (*f)(), a;
 146: 
 147:         /* process the event on the top of the queue */
 148:         ev = EventQueue;
 149:         EventQueue = EventQueue->ev_link;
 150: # ifdef DEBUG
 151:         if (tTd(5, 6))
 152:             printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev,
 153:                 ev->ev_func, ev->ev_arg, ev->ev_pid);
 154: # endif DEBUG
 155: 
 156:         /* we must be careful in here because ev_func may not return */
 157:         (void) signal(SIGALRM, tick);
 158:         f = ev->ev_func;
 159:         a = ev->ev_arg;
 160:         free((char *) ev);
 161:         if (ev->ev_pid != getpid())
 162:             continue;
 163:         if (EventQueue != NULL)
 164:         {
 165:             if (EventQueue->ev_time > now)
 166:                 (void) alarm((unsigned) (EventQueue->ev_time - now));
 167:             else
 168:                 (void) alarm(3);
 169:         }
 170:         (*f)(a);
 171:         (void) alarm(0);
 172:         now = curtime();
 173:     }
 174:     (void) signal(SIGALRM, tick);
 175:     if (EventQueue != NULL)
 176:         (void) alarm((unsigned) (EventQueue->ev_time - now));
 177: }
 178: /*
 179: **  SLEEP -- a version of sleep that works with this stuff
 180: **
 181: **	Because sleep uses the alarm facility, I must reimplement
 182: **	it here.
 183: **
 184: **	Parameters:
 185: **		intvl -- time to sleep.
 186: **
 187: **	Returns:
 188: **		none.
 189: **
 190: **	Side Effects:
 191: **		waits for intvl time.  However, other events can
 192: **		be run during that interval.
 193: */
 194: 
 195: static bool SleepDone;
 196: 
 197: sleep(intvl)
 198:     int intvl;
 199: {
 200:     extern endsleep();
 201: 
 202:     if (intvl == 0)
 203:         return;
 204:     SleepDone = FALSE;
 205:     (void) setevent((time_t) intvl, endsleep, 0);
 206:     while (!SleepDone)
 207:         pause();
 208: }
 209: 
 210: static
 211: endsleep()
 212: {
 213:     SleepDone = TRUE;
 214: }
Last modified: 1983-12-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 906
Valid CSS Valid XHTML 1.0 Strict