Changed kern/timer.c to use the higher precision time_value64_t. Of course, this won't suffer from the 2038 overflow but it does provide nanosecond precision (if gnumach ever uses a better timer) and moves us closer to only having time_value64_t. --- include/mach/time_value.h | 5 +++ kern/mach_clock.c | 7 ++-- kern/mach_clock.h | 2 +- kern/task.c | 42 ++++++++++---------- kern/task.h | 4 +- kern/thread.c | 19 +++++---- kern/timer.c | 82 ++++++++++++++++----------------------- kern/timer.h | 24 +++--------- 8 files changed, 81 insertions(+), 104 deletions(-)
diff --git a/include/mach/time_value.h b/include/mach/time_value.h index 0643b740..ea661ec3 100644 --- a/include/mach/time_value.h +++ b/include/mach/time_value.h @@ -140,6 +140,11 @@ static __inline__ time_value_t convert_time_value_from_user(rpc_time_value_t tv) time_value64_sub_nanos(result, (subtrahend)->nanoseconds); \ } +#define time_value64_init(tv) { \ + (tv)->seconds = 0; \ + (tv)->nanoseconds = 0; \ + } + #define TIME_VALUE64_TO_TIME_VALUE(tv64, tv) do { \ (tv)->seconds = (tv64)->seconds; \ (tv)->microseconds = (tv64)->nanoseconds / 1000; \ diff --git a/kern/mach_clock.c b/kern/mach_clock.c index e33404a2..65c38086 100644 --- a/kern/mach_clock.c +++ b/kern/mach_clock.c @@ -428,11 +428,10 @@ record_time_stamp(time_value64_t *stamp) * real-time clock frame. */ void -read_time_stamp (const time_value64_t *stamp, rpc_time_value_t *result) +read_time_stamp (const time_value64_t *stamp, time_value64_t *result) { - time_value64_t result64 = *stamp; - time_value64_sub(&result64, &clock_boottime_offset); - TIME_VALUE64_TO_TIME_VALUE(&result64, result); + *result = *stamp; + time_value64_sub(result, &clock_boottime_offset); } diff --git a/kern/mach_clock.h b/kern/mach_clock.h index 60b49b8a..66903b8a 100644 --- a/kern/mach_clock.h +++ b/kern/mach_clock.h @@ -98,7 +98,7 @@ extern void record_time_stamp (time_value64_t *stamp); * Read a timestamp in STAMP into RESULT. Returns values in the * real-time clock frame. */ -extern void read_time_stamp (const time_value64_t *stamp, rpc_time_value_t *result); +extern void read_time_stamp (const time_value64_t *stamp, time_value64_t *result); extern void mapable_time_init (void); diff --git a/kern/task.c b/kern/task.c index be385a1b..65191f5d 100644 --- a/kern/task.c +++ b/kern/task.c @@ -154,10 +154,8 @@ task_create_kernel( ipc_task_init(new_task, parent_task); machine_task_init (new_task); - new_task->total_user_time.seconds = 0; - new_task->total_user_time.microseconds = 0; - new_task->total_system_time.seconds = 0; - new_task->total_system_time.microseconds = 0; + time_value64_init(&new_task->total_user_time); + time_value64_init(&new_task->total_system_time); record_time_stamp (&new_task->creation_time); @@ -808,16 +806,13 @@ kern_return_t task_info( task_lock(task); basic_info->base_priority = task->priority; basic_info->suspend_count = task->user_stop_count; - basic_info->user_time.seconds - = task->total_user_time.seconds; - basic_info->user_time.microseconds - = task->total_user_time.microseconds; - basic_info->system_time.seconds - = task->total_system_time.seconds; - basic_info->system_time.microseconds - = task->total_system_time.microseconds; - read_time_stamp(&task->creation_time, - &basic_info->creation_time); + TIME_VALUE64_TO_TIME_VALUE(&task->total_user_time, + &basic_info->user_time); + TIME_VALUE64_TO_TIME_VALUE(&task->total_system_time, + &basic_info->system_time); + time_value64_t creation_time64; + read_time_stamp(&task->creation_time, &creation_time64); + TIME_VALUE64_TO_TIME_VALUE(&creation_time64, &basic_info->creation_time); task_unlock(task); if (*task_info_count > TASK_BASIC_INFO_COUNT) @@ -854,21 +849,22 @@ kern_return_t task_info( task_thread_times_info_t times_info; thread_t thread; - if (*task_info_count < TASK_THREAD_TIMES_INFO_COUNT) { + /* Callers might not known about time_value64_t fields yet. */ + if (*task_info_count < TASK_THREAD_TIMES_INFO_COUNT - (2 * sizeof(time_value64_t)) / sizeof(integer_t)) { return KERN_INVALID_ARGUMENT; } times_info = (task_thread_times_info_t) task_info_out; - times_info->user_time.seconds = 0; - times_info->user_time.microseconds = 0; - times_info->system_time.seconds = 0; - times_info->system_time.microseconds = 0; + + time_value64_t acc_user_time, acc_system_time; + time_value64_init(&acc_user_time); + time_value64_init(&acc_system_time); task_lock(task); queue_iterate(&task->thread_list, thread, thread_t, thread_list) { - time_value_t user_time, system_time; + time_value64_t user_time, system_time; spl_t s; s = splsched(); @@ -879,10 +875,12 @@ kern_return_t task_info( thread_unlock(thread); splx(s); - time_value_add(×_info->user_time, &user_time); - time_value_add(×_info->system_time, &system_time); + time_value64_add(&acc_user_time, &user_time); + time_value64_add(&acc_system_time, &system_time); } task_unlock(task); + TIME_VALUE64_TO_TIME_VALUE(&acc_user_time, ×_info->user_time); + TIME_VALUE64_TO_TIME_VALUE(&acc_system_time, ×_info->system_time); *task_info_count = TASK_THREAD_TIMES_INFO_COUNT; break; diff --git a/kern/task.h b/kern/task.h index 38aa9feb..dec3a530 100644 --- a/kern/task.h +++ b/kern/task.h @@ -82,9 +82,9 @@ struct task { int priority; /* for new threads */ /* Statistics */ - time_value_t total_user_time; + time_value64_t total_user_time; /* total user time for dead threads */ - time_value_t total_system_time; + time_value64_t total_system_time; /* total system time for dead threads */ time_value64_t creation_time; /* time stamp at creation */ diff --git a/kern/thread.c b/kern/thread.c index 4a6b9eda..392d38f8 100644 --- a/kern/thread.c +++ b/kern/thread.c @@ -592,7 +592,7 @@ void thread_deallocate( task_t task; processor_set_t pset; - time_value_t user_time, system_time; + time_value64_t user_time, system_time; if (thread == THREAD_NULL) return; @@ -669,8 +669,8 @@ void thread_deallocate( * Accumulate times for dead threads in task. */ thread_read_times(thread, &user_time, &system_time); - time_value_add(&task->total_user_time, &user_time); - time_value_add(&task->total_system_time, &system_time); + time_value64_add(&task->total_user_time, &user_time); + time_value64_add(&task->total_system_time, &system_time); /* * Remove thread from task list and processor_set threads list. @@ -1522,13 +1522,16 @@ kern_return_t thread_info( /* fill in info */ - thread_read_times_rpc(thread, - &basic_info->user_time, - &basic_info->system_time); + time_value64_t user_time, system_time; + thread_read_times(thread, &user_time, &system_time); + TIME_VALUE64_TO_TIME_VALUE(&user_time, &basic_info->user_time); + TIME_VALUE64_TO_TIME_VALUE(&system_time, &basic_info->system_time); + basic_info->base_priority = thread->priority; basic_info->cur_priority = thread->sched_pri; - read_time_stamp(&thread->creation_time, - &basic_info->creation_time); + time_value64_t creation_time; + read_time_stamp(&thread->creation_time, &creation_time); + TIME_VALUE64_TO_TIME_VALUE(&creation_time, &basic_info->creation_time); /* * To calculate cpu_usage, first correct for timer rate, diff --git a/kern/timer.c b/kern/timer.c index 3b81ab79..7d029b7c 100644 --- a/kern/timer.c +++ b/kern/timer.c @@ -378,8 +378,13 @@ static void timer_grab( } while ( (save)->high != (timer)->high_bits_check); } +#define TIMER_TO_TIME_VALUE64(tv, timer) do { \ + (tv)->seconds = (timer)->high + (timer)->low / 1000000; \ + (tv)->nanoseconds = (timer)->low % 1000000 * 1000; \ +} while(0); + /* - * timer_read reads the value of a timer into a time_value_t. If the + * timer_read reads the value of a timer into a time_value64_t. If the * timer was modified during the read, retry. The value returned * is accurate to the last update; time accumulated by a running * timer since its last timestamp is not included. @@ -388,7 +393,7 @@ static void timer_grab( void timer_read( timer_t timer, - time_value_t *tv) + time_value64_t *tv) { timer_save_data_t temp; @@ -399,9 +404,7 @@ timer_read( #ifdef TIMER_ADJUST TIMER_ADJUST(&temp); #endif /* TIMER_ADJUST */ - tv->seconds = temp.high + temp.low/1000000; - tv->microseconds = temp.low%1000000; - + TIMER_TO_TIME_VALUE64(tv, &temp); } /* @@ -414,29 +417,11 @@ timer_read( */ void thread_read_times( thread_t thread, - time_value_t *user_time_p, - time_value_t *system_time_p) + time_value64_t *user_time_p, + time_value64_t *system_time_p) { - timer_save_data_t temp; - timer_t timer; - - timer = &thread->user_timer; - timer_grab(timer, &temp); - -#ifdef TIMER_ADJUST - TIMER_ADJUST(&temp); -#endif /* TIMER_ADJUST */ - user_time_p->seconds = temp.high + temp.low/1000000; - user_time_p->microseconds = temp.low % 1000000; - - timer = &thread->system_timer; - timer_grab(timer, &temp); - -#ifdef TIMER_ADJUST - TIMER_ADJUST(&temp); -#endif /* TIMER_ADJUST */ - system_time_p->seconds = temp.high + temp.low/1000000; - system_time_p->microseconds = temp.low % 1000000; + timer_read(&thread->user_timer, user_time_p); + timer_read(&thread->system_timer, system_time_p); } #if MACH_DEBUG @@ -458,6 +443,23 @@ static void db_timer_grab( (save)->low = (timer)->low_bits; } +static void +nonblocking_timer_read( + timer_t timer, + time_value64_t *tv) +{ + timer_save_data_t temp; + + db_timer_grab(timer, &temp); + /* + * Normalize the result + */ +#ifdef TIMER_ADJUST + TIMER_ADJUST(&temp); +#endif /* TIMER_ADJUST */ + TIMER_TO_TIME_VALUE64(tv, &temp); +} + /* * Db_thread_read_times: A version of thread_read_times that * can be called by the debugger. This version does not call @@ -467,29 +469,11 @@ static void db_timer_grab( */ void db_thread_read_times( thread_t thread, - time_value_t *user_time_p, - time_value_t *system_time_p) + time_value64_t *user_time_p, + time_value64_t *system_time_p) { - timer_save_data_t temp; - timer_t timer; - - timer = &thread->user_timer; - db_timer_grab(timer, &temp); - -#ifdef TIMER_ADJUST - TIMER_ADJUST(&temp); -#endif /* TIMER_ADJUST */ - user_time_p->seconds = temp.high + temp.low/1000000; - user_time_p->microseconds = temp.low % 1000000; - - timer = &thread->system_timer; - timer_grab(timer, &temp); - -#ifdef TIMER_ADJUST - TIMER_ADJUST(&temp); -#endif /* TIMER_ADJUST */ - system_time_p->seconds = temp.high + temp.low/1000000; - system_time_p->microseconds = temp.low % 1000000; + nonblocking_timer_read(&thread->user_timer, user_time_p); + nonblocking_timer_read(&thread->system_timer, system_time_p); } #endif /* MACH_DEBUG */ diff --git a/kern/timer.h b/kern/timer.h index 89790230..92259a2b 100644 --- a/kern/timer.h +++ b/kern/timer.h @@ -32,7 +32,7 @@ #if STAT_TIME /* * Statistical timer definitions - use microseconds in timer, seconds - * in high unit field. No adjustment needed to convert to time_value_t + * in high unit field. No adjustment needed to convert to time_value64_t * as a result. Service timers once an hour. */ @@ -56,7 +56,7 @@ /* * TIMER_ADJUST is used to adjust the value of a timer after it has been - * copied into a time_value_t. No adjustment is needed if high_bits is in + * copied into a time_value64_t. No adjustment is needed if high_bits is in * seconds. */ #undef TIMER_ADJUST @@ -128,24 +128,12 @@ extern void start_timer(timer_t); extern void timer_switch(timer_t); #endif /* STAT_TIME */ -extern void timer_read(timer_t, time_value_t *); -extern void thread_read_times(thread_t, time_value_t *, time_value_t *); +extern void timer_read(timer_t, time_value64_t *); +extern void thread_read_times(thread_t, time_value64_t *, time_value64_t *); extern unsigned timer_delta(timer_t, timer_save_t); extern void timer_normalize(timer_t); extern void timer_init(timer_t); -static inline void -thread_read_times_rpc(thread_t thread, - rpc_time_value_t *user_time_p, rpc_time_value_t *system_time_p) -{ - time_value_t user_p, system_p; - thread_read_times(thread, &user_p, &system_p); - user_time_p->seconds = user_p.seconds; - user_time_p->microseconds = user_p.microseconds; - system_time_p->seconds = system_p.seconds; - system_time_p->microseconds = system_p.microseconds; -} - #if STAT_TIME /* * Macro to bump timer values. @@ -199,8 +187,8 @@ void timer_init(timer_t this_timer); #if MACH_DEBUG void db_thread_read_times( thread_t thread, - time_value_t *user_time_p, - time_value_t *system_time_p); + time_value64_t *user_time_p, + time_value64_t *system_time_p); #endif -- 2.39.2