Index: sys/sys/callout.h =================================================================== --- sys/sys/callout.h (revision 237576) +++ sys/sys/callout.h (working copy) @@ -51,9 +51,28 @@ #define CALLOUT_DIRECT 0x1000 /* allow exec from hw int context */ #define C_DIRECT_EXEC 0x0001 /* direct execution of callout */ -#define C_10US 0x0002 /* precision field */ -#define C_100US 0x0004 /* precision field */ -#define C_1MS 0x0008 /* precision field */ +#define C_P1S 0x0002 /* fields related to precision */ +#define C_P500MS 0x0006 +#define C_P250MS 0x000a +#define C_P125MS 0x000e +#define C_P64MS 0x0012 +#define C_P32MS 0x0016 +#define C_P16MS 0x001a +#define C_P8MS 0x001e +#define C_P4MS 0x0022 +#define C_P2MS 0x0026 +#define C_P1MS 0x002a +#define C_P500US 0x002e +#define C_P250US 0x0032 +#define C_P125US 0x0036 +#define C_P64US 0x003a +#define C_P32US 0x003e +#define C_P16US 0x0042 +#define C_P8US 0x0046 +#define C_P4US 0x004a +#define C_P2US 0x004e +#define PRECISION_BITS 7 +#define PRECISION_RANGE ((1 << PRECISION_BITS) - 1) struct callout_handle { struct callout *callout; Index: sys/kern/kern_timeout.c =================================================================== --- sys/kern/kern_timeout.c (revision 237576) +++ sys/kern/kern_timeout.c (working copy) @@ -497,8 +497,7 @@ struct bintime to_bintime, void (*func)(void *), void *arg, int cpu, int flags) { - struct timeval tv; - int bucket; + int bucket, r_shift; CC_LOCK_ASSERT(cc); if (bintime_cmp(&to_bintime, &cc->cc_lastscan, <)) { @@ -510,24 +509,24 @@ c->c_flags |= CALLOUT_DIRECT; c->c_flags &= ~CALLOUT_PROCESSED; c->c_func = func; - c->c_time = to_bintime; - tv.tv_sec = 0; - if (flags & C_10US) { - tv.tv_usec = 10; - timeval2bintime(&tv, &c->c_precision); - } - else if (flags & C_100US) { - tv.tv_usec = 100; - timeval2bintime(&tv, &c->c_precision); + c->c_time = to_bintime; + bintime_clear(&c->c_precision); + if (flags & 0x2) { + r_shift = ((flags >> 2) & PRECISION_RANGE) - 1; + /* + * Round as far as precision specified is coarse (up to 8ms). + * In order to play safe, round to to half of the interval and + * set half precision. + */ + if (r_shift < 6) { + r_shift += 1; + c->c_time.sec |= (((uint64_t)1 << (64 - r_shift)) - 1); + c->c_time.frac += 1; + if (c->c_time.frac == 0) + c->c_time.sec += 1; + } + c->c_precision.frac = (uint64_t)1 << (64 - r_shift); } - else if (flags & C_1MS) { - tv.tv_usec = 1000; - timeval2bintime(&tv, &c->c_precision); - } - else { - c->c_precision.sec = 0; - c->c_precision.frac = 0; - } bucket = get_bucket(&c->c_time); TAILQ_INSERT_TAIL(&cc->cc_callwheel[bucket & callwheelmask], c, c_links.tqe);