Re: nonexistent clocks
Jan Stary <[email protected]> Fri, 26 Jun 2026 14:39:53 +0200
| Newsgroups | gmane.os.netbsd.devel.kernel |
|---|---|
| Message-ID | <[email protected]> |
Hi, I am moving this to tech-kern as it's getting technical and I include a diff; please let me know if this is not the approproate list (I am pretty new to netbsd). The clock_gettime(2) manpage documents CLOCK_VIRTUAL and CLOCK_PROF, but the clock_*() functions fail (EINVAL) on these clocks. In fact, a test in tests/ (see below) expect them to fail. I think it is confusing to list these clocks in ths manpage among other valid clocks, if they are not a valid argument to the clock functions; and I believe the manpage would be better off without them. Looking at sys/kern/kern_time.c, these clocks indeed cannot be read or set; but perhaps (I am speculating here) they still do exist - as the underlying clocks for the respective itimers, namely ITIMER_VIRTUAL and ITIMER_PROF. If that is the case, the manpage should either clearly state that these clocks cannot be read or set, or (imho preferably) just not mention them at all. Can someone who actually knows how this works shed some light please? The diff and my naive clock and timer tests are below. Jan On Jun 25 13:17:00, [email protected] wrote: > Hi, > > > According to tests/lib/libc/sys/t_clock_gettime.c > > ""These clocks aren't supported but are documented" > > " in clock_gettime(2) for some reason" > > thanks for the pointer. I am new to NetBSD > and am only getting into tests(7) so please bare with me. > > According to these test results (random google hit, but a recent run) > > https://www.netbsd.org/~martin/landisk-atf/last_atf.html#lib_libc_sys_t_clock_gettime_clock_getres > > calling clock_getres() on these two clocks is expected to fail. > It seems a bit silly to test that NetBSD does _not_ support a clock. > (Isn't clock_gettime() also expected to fail, if they do not exist? :-) > Wouldn't it make more sense to just remove these from the documentation? > > > There's also a PR in about CLOCK_MONOTONIC & what it actually represents: > > https://gnats.netbsd.org/60315 > > Thank you. I am in fact studying the clock_*() interface on various > unixes and what clocks they provide - see my naive take below. > > I guess my first question (please excuse the naivety) is where is > NetBSD's clock_get*() implemented? That must be these, right? > > /usr/src/sys/kern/kern_time.c:clock_getres1() > /usr/src/sys/kern/subr_time.c:clock_gettime1() > > These only support > > CLOCK_REALTIME > CLOCK_MONOTONIC > CLOCK_PROCESS_CPUTIME_ID > CLOCK_THREAD_CPUTIME_ID > > and set EINVAL otherwise. Index: lib/libc/sys/clock_settime.2 =================================================================== RCS file: /pub/NetBSD-CVS/src/lib/libc/sys/clock_settime.2,v retrieving revision 1.27 diff -u -p -r1.27 clock_settime.2 --- lib/libc/sys/clock_settime.2 27 Sep 2016 11:11:43 -0000 1.27 +++ lib/libc/sys/clock_settime.2 25 Jun 2026 13:40:54 -0000 @@ -101,12 +101,6 @@ fail with an error if it's the clock specified in a call to .Fn clock_settime . The origin of the clock is unspecified. -.It Dv CLOCK_VIRTUAL -identifies a clock that increments only when the CPU is running in -user mode on behalf of the calling process. -.It Dv CLOCK_PROF -identifies a clock that increments when the CPU is running in user -or kernel mode on behalf of the calling process. .It Dv CLOCK_PROCESS_CPUTIME_ID identifies a per process clock based on tick values. This clock is not settable. $ cat clock.c #include <stdint.h> #include <string.h> #include <stdio.h> #include <time.h> #include <err.h> void show(clockid_t id, char* name) { struct timespec ts; struct timespec cr; if (clock_gettime(id, &ts) == -1) err(1, NULL); if (clock_getres(id, &cr) == -1) err(1, NULL); printf("%s %10lld.%09ld s, %8ld ns resolution\n", name, ts.tv_sec, ts.tv_nsec, cr.tv_nsec); } int main(void) { #ifdef __APPLE__ show(CLOCK_REALTIME, "real time"); show(CLOCK_MONOTONIC, "monotonic"); show(CLOCK_UPTIME_RAW, "up time "); show(CLOCK_PROCESS_CPUTIME_ID, "proc time"); #elif __OpenBSD__ show(CLOCK_REALTIME, "real time"); show(CLOCK_MONOTONIC, "monotonic"); show(CLOCK_BOOTTIME, "boot time"); show(CLOCK_UPTIME, "up time "); show(CLOCK_PROCESS_CPUTIME_ID, "proc time"); #elif __FreeBSD__ show(CLOCK_REALTIME, "real time"); show(CLOCK_MONOTONIC, "monotonic"); show(CLOCK_BOOTTIME, "boot time"); show(CLOCK_UPTIME, "up time "); show(CLOCK_PROCESS_CPUTIME_ID, "proc time"); show(CLOCK_VIRTUAL, "virt time"); show(CLOCK_PROF, "prof time"); #elif __NetBSD__ show(CLOCK_REALTIME, "real time"); show(CLOCK_MONOTONIC, "monotonic"); show(CLOCK_PROCESS_CPUTIME_ID, "proc time"); #else show(CLOCK_REALTIME, "real time"); show(CLOCK_MONOTONIC, "monotonic"); show(CLOCK_BOOTTIME, "boot time"); show(CLOCK_PROCESS_CPUTIME_ID, "proc time"); #endif return 0; } $ cat timer.c #include <sys/time.h> #include <unistd.h> #include <stdio.h> #include <time.h> #include <err.h> void get(int which) { struct itimerval timer; if (getitimer(which, &timer) == -1) err(1, NULL); printf("timer %d: %lld.%03ld remains, resets to %lld.%03ld\n", which, (long long)timer.it_value.tv_sec, (long)timer.it_value.tv_usec, (long long)timer.it_interval.tv_sec, (long) timer.it_interval.tv_usec); } void set(int which, time_t sec, long usec) { struct itimerval timer = { { sec, usec}, { 1, 0 } }; if (setitimer(which, &timer, NULL) == -1) err(1, NULL); } int main(void) { unsigned s = 0; struct timespec len = { 3, 0 }; struct timespec rem; set(ITIMER_REAL, 1, 000); set(ITIMER_VIRTUAL, 1, 500); set(ITIMER_PROF, 2, 000); #ifdef __NetBSD__ set(ITIMER_MONOTONIC, 2, 500); #endif get(ITIMER_REAL); get(ITIMER_VIRTUAL); get(ITIMER_PROF); #ifdef __NetBSD__ get(ITIMER_MONOTONIC); #endif if ((s = sleep(2)) != 0) { /* This will be EINTR'd by a SIGALRM from ITIMER_REAL */ printf("sleep interrupted: %u seconds remaining", s); } if (nanosleep(&len, &rem) == -1) printf("sleep interrupted: %lld.%9ld remaining", (long long) rem.tv_sec, (long) rem.tv_nsec); return 0; }