]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
time: Add TIME_MONOTONIC, TIME_ACTIVE, and TIME_THREAD_ACTIVE
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>
Tue, 2 Dec 2025 12:24:18 +0000 (09:24 -0300)
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>
Wed, 3 Dec 2025 14:03:58 +0000 (11:03 -0300)
The TIME_MONOTONIC maps to POSIX's CLOCK_MONOTONIC, TIME_ACTIVE to
CLOCK_PROCESS_CPUTIME_ID, and TIME_THREAD_ACTIVE to
CLOCK_THREAD_CPUTIME_ID.

No Linux specific timer are added as extension.

Co-authored-by: Yonggang Luo <luoyonggang@gmail.com>
Reviewed-by: Paul Eggert <eggert@cs.ucla.edu>
NEWS
include/time.h
manual/time.texi
sysdeps/unix/sysv/linux/timespec_get.c
sysdeps/unix/sysv/linux/timespec_getres.c
time/time.h
time/timespec_get.c
time/timespec_getres.c
time/tst-timespec_get.c
time/tst-timespec_getres.c

diff --git a/NEWS b/NEWS
index 81c7e04293fc6b4e29a51342d9dd272e1de549e4..c420b67676ead0bc1c8b7426a219896e7597b75e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,9 @@ Major new features:
   lgammaf/lgammaf_r, log10f, sinhf, sqrtf, tgammaf, y0/j0, y1/j1, and yn/jn
   were moved to compat symbols, allowing improvements in performance.
 
+* The ISO C23 optional time base TIME_MONOTONIC, TIME_ACTIVE, and
+  TIME_THREAD_ACTIVE have been added.
+
 Deprecated and removed features, and other changes affecting compatibility:
 
 * Support for dumped heaps has been removed - malloc_set_state() now always
index f599eeed4e2d9990c3862442037353aca397117c..ceede2ea26d5b393693f059f69c7793d6a49d75b 100644 (file)
@@ -12,6 +12,7 @@
 # include <time-clockid.h>
 # include <sys/time.h>
 # include <stdint.h>
+# include <verify.h>
 
 extern __typeof (strftime_l) __strftime_l;
 libc_hidden_proto (__strftime_l)
@@ -536,6 +537,17 @@ time64_now (void)
   return ts.tv_sec;
 }
 
+/* Helper that converts from C timebase to POSIX clockid_t.  */
+static inline clockid_t
+clock_from_timebase (int timebase)
+{
+  verify (TIME_UTC - 1 == CLOCK_REALTIME);
+  verify (TIME_MONOTONIC - 1 == CLOCK_MONOTONIC);
+  verify (TIME_ACTIVE - 1 == CLOCK_PROCESS_CPUTIME_ID);
+  verify (TIME_THREAD_ACTIVE - 1 == CLOCK_THREAD_CPUTIME_ID);
+  return timebase - 1;
+}
+
 #define NSEC_PER_SEC    1000000000L  /* Nanoseconds per second.  */
 #define USEC_PER_SEC    1000000L     /* Microseconds per second.  */
 #define NSEC_PER_USEC   1000L        /* Nanoseconds per microsecond.  */
index d003ddb6377940931a66a3aac320506c7cf22d70..254638c8f15e0ed596e90fd20de2da551b0bc8ca 100644 (file)
@@ -629,6 +629,19 @@ Systems may support more than just this @w{ISO C} clock.
 Store into @code{*@var{ts}} the current time according to the @w{ISO
 C} time @var{base}.
 
+The base @code{TIME_UTC} returns the time since the epoch.  It corresponds
+to @code{CLOCK_REALTIME}.
+
+The base @code{TIME_MONOTONIC} returns a monotonically nondecreasing time since
+an unspecified point in the past that may change if the system is rebooted or
+suspended.  It corresponds to @code{CLOCK_MONOTONIC}.
+
+The base @code{TIME_ACTIVE} returns the CPU time consumed by the process
+(including all threads).  It corresponds to @code{CLOCK_PROCESS_CPUTIME_ID}.
+
+The base @code{TIME_THREAD_ACTIVE} returns the CPU time consumed by the
+calling thread.  It corresponds to @code{CLOCK_THREAD_CPUTIME_ID}.
+
 The return value is @var{base} on success and @code{0} on failure.
 @end deftypefun
 
index 9ed49a63e49309f0d42fd6536c1f27fa1b2768f6..c02d792a7c08852fc348f682979d4c65ac111fa6 100644 (file)
 int
 __timespec_get64 (struct __timespec64 *ts, int base)
 {
-  if (base == TIME_UTC)
-    {
-      __clock_gettime64 (CLOCK_REALTIME, ts);
-      return base;
-    }
-  return 0;
+  return __clock_gettime64 (clock_from_timebase (base), ts) == 0 ? base : 0;
 }
 
 #if __TIMESIZE != 64
@@ -42,7 +37,7 @@ __timespec_get (struct timespec *ts, int base)
 
   ret = __timespec_get64 (&tp64, base);
 
-  if (ret == TIME_UTC)
+  if (ret != 0)
     {
       if (! in_time_t_range (tp64.tv_sec))
         {
index f1c915d729adbaa22af7ce711470a51501f5fd95..1e6abef72d6223eb1b0831560252739678eb2007 100644 (file)
 int
 __timespec_getres64 (struct __timespec64 *ts, int base)
 {
-  if (base == TIME_UTC)
-    {
-      __clock_getres64 (CLOCK_REALTIME, ts);
-      return base;
-    }
-  return 0;
+  return __clock_getres64 (clock_from_timebase (base), ts) == 0 ? base : 0;
 }
 
 #if __TIMESIZE != 64
@@ -40,8 +35,7 @@ __timespec_getres (struct timespec *ts, int base)
   struct __timespec64 tp64;
 
   ret = __timespec_getres64 (&tp64, base);
-
-  if (ret == TIME_UTC && ts != NULL)
+  if (ret != 0 && ts != NULL)
     *ts = valid_timespec64_to_timespec (tp64);
 
   return ret;
index ca4f2828de99c3bf8e7e2945da1fc74b51434e74..52a24e9799aecd9422cf102e654e15a264353b8a 100644 (file)
@@ -68,6 +68,11 @@ typedef __pid_t pid_t;
 /* Time base values for timespec_get.  */
 # define TIME_UTC 1
 #endif
+#if __GLIBC_USE (ISOC23)
+# define TIME_MONOTONIC          2
+# define TIME_ACTIVE             3
+# define TIME_THREAD_ACTIVE      4
+#endif
 
 __BEGIN_DECLS
 
index 1f85c9d428df97b13d456c9b967f21fe04dd7c96..26574aa20f85d4acdbb51087aecd1ab09836a4f1 100644 (file)
 int
 timespec_get (struct timespec *ts, int base)
 {
-  if (base == TIME_UTC)
-    {
-      __clock_gettime (CLOCK_REALTIME, ts);
-      return base;
-    }
-  return 0;
+  return __clock_gettime (clock_from_timebase (base), ts) == 0 ? base : 0;
 }
index 0c3a18f6aae4356408b035cd79f9f001ed9b267d..6543043115ff58a2f076a9eff9fdf20edd6d3e85 100644 (file)
 int
 timespec_getres (struct timespec *ts, int base)
 {
-  if (base == TIME_UTC)
-    {
-      __clock_getres (CLOCK_REALTIME, ts);
-      return base;
-    }
-  return 0;
+  return __clock_getres (clock_from_timebase (base), ts) == 0 ? base : 0;
 }
index 0d2f9a167879b94973ba1d260d84045eeaab151f..6e055b7c07af6917fa7962fafd3ffb2d1b03c4da 100644 (file)
 #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)
 {
-  {
-    struct timespec ts;
-    TEST_COMPARE (timespec_get (&ts, 0), 0);
-  }
-
-  {
-    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;
 }
index e9d6308149cbc9a7685c0b1ca2112b63a1e271fa..5d4317480459919da7b5aec98a6042699cd219ce 100644 (file)
 #include <time.h>
 #include <support/check.h>
 
+static void
+test_timespec_getres (int clockid, int timebase)
+{
+  struct timespec ts;
+  TEST_COMPARE (timespec_getres (&ts, TIME_UTC), TIME_UTC);
+  /* 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);
+  /* Expect the resolution to be the same as that reported for
+     'clockid' 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);
+}
+
 static int
 do_test (void)
 {
   {
     struct timespec ts;
+    /* Invalid timebase.  */
     TEST_COMPARE (timespec_getres (&ts, 0), 0);
+    /* Invalid timespec.  */
     TEST_COMPARE (timespec_getres (NULL, 0), 0);
   }
 
-  {
-    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;
 }