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>