kern/59127: clock_getres(2) returns EINVAL for CLOCK_{PROCESS,THREAD}_CPUTIME_ID
PHO <[email protected]>
| Newsgroups | gmane.os.netbsd.devel.kernel |
|---|---|
| Message-ID | <[email protected]> |
Hi, I just filed a PR with the attached patch to make clock_getres(2) support these two clocks. I will commit the patch in a week or two if no one objects: https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=59127 The reason why this matters to me is that lang/ghc910 has been silently broken. Its function System.CPUTime.cpuTimePrecision tries to call clock_getres(CLOCK_PROCESS_CPUTIME_ID) if: #elif _POSIX_TIMERS > 0 && defined(_POSIX_CPUTIME) && _POSIX_CPUTIME >= 0 which holds true on NetBSD, but then the syscall returns EINVAL: % ghci GHCi, version 9.10.1: https://www.haskell.org/ghc/ :? for help Loaded GHCi configuration from /home/pho/.ghci ghci> :m System.CPUTime ghci> cpuTimePrecision *** Exception: clock_getres: invalid argument (Invalid argument) GHC still needs to be patched in the meantime but I believe the kernel should support this.
clock_getres.patch
(text/x-patch, 2.6 KB)
From ebf335048a3a4684b05c4efd07acaeae2b8c0cf0 Mon Sep 17 00:00:00 2001 From: PHO <[email protected]> Date: Tue, 4 Mar 2025 21:28:46 +0900 Subject: [PATCH] clock_getres(2): Support CLOCK_{PROCESS,THREAD}_CPUTIME_ID The syscall previously returned EINVAL for these two clocks. It still has no support for CLOCK_VIRTUAL and CLOCK_PROF but clock_gettime(2) doesn't either. --- sys/kern/kern_time.c | 2 ++ tests/lib/libc/sys/t_clock_gettime.c | 34 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 91d259d810ac5..213a151b6b506 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -339,6 +339,8 @@ clock_getres1(clockid_t clock_id, struct timespec *ts) switch (clock_id) { case CLOCK_REALTIME: case CLOCK_MONOTONIC: + case CLOCK_PROCESS_CPUTIME_ID: + case CLOCK_THREAD_CPUTIME_ID: ts->tv_sec = 0; if (tc_getfrequency() > 1000000000) ts->tv_nsec = 1; diff --git a/tests/lib/libc/sys/t_clock_gettime.c b/tests/lib/libc/sys/t_clock_gettime.c index 6421b1ab0cb8c..7e0954c1244aa 100644 --- a/tests/lib/libc/sys/t_clock_gettime.c +++ b/tests/lib/libc/sys/t_clock_gettime.c @@ -285,12 +285,46 @@ ATF_TC_BODY(clock_gettime_thread_cputime_is_monotonic, tc) CLOCK_THREAD_CPUTIME_ID, &waste_user_time); } +static void +check_resolution(const char *clockname, clockid_t clockid) +{ + struct timespec ts; + int rv; + + RLF(rv = clock_getres(clockid, &ts), "%s", clockname); + if (rv != -1) { + ATF_CHECK_MSG(ts.tv_sec == 0, + "The resolution of the clock %s is reported as %jd.%09jd which is" + " lower than a second; most likely an wrong value", + clockname, ts.tv_sec, ts.tv_nsec); + } +} + +ATF_TC(clock_getres); +ATF_TC_HEAD(clock_getres, tc) +{ + atf_tc_set_md_var(tc, "descr", + "Checks that clock_getres(2) returns some reasonable resolution for all supported clocks"); +} +ATF_TC_BODY(clock_getres, tc) +{ + check_resolution("CLOCK_REALTIME", CLOCK_REALTIME); + check_resolution("CLOCK_MONOTONIC", CLOCK_MONOTONIC); + atf_tc_expect_fail("These clocks aren't supported but are documented in clock_gettime(2) for some reason"); + check_resolution("CLOCK_VIRTUAL", CLOCK_VIRTUAL); + check_resolution("CLOCK_PROF", CLOCK_PROF); + atf_tc_expect_pass(); + check_resolution("CLOCK_PROCESS_CPUTIME_ID", CLOCK_PROCESS_CPUTIME_ID); + check_resolution("CLOCK_THREAD_CPUTIME_ID", CLOCK_THREAD_CPUTIME_ID); +} + ATF_TP_ADD_TCS(tp) { ATF_TP_ADD_TC(tp, clock_gettime_real); ATF_TP_ADD_TC(tp, clock_gettime_process_cputime_is_monotonic); ATF_TP_ADD_TC(tp, clock_gettime_thread_cputime_is_monotonic); + ATF_TP_ADD_TC(tp, clock_getres); return atf_no_error(); }