From f28a11e43f40df2ad92ece62b28ee004a8ad600b Mon Sep 17 00:00:00 2001 From: Adhemerval Zanella Date: Tue, 2 Dec 2025 09:24:18 -0300 Subject: [PATCH] time: Add TIME_MONOTONIC, TIME_ACTIVE, and TIME_THREAD_ACTIVE 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 Reviewed-by: Paul Eggert --- 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 81c7e04293f..c420b67676e 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 f599eeed4e2..ceede2ea26d 100644 --- a/include/time.h +++ b/include/time.h @@ -12,6 +12,7 @@ # include # include # include +# include 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. */ diff --git a/manual/time.texi b/manual/time.texi index d003ddb6377..254638c8f15 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 9ed49a63e49..c02d792a7c0 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 f1c915d729a..1e6abef72d6 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 ca4f2828de9..52a24e9799a 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 1f85c9d428d..26574aa20f8 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 0c3a18f6aae..6543043115f 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 0d2f9a16787..6e055b7c07a 100644 --- a/time/tst-timespec_get.c +++ b/time/tst-timespec_get.c @@ -19,20 +19,22 @@ #include #include +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 e9d6308149c..5d431748045 100644 --- a/time/tst-timespec_getres.c +++ b/time/tst-timespec_getres.c @@ -19,31 +19,39 @@ #include #include +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.47.3