[PATCH v6] time: Add TIME_MONOTONIC, TIME_ACTIVE, and TIME_THREAD_ACTIVE

罗勇刚(Yonggang Luo) luoyonggang@gmail.com
Thu Dec 4 13:56:51 GMT 2025


On Wed, Dec 3, 2025 at 2:51 AM Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>
> 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>
> --
> Change from v5:
> * Changed _Static_assert to use verify.
> * Added Paul Eggert manual suggestions.
>
> Changes from v4:
> * Fixed _Static_assert naming in clock_from_timebase (hopefully
>   this time).
>
> Changes from v3:
> * Fixed _Static_assert naming in clock_from_timebase.
>
> Changes from v2:
> * Added manual entries for the new symbols.
> * Optimized C TIME to POSIX clockid_t mapping.
>
> Changes from v1:
> * Fixed new timers on ABIs with 32 bit time_t support.
> * Dropped support for the Linux specific timers.
> ---
>  NEWS                                      |  3 ++
>  include/time.h                            | 12 +++++++
>  manual/time.texi                          | 13 ++++++++
>  sysdeps/unix/sysv/linux/timespec_get.c    |  9 ++---
>  sysdeps/unix/sysv/linux/timespec_getres.c | 10 ++----
>  time/time.h                               |  5 +++
>  time/timespec_get.c                       |  7 +---
>  time/timespec_getres.c                    |  7 +---
>  time/tst-timespec_get.c                   | 24 +++++++-------
>  time/tst-timespec_getres.c                | 40 ++++++++++++++---------
>  10 files changed, 76 insertions(+), 54 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index 81c7e04293..c420b67676 100644
> --- 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
> diff --git a/include/time.h b/include/time.h
> index f599eeed4e..518215a2f9 100644
> --- a/include/time.h
> +++ b/include/time.h
> @@ -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)

Please rename clock_from_timebase to __clock_from_timebase
or   __glibc_clock_from_timebase, as this function is in header that
be used by so much code, use __glibc_clock_from_timebase will reduce
potential conflict


> +{
> +  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.  */
> diff --git a/manual/time.texi b/manual/time.texi
> index d003ddb637..254638c8f1 100644
> --- a/manual/time.texi
> +++ b/manual/time.texi
> @@ -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
>
> diff --git a/sysdeps/unix/sysv/linux/timespec_get.c b/sysdeps/unix/sysv/linux/timespec_get.c
> index 9ed49a63e4..c02d792a7c 100644
> --- a/sysdeps/unix/sysv/linux/timespec_get.c
> +++ b/sysdeps/unix/sysv/linux/timespec_get.c
> @@ -23,12 +23,7 @@
>  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))
>          {
> diff --git a/sysdeps/unix/sysv/linux/timespec_getres.c b/sysdeps/unix/sysv/linux/timespec_getres.c
> index f1c915d729..1e6abef72d 100644
> --- a/sysdeps/unix/sysv/linux/timespec_getres.c
> +++ b/sysdeps/unix/sysv/linux/timespec_getres.c
> @@ -22,12 +22,7 @@
>  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;
> diff --git a/time/time.h b/time/time.h
> index ca4f2828de..52a24e9799 100644
> --- a/time/time.h
> +++ b/time/time.h
> @@ -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
>
> diff --git a/time/timespec_get.c b/time/timespec_get.c
> index 1f85c9d428..26574aa20f 100644
> --- a/time/timespec_get.c
> +++ b/time/timespec_get.c
> @@ -22,10 +22,5 @@
>  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;
>  }
> diff --git a/time/timespec_getres.c b/time/timespec_getres.c
> index 0c3a18f6aa..6543043115 100644
> --- a/time/timespec_getres.c
> +++ b/time/timespec_getres.c
> @@ -23,10 +23,5 @@
>  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;
>  }
> diff --git a/time/tst-timespec_get.c b/time/tst-timespec_get.c
> index 0d2f9a1678..6e055b7c07 100644
> --- a/time/tst-timespec_get.c
> +++ b/time/tst-timespec_get.c
> @@ -19,20 +19,22 @@
>  #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;
>  }
> diff --git a/time/tst-timespec_getres.c b/time/tst-timespec_getres.c
> index e9d6308149..5d43174804 100644
> --- a/time/tst-timespec_getres.c
> +++ b/time/tst-timespec_getres.c
> @@ -19,31 +19,39 @@
>  #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;
>  }
> --
> 2.43.0
>


-- 
         此致
礼
罗勇刚
Yours
    sincerely,
Yonggang Luo


More information about the Libc-alpha mailing list