summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavide <davide@FreeBSD.org>2013-03-04 15:57:41 +0000
committerdavide <davide@FreeBSD.org>2013-03-04 15:57:41 +0000
commit4d11390875abd4474e652d8ca656da1c36791bb5 (patch)
tree267b7c8cda757bcadec398deec40341b55d82989
parent2ca848c3f6d41f466c5bacf9f67c57da0c0764e2 (diff)
downloadFreeBSD-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.c46
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_
OpenPOWER on IntegriCloud