[1/2] time: Implement newly add timebase defines for c2x timespec_get and timespec_getres

Message ID 20230621183206.260-2-luoyonggang@gmail.com
State New
Headers
Series Implement newly add timebase defines for c2x timespec_get and timespec_getres |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm fail Testing failed

Commit Message

Yonggang Luo June 21, 2023, 6:32 p.m. UTC
  The following timebase defines are implemented
# define TIME_MONOTONIC          2
# define TIME_ACTIVE             3
# define TIME_THREAD_ACTIVE      4

And a private function named clock_from_timebase is added, this is used to
map c11 timebase to posix clockid_t in a common place
Maybe it's can be prompted into a POSIX function
in future to resolve issue that from
https://www.openwall.com/lists/libc-coord/2023/04/25/1

Signed-off-by: Yonggang Luo <luoyonggang@gmail.com>
---
 NEWS                                      |  5 +++
 include/time.h                            | 26 ++++++++++++++++
 sysdeps/unix/sysv/linux/timespec_get.c    |  7 +++--
 sysdeps/unix/sysv/linux/timespec_getres.c |  5 +--
 time/time.h                               |  7 ++++-
 time/timespec_get.c                       |  7 +++--
 time/timespec_getres.c                    |  7 +++--
 time/tst-timespec_get.c                   | 17 ++++++++---
 time/tst-timespec_getres.c                | 37 ++++++++++++++---------
 9 files changed, 88 insertions(+), 30 deletions(-)
  

Patch

diff --git a/NEWS b/NEWS
index 709ee40e50..375e15c5e1 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,11 @@  Version 2.38
 
 Major new features:
 
+* C2x timebase macro defines are supported, these are:
+  TIME_MONOTONIC
+  TIME_ACTIVE
+  TIME_THREAD_ACTIVE
+
 * When C2X features are enabled and the base argument is 0 or 2, the
   following functions support binary integers prefixed by 0b or 0B as
   input: strtol, strtoll, strtoul, strtoull, strtol_l, strtoll_l,
diff --git a/include/time.h b/include/time.h
index f599eeed4e..77ca52ecbf 100644
--- a/include/time.h
+++ b/include/time.h
@@ -361,6 +361,32 @@  in_time_t_range (__time64_t t)
   return s == t;
 }
 
+/* Helper that convert from c11 timebase to posix clockid_t,
+   when the mapping not exist, return -1 */
+static inline clockid_t
+clock_from_timebase (int timebase)
+{
+  clockid_t clockid = -1;
+  switch (timebase)
+    {
+    case TIME_UTC:
+      clockid = CLOCK_REALTIME;
+      break;
+    case TIME_MONOTONIC:
+      clockid = CLOCK_MONOTONIC;
+      break;
+    case TIME_ACTIVE:
+      clockid = CLOCK_PROCESS_CPUTIME_ID;
+      break;
+    case TIME_THREAD_ACTIVE:
+      clockid = CLOCK_THREAD_CPUTIME_ID;
+      break;
+    default:
+      break;
+    }
+  return clockid;
+}
+
 /* Convert a known valid struct timeval into a struct __timespec64.  */
 static inline struct __timespec64
 valid_timeval_to_timespec64 (const struct timeval tv)
diff --git a/sysdeps/unix/sysv/linux/timespec_get.c b/sysdeps/unix/sysv/linux/timespec_get.c
index 3c852be99b..40d3ae3f0d 100644
--- a/sysdeps/unix/sysv/linux/timespec_get.c
+++ b/sysdeps/unix/sysv/linux/timespec_get.c
@@ -23,10 +23,11 @@ 
 int
 __timespec_get64 (struct __timespec64 *ts, int base)
 {
-  if (base == TIME_UTC)
+  clockid_t clockid = clock_from_timebase (base);
+  if (clockid >= 0)
     {
-      __clock_gettime64 (CLOCK_REALTIME, ts);
-      return base;
+      if (__clock_gettime (clockid, ts) >= 0)
+        return base;
     }
   return 0;
 }
diff --git a/sysdeps/unix/sysv/linux/timespec_getres.c b/sysdeps/unix/sysv/linux/timespec_getres.c
index 7e61d78a77..e73c73cf74 100644
--- a/sysdeps/unix/sysv/linux/timespec_getres.c
+++ b/sysdeps/unix/sysv/linux/timespec_getres.c
@@ -22,9 +22,10 @@ 
 int
 __timespec_getres64 (struct __timespec64 *ts, int base)
 {
-  if (base == TIME_UTC)
+  clockid_t clockid = clock_from_timebase (base);
+  if (clockid >= 0)
     {
-      __clock_getres64 (CLOCK_REALTIME, ts);
+      __clock_getres64 (clockid, ts);
       return base;
     }
   return 0;
diff --git a/time/time.h b/time/time.h
index 368f4dc588..d01c90e229 100644
--- a/time/time.h
+++ b/time/time.h
@@ -62,7 +62,12 @@  typedef __pid_t pid_t;
 
 #ifdef __USE_ISOC11
 /* Time base values for timespec_get.  */
-# define TIME_UTC 1
+# define TIME_UTC                1
+#endif
+#if __GLIBC_USE_ISOC2X
+# define TIME_MONOTONIC          2
+# define TIME_ACTIVE             3
+# define TIME_THREAD_ACTIVE      4
 #endif
 
 __BEGIN_DECLS
diff --git a/time/timespec_get.c b/time/timespec_get.c
index 9b1d4f22ed..93aa442ca0 100644
--- a/time/timespec_get.c
+++ b/time/timespec_get.c
@@ -22,10 +22,11 @@ 
 int
 timespec_get (struct timespec *ts, int base)
 {
-  if (base == TIME_UTC)
+  clockid_t clockid = clock_from_timebase (base);
+  if (clockid >= 0)
     {
-      __clock_gettime (CLOCK_REALTIME, ts);
-      return base;
+      if (__clock_gettime (clockid, ts) >= 0)
+        return base;
     }
   return 0;
 }
diff --git a/time/timespec_getres.c b/time/timespec_getres.c
index fd64dc7a47..3cc7a4b3bb 100644
--- a/time/timespec_getres.c
+++ b/time/timespec_getres.c
@@ -23,10 +23,11 @@ 
 int
 timespec_getres (struct timespec *ts, int base)
 {
-  if (base == TIME_UTC)
+  clockid_t clockid = clock_from_timebase (base);
+  if (clockid >= 0)
     {
-      __clock_getres (CLOCK_REALTIME, ts);
-      return base;
+      if (__clock_getres (clockid, ts) >= 0)
+        return base;
     }
   return 0;
 }
diff --git a/time/tst-timespec_get.c b/time/tst-timespec_get.c
index d735160394..f97327666c 100644
--- a/time/tst-timespec_get.c
+++ b/time/tst-timespec_get.c
@@ -19,6 +19,15 @@ 
 #include <time.h>
 #include <support/check.h>
 
+static void
+test_timespec_get (int timebase)
+{
+    struct timespec ts;
+    TEST_COMPARE (timespec_get (&ts, timebase), timebase);
+    TEST_VERIFY (ts.tv_nsec >= 0);
+    TEST_VERIFY (ts.tv_nsec < 1000000000);
+}
+
 static int
 do_test (void)
 {
@@ -28,10 +37,10 @@  do_test (void)
   }
 
   {
-    struct timespec ts;
-    TEST_COMPARE (timespec_get (&ts, TIME_UTC), TIME_UTC);
-    TEST_VERIFY (ts.tv_nsec >= 0);
-    TEST_VERIFY (ts.tv_nsec < 1000000000);
+    test_timespec_get (TIME_UTC);
+    test_timespec_get (TIME_MONOTONIC);
+    test_timespec_get (TIME_ACTIVE);
+    test_timespec_get (TIME_THREAD_ACTIVE);
   }
 
   return 0;
diff --git a/time/tst-timespec_getres.c b/time/tst-timespec_getres.c
index b400a70138..960f7c3298 100644
--- a/time/tst-timespec_getres.c
+++ b/time/tst-timespec_getres.c
@@ -19,6 +19,25 @@ 
 #include <time.h>
 #include <support/check.h>
 
+static void
+test_timespec_getres (clockid_t clock, int timebase)
+{
+  struct timespec ts;
+  TEST_COMPARE (timespec_getres (&ts, timebase), timebase);
+  /* Expect all supported systems to support timebase with
+     resolution better than one second.  */
+  TEST_VERIFY (ts.tv_sec == 0);
+  TEST_VERIFY (ts.tv_nsec > 0);
+  TEST_VERIFY (ts.tv_nsec < 1000000000);
+  TEST_COMPARE (timespec_getres (NULL, timebase), timebase);
+  /* Expect the resolution to be the same as that reported for
+     clock with clock_getres.  */
+  struct timespec cts;
+  TEST_COMPARE (clock_getres (clock, &cts), 0);
+  TEST_COMPARE (ts.tv_sec, cts.tv_sec);
+  TEST_COMPARE (ts.tv_nsec, cts.tv_nsec);
+}
+
 static int
 do_test (void)
 {
@@ -29,20 +48,10 @@  do_test (void)
   }
 
   {
-    struct timespec ts;
-    TEST_COMPARE (timespec_getres (&ts, TIME_UTC), TIME_UTC);
-    /* Expect all supported systems to support TIME_UTC with
-       resolution better than one second.  */
-    TEST_VERIFY (ts.tv_sec == 0);
-    TEST_VERIFY (ts.tv_nsec > 0);
-    TEST_VERIFY (ts.tv_nsec < 1000000000);
-    TEST_COMPARE (timespec_getres (NULL, TIME_UTC), TIME_UTC);
-    /* Expect the resolution to be the same as that reported for
-       CLOCK_REALTIME with clock_getres.  */
-    struct timespec cts;
-    TEST_COMPARE (clock_getres (CLOCK_REALTIME, &cts), 0);
-    TEST_COMPARE (ts.tv_sec, cts.tv_sec);
-    TEST_COMPARE (ts.tv_nsec, cts.tv_nsec);
+    test_timespec_getres (CLOCK_REALTIME, TIME_UTC);
+    test_timespec_getres (CLOCK_MONOTONIC, TIME_MONOTONIC);
+    test_timespec_getres (CLOCK_PROCESS_CPUTIME_ID, TIME_ACTIVE);
+    test_timespec_getres (CLOCK_THREAD_CPUTIME_ID, TIME_THREAD_ACTIVE);
   }
 
   return 0;