diff options
author | davide <davide@FreeBSD.org> | 2013-03-04 15:57:41 +0000 |
---|---|---|
committer | davide <davide@FreeBSD.org> | 2013-03-04 15:57:41 +0000 |
commit | 4d11390875abd4474e652d8ca656da1c36791bb5 (patch) | |
tree | 267b7c8cda757bcadec398deec40341b55d82989 | |
parent | 2ca848c3f6d41f466c5bacf9f67c57da0c0764e2 (diff) | |
download | FreeBSD-src-4d11390875abd4474e652d8ca656da1c36791bb5.zip FreeBSD-src-4d11390875abd4474e652d8ca656da1c36791bb5.tar.gz |
MFcalloutng:
kern_nanosleep() is now converted to use tsleep_sbt(). With this change
nanosleep() and usleep() can handle sub-tick precision for timeouts.
Also, try to help coalesce of events passing as argument to tsleep_bt()
a precision value calculated as a percentage of the sleep time.
This percentage is default 5%, but it can tuned according to users
need via the sysctl interface.
Sponsored by: Google Summer of Code 2012, iXsystems inc.
Tested by: flo, marius, ian, markj, Fabian Keil
-rw-r--r-- | sys/kern/kern_time.c | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 97c288d..da51106 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <sys/resourcevar.h> #include <sys/signalvar.h> #include <sys/kernel.h> +#include <sys/sleepqueue.h> #include <sys/syscallsubr.h> #include <sys/sysctl.h> #include <sys/sysent.h> @@ -481,38 +482,37 @@ static int nanowait; int kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt) { - struct timespec ts, ts2, ts3; - struct timeval tv; + struct timespec ts; + sbintime_t sbt, sbtt, prec, tmp; int error; if (rqt->tv_nsec < 0 || rqt->tv_nsec >= 1000000000) return (EINVAL); if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0)) return (0); - getnanouptime(&ts); - timespecadd(&ts, rqt); - TIMESPEC_TO_TIMEVAL(&tv, rqt); - for (;;) { - error = tsleep(&nanowait, PWAIT | PCATCH, "nanslp", - tvtohz(&tv)); - getnanouptime(&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); + tmp = tstosbt(*rqt); + prec = tmp; + prec >>= tc_precexp; + if (TIMESEL(&sbt, tmp)) + sbt += tc_tick_sbt; + sbt += tmp; + error = tsleep_sbt(&nanowait, PWAIT | PCATCH, "nanslp", sbt, prec, + C_ABSOLUTE); + if (error != EWOULDBLOCK) { + if (error == ERESTART) + error = EINTR; + TIMESEL(&sbtt, tmp); + if (rmt != NULL) { + ts = sbttots(sbt - sbtt); + if (ts.tv_sec < 0) + timespecclear(&ts); + *rmt = ts; } - if (timespeccmp(&ts2, &ts, >=)) + if (sbtt >= sbt) return (0); - ts3 = ts; - timespecsub(&ts3, &ts2); - TIMESPEC_TO_TIMEVAL(&tv, &ts3); + return (error); } + return (0); } #ifndef _SYS_SYSPROTO_H_ |