bug-hurd
[Top][All Lists]
Advanced

[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(&current_time64);
> +     TIME_VALUE64_TO_TIME_VALUE(&current_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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]