tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

kern/59127: clock_getres(2) returns EINVAL for CLOCK_{PROCESS,THREAD}_CPUTIME_ID



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.
From ebf335048a3a4684b05c4efd07acaeae2b8c0cf0 Mon Sep 17 00:00:00 2001
From: PHO <pho%cielonegro.org@localhost>
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();
 }


Home | Main Index | Thread Index | Old Index