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