fsleep() -- sleep for fractional seconds (4.2 BSD)
Edward Keegan
keegane at ittvax.UUCP
Tue Apr 30 23:09:32 AEST 1985
> /*
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 <signal.h>
> # include <sys/time.h>
>
> # 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 ***
More information about the Comp.sources.unix
mailing list