1*722Smuffin /* 2*722Smuffin * Copyright 1986 Sun Microsystems, Inc. All rights reserved. 3*722Smuffin * Use is subject to license terms. 4*722Smuffin */ 50Sstevel@tonic-gate 60Sstevel@tonic-gate /* 70Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 80Sstevel@tonic-gate * All rights reserved. The Berkeley software License Agreement 90Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 100Sstevel@tonic-gate */ 110Sstevel@tonic-gate 12*722Smuffin #pragma ident "%Z%%M% %I% %E% SMI" 130Sstevel@tonic-gate 140Sstevel@tonic-gate #include <sys/time.h> 150Sstevel@tonic-gate #include <signal.h> 160Sstevel@tonic-gate 170Sstevel@tonic-gate #define setvec(vec, a) \ 180Sstevel@tonic-gate vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0 190Sstevel@tonic-gate 20*722Smuffin static void sleepx(void); 21*722Smuffin 220Sstevel@tonic-gate /* 230Sstevel@tonic-gate * sleep(n) 240Sstevel@tonic-gate * 250Sstevel@tonic-gate * return 0 if n seconds passed 260Sstevel@tonic-gate * return n - t if t seconds passed 270Sstevel@tonic-gate * 280Sstevel@tonic-gate * this code is gross and works just barely. 290Sstevel@tonic-gate * it would be nice if someone rewrote it. 300Sstevel@tonic-gate */ 310Sstevel@tonic-gate unsigned 32*722Smuffin sleep(unsigned n) 330Sstevel@tonic-gate { 340Sstevel@tonic-gate int omask; 350Sstevel@tonic-gate struct itimerval new, old, zero; 36*722Smuffin struct itimerval *newp = &new; 370Sstevel@tonic-gate struct timeval left_over; 380Sstevel@tonic-gate int alrm_flg; 390Sstevel@tonic-gate struct sigvec vec, ovec; 400Sstevel@tonic-gate 410Sstevel@tonic-gate if (n == 0) 420Sstevel@tonic-gate return(0); 430Sstevel@tonic-gate timerclear(&newp->it_interval); 440Sstevel@tonic-gate timerclear(&newp->it_value); 450Sstevel@tonic-gate if (setitimer(ITIMER_REAL, newp, &old) < 0) 460Sstevel@tonic-gate return(n); 470Sstevel@tonic-gate newp->it_value.tv_sec = n; 480Sstevel@tonic-gate alrm_flg = 0; 490Sstevel@tonic-gate timerclear(&left_over); 500Sstevel@tonic-gate if (timerisset(&old.it_value)) { 510Sstevel@tonic-gate if (timercmp(&old.it_value, &newp->it_value, >)) { 520Sstevel@tonic-gate old.it_value.tv_sec -= newp->it_value.tv_sec; 530Sstevel@tonic-gate ++alrm_flg; 540Sstevel@tonic-gate } else { 550Sstevel@tonic-gate left_over.tv_sec = newp->it_value.tv_sec 560Sstevel@tonic-gate - old.it_value.tv_sec; 570Sstevel@tonic-gate if (old.it_value.tv_usec != 0) { 580Sstevel@tonic-gate left_over.tv_sec--; 590Sstevel@tonic-gate left_over.tv_usec = 1000000 600Sstevel@tonic-gate - old.it_value.tv_usec; 610Sstevel@tonic-gate } 620Sstevel@tonic-gate newp->it_value = old.it_value; 630Sstevel@tonic-gate timerclear(&old.it_value); 640Sstevel@tonic-gate --alrm_flg; 650Sstevel@tonic-gate } 660Sstevel@tonic-gate } 670Sstevel@tonic-gate if (alrm_flg >= 0) { 680Sstevel@tonic-gate setvec(vec, sleepx); 690Sstevel@tonic-gate (void) sigvec(SIGALRM, &vec, &ovec); 700Sstevel@tonic-gate } 710Sstevel@tonic-gate omask = sigblock(sigmask(SIGALRM)); 720Sstevel@tonic-gate (void) setitimer(ITIMER_REAL, newp, (struct itimerval *)0); 730Sstevel@tonic-gate sigpause(omask &~ sigmask(SIGALRM)); 740Sstevel@tonic-gate timerclear(&zero.it_value); 750Sstevel@tonic-gate timerclear(&zero.it_interval); 760Sstevel@tonic-gate (void) setitimer(ITIMER_REAL, &zero, newp); 770Sstevel@tonic-gate if (alrm_flg >= 0) 780Sstevel@tonic-gate (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0); 790Sstevel@tonic-gate (void) sigsetmask(omask); 800Sstevel@tonic-gate if (alrm_flg > 0 || (alrm_flg < 0 && timerisset(&newp->it_value))) { 810Sstevel@tonic-gate struct itimerval reset; 820Sstevel@tonic-gate 830Sstevel@tonic-gate /* 840Sstevel@tonic-gate * I use reset instead of what new points to because the 850Sstevel@tonic-gate * code that calculates the return value depends on the 860Sstevel@tonic-gate * old value of *newp. 870Sstevel@tonic-gate */ 880Sstevel@tonic-gate reset = *newp; 890Sstevel@tonic-gate newp = &reset; 900Sstevel@tonic-gate newp->it_value.tv_usec += old.it_value.tv_usec; 910Sstevel@tonic-gate newp->it_value.tv_sec += old.it_value.tv_sec; 920Sstevel@tonic-gate if (newp->it_value.tv_usec >= 1000000) { 930Sstevel@tonic-gate newp->it_value.tv_usec -= 1000000; 940Sstevel@tonic-gate newp->it_value.tv_sec++; 950Sstevel@tonic-gate } 960Sstevel@tonic-gate (void) setitimer(ITIMER_REAL, newp, (struct itimerval *)0); 970Sstevel@tonic-gate newp = &new; 980Sstevel@tonic-gate } 990Sstevel@tonic-gate left_over.tv_sec += newp->it_value.tv_sec; 1000Sstevel@tonic-gate left_over.tv_usec += newp->it_value.tv_usec; 1010Sstevel@tonic-gate if (left_over.tv_usec >= 1000000) { 1020Sstevel@tonic-gate left_over.tv_sec++; 1030Sstevel@tonic-gate left_over.tv_usec -= 1000000; 1040Sstevel@tonic-gate } 1050Sstevel@tonic-gate if (left_over.tv_usec >= 500000) 1060Sstevel@tonic-gate left_over.tv_sec++; 1070Sstevel@tonic-gate return(left_over.tv_sec); 1080Sstevel@tonic-gate } 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate static void 111*722Smuffin sleepx(void) 1120Sstevel@tonic-gate { 1130Sstevel@tonic-gate } 114