xref: /illumos-gate/usr/src/cmd/sendmail/libsm/clock.c (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *	All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
57c478bd9Sstevel@tonic-gate  * Copyright (c) 1988, 1993
67c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
97c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
107c478bd9Sstevel@tonic-gate  * the sendmail distribution.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  */
137c478bd9Sstevel@tonic-gate 
147c478bd9Sstevel@tonic-gate #include <sm/gen.h>
15*49218d4fSjbeck SM_RCSID("@(#)$Id: clock.c,v 1.47 2005/06/14 23:07:20 ca Exp $")
167c478bd9Sstevel@tonic-gate #include <unistd.h>
177c478bd9Sstevel@tonic-gate #include <time.h>
187c478bd9Sstevel@tonic-gate #include <errno.h>
197c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
20*49218d4fSjbeck # include <sm/time.h>
217c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
227c478bd9Sstevel@tonic-gate #include <sm/heap.h>
237c478bd9Sstevel@tonic-gate #include <sm/debug.h>
247c478bd9Sstevel@tonic-gate #include <sm/bitops.h>
257c478bd9Sstevel@tonic-gate #include <sm/clock.h>
267c478bd9Sstevel@tonic-gate #include "local.h"
277c478bd9Sstevel@tonic-gate #if _FFR_SLEEP_USE_SELECT > 0
287c478bd9Sstevel@tonic-gate # include <sys/types.h>
297c478bd9Sstevel@tonic-gate #endif /* _FFR_SLEEP_USE_SELECT > 0 */
307c478bd9Sstevel@tonic-gate #if defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2
317c478bd9Sstevel@tonic-gate # include <syslog.h>
327c478bd9Sstevel@tonic-gate #endif /* defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2 */
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate #ifndef sigmask
357c478bd9Sstevel@tonic-gate # define sigmask(s)	(1 << ((s) - 1))
367c478bd9Sstevel@tonic-gate #endif /* ! sigmask */
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate **  SM_SETEVENTM -- set an event to happen at a specific time in milliseconds.
417c478bd9Sstevel@tonic-gate **
427c478bd9Sstevel@tonic-gate **	Events are stored in a sorted list for fast processing.
437c478bd9Sstevel@tonic-gate **	An event only applies to the process that set it.
447c478bd9Sstevel@tonic-gate **	Source is #ifdef'd to work with older OS's that don't have setitimer()
457c478bd9Sstevel@tonic-gate **	(that is, don't have a timer granularity less than 1 second).
467c478bd9Sstevel@tonic-gate **
477c478bd9Sstevel@tonic-gate **	Parameters:
487c478bd9Sstevel@tonic-gate **		intvl -- interval until next event occurs (milliseconds).
497c478bd9Sstevel@tonic-gate **		func -- function to call on event.
507c478bd9Sstevel@tonic-gate **		arg -- argument to func on event.
517c478bd9Sstevel@tonic-gate **
527c478bd9Sstevel@tonic-gate **	Returns:
537c478bd9Sstevel@tonic-gate **		On success returns the SM_EVENT entry created.
547c478bd9Sstevel@tonic-gate **		On failure returns NULL.
557c478bd9Sstevel@tonic-gate **
567c478bd9Sstevel@tonic-gate **	Side Effects:
577c478bd9Sstevel@tonic-gate **		none.
587c478bd9Sstevel@tonic-gate */
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate static SM_EVENT	*volatile SmEventQueue;		/* head of event queue */
617c478bd9Sstevel@tonic-gate static SM_EVENT	*volatile SmFreeEventList;	/* list of free events */
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate SM_EVENT *
sm_seteventm(intvl,func,arg)647c478bd9Sstevel@tonic-gate sm_seteventm(intvl, func, arg)
657c478bd9Sstevel@tonic-gate 	int intvl;
667c478bd9Sstevel@tonic-gate 	void (*func)__P((int));
677c478bd9Sstevel@tonic-gate 	int arg;
687c478bd9Sstevel@tonic-gate {
697c478bd9Sstevel@tonic-gate 	ENTER_CRITICAL();
707c478bd9Sstevel@tonic-gate 	if (SmFreeEventList == NULL)
717c478bd9Sstevel@tonic-gate 	{
727c478bd9Sstevel@tonic-gate 		SmFreeEventList = (SM_EVENT *) sm_pmalloc_x(sizeof *SmFreeEventList);
737c478bd9Sstevel@tonic-gate 		SmFreeEventList->ev_link = NULL;
747c478bd9Sstevel@tonic-gate 	}
757c478bd9Sstevel@tonic-gate 	LEAVE_CRITICAL();
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 	return sm_sigsafe_seteventm(intvl, func, arg);
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /*
817c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
827c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
837c478bd9Sstevel@tonic-gate **		DOING.
847c478bd9Sstevel@tonic-gate */
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate SM_EVENT *
sm_sigsafe_seteventm(intvl,func,arg)877c478bd9Sstevel@tonic-gate sm_sigsafe_seteventm(intvl, func, arg)
887c478bd9Sstevel@tonic-gate 	int intvl;
897c478bd9Sstevel@tonic-gate 	void (*func)__P((int));
907c478bd9Sstevel@tonic-gate 	int arg;
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate 	register SM_EVENT **evp;
937c478bd9Sstevel@tonic-gate 	register SM_EVENT *ev;
947c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
957c478bd9Sstevel@tonic-gate 	auto struct timeval now, nowi, ival;
967c478bd9Sstevel@tonic-gate 	auto struct itimerval itime;
977c478bd9Sstevel@tonic-gate #else /*  SM_CONF_SETITIMER */
987c478bd9Sstevel@tonic-gate 	auto time_t now, nowi;
997c478bd9Sstevel@tonic-gate #endif /*  SM_CONF_SETITIMER */
1007c478bd9Sstevel@tonic-gate 	int wasblocked;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	/* negative times are not allowed */
1037c478bd9Sstevel@tonic-gate 	if (intvl <= 0)
1047c478bd9Sstevel@tonic-gate 		return NULL;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	wasblocked = sm_blocksignal(SIGALRM);
1077c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
1087c478bd9Sstevel@tonic-gate 	ival.tv_sec = intvl / 1000;
1097c478bd9Sstevel@tonic-gate 	ival.tv_usec = (intvl - ival.tv_sec * 1000) * 10;
1107c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&now, NULL);
1117c478bd9Sstevel@tonic-gate 	nowi = now;
1127c478bd9Sstevel@tonic-gate 	timeradd(&now, &ival, &nowi);
1137c478bd9Sstevel@tonic-gate #else /*  SM_CONF_SETITIMER */
1147c478bd9Sstevel@tonic-gate 	now = time(NULL);
1157c478bd9Sstevel@tonic-gate 	nowi = now + (time_t)(intvl / 1000);
1167c478bd9Sstevel@tonic-gate #endif /*  SM_CONF_SETITIMER */
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	/* search event queue for correct position */
1197c478bd9Sstevel@tonic-gate 	for (evp = (SM_EVENT **) (&SmEventQueue);
1207c478bd9Sstevel@tonic-gate 	     (ev = *evp) != NULL;
1217c478bd9Sstevel@tonic-gate 	     evp = &ev->ev_link)
1227c478bd9Sstevel@tonic-gate 	{
1237c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
1247c478bd9Sstevel@tonic-gate 		if (timercmp(&(ev->ev_time), &nowi, >=))
1257c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
1267c478bd9Sstevel@tonic-gate 		if (ev->ev_time >= nowi)
1277c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
1287c478bd9Sstevel@tonic-gate 			break;
1297c478bd9Sstevel@tonic-gate 	}
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	ENTER_CRITICAL();
1327c478bd9Sstevel@tonic-gate 	if (SmFreeEventList == NULL)
1337c478bd9Sstevel@tonic-gate 	{
1347c478bd9Sstevel@tonic-gate 		/*
1357c478bd9Sstevel@tonic-gate 		**  This shouldn't happen.  If called from sm_seteventm(),
1367c478bd9Sstevel@tonic-gate 		**  we have just malloced a SmFreeEventList entry.  If
1377c478bd9Sstevel@tonic-gate 		**  called from a signal handler, it should have been
1387c478bd9Sstevel@tonic-gate 		**  from an existing event which sm_tick() just added to
1397c478bd9Sstevel@tonic-gate 		**  SmFreeEventList.
1407c478bd9Sstevel@tonic-gate 		*/
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 		LEAVE_CRITICAL();
1437c478bd9Sstevel@tonic-gate 		if (wasblocked == 0)
1447c478bd9Sstevel@tonic-gate 			(void) sm_releasesignal(SIGALRM);
1457c478bd9Sstevel@tonic-gate 		return NULL;
1467c478bd9Sstevel@tonic-gate 	}
1477c478bd9Sstevel@tonic-gate 	else
1487c478bd9Sstevel@tonic-gate 	{
1497c478bd9Sstevel@tonic-gate 		ev = SmFreeEventList;
1507c478bd9Sstevel@tonic-gate 		SmFreeEventList = ev->ev_link;
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 	LEAVE_CRITICAL();
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 	/* insert new event */
1557c478bd9Sstevel@tonic-gate 	ev->ev_time = nowi;
1567c478bd9Sstevel@tonic-gate 	ev->ev_func = func;
1577c478bd9Sstevel@tonic-gate 	ev->ev_arg = arg;
1587c478bd9Sstevel@tonic-gate 	ev->ev_pid = getpid();
1597c478bd9Sstevel@tonic-gate 	ENTER_CRITICAL();
1607c478bd9Sstevel@tonic-gate 	ev->ev_link = *evp;
1617c478bd9Sstevel@tonic-gate 	*evp = ev;
1627c478bd9Sstevel@tonic-gate 	LEAVE_CRITICAL();
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	(void) sm_signal(SIGALRM, sm_tick);
1657c478bd9Sstevel@tonic-gate # if SM_CONF_SETITIMER
1667c478bd9Sstevel@tonic-gate 	timersub(&SmEventQueue->ev_time, &now, &itime.it_value);
1677c478bd9Sstevel@tonic-gate 	itime.it_interval.tv_sec = 0;
1687c478bd9Sstevel@tonic-gate 	itime.it_interval.tv_usec = 0;
1697c478bd9Sstevel@tonic-gate 	if (itime.it_value.tv_sec < 0)
1707c478bd9Sstevel@tonic-gate 		itime.it_value.tv_sec = 0;
1717c478bd9Sstevel@tonic-gate 	if (itime.it_value.tv_sec == 0 && itime.it_value.tv_usec == 0)
1727c478bd9Sstevel@tonic-gate 		itime.it_value.tv_usec = 1000;
1737c478bd9Sstevel@tonic-gate 	(void) setitimer(ITIMER_REAL, &itime, NULL);
1747c478bd9Sstevel@tonic-gate # else /* SM_CONF_SETITIMER */
1757c478bd9Sstevel@tonic-gate 	intvl = SmEventQueue->ev_time - now;
1767c478bd9Sstevel@tonic-gate 	(void) alarm((unsigned) (intvl < 1 ? 1 : intvl));
1777c478bd9Sstevel@tonic-gate # endif /* SM_CONF_SETITIMER */
1787c478bd9Sstevel@tonic-gate 	if (wasblocked == 0)
1797c478bd9Sstevel@tonic-gate 		(void) sm_releasesignal(SIGALRM);
1807c478bd9Sstevel@tonic-gate 	return ev;
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate **  SM_CLREVENT -- remove an event from the event queue.
1847c478bd9Sstevel@tonic-gate **
1857c478bd9Sstevel@tonic-gate **	Parameters:
1867c478bd9Sstevel@tonic-gate **		ev -- pointer to event to remove.
1877c478bd9Sstevel@tonic-gate **
1887c478bd9Sstevel@tonic-gate **	Returns:
1897c478bd9Sstevel@tonic-gate **		none.
1907c478bd9Sstevel@tonic-gate **
1917c478bd9Sstevel@tonic-gate **	Side Effects:
1927c478bd9Sstevel@tonic-gate **		arranges for event ev to not happen.
1937c478bd9Sstevel@tonic-gate */
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate void
sm_clrevent(ev)1967c478bd9Sstevel@tonic-gate sm_clrevent(ev)
1977c478bd9Sstevel@tonic-gate 	register SM_EVENT *ev;
1987c478bd9Sstevel@tonic-gate {
1997c478bd9Sstevel@tonic-gate 	register SM_EVENT **evp;
2007c478bd9Sstevel@tonic-gate 	int wasblocked;
2017c478bd9Sstevel@tonic-gate # if SM_CONF_SETITIMER
2027c478bd9Sstevel@tonic-gate 	struct itimerval clr;
2037c478bd9Sstevel@tonic-gate # endif /* SM_CONF_SETITIMER */
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	if (ev == NULL)
2067c478bd9Sstevel@tonic-gate 		return;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	/* find the parent event */
2097c478bd9Sstevel@tonic-gate 	wasblocked = sm_blocksignal(SIGALRM);
2107c478bd9Sstevel@tonic-gate 	for (evp = (SM_EVENT **) (&SmEventQueue);
2117c478bd9Sstevel@tonic-gate 	     *evp != NULL;
2127c478bd9Sstevel@tonic-gate 	     evp = &(*evp)->ev_link)
2137c478bd9Sstevel@tonic-gate 	{
2147c478bd9Sstevel@tonic-gate 		if (*evp == ev)
2157c478bd9Sstevel@tonic-gate 			break;
2167c478bd9Sstevel@tonic-gate 	}
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	/* now remove it */
2197c478bd9Sstevel@tonic-gate 	if (*evp != NULL)
2207c478bd9Sstevel@tonic-gate 	{
2217c478bd9Sstevel@tonic-gate 		ENTER_CRITICAL();
2227c478bd9Sstevel@tonic-gate 		*evp = ev->ev_link;
2237c478bd9Sstevel@tonic-gate 		ev->ev_link = SmFreeEventList;
2247c478bd9Sstevel@tonic-gate 		SmFreeEventList = ev;
2257c478bd9Sstevel@tonic-gate 		LEAVE_CRITICAL();
2267c478bd9Sstevel@tonic-gate 	}
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	/* restore clocks and pick up anything spare */
2297c478bd9Sstevel@tonic-gate 	if (wasblocked == 0)
2307c478bd9Sstevel@tonic-gate 		(void) sm_releasesignal(SIGALRM);
2317c478bd9Sstevel@tonic-gate 	if (SmEventQueue != NULL)
2327c478bd9Sstevel@tonic-gate 		(void) kill(getpid(), SIGALRM);
2337c478bd9Sstevel@tonic-gate 	else
2347c478bd9Sstevel@tonic-gate 	{
2357c478bd9Sstevel@tonic-gate 		/* nothing left in event queue, no need for an alarm */
2367c478bd9Sstevel@tonic-gate # if SM_CONF_SETITIMER
2377c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_sec = 0;
2387c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_usec = 0;
2397c478bd9Sstevel@tonic-gate 		clr.it_value.tv_sec = 0;
2407c478bd9Sstevel@tonic-gate 		clr.it_value.tv_usec = 0;
2417c478bd9Sstevel@tonic-gate 		(void) setitimer(ITIMER_REAL, &clr, NULL);
2427c478bd9Sstevel@tonic-gate # else /* SM_CONF_SETITIMER */
2437c478bd9Sstevel@tonic-gate 		(void) alarm(0);
2447c478bd9Sstevel@tonic-gate # endif /* SM_CONF_SETITIMER */
2457c478bd9Sstevel@tonic-gate 	}
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate /*
2487c478bd9Sstevel@tonic-gate **  SM_CLEAR_EVENTS -- remove all events from the event queue.
2497c478bd9Sstevel@tonic-gate **
2507c478bd9Sstevel@tonic-gate **	Parameters:
2517c478bd9Sstevel@tonic-gate **		none.
2527c478bd9Sstevel@tonic-gate **
2537c478bd9Sstevel@tonic-gate **	Returns:
2547c478bd9Sstevel@tonic-gate **		none.
2557c478bd9Sstevel@tonic-gate */
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate void
sm_clear_events()2587c478bd9Sstevel@tonic-gate sm_clear_events()
2597c478bd9Sstevel@tonic-gate {
2607c478bd9Sstevel@tonic-gate 	register SM_EVENT *ev;
2617c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
2627c478bd9Sstevel@tonic-gate 	struct itimerval clr;
2637c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
2647c478bd9Sstevel@tonic-gate 	int wasblocked;
2657c478bd9Sstevel@tonic-gate 
2667c478bd9Sstevel@tonic-gate 	/* nothing will be left in event queue, no need for an alarm */
2677c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
2687c478bd9Sstevel@tonic-gate 	clr.it_interval.tv_sec = 0;
2697c478bd9Sstevel@tonic-gate 	clr.it_interval.tv_usec = 0;
2707c478bd9Sstevel@tonic-gate 	clr.it_value.tv_sec = 0;
2717c478bd9Sstevel@tonic-gate 	clr.it_value.tv_usec = 0;
2727c478bd9Sstevel@tonic-gate 	(void) setitimer(ITIMER_REAL, &clr, NULL);
2737c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
2747c478bd9Sstevel@tonic-gate 	(void) alarm(0);
2757c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate 	if (SmEventQueue == NULL)
2787c478bd9Sstevel@tonic-gate 		return;
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	wasblocked = sm_blocksignal(SIGALRM);
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 	/* find the end of the EventQueue */
2837c478bd9Sstevel@tonic-gate 	for (ev = SmEventQueue; ev->ev_link != NULL; ev = ev->ev_link)
2847c478bd9Sstevel@tonic-gate 		continue;
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate 	ENTER_CRITICAL();
2877c478bd9Sstevel@tonic-gate 	ev->ev_link = SmFreeEventList;
2887c478bd9Sstevel@tonic-gate 	SmFreeEventList = SmEventQueue;
2897c478bd9Sstevel@tonic-gate 	SmEventQueue = NULL;
2907c478bd9Sstevel@tonic-gate 	LEAVE_CRITICAL();
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	/* restore clocks and pick up anything spare */
2937c478bd9Sstevel@tonic-gate 	if (wasblocked == 0)
2947c478bd9Sstevel@tonic-gate 		(void) sm_releasesignal(SIGALRM);
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate /*
2977c478bd9Sstevel@tonic-gate **  SM_TICK -- take a clock tick
2987c478bd9Sstevel@tonic-gate **
2997c478bd9Sstevel@tonic-gate **	Called by the alarm clock.  This routine runs events as needed.
3007c478bd9Sstevel@tonic-gate **	Always called as a signal handler, so we assume that SIGALRM
3017c478bd9Sstevel@tonic-gate **	has been blocked.
3027c478bd9Sstevel@tonic-gate **
3037c478bd9Sstevel@tonic-gate **	Parameters:
3047c478bd9Sstevel@tonic-gate **		One that is ignored; for compatibility with signal handlers.
3057c478bd9Sstevel@tonic-gate **
3067c478bd9Sstevel@tonic-gate **	Returns:
3077c478bd9Sstevel@tonic-gate **		none.
3087c478bd9Sstevel@tonic-gate **
3097c478bd9Sstevel@tonic-gate **	Side Effects:
3107c478bd9Sstevel@tonic-gate **		calls the next function in EventQueue.
3117c478bd9Sstevel@tonic-gate **
3127c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
3137c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
3147c478bd9Sstevel@tonic-gate **		DOING.
3157c478bd9Sstevel@tonic-gate */
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate /* ARGSUSED */
3187c478bd9Sstevel@tonic-gate SIGFUNC_DECL
sm_tick(sig)3197c478bd9Sstevel@tonic-gate sm_tick(sig)
3207c478bd9Sstevel@tonic-gate 	int sig;
3217c478bd9Sstevel@tonic-gate {
3227c478bd9Sstevel@tonic-gate 	register SM_EVENT *ev;
3237c478bd9Sstevel@tonic-gate 	pid_t mypid;
3247c478bd9Sstevel@tonic-gate 	int save_errno = errno;
3257c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
3267c478bd9Sstevel@tonic-gate 	struct itimerval clr;
3277c478bd9Sstevel@tonic-gate 	struct timeval now;
3287c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
3297c478bd9Sstevel@tonic-gate 	register time_t now;
3307c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
3337c478bd9Sstevel@tonic-gate 	clr.it_interval.tv_sec = 0;
3347c478bd9Sstevel@tonic-gate 	clr.it_interval.tv_usec = 0;
3357c478bd9Sstevel@tonic-gate 	clr.it_value.tv_sec = 0;
3367c478bd9Sstevel@tonic-gate 	clr.it_value.tv_usec = 0;
3377c478bd9Sstevel@tonic-gate 	(void) setitimer(ITIMER_REAL, &clr, NULL);
3387c478bd9Sstevel@tonic-gate 	gettimeofday(&now, NULL);
3397c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
3407c478bd9Sstevel@tonic-gate 	(void) alarm(0);
3417c478bd9Sstevel@tonic-gate 	now = time(NULL);
3427c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate 	FIX_SYSV_SIGNAL(sig, sm_tick);
3457c478bd9Sstevel@tonic-gate 	errno = save_errno;
3467c478bd9Sstevel@tonic-gate 	CHECK_CRITICAL(sig);
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	mypid = getpid();
3497c478bd9Sstevel@tonic-gate 	while (PendingSignal != 0)
3507c478bd9Sstevel@tonic-gate 	{
3517c478bd9Sstevel@tonic-gate 		int sigbit = 0;
3527c478bd9Sstevel@tonic-gate 		int sig = 0;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 		if (bitset(PEND_SIGHUP, PendingSignal))
3557c478bd9Sstevel@tonic-gate 		{
3567c478bd9Sstevel@tonic-gate 			sigbit = PEND_SIGHUP;
3577c478bd9Sstevel@tonic-gate 			sig = SIGHUP;
3587c478bd9Sstevel@tonic-gate 		}
3597c478bd9Sstevel@tonic-gate 		else if (bitset(PEND_SIGINT, PendingSignal))
3607c478bd9Sstevel@tonic-gate 		{
3617c478bd9Sstevel@tonic-gate 			sigbit = PEND_SIGINT;
3627c478bd9Sstevel@tonic-gate 			sig = SIGINT;
3637c478bd9Sstevel@tonic-gate 		}
3647c478bd9Sstevel@tonic-gate 		else if (bitset(PEND_SIGTERM, PendingSignal))
3657c478bd9Sstevel@tonic-gate 		{
3667c478bd9Sstevel@tonic-gate 			sigbit = PEND_SIGTERM;
3677c478bd9Sstevel@tonic-gate 			sig = SIGTERM;
3687c478bd9Sstevel@tonic-gate 		}
3697c478bd9Sstevel@tonic-gate 		else if (bitset(PEND_SIGUSR1, PendingSignal))
3707c478bd9Sstevel@tonic-gate 		{
3717c478bd9Sstevel@tonic-gate 			sigbit = PEND_SIGUSR1;
3727c478bd9Sstevel@tonic-gate 			sig = SIGUSR1;
3737c478bd9Sstevel@tonic-gate 		}
3747c478bd9Sstevel@tonic-gate 		else
3757c478bd9Sstevel@tonic-gate 		{
3767c478bd9Sstevel@tonic-gate 			/* If we get here, we are in trouble */
3777c478bd9Sstevel@tonic-gate 			abort();
3787c478bd9Sstevel@tonic-gate 		}
3797c478bd9Sstevel@tonic-gate 		PendingSignal &= ~sigbit;
3807c478bd9Sstevel@tonic-gate 		kill(mypid, sig);
3817c478bd9Sstevel@tonic-gate 	}
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
3847c478bd9Sstevel@tonic-gate 	gettimeofday(&now, NULL);
3857c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
3867c478bd9Sstevel@tonic-gate 	now = time(NULL);
3877c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
3887c478bd9Sstevel@tonic-gate 	while ((ev = SmEventQueue) != NULL &&
3897c478bd9Sstevel@tonic-gate 	       (ev->ev_pid != mypid ||
3907c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
3917c478bd9Sstevel@tonic-gate 		timercmp(&ev->ev_time, &now, <=)
3927c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
3937c478bd9Sstevel@tonic-gate 		ev->ev_time <= now
3947c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
3957c478bd9Sstevel@tonic-gate 		))
3967c478bd9Sstevel@tonic-gate 	{
3977c478bd9Sstevel@tonic-gate 		void (*f)__P((int));
3987c478bd9Sstevel@tonic-gate 		int arg;
3997c478bd9Sstevel@tonic-gate 		pid_t pid;
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 		/* process the event on the top of the queue */
4027c478bd9Sstevel@tonic-gate 		ev = SmEventQueue;
4037c478bd9Sstevel@tonic-gate 		SmEventQueue = SmEventQueue->ev_link;
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 		/* we must be careful in here because ev_func may not return */
4067c478bd9Sstevel@tonic-gate 		f = ev->ev_func;
4077c478bd9Sstevel@tonic-gate 		arg = ev->ev_arg;
4087c478bd9Sstevel@tonic-gate 		pid = ev->ev_pid;
4097c478bd9Sstevel@tonic-gate 		ENTER_CRITICAL();
4107c478bd9Sstevel@tonic-gate 		ev->ev_link = SmFreeEventList;
4117c478bd9Sstevel@tonic-gate 		SmFreeEventList = ev;
4127c478bd9Sstevel@tonic-gate 		LEAVE_CRITICAL();
4137c478bd9Sstevel@tonic-gate 		if (pid != getpid())
4147c478bd9Sstevel@tonic-gate 			continue;
4157c478bd9Sstevel@tonic-gate 		if (SmEventQueue != NULL)
4167c478bd9Sstevel@tonic-gate 		{
4177c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
4187c478bd9Sstevel@tonic-gate 			if (timercmp(&SmEventQueue->ev_time, &now, >))
4197c478bd9Sstevel@tonic-gate 			{
4207c478bd9Sstevel@tonic-gate 				timersub(&SmEventQueue->ev_time, &now,
4217c478bd9Sstevel@tonic-gate 					 &clr.it_value);
4227c478bd9Sstevel@tonic-gate 				clr.it_interval.tv_sec = 0;
4237c478bd9Sstevel@tonic-gate 				clr.it_interval.tv_usec = 0;
4247c478bd9Sstevel@tonic-gate 				if (clr.it_value.tv_sec < 0)
4257c478bd9Sstevel@tonic-gate 					clr.it_value.tv_sec = 0;
4267c478bd9Sstevel@tonic-gate 				if (clr.it_value.tv_sec == 0 &&
4277c478bd9Sstevel@tonic-gate 				    clr.it_value.tv_usec == 0)
4287c478bd9Sstevel@tonic-gate 					clr.it_value.tv_usec = 1000;
4297c478bd9Sstevel@tonic-gate 				(void) setitimer(ITIMER_REAL, &clr, NULL);
4307c478bd9Sstevel@tonic-gate 			}
4317c478bd9Sstevel@tonic-gate 			else
4327c478bd9Sstevel@tonic-gate 			{
4337c478bd9Sstevel@tonic-gate 				clr.it_interval.tv_sec = 0;
4347c478bd9Sstevel@tonic-gate 				clr.it_interval.tv_usec = 0;
4357c478bd9Sstevel@tonic-gate 				clr.it_value.tv_sec = 3;
4367c478bd9Sstevel@tonic-gate 				clr.it_value.tv_usec = 0;
4377c478bd9Sstevel@tonic-gate 				(void) setitimer(ITIMER_REAL, &clr, NULL);
4387c478bd9Sstevel@tonic-gate 			}
4397c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
4407c478bd9Sstevel@tonic-gate 			if (SmEventQueue->ev_time > now)
4417c478bd9Sstevel@tonic-gate 				(void) alarm((unsigned) (SmEventQueue->ev_time
4427c478bd9Sstevel@tonic-gate 							 - now));
4437c478bd9Sstevel@tonic-gate 			else
4447c478bd9Sstevel@tonic-gate 				(void) alarm(3);
4457c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
4467c478bd9Sstevel@tonic-gate 		}
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 		/* call ev_func */
4497c478bd9Sstevel@tonic-gate 		errno = save_errno;
4507c478bd9Sstevel@tonic-gate 		(*f)(arg);
4517c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
4527c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_sec = 0;
4537c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_usec = 0;
4547c478bd9Sstevel@tonic-gate 		clr.it_value.tv_sec = 0;
4557c478bd9Sstevel@tonic-gate 		clr.it_value.tv_usec = 0;
4567c478bd9Sstevel@tonic-gate 		(void) setitimer(ITIMER_REAL, &clr, NULL);
4577c478bd9Sstevel@tonic-gate 		gettimeofday(&now, NULL);
4587c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
4597c478bd9Sstevel@tonic-gate 		(void) alarm(0);
4607c478bd9Sstevel@tonic-gate 		now = time(NULL);
4617c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
4627c478bd9Sstevel@tonic-gate 	}
4637c478bd9Sstevel@tonic-gate 	if (SmEventQueue != NULL)
4647c478bd9Sstevel@tonic-gate 	{
4657c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
4667c478bd9Sstevel@tonic-gate 		timersub(&SmEventQueue->ev_time, &now, &clr.it_value);
4677c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_sec = 0;
4687c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_usec = 0;
4697c478bd9Sstevel@tonic-gate 		if (clr.it_value.tv_sec < 0)
4707c478bd9Sstevel@tonic-gate 			clr.it_value.tv_sec = 0;
4717c478bd9Sstevel@tonic-gate 		if (clr.it_value.tv_sec == 0 && clr.it_value.tv_usec == 0)
4727c478bd9Sstevel@tonic-gate 			clr.it_value.tv_usec = 1000;
4737c478bd9Sstevel@tonic-gate 		(void) setitimer(ITIMER_REAL, &clr, NULL);
4747c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
4757c478bd9Sstevel@tonic-gate 		(void) alarm((unsigned) (SmEventQueue->ev_time - now));
4767c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
4777c478bd9Sstevel@tonic-gate 	}
4787c478bd9Sstevel@tonic-gate 	errno = save_errno;
4797c478bd9Sstevel@tonic-gate 	return SIGFUNC_RETURN;
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate /*
4827c478bd9Sstevel@tonic-gate **  SLEEP -- a version of sleep that works with this stuff
4837c478bd9Sstevel@tonic-gate **
4847c478bd9Sstevel@tonic-gate **	Because Unix sleep uses the alarm facility, I must reimplement
4857c478bd9Sstevel@tonic-gate **	it here.
4867c478bd9Sstevel@tonic-gate **
4877c478bd9Sstevel@tonic-gate **	Parameters:
4887c478bd9Sstevel@tonic-gate **		intvl -- time to sleep.
4897c478bd9Sstevel@tonic-gate **
4907c478bd9Sstevel@tonic-gate **	Returns:
4917c478bd9Sstevel@tonic-gate **		zero.
4927c478bd9Sstevel@tonic-gate **
4937c478bd9Sstevel@tonic-gate **	Side Effects:
4947c478bd9Sstevel@tonic-gate **		waits for intvl time.  However, other events can
4957c478bd9Sstevel@tonic-gate **		be run during that interval.
4967c478bd9Sstevel@tonic-gate */
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate # if !HAVE_NANOSLEEP
5007c478bd9Sstevel@tonic-gate static void	sm_endsleep __P((int));
5017c478bd9Sstevel@tonic-gate static bool	volatile SmSleepDone;
5027c478bd9Sstevel@tonic-gate # endif /* !HAVE_NANOSLEEP */
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate #ifndef SLEEP_T
5057c478bd9Sstevel@tonic-gate # define SLEEP_T	unsigned int
5067c478bd9Sstevel@tonic-gate #endif /* ! SLEEP_T */
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate SLEEP_T
sleep(intvl)5097c478bd9Sstevel@tonic-gate sleep(intvl)
5107c478bd9Sstevel@tonic-gate 	unsigned int intvl;
5117c478bd9Sstevel@tonic-gate {
5127c478bd9Sstevel@tonic-gate #if HAVE_NANOSLEEP
5137c478bd9Sstevel@tonic-gate 	struct timespec rqtp;
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate 	if (intvl == 0)
5167c478bd9Sstevel@tonic-gate 		return (SLEEP_T) 0;
5177c478bd9Sstevel@tonic-gate 	rqtp.tv_sec = intvl;
5187c478bd9Sstevel@tonic-gate 	rqtp.tv_nsec = 0;
5197c478bd9Sstevel@tonic-gate 	nanosleep(&rqtp, NULL);
5207c478bd9Sstevel@tonic-gate 	return (SLEEP_T) 0;
5217c478bd9Sstevel@tonic-gate #else /* HAVE_NANOSLEEP */
5227c478bd9Sstevel@tonic-gate 	int was_held;
5237c478bd9Sstevel@tonic-gate 	SM_EVENT *ev;
5247c478bd9Sstevel@tonic-gate #if _FFR_SLEEP_USE_SELECT > 0
5257c478bd9Sstevel@tonic-gate 	int r;
5267c478bd9Sstevel@tonic-gate # if _FFR_SLEEP_USE_SELECT > 0
5277c478bd9Sstevel@tonic-gate 	struct timeval sm_io_to;
5287c478bd9Sstevel@tonic-gate # endif /* _FFR_SLEEP_USE_SELECT > 0 */
5297c478bd9Sstevel@tonic-gate #endif /* _FFR_SLEEP_USE_SELECT > 0 */
5307c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
5317c478bd9Sstevel@tonic-gate 	struct timeval now, begin, diff;
5327c478bd9Sstevel@tonic-gate # if _FFR_SLEEP_USE_SELECT > 0
5337c478bd9Sstevel@tonic-gate 	struct timeval slpv;
5347c478bd9Sstevel@tonic-gate # endif /* _FFR_SLEEP_USE_SELECT > 0 */
5357c478bd9Sstevel@tonic-gate #else /*  SM_CONF_SETITIMER */
5367c478bd9Sstevel@tonic-gate 	time_t begin, now;
5377c478bd9Sstevel@tonic-gate #endif /*  SM_CONF_SETITIMER */
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	if (intvl == 0)
5407c478bd9Sstevel@tonic-gate 		return (SLEEP_T) 0;
5417c478bd9Sstevel@tonic-gate #if defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2
5427c478bd9Sstevel@tonic-gate 	if (intvl > _FFR_MAX_SLEEP_TIME)
5437c478bd9Sstevel@tonic-gate 	{
5447c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "sleep: interval=%u exceeds max value %d",
5457c478bd9Sstevel@tonic-gate 			intvl, _FFR_MAX_SLEEP_TIME);
5467c478bd9Sstevel@tonic-gate # if 0
5477c478bd9Sstevel@tonic-gate 		SM_ASSERT(intvl < (unsigned int) INT_MAX);
5487c478bd9Sstevel@tonic-gate # endif /* 0 */
5497c478bd9Sstevel@tonic-gate 		intvl = _FFR_MAX_SLEEP_TIME;
5507c478bd9Sstevel@tonic-gate 	}
5517c478bd9Sstevel@tonic-gate #endif /* defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2 */
5527c478bd9Sstevel@tonic-gate 	SmSleepDone = false;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
5557c478bd9Sstevel@tonic-gate # if _FFR_SLEEP_USE_SELECT > 0
5567c478bd9Sstevel@tonic-gate 	slpv.tv_sec = intvl;
5577c478bd9Sstevel@tonic-gate 	slpv.tv_usec = 0;
5587c478bd9Sstevel@tonic-gate # endif /* _FFR_SLEEP_USE_SELECT > 0 */
5597c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&now, NULL);
5607c478bd9Sstevel@tonic-gate 	begin = now;
5617c478bd9Sstevel@tonic-gate #else /*  SM_CONF_SETITIMER */
5627c478bd9Sstevel@tonic-gate 	now = begin = time(NULL);
5637c478bd9Sstevel@tonic-gate #endif /*  SM_CONF_SETITIMER */
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	ev = sm_setevent((time_t) intvl, sm_endsleep, 0);
5667c478bd9Sstevel@tonic-gate 	if (ev == NULL)
5677c478bd9Sstevel@tonic-gate 	{
5687c478bd9Sstevel@tonic-gate 		/* COMPLAIN */
5697c478bd9Sstevel@tonic-gate #if 0
5707c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "sleep: sm_setevent(%u) failed", intvl);
5717c478bd9Sstevel@tonic-gate #endif /* 0 */
5727c478bd9Sstevel@tonic-gate 		SmSleepDone = true;
5737c478bd9Sstevel@tonic-gate 	}
5747c478bd9Sstevel@tonic-gate 	was_held = sm_releasesignal(SIGALRM);
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	while (!SmSleepDone)
5777c478bd9Sstevel@tonic-gate 	{
5787c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
5797c478bd9Sstevel@tonic-gate 		(void) gettimeofday(&now, NULL);
5807c478bd9Sstevel@tonic-gate 		timersub(&now, &begin, &diff);
5817c478bd9Sstevel@tonic-gate 		if (diff.tv_sec < 0 ||
5827c478bd9Sstevel@tonic-gate 		    (diff.tv_sec == 0 && diff.tv_usec == 0))
5837c478bd9Sstevel@tonic-gate 			break;
5847c478bd9Sstevel@tonic-gate # if _FFR_SLEEP_USE_SELECT > 0
5857c478bd9Sstevel@tonic-gate 		timersub(&slpv, &diff, &sm_io_to);
5867c478bd9Sstevel@tonic-gate # endif /* _FFR_SLEEP_USE_SELECT > 0 */
5877c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
5887c478bd9Sstevel@tonic-gate 		now = time(NULL);
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 		/*
5917c478bd9Sstevel@tonic-gate 		**  Check whether time expired before signal is released.
5927c478bd9Sstevel@tonic-gate 		**  Due to the granularity of time() add 1 to be on the
5937c478bd9Sstevel@tonic-gate 		**  safe side.
5947c478bd9Sstevel@tonic-gate 		*/
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 		if (!(begin + (time_t) intvl + 1 > now))
5977c478bd9Sstevel@tonic-gate 			break;
5987c478bd9Sstevel@tonic-gate # if _FFR_SLEEP_USE_SELECT > 0
5997c478bd9Sstevel@tonic-gate 		sm_io_to.tv_sec = intvl - (now - begin);
6007c478bd9Sstevel@tonic-gate 		if (sm_io_to.tv_sec <= 0)
6017c478bd9Sstevel@tonic-gate 			sm_io_to.tv_sec = 1;
6027c478bd9Sstevel@tonic-gate 		sm_io_to.tv_usec = 0;
6037c478bd9Sstevel@tonic-gate # endif /* _FFR_SLEEP_USE_SELECT > 0 */
6047c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
6057c478bd9Sstevel@tonic-gate #if _FFR_SLEEP_USE_SELECT > 0
6067c478bd9Sstevel@tonic-gate 		if (intvl <= _FFR_SLEEP_USE_SELECT)
6077c478bd9Sstevel@tonic-gate 		{
6087c478bd9Sstevel@tonic-gate 			r = select(0, NULL, NULL, NULL, &sm_io_to);
6097c478bd9Sstevel@tonic-gate 			if (r == 0)
6107c478bd9Sstevel@tonic-gate 				break;
6117c478bd9Sstevel@tonic-gate 		}
6127c478bd9Sstevel@tonic-gate 		else
6137c478bd9Sstevel@tonic-gate #endif /* _FFR_SLEEP_USE_SELECT > 0 */
6147c478bd9Sstevel@tonic-gate 		(void) pause();
6157c478bd9Sstevel@tonic-gate 	}
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	/* if out of the loop without the event being triggered remove it */
6187c478bd9Sstevel@tonic-gate 	if (!SmSleepDone)
6197c478bd9Sstevel@tonic-gate 		sm_clrevent(ev);
6207c478bd9Sstevel@tonic-gate 	if (was_held > 0)
6217c478bd9Sstevel@tonic-gate 		(void) sm_blocksignal(SIGALRM);
6227c478bd9Sstevel@tonic-gate 	return (SLEEP_T) 0;
6237c478bd9Sstevel@tonic-gate #endif /* HAVE_NANOSLEEP */
6247c478bd9Sstevel@tonic-gate }
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate #if !HAVE_NANOSLEEP
6277c478bd9Sstevel@tonic-gate static void
sm_endsleep(ignore)6287c478bd9Sstevel@tonic-gate sm_endsleep(ignore)
6297c478bd9Sstevel@tonic-gate 	int ignore;
6307c478bd9Sstevel@tonic-gate {
6317c478bd9Sstevel@tonic-gate 	/*
6327c478bd9Sstevel@tonic-gate 	**  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
6337c478bd9Sstevel@tonic-gate 	**	ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
6347c478bd9Sstevel@tonic-gate 	**	DOING.
6357c478bd9Sstevel@tonic-gate 	*/
6367c478bd9Sstevel@tonic-gate 
6377c478bd9Sstevel@tonic-gate 	SmSleepDone = true;
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate #endif /* !HAVE_NANOSLEEP */
6407c478bd9Sstevel@tonic-gate 
641