xref: /csrg-svn/lib/libc/gen/sleep.c (revision 61111)
121360Sdist /*
2*61111Sbostic  * Copyright (c) 1989, 1993
3*61111Sbostic  *	The Regents of the University of California.  All rights reserved.
439169Sbostic  *
542626Sbostic  * %sccs.include.redist.c%
621360Sdist  */
721360Sdist 
826593Sdonn #if defined(LIBC_SCCS) && !defined(lint)
9*61111Sbostic static char sccsid[] = "@(#)sleep.c	8.1 (Berkeley) 06/04/93";
1039169Sbostic #endif /* LIBC_SCCS and not lint */
1112977Ssam 
1213582Ssam #include <sys/time.h>
1339169Sbostic #include <sys/signal.h>
1446597Sdonn #include <unistd.h>
151979Swnj 
1612977Ssam #define	setvec(vec, a) \
1712977Ssam 	vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
1812977Ssam 
1914618Skarels static int ringring;
2014618Skarels 
2146597Sdonn unsigned int
sleep(seconds)2239169Sbostic sleep(seconds)
2339169Sbostic 	unsigned int seconds;
241979Swnj {
2539169Sbostic 	register struct itimerval *itp;
2612977Ssam 	struct itimerval itv, oitv;
2712977Ssam 	struct sigvec vec, ovec;
2839169Sbostic 	long omask;
2946597Sdonn 	static void sleephandler();
301979Swnj 
3139169Sbostic 	itp = &itv;
3239169Sbostic 	if (!seconds)
3346597Sdonn 		return 0;
3412977Ssam 	timerclear(&itp->it_interval);
3512977Ssam 	timerclear(&itp->it_value);
3612977Ssam 	if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
3746597Sdonn 		return seconds;
3839169Sbostic 	itp->it_value.tv_sec = seconds;
3912977Ssam 	if (timerisset(&oitv.it_value)) {
4012977Ssam 		if (timercmp(&oitv.it_value, &itp->it_value, >))
4112977Ssam 			oitv.it_value.tv_sec -= itp->it_value.tv_sec;
421979Swnj 		else {
4312977Ssam 			itp->it_value = oitv.it_value;
4412977Ssam 			/*
4539169Sbostic 			 * This is a hack, but we must have time to return
4639169Sbostic 			 * from the setitimer after the alarm or else it'll
4739169Sbostic 			 * be restarted.  And, anyway, sleep never did
4839169Sbostic 			 * anything more than this before.
4912977Ssam 			 */
5013019Ssam 			oitv.it_value.tv_sec = 1;
5113019Ssam 			oitv.it_value.tv_usec = 0;
521979Swnj 		}
531979Swnj 	}
5439169Sbostic 	setvec(vec, sleephandler);
5512977Ssam 	(void) sigvec(SIGALRM, &vec, &ovec);
5617491Skarels 	omask = sigblock(sigmask(SIGALRM));
5714954Skarels 	ringring = 0;
5814618Skarels 	(void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
5914618Skarels 	while (!ringring)
6017491Skarels 		sigpause(omask &~ sigmask(SIGALRM));
6114618Skarels 	(void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
6217491Skarels 	(void) sigsetmask(omask);
6314618Skarels 	(void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
6446597Sdonn 	return 0;
651979Swnj }
661979Swnj 
6739169Sbostic static void
sleephandler()6839169Sbostic sleephandler()
691979Swnj {
7014618Skarels 	ringring = 1;
711979Swnj }
72