diff options
author | Flavio Cruz <flaviocruz@gmail.com> | 2023-01-19 23:26:19 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2023-01-19 23:26:19 +0100 |
commit | 569df850cd7badd1e36132ad3b44aa76a4d27c25 (patch) | |
tree | 3a840d7b0ea28ffd3a542ffc6e4bfe1206b78d97 | |
parent | 8d30c12342c1cafa7c02ecc00244f57cb39eb148 (diff) | |
download | gnumach-569df850cd7badd1e36132ad3b44aa76a4d27c25.tar.gz gnumach-569df850cd7badd1e36132ad3b44aa76a4d27c25.tar.bz2 gnumach-569df850cd7badd1e36132ad3b44aa76a4d27c25.zip |
Add host_get_time64 RPC to return the time as time_value64_t
Also updated the mapped time to support the new 64-bit time while
keeping compatible with the user land programs currently using it so
they can be migrated in parallel.
-rw-r--r-- | doc/mach.texi | 42 | ||||
-rw-r--r-- | include/mach/mach_host.defs | 8 | ||||
-rw-r--r-- | include/mach/mach_types.defs | 5 | ||||
-rw-r--r-- | include/mach/time_value.h | 44 | ||||
-rw-r--r-- | kern/mach_clock.c | 73 | ||||
-rw-r--r-- | kern/mach_clock.h | 2 |
6 files changed, 118 insertions, 56 deletions
diff --git a/doc/mach.texi b/doc/mach.texi index 86a557cb..53026d0b 100644 --- a/doc/mach.texi +++ b/doc/mach.texi @@ -5612,39 +5612,39 @@ necessarily null-terminated. @node Host Time @section Host Time -@deftp {Data type} time_value_t +@deftp {Data type} time_value64_t This is the representation of a time in Mach. It is a @code{struct -time_value} and consists of the following members: +time_value64} and consists of the following members: @table @code -@item integer_t seconds +@item int64_t seconds The number of seconds. -@item integer_t microseconds -The number of microseconds. +@item int64_t nanoseconds +The number of nanoseconds. @end table @end deftp -The number of microseconds should always be smaller than -@code{TIME_MICROS_MAX} (100000). A time with this property is +The number of nanoseconds should always be smaller than +@code{TIME_NANOS_MAX} (100000000). A time with this property is @dfn{normalized}. Normalized time values can be manipulated with the following macros: -@defmac time_value_add_usec (@w{time_value_t *@var{val}}, @w{integer_t *@var{micros}}) -Add @var{micros} microseconds to @var{val}. If @var{val} is normalized -and @var{micros} smaller than @code{TIME_MICROS_MAX}, @var{val} will be +@defmac time_value64_add_nanos (@w{time_value64_t *@var{val}}, @w{int64_t *@var{nanos}}) +Add @var{nanos} nanoseconds to @var{val}. If @var{val} is normalized +and @var{nanos} smaller than @code{TIME_NANOS_MAX}, @var{val} will be normalized afterwards. @end defmac -@defmac time_value_add (@w{time_value_t *@var{result}}, @w{time_value_t *@var{addend}}) +@defmac time_value64_add (@w{time_value64_t *@var{result}}, @w{time_value64_t *@var{addend}}) Add the values in @var{addend} to @var{result}. If both are normalized, @var{result} will be normalized afterwards. @end defmac -A variable of type @code{time_value_t} can either represent a duration +A variable of type @code{time_value64_t} can either represent a duration or a fixed point in time. In the latter case, it shall be interpreted as -the number of seconds and microseconds after the epoch 1. Jan 1970. +the number of seconds and nanoseconds after the epoch 1. Jan 1970. -@deftypefun kern_return_t host_get_time (@w{host_t @var{host}}, @w{time_value_t *@var{current_time}}) +@deftypefun kern_return_t host_get_time64 (@w{host_t @var{host}}, @w{time_value64_t *@var{current_time}}) 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 @@ -5675,6 +5675,14 @@ The number of microseconds. @item integer_t check_seconds This is a copy of the seconds value, which must be checked to protect +against a race condition when reading out the two time values. This +should only be used when getting the 32 bit version of @code{time_value64_t}. + +@item time_value64_t time_value +The current time. + +@item int64_t check_seconds64 +This is a copy of the seconds value in @var{time_value}, which must be checked to protect against a race condition when reading out the two time values. @end table @end deftp @@ -5686,12 +5694,12 @@ mapped-time interface: @example do @{ - secs = mtime->seconds; + secs = mtime->time_value.seconds; __sync_synchronize(); - usecs = mtime->microseconds; + nanos = mtime->time_value.nanoseconds; __sync_synchronize(); @} -while (secs != mtime->check_seconds); +while (secs != mtime->check_seconds64); @end example diff --git a/include/mach/mach_host.defs b/include/mach/mach_host.defs index 28439a01..0674c859 100644 --- a/include/mach/mach_host.defs +++ b/include/mach/mach_host.defs @@ -352,3 +352,11 @@ routine processor_control( routine host_get_boot_info( host_priv : host_priv_t; out boot_info : kernel_boot_info_t); + +/* + * Get the time on this host. + * Available to all. + */ +routine host_get_time64( + host : host_t; + out current_time : time_value64_t); diff --git a/include/mach/mach_types.defs b/include/mach/mach_types.defs index a98e5c67..8f22137a 100644 --- a/include/mach/mach_types.defs +++ b/include/mach/mach_types.defs @@ -272,6 +272,11 @@ type time_value_t = rpc_time_value_t #endif ; +type time_value64_t = struct { + int64_t seconds; + int64_t nanoseconds; +}; + type emulation_vector_t = ^array[] of vm_offset_t; type rpc_signature_info_t = array[*:1024] of int; diff --git a/include/mach/time_value.h b/include/mach/time_value.h index 9ecdd28e..3a816b22 100644 --- a/include/mach/time_value.h +++ b/include/mach/time_value.h @@ -98,23 +98,23 @@ static __inline__ time_value_t convert_time_value_from_user(rpc_time_value_t tv) time_value_assert(val); \ } -#define time_value64_add_usec(val, micros) { \ - time_value64_assert(val); \ - if (((val)->nanoseconds += (micros) * 1000) \ +#define time_value64_add_nanos(val, nanos) { \ + time_value64_assert(val); \ + if (((val)->nanoseconds += (nanos)) \ >= TIME_NANOS_MAX) { \ (val)->nanoseconds -= TIME_NANOS_MAX; \ (val)->seconds++; \ } \ - time_value64_assert(val); \ + time_value64_assert(val); \ } -#define time_value_sub_usec(val, micros) { \ - time_value_assert(val); \ - if (((val)->microseconds -= (micros)) < 0) { \ - (val)->microseconds += TIME_MICROS_MAX; \ +#define time_value64_sub_nanos(val, nanos) { \ + time_value64_assert(val); \ + if (((val)->nanoseconds -= (nanos)) < 0) { \ + (val)->nanoseconds += TIME_NANOS_MAX; \ (val)->seconds--; \ } \ - time_value_assert(val); \ + time_value64_assert(val); \ } #define time_value_add(result, addend) { \ @@ -123,12 +123,28 @@ static __inline__ time_value_t convert_time_value_from_user(rpc_time_value_t tv) time_value_add_usec(result, (addend)->microseconds); \ } -#define time_value_sub(result, subtrahend) { \ - time_value_assert(subtrahend); \ - (result)->seconds -= (subtrahend)->seconds; \ - time_value_sub_usec(result, (subtrahend)->microseconds); \ +#define time_value64_add(result, addend) { \ + time_value64_assert(addend); \ + (result)->seconds += (addend)->seconds; \ + time_value64_add_nanos(result, (addend)->nanoseconds); \ } +#define time_value64_sub(result, subtrahend) { \ + time_value64_assert(subtrahend); \ + (result)->seconds -= (subtrahend)->seconds; \ + time_value64_sub_nanos(result, (subtrahend)->nanoseconds); \ + } + +#define TIME_VALUE64_TO_TIME_VALUE(tv64, tv) do { \ + (tv)->seconds = (tv64)->seconds; \ + (tv)->microseconds = (tv64)->nanoseconds / 1000; \ +} while(0) + +#define TIME_VALUE_TO_TIME_VALUE64(tv, tv64) do { \ + (tv64)->seconds = (tv)->seconds; \ + (tv64)->nanoseconds = (tv)->microseconds * 1000; \ +} while(0) + /* * Time value available through the mapped-time interface. * Read this mapped value with @@ -144,6 +160,8 @@ typedef struct mapped_time_value { integer_t seconds; integer_t microseconds; integer_t check_seconds; + struct time_value64 time_value; + int64_t check_seconds64; } mapped_time_value_t; /* Macros for converting between struct timespec and time_value_t. */ diff --git a/kern/mach_clock.c b/kern/mach_clock.c index 7383684b..06688fea 100644 --- a/kern/mach_clock.c +++ b/kern/mach_clock.c @@ -96,21 +96,24 @@ volatile mapped_time_value_t *mtime = 0; MACRO_BEGIN \ if (mtime != 0) { \ mtime->check_seconds = (time)->seconds; \ + mtime->check_seconds64 = (time)->seconds; \ __sync_synchronize(); \ mtime->microseconds = (time)->nanoseconds / 1000; \ + mtime->time_value.nanoseconds = (time)->nanoseconds; \ __sync_synchronize(); \ mtime->seconds = (time)->seconds; \ + mtime->time_value.seconds = (time)->seconds; \ } \ MACRO_END -#define read_mapped_time(time) \ -MACRO_BEGIN \ - do { \ - time->seconds = mtime->seconds; \ - __sync_synchronize(); \ - time->microseconds = mtime->microseconds; \ - __sync_synchronize(); \ - } while (time->seconds != mtime->check_seconds); \ +#define read_mapped_time(time) \ +MACRO_BEGIN \ + do { \ + (time)->seconds = mtime->time_value.seconds; \ + __sync_synchronize(); \ + (time)->nanoseconds = mtime->time_value.nanoseconds; \ + __sync_synchronize(); \ + } while ((time)->seconds != mtime->check_seconds64); \ MACRO_END decl_simple_lock_data(, timer_lock) /* lock for ... */ @@ -225,7 +228,7 @@ void clock_interrupt( * Increment the time-of-day clock. */ if (timedelta == 0) { - time_value64_add_usec(&time, usec); + time_value64_add_nanos(&time, usec * 1000); } else { int delta; @@ -246,7 +249,7 @@ void clock_interrupt( delta = usec + tickdelta; timedelta -= tickdelta; } - time_value64_add_usec(&time, delta); + time_value64_add_nanos(&time, delta * 1000); } update_mapped_time(&time); @@ -390,7 +393,7 @@ void init_timeout(void) * the boot-time clock by storing the difference to the real-time * clock. */ -struct time_value clock_boottime_offset; +struct time_value64 clock_boottime_offset; /* * Update the offset of the boot-time clock from the real-time clock. @@ -398,11 +401,11 @@ struct time_value clock_boottime_offset; * This function must be called at SPLHIGH. */ static void -clock_boottime_update(struct time_value *new_time) +clock_boottime_update(const struct time_value64 *new_time) { - struct time_value delta = {.seconds = time.seconds, .microseconds = time.nanoseconds / 1000}; - time_value_sub(&delta, new_time); - time_value_add(&clock_boottime_offset, &delta); + struct time_value64 delta = time; + time_value64_sub(&delta, new_time); + time_value64_add(&clock_boottime_offset, &delta); } /* @@ -410,10 +413,12 @@ clock_boottime_update(struct time_value *new_time) * frame. */ void -record_time_stamp (time_value_t *stamp) +record_time_stamp(time_value_t *stamp) { - read_mapped_time(stamp); - time_value_add(stamp, &clock_boottime_offset); + time_value64_t stamp64; + read_mapped_time(&stamp64); + time_value64_add(&stamp64, &clock_boottime_offset); + TIME_VALUE64_TO_TIME_VALUE(&stamp64, stamp); } /* @@ -421,15 +426,17 @@ record_time_stamp (time_value_t *stamp) * real-time clock frame. */ void -read_time_stamp (time_value_t *stamp, time_value_t *result) +read_time_stamp (const time_value_t *stamp, time_value_t *result) { - *result = *stamp; - time_value_sub(result, &clock_boottime_offset); + time_value64_t result64; + TIME_VALUE_TO_TIME_VALUE64(stamp, &result64); + time_value64_sub(&result64, &clock_boottime_offset); + TIME_VALUE64_TO_TIME_VALUE(&result64, result); } /* - * Read the time. + * Read the time (deprecated version). */ kern_return_t host_get_time(const host_t host, time_value_t *current_time) @@ -437,6 +444,21 @@ host_get_time(const host_t host, time_value_t *current_time) if (host == HOST_NULL) return(KERN_INVALID_HOST); + time_value64_t current_time64; + read_mapped_time(¤t_time64); + TIME_VALUE64_TO_TIME_VALUE(¤t_time64, current_time); + return (KERN_SUCCESS); +} + +/* + * Read the time. + */ +kern_return_t +host_get_time64(const host_t host, time_value64_t *current_time) +{ + if (host == HOST_NULL) + return(KERN_INVALID_HOST); + read_mapped_time(current_time); return (KERN_SUCCESS); } @@ -462,9 +484,10 @@ host_set_time(const host_t host, time_value_t new_time) #endif /* NCPUS > 1 */ s = splhigh(); - clock_boottime_update(&new_time); - time.seconds = new_time.seconds; - time.nanoseconds = new_time.microseconds * 1000; + time_value64_t new_time64; + TIME_VALUE_TO_TIME_VALUE64(&new_time, &new_time64); + clock_boottime_update(&new_time64); + time = new_time64; update_mapped_time(&time); resettodr(); splx(s); diff --git a/kern/mach_clock.h b/kern/mach_clock.h index 903492e6..2da311d1 100644 --- a/kern/mach_clock.h +++ b/kern/mach_clock.h @@ -98,7 +98,7 @@ 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 void read_time_stamp (const time_value_t *stamp, time_value_t *result); extern kern_return_t host_get_time( host_t host, |