From 3db15a3f80f193826e144b1944727a65c13340fe Mon Sep 17 00:00:00 2001 From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Sat, 25 Jul 2015 18:23:10 +0200 Subject: kern: add boot-time clock, use it for time stamps 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. --- kern/mach_clock.c | 36 +++++++++++++++++++++++++++++++++++- kern/mach_clock.h | 11 ++++++++++- kern/task.c | 3 ++- kern/thread.c | 3 ++- 4 files changed, 49 insertions(+), 4 deletions(-) (limited to 'kern') 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, -- cgit v1.2.3