Index: sys/sys/sx.h =================================================================== --- sys/sys/sx.h (revision 243581) +++ sys/sys/sx.h (working copy) @@ -276,7 +276,7 @@ __sx_sunlock(struct sx *sx, const char *file, int #define sx_sleep(chan, sx, pri, wmesg, timo) \ _sleep((chan), &(sx)->lock_object, (pri), (wmesg), (timo), \ - NULL, 0) + NULL, NULL, 0) /* * Options passed to sx_init_flags(). Index: sys/sys/rwlock.h =================================================================== --- sys/sys/rwlock.h (revision 243581) +++ sys/sys/rwlock.h (working copy) @@ -211,7 +211,8 @@ void __rw_assert(const volatile uintptr_t *c, int rw_runlock(rw); \ } while (0) #define rw_sleep(chan, rw, pri, wmesg, timo) \ - _sleep((chan), &(rw)->lock_object, (pri), (wmesg), (timo), NULL, 0) + _sleep((chan), &(rw)->lock_object, (pri), (wmesg), (timo), \ + NULL, NULL, 0) #define rw_initialized(rw) lock_initalized(&(rw)->lock_object) Index: sys/sys/mutex.h =================================================================== --- sys/sys/mutex.h (revision 243581) +++ sys/sys/mutex.h (working copy) @@ -377,7 +377,7 @@ extern struct mtx_pool *mtxpool_sleep; #define mtx_sleep(chan, mtx, pri, wmesg, timo) \ _sleep((chan), &(mtx)->lock_object, (pri), (wmesg), (timo), \ - NULL, 0) + NULL, NULL, 0) #define mtx_initialized(m) lock_initalized(&(m)->lock_object) Index: sys/sys/sleepqueue.h =================================================================== --- sys/sys/sleepqueue.h (revision 243581) +++ sys/sys/sleepqueue.h (working copy) @@ -108,14 +108,14 @@ struct sleepqueue *sleepq_lookup(void *wchan); void sleepq_release(void *wchan); void sleepq_remove(struct thread *td, void *wchan); int sleepq_signal(void *wchan, int flags, int pri, int queue); -void _sleepq_set_timeout(void *wchan, struct bintime *bt, int timo, - int flags); +void _sleepq_set_timeout(void *wchan, struct bintime *bt, + struct bintime *precision, int timo, int flags); #define sleepq_set_timeout(wchan, timo) \ - _sleepq_set_timeout((wchan), NULL, (timo), 0) + _sleepq_set_timeout((wchan), NULL, NULL, (timo), 0) #define sleepq_set_timeout_flags(wchan, timo, flags) \ - _sleepq_set_timeout((wchan), NULL, (timo), (flags)) -#define sleepq_set_timeout_bt(wchan, bt, flags) \ - _sleepq_set_timeout((wchan), (bt), 0, (flags)) + _sleepq_set_timeout((wchan), NULL, NULL, (timo), (flags)) +#define sleepq_set_timeout_bt(wchan, bt, precision) \ + _sleepq_set_timeout((wchan), (bt), (precision), 0, 0) u_int sleepq_sleepcnt(void *wchan, int queue); int sleepq_timedwait(void *wchan, int pri); int sleepq_timedwait_sig(void *wchan, int pri); Index: sys/sys/callout.h =================================================================== --- sys/sys/callout.h (revision 243581) +++ sys/sys/callout.h (working copy) @@ -51,25 +51,11 @@ #define CALLOUT_DIRECT 0x0100 /* allow exec from hw int context */ #define C_DIRECT_EXEC 0x0001 /* direct execution of callout */ -#define C_PABSBITS 24 -#define C_PABSMASK (~((1 << (32 - C_PABSBITS)) - 1)) -#define C_PABSRANGE ((1 << C_PABSBITS) - 1) -#define C_BT2PABS(x) ((x) >> 40) -#define C_SETPABS(x) (((x) & C_PABSRANGE) << 8) -#define C_US2PABS(x) (((x) * 4294) & ~C_PABSMASK) -#define C_PABS2BT(x) ((uint64_t)(flags & C_PABSMASK) << 32) -#define C_PRELBITS 5 +#define C_PRELBITS 7 #define C_PRELRANGE ((1 << C_PRELBITS) - 1) -#define C_PRELSET(x) (((x) & C_PRELRANGE) << 1) +#define C_PRELSET(x) ((x) << 1) #define C_PRELGET(x) (((x) >> 1) & C_PRELRANGE) -/* - * Common values specified for precision. - */ -#define C_P1MS C_US2PABS(1000) -#define C_P10MS C_US2PABS(10000) -#define C_P100MS C_US2PABS(100000) - struct callout_handle { struct callout *callout; }; @@ -89,16 +75,16 @@ void _callout_init_lock(struct callout *, struct l _callout_init_lock((c), ((rw) != NULL) ? &(rw)->lock_object : \ NULL, (flags)) #define callout_pending(c) ((c)->c_flags & CALLOUT_PENDING) -int _callout_reset_on(struct callout *, struct bintime *, int, - void (*)(void *), void *, int, int); +int _callout_reset_on(struct callout *, struct bintime *, + struct bintime *, int, void (*)(void *), void *, int, int); #define callout_reset_on(c, to_ticks, fn, arg, cpu) \ - _callout_reset_on((c), (NULL), (to_ticks), (fn), (arg), (cpu), \ - (0)) + _callout_reset_on((c), NULL, NULL, (to_ticks), (fn), (arg), \ + (cpu), 0) #define callout_reset_flags_on(c, to_ticks, fn, arg, cpu, flags) \ - _callout_reset_on((c), (NULL), (to_ticks), (fn), (arg), (cpu), \ - (flags)) -#define callout_reset_bt_on(c, bt, fn, arg, cpu, flags) \ - _callout_reset_on((c), (bt), (0), (fn), (arg), (cpu), (flags)) + _callout_reset_on((c), NULL, NULL, (to_ticks), (fn), (arg), (cpu), \ + (flags)) +#define callout_reset_bt_on(c, bt, pr, fn, arg, cpu, flags) \ + _callout_reset_on((c), (bt), (pr), 0, (fn), (arg), (cpu), (flags)) #define callout_reset(c, on_tick, fn, arg) \ callout_reset_on((c), (on_tick), (fn), (arg), (c)->c_cpu) #define callout_reset_curcpu(c, on_tick, fn, arg) \ Index: sys/sys/condvar.h =================================================================== --- sys/sys/condvar.h (revision 243581) +++ sys/sys/condvar.h (working copy) @@ -56,9 +56,11 @@ void _cv_wait(struct cv *cvp, struct lock_object * void _cv_wait_unlock(struct cv *cvp, struct lock_object *lock); int _cv_wait_sig(struct cv *cvp, struct lock_object *lock); int _cv_timedwait(struct cv *cvp, struct lock_object *lock, - struct bintime *bt, int timo, int flags); + struct bintime *bt, struct bintime *precision, int timo, + int flags); int _cv_timedwait_sig(struct cv *cvp, struct lock_object *lock, - struct bintime *bt, int timo, int flags); + struct bintime *bt, struct bintime *precision, int timo, + int flags); void cv_signal(struct cv *cvp); void cv_broadcastpri(struct cv *cvp, int pri); @@ -70,20 +72,23 @@ void cv_broadcastpri(struct cv *cvp, int pri); #define cv_wait_sig(cvp, lock) \ _cv_wait_sig((cvp), &(lock)->lock_object) #define cv_timedwait(cvp, lock, timo) \ - _cv_timedwait((cvp), &(lock)->lock_object, NULL, (timo), 0) -#define cv_timedwait_bt(cvp, lock, bt, flags) \ - _cv_timedwait_sig((cvp), &(lock)->lock_object, (bt), 0, 0) -#define cv_timedwait_sig_bt(cvp, lock, bt, flags) \ - _cv_timedwait_sig((cvp), &(lock)->lock_object, (bt), 0, \ - (flags)) + _cv_timedwait((cvp), &(lock)->lock_object, NULL, NULL, \ + (timo), 0) +#define cv_timedwait_bt(cvp, lock, bt, pr) \ + _cv_timedwait_sig((cvp), &(lock)->lock_object, (bt), \ + (pr), 0, 0) +#define cv_timedwait_sig_bt(cvp, lock, bt, pr) \ + _cv_timedwait_sig((cvp), &(lock)->lock_object, (bt), (pr), 0, \ + 0) #define cv_timedwait_flags(cvp, lock, timo, flags) \ - _cv_timedwait((cvp), &(lock)->lock_object, NULL, (timo), \ + _cv_timedwait((cvp), &(lock)->lock_object, NULL, NULL, (timo), \ (flags)) #define cv_timedwait_sig(cvp, lock, timo) \ - _cv_timedwait_sig((cvp), &(lock)->lock_object, NULL, (timo), 0) + _cv_timedwait_sig((cvp), &(lock)->lock_object, NULL, NULL, \ + (timo), 0) #define cv_timedwait_sig_flags(cvp, lock, timo, flags) \ - _cv_timedwait_sig((cvp), &(lock)->lock_object, NULL, (timo), \ - (flags)) + _cv_timedwait_sig((cvp), &(lock)->lock_object, NULL, NULL, \ + (timo), (flags)) #define cv_broadcast(cvp) cv_broadcastpri(cvp, 0) Index: sys/sys/systm.h =================================================================== --- sys/sys/systm.h (revision 243581) +++ sys/sys/systm.h (working copy) @@ -341,23 +341,24 @@ static __inline void splx(intrmask_t ipl __unused * less often. */ int _sleep(void *chan, struct lock_object *lock, int pri, const char *wmesg, - int timo, struct bintime *bt, int flags) __nonnull(1); + int timo, struct bintime *bt, struct bintime *precision, + int flags) __nonnull(1); #define msleep(chan, mtx, pri, wmesg, timo) \ _sleep((chan), &(mtx)->lock_object, (pri), (wmesg), (timo), \ - NULL, 0) + NULL, NULL, 0) #define msleep_flags(chan, mtx, pri, wmesg, timo, flags) \ _sleep((chan), &(mtx)->lock_object, (pri), (wmesg), (timo), \ - NULL, (flags)) -#define msleep_bt(chan, mtx, pri, wmesg, bt, flags) \ + NULL, NULL, (flags)) +#define msleep_bt(chan, mtx, pri, wmesg, bt, pr) \ _sleep((chan), &(mtx)->lock_object, (pri), (wmesg) 0, (bt), \ - (flags)) + (pr), 0) int msleep_spin(void *chan, struct mtx *mtx, const char *wmesg, int timo) __nonnull(1); int pause(const char *wmesg, int timo); #define tsleep(chan, pri, wmesg, timo) \ - _sleep((chan), NULL, (pri), (wmesg), (timo), NULL, 0) -#define tsleep_bt(chan, pri, wmesg, bt, flags) \ - _sleep((chan), NULL, (pri), (wmesg), 0, (bt), (flags)) + _sleep((chan), NULL, (pri), (wmesg), (timo), NULL, NULL, 0) +#define tsleep_bt(chan, pri, wmesg, bt, pr) \ + _sleep((chan), NULL, (pri), (wmesg), 0, (bt), (pr), 0) void wakeup(void *chan) __nonnull(1); void wakeup_one(void *chan) __nonnull(1); Index: sys/sys/time.h =================================================================== --- sys/sys/time.h (revision 243581) +++ sys/sys/time.h (working copy) @@ -102,6 +102,15 @@ bintime_mul(struct bintime *bt, u_int x) bt->frac = (p2 << 32) | (p1 & 0xffffffffull); } +static __inline void +bintime_divpow2(struct bintime *bt, u_int exp) +{ + + bt->frac >>= exp; + bt->frac |= (uint64_t)bt->sec << (64 - exp); + bt->sec >>= exp; +} + #define bintime_clear(a) ((a)->sec = (a)->frac = 0) #define bintime_isset(a) ((a)->sec || (a)->frac) #define bintime_cmp(a, b, cmp) \ @@ -292,7 +301,9 @@ extern time_t time_uptime; extern struct bintime boottimebin; extern struct bintime tick_bt; extern struct timeval boottime; +extern int tc_timepercentage; extern int tc_timethreshold; +extern struct bintime bt_timethreshold; /* * Functions for looking at our clock: [get]{bin,nano,micro}[up]time() @@ -342,19 +353,20 @@ int tvtohz(struct timeval *tv); #define TC_DEFAULTPERC 5 +#define BT2FREQ(bt) \ + (((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) / \ + ((bt)->frac >> 1)) + #define FREQ2BT(freq, bt) \ -{ \ - (bt)->sec = 0; \ - (bt)->frac = ((uint64_t)0x8000000000000000 / (freq)) << 1; \ +{ \ + (bt)->sec = 0; \ + (bt)->frac = ((uint64_t)0x8000000000000000 / (freq)) << 1; \ } -#define BT2FREQ(bt) \ - (((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) / \ - ((bt)->frac >> 1)) -#define TIMESEL(x, bt) \ - ((x) < tc_timethreshold ? (binuptime : getbinuptime(&(bt))) +#define TIMESEL(bt, bt2) \ + ((bintime_cmp((bt), (bt2), >=)) ? \ + binuptime((bt)) : getbinuptime((bt))) - #else /* !_KERNEL */ #include Index: sys/kern/kern_time.c =================================================================== --- sys/kern/kern_time.c (revision 243581) +++ sys/kern/kern_time.c (working copy) @@ -483,35 +483,45 @@ int kern_nanosleep(struct thread *td, struct timespec *rqt, struct timespec *rmt) { struct timespec ts; - struct bintime bt, bt2, tmp; + struct bintime bt, btt, bt_prec, halftick_bt, 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); - binuptime(&bt); timespec2bintime(rqt, &tmp); - bintime_add(&bt,&tmp); - for (;;) { - error = tsleep_bt(&nanowait, PWAIT | PCATCH, "nanslp", &bt, 0); - binuptime(&bt2); - if (error != EWOULDBLOCK) { - if (error == ERESTART) - error = EINTR; - if (rmt != NULL) { - tmp = bt; - bintime_sub(&tmp, &bt2); - bintime2timespec(&tmp, &ts); - if (ts.tv_sec < 0) - timespecclear(&ts); - *rmt = ts; - } - return (error); + TIMESEL(&bt, &bt_timethreshold); + bintime_add(&bt, &tmp); + bt_prec = tmp; + bintime_divpow2(&bt_prec, tc_timepercentage); + if (rqt->tv_nsec > tc_timethreshold) { + /* Use this to compensate getbinuptime() impreciness */ + bintime_add(&bt, &tick_bt); + halftick_bt = tick_bt; + bintime_divpow2(&halftick_bt, 1); + if (bintime_cmp(&bt_prec, &halftick_bt, <)) + bt_prec = halftick_bt; + } + bintime_add(&bt, &bt_prec); + error = tsleep_bt(&nanowait, PWAIT | PCATCH, "nanslp", &bt, &bt_prec); + TIMESEL(&btt, &bt_timethreshold); + if (error != EWOULDBLOCK) { + if (error == ERESTART) + error = EINTR; + if (rmt != NULL) { + tmp = bt; + bintime_sub(&tmp, &btt); + bintime2timespec(&tmp, &ts); + if (ts.tv_sec < 0) + timespecclear(&ts); + *rmt = ts; } - if (bintime_cmp(&bt2, &bt, >=)) + if (bintime_cmp(&btt, &bt, >=)) return (0); + return (error); } + return (0); } #ifndef _SYS_SYSPROTO_H_ Index: sys/kern/subr_sleepqueue.c =================================================================== --- sys/kern/subr_sleepqueue.c (revision 243581) +++ sys/kern/subr_sleepqueue.c (working copy) @@ -363,7 +363,8 @@ sleepq_add(void *wchan, struct lock_object *lock, * sleep queue after timo ticks if the thread has not already been awakened. */ void -_sleepq_set_timeout(void *wchan, struct bintime *bt, int timo, int flags) +_sleepq_set_timeout(void *wchan, struct bintime *bt, struct bintime *precision, + int timo, int flags) { struct sleepqueue_chain *sc; @@ -379,7 +380,7 @@ void callout_reset_flags_on(&td->td_slpcallout, timo, sleepq_timeout, td, PCPU_GET(cpuid), flags | C_DIRECT_EXEC); else - callout_reset_bt_on(&td->td_slpcallout, bt, + callout_reset_bt_on(&td->td_slpcallout, bt, precision, sleepq_timeout, td, PCPU_GET(cpuid), flags | C_DIRECT_EXEC); } Index: sys/kern/sys_generic.c =================================================================== --- sys/kern/sys_generic.c (revision 243581) +++ sys/kern/sys_generic.c (working copy) @@ -102,7 +102,8 @@ static int dofilewrite(struct thread *, int, struc off_t, int); static void doselwakeup(struct selinfo *, int); static void seltdinit(struct thread *); -static int seltdwait(struct thread *, struct bintime *, int); +static int seltdwait(struct thread *, struct bintime *, struct bintime *, + int); static void seltdclear(struct thread *); /* @@ -902,11 +903,12 @@ kern_select(struct thread *td, int nd, fd_set *fd_ */ fd_mask s_selbits[howmany(2048, NFDBITS)]; fd_mask *ibits[3], *obits[3], *selbits, *sbp; - struct bintime abt, rbt; + struct bintime abt, halftick_bt, precision, rbt; struct timeval atv; - int error, lf, ndu, timo; + int error, lf, ndu; u_int nbufbytes, ncpbytes, ncpubytes, nfdbits; + timevalclear(&atv); if (nd < 0) return (EINVAL); fdp = td->td_proc->p_fd; @@ -1002,9 +1004,19 @@ kern_select(struct thread *td, int nd, fd_set *fd_ error = EINVAL; goto done; } - binuptime(&rbt); timeval2bintime(&atv, &abt); + TIMESEL(&rbt, &bt_timethreshold); bintime_add(&abt, &rbt); + precision = abt; + bintime_divpow2(&precision, tc_timepercentage); + if (bintime_cmp(&tick_bt, &precision, >)) { + bintime_add(&abt, &tick_bt); + halftick_bt = tick_bt; + bintime_divpow2(&halftick_bt, 1); + if (bintime_cmp(&precision, &halftick_bt, <)) + precision = halftick_bt; + } + bintime_add(&abt, &precision); } else { abt.sec = 0; abt.frac = 0; @@ -1016,14 +1028,13 @@ kern_select(struct thread *td, int nd, fd_set *fd_ if (error || td->td_retval[0] != 0) break; if (abt.sec || abt.frac) { - binuptime(&rbt); + TIMESEL(&rbt, &bt_timethreshold); if (bintime_cmp(&rbt, &abt, >=)) break; - error = seltdwait(td, &abt, 0); + error = seltdwait(td, &abt, &precision, 0); } else { - timo = 0; - error = seltdwait(td, NULL, timo); + error = seltdwait(td, NULL, NULL, 0); } if (error) break; @@ -1256,12 +1267,13 @@ sys_poll(td, uap) { struct pollfd *bits; struct pollfd smallbits[32]; - struct bintime abt, rbt; + struct bintime abt, halftick_bt, precision, rbt; struct timeval atv; - int error, timo; + int error; u_int nfds; size_t ni; + timevalclear(&atv); nfds = uap->nfds; if (nfds > maxfilesperproc && nfds > FD_SETSIZE) return (EINVAL); @@ -1281,9 +1293,19 @@ sys_poll(td, uap) error = EINVAL; goto done; } - binuptime(&rbt); timeval2bintime(&atv, &abt); + TIMESEL(&rbt, &bt_timethreshold); + precision = abt; bintime_add(&abt, &rbt); + bintime_divpow2(&precision, tc_timepercentage); + if (atv.tv_usec * 1000 > tc_timethreshold) { + bintime_add(&abt, &tick_bt); + halftick_bt = tick_bt; + bintime_divpow2(&halftick_bt, 1); + if (bintime_cmp(&precision, &halftick_bt, <)) + precision = halftick_bt; + } + bintime_add(&abt, &precision); } else { abt.sec = 0; abt.frac = 0; @@ -1295,13 +1317,12 @@ sys_poll(td, uap) if (error || td->td_retval[0] != 0) break; if (abt.sec || abt.frac) { - binuptime(&rbt); + TIMESEL(&rbt, &bt_timethreshold); if (bintime_cmp(&rbt, &abt, >=)) break; - error = seltdwait(td, &abt, 0); + error = seltdwait(td, &abt, &precision, 0); } else { - timo = 0; - error = seltdwait(td, NULL, timo); + error = seltdwait(td, NULL, NULL, 0); } if (error) break; @@ -1644,7 +1665,8 @@ out: } static int -seltdwait(struct thread *td, struct bintime *bt, int timo) +seltdwait(struct thread *td, struct bintime *bt, struct bintime *precision, + int timo) { struct seltd *stp; int error; @@ -1667,7 +1689,7 @@ static int error = cv_timedwait_sig(&stp->st_wait, &stp->st_mtx, timo); else if (bt != NULL) error = cv_timedwait_sig_bt(&stp->st_wait, &stp->st_mtx, - bt, 0); + bt, precision); else error = cv_wait_sig(&stp->st_wait, &stp->st_mtx); mtx_unlock(&stp->st_mtx); Index: sys/kern/kern_tc.c =================================================================== --- sys/kern/kern_tc.c (revision 243581) +++ sys/kern/kern_tc.c (working copy) @@ -119,9 +119,10 @@ static int timestepwarnings; SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW, ×tepwarnings, 0, "Log time steps"); +struct bintime bt_timethreshold; +struct bintime tick_bt; +int tc_timepercentage = TC_DEFAULTPERC; int tc_timethreshold; -int tc_timepercentage = TC_DEFAULTPERC; -struct bintime tick_bt; SYSCTL_INT(_kern, OID_AUTO, tc_timepercentage, CTLFLAG_RW, &tc_timepercentage, 0, "Precision percentage tolerance"); @@ -281,7 +282,7 @@ fbclock_getmicrouptime(struct timeval *tvp) do { th = timehands; gen = th->th_generation; - bintime2timeval(&th->th_offset, tvp); + Bintime2timeval(&th->th_offset, tvp); } while (gen == 0 || gen != th->th_generation); } @@ -1715,6 +1716,7 @@ static void inittimecounter(void *dummy) { u_int p; + struct timespec ts; int tick_rate; /* @@ -1730,7 +1732,10 @@ inittimecounter(void *dummy) else tc_tick = 1; tick_rate = hz / tc_tick; - tc_timethreshold = (100 / tc_timepercentage) * (1000000000 / tick_rate); + tc_timethreshold = (1000000000 / (tick_rate * tc_timepercentage)) * 100; + ts.tv_sec = tc_timethreshold / 1000000000; + ts.tv_nsec = tc_timethreshold % 1000000000; + timespec2bintime(&ts, &bt_timethreshold); FREQ2BT(tick_rate, &tick_bt); p = (tc_tick * 1000000) / hz; printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000); Index: sys/kern/kern_condvar.c =================================================================== --- sys/kern/kern_condvar.c (revision 243581) +++ sys/kern/kern_condvar.c (working copy) @@ -275,7 +275,7 @@ _cv_wait_sig(struct cv *cvp, struct lock_object *l */ int _cv_timedwait(struct cv *cvp, struct lock_object *lock, struct bintime *bt, - int timo, int flags) + struct bintime *precision, int timo, int flags) { WITNESS_SAVE_DECL(lock_witness); struct lock_class *class; @@ -314,7 +314,7 @@ _cv_timedwait(struct cv *cvp, struct lock_object * if (bt == NULL) sleepq_set_timeout_flags(cvp, timo, flags); else - sleepq_set_timeout_bt(cvp, bt, flags); + sleepq_set_timeout_bt(cvp, bt, precision); if (lock != &Giant.lock_object) { if (class->lc_flags & LC_SLEEPABLE) sleepq_release(cvp); @@ -346,7 +346,7 @@ _cv_timedwait(struct cv *cvp, struct lock_object * */ int _cv_timedwait_sig(struct cv *cvp, struct lock_object *lock, - struct bintime *bt, int timo, int flags) + struct bintime *bt, struct bintime *precision, int timo, int flags) { WITNESS_SAVE_DECL(lock_witness); struct lock_class *class; @@ -386,7 +386,7 @@ _cv_timedwait_sig(struct cv *cvp, struct lock_obje if (bt == NULL) sleepq_set_timeout_flags(cvp, timo, flags); else - sleepq_set_timeout_bt(cvp, bt, flags); + sleepq_set_timeout_bt(cvp, bt, precision); if (lock != &Giant.lock_object) { if (class->lc_flags & LC_SLEEPABLE) sleepq_release(cvp); Index: sys/kern/kern_timeout.c =================================================================== --- sys/kern/kern_timeout.c (revision 243581) +++ sys/kern/kern_timeout.c (working copy) @@ -565,11 +565,10 @@ callout_lock(struct callout *c) static void callout_cc_add(struct callout *c, struct callout_cpu *cc, - struct bintime to_bintime, void (*func)(void *), void *arg, int cpu, - int flags) + struct bintime to_bintime, struct bintime precision, void (*func)(void *), + void *arg, int cpu, int flags) { struct bintime bt; - uint64_t r_val; int bucket; CC_LOCK_ASSERT(cc); @@ -582,11 +581,10 @@ callout_cc_add(struct callout *c, struct callout_c c->c_flags &= ~CALLOUT_PROCESSED; c->c_func = func; c->c_time = to_bintime; - bintime_clear(&c->c_precision); - r_val = C_PABS2BT(flags); - c->c_precision.frac = r_val; - CTR3(KTR_CALLOUT, "precision set for %p: 0.%08x%08", - c, (u_int) (r_val >> 32), (u_int) (r_val & 0xffffffff)); + c->c_precision = precision; + CTR4(KTR_CALLOUT, "precision set for %p: %d.%08x%08x", + c, c->precision.sec, (u_int) (c->c_precision.frac >> 32), + (u_int) (c->c_precision.frac & 0xffffffff)); bucket = get_bucket(&c->c_time); TAILQ_INSERT_TAIL(&cc->cc_callwheel[bucket], c, c_links.tqe); /* @@ -779,8 +777,8 @@ skip: */ new_cc = callout_cpu_switch(c, cc, new_cpu); flags = (direct) ? C_DIRECT_EXEC : 0; - callout_cc_add(c, new_cc, new_time, new_func, new_arg, - new_cpu, flags); + callout_cc_add(c, new_cc, new_time, c->c_precision, new_func, + new_arg, new_cpu, flags); CC_UNLOCK(new_cc); CC_LOCK(cc); #else @@ -924,23 +922,32 @@ callout_handle_init(struct callout_handle *handle) * callout_pending() - returns truth if callout is still waiting for timeout * callout_deactivate() - marks the callout as having been serviced */ -int -_callout_reset_on(struct callout *c, struct bintime *bt, int to_ticks, - void (*ftn)(void *), void *arg, int cpu, int flags) +int +_callout_reset_on(struct callout *c, struct bintime *bt, + struct bintime *precision, int to_ticks, void (*ftn)(void *), + void *arg, int cpu, int flags) { - struct bintime now, to_bt; + struct bintime now, to_bt, pr; struct callout_cpu *cc; int bucket, cancelled, direct; cancelled = 0; if (bt == NULL) { FREQ2BT(hz, &to_bt); + pr = to_bt; getbinuptime(&now); if (to_ticks > 0) bintime_mul(&to_bt, to_ticks); bintime_add(&to_bt, &now); - } else + to_ticks >>= C_PRELGET(flags); + bintime_mul(&pr, to_ticks); + } else { to_bt = *bt; + if (precision != NULL) + pr = *precision; + else + bintime_clear(&pr); + } /* * Don't allow migration of pre-allocated callouts lest they * become unbalanced. @@ -1013,7 +1020,7 @@ callout_handle_init(struct callout_handle *handle) } #endif - callout_cc_add(c, cc, to_bt, ftn, arg, cpu, flags); + callout_cc_add(c, cc, to_bt, pr, ftn, arg, cpu, flags); CTR6(KTR_CALLOUT, "%sscheduled %p func %p arg %p in %d.%08x", cancelled ? "re" : "", c, c->c_func, c->c_arg, (int)(to_bt.sec), (u_int)(to_bt.frac >> 32)); Index: sys/kern/kern_synch.c =================================================================== --- sys/kern/kern_synch.c (revision 243581) +++ sys/kern/kern_synch.c (working copy) @@ -146,7 +146,8 @@ sleepinit(void) */ int _sleep(void *ident, struct lock_object *lock, int priority, - const char *wmesg, int timo, struct bintime *bt, int flags) + const char *wmesg, int timo, struct bintime *bt, + struct bintime *precision, int flags) { struct thread *td; struct proc *p; @@ -233,7 +234,7 @@ _sleep(void *ident, struct lock_object *lock, int */ sleepq_add(ident, lock, wmesg, sleepq_flags, 0); if (bt) - sleepq_set_timeout_bt(ident, bt, flags); + sleepq_set_timeout_bt(ident, bt, precision); else if (timo) sleepq_set_timeout_flags(ident, timo, flags); if (lock != NULL && class->lc_flags & LC_SLEEPABLE) { Index: sys/kern/kern_event.c =================================================================== --- sys/kern/kern_event.c (revision 243581) +++ sys/kern/kern_event.c (working copy) @@ -550,8 +550,8 @@ filt_timerexpire(void *knx) if ((kn->kn_flags & EV_ONESHOT) != EV_ONESHOT) { bt = timer2bintime(kn->kn_sdata); calloutp = (struct callout *)kn->kn_hook; - callout_reset_bt_on(calloutp, &bt, filt_timerexpire, kn, - PCPU_GET(cpuid), C_P1MS); + callout_reset_bt_on(calloutp, &bt, NULL, filt_timerexpire, kn, + PCPU_GET(cpuid), 0); } } @@ -577,8 +577,8 @@ filt_timerattach(struct knote *kn) callout_init(calloutp, CALLOUT_MPSAFE); kn->kn_hook = calloutp; bt = timer2bintime(kn->kn_sdata); - callout_reset_bt_on(calloutp, &bt, filt_timerexpire, kn, - PCPU_GET(cpuid), C_P1MS); + callout_reset_bt_on(calloutp, &bt, NULL, filt_timerexpire, kn, + PCPU_GET(cpuid), 0); return (0); } Index: sys/ofed/include/linux/timer.h =================================================================== --- sys/ofed/include/linux/timer.h (revision 243581) +++ sys/ofed/include/linux/timer.h (working copy) @@ -38,10 +38,9 @@ struct timer_list { struct callout timer_callout; void (*function)(unsigned long); unsigned long data; + int expires; }; -#define expires timer_callout.c_time - static inline void _timer_fn(void *context) { @@ -65,13 +64,16 @@ do { \ callout_init(&(timer)->timer_callout, CALLOUT_MPSAFE); \ } while (0) -#define mod_timer(timer, expire) \ - callout_reset(&(timer)->timer_callout, (expire) - jiffies, \ - _timer_fn, (timer)) +#define mod_timer(timer, exp) \ +do { \ + (timer)->expires = exp; \ + callout_reset(&(timer)->timer_callout, (exp) - jiffies, \ + _timer_fn, (timer)); \ +} while (0) #define add_timer(timer) \ callout_reset(&(timer)->timer_callout, \ - (timer)->timer_callout.c_time - jiffies, _timer_fn, (timer)) + (timer)->expires - jiffies, _timer_fn, (timer)) #define del_timer(timer) callout_stop(&(timer)->timer_callout) #define del_timer_sync(timer) callout_drain(&(timer)->timer_callout) Index: sys/dev/sound/pci/hda/hdaa.c =================================================================== --- sys/dev/sound/pci/hda/hdaa.c (revision 243581) +++ sys/dev/sound/pci/hda/hdaa.c (working copy) @@ -5553,7 +5553,7 @@ hdaa_dump_ctls(struct hdaa_pcm_devinfo *pdevinfo, struct hdaa_devinfo *devinfo = pdevinfo->devinfo; struct hdaa_audio_ctl *ctl; char buf[64]; - int i, j, printed; + int i, j, printed = 0; if (flag == 0) { flag = ~(SOUND_MASK_VOLUME | SOUND_MASK_PCM |