Index: sys/kern/kern_time.c =================================================================== --- sys/kern/kern_time.c (revision 239329) +++ sys/kern/kern_time.c (working copy) @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -60,6 +61,13 @@ __FBSDID("$FreeBSD$"); #define MAX_CLOCKS (CLOCK_MONOTONIC+1) +#define TIMESEL(x, bt) \ + (((x) < (nanosleep_precision)) ? binuptime(&bt) : getbinuptime(&bt)) + +static int nanosleep_precision; +SYSCTL_INT(_kern, OID_AUTO, nanosleep_precision, CTLFLAG_RW, + &nanosleep_precision, 0, "Precision threshold for nanosleep function"); + static struct kclock posix_clocks[MAX_CLOCKS]; static uma_zone_t itimer_zone = NULL; @@ -105,7 +113,15 @@ int itimespecfix(struct timespec *ts); SYSINIT(posix_timer, SI_SUB_P1003_1B, SI_ORDER_FIRST+4, itimer_start, NULL); +static void +init_precision(void) +{ + + nanosleep_precision = 20 * imin(1000000000 / hz, 1000000); +} +SYSINIT(init_precision, SI_SUB_SOFTINTR, SI_ORDER_ANY, init_precision, NULL); + static int settime(struct thread *td, struct timeval *tv) { @@ -361,13 +377,13 @@ kern_nanosleep(struct thread *td, struct timespec return (EINVAL); if (rqt->tv_sec < 0 || (rqt->tv_sec == 0 && rqt->tv_nsec == 0)) return (0); - binuptime(&bt); + TIMESEL(rqt->tv_nsec, bt); timespec2bintime(rqt, &tmp); bintime_add(&bt,&tmp); for (;;) { error = tsleep_bt(&nanowait, PWAIT | PCATCH, "nanslp", &bt, C_DIRECT_EXEC); - binuptime(&bt2); + TIMESEL(rqt->tv_nsec, bt2); if (error != EWOULDBLOCK) { if (error == ERESTART) error = EINTR;