[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] Add host_get_time64 RPC to return the time as time_value64_t
From: |
Samuel Thibault |
Subject: |
Re: [PATCH] Add host_get_time64 RPC to return the time as time_value64_t. |
Date: |
Thu, 19 Jan 2023 23:26:39 +0100 |
User-agent: |
NeoMutt/20170609 (1.8.3) |
Applied, thanks!
Flavio Cruz, le jeu. 19 janv. 2023 14:21:38 -0500, a ecrit:
> 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.
> ---
> On Mon, Jan 16, 2023 at 11:37:47PM +0100, Samuel Thibault wrote:
> > Flavio Cruz, le ven. 13 janv. 2023 03:27:05 -0500, a ecrit:
> > > #define time_value64_assert(val) \
> > > - assert(0 <= (val)->nanoseconds && (val)->nanoseconds < TIME_NANOS_MAX);
> > > + assert(0 <= (val).nanoseconds && (val).nanoseconds < TIME_NANOS_MAX);
> > [...]
> > > +#define time_value64_add_nanos(val, nanos) { \
> > > + time_value64_assert(*val); \
> > [...]
> >
> > Macros such as TIMEVAL_TO_TIMESPEC etc. do always take pointers, so
> > better keep coherent with them.
>
> Done.
>
> >
> > > -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);
> > > + stamp->seconds = stamp64.seconds;
> > > + stamp->microseconds = stamp64.nanoseconds / 1000;
> >
> > There are quite a few such conversions, perhaps introduce a macro to
> > convert between time_value_t and time_value64_t?
>
> Created two new macros for the translations.
>
> >
> > Samuel
>
> doc/mach.texi | 42 ++++++++++++---------
> include/mach/mach_host.defs | 8 ++++
> include/mach/mach_types.defs | 5 +++
> include/mach/time_value.h | 44 +++++++++++++++-------
> kern/mach_clock.c | 73 ++++++++++++++++++++++++------------
> 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,18 +426,35 @@ 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)
> +{
> + 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);
> @@ -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,
> --
> 2.39.0
>
--
Samuel
---
Pour une évaluation indépendante, transparente et rigoureuse !
Je soutiens la Commission d'Évaluation de l'Inria.