diff options
-rw-r--r-- | sys/kern/kern_clock.c | 5 | ||||
-rw-r--r-- | sys/kern/kern_tc.c | 56 | ||||
-rw-r--r-- | sys/kern/kern_time.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_timeout.c | 48 | ||||
-rw-r--r-- | sys/sys/timeout.h | 3 | ||||
-rw-r--r-- | sys/sys/timetc.h | 3 |
6 files changed, 105 insertions, 14 deletions
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index ab567332f37..c35ff9e95a0 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_clock.c,v 1.73 2012/03/23 15:51:26 guenther Exp $ */ +/* $OpenBSD: kern_clock.c,v 1.74 2012/05/24 07:17:42 guenther Exp $ */ /* $NetBSD: kern_clock.c,v 1.34 1996/06/09 04:51:03 briggs Exp $ */ /*- @@ -129,9 +129,6 @@ void initclocks(void) { int i; -#ifdef __HAVE_TIMECOUNTER - extern void inittimecounter(void); -#endif softclock_si = softintr_establish(IPL_SOFTCLOCK, softclock, NULL); if (softclock_si == NULL) diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c index 427cdb88b66..b6c7875e546 100644 --- a/sys/kern/kern_tc.c +++ b/sys/kern/kern_tc.c @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $OpenBSD: kern_tc.c,v 1.16 2010/09/24 07:29:30 deraadt Exp $ + * $OpenBSD: kern_tc.c,v 1.17 2012/05/24 07:17:42 guenther Exp $ * $FreeBSD: src/sys/kern/kern_tc.c,v 1.148 2003/03/18 08:45:23 phk Exp $ */ @@ -258,7 +258,7 @@ tc_init(struct timecounter *tc) /* * Never automatically use a timecounter with negative quality. * Even though we run on the dummy counter, switching here may be - * worse since this timecounter may not be monotonous. + * worse since this timecounter may not be monotonic. */ if (tc->tc_quality < 0) return; @@ -282,12 +282,12 @@ tc_getfrequency(void) } /* - * Step our concept of UTC. This is done by modifying our estimate of - * when we booted. + * Step our concept of UTC, aka the realtime clock. + * This is done by modifying our estimate of when we booted. * XXX: not locked. */ void -tc_setclock(struct timespec *ts) +tc_setrealtimeclock(struct timespec *ts) { struct timespec ts2; struct bintime bt, bt2; @@ -311,6 +311,52 @@ tc_setclock(struct timespec *ts) } /* + * Step the monotonic and realtime clocks, triggering any timeouts that + * should have occurred across the interval. + * XXX: not locked. + */ +void +tc_setclock(struct timespec *ts) +{ + struct bintime bt, bt2; +#ifndef SMALL_KERNEL + long long adj_ticks; +#endif + + /* + * When we're called for the first time, during boot when + * the root partition is mounted, boottime is still zero: + * we just need to set it. + */ + if (boottimebin.sec == 0) { + tc_setrealtimeclock(ts); + return; + } + + add_timer_randomness(ts->tv_sec); + + timespec2bintime(ts, &bt); + bintime_sub(&bt, &boottimebin); + bt2 = timehands->th_offset; + timehands->th_offset = bt; + +#ifndef SMALL_KERNEL + /* convert the bintime to ticks */ + bintime_sub(&bt, &bt2); + adj_ticks = (long long)hz * bt.sec + + (((uint64_t)1000000 * (uint32_t)(bt.frac >> 32)) >> 32) / tick; + if (adj_ticks > 0) { + if (adj_ticks > INT_MAX) + adj_ticks = INT_MAX; + timeout_adjust_ticks(adj_ticks); + } +#endif + + /* XXX fiddle all the little crinkly bits around the fiords... */ + tc_windup(); +} + +/* * Initialize the next struct timehands in the ring and make * it the active timehands. Along the way we might switch to a different * timecounter and/or do seconds processing in NTP. Slightly magic. diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 3ed6a7d53eb..2e83b07ffb1 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_time.c,v 1.74 2012/03/23 15:51:26 guenther Exp $ */ +/* $OpenBSD: kern_time.c,v 1.75 2012/05/24 07:17:42 guenther Exp $ */ /* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */ /* @@ -115,7 +115,7 @@ settime(struct timespec *ts) return (EPERM); } - tc_setclock(ts); + tc_setrealtimeclock(ts); resettodr(); return (0); diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index 3237f60b600..1fdf1fe110f 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_timeout.c,v 1.33 2011/05/10 00:58:42 dlg Exp $ */ +/* $OpenBSD: kern_timeout.c,v 1.34 2012/05/24 07:17:42 guenther Exp $ */ /* * Copyright (c) 2001 Thomas Nordin <nordin@openbsd.org> * Copyright (c) 2000-2001 Artur Grabowski <art@openbsd.org> @@ -344,6 +344,52 @@ softclock(void *arg) mtx_leave(&timeout_mutex); } +#ifndef SMALL_KERNEL +void +timeout_adjust_ticks(int adj) +{ + struct timeout *to; + struct circq *p; +#ifdef DDB + char *name; + db_expr_t offset; +#endif + int new_ticks, b, old; + + /* adjusting the monotonic clock backwards would be a Bad Thing */ + if (adj <= 0) + return; + + mtx_enter(&timeout_mutex); + new_ticks = ticks + adj; + for (b = 0; b < nitems(timeout_wheel); b++) { + p = CIRCQ_FIRST(&timeout_wheel[b]); + while (p != &timeout_wheel[b]) { + to = (struct timeout *)p; /* XXX */ + p = CIRCQ_FIRST(p); + + old = to->to_time; + + /* when moving a timeout forward need to reinsert it */ + if (to->to_time - ticks < adj) + to->to_time = new_ticks; + CIRCQ_REMOVE(&to->to_list); + CIRCQ_INSERT(&to->to_list, &timeout_todo); + +#ifdef DDB + db_find_sym_and_offset((db_addr_t)to->to_func, &name, + &offset); + name = name ? name : "?"; + printf("adjusted timeout %6d -> %6d for %s\n", + old - ticks, to->to_time - new_ticks, name); +#endif + } + } + ticks = new_ticks; + mtx_leave(&timeout_mutex); +} +#endif + #ifdef DDB void db_show_callout_bucket(struct circq *); diff --git a/sys/sys/timeout.h b/sys/sys/timeout.h index 98b984ffae3..6d1cdf01c9a 100644 --- a/sys/sys/timeout.h +++ b/sys/sys/timeout.h @@ -1,4 +1,4 @@ -/* $OpenBSD: timeout.h,v 1.21 2011/05/10 00:58:42 dlg Exp $ */ +/* $OpenBSD: timeout.h,v 1.22 2012/05/24 07:17:42 guenther Exp $ */ /* * Copyright (c) 2000-2001 Artur Grabowski <art@openbsd.org> * All rights reserved. @@ -94,6 +94,7 @@ void timeout_add_nsec(struct timeout *, int); int timeout_del(struct timeout *); void timeout_startup(void); +void timeout_adjust_ticks(int); /* * called once every hardclock. returns non-zero if we need to schedule a diff --git a/sys/sys/timetc.h b/sys/sys/timetc.h index 54daeeea88a..42125365458 100644 --- a/sys/sys/timetc.h +++ b/sys/sys/timetc.h @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * - * $OpenBSD: timetc.h,v 1.2 2006/10/30 20:19:33 otto Exp $ + * $OpenBSD: timetc.h,v 1.3 2012/05/24 07:17:42 guenther Exp $ * $FreeBSD: src/sys/sys/timetc.h,v 1.57 2003/04/10 23:07:24 des Exp $ */ @@ -71,6 +71,7 @@ extern struct timecounter *timecounter; u_int64_t tc_getfrequency(void); void tc_init(struct timecounter *tc); void tc_setclock(struct timespec *ts); +void tc_setrealtimeclock(struct timespec *ts); void tc_ticktock(void); void inittimecounter(void); int sysctl_tc(int *, u_int, void *, size_t *, void *, size_t); |