summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2015-07-25 18:23:10 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2015-07-25 20:12:14 +0200
commit3db15a3f80f193826e144b1944727a65c13340fe (patch)
treef6eef1e163de6a5dccdc1067300c5fce333d722b
parentbb23879791cf015f17cb50b6443bac44b1cfbc72 (diff)
kern: add boot-time clock, use it for time stampsHEADmaster
The kernel keeps track of task and thread creation times by saving a time stamp. Previously, the real-time clock was used for this. When the real-time clock is changed, however, the reference frame for the time stamps is lost. This surfaced in Hurd systems reporting spuriously long uptimes. Fix this by creating a boot-time clock and use it as reference frame for the time stamps. * kern/mach_clock.c (clock_boottime_offset): Create clock by keeping track of the offset from the real-time. (clock_boottime_update): New function. (record_time_stamp): Use the boot-time clock for time stamps. (read_time_stamp): New function to convert it back to real-time. (host_set_time): Call `clock_boottime_update'. * kern/mach_clock.h (record_time_stamp): Amend comment. (read_time_stamp): New declaration. * kern/task.c (task_info): Use `read_time_stamp'. * kern/thread.c (thread_info): Likewise.
-rw-r--r--kern/mach_clock.c36
-rw-r--r--kern/mach_clock.h11
-rw-r--r--kern/task.c3
-rw-r--r--kern/thread.c3
4 files changed, 49 insertions, 4 deletions
diff --git a/kern/mach_clock.c b/kern/mach_clock.c
index b627b89..655adf4 100644
--- a/kern/mach_clock.c
+++ b/kern/mach_clock.c
@@ -367,9 +367,30 @@ void init_timeout(void)
elapsed_ticks = 0;
}
+
+/*
+ * We record timestamps using the boot-time clock. We keep track of
+ * the boot-time clock by storing the difference to the real-time
+ * clock.
+ */
+struct time_value clock_boottime_offset;
+
+/*
+ * Update the offset of the boot-time clock from the real-time clock.
+ * This function must be called when the real-time clock is updated.
+ * This function must be called at SPLHIGH.
+ */
+void
+clock_boottime_update(struct time_value *new_time)
+{
+ struct time_value delta = time;
+ time_value_sub(&delta, new_time);
+ time_value_add(&clock_boottime_offset, &delta);
+}
/*
- * Record a timestamp in STAMP.
+ * Record a timestamp in STAMP. Records values in the boot-time clock
+ * frame.
*/
void
record_time_stamp (time_value_t *stamp)
@@ -378,6 +399,18 @@ record_time_stamp (time_value_t *stamp)
stamp->seconds = mtime->seconds;
stamp->microseconds = mtime->microseconds;
} while (stamp->seconds != mtime->check_seconds);
+ time_value_add(stamp, &clock_boottime_offset);
+}
+
+/*
+ * Read a timestamp in STAMP into RESULT. Returns values in the
+ * real-time clock frame.
+ */
+void
+read_time_stamp (time_value_t *stamp, time_value_t *result)
+{
+ *result = *stamp;
+ time_value_sub(result, &clock_boottime_offset);
}
@@ -423,6 +456,7 @@ host_set_time(host, new_time)
#endif /* NCPUS > 1 */
s = splhigh();
+ clock_boottime_update(&new_time);
time = new_time;
update_mapped_time(&time);
resettodr();
diff --git a/kern/mach_clock.h b/kern/mach_clock.h
index 89fd335..1af0cda 100644
--- a/kern/mach_clock.h
+++ b/kern/mach_clock.h
@@ -86,9 +86,18 @@ extern boolean_t reset_timeout(timer_elt_t telt);
extern void init_timeout (void);
-/* Read the current time into STAMP. */
+/*
+ * Record a timestamp in STAMP. Records values in the boot-time clock
+ * frame.
+ */
extern void record_time_stamp (time_value_t *stamp);
+/*
+ * Read a timestamp in STAMP into RESULT. Returns values in the
+ * real-time clock frame.
+ */
+extern void read_time_stamp (time_value_t *stamp, time_value_t *result);
+
extern kern_return_t host_get_time(
host_t host,
time_value_t *current_time);
diff --git a/kern/task.c b/kern/task.c
index b384347..9a3d848 100644
--- a/kern/task.c
+++ b/kern/task.c
@@ -783,7 +783,8 @@ kern_return_t task_info(
= task->total_system_time.seconds;
basic_info->system_time.microseconds
= task->total_system_time.microseconds;
- basic_info->creation_time = task->creation_time;
+ read_time_stamp(&task->creation_time,
+ &basic_info->creation_time);
task_unlock(task);
if (*task_info_count > TASK_BASIC_INFO_COUNT)
diff --git a/kern/thread.c b/kern/thread.c
index 1f47553..865a1cc 100644
--- a/kern/thread.c
+++ b/kern/thread.c
@@ -1503,7 +1503,8 @@ kern_return_t thread_info(
&basic_info->system_time);
basic_info->base_priority = thread->priority;
basic_info->cur_priority = thread->sched_pri;
- basic_info->creation_time = thread->creation_time;
+ read_time_stamp(&thread->creation_time,
+ &basic_info->creation_time);
/*
* To calculate cpu_usage, first correct for timer rate,