xref: /original-bsd/lib/libc/gen/usleep.c (revision bac379f5)
1f57949ebSmckusick /*
2*bac379f5Sbostic  * Copyright (c) 1989, 1993
3*bac379f5Sbostic  *	The Regents of the University of California.  All rights reserved.
4f9c00025Sbostic  *
524ce2517Sbostic  * %sccs.include.redist.c%
6f57949ebSmckusick  */
7f57949ebSmckusick 
8c34e25a4Sdonn #if defined(LIBC_SCCS) && !defined(lint)
9*bac379f5Sbostic static char sccsid[] = "@(#)usleep.c	8.1 (Berkeley) 06/04/93";
10f9c00025Sbostic #endif /* LIBC_SCCS and not lint */
1112e61e86Sserge 
1212e61e86Sserge #include <sys/time.h>
13f9c00025Sbostic #include <sys/signal.h>
14ae227ee3Sdonn #include <unistd.h>
1512e61e86Sserge 
1612e61e86Sserge #define	TICK	10000		/* system clock resolution in microseconds */
17f9c00025Sbostic #define	USPS	1000000		/* number of microseconds in a second */
1812e61e86Sserge 
1912e61e86Sserge #define	setvec(vec, a) \
2012e61e86Sserge 	vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
2112e61e86Sserge 
2212e61e86Sserge static int ringring;
2312e61e86Sserge 
24ae227ee3Sdonn void
usleep(useconds)25f9c00025Sbostic usleep(useconds)
26f9c00025Sbostic 	unsigned int useconds;
2712e61e86Sserge {
28f9c00025Sbostic 	register struct itimerval *itp;
2912e61e86Sserge 	struct itimerval itv, oitv;
3012e61e86Sserge 	struct sigvec vec, ovec;
31f9c00025Sbostic 	long omask;
32ae227ee3Sdonn 	static void sleephandler();
3312e61e86Sserge 
34f9c00025Sbostic 	itp = &itv;
35f9c00025Sbostic 	if (!useconds)
3612e61e86Sserge 		return;
3712e61e86Sserge 	timerclear(&itp->it_interval);
3812e61e86Sserge 	timerclear(&itp->it_value);
3912e61e86Sserge 	if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
4012e61e86Sserge 		return;
41f9c00025Sbostic 	itp->it_value.tv_sec = useconds / USPS;
42f9c00025Sbostic 	itp->it_value.tv_usec = useconds % USPS;
4312e61e86Sserge 	if (timerisset(&oitv.it_value)) {
4412e61e86Sserge 		if (timercmp(&oitv.it_value, &itp->it_value, >)) {
4512e61e86Sserge 			oitv.it_value.tv_sec -= itp->it_value.tv_sec;
4612e61e86Sserge 			oitv.it_value.tv_usec -= itp->it_value.tv_usec;
4712e61e86Sserge 			if (oitv.it_value.tv_usec < 0) {
4812e61e86Sserge 				oitv.it_value.tv_usec += USPS;
4912e61e86Sserge 				oitv.it_value.tv_sec--;
5012e61e86Sserge 			}
5112e61e86Sserge 		} else {
5212e61e86Sserge 			itp->it_value = oitv.it_value;
5312e61e86Sserge 			oitv.it_value.tv_sec = 0;
5412e61e86Sserge 			oitv.it_value.tv_usec = 2 * TICK;
5512e61e86Sserge 		}
5612e61e86Sserge 	}
57f9c00025Sbostic 	setvec(vec, sleephandler);
5812e61e86Sserge 	(void) sigvec(SIGALRM, &vec, &ovec);
5912e61e86Sserge 	omask = sigblock(sigmask(SIGALRM));
6012e61e86Sserge 	ringring = 0;
6112e61e86Sserge 	(void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
6212e61e86Sserge 	while (!ringring)
6312e61e86Sserge 		sigpause(omask &~ sigmask(SIGALRM));
6412e61e86Sserge 	(void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
6512e61e86Sserge 	(void) sigsetmask(omask);
6612e61e86Sserge 	(void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
6712e61e86Sserge }
6812e61e86Sserge 
69f9c00025Sbostic static void
sleephandler()70f9c00025Sbostic sleephandler()
7112e61e86Sserge {
7212e61e86Sserge 	ringring = 1;
7312e61e86Sserge }
74