xref: /titanic_44/usr/src/cmd/sendmail/libsm/clock.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
3*7c478bd9Sstevel@tonic-gate  *	All rights reserved.
4*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1988, 1993
6*7c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
7*7c478bd9Sstevel@tonic-gate  *
8*7c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
9*7c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
10*7c478bd9Sstevel@tonic-gate  * the sendmail distribution.
11*7c478bd9Sstevel@tonic-gate  *
12*7c478bd9Sstevel@tonic-gate  */
13*7c478bd9Sstevel@tonic-gate 
14*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
15*7c478bd9Sstevel@tonic-gate 
16*7c478bd9Sstevel@tonic-gate #include <sm/gen.h>
17*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: clock.c,v 1.46 2004/08/03 19:57:22 ca Exp $")
18*7c478bd9Sstevel@tonic-gate #include <unistd.h>
19*7c478bd9Sstevel@tonic-gate #include <time.h>
20*7c478bd9Sstevel@tonic-gate #include <errno.h>
21*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
22*7c478bd9Sstevel@tonic-gate # include <sys/time.h>
23*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
24*7c478bd9Sstevel@tonic-gate #include <sm/heap.h>
25*7c478bd9Sstevel@tonic-gate #include <sm/debug.h>
26*7c478bd9Sstevel@tonic-gate #include <sm/bitops.h>
27*7c478bd9Sstevel@tonic-gate #include <sm/clock.h>
28*7c478bd9Sstevel@tonic-gate #include "local.h"
29*7c478bd9Sstevel@tonic-gate #if _FFR_SLEEP_USE_SELECT > 0
30*7c478bd9Sstevel@tonic-gate # include <sys/types.h>
31*7c478bd9Sstevel@tonic-gate #endif /* _FFR_SLEEP_USE_SELECT > 0 */
32*7c478bd9Sstevel@tonic-gate #if defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2
33*7c478bd9Sstevel@tonic-gate # include <syslog.h>
34*7c478bd9Sstevel@tonic-gate #endif /* defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2 */
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #ifndef sigmask
37*7c478bd9Sstevel@tonic-gate # define sigmask(s)	(1 << ((s) - 1))
38*7c478bd9Sstevel@tonic-gate #endif /* ! sigmask */
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate /*
42*7c478bd9Sstevel@tonic-gate **  SM_SETEVENTM -- set an event to happen at a specific time in milliseconds.
43*7c478bd9Sstevel@tonic-gate **
44*7c478bd9Sstevel@tonic-gate **	Events are stored in a sorted list for fast processing.
45*7c478bd9Sstevel@tonic-gate **	An event only applies to the process that set it.
46*7c478bd9Sstevel@tonic-gate **	Source is #ifdef'd to work with older OS's that don't have setitimer()
47*7c478bd9Sstevel@tonic-gate **	(that is, don't have a timer granularity less than 1 second).
48*7c478bd9Sstevel@tonic-gate **
49*7c478bd9Sstevel@tonic-gate **	Parameters:
50*7c478bd9Sstevel@tonic-gate **		intvl -- interval until next event occurs (milliseconds).
51*7c478bd9Sstevel@tonic-gate **		func -- function to call on event.
52*7c478bd9Sstevel@tonic-gate **		arg -- argument to func on event.
53*7c478bd9Sstevel@tonic-gate **
54*7c478bd9Sstevel@tonic-gate **	Returns:
55*7c478bd9Sstevel@tonic-gate **		On success returns the SM_EVENT entry created.
56*7c478bd9Sstevel@tonic-gate **		On failure returns NULL.
57*7c478bd9Sstevel@tonic-gate **
58*7c478bd9Sstevel@tonic-gate **	Side Effects:
59*7c478bd9Sstevel@tonic-gate **		none.
60*7c478bd9Sstevel@tonic-gate */
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate static SM_EVENT	*volatile SmEventQueue;		/* head of event queue */
63*7c478bd9Sstevel@tonic-gate static SM_EVENT	*volatile SmFreeEventList;	/* list of free events */
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate SM_EVENT *
66*7c478bd9Sstevel@tonic-gate sm_seteventm(intvl, func, arg)
67*7c478bd9Sstevel@tonic-gate 	int intvl;
68*7c478bd9Sstevel@tonic-gate 	void (*func)__P((int));
69*7c478bd9Sstevel@tonic-gate 	int arg;
70*7c478bd9Sstevel@tonic-gate {
71*7c478bd9Sstevel@tonic-gate 	ENTER_CRITICAL();
72*7c478bd9Sstevel@tonic-gate 	if (SmFreeEventList == NULL)
73*7c478bd9Sstevel@tonic-gate 	{
74*7c478bd9Sstevel@tonic-gate 		SmFreeEventList = (SM_EVENT *) sm_pmalloc_x(sizeof *SmFreeEventList);
75*7c478bd9Sstevel@tonic-gate 		SmFreeEventList->ev_link = NULL;
76*7c478bd9Sstevel@tonic-gate 	}
77*7c478bd9Sstevel@tonic-gate 	LEAVE_CRITICAL();
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate 	return sm_sigsafe_seteventm(intvl, func, arg);
80*7c478bd9Sstevel@tonic-gate }
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate /*
83*7c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
84*7c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
85*7c478bd9Sstevel@tonic-gate **		DOING.
86*7c478bd9Sstevel@tonic-gate */
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate SM_EVENT *
89*7c478bd9Sstevel@tonic-gate sm_sigsafe_seteventm(intvl, func, arg)
90*7c478bd9Sstevel@tonic-gate 	int intvl;
91*7c478bd9Sstevel@tonic-gate 	void (*func)__P((int));
92*7c478bd9Sstevel@tonic-gate 	int arg;
93*7c478bd9Sstevel@tonic-gate {
94*7c478bd9Sstevel@tonic-gate 	register SM_EVENT **evp;
95*7c478bd9Sstevel@tonic-gate 	register SM_EVENT *ev;
96*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
97*7c478bd9Sstevel@tonic-gate 	auto struct timeval now, nowi, ival;
98*7c478bd9Sstevel@tonic-gate 	auto struct itimerval itime;
99*7c478bd9Sstevel@tonic-gate #else /*  SM_CONF_SETITIMER */
100*7c478bd9Sstevel@tonic-gate 	auto time_t now, nowi;
101*7c478bd9Sstevel@tonic-gate #endif /*  SM_CONF_SETITIMER */
102*7c478bd9Sstevel@tonic-gate 	int wasblocked;
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	/* negative times are not allowed */
105*7c478bd9Sstevel@tonic-gate 	if (intvl <= 0)
106*7c478bd9Sstevel@tonic-gate 		return NULL;
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate 	wasblocked = sm_blocksignal(SIGALRM);
109*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
110*7c478bd9Sstevel@tonic-gate 	ival.tv_sec = intvl / 1000;
111*7c478bd9Sstevel@tonic-gate 	ival.tv_usec = (intvl - ival.tv_sec * 1000) * 10;
112*7c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&now, NULL);
113*7c478bd9Sstevel@tonic-gate 	nowi = now;
114*7c478bd9Sstevel@tonic-gate 	timeradd(&now, &ival, &nowi);
115*7c478bd9Sstevel@tonic-gate #else /*  SM_CONF_SETITIMER */
116*7c478bd9Sstevel@tonic-gate 	now = time(NULL);
117*7c478bd9Sstevel@tonic-gate 	nowi = now + (time_t)(intvl / 1000);
118*7c478bd9Sstevel@tonic-gate #endif /*  SM_CONF_SETITIMER */
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 	/* search event queue for correct position */
121*7c478bd9Sstevel@tonic-gate 	for (evp = (SM_EVENT **) (&SmEventQueue);
122*7c478bd9Sstevel@tonic-gate 	     (ev = *evp) != NULL;
123*7c478bd9Sstevel@tonic-gate 	     evp = &ev->ev_link)
124*7c478bd9Sstevel@tonic-gate 	{
125*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
126*7c478bd9Sstevel@tonic-gate 		if (timercmp(&(ev->ev_time), &nowi, >=))
127*7c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
128*7c478bd9Sstevel@tonic-gate 		if (ev->ev_time >= nowi)
129*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
130*7c478bd9Sstevel@tonic-gate 			break;
131*7c478bd9Sstevel@tonic-gate 	}
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	ENTER_CRITICAL();
134*7c478bd9Sstevel@tonic-gate 	if (SmFreeEventList == NULL)
135*7c478bd9Sstevel@tonic-gate 	{
136*7c478bd9Sstevel@tonic-gate 		/*
137*7c478bd9Sstevel@tonic-gate 		**  This shouldn't happen.  If called from sm_seteventm(),
138*7c478bd9Sstevel@tonic-gate 		**  we have just malloced a SmFreeEventList entry.  If
139*7c478bd9Sstevel@tonic-gate 		**  called from a signal handler, it should have been
140*7c478bd9Sstevel@tonic-gate 		**  from an existing event which sm_tick() just added to
141*7c478bd9Sstevel@tonic-gate 		**  SmFreeEventList.
142*7c478bd9Sstevel@tonic-gate 		*/
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 		LEAVE_CRITICAL();
145*7c478bd9Sstevel@tonic-gate 		if (wasblocked == 0)
146*7c478bd9Sstevel@tonic-gate 			(void) sm_releasesignal(SIGALRM);
147*7c478bd9Sstevel@tonic-gate 		return NULL;
148*7c478bd9Sstevel@tonic-gate 	}
149*7c478bd9Sstevel@tonic-gate 	else
150*7c478bd9Sstevel@tonic-gate 	{
151*7c478bd9Sstevel@tonic-gate 		ev = SmFreeEventList;
152*7c478bd9Sstevel@tonic-gate 		SmFreeEventList = ev->ev_link;
153*7c478bd9Sstevel@tonic-gate 	}
154*7c478bd9Sstevel@tonic-gate 	LEAVE_CRITICAL();
155*7c478bd9Sstevel@tonic-gate 
156*7c478bd9Sstevel@tonic-gate 	/* insert new event */
157*7c478bd9Sstevel@tonic-gate 	ev->ev_time = nowi;
158*7c478bd9Sstevel@tonic-gate 	ev->ev_func = func;
159*7c478bd9Sstevel@tonic-gate 	ev->ev_arg = arg;
160*7c478bd9Sstevel@tonic-gate 	ev->ev_pid = getpid();
161*7c478bd9Sstevel@tonic-gate 	ENTER_CRITICAL();
162*7c478bd9Sstevel@tonic-gate 	ev->ev_link = *evp;
163*7c478bd9Sstevel@tonic-gate 	*evp = ev;
164*7c478bd9Sstevel@tonic-gate 	LEAVE_CRITICAL();
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate 	(void) sm_signal(SIGALRM, sm_tick);
167*7c478bd9Sstevel@tonic-gate # if SM_CONF_SETITIMER
168*7c478bd9Sstevel@tonic-gate 	timersub(&SmEventQueue->ev_time, &now, &itime.it_value);
169*7c478bd9Sstevel@tonic-gate 	itime.it_interval.tv_sec = 0;
170*7c478bd9Sstevel@tonic-gate 	itime.it_interval.tv_usec = 0;
171*7c478bd9Sstevel@tonic-gate 	if (itime.it_value.tv_sec < 0)
172*7c478bd9Sstevel@tonic-gate 		itime.it_value.tv_sec = 0;
173*7c478bd9Sstevel@tonic-gate 	if (itime.it_value.tv_sec == 0 && itime.it_value.tv_usec == 0)
174*7c478bd9Sstevel@tonic-gate 		itime.it_value.tv_usec = 1000;
175*7c478bd9Sstevel@tonic-gate 	(void) setitimer(ITIMER_REAL, &itime, NULL);
176*7c478bd9Sstevel@tonic-gate # else /* SM_CONF_SETITIMER */
177*7c478bd9Sstevel@tonic-gate 	intvl = SmEventQueue->ev_time - now;
178*7c478bd9Sstevel@tonic-gate 	(void) alarm((unsigned) (intvl < 1 ? 1 : intvl));
179*7c478bd9Sstevel@tonic-gate # endif /* SM_CONF_SETITIMER */
180*7c478bd9Sstevel@tonic-gate 	if (wasblocked == 0)
181*7c478bd9Sstevel@tonic-gate 		(void) sm_releasesignal(SIGALRM);
182*7c478bd9Sstevel@tonic-gate 	return ev;
183*7c478bd9Sstevel@tonic-gate }
184*7c478bd9Sstevel@tonic-gate /*
185*7c478bd9Sstevel@tonic-gate **  SM_CLREVENT -- remove an event from the event queue.
186*7c478bd9Sstevel@tonic-gate **
187*7c478bd9Sstevel@tonic-gate **	Parameters:
188*7c478bd9Sstevel@tonic-gate **		ev -- pointer to event to remove.
189*7c478bd9Sstevel@tonic-gate **
190*7c478bd9Sstevel@tonic-gate **	Returns:
191*7c478bd9Sstevel@tonic-gate **		none.
192*7c478bd9Sstevel@tonic-gate **
193*7c478bd9Sstevel@tonic-gate **	Side Effects:
194*7c478bd9Sstevel@tonic-gate **		arranges for event ev to not happen.
195*7c478bd9Sstevel@tonic-gate */
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate void
198*7c478bd9Sstevel@tonic-gate sm_clrevent(ev)
199*7c478bd9Sstevel@tonic-gate 	register SM_EVENT *ev;
200*7c478bd9Sstevel@tonic-gate {
201*7c478bd9Sstevel@tonic-gate 	register SM_EVENT **evp;
202*7c478bd9Sstevel@tonic-gate 	int wasblocked;
203*7c478bd9Sstevel@tonic-gate # if SM_CONF_SETITIMER
204*7c478bd9Sstevel@tonic-gate 	struct itimerval clr;
205*7c478bd9Sstevel@tonic-gate # endif /* SM_CONF_SETITIMER */
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 	if (ev == NULL)
208*7c478bd9Sstevel@tonic-gate 		return;
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	/* find the parent event */
211*7c478bd9Sstevel@tonic-gate 	wasblocked = sm_blocksignal(SIGALRM);
212*7c478bd9Sstevel@tonic-gate 	for (evp = (SM_EVENT **) (&SmEventQueue);
213*7c478bd9Sstevel@tonic-gate 	     *evp != NULL;
214*7c478bd9Sstevel@tonic-gate 	     evp = &(*evp)->ev_link)
215*7c478bd9Sstevel@tonic-gate 	{
216*7c478bd9Sstevel@tonic-gate 		if (*evp == ev)
217*7c478bd9Sstevel@tonic-gate 			break;
218*7c478bd9Sstevel@tonic-gate 	}
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	/* now remove it */
221*7c478bd9Sstevel@tonic-gate 	if (*evp != NULL)
222*7c478bd9Sstevel@tonic-gate 	{
223*7c478bd9Sstevel@tonic-gate 		ENTER_CRITICAL();
224*7c478bd9Sstevel@tonic-gate 		*evp = ev->ev_link;
225*7c478bd9Sstevel@tonic-gate 		ev->ev_link = SmFreeEventList;
226*7c478bd9Sstevel@tonic-gate 		SmFreeEventList = ev;
227*7c478bd9Sstevel@tonic-gate 		LEAVE_CRITICAL();
228*7c478bd9Sstevel@tonic-gate 	}
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 	/* restore clocks and pick up anything spare */
231*7c478bd9Sstevel@tonic-gate 	if (wasblocked == 0)
232*7c478bd9Sstevel@tonic-gate 		(void) sm_releasesignal(SIGALRM);
233*7c478bd9Sstevel@tonic-gate 	if (SmEventQueue != NULL)
234*7c478bd9Sstevel@tonic-gate 		(void) kill(getpid(), SIGALRM);
235*7c478bd9Sstevel@tonic-gate 	else
236*7c478bd9Sstevel@tonic-gate 	{
237*7c478bd9Sstevel@tonic-gate 		/* nothing left in event queue, no need for an alarm */
238*7c478bd9Sstevel@tonic-gate # if SM_CONF_SETITIMER
239*7c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_sec = 0;
240*7c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_usec = 0;
241*7c478bd9Sstevel@tonic-gate 		clr.it_value.tv_sec = 0;
242*7c478bd9Sstevel@tonic-gate 		clr.it_value.tv_usec = 0;
243*7c478bd9Sstevel@tonic-gate 		(void) setitimer(ITIMER_REAL, &clr, NULL);
244*7c478bd9Sstevel@tonic-gate # else /* SM_CONF_SETITIMER */
245*7c478bd9Sstevel@tonic-gate 		(void) alarm(0);
246*7c478bd9Sstevel@tonic-gate # endif /* SM_CONF_SETITIMER */
247*7c478bd9Sstevel@tonic-gate 	}
248*7c478bd9Sstevel@tonic-gate }
249*7c478bd9Sstevel@tonic-gate /*
250*7c478bd9Sstevel@tonic-gate **  SM_CLEAR_EVENTS -- remove all events from the event queue.
251*7c478bd9Sstevel@tonic-gate **
252*7c478bd9Sstevel@tonic-gate **	Parameters:
253*7c478bd9Sstevel@tonic-gate **		none.
254*7c478bd9Sstevel@tonic-gate **
255*7c478bd9Sstevel@tonic-gate **	Returns:
256*7c478bd9Sstevel@tonic-gate **		none.
257*7c478bd9Sstevel@tonic-gate */
258*7c478bd9Sstevel@tonic-gate 
259*7c478bd9Sstevel@tonic-gate void
260*7c478bd9Sstevel@tonic-gate sm_clear_events()
261*7c478bd9Sstevel@tonic-gate {
262*7c478bd9Sstevel@tonic-gate 	register SM_EVENT *ev;
263*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
264*7c478bd9Sstevel@tonic-gate 	struct itimerval clr;
265*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
266*7c478bd9Sstevel@tonic-gate 	int wasblocked;
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 	/* nothing will be left in event queue, no need for an alarm */
269*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
270*7c478bd9Sstevel@tonic-gate 	clr.it_interval.tv_sec = 0;
271*7c478bd9Sstevel@tonic-gate 	clr.it_interval.tv_usec = 0;
272*7c478bd9Sstevel@tonic-gate 	clr.it_value.tv_sec = 0;
273*7c478bd9Sstevel@tonic-gate 	clr.it_value.tv_usec = 0;
274*7c478bd9Sstevel@tonic-gate 	(void) setitimer(ITIMER_REAL, &clr, NULL);
275*7c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
276*7c478bd9Sstevel@tonic-gate 	(void) alarm(0);
277*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	if (SmEventQueue == NULL)
280*7c478bd9Sstevel@tonic-gate 		return;
281*7c478bd9Sstevel@tonic-gate 
282*7c478bd9Sstevel@tonic-gate 	wasblocked = sm_blocksignal(SIGALRM);
283*7c478bd9Sstevel@tonic-gate 
284*7c478bd9Sstevel@tonic-gate 	/* find the end of the EventQueue */
285*7c478bd9Sstevel@tonic-gate 	for (ev = SmEventQueue; ev->ev_link != NULL; ev = ev->ev_link)
286*7c478bd9Sstevel@tonic-gate 		continue;
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	ENTER_CRITICAL();
289*7c478bd9Sstevel@tonic-gate 	ev->ev_link = SmFreeEventList;
290*7c478bd9Sstevel@tonic-gate 	SmFreeEventList = SmEventQueue;
291*7c478bd9Sstevel@tonic-gate 	SmEventQueue = NULL;
292*7c478bd9Sstevel@tonic-gate 	LEAVE_CRITICAL();
293*7c478bd9Sstevel@tonic-gate 
294*7c478bd9Sstevel@tonic-gate 	/* restore clocks and pick up anything spare */
295*7c478bd9Sstevel@tonic-gate 	if (wasblocked == 0)
296*7c478bd9Sstevel@tonic-gate 		(void) sm_releasesignal(SIGALRM);
297*7c478bd9Sstevel@tonic-gate }
298*7c478bd9Sstevel@tonic-gate /*
299*7c478bd9Sstevel@tonic-gate **  SM_TICK -- take a clock tick
300*7c478bd9Sstevel@tonic-gate **
301*7c478bd9Sstevel@tonic-gate **	Called by the alarm clock.  This routine runs events as needed.
302*7c478bd9Sstevel@tonic-gate **	Always called as a signal handler, so we assume that SIGALRM
303*7c478bd9Sstevel@tonic-gate **	has been blocked.
304*7c478bd9Sstevel@tonic-gate **
305*7c478bd9Sstevel@tonic-gate **	Parameters:
306*7c478bd9Sstevel@tonic-gate **		One that is ignored; for compatibility with signal handlers.
307*7c478bd9Sstevel@tonic-gate **
308*7c478bd9Sstevel@tonic-gate **	Returns:
309*7c478bd9Sstevel@tonic-gate **		none.
310*7c478bd9Sstevel@tonic-gate **
311*7c478bd9Sstevel@tonic-gate **	Side Effects:
312*7c478bd9Sstevel@tonic-gate **		calls the next function in EventQueue.
313*7c478bd9Sstevel@tonic-gate **
314*7c478bd9Sstevel@tonic-gate **	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
315*7c478bd9Sstevel@tonic-gate **		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
316*7c478bd9Sstevel@tonic-gate **		DOING.
317*7c478bd9Sstevel@tonic-gate */
318*7c478bd9Sstevel@tonic-gate 
319*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
320*7c478bd9Sstevel@tonic-gate SIGFUNC_DECL
321*7c478bd9Sstevel@tonic-gate sm_tick(sig)
322*7c478bd9Sstevel@tonic-gate 	int sig;
323*7c478bd9Sstevel@tonic-gate {
324*7c478bd9Sstevel@tonic-gate 	register SM_EVENT *ev;
325*7c478bd9Sstevel@tonic-gate 	pid_t mypid;
326*7c478bd9Sstevel@tonic-gate 	int save_errno = errno;
327*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
328*7c478bd9Sstevel@tonic-gate 	struct itimerval clr;
329*7c478bd9Sstevel@tonic-gate 	struct timeval now;
330*7c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
331*7c478bd9Sstevel@tonic-gate 	register time_t now;
332*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
335*7c478bd9Sstevel@tonic-gate 	clr.it_interval.tv_sec = 0;
336*7c478bd9Sstevel@tonic-gate 	clr.it_interval.tv_usec = 0;
337*7c478bd9Sstevel@tonic-gate 	clr.it_value.tv_sec = 0;
338*7c478bd9Sstevel@tonic-gate 	clr.it_value.tv_usec = 0;
339*7c478bd9Sstevel@tonic-gate 	(void) setitimer(ITIMER_REAL, &clr, NULL);
340*7c478bd9Sstevel@tonic-gate 	gettimeofday(&now, NULL);
341*7c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
342*7c478bd9Sstevel@tonic-gate 	(void) alarm(0);
343*7c478bd9Sstevel@tonic-gate 	now = time(NULL);
344*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	FIX_SYSV_SIGNAL(sig, sm_tick);
347*7c478bd9Sstevel@tonic-gate 	errno = save_errno;
348*7c478bd9Sstevel@tonic-gate 	CHECK_CRITICAL(sig);
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 	mypid = getpid();
351*7c478bd9Sstevel@tonic-gate 	while (PendingSignal != 0)
352*7c478bd9Sstevel@tonic-gate 	{
353*7c478bd9Sstevel@tonic-gate 		int sigbit = 0;
354*7c478bd9Sstevel@tonic-gate 		int sig = 0;
355*7c478bd9Sstevel@tonic-gate 
356*7c478bd9Sstevel@tonic-gate 		if (bitset(PEND_SIGHUP, PendingSignal))
357*7c478bd9Sstevel@tonic-gate 		{
358*7c478bd9Sstevel@tonic-gate 			sigbit = PEND_SIGHUP;
359*7c478bd9Sstevel@tonic-gate 			sig = SIGHUP;
360*7c478bd9Sstevel@tonic-gate 		}
361*7c478bd9Sstevel@tonic-gate 		else if (bitset(PEND_SIGINT, PendingSignal))
362*7c478bd9Sstevel@tonic-gate 		{
363*7c478bd9Sstevel@tonic-gate 			sigbit = PEND_SIGINT;
364*7c478bd9Sstevel@tonic-gate 			sig = SIGINT;
365*7c478bd9Sstevel@tonic-gate 		}
366*7c478bd9Sstevel@tonic-gate 		else if (bitset(PEND_SIGTERM, PendingSignal))
367*7c478bd9Sstevel@tonic-gate 		{
368*7c478bd9Sstevel@tonic-gate 			sigbit = PEND_SIGTERM;
369*7c478bd9Sstevel@tonic-gate 			sig = SIGTERM;
370*7c478bd9Sstevel@tonic-gate 		}
371*7c478bd9Sstevel@tonic-gate 		else if (bitset(PEND_SIGUSR1, PendingSignal))
372*7c478bd9Sstevel@tonic-gate 		{
373*7c478bd9Sstevel@tonic-gate 			sigbit = PEND_SIGUSR1;
374*7c478bd9Sstevel@tonic-gate 			sig = SIGUSR1;
375*7c478bd9Sstevel@tonic-gate 		}
376*7c478bd9Sstevel@tonic-gate 		else
377*7c478bd9Sstevel@tonic-gate 		{
378*7c478bd9Sstevel@tonic-gate 			/* If we get here, we are in trouble */
379*7c478bd9Sstevel@tonic-gate 			abort();
380*7c478bd9Sstevel@tonic-gate 		}
381*7c478bd9Sstevel@tonic-gate 		PendingSignal &= ~sigbit;
382*7c478bd9Sstevel@tonic-gate 		kill(mypid, sig);
383*7c478bd9Sstevel@tonic-gate 	}
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
386*7c478bd9Sstevel@tonic-gate 	gettimeofday(&now, NULL);
387*7c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
388*7c478bd9Sstevel@tonic-gate 	now = time(NULL);
389*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
390*7c478bd9Sstevel@tonic-gate 	while ((ev = SmEventQueue) != NULL &&
391*7c478bd9Sstevel@tonic-gate 	       (ev->ev_pid != mypid ||
392*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
393*7c478bd9Sstevel@tonic-gate 		timercmp(&ev->ev_time, &now, <=)
394*7c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
395*7c478bd9Sstevel@tonic-gate 		ev->ev_time <= now
396*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
397*7c478bd9Sstevel@tonic-gate 		))
398*7c478bd9Sstevel@tonic-gate 	{
399*7c478bd9Sstevel@tonic-gate 		void (*f)__P((int));
400*7c478bd9Sstevel@tonic-gate 		int arg;
401*7c478bd9Sstevel@tonic-gate 		pid_t pid;
402*7c478bd9Sstevel@tonic-gate 
403*7c478bd9Sstevel@tonic-gate 		/* process the event on the top of the queue */
404*7c478bd9Sstevel@tonic-gate 		ev = SmEventQueue;
405*7c478bd9Sstevel@tonic-gate 		SmEventQueue = SmEventQueue->ev_link;
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate 		/* we must be careful in here because ev_func may not return */
408*7c478bd9Sstevel@tonic-gate 		f = ev->ev_func;
409*7c478bd9Sstevel@tonic-gate 		arg = ev->ev_arg;
410*7c478bd9Sstevel@tonic-gate 		pid = ev->ev_pid;
411*7c478bd9Sstevel@tonic-gate 		ENTER_CRITICAL();
412*7c478bd9Sstevel@tonic-gate 		ev->ev_link = SmFreeEventList;
413*7c478bd9Sstevel@tonic-gate 		SmFreeEventList = ev;
414*7c478bd9Sstevel@tonic-gate 		LEAVE_CRITICAL();
415*7c478bd9Sstevel@tonic-gate 		if (pid != getpid())
416*7c478bd9Sstevel@tonic-gate 			continue;
417*7c478bd9Sstevel@tonic-gate 		if (SmEventQueue != NULL)
418*7c478bd9Sstevel@tonic-gate 		{
419*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
420*7c478bd9Sstevel@tonic-gate 			if (timercmp(&SmEventQueue->ev_time, &now, >))
421*7c478bd9Sstevel@tonic-gate 			{
422*7c478bd9Sstevel@tonic-gate 				timersub(&SmEventQueue->ev_time, &now,
423*7c478bd9Sstevel@tonic-gate 					 &clr.it_value);
424*7c478bd9Sstevel@tonic-gate 				clr.it_interval.tv_sec = 0;
425*7c478bd9Sstevel@tonic-gate 				clr.it_interval.tv_usec = 0;
426*7c478bd9Sstevel@tonic-gate 				if (clr.it_value.tv_sec < 0)
427*7c478bd9Sstevel@tonic-gate 					clr.it_value.tv_sec = 0;
428*7c478bd9Sstevel@tonic-gate 				if (clr.it_value.tv_sec == 0 &&
429*7c478bd9Sstevel@tonic-gate 				    clr.it_value.tv_usec == 0)
430*7c478bd9Sstevel@tonic-gate 					clr.it_value.tv_usec = 1000;
431*7c478bd9Sstevel@tonic-gate 				(void) setitimer(ITIMER_REAL, &clr, NULL);
432*7c478bd9Sstevel@tonic-gate 			}
433*7c478bd9Sstevel@tonic-gate 			else
434*7c478bd9Sstevel@tonic-gate 			{
435*7c478bd9Sstevel@tonic-gate 				clr.it_interval.tv_sec = 0;
436*7c478bd9Sstevel@tonic-gate 				clr.it_interval.tv_usec = 0;
437*7c478bd9Sstevel@tonic-gate 				clr.it_value.tv_sec = 3;
438*7c478bd9Sstevel@tonic-gate 				clr.it_value.tv_usec = 0;
439*7c478bd9Sstevel@tonic-gate 				(void) setitimer(ITIMER_REAL, &clr, NULL);
440*7c478bd9Sstevel@tonic-gate 			}
441*7c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
442*7c478bd9Sstevel@tonic-gate 			if (SmEventQueue->ev_time > now)
443*7c478bd9Sstevel@tonic-gate 				(void) alarm((unsigned) (SmEventQueue->ev_time
444*7c478bd9Sstevel@tonic-gate 							 - now));
445*7c478bd9Sstevel@tonic-gate 			else
446*7c478bd9Sstevel@tonic-gate 				(void) alarm(3);
447*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
448*7c478bd9Sstevel@tonic-gate 		}
449*7c478bd9Sstevel@tonic-gate 
450*7c478bd9Sstevel@tonic-gate 		/* call ev_func */
451*7c478bd9Sstevel@tonic-gate 		errno = save_errno;
452*7c478bd9Sstevel@tonic-gate 		(*f)(arg);
453*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
454*7c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_sec = 0;
455*7c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_usec = 0;
456*7c478bd9Sstevel@tonic-gate 		clr.it_value.tv_sec = 0;
457*7c478bd9Sstevel@tonic-gate 		clr.it_value.tv_usec = 0;
458*7c478bd9Sstevel@tonic-gate 		(void) setitimer(ITIMER_REAL, &clr, NULL);
459*7c478bd9Sstevel@tonic-gate 		gettimeofday(&now, NULL);
460*7c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
461*7c478bd9Sstevel@tonic-gate 		(void) alarm(0);
462*7c478bd9Sstevel@tonic-gate 		now = time(NULL);
463*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
464*7c478bd9Sstevel@tonic-gate 	}
465*7c478bd9Sstevel@tonic-gate 	if (SmEventQueue != NULL)
466*7c478bd9Sstevel@tonic-gate 	{
467*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
468*7c478bd9Sstevel@tonic-gate 		timersub(&SmEventQueue->ev_time, &now, &clr.it_value);
469*7c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_sec = 0;
470*7c478bd9Sstevel@tonic-gate 		clr.it_interval.tv_usec = 0;
471*7c478bd9Sstevel@tonic-gate 		if (clr.it_value.tv_sec < 0)
472*7c478bd9Sstevel@tonic-gate 			clr.it_value.tv_sec = 0;
473*7c478bd9Sstevel@tonic-gate 		if (clr.it_value.tv_sec == 0 && clr.it_value.tv_usec == 0)
474*7c478bd9Sstevel@tonic-gate 			clr.it_value.tv_usec = 1000;
475*7c478bd9Sstevel@tonic-gate 		(void) setitimer(ITIMER_REAL, &clr, NULL);
476*7c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
477*7c478bd9Sstevel@tonic-gate 		(void) alarm((unsigned) (SmEventQueue->ev_time - now));
478*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
479*7c478bd9Sstevel@tonic-gate 	}
480*7c478bd9Sstevel@tonic-gate 	errno = save_errno;
481*7c478bd9Sstevel@tonic-gate 	return SIGFUNC_RETURN;
482*7c478bd9Sstevel@tonic-gate }
483*7c478bd9Sstevel@tonic-gate /*
484*7c478bd9Sstevel@tonic-gate **  SLEEP -- a version of sleep that works with this stuff
485*7c478bd9Sstevel@tonic-gate **
486*7c478bd9Sstevel@tonic-gate **	Because Unix sleep uses the alarm facility, I must reimplement
487*7c478bd9Sstevel@tonic-gate **	it here.
488*7c478bd9Sstevel@tonic-gate **
489*7c478bd9Sstevel@tonic-gate **	Parameters:
490*7c478bd9Sstevel@tonic-gate **		intvl -- time to sleep.
491*7c478bd9Sstevel@tonic-gate **
492*7c478bd9Sstevel@tonic-gate **	Returns:
493*7c478bd9Sstevel@tonic-gate **		zero.
494*7c478bd9Sstevel@tonic-gate **
495*7c478bd9Sstevel@tonic-gate **	Side Effects:
496*7c478bd9Sstevel@tonic-gate **		waits for intvl time.  However, other events can
497*7c478bd9Sstevel@tonic-gate **		be run during that interval.
498*7c478bd9Sstevel@tonic-gate */
499*7c478bd9Sstevel@tonic-gate 
500*7c478bd9Sstevel@tonic-gate 
501*7c478bd9Sstevel@tonic-gate # if !HAVE_NANOSLEEP
502*7c478bd9Sstevel@tonic-gate static void	sm_endsleep __P((int));
503*7c478bd9Sstevel@tonic-gate static bool	volatile SmSleepDone;
504*7c478bd9Sstevel@tonic-gate # endif /* !HAVE_NANOSLEEP */
505*7c478bd9Sstevel@tonic-gate 
506*7c478bd9Sstevel@tonic-gate #ifndef SLEEP_T
507*7c478bd9Sstevel@tonic-gate # define SLEEP_T	unsigned int
508*7c478bd9Sstevel@tonic-gate #endif /* ! SLEEP_T */
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate SLEEP_T
511*7c478bd9Sstevel@tonic-gate sleep(intvl)
512*7c478bd9Sstevel@tonic-gate 	unsigned int intvl;
513*7c478bd9Sstevel@tonic-gate {
514*7c478bd9Sstevel@tonic-gate #if HAVE_NANOSLEEP
515*7c478bd9Sstevel@tonic-gate 	struct timespec rqtp;
516*7c478bd9Sstevel@tonic-gate 
517*7c478bd9Sstevel@tonic-gate 	if (intvl == 0)
518*7c478bd9Sstevel@tonic-gate 		return (SLEEP_T) 0;
519*7c478bd9Sstevel@tonic-gate 	rqtp.tv_sec = intvl;
520*7c478bd9Sstevel@tonic-gate 	rqtp.tv_nsec = 0;
521*7c478bd9Sstevel@tonic-gate 	nanosleep(&rqtp, NULL);
522*7c478bd9Sstevel@tonic-gate 	return (SLEEP_T) 0;
523*7c478bd9Sstevel@tonic-gate #else /* HAVE_NANOSLEEP */
524*7c478bd9Sstevel@tonic-gate 	int was_held;
525*7c478bd9Sstevel@tonic-gate 	SM_EVENT *ev;
526*7c478bd9Sstevel@tonic-gate #if _FFR_SLEEP_USE_SELECT > 0
527*7c478bd9Sstevel@tonic-gate 	int r;
528*7c478bd9Sstevel@tonic-gate # if _FFR_SLEEP_USE_SELECT > 0
529*7c478bd9Sstevel@tonic-gate 	struct timeval sm_io_to;
530*7c478bd9Sstevel@tonic-gate # endif /* _FFR_SLEEP_USE_SELECT > 0 */
531*7c478bd9Sstevel@tonic-gate #endif /* _FFR_SLEEP_USE_SELECT > 0 */
532*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
533*7c478bd9Sstevel@tonic-gate 	struct timeval now, begin, diff;
534*7c478bd9Sstevel@tonic-gate # if _FFR_SLEEP_USE_SELECT > 0
535*7c478bd9Sstevel@tonic-gate 	struct timeval slpv;
536*7c478bd9Sstevel@tonic-gate # endif /* _FFR_SLEEP_USE_SELECT > 0 */
537*7c478bd9Sstevel@tonic-gate #else /*  SM_CONF_SETITIMER */
538*7c478bd9Sstevel@tonic-gate 	time_t begin, now;
539*7c478bd9Sstevel@tonic-gate #endif /*  SM_CONF_SETITIMER */
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate 	if (intvl == 0)
542*7c478bd9Sstevel@tonic-gate 		return (SLEEP_T) 0;
543*7c478bd9Sstevel@tonic-gate #if defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2
544*7c478bd9Sstevel@tonic-gate 	if (intvl > _FFR_MAX_SLEEP_TIME)
545*7c478bd9Sstevel@tonic-gate 	{
546*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "sleep: interval=%u exceeds max value %d",
547*7c478bd9Sstevel@tonic-gate 			intvl, _FFR_MAX_SLEEP_TIME);
548*7c478bd9Sstevel@tonic-gate # if 0
549*7c478bd9Sstevel@tonic-gate 		SM_ASSERT(intvl < (unsigned int) INT_MAX);
550*7c478bd9Sstevel@tonic-gate # endif /* 0 */
551*7c478bd9Sstevel@tonic-gate 		intvl = _FFR_MAX_SLEEP_TIME;
552*7c478bd9Sstevel@tonic-gate 	}
553*7c478bd9Sstevel@tonic-gate #endif /* defined(_FFR_MAX_SLEEP_TIME) && _FFR_MAX_SLEEP_TIME > 2 */
554*7c478bd9Sstevel@tonic-gate 	SmSleepDone = false;
555*7c478bd9Sstevel@tonic-gate 
556*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
557*7c478bd9Sstevel@tonic-gate # if _FFR_SLEEP_USE_SELECT > 0
558*7c478bd9Sstevel@tonic-gate 	slpv.tv_sec = intvl;
559*7c478bd9Sstevel@tonic-gate 	slpv.tv_usec = 0;
560*7c478bd9Sstevel@tonic-gate # endif /* _FFR_SLEEP_USE_SELECT > 0 */
561*7c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&now, NULL);
562*7c478bd9Sstevel@tonic-gate 	begin = now;
563*7c478bd9Sstevel@tonic-gate #else /*  SM_CONF_SETITIMER */
564*7c478bd9Sstevel@tonic-gate 	now = begin = time(NULL);
565*7c478bd9Sstevel@tonic-gate #endif /*  SM_CONF_SETITIMER */
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	ev = sm_setevent((time_t) intvl, sm_endsleep, 0);
568*7c478bd9Sstevel@tonic-gate 	if (ev == NULL)
569*7c478bd9Sstevel@tonic-gate 	{
570*7c478bd9Sstevel@tonic-gate 		/* COMPLAIN */
571*7c478bd9Sstevel@tonic-gate #if 0
572*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "sleep: sm_setevent(%u) failed", intvl);
573*7c478bd9Sstevel@tonic-gate #endif /* 0 */
574*7c478bd9Sstevel@tonic-gate 		SmSleepDone = true;
575*7c478bd9Sstevel@tonic-gate 	}
576*7c478bd9Sstevel@tonic-gate 	was_held = sm_releasesignal(SIGALRM);
577*7c478bd9Sstevel@tonic-gate 
578*7c478bd9Sstevel@tonic-gate 	while (!SmSleepDone)
579*7c478bd9Sstevel@tonic-gate 	{
580*7c478bd9Sstevel@tonic-gate #if SM_CONF_SETITIMER
581*7c478bd9Sstevel@tonic-gate 		(void) gettimeofday(&now, NULL);
582*7c478bd9Sstevel@tonic-gate 		timersub(&now, &begin, &diff);
583*7c478bd9Sstevel@tonic-gate 		if (diff.tv_sec < 0 ||
584*7c478bd9Sstevel@tonic-gate 		    (diff.tv_sec == 0 && diff.tv_usec == 0))
585*7c478bd9Sstevel@tonic-gate 			break;
586*7c478bd9Sstevel@tonic-gate # if _FFR_SLEEP_USE_SELECT > 0
587*7c478bd9Sstevel@tonic-gate 		timersub(&slpv, &diff, &sm_io_to);
588*7c478bd9Sstevel@tonic-gate # endif /* _FFR_SLEEP_USE_SELECT > 0 */
589*7c478bd9Sstevel@tonic-gate #else /* SM_CONF_SETITIMER */
590*7c478bd9Sstevel@tonic-gate 		now = time(NULL);
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate 		/*
593*7c478bd9Sstevel@tonic-gate 		**  Check whether time expired before signal is released.
594*7c478bd9Sstevel@tonic-gate 		**  Due to the granularity of time() add 1 to be on the
595*7c478bd9Sstevel@tonic-gate 		**  safe side.
596*7c478bd9Sstevel@tonic-gate 		*/
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate 		if (!(begin + (time_t) intvl + 1 > now))
599*7c478bd9Sstevel@tonic-gate 			break;
600*7c478bd9Sstevel@tonic-gate # if _FFR_SLEEP_USE_SELECT > 0
601*7c478bd9Sstevel@tonic-gate 		sm_io_to.tv_sec = intvl - (now - begin);
602*7c478bd9Sstevel@tonic-gate 		if (sm_io_to.tv_sec <= 0)
603*7c478bd9Sstevel@tonic-gate 			sm_io_to.tv_sec = 1;
604*7c478bd9Sstevel@tonic-gate 		sm_io_to.tv_usec = 0;
605*7c478bd9Sstevel@tonic-gate # endif /* _FFR_SLEEP_USE_SELECT > 0 */
606*7c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SETITIMER */
607*7c478bd9Sstevel@tonic-gate #if _FFR_SLEEP_USE_SELECT > 0
608*7c478bd9Sstevel@tonic-gate 		if (intvl <= _FFR_SLEEP_USE_SELECT)
609*7c478bd9Sstevel@tonic-gate 		{
610*7c478bd9Sstevel@tonic-gate 			r = select(0, NULL, NULL, NULL, &sm_io_to);
611*7c478bd9Sstevel@tonic-gate 			if (r == 0)
612*7c478bd9Sstevel@tonic-gate 				break;
613*7c478bd9Sstevel@tonic-gate 		}
614*7c478bd9Sstevel@tonic-gate 		else
615*7c478bd9Sstevel@tonic-gate #endif /* _FFR_SLEEP_USE_SELECT > 0 */
616*7c478bd9Sstevel@tonic-gate 		(void) pause();
617*7c478bd9Sstevel@tonic-gate 	}
618*7c478bd9Sstevel@tonic-gate 
619*7c478bd9Sstevel@tonic-gate 	/* if out of the loop without the event being triggered remove it */
620*7c478bd9Sstevel@tonic-gate 	if (!SmSleepDone)
621*7c478bd9Sstevel@tonic-gate 		sm_clrevent(ev);
622*7c478bd9Sstevel@tonic-gate 	if (was_held > 0)
623*7c478bd9Sstevel@tonic-gate 		(void) sm_blocksignal(SIGALRM);
624*7c478bd9Sstevel@tonic-gate 	return (SLEEP_T) 0;
625*7c478bd9Sstevel@tonic-gate #endif /* HAVE_NANOSLEEP */
626*7c478bd9Sstevel@tonic-gate }
627*7c478bd9Sstevel@tonic-gate 
628*7c478bd9Sstevel@tonic-gate #if !HAVE_NANOSLEEP
629*7c478bd9Sstevel@tonic-gate static void
630*7c478bd9Sstevel@tonic-gate sm_endsleep(ignore)
631*7c478bd9Sstevel@tonic-gate 	int ignore;
632*7c478bd9Sstevel@tonic-gate {
633*7c478bd9Sstevel@tonic-gate 	/*
634*7c478bd9Sstevel@tonic-gate 	**  NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
635*7c478bd9Sstevel@tonic-gate 	**	ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
636*7c478bd9Sstevel@tonic-gate 	**	DOING.
637*7c478bd9Sstevel@tonic-gate 	*/
638*7c478bd9Sstevel@tonic-gate 
639*7c478bd9Sstevel@tonic-gate 	SmSleepDone = true;
640*7c478bd9Sstevel@tonic-gate }
641*7c478bd9Sstevel@tonic-gate #endif /* !HAVE_NANOSLEEP */
642*7c478bd9Sstevel@tonic-gate 
643