donn@utah-gr.UUCP (Donn Seeley) (04/29/85)
/*
* 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;
}
}keegane@ittvax.UUCP (Edward Keegan) (04/30/85)
> /* 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 ***