From a8fbf3737be9a6f5fd1d87765072292d54e54aac Mon Sep 17 00:00:00 2001 From: Flavio Cruz Date: Sat, 28 Jan 2023 02:04:34 -0500 Subject: Add host_set_time64 and host_adjust_time64 Same existing logic, just with 64 bits. Old RPCs are implemented by calling into the new RPCs. Message-Id: --- doc/mach.texi | 4 +-- include/mach/mach_host.defs | 18 ++++++++++++ kern/mach_clock.c | 67 +++++++++++++++++++++++++++++++++------------ 3 files changed, 69 insertions(+), 20 deletions(-) diff --git a/doc/mach.texi b/doc/mach.texi index 53026d0b..3fdba3fc 100644 --- a/doc/mach.texi +++ b/doc/mach.texi @@ -5649,11 +5649,11 @@ Get the current time as seen by @var{host}. On success, the time passed since the epoch is returned in @var{current_time}. @end deftypefun -@deftypefun kern_return_t host_set_time (@w{host_priv_t @var{host_priv}}, @w{time_value_t @var{new_time}}) +@deftypefun kern_return_t host_set_time64 (@w{host_priv_t @var{host_priv}}, @w{time_value64_t @var{new_time}}) Set the time of @var{host_priv} to @var{new_time}. @end deftypefun -@deftypefun kern_return_t host_adjust_time (@w{host_priv_t @var{host_priv}}, @w{time_value_t @var{new_adjustment}}, @w{time_value_t *@var{old_adjustment}}) +@deftypefun kern_return_t host_adjust_time64 (@w{host_priv_t @var{host_priv}}, @w{time_value64_t @var{new_adjustment}}, @w{time_value64_t *@var{old_adjustment}}) Arrange for the current time as seen by @var{host_priv} to be gradually changed by the adjustment value @var{new_adjustment}, and return the old adjustment value in @var{old_adjustment}. diff --git a/include/mach/mach_host.defs b/include/mach/mach_host.defs index 0674c859..223f4576 100644 --- a/include/mach/mach_host.defs +++ b/include/mach/mach_host.defs @@ -360,3 +360,21 @@ routine host_get_boot_info( routine host_get_time64( host : host_t; out current_time : time_value64_t); + +/* + * Set the time on this host. + * Only available to privileged users. + */ +routine host_set_time64( + host : host_t; + new_time : time_value64_t); + +/* + * Arrange for the time on this host to be gradually changed + * by an adjustment value, and return the old value. + * Only available to privileged users. + */ +routine host_adjust_time64( + host_priv : host_priv_t; + in new_adjustment : time_value64_t; + out old_adjustment : time_value64_t); diff --git a/kern/mach_clock.c b/kern/mach_clock.c index 4b983fdd..0e3a2cf2 100644 --- a/kern/mach_clock.c +++ b/kern/mach_clock.c @@ -64,8 +64,10 @@ #include #endif +#define MICROSECONDS_IN_ONE_SECOND 1000000 + int hz = HZ; /* number of ticks per second */ -int tick = (1000000 / HZ); /* number of usec per tick */ +int tick = (MICROSECONDS_IN_ONE_SECOND / HZ); /* number of usec per tick */ time_value64_t time = { 0, 0 }; /* time since bootup (uncorrected) */ unsigned long elapsed_ticks = 0; /* ticks elapsed since bootup */ @@ -469,6 +471,14 @@ host_get_time64(const host_t host, time_value64_t *current_time) */ kern_return_t host_set_time(const host_t host, time_value_t new_time) +{ + time_value64_t new_time64; + TIME_VALUE_TO_TIME_VALUE64(&new_time, &new_time64); + return host_set_time64(host, new_time64); +} + +kern_return_t +host_set_time64(const host_t host, time_value64_t new_time) { spl_t s; @@ -481,14 +491,12 @@ host_set_time(const host_t host, time_value_t new_time) */ thread_bind(current_thread(), master_processor); if (current_processor() != master_processor) - thread_block((void (*)) 0); + thread_block(thread_no_continuation); #endif /* NCPUS > 1 */ s = splhigh(); - time_value64_t new_time64; - TIME_VALUE_TO_TIME_VALUE64(&new_time, &new_time64); - clock_boottime_update(&new_time64); - time = new_time64; + clock_boottime_update(&new_time); + time = new_time; update_mapped_time(&time); resettodr(); splx(s); @@ -500,7 +508,7 @@ host_set_time(const host_t host, time_value_t new_time) thread_bind(current_thread(), PROCESSOR_NULL); #endif /* NCPUS > 1 */ - return (KERN_SUCCESS); + return(KERN_SUCCESS); } /* @@ -512,37 +520,60 @@ host_adjust_time( time_value_t new_adjustment, time_value_t *old_adjustment /* OUT */) { - time_value_t oadj; - unsigned int ndelta; + time_value64_t old_adjustment64; + time_value64_t new_adjustment64; + kern_return_t ret; + + TIME_VALUE_TO_TIME_VALUE64(&new_adjustment, &new_adjustment64); + ret = host_adjust_time64(host, new_adjustment64, &old_adjustment64); + if (ret == KERN_SUCCESS) { + TIME_VALUE64_TO_TIME_VALUE(&old_adjustment64, old_adjustment); + } + return ret; +} + +/* + * Adjust the time gradually. + */ +kern_return_t +host_adjust_time64( + const host_t host, + time_value64_t new_adjustment, + time_value64_t *old_adjustment /* OUT */) +{ + time_value64_t oadj; + uint64_t ndelta_microseconds; spl_t s; if (host == HOST_NULL) return (KERN_INVALID_HOST); - ndelta = new_adjustment.seconds * 1000000 - + new_adjustment.microseconds; + /* Note we only adjust up to microsecond precision */ + ndelta_microseconds = new_adjustment.seconds * MICROSECONDS_IN_ONE_SECOND + + new_adjustment.nanoseconds / 1000; #if NCPUS > 1 thread_bind(current_thread(), master_processor); if (current_processor() != master_processor) - thread_block((void (*)) 0); + thread_block(thread_no_continuation); #endif /* NCPUS > 1 */ s = splclock(); - oadj.seconds = timedelta / 1000000; - oadj.microseconds = timedelta % 1000000; + oadj.seconds = timedelta / MICROSECONDS_IN_ONE_SECOND; + oadj.nanoseconds = (timedelta % MICROSECONDS_IN_ONE_SECOND) * 1000; if (timedelta == 0) { - if (ndelta > bigadj) + if (ndelta_microseconds > bigadj) tickdelta = 10 * tickadj; else tickdelta = tickadj; } - if (ndelta % tickdelta) - ndelta = ndelta / tickdelta * tickdelta; + /* Make ndelta_microseconds a multiple of tickdelta */ + if (ndelta_microseconds % tickdelta) + ndelta_microseconds = ndelta_microseconds / tickdelta * tickdelta; - timedelta = ndelta; + timedelta = ndelta_microseconds; splx(s); #if NCPUS > 1 -- cgit v1.2.3