1*d3aba683SRobert Mustacchi /*
2*d3aba683SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*d3aba683SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*d3aba683SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*d3aba683SRobert Mustacchi * 1.0 of the CDDL.
6*d3aba683SRobert Mustacchi *
7*d3aba683SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*d3aba683SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*d3aba683SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*d3aba683SRobert Mustacchi */
11*d3aba683SRobert Mustacchi
12*d3aba683SRobert Mustacchi /*
13*d3aba683SRobert Mustacchi * Copyright 2025 Oxide Computer Company
14*d3aba683SRobert Mustacchi */
15*d3aba683SRobert Mustacchi
16*d3aba683SRobert Mustacchi /*
17*d3aba683SRobert Mustacchi * Basic tests for C23 timespec_getres.
18*d3aba683SRobert Mustacchi */
19*d3aba683SRobert Mustacchi
20*d3aba683SRobert Mustacchi #include <stdlib.h>
21*d3aba683SRobert Mustacchi #include <time.h>
22*d3aba683SRobert Mustacchi #include <err.h>
23*d3aba683SRobert Mustacchi #include <sys/sysmacros.h>
24*d3aba683SRobert Mustacchi #include <limits.h>
25*d3aba683SRobert Mustacchi
26*d3aba683SRobert Mustacchi typedef struct {
27*d3aba683SRobert Mustacchi int rc_base;
28*d3aba683SRobert Mustacchi clockid_t rc_clock;
29*d3aba683SRobert Mustacchi const char *rc_desc;
30*d3aba683SRobert Mustacchi } res_cmp_t;
31*d3aba683SRobert Mustacchi
32*d3aba683SRobert Mustacchi static const res_cmp_t resolutions[] = {
33*d3aba683SRobert Mustacchi { TIME_UTC, CLOCK_REALTIME, "real time clock" },
34*d3aba683SRobert Mustacchi { TIME_MONOTONIC, CLOCK_HIGHRES, "highres clock" },
35*d3aba683SRobert Mustacchi { TIME_ACTIVE, CLOCK_PROCESS_CPUTIME_ID, "process clock" },
36*d3aba683SRobert Mustacchi { TIME_THREAD_ACTIVE, CLOCK_THREAD_CPUTIME_ID, "thread clock" },
37*d3aba683SRobert Mustacchi { TIME_THREAD_ACTIVE_USR, CLOCK_VIRTUAL, "thread (usr) clock" },
38*d3aba683SRobert Mustacchi };
39*d3aba683SRobert Mustacchi
40*d3aba683SRobert Mustacchi static const int bad_clocks[] = { 23, INT_MAX, INT_MIN, -42 };
41*d3aba683SRobert Mustacchi
42*d3aba683SRobert Mustacchi int
main(void)43*d3aba683SRobert Mustacchi main(void)
44*d3aba683SRobert Mustacchi {
45*d3aba683SRobert Mustacchi int ret = EXIT_SUCCESS;
46*d3aba683SRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(resolutions); i++) {
47*d3aba683SRobert Mustacchi struct timespec ts_c, ts_posix;
48*d3aba683SRobert Mustacchi int res;
49*d3aba683SRobert Mustacchi
50*d3aba683SRobert Mustacchi res = timespec_getres(&ts_c, resolutions[i].rc_base);
51*d3aba683SRobert Mustacchi if (res != resolutions[i].rc_base) {
52*d3aba683SRobert Mustacchi warnx("TEST FAILED: %s: timespec_getres did not "
53*d3aba683SRobert Mustacchi "return expected base %d, got %d",
54*d3aba683SRobert Mustacchi resolutions[i].rc_desc, resolutions[i].rc_base,
55*d3aba683SRobert Mustacchi res);
56*d3aba683SRobert Mustacchi ret = EXIT_FAILURE;
57*d3aba683SRobert Mustacchi continue;
58*d3aba683SRobert Mustacchi }
59*d3aba683SRobert Mustacchi
60*d3aba683SRobert Mustacchi if (clock_getres(resolutions[i].rc_clock, &ts_posix) != 0) {
61*d3aba683SRobert Mustacchi warn("TEST FAILED: %s: clock_getres for clock %d "
62*d3aba683SRobert Mustacchi "failed", resolutions[i].rc_desc,
63*d3aba683SRobert Mustacchi resolutions[i].rc_clock);
64*d3aba683SRobert Mustacchi ret = EXIT_FAILURE;
65*d3aba683SRobert Mustacchi continue;
66*d3aba683SRobert Mustacchi }
67*d3aba683SRobert Mustacchi
68*d3aba683SRobert Mustacchi if (ts_c.tv_sec != ts_posix.tv_sec ||
69*d3aba683SRobert Mustacchi ts_c.tv_nsec != ts_posix.tv_nsec) {
70*d3aba683SRobert Mustacchi warnx("TEST FAILED: %s: resolution mismatch: C has "
71*d3aba683SRobert Mustacchi "0x%lx/0x%lx, posix has 0x%lx/0x%lx",
72*d3aba683SRobert Mustacchi resolutions[i].rc_desc, ts_c.tv_sec, ts_c.tv_nsec,
73*d3aba683SRobert Mustacchi ts_posix.tv_sec, ts_posix.tv_nsec);
74*d3aba683SRobert Mustacchi ret = EXIT_FAILURE;
75*d3aba683SRobert Mustacchi continue;
76*d3aba683SRobert Mustacchi }
77*d3aba683SRobert Mustacchi
78*d3aba683SRobert Mustacchi (void) printf("TEST PASSED: %s: C and POSIX resoultions "
79*d3aba683SRobert Mustacchi "match\n", resolutions[i].rc_desc);
80*d3aba683SRobert Mustacchi }
81*d3aba683SRobert Mustacchi
82*d3aba683SRobert Mustacchi for (size_t i = 0; i < ARRAY_SIZE(bad_clocks); i++) {
83*d3aba683SRobert Mustacchi struct timespec ts;
84*d3aba683SRobert Mustacchi
85*d3aba683SRobert Mustacchi if (timespec_getres(&ts, bad_clocks[i]) != 0) {
86*d3aba683SRobert Mustacchi warnx("TEST FAILED: timespec_getres didn't fail "
87*d3aba683SRobert Mustacchi "with bad clock (%d)", bad_clocks[i]);
88*d3aba683SRobert Mustacchi ret = EXIT_FAILURE;
89*d3aba683SRobert Mustacchi } else {
90*d3aba683SRobert Mustacchi (void) printf("TEST PASSED: timespec_getres failed "
91*d3aba683SRobert Mustacchi "with bad clock (%d)\n", bad_clocks[i]);
92*d3aba683SRobert Mustacchi }
93*d3aba683SRobert Mustacchi }
94*d3aba683SRobert Mustacchi
95*d3aba683SRobert Mustacchi if (ret == EXIT_SUCCESS) {
96*d3aba683SRobert Mustacchi (void) printf("All tests passed successfully\n");
97*d3aba683SRobert Mustacchi }
98*d3aba683SRobert Mustacchi
99*d3aba683SRobert Mustacchi return (ret);
100*d3aba683SRobert Mustacchi }
101