xref: /onnv-gate/usr/src/lib/libbc/libc/gen/sys5/sleep.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
2*0Sstevel@tonic-gate 
3*0Sstevel@tonic-gate /*
4*0Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
5*0Sstevel@tonic-gate  * All rights reserved.  The Berkeley software License Agreement
6*0Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
7*0Sstevel@tonic-gate  */
8*0Sstevel@tonic-gate 
9*0Sstevel@tonic-gate /*
10*0Sstevel@tonic-gate  * Copyright (c) 1986 by Sun Microsystems, Inc.
11*0Sstevel@tonic-gate  */
12*0Sstevel@tonic-gate 
13*0Sstevel@tonic-gate #include <sys/time.h>
14*0Sstevel@tonic-gate #include <signal.h>
15*0Sstevel@tonic-gate 
16*0Sstevel@tonic-gate #define	setvec(vec, a) \
17*0Sstevel@tonic-gate 	vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0
18*0Sstevel@tonic-gate 
19*0Sstevel@tonic-gate /*
20*0Sstevel@tonic-gate  * sleep(n)
21*0Sstevel@tonic-gate  *
22*0Sstevel@tonic-gate  * return 0 if n seconds passed
23*0Sstevel@tonic-gate  * return n - t if t seconds passed
24*0Sstevel@tonic-gate  *
25*0Sstevel@tonic-gate  * this code is gross and works just barely.
26*0Sstevel@tonic-gate  * it would be nice if someone rewrote it.
27*0Sstevel@tonic-gate  */
28*0Sstevel@tonic-gate unsigned
29*0Sstevel@tonic-gate sleep(n)
30*0Sstevel@tonic-gate 	unsigned n;
31*0Sstevel@tonic-gate {
32*0Sstevel@tonic-gate 	void sleepx();
33*0Sstevel@tonic-gate 	int omask;
34*0Sstevel@tonic-gate 	struct itimerval new, old, zero;
35*0Sstevel@tonic-gate 	register struct itimerval *newp = &new;
36*0Sstevel@tonic-gate 	struct timeval left_over;
37*0Sstevel@tonic-gate 	int alrm_flg;
38*0Sstevel@tonic-gate 	struct sigvec vec, ovec;
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate 	if (n == 0)
41*0Sstevel@tonic-gate 		return(0);
42*0Sstevel@tonic-gate 	timerclear(&newp->it_interval);
43*0Sstevel@tonic-gate 	timerclear(&newp->it_value);
44*0Sstevel@tonic-gate 	if (setitimer(ITIMER_REAL, newp, &old) < 0)
45*0Sstevel@tonic-gate 		return(n);
46*0Sstevel@tonic-gate 	newp->it_value.tv_sec = n;
47*0Sstevel@tonic-gate 	alrm_flg = 0;
48*0Sstevel@tonic-gate 	timerclear(&left_over);
49*0Sstevel@tonic-gate 	if (timerisset(&old.it_value)) {
50*0Sstevel@tonic-gate 		if (timercmp(&old.it_value, &newp->it_value, >)) {
51*0Sstevel@tonic-gate 			old.it_value.tv_sec -= newp->it_value.tv_sec;
52*0Sstevel@tonic-gate 			++alrm_flg;
53*0Sstevel@tonic-gate 		} else {
54*0Sstevel@tonic-gate 			left_over.tv_sec = newp->it_value.tv_sec
55*0Sstevel@tonic-gate 			    - old.it_value.tv_sec;
56*0Sstevel@tonic-gate 			if (old.it_value.tv_usec != 0) {
57*0Sstevel@tonic-gate 				left_over.tv_sec--;
58*0Sstevel@tonic-gate 				left_over.tv_usec = 1000000
59*0Sstevel@tonic-gate 				    - old.it_value.tv_usec;
60*0Sstevel@tonic-gate 			}
61*0Sstevel@tonic-gate 			newp->it_value = old.it_value;
62*0Sstevel@tonic-gate 			timerclear(&old.it_value);
63*0Sstevel@tonic-gate 			--alrm_flg;
64*0Sstevel@tonic-gate 		}
65*0Sstevel@tonic-gate 	}
66*0Sstevel@tonic-gate 	if (alrm_flg >= 0) {
67*0Sstevel@tonic-gate 		setvec(vec, sleepx);
68*0Sstevel@tonic-gate 		(void) sigvec(SIGALRM, &vec, &ovec);
69*0Sstevel@tonic-gate 	}
70*0Sstevel@tonic-gate 	omask = sigblock(sigmask(SIGALRM));
71*0Sstevel@tonic-gate 	(void) setitimer(ITIMER_REAL, newp, (struct itimerval *)0);
72*0Sstevel@tonic-gate 	sigpause(omask &~ sigmask(SIGALRM));
73*0Sstevel@tonic-gate 	timerclear(&zero.it_value);
74*0Sstevel@tonic-gate 	timerclear(&zero.it_interval);
75*0Sstevel@tonic-gate 	(void) setitimer(ITIMER_REAL, &zero, newp);
76*0Sstevel@tonic-gate 	if (alrm_flg >= 0)
77*0Sstevel@tonic-gate 		(void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
78*0Sstevel@tonic-gate 	(void) sigsetmask(omask);
79*0Sstevel@tonic-gate 	if (alrm_flg > 0 || (alrm_flg < 0 && timerisset(&newp->it_value))) {
80*0Sstevel@tonic-gate 		struct itimerval reset;
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 		/*
83*0Sstevel@tonic-gate 		 * I use reset instead of what new points to because the
84*0Sstevel@tonic-gate 		 * code that calculates the return value depends on the
85*0Sstevel@tonic-gate 		 * old value of *newp.
86*0Sstevel@tonic-gate 		 */
87*0Sstevel@tonic-gate 		reset = *newp;
88*0Sstevel@tonic-gate 		newp = &reset;
89*0Sstevel@tonic-gate 		newp->it_value.tv_usec += old.it_value.tv_usec;
90*0Sstevel@tonic-gate 		newp->it_value.tv_sec += old.it_value.tv_sec;
91*0Sstevel@tonic-gate 		if (newp->it_value.tv_usec >= 1000000) {
92*0Sstevel@tonic-gate 			newp->it_value.tv_usec -= 1000000;
93*0Sstevel@tonic-gate 			newp->it_value.tv_sec++;
94*0Sstevel@tonic-gate 		}
95*0Sstevel@tonic-gate 		(void) setitimer(ITIMER_REAL, newp, (struct itimerval *)0);
96*0Sstevel@tonic-gate 		newp = &new;
97*0Sstevel@tonic-gate 	}
98*0Sstevel@tonic-gate 	left_over.tv_sec += newp->it_value.tv_sec;
99*0Sstevel@tonic-gate 	left_over.tv_usec += newp->it_value.tv_usec;
100*0Sstevel@tonic-gate 	if (left_over.tv_usec >= 1000000) {
101*0Sstevel@tonic-gate 		left_over.tv_sec++;
102*0Sstevel@tonic-gate 		left_over.tv_usec -= 1000000;
103*0Sstevel@tonic-gate 	}
104*0Sstevel@tonic-gate 	if (left_over.tv_usec >= 500000)
105*0Sstevel@tonic-gate 		left_over.tv_sec++;
106*0Sstevel@tonic-gate 	return(left_over.tv_sec);
107*0Sstevel@tonic-gate }
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate static void
110*0Sstevel@tonic-gate sleepx()
111*0Sstevel@tonic-gate {
112*0Sstevel@tonic-gate }
113