Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/17/84; site ittvax.UUCP Path: utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!genrad!decvax!ittvax!keegane From: keegane@ittvax.UUCP (Edward Keegan) Newsgroups: net.sources Subject: Re: fsleep() -- sleep for fractional seconds (4.2 BSD) Message-ID: <1659@ittvax.UUCP> Date: Tue, 30-Apr-85 09:09:32 EDT Article-I.D.: ittvax.1659 Posted: Tue Apr 30 09:09:32 1985 Date-Received: Thu, 2-May-85 00:47:12 EDT References: <1432@utah-gr.UUCP> Organization: ITT-ATC, Stratford Ct. Lines: 205 > /* s s s * fsleep( d ) -- Sleep for d seconds, where d is a double. Like sleep() > * but with a finer grain. Uses the 4.2 BSD interval timer. > * > * Author: Donn Seeley, UCSD Chemistry Dept., sdchema!donn > * Date: Wed Apr 25 03:28:14 PST 1984 > * Remarks: > * If an alarm clock has gone off for the caller and alarms are being > * blocked, the alarm is lost. You'd think with all those new > * system calls, there would be a way to find out what signals > * have arrived without actually taking them... > * You must define SLEEPBUG when compiling to get the 'feature' of > * sleep() that signals other than alarms won't terminate > * the sleep. > */ > > # include > # include > > # define mask(s) (1 << ((s) - 1)) > > # ifdef SLEEPBUG > static int beep; > # endif SLEEPBUG > > fsleep( d ) > double d; > { > struct itimerval oldalarm, newalarm; > struct sigvec oldvec, newvec; > int _fsleep_handler(); > int savemask; > int wasblocked = 0; > int alarmpending = 0; > > /* > * Sanity check. > */ > if ( d <= 0.0 ) > return; > > /* > * Block the alarm signal. > */ > savemask = sigblock( mask( SIGALRM ) ); > wasblocked = savemask & mask( SIGALRM ); > > /* > * Get the old alarm time, set up the new one. > */ > newalarm.it_value.tv_sec = (long) d; > newalarm.it_value.tv_usec = > (long) ((d - (double) newalarm.it_value.tv_sec) * 1000000.0); > timerclear( &newalarm.it_interval ); > if ( setitimer( ITIMER_REAL, &newalarm, &oldalarm ) < 0 ) { > /* > * Illegal sleep time. > */ > (void) setitimer( ITIMER_REAL, &oldalarm, (struct itimerval *) 0 ); > (void) sigsetmask( savemask ); > return; > } > > /* > * Was there an alarm out there already? > */ > if ( timerisset( &oldalarm.it_value ) ) > ++alarmpending; > else if ( timerisset( &oldalarm.it_interval ) ) { > /* > * Paranoia. > */ > ++alarmpending; > oldalarm.it_value.tv_usec = 11000; > } > > /* > * If an old alarm would come while we slept, shorten the sleep. > */ > if ( alarmpending && > ! timercmp( &oldalarm.it_value, &newalarm.it_value, > ) ) { > (void) setitimer( ITIMER_REAL, &oldalarm, (struct itimerval *) 0 ); > if ( ! wasblocked ) { > /* > * Just take the old alarm and return. > */ > sigpause( savemask ); > (void) sigsetmask( savemask ); > return; > } > /* > * Alarms are being blocked by the caller -- arrange to queue > * an alarm for the caller when the sleep finishes. > */ > newalarm.it_value = oldalarm.it_value; > { > struct timeval t; > > timerclear( &t ); > t.tv_usec = 11000; > timevaladd( &oldalarm.it_value, &t ); > } > } > > /* > * Get the old signal handler, set up the new one. > */ > newvec.sv_handler = _fsleep_handler; > newvec.sv_mask = savemask; > newvec.sv_onstack = 0; > (void) sigvec( SIGALRM, &newvec, &oldvec ); > > /* > * Pause for the alarm. > */ > # ifdef SLEEPBUG > /* > * Duplicate disgusting sleep() behavior of only breaking for alarms. > */ > beep = 0; > while ( ! beep ) > # endif SLEEPBUG > sigpause( savemask & ~ mask( SIGALRM ) ); > > /* > * Reset the old signal handler and alarm. > */ > sigvec( SIGALRM, &oldvec, (struct sigvec *) 0 ); > if ( alarmpending ) { > timevalsub( &oldalarm.it_value, &newalarm.it_value ); > (void) setitimer( ITIMER_REAL, (struct itimerval *) 0, &newalarm ); > timevaladd( &oldalarm.it_value, &newalarm.it_value ); > (void) setitimer( ITIMER_REAL, &oldalarm, (struct itimerval *) 0 ); > } > > /* > * Reset the mask and return. This unblocks the alarm if it was > * unblocked previously, allowing any old alarm to arrive. > */ > (void) sigsetmask( savemask ); > return; > } > > > > /* > * _fsleep_handler() -- Dummy routine for handling alarms. > */ > int _fsleep_handler() > { > # ifdef SLEEPBUG > ++beep; > # endif SLEEPBUG > return 0; > } > > > > /* > * Add and subtract routines for timevals. > * Stolen from the kernel. > * > * N.B.: subtract routine doesn't deal with > * results which are before the beginning, > * it just gets very confused in this case. > * Caveat emptor. > */ > timevaladd(t1, t2) > struct timeval *t1, *t2; > { > > t1->tv_sec += t2->tv_sec; > t1->tv_usec += t2->tv_usec; > timevalfix(t1); > } > > timevalsub(t1, t2) > struct timeval *t1, *t2; > { > > t1->tv_sec -= t2->tv_sec; > t1->tv_usec -= t2->tv_usec; > timevalfix(t1); > } > > timevalfix(t1) > struct timeval *t1; > { > > if (t1->tv_usec < 0) { > t1->tv_sec--; > t1->tv_usec += 1000000; > } > if (t1->tv_usec >= 1000000) { > t1->tv_sec++; > t1->tv_usec -= 1000000; > } > } *** REPLACE THIS LINE WITH YOUR MESSAGE ***