1*dea9f5e6SRobert Mustacchi /*
2*dea9f5e6SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*dea9f5e6SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*dea9f5e6SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*dea9f5e6SRobert Mustacchi * 1.0 of the CDDL.
6*dea9f5e6SRobert Mustacchi *
7*dea9f5e6SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*dea9f5e6SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*dea9f5e6SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*dea9f5e6SRobert Mustacchi */
11*dea9f5e6SRobert Mustacchi
12*dea9f5e6SRobert Mustacchi /*
13*dea9f5e6SRobert Mustacchi * Copyright 2021 Oxide Comptuer Company
14*dea9f5e6SRobert Mustacchi */
15*dea9f5e6SRobert Mustacchi
16*dea9f5e6SRobert Mustacchi /*
17*dea9f5e6SRobert Mustacchi * Test a bunch of basics around clocks.
18*dea9f5e6SRobert Mustacchi */
19*dea9f5e6SRobert Mustacchi
20*dea9f5e6SRobert Mustacchi #include <time.h>
21*dea9f5e6SRobert Mustacchi #include <err.h>
22*dea9f5e6SRobert Mustacchi #include <stdlib.h>
23*dea9f5e6SRobert Mustacchi #include <libproc.h>
24*dea9f5e6SRobert Mustacchi #include <thread.h>
25*dea9f5e6SRobert Mustacchi #include <sys/sysmacros.h>
26*dea9f5e6SRobert Mustacchi
27*dea9f5e6SRobert Mustacchi typedef hrtime_t (*clock_alttime_f)(void);
28*dea9f5e6SRobert Mustacchi
29*dea9f5e6SRobert Mustacchi typedef struct clock_gettime_test {
30*dea9f5e6SRobert Mustacchi clockid_t cgt_clock;
31*dea9f5e6SRobert Mustacchi clock_alttime_f cgt_alt;
32*dea9f5e6SRobert Mustacchi const char *cgt_name;
33*dea9f5e6SRobert Mustacchi } clock_gettime_test_t;
34*dea9f5e6SRobert Mustacchi
35*dea9f5e6SRobert Mustacchi typedef struct clock_gettime_thr_arg {
36*dea9f5e6SRobert Mustacchi hrtime_t cgta_usr;
37*dea9f5e6SRobert Mustacchi hrtime_t cgta_usrsys;
38*dea9f5e6SRobert Mustacchi } clock_gettime_thr_arg_t;
39*dea9f5e6SRobert Mustacchi
40*dea9f5e6SRobert Mustacchi static hrtime_t
clock_ts2hrt(const timespec_t * tsp)41*dea9f5e6SRobert Mustacchi clock_ts2hrt(const timespec_t *tsp)
42*dea9f5e6SRobert Mustacchi {
43*dea9f5e6SRobert Mustacchi return ((tsp->tv_sec * NANOSEC) + tsp->tv_nsec);
44*dea9f5e6SRobert Mustacchi }
45*dea9f5e6SRobert Mustacchi
46*dea9f5e6SRobert Mustacchi static hrtime_t
clock_gettime_proc(void)47*dea9f5e6SRobert Mustacchi clock_gettime_proc(void)
48*dea9f5e6SRobert Mustacchi {
49*dea9f5e6SRobert Mustacchi psinfo_t ps;
50*dea9f5e6SRobert Mustacchi
51*dea9f5e6SRobert Mustacchi if (proc_get_psinfo(getpid(), &ps) != 0) {
52*dea9f5e6SRobert Mustacchi warn("failed to get psinfo for process");
53*dea9f5e6SRobert Mustacchi return (0);
54*dea9f5e6SRobert Mustacchi }
55*dea9f5e6SRobert Mustacchi
56*dea9f5e6SRobert Mustacchi return (clock_ts2hrt(&ps.pr_time));
57*dea9f5e6SRobert Mustacchi }
58*dea9f5e6SRobert Mustacchi
59*dea9f5e6SRobert Mustacchi static hrtime_t
clock_gettime_thread(void)60*dea9f5e6SRobert Mustacchi clock_gettime_thread(void)
61*dea9f5e6SRobert Mustacchi {
62*dea9f5e6SRobert Mustacchi lwpsinfo_t lwpsinfo;
63*dea9f5e6SRobert Mustacchi
64*dea9f5e6SRobert Mustacchi if (proc_get_lwpsinfo(getpid(), thr_self(), &lwpsinfo) != 0) {
65*dea9f5e6SRobert Mustacchi warn("failed to get lwpsinfo for thread %u", thr_self());
66*dea9f5e6SRobert Mustacchi return (0);
67*dea9f5e6SRobert Mustacchi }
68*dea9f5e6SRobert Mustacchi
69*dea9f5e6SRobert Mustacchi return (clock_ts2hrt(&lwpsinfo.pr_time));
70*dea9f5e6SRobert Mustacchi }
71*dea9f5e6SRobert Mustacchi
72*dea9f5e6SRobert Mustacchi clock_gettime_test_t clock_tests[] = {
73*dea9f5e6SRobert Mustacchi { CLOCK_HIGHRES, gethrtime, "highres" },
74*dea9f5e6SRobert Mustacchi { CLOCK_VIRTUAL, gethrvtime, "virtual" },
75*dea9f5e6SRobert Mustacchi { CLOCK_THREAD_CPUTIME_ID, clock_gettime_thread, "thread_cputime" },
76*dea9f5e6SRobert Mustacchi { CLOCK_PROCESS_CPUTIME_ID, clock_gettime_proc, "proc_cputime" }
77*dea9f5e6SRobert Mustacchi };
78*dea9f5e6SRobert Mustacchi
79*dea9f5e6SRobert Mustacchi /*
80*dea9f5e6SRobert Mustacchi * Do a series of reads of the clock from clock_gettime and its secondary
81*dea9f5e6SRobert Mustacchi * source. Make sure that we always see increasing values.
82*dea9f5e6SRobert Mustacchi */
83*dea9f5e6SRobert Mustacchi static boolean_t
clock_test(clock_gettime_test_t * test)84*dea9f5e6SRobert Mustacchi clock_test(clock_gettime_test_t *test)
85*dea9f5e6SRobert Mustacchi {
86*dea9f5e6SRobert Mustacchi hrtime_t hrt0, hrt1, hrt2, convts0, convts1;
87*dea9f5e6SRobert Mustacchi struct timespec ts0, ts1;
88*dea9f5e6SRobert Mustacchi boolean_t ret = B_TRUE;
89*dea9f5e6SRobert Mustacchi
90*dea9f5e6SRobert Mustacchi if (clock_gettime(test->cgt_clock, &ts0) != 0) {
91*dea9f5e6SRobert Mustacchi warn("failed to get clock %u", test->cgt_clock);
92*dea9f5e6SRobert Mustacchi return (B_FALSE);
93*dea9f5e6SRobert Mustacchi }
94*dea9f5e6SRobert Mustacchi
95*dea9f5e6SRobert Mustacchi hrt0 = test->cgt_alt();
96*dea9f5e6SRobert Mustacchi hrt1 = test->cgt_alt();
97*dea9f5e6SRobert Mustacchi
98*dea9f5e6SRobert Mustacchi if (clock_gettime(test->cgt_clock, &ts1) != 0) {
99*dea9f5e6SRobert Mustacchi warn("failed to get clock %u", test->cgt_clock);
100*dea9f5e6SRobert Mustacchi return (B_FALSE);
101*dea9f5e6SRobert Mustacchi }
102*dea9f5e6SRobert Mustacchi
103*dea9f5e6SRobert Mustacchi hrt2 = test->cgt_alt();
104*dea9f5e6SRobert Mustacchi
105*dea9f5e6SRobert Mustacchi convts0 = clock_ts2hrt(&ts0);
106*dea9f5e6SRobert Mustacchi convts1 = clock_ts2hrt(&ts1);
107*dea9f5e6SRobert Mustacchi
108*dea9f5e6SRobert Mustacchi if (convts0 > hrt0) {
109*dea9f5e6SRobert Mustacchi warnx("clock %s traveled backwards, clock_gettime ahead of "
110*dea9f5e6SRobert Mustacchi "later alternate: clock_gettime %lld, alternate: %lld",
111*dea9f5e6SRobert Mustacchi test->cgt_name, convts0, hrt0);
112*dea9f5e6SRobert Mustacchi ret = B_FALSE;
113*dea9f5e6SRobert Mustacchi }
114*dea9f5e6SRobert Mustacchi
115*dea9f5e6SRobert Mustacchi if (hrt0 > hrt1) {
116*dea9f5e6SRobert Mustacchi warnx("clock %s traveled backwards, alternate ahead of "
117*dea9f5e6SRobert Mustacchi "later alternate: first alternate %lld, later "
118*dea9f5e6SRobert Mustacchi "alternate: %lld", test->cgt_name, hrt0, hrt1);
119*dea9f5e6SRobert Mustacchi ret = B_FALSE;
120*dea9f5e6SRobert Mustacchi }
121*dea9f5e6SRobert Mustacchi
122*dea9f5e6SRobert Mustacchi if (convts1 > hrt2) {
123*dea9f5e6SRobert Mustacchi warnx("clock %s traveled backwards, clock_gettime ahead of "
124*dea9f5e6SRobert Mustacchi "later alternate: clock_gettime %lld, alternate: %lld",
125*dea9f5e6SRobert Mustacchi test->cgt_name, convts1, hrt2);
126*dea9f5e6SRobert Mustacchi ret = B_FALSE;
127*dea9f5e6SRobert Mustacchi }
128*dea9f5e6SRobert Mustacchi
129*dea9f5e6SRobert Mustacchi if (hrt1 > hrt2) {
130*dea9f5e6SRobert Mustacchi warnx("clock %s traveled backwards, alternate ahead of "
131*dea9f5e6SRobert Mustacchi "later alternate: first alternate %lld, later "
132*dea9f5e6SRobert Mustacchi "alternate: %lld", test->cgt_name, hrt1, hrt2);
133*dea9f5e6SRobert Mustacchi ret = B_FALSE;
134*dea9f5e6SRobert Mustacchi }
135*dea9f5e6SRobert Mustacchi
136*dea9f5e6SRobert Mustacchi if (convts0 > convts1) {
137*dea9f5e6SRobert Mustacchi warnx("clock %s traveled backwards, clock_gettime ahead of "
138*dea9f5e6SRobert Mustacchi "later clock_gettime: first clock_gettime %lld, later "
139*dea9f5e6SRobert Mustacchi "clock_gettime: %lld", test->cgt_name, convts0, convts1);
140*dea9f5e6SRobert Mustacchi ret = B_FALSE;
141*dea9f5e6SRobert Mustacchi }
142*dea9f5e6SRobert Mustacchi
143*dea9f5e6SRobert Mustacchi return (ret);
144*dea9f5e6SRobert Mustacchi }
145*dea9f5e6SRobert Mustacchi
146*dea9f5e6SRobert Mustacchi static void *
clock_test_thr(void * arg)147*dea9f5e6SRobert Mustacchi clock_test_thr(void *arg)
148*dea9f5e6SRobert Mustacchi {
149*dea9f5e6SRobert Mustacchi boolean_t ret = B_TRUE;
150*dea9f5e6SRobert Mustacchi
151*dea9f5e6SRobert Mustacchi for (uint_t i = 0; i < ARRAY_SIZE(clock_tests); i++) {
152*dea9f5e6SRobert Mustacchi boolean_t rval = clock_test(&clock_tests[i]);
153*dea9f5e6SRobert Mustacchi if (!rval) {
154*dea9f5e6SRobert Mustacchi ret = B_FALSE;
155*dea9f5e6SRobert Mustacchi }
156*dea9f5e6SRobert Mustacchi
157*dea9f5e6SRobert Mustacchi (void) printf("TEST %s: basic %s usage and interleaving%s\n",
158*dea9f5e6SRobert Mustacchi rval ? "PASSED" : "FAILED", clock_tests[i].cgt_name,
159*dea9f5e6SRobert Mustacchi thr_self() == 1 ? "" : " (in thread)");
160*dea9f5e6SRobert Mustacchi }
161*dea9f5e6SRobert Mustacchi
162*dea9f5e6SRobert Mustacchi return ((void *)(uintptr_t)ret);
163*dea9f5e6SRobert Mustacchi }
164*dea9f5e6SRobert Mustacchi
165*dea9f5e6SRobert Mustacchi static void *
clock_test_cputime_thr(void * arg)166*dea9f5e6SRobert Mustacchi clock_test_cputime_thr(void *arg)
167*dea9f5e6SRobert Mustacchi {
168*dea9f5e6SRobert Mustacchi struct timespec ts;
169*dea9f5e6SRobert Mustacchi clock_gettime_thr_arg_t *cp = arg;
170*dea9f5e6SRobert Mustacchi
171*dea9f5e6SRobert Mustacchi if (clock_gettime(CLOCK_VIRTUAL, &ts) != 0) {
172*dea9f5e6SRobert Mustacchi warn("failed to get clock CLOCK_VIRTUAL");
173*dea9f5e6SRobert Mustacchi cp->cgta_usr = 0;
174*dea9f5e6SRobert Mustacchi } else {
175*dea9f5e6SRobert Mustacchi cp->cgta_usr = clock_ts2hrt(&ts);
176*dea9f5e6SRobert Mustacchi }
177*dea9f5e6SRobert Mustacchi
178*dea9f5e6SRobert Mustacchi if (clock_gettime(CLOCK_VIRTUAL, &ts) != 0) {
179*dea9f5e6SRobert Mustacchi warn("failed to get clock CLOCK_VIRTUAL");
180*dea9f5e6SRobert Mustacchi cp->cgta_usrsys = 0;
181*dea9f5e6SRobert Mustacchi } else {
182*dea9f5e6SRobert Mustacchi cp->cgta_usrsys = clock_ts2hrt(&ts);
183*dea9f5e6SRobert Mustacchi }
184*dea9f5e6SRobert Mustacchi
185*dea9f5e6SRobert Mustacchi return (NULL);
186*dea9f5e6SRobert Mustacchi }
187*dea9f5e6SRobert Mustacchi
188*dea9f5e6SRobert Mustacchi /*
189*dea9f5e6SRobert Mustacchi * Compare the value of CLOCK_THREAD_CPUTIME_ID between a new thread and the
190*dea9f5e6SRobert Mustacchi * main thread.
191*dea9f5e6SRobert Mustacchi */
192*dea9f5e6SRobert Mustacchi static boolean_t
clock_test_thread_clock(void)193*dea9f5e6SRobert Mustacchi clock_test_thread_clock(void)
194*dea9f5e6SRobert Mustacchi {
195*dea9f5e6SRobert Mustacchi thread_t thr;
196*dea9f5e6SRobert Mustacchi clock_gettime_thr_arg_t arg;
197*dea9f5e6SRobert Mustacchi hrtime_t hrt;
198*dea9f5e6SRobert Mustacchi struct timespec ts;
199*dea9f5e6SRobert Mustacchi boolean_t ret = B_TRUE;
200*dea9f5e6SRobert Mustacchi
201*dea9f5e6SRobert Mustacchi if (thr_create(NULL, 0, clock_test_cputime_thr, &arg, 0, &thr) != 0) {
202*dea9f5e6SRobert Mustacchi errx(EXIT_FAILURE, "failed to create thread to run basic "
203*dea9f5e6SRobert Mustacchi "tests!");
204*dea9f5e6SRobert Mustacchi }
205*dea9f5e6SRobert Mustacchi
206*dea9f5e6SRobert Mustacchi if (thr_join(thr, NULL, NULL) != 0) {
207*dea9f5e6SRobert Mustacchi errx(EXIT_FAILURE, "failed to join to thread that ran basic "
208*dea9f5e6SRobert Mustacchi "tests");
209*dea9f5e6SRobert Mustacchi }
210*dea9f5e6SRobert Mustacchi
211*dea9f5e6SRobert Mustacchi if (clock_gettime(CLOCK_VIRTUAL, &ts) != 0) {
212*dea9f5e6SRobert Mustacchi warn("failed to get clock CLOCK_VIRTUAL");
213*dea9f5e6SRobert Mustacchi return (B_FALSE);
214*dea9f5e6SRobert Mustacchi }
215*dea9f5e6SRobert Mustacchi
216*dea9f5e6SRobert Mustacchi hrt = clock_ts2hrt(&ts);
217*dea9f5e6SRobert Mustacchi if (arg.cgta_usr > hrt) {
218*dea9f5e6SRobert Mustacchi warnx("new thread %u somehow had higher CLOCK_VIRTUAL time "
219*dea9f5e6SRobert Mustacchi "than main thread: new thread: %lld, main thread: %lld",
220*dea9f5e6SRobert Mustacchi thr, hrt, arg.cgta_usr);
221*dea9f5e6SRobert Mustacchi ret = B_FALSE;
222*dea9f5e6SRobert Mustacchi }
223*dea9f5e6SRobert Mustacchi
224*dea9f5e6SRobert Mustacchi if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0) {
225*dea9f5e6SRobert Mustacchi warn("failed to get clock CLOCK_THREAD_CPUTIME_ID");
226*dea9f5e6SRobert Mustacchi return (B_FALSE);
227*dea9f5e6SRobert Mustacchi }
228*dea9f5e6SRobert Mustacchi
229*dea9f5e6SRobert Mustacchi hrt = clock_ts2hrt(&ts);
230*dea9f5e6SRobert Mustacchi if (arg.cgta_usr > hrt) {
231*dea9f5e6SRobert Mustacchi warnx("new thread %u somehow had higher "
232*dea9f5e6SRobert Mustacchi "CLOCK_THREAD_CPUTIME_ID time than main thread: new "
233*dea9f5e6SRobert Mustacchi "thread: %lld, main thread: %lld", thr, hrt, arg.cgta_usr);
234*dea9f5e6SRobert Mustacchi ret = B_FALSE;
235*dea9f5e6SRobert Mustacchi }
236*dea9f5e6SRobert Mustacchi
237*dea9f5e6SRobert Mustacchi return (ret);
238*dea9f5e6SRobert Mustacchi }
239*dea9f5e6SRobert Mustacchi
240*dea9f5e6SRobert Mustacchi /*
241*dea9f5e6SRobert Mustacchi * This test is a little circumspect. It's basically going to argue that all the
242*dea9f5e6SRobert Mustacchi * time we spent doing kernel actions should be larger than the additional bit
243*dea9f5e6SRobert Mustacchi * of user time to make a subsequent system call. That seems probably
244*dea9f5e6SRobert Mustacchi * reasonable given everything we've done; however, there's no way to feel like
245*dea9f5e6SRobert Mustacchi * it's not possibly going to lead to false positives. If so, then just delete
246*dea9f5e6SRobert Mustacchi * this.
247*dea9f5e6SRobert Mustacchi */
248*dea9f5e6SRobert Mustacchi static boolean_t
clock_test_thread_sys(void)249*dea9f5e6SRobert Mustacchi clock_test_thread_sys(void)
250*dea9f5e6SRobert Mustacchi {
251*dea9f5e6SRobert Mustacchi struct timespec usr, sys;
252*dea9f5e6SRobert Mustacchi hrtime_t hrtusr, hrtsys;
253*dea9f5e6SRobert Mustacchi
254*dea9f5e6SRobert Mustacchi if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &sys) != 0) {
255*dea9f5e6SRobert Mustacchi warn("failed to get clock CLOCK_THREAD_CPUTIME_ID");
256*dea9f5e6SRobert Mustacchi return (B_FALSE);
257*dea9f5e6SRobert Mustacchi }
258*dea9f5e6SRobert Mustacchi
259*dea9f5e6SRobert Mustacchi if (clock_gettime(CLOCK_VIRTUAL, &usr) != 0) {
260*dea9f5e6SRobert Mustacchi warn("failed to get clock CLOCK_VIRTUAL");
261*dea9f5e6SRobert Mustacchi return (B_FALSE);
262*dea9f5e6SRobert Mustacchi }
263*dea9f5e6SRobert Mustacchi
264*dea9f5e6SRobert Mustacchi hrtusr = clock_ts2hrt(&usr);
265*dea9f5e6SRobert Mustacchi hrtsys = clock_ts2hrt(&sys);
266*dea9f5e6SRobert Mustacchi
267*dea9f5e6SRobert Mustacchi if (hrtusr > hrtsys) {
268*dea9f5e6SRobert Mustacchi warnx("CLOCK_VIRTUAL was greater than CLOCK_THREAD_CPUTIME_ID: "
269*dea9f5e6SRobert Mustacchi "usr time: %lld, usr/sys time: %lld (this may be a race)",
270*dea9f5e6SRobert Mustacchi hrtusr, hrtsys);
271*dea9f5e6SRobert Mustacchi return (B_FALSE);
272*dea9f5e6SRobert Mustacchi }
273*dea9f5e6SRobert Mustacchi
274*dea9f5e6SRobert Mustacchi return (B_TRUE);
275*dea9f5e6SRobert Mustacchi }
276*dea9f5e6SRobert Mustacchi
277*dea9f5e6SRobert Mustacchi /*
278*dea9f5e6SRobert Mustacchi * This is similar to clock_test_thread_sys(), but using the process clock and
279*dea9f5e6SRobert Mustacchi * the thread clock. This is circumspect for similar reasons.
280*dea9f5e6SRobert Mustacchi */
281*dea9f5e6SRobert Mustacchi static boolean_t
clock_test_thread_proc(void)282*dea9f5e6SRobert Mustacchi clock_test_thread_proc(void)
283*dea9f5e6SRobert Mustacchi {
284*dea9f5e6SRobert Mustacchi struct timespec thr, proc;
285*dea9f5e6SRobert Mustacchi hrtime_t hrtthr, hrtproc;
286*dea9f5e6SRobert Mustacchi
287*dea9f5e6SRobert Mustacchi if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &proc) != 0) {
288*dea9f5e6SRobert Mustacchi warn("failed to get clock CLOCK_VIRTUAL");
289*dea9f5e6SRobert Mustacchi return (B_FALSE);
290*dea9f5e6SRobert Mustacchi }
291*dea9f5e6SRobert Mustacchi
292*dea9f5e6SRobert Mustacchi if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &thr) != 0) {
293*dea9f5e6SRobert Mustacchi warn("failed to get clock CLOCK_THREAD_CPUTIME_ID");
294*dea9f5e6SRobert Mustacchi return (B_FALSE);
295*dea9f5e6SRobert Mustacchi }
296*dea9f5e6SRobert Mustacchi
297*dea9f5e6SRobert Mustacchi hrtthr = clock_ts2hrt(&thr);
298*dea9f5e6SRobert Mustacchi hrtproc = clock_ts2hrt(&proc);
299*dea9f5e6SRobert Mustacchi
300*dea9f5e6SRobert Mustacchi if (hrtthr > hrtproc) {
301*dea9f5e6SRobert Mustacchi warnx("CLOCK_THRAD_CPUTIME_ID was greater than "
302*dea9f5e6SRobert Mustacchi "CLOCK_PROCESS_CPUTIME_ID: thr time: %lld, proc time: %lld "
303*dea9f5e6SRobert Mustacchi "(this may be a race)", hrtthr, hrtproc);
304*dea9f5e6SRobert Mustacchi return (B_FALSE);
305*dea9f5e6SRobert Mustacchi }
306*dea9f5e6SRobert Mustacchi
307*dea9f5e6SRobert Mustacchi return (B_TRUE);
308*dea9f5e6SRobert Mustacchi }
309*dea9f5e6SRobert Mustacchi
310*dea9f5e6SRobert Mustacchi int
main(void)311*dea9f5e6SRobert Mustacchi main(void)
312*dea9f5e6SRobert Mustacchi {
313*dea9f5e6SRobert Mustacchi int ret = EXIT_SUCCESS;
314*dea9f5e6SRobert Mustacchi void *thr_ret;
315*dea9f5e6SRobert Mustacchi thread_t thr;
316*dea9f5e6SRobert Mustacchi boolean_t bval;
317*dea9f5e6SRobert Mustacchi
318*dea9f5e6SRobert Mustacchi thr_ret = clock_test_thr(NULL);
319*dea9f5e6SRobert Mustacchi if (!(boolean_t)(uintptr_t)thr_ret) {
320*dea9f5e6SRobert Mustacchi ret = EXIT_FAILURE;
321*dea9f5e6SRobert Mustacchi }
322*dea9f5e6SRobert Mustacchi
323*dea9f5e6SRobert Mustacchi if (thr_create(NULL, 0, clock_test_thr, NULL, 0, &thr) != 0) {
324*dea9f5e6SRobert Mustacchi errx(EXIT_FAILURE, "failed to create thread to run basic "
325*dea9f5e6SRobert Mustacchi "tests!");
326*dea9f5e6SRobert Mustacchi }
327*dea9f5e6SRobert Mustacchi
328*dea9f5e6SRobert Mustacchi if (thr_join(thr, NULL, &thr_ret) != 0) {
329*dea9f5e6SRobert Mustacchi errx(EXIT_FAILURE, "failed to join to thread that ran basic "
330*dea9f5e6SRobert Mustacchi "tests");
331*dea9f5e6SRobert Mustacchi }
332*dea9f5e6SRobert Mustacchi
333*dea9f5e6SRobert Mustacchi if (!(boolean_t)(uintptr_t)thr_ret) {
334*dea9f5e6SRobert Mustacchi ret = EXIT_FAILURE;
335*dea9f5e6SRobert Mustacchi }
336*dea9f5e6SRobert Mustacchi
337*dea9f5e6SRobert Mustacchi bval = clock_test_thread_clock();
338*dea9f5e6SRobert Mustacchi (void) printf("TEST %s: comparing CLOCK_THREAD_CPUTIME_ID and "
339*dea9f5e6SRobert Mustacchi "CLOCK_VIRTUAL between threads\n", bval ? "PASSED" : "FAILED");
340*dea9f5e6SRobert Mustacchi
341*dea9f5e6SRobert Mustacchi bval = clock_test_thread_sys();
342*dea9f5e6SRobert Mustacchi (void) printf("TEST %s: comparing CLOCK_THREAD_CPUTIME_ID and "
343*dea9f5e6SRobert Mustacchi "CLOCK_VIRTUAL\n", bval ? "PASSED" : "FAILED");
344*dea9f5e6SRobert Mustacchi
345*dea9f5e6SRobert Mustacchi
346*dea9f5e6SRobert Mustacchi bval = clock_test_thread_proc();
347*dea9f5e6SRobert Mustacchi (void) printf("TEST %s: comparing CLOCK_THREAD_CPUTIME_ID and "
348*dea9f5e6SRobert Mustacchi "CLOCK_PROCESS_CPUTIME_ID\n", bval ? "PASSED" : "FAILED");
349*dea9f5e6SRobert Mustacchi /*
350*dea9f5e6SRobert Mustacchi * XXX CLOCK_THREAD_CPUTIME_ID > CLOCK_VIRTUAL for same thread?
351*dea9f5e6SRobert Mustacchi * XXX CLOCK_PROCESS_CPUTIME_ID > CLOCK_THREAD_CPUTIME_ID
352*dea9f5e6SRobert Mustacchi */
353*dea9f5e6SRobert Mustacchi
354*dea9f5e6SRobert Mustacchi return (ret);
355*dea9f5e6SRobert Mustacchi }
356