xref: /csrg-svn/usr.sbin/sendmail/src/clock.c (revision 56795)
122696Sdist /*
234920Sbostic  * Copyright (c) 1983 Eric P. Allman
333728Sbostic  * Copyright (c) 1988 Regents of the University of California.
433728Sbostic  * All rights reserved.
533728Sbostic  *
642824Sbostic  * %sccs.include.redist.c%
733728Sbostic  */
822696Sdist 
922696Sdist #ifndef lint
10*56795Seric static char sccsid[] = "@(#)clock.c	5.11 (Berkeley) 11/14/92";
1133728Sbostic #endif /* not lint */
1222696Sdist 
137358Seric # include "sendmail.h"
1411728Seric # include <signal.h>
157358Seric 
167358Seric /*
177684Seric **  SETEVENT -- set an event to happen at a specific time.
187684Seric **
199373Seric **	Events are stored in a sorted list for fast processing.
209373Seric **	An event only applies to the process that set it.
219373Seric **
227684Seric **	Parameters:
237684Seric **		intvl -- intvl until next event occurs.
247684Seric **		func -- function to call on event.
257684Seric **		arg -- argument to func on event.
267684Seric **
277684Seric **	Returns:
287684Seric **		none.
297684Seric **
307684Seric **	Side Effects:
317684Seric **		none.
327684Seric */
337684Seric 
3446928Sbostic static void tick();
3546928Sbostic 
367684Seric EVENT *
377684Seric setevent(intvl, func, arg)
387684Seric 	time_t intvl;
397684Seric 	int (*func)();
407684Seric 	int arg;
417684Seric {
427684Seric 	register EVENT **evp;
437684Seric 	register EVENT *ev;
447684Seric 	auto time_t now;
457684Seric 
467757Seric 	if (intvl <= 0)
477757Seric 	{
487757Seric 		syserr("setevent: intvl=%ld\n", intvl);
499346Seric 		return (NULL);
507757Seric 	}
517757Seric 
527684Seric 	(void) time(&now);
537684Seric 
547684Seric 	/* search event queue for correct position */
557684Seric 	for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link)
567684Seric 	{
577684Seric 		if (ev->ev_time >= now + intvl)
587684Seric 			break;
597684Seric 	}
607684Seric 
617684Seric 	/* insert new event */
627684Seric 	ev = (EVENT *) xalloc(sizeof *ev);
637684Seric 	ev->ev_time = now + intvl;
647684Seric 	ev->ev_func = func;
657684Seric 	ev->ev_arg = arg;
667931Seric 	ev->ev_pid = getpid();
677684Seric 	ev->ev_link = *evp;
687684Seric 	*evp = ev;
697684Seric 
708063Seric 	if (tTd(5, 5))
717684Seric 		printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n",
727684Seric 			intvl, now + intvl, func, arg, ev);
737684Seric 
747939Seric 	tick();
757684Seric 	return (ev);
767684Seric }
777684Seric /*
787684Seric **  CLREVENT -- remove an event from the event queue.
797684Seric **
807684Seric **	Parameters:
817684Seric **		ev -- pointer to event to remove.
827684Seric **
837684Seric **	Returns:
847684Seric **		none.
857684Seric **
867684Seric **	Side Effects:
877684Seric **		arranges for event ev to not happen.
887684Seric */
897684Seric 
907684Seric clrevent(ev)
917684Seric 	register EVENT *ev;
927684Seric {
937684Seric 	register EVENT **evp;
947684Seric 
958063Seric 	if (tTd(5, 5))
967684Seric 		printf("clrevent: ev=%x\n", ev);
977757Seric 	if (ev == NULL)
987757Seric 		return;
997684Seric 
1007684Seric 	/* find the parent event */
1019373Seric 	(void) signal(SIGALRM, SIG_IGN);
1027684Seric 	for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
1037684Seric 	{
1047684Seric 		if (*evp == ev)
1057684Seric 			break;
1067684Seric 	}
1077684Seric 
1087684Seric 	/* now remove it */
1097939Seric 	if (*evp != NULL)
1107939Seric 	{
1117939Seric 		*evp = ev->ev_link;
1129346Seric 		free((char *) ev);
1137939Seric 	}
1147862Seric 
1157862Seric 	/* restore clocks and pick up anything spare */
1167862Seric 	tick();
1177684Seric }
1187684Seric /*
1197358Seric **  TICK -- take a clock tick
1207358Seric **
1217684Seric **	Called by the alarm clock.  This routine runs events as needed.
1227358Seric **
1237358Seric **	Parameters:
1247358Seric **		none.
1257358Seric **
1267358Seric **	Returns:
1277684Seric **		none.
1287358Seric **
1297358Seric **	Side Effects:
1307684Seric **		calls the next function in EventQueue.
1317358Seric */
1327358Seric 
13346979Sbostic static void
1347358Seric tick()
1357358Seric {
1367889Seric 	register time_t now;
1377684Seric 	register EVENT *ev;
13824955Seric 	int mypid = getpid();
1397684Seric 
1409373Seric 	(void) signal(SIGALRM, SIG_IGN);
1419373Seric 	(void) alarm(0);
1427889Seric 	now = curtime();
1437684Seric 
1448063Seric 	if (tTd(5, 4))
1457684Seric 		printf("tick: now=%ld\n", now);
1467684Seric 
1478128Seric 	while ((ev = EventQueue) != NULL &&
14824955Seric 	       (ev->ev_time <= now || ev->ev_pid != mypid))
1497684Seric 	{
15016141Seric 		int (*f)();
15116141Seric 		int arg;
15216141Seric 		int pid;
1537862Seric 
1547684Seric 		/* process the event on the top of the queue */
1557684Seric 		ev = EventQueue;
1567684Seric 		EventQueue = EventQueue->ev_link;
1578063Seric 		if (tTd(5, 6))
1587931Seric 			printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev,
1597931Seric 				ev->ev_func, ev->ev_arg, ev->ev_pid);
1607862Seric 
1617862Seric 		/* we must be careful in here because ev_func may not return */
1629373Seric 		(void) signal(SIGALRM, tick);
16320844Seric #ifdef SIGVTALRM
16420844Seric 		/* reset 4.2bsd signal mask to allow future alarms */
16520844Seric 		(void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
166*56795Seric #endif /* SIGVTALRM */
16720844Seric 
1687862Seric 		f = ev->ev_func;
16916141Seric 		arg = ev->ev_arg;
17016141Seric 		pid = ev->ev_pid;
1719346Seric 		free((char *) ev);
17216141Seric 		if (pid != getpid())
1737931Seric 			continue;
1747862Seric 		if (EventQueue != NULL)
1757862Seric 		{
1767862Seric 			if (EventQueue->ev_time > now)
17712635Seric 				(void) alarm((unsigned) (EventQueue->ev_time - now));
1787862Seric 			else
1797889Seric 				(void) alarm(3);
1807862Seric 		}
18116141Seric 		(*f)(arg);
1827862Seric 		(void) alarm(0);
1837889Seric 		now = curtime();
1847684Seric 	}
1859373Seric 	(void) signal(SIGALRM, tick);
1867889Seric 	if (EventQueue != NULL)
18712635Seric 		(void) alarm((unsigned) (EventQueue->ev_time - now));
1887358Seric }
1897690Seric /*
1907690Seric **  SLEEP -- a version of sleep that works with this stuff
1917690Seric **
1927690Seric **	Because sleep uses the alarm facility, I must reimplement
1937690Seric **	it here.
1947690Seric **
1957690Seric **	Parameters:
1967690Seric **		intvl -- time to sleep.
1977690Seric **
1987690Seric **	Returns:
1997690Seric **		none.
2007690Seric **
2017690Seric **	Side Effects:
2027690Seric **		waits for intvl time.  However, other events can
2037690Seric **		be run during that interval.
2047690Seric */
2057690Seric 
2067690Seric static bool	SleepDone;
2077690Seric 
2087690Seric sleep(intvl)
20925615Seric 	unsigned int intvl;
2107690Seric {
21146928Sbostic 	static int endsleep();
2127690Seric 
2137757Seric 	if (intvl == 0)
2147757Seric 		return;
2157690Seric 	SleepDone = FALSE;
21612635Seric 	(void) setevent((time_t) intvl, endsleep, 0);
2177690Seric 	while (!SleepDone)
2187690Seric 		pause();
2197690Seric }
2207690Seric 
2217690Seric static
2227690Seric endsleep()
2237690Seric {
2247690Seric 	SleepDone = TRUE;
2257690Seric }
226