summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_clock.c5
-rw-r--r--sys/kern/kern_tc.c56
-rw-r--r--sys/kern/kern_time.c4
-rw-r--r--sys/kern/kern_timeout.c48
-rw-r--r--sys/sys/timeout.h3
-rw-r--r--sys/sys/timetc.h3
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);