home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65 / src / clock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-05  |  4.9 KB  |  236 lines

  1. /*
  2.  * Copyright (c) 1983 Eric P. Allman
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted provided
  7.  * that: (1) source distributions retain this entire copyright notice and
  8.  * comment, and (2) distributions including binaries display the following
  9.  * acknowledgement:  ``This product includes software developed by the
  10.  * University of California, Berkeley and its contributors'' in the
  11.  * documentation or other materials provided with the distribution and in
  12.  * all advertising materials mentioning features or use of this software.
  13.  * Neither the name of the University nor the names of its contributors may
  14.  * be used to endorse or promote products derived from this software without
  15.  * specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  17.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  18.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20.  
  21. #ifndef lint
  22. static char sccsid[] = "@(#)clock.c    5.8 (Berkeley) 6/1/90";
  23. #endif /* not lint */
  24.  
  25. # include "sendmail.h"
  26. # include <signal.h>
  27.  
  28. /*
  29. **  SETEVENT -- set an event to happen at a specific time.
  30. **
  31. **    Events are stored in a sorted list for fast processing.
  32. **    An event only applies to the process that set it.
  33. **
  34. **    Parameters:
  35. **        intvl -- intvl until next event occurs.
  36. **        func -- function to call on event.
  37. **        arg -- argument to func on event.
  38. **
  39. **    Returns:
  40. **        none.
  41. **
  42. **    Side Effects:
  43. **        none.
  44. */
  45.  
  46. EVENT *
  47. setevent(intvl, func, arg)
  48.     time_t intvl;
  49.     int (*func)();
  50.     int arg;
  51. {
  52.     register EVENT **evp;
  53.     register EVENT *ev;
  54.     auto time_t now;
  55.     extern tick();
  56.  
  57.     if (intvl <= 0)
  58.     {
  59.         syserr("setevent: intvl=%ld\n", intvl);
  60.         return (NULL);
  61.     }
  62.  
  63.     (void) time(&now);
  64.  
  65.     /* search event queue for correct position */
  66.     for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link)
  67.     {
  68.         if (ev->ev_time >= now + intvl)
  69.             break;
  70.     }
  71.  
  72.     /* insert new event */
  73.     ev = (EVENT *) xalloc(sizeof *ev);
  74.     ev->ev_time = now + intvl;
  75.     ev->ev_func = func;
  76.     ev->ev_arg = arg;
  77.     ev->ev_pid = getpid();
  78.     ev->ev_link = *evp;
  79.     *evp = ev;
  80.  
  81.     if (tTd(5, 5))
  82.         printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n",
  83.             intvl, now + intvl, func, arg, ev);
  84.  
  85.     tick();
  86.     return (ev);
  87. }
  88. /*
  89. **  CLREVENT -- remove an event from the event queue.
  90. **
  91. **    Parameters:
  92. **        ev -- pointer to event to remove.
  93. **
  94. **    Returns:
  95. **        none.
  96. **
  97. **    Side Effects:
  98. **        arranges for event ev to not happen.
  99. */
  100.  
  101. clrevent(ev)
  102.     register EVENT *ev;
  103. {
  104.     register EVENT **evp;
  105.  
  106.     if (tTd(5, 5))
  107.         printf("clrevent: ev=%x\n", ev);
  108.     if (ev == NULL)
  109.         return;
  110.  
  111.     /* find the parent event */
  112.     (void) signal(SIGALRM, SIG_IGN);
  113.     for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
  114.     {
  115.         if (*evp == ev)
  116.             break;
  117.     }
  118.  
  119.     /* now remove it */
  120.     if (*evp != NULL)
  121.     {
  122.         *evp = ev->ev_link;
  123.         free((char *) ev);
  124.     }
  125.  
  126.     /* restore clocks and pick up anything spare */
  127.     tick();
  128. }
  129. /*
  130. **  TICK -- take a clock tick
  131. **
  132. **    Called by the alarm clock.  This routine runs events as needed.
  133. **
  134. **    Parameters:
  135. **        none.
  136. **
  137. **    Returns:
  138. **        none.
  139. **
  140. **    Side Effects:
  141. **        calls the next function in EventQueue.
  142. */
  143.  
  144. tick()
  145. {
  146.     register time_t now;
  147.     register EVENT *ev;
  148.     int mypid = getpid();
  149.  
  150.     (void) signal(SIGALRM, SIG_IGN);
  151.     (void) alarm(0);
  152.     now = curtime();
  153.  
  154.     if (tTd(5, 4))
  155.         printf("tick: now=%ld\n", now);
  156.  
  157.     while ((ev = EventQueue) != NULL &&
  158.            (ev->ev_time <= now || ev->ev_pid != mypid))
  159.     {
  160.         int (*f)();
  161.         int arg;
  162.         int pid;
  163.  
  164.         /* process the event on the top of the queue */
  165.         ev = EventQueue;
  166.         EventQueue = EventQueue->ev_link;
  167.         if (tTd(5, 6))
  168.             printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev,
  169.                 ev->ev_func, ev->ev_arg, ev->ev_pid);
  170.  
  171.         /* we must be careful in here because ev_func may not return */
  172.         (void) signal(SIGALRM, tick);
  173. #ifdef SIGVTALRM
  174.         /* reset 4.2bsd signal mask to allow future alarms */
  175.         (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
  176. #endif SIGVTALRM
  177.  
  178.         f = ev->ev_func;
  179.         arg = ev->ev_arg;
  180.         pid = ev->ev_pid;
  181.         free((char *) ev);
  182.         if (pid != getpid())
  183.             continue;
  184.         if (EventQueue != NULL)
  185.         {
  186.             if (EventQueue->ev_time > now)
  187.                 (void) alarm((unsigned) (EventQueue->ev_time - now));
  188.             else
  189.                 (void) alarm(3);
  190.         }
  191.         (*f)(arg);
  192.         (void) alarm(0);
  193.         now = curtime();
  194.     }
  195.     (void) signal(SIGALRM, tick);
  196.     if (EventQueue != NULL)
  197.         (void) alarm((unsigned) (EventQueue->ev_time - now));
  198. }
  199. /*
  200. **  SLEEP -- a version of sleep that works with this stuff
  201. **
  202. **    Because sleep uses the alarm facility, I must reimplement
  203. **    it here.
  204. **
  205. **    Parameters:
  206. **        intvl -- time to sleep.
  207. **
  208. **    Returns:
  209. **        none.
  210. **
  211. **    Side Effects:
  212. **        waits for intvl time.  However, other events can
  213. **        be run during that interval.
  214. */
  215.  
  216. static bool    SleepDone;
  217.  
  218. sleep(intvl)
  219.     unsigned int intvl;
  220. {
  221.     extern endsleep();
  222.  
  223.     if (intvl == 0)
  224.         return;
  225.     SleepDone = FALSE;
  226.     (void) setevent((time_t) intvl, endsleep, 0);
  227.     while (!SleepDone)
  228.         pause();
  229. }
  230.  
  231. static
  232. endsleep()
  233. {
  234.     SleepDone = TRUE;
  235. }
  236.