Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 5 Apr 1998 17:42:23 +1000
From:      Bruce Evans <bde@zeta.org.au>
To:        peter@netplex.com.au, smp@FreeBSD.ORG
Cc:        phk@FreeBSD.ORG
Subject:   Re: more SMP stuff
Message-ID:  <199804050742.RAA27669@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>I was curious about why cron was failing and tested to see what a manual 
>SIGALRM did to cron in nanosleep to test the suspicion that signals were a 
>problem:

nanosleep() is currently quite broken:
- EWOULDBLOCK is returned instead of 0 in most cases when the timeout
  expires.
- EWOULDBLOCK is returned instead of EINTR if an interrupt occurs and
  syscalls are not being restarted after this interrupt.
- a too-large remaining time is often returned after an interrupt.
- negative remaining times are sometimes returned.
- the reduction to 24 hours is unnecessary and doesn't work when
  hz is very large or not a divisor of 1000000000, or if hz is
  normal and ints are much smaller than 32 bits.

I'm also getting almost infinite loops in nanotime().  `delta' has an
unexpected value and the while loop takes a long time to reduce it.
It should be < 2000000000 and held in a `long' to unpessimise the
loop.

Here is my current attempt to fix nanosleep1().  It only returns the
remaining time on error (nanosleep1() still wastes time copyout()ing
the unusable and now always garbage value on successful completion).

Bruce

diff -c2 kern_time.c~ kern_time.c
*** kern_time.c~	Sun Apr  5 14:58:02 1998
--- kern_time.c	Sun Apr  5 15:21:31 1998
***************
*** 200,204 ****
  {
  	struct timespec ts, ts2;
! 	int error, timo;
  
  	if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
--- 205,210 ----
  {
  	struct timespec ts, ts2;
! 	struct timeval tv;
! 	int error;
  
  	if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000)
***************
*** 206,240 ****
  	if (rqt->tv_sec < 0 || rqt->tv_sec == 0 && rqt->tv_nsec == 0)
  		return (0);
- 
  	getnanoruntime(&ts);
  	timespecadd(&ts, rqt);
! 	error = 0;
! 	while (1) {
  		getnanoruntime(&ts2);
! 		if (timespeccmp(&ts2, &ts, >=))
! 			break;
! 		else if (ts2.tv_sec + 60 * 60 * 24 * hz < ts.tv_sec) 
! 			timo = 60 * 60 * 24 * hz;
! 		else if (ts2.tv_sec + 2 < ts.tv_sec) {
! 			/* Leave one second for the difference in tv_nsec */
! 			timo = ts.tv_sec - ts2.tv_sec - 1;
! 			timo *= hz;
! 		} else {
! 			timo = (ts.tv_sec - ts2.tv_sec) * 1000000000;
! 			timo += ts.tv_nsec - ts2.tv_nsec;
! 			timo /= (1000000000 / hz);
! 			timo ++;
  		}
! 		error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", timo);
! 		if (error == ERESTART) {
! 			error = EINTR;
! 			break;
! 		}
! 	}
! 	if (rmt) {
! 		*rmt = ts;
! 		timespecsub(rmt, &ts2);
  	}
- 	return(error);
  }
  
--- 212,236 ----
  	if (rqt->tv_sec < 0 || rqt->tv_sec == 0 && rqt->tv_nsec == 0)
  		return (0);
  	getnanoruntime(&ts);
  	timespecadd(&ts, rqt);
! 	for (;;) {
! 		TIMESPEC_TO_TIMEVAL(&tv, &ts);
! 		error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp",
! 		    tvtohz(&tv));
  		getnanoruntime(&ts2);
! 		if (error != EWOULDBLOCK) {
! 			if (error == ERESTART)
! 				error = EINTR;
! 			if (rmt != NULL) {
! 				timespecsub(&ts, &ts2);
! 				if (ts.tv_sec < 0)
! 					timespecclear(&ts);
! 				*rmt = ts;
! 			}
! 			return (error);
  		}
! 		if (timespeccmp(&ts2, &ts, >=))
! 			return (0);
  	}
  }
  

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-smp" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199804050742.RAA27669>