bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Add host_get_time64 RPC to return the time as time_value64_t.


From: Flavio Cruz
Subject: [PATCH] Add host_get_time64 RPC to return the time as time_value64_t.
Date: Fri, 13 Jan 2023 03:27:05 -0500

Also updated the mapped time to support the new 64-bit time while
keeping compatibility with the user land programs currently using it so
they can be migrated in parallel.
---
 doc/mach.texi                | 42 ++++++++++++--------
 include/mach/mach_host.defs  |  8 ++++
 include/mach/mach_types.defs |  5 +++
 include/mach/time_value.h    | 36 ++++++++++-------
 kern/mach_clock.c            | 75 ++++++++++++++++++++++++------------
 kern/mach_clock.h            |  2 +-
 6 files changed, 111 insertions(+), 57 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..01f86644 100644
--- a/include/mach/time_value.h
+++ b/include/mach/time_value.h
@@ -86,7 +86,7 @@ static __inline__ time_value_t 
convert_time_value_from_user(rpc_time_value_t tv)
   assert(0 <= (val)->microseconds && (val)->microseconds < TIME_MICROS_MAX);
 
 #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_value_add_usec(val, micros)        {       \
        time_value_assert(val);                         \
@@ -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,10 +123,16 @@ 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);  \
   }
 
 /*
@@ -144,6 +150,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..c7725ce5 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,13 @@ 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);
+       stamp->seconds = stamp64.seconds;
+       stamp->microseconds = stamp64.nanoseconds / 1000;
 }
 
 /*
@@ -421,18 +427,36 @@ 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 = {.seconds = stamp->seconds, .nanoseconds = 
stamp->microseconds * 1000};
+       time_value64_sub(&result64, clock_boottime_offset);
+       result->seconds = result64.seconds;
+       result->microseconds = result64.nanoseconds / 1000;
 }
 
 
 /*
- * 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);
+       current_time->seconds = current_time64.seconds;
+       current_time->microseconds = current_time64.nanoseconds / 1000;
+       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 +486,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;
+       const time_value64_t new_time64 = {.seconds = new_time.seconds,
+                                    .nanoseconds = new_time.microseconds * 
1000};
+       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




reply via email to

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