xref: /xnu-12377.41.6/tests/mach_continuous_time.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828)
1*bbb1b6f9SApple OSS Distributions #include <mach/mach.h>
2*bbb1b6f9SApple OSS Distributions #include <mach/mach_time.h>
3*bbb1b6f9SApple OSS Distributions #include <mach/clock_types.h>
4*bbb1b6f9SApple OSS Distributions #include <sys/time.h>
5*bbb1b6f9SApple OSS Distributions #include <spawn.h>
6*bbb1b6f9SApple OSS Distributions #include <sys/wait.h>
7*bbb1b6f9SApple OSS Distributions #include <stdio.h>
8*bbb1b6f9SApple OSS Distributions #include <unistd.h>
9*bbb1b6f9SApple OSS Distributions #include <stdlib.h>
10*bbb1b6f9SApple OSS Distributions #include <time.h>
11*bbb1b6f9SApple OSS Distributions #include <errno.h>
12*bbb1b6f9SApple OSS Distributions 
13*bbb1b6f9SApple OSS Distributions #include <darwintest.h>
14*bbb1b6f9SApple OSS Distributions 
15*bbb1b6f9SApple OSS Distributions #if defined(__arm64__)
16*bbb1b6f9SApple OSS Distributions #define HAS_KERNEL_TIME_TRAPS
17*bbb1b6f9SApple OSS Distributions 
18*bbb1b6f9SApple OSS Distributions extern uint64_t mach_absolute_time_kernel(void);
19*bbb1b6f9SApple OSS Distributions extern uint64_t mach_continuous_time_kernel(void);
20*bbb1b6f9SApple OSS Distributions 
21*bbb1b6f9SApple OSS Distributions #endif
22*bbb1b6f9SApple OSS Distributions 
23*bbb1b6f9SApple OSS Distributions extern char **environ;
24*bbb1b6f9SApple OSS Distributions 
25*bbb1b6f9SApple OSS Distributions static const int64_t one_mil = 1000 * 1000;
26*bbb1b6f9SApple OSS Distributions 
27*bbb1b6f9SApple OSS Distributions #define to_ns(ticks) (((ticks) * tb_info.numer) / (tb_info.denom))
28*bbb1b6f9SApple OSS Distributions #define to_ms(ticks) (to_ns(ticks)/one_mil)
29*bbb1b6f9SApple OSS Distributions 
30*bbb1b6f9SApple OSS Distributions static mach_timebase_info_data_t tb_info;
31*bbb1b6f9SApple OSS Distributions 
32*bbb1b6f9SApple OSS Distributions static void
update(uint64_t * a,uint64_t * c)33*bbb1b6f9SApple OSS Distributions update(uint64_t *a, uint64_t *c)
34*bbb1b6f9SApple OSS Distributions {
35*bbb1b6f9SApple OSS Distributions 	mach_get_times(a, c, NULL);
36*bbb1b6f9SApple OSS Distributions }
37*bbb1b6f9SApple OSS Distributions 
38*bbb1b6f9SApple OSS Distributions T_DECL(mct_monotonic, "Testing mach_continuous_time returns sane, monotonic values",
39*bbb1b6f9SApple OSS Distributions     T_META_ALL_VALID_ARCHS(true), T_META_RUN_CONCURRENTLY(true))
40*bbb1b6f9SApple OSS Distributions {
41*bbb1b6f9SApple OSS Distributions 	mach_timebase_info(&tb_info);
42*bbb1b6f9SApple OSS Distributions #ifdef HAS_KERNEL_TIME_TRAPS
43*bbb1b6f9SApple OSS Distributions 	bool kernel = false;
44*bbb1b6f9SApple OSS Distributions #endif
45*bbb1b6f9SApple OSS Distributions 
46*bbb1b6f9SApple OSS Distributions 	volatile uint64_t multiple_test = to_ms(mach_continuous_time());
47*bbb1b6f9SApple OSS Distributions 	for (int i = 0; i < 20; i++) {
48*bbb1b6f9SApple OSS Distributions 		uint64_t tmp;
49*bbb1b6f9SApple OSS Distributions 		const char *test_type = "user";
50*bbb1b6f9SApple OSS Distributions #ifdef HAS_KERNEL_TIME_TRAPS
51*bbb1b6f9SApple OSS Distributions 		if (kernel) {
52*bbb1b6f9SApple OSS Distributions 			test_type = "kernel";
53*bbb1b6f9SApple OSS Distributions 			tmp = mach_continuous_time_kernel();
54*bbb1b6f9SApple OSS Distributions 		} else {
55*bbb1b6f9SApple OSS Distributions 			tmp = mach_continuous_time();
56*bbb1b6f9SApple OSS Distributions 		}
57*bbb1b6f9SApple OSS Distributions 		kernel = !kernel;
58*bbb1b6f9SApple OSS Distributions #else
59*bbb1b6f9SApple OSS Distributions 		tmp = mach_continuous_time();
60*bbb1b6f9SApple OSS Distributions #endif
61*bbb1b6f9SApple OSS Distributions 		tmp = to_ms(tmp);
62*bbb1b6f9SApple OSS Distributions 		T_ASSERT_GE(tmp, multiple_test, "mach_continuous_time (%s) must be monotonic", test_type);
63*bbb1b6f9SApple OSS Distributions 
64*bbb1b6f9SApple OSS Distributions 		// each successive call shouldn't be more than 100ms in the future
65*bbb1b6f9SApple OSS Distributions 		T_ASSERT_LE(tmp - multiple_test, 100ULL, "mach_continuous_time (%s) should not jump forward too fast", test_type);
66*bbb1b6f9SApple OSS Distributions 
67*bbb1b6f9SApple OSS Distributions 		multiple_test = tmp;
68*bbb1b6f9SApple OSS Distributions 	}
69*bbb1b6f9SApple OSS Distributions }
70*bbb1b6f9SApple OSS Distributions 
71*bbb1b6f9SApple OSS Distributions T_DECL(mat_monotonic, "Testing mach_absolute_time returns sane, monotonic values",
72*bbb1b6f9SApple OSS Distributions     T_META_ALL_VALID_ARCHS(true), T_META_RUN_CONCURRENTLY(true))
73*bbb1b6f9SApple OSS Distributions {
74*bbb1b6f9SApple OSS Distributions 	mach_timebase_info(&tb_info);
75*bbb1b6f9SApple OSS Distributions #ifdef HAS_KERNEL_TIME_TRAPS
76*bbb1b6f9SApple OSS Distributions 	bool kernel = false;
77*bbb1b6f9SApple OSS Distributions #endif
78*bbb1b6f9SApple OSS Distributions 
79*bbb1b6f9SApple OSS Distributions 	volatile uint64_t multiple_test = to_ms(mach_absolute_time());
80*bbb1b6f9SApple OSS Distributions 	for (int i = 0; i < 20; i++) {
81*bbb1b6f9SApple OSS Distributions 		uint64_t tmp;
82*bbb1b6f9SApple OSS Distributions 		const char *test_type = "user";
83*bbb1b6f9SApple OSS Distributions #ifdef HAS_KERNEL_TIME_TRAPS
84*bbb1b6f9SApple OSS Distributions 		if (kernel) {
85*bbb1b6f9SApple OSS Distributions 			test_type = "kernel";
86*bbb1b6f9SApple OSS Distributions 			tmp = mach_absolute_time_kernel();
87*bbb1b6f9SApple OSS Distributions 		} else {
88*bbb1b6f9SApple OSS Distributions 			tmp = mach_absolute_time();
89*bbb1b6f9SApple OSS Distributions 		}
90*bbb1b6f9SApple OSS Distributions 		kernel = !kernel;
91*bbb1b6f9SApple OSS Distributions #endif
92*bbb1b6f9SApple OSS Distributions 		tmp = mach_absolute_time();
93*bbb1b6f9SApple OSS Distributions 		tmp = to_ms(tmp);
94*bbb1b6f9SApple OSS Distributions 		T_ASSERT_GE(tmp, multiple_test, "mach_absolute_time (%s) must be monotonic", test_type);
95*bbb1b6f9SApple OSS Distributions 
96*bbb1b6f9SApple OSS Distributions 		// each successive call shouldn't be more than 100ms in the future
97*bbb1b6f9SApple OSS Distributions 		T_ASSERT_LE(tmp - multiple_test, 100ULL, "mach_absolute_time (%s) should not jump forward too fast", test_type);
98*bbb1b6f9SApple OSS Distributions 
99*bbb1b6f9SApple OSS Distributions 		multiple_test = tmp;
100*bbb1b6f9SApple OSS Distributions 	}
101*bbb1b6f9SApple OSS Distributions }
102*bbb1b6f9SApple OSS Distributions 
103*bbb1b6f9SApple OSS Distributions T_DECL(mct_pause, "Testing mach_continuous_time and mach_absolute_time don't diverge",
104*bbb1b6f9SApple OSS Distributions     T_META_RUN_CONCURRENTLY(true))
105*bbb1b6f9SApple OSS Distributions {
106*bbb1b6f9SApple OSS Distributions 	mach_timebase_info(&tb_info);
107*bbb1b6f9SApple OSS Distributions 
108*bbb1b6f9SApple OSS Distributions 	uint64_t abs_now;
109*bbb1b6f9SApple OSS Distributions 	uint64_t cnt_now;
110*bbb1b6f9SApple OSS Distributions 	int before_diff, after_diff;
111*bbb1b6f9SApple OSS Distributions 
112*bbb1b6f9SApple OSS Distributions 	update(&abs_now, &cnt_now);
113*bbb1b6f9SApple OSS Distributions 	before_diff = (int)(to_ms(cnt_now) - to_ms(abs_now));
114*bbb1b6f9SApple OSS Distributions 
115*bbb1b6f9SApple OSS Distributions 	sleep(1);
116*bbb1b6f9SApple OSS Distributions 
117*bbb1b6f9SApple OSS Distributions 	update(&abs_now, &cnt_now);
118*bbb1b6f9SApple OSS Distributions 	after_diff = (int)(to_ms(cnt_now) - to_ms(abs_now));
119*bbb1b6f9SApple OSS Distributions 
120*bbb1b6f9SApple OSS Distributions 	T_ASSERT_LE(abs(after_diff - before_diff), 1, "mach_continuous_time and mach_absolute_time should not diverge");
121*bbb1b6f9SApple OSS Distributions }
122*bbb1b6f9SApple OSS Distributions 
123*bbb1b6f9SApple OSS Distributions #ifdef HAS_KERNEL_TIME_TRAPS
124*bbb1b6f9SApple OSS Distributions static void
update_kern(uint64_t * abs,uint64_t * cont)125*bbb1b6f9SApple OSS Distributions update_kern(uint64_t *abs, uint64_t *cont)
126*bbb1b6f9SApple OSS Distributions {
127*bbb1b6f9SApple OSS Distributions 	uint64_t abs1, abs2, cont1, cont2;
128*bbb1b6f9SApple OSS Distributions 	do {
129*bbb1b6f9SApple OSS Distributions 		abs1 = mach_absolute_time_kernel();
130*bbb1b6f9SApple OSS Distributions 		cont1 = mach_continuous_time_kernel();
131*bbb1b6f9SApple OSS Distributions 		abs2 = mach_absolute_time_kernel();
132*bbb1b6f9SApple OSS Distributions 		cont2 = mach_continuous_time_kernel();
133*bbb1b6f9SApple OSS Distributions 	} while (to_ms(abs2 - abs1) || to_ms(cont2 - cont1));
134*bbb1b6f9SApple OSS Distributions 	*abs = abs2;
135*bbb1b6f9SApple OSS Distributions 	*cont = cont2;
136*bbb1b6f9SApple OSS Distributions }
137*bbb1b6f9SApple OSS Distributions #endif
138*bbb1b6f9SApple OSS Distributions 
139*bbb1b6f9SApple OSS Distributions #ifdef HAS_KERNEL_TIME_TRAPS
140*bbb1b6f9SApple OSS Distributions T_DECL(mct_pause_kern, "Testing kernel mach_continuous_time and mach_absolute_time don't diverge",
141*bbb1b6f9SApple OSS Distributions     T_META_RUN_CONCURRENTLY(true))
142*bbb1b6f9SApple OSS Distributions {
143*bbb1b6f9SApple OSS Distributions 	mach_timebase_info(&tb_info);
144*bbb1b6f9SApple OSS Distributions 
145*bbb1b6f9SApple OSS Distributions 	uint64_t abs_now;
146*bbb1b6f9SApple OSS Distributions 	uint64_t cnt_now;
147*bbb1b6f9SApple OSS Distributions 	int before_diff, after_diff;
148*bbb1b6f9SApple OSS Distributions 
149*bbb1b6f9SApple OSS Distributions 	update_kern(&abs_now, &cnt_now);
150*bbb1b6f9SApple OSS Distributions 	before_diff = (int)(to_ms(cnt_now) - to_ms(abs_now));
151*bbb1b6f9SApple OSS Distributions 
152*bbb1b6f9SApple OSS Distributions 	sleep(1);
153*bbb1b6f9SApple OSS Distributions 
154*bbb1b6f9SApple OSS Distributions 	update_kern(&abs_now, &cnt_now);
155*bbb1b6f9SApple OSS Distributions 	after_diff = (int)(to_ms(cnt_now) - to_ms(abs_now));
156*bbb1b6f9SApple OSS Distributions 
157*bbb1b6f9SApple OSS Distributions 	T_ASSERT_LE(abs(after_diff - before_diff), 1, "mach_continuous_time_kernel and mach_absolute_time_kernel should not diverge");
158*bbb1b6f9SApple OSS Distributions }
159*bbb1b6f9SApple OSS Distributions #endif
160*bbb1b6f9SApple OSS Distributions 
161*bbb1b6f9SApple OSS Distributions T_DECL(mct_sleep, "Testing mach_continuous_time behavior over system sleep"){
162*bbb1b6f9SApple OSS Distributions #ifndef MCT_SLEEP_TEST
163*bbb1b6f9SApple OSS Distributions 	T_SKIP("Skipping test that sleeps the device; compile with MCT_SLEEP_TEST define to enable.");
164*bbb1b6f9SApple OSS Distributions #endif
165*bbb1b6f9SApple OSS Distributions 
166*bbb1b6f9SApple OSS Distributions 	mach_timebase_info(&tb_info);
167*bbb1b6f9SApple OSS Distributions 
168*bbb1b6f9SApple OSS Distributions 	uint64_t abs_now;
169*bbb1b6f9SApple OSS Distributions 	uint64_t cnt_now;
170*bbb1b6f9SApple OSS Distributions 	int before_diff, after_diff = 0;
171*bbb1b6f9SApple OSS Distributions 
172*bbb1b6f9SApple OSS Distributions 	T_LOG("Testing mach_continuous_time is ~5 seconds ahead of mach_absolute_time after 5 second sleep");
173*bbb1b6f9SApple OSS Distributions 	update(&abs_now, &cnt_now);
174*bbb1b6f9SApple OSS Distributions 	before_diff = (int)(to_ms(cnt_now) - to_ms(abs_now));
175*bbb1b6f9SApple OSS Distributions 
176*bbb1b6f9SApple OSS Distributions 	// performs:
177*bbb1b6f9SApple OSS Distributions 	// pmset relative wake 5
178*bbb1b6f9SApple OSS Distributions 	// pmset sleepnow
179*bbb1b6f9SApple OSS Distributions 
180*bbb1b6f9SApple OSS Distributions 	pid_t pid;
181*bbb1b6f9SApple OSS Distributions 	int spawn_ret = 0;
182*bbb1b6f9SApple OSS Distributions 	time_t before_sleep = time(NULL);
183*bbb1b6f9SApple OSS Distributions 	int ct_ms_before_sleep = (int)to_ms(cnt_now);
184*bbb1b6f9SApple OSS Distributions 	int ab_ms_before_sleep = (int)to_ms(abs_now);
185*bbb1b6f9SApple OSS Distributions 
186*bbb1b6f9SApple OSS Distributions 	char *const pmset1_args[] = {"/usr/bin/pmset", "relative", "wake", "5", NULL};
187*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_ZERO((spawn_ret = posix_spawn(&pid, pmset1_args[0], NULL, NULL, pmset1_args, environ)), NULL);
188*bbb1b6f9SApple OSS Distributions 
189*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ(waitpid(pid, &spawn_ret, 0), pid, "waitpid failed");
190*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ(spawn_ret, 0, "pmset relative wait 5 failed");
191*bbb1b6f9SApple OSS Distributions 
192*bbb1b6f9SApple OSS Distributions 	char *const pmset2_args[] = {"/usr/bin/pmset", "sleepnow", NULL};
193*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_ZERO((spawn_ret = posix_spawn(&pid, pmset2_args[0], NULL, NULL, pmset2_args, environ)), NULL);
194*bbb1b6f9SApple OSS Distributions 
195*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ(waitpid(pid, &spawn_ret, 0), pid, "waitpid failed");
196*bbb1b6f9SApple OSS Distributions 	T_ASSERT_EQ(spawn_ret, 0, "pmset relative wait 5 failed");
197*bbb1b6f9SApple OSS Distributions 
198*bbb1b6f9SApple OSS Distributions 	// wait for device to sleep (up to 30 seconds)
199*bbb1b6f9SApple OSS Distributions 	for (int i = 0; i < 30; i++) {
200*bbb1b6f9SApple OSS Distributions 		update(&abs_now, &cnt_now);
201*bbb1b6f9SApple OSS Distributions 		after_diff = (int)(to_ms(cnt_now) - to_ms(abs_now));
202*bbb1b6f9SApple OSS Distributions 
203*bbb1b6f9SApple OSS Distributions 		// on OSX, there's enough latency between calls to MCT and MAT
204*bbb1b6f9SApple OSS Distributions 		// when the system is going down for sleep for values to diverge a few ms
205*bbb1b6f9SApple OSS Distributions 		if (abs(before_diff - after_diff) > 2) {
206*bbb1b6f9SApple OSS Distributions 			break;
207*bbb1b6f9SApple OSS Distributions 		}
208*bbb1b6f9SApple OSS Distributions 
209*bbb1b6f9SApple OSS Distributions 		sleep(1);
210*bbb1b6f9SApple OSS Distributions 		T_LOG("waited %d seconds for sleep...", i + 1);
211*bbb1b6f9SApple OSS Distributions 	}
212*bbb1b6f9SApple OSS Distributions 
213*bbb1b6f9SApple OSS Distributions 	if ((after_diff - before_diff) < 4000) {
214*bbb1b6f9SApple OSS Distributions 		T_LOG("Device slept for less than 4 seconds, did it really sleep? (%d ms change between abs and cont)",
215*bbb1b6f9SApple OSS Distributions 		    after_diff - before_diff);
216*bbb1b6f9SApple OSS Distributions 	}
217*bbb1b6f9SApple OSS Distributions 
218*bbb1b6f9SApple OSS Distributions 	time_t after_sleep = time(NULL);
219*bbb1b6f9SApple OSS Distributions 
220*bbb1b6f9SApple OSS Distributions 	int cal_sleep_diff  = (int)(double)difftime(after_sleep, before_sleep);
221*bbb1b6f9SApple OSS Distributions 	int ct_sleep_diff = ((int)to_ms(cnt_now) - ct_ms_before_sleep) / 1000;
222*bbb1b6f9SApple OSS Distributions 	int ab_sleep_diff = ((int)to_ms(abs_now) - ab_ms_before_sleep) / 1000;
223*bbb1b6f9SApple OSS Distributions 
224*bbb1b6f9SApple OSS Distributions 	T_LOG("Calendar progressed: %d sec; continuous time progressed: %d sec; absolute time progressed %d sec",
225*bbb1b6f9SApple OSS Distributions 	    cal_sleep_diff, ct_sleep_diff, ab_sleep_diff);
226*bbb1b6f9SApple OSS Distributions 
227*bbb1b6f9SApple OSS Distributions 	T_ASSERT_LE(abs(ct_sleep_diff - cal_sleep_diff), 2,
228*bbb1b6f9SApple OSS Distributions 	    "continuous time should progress at ~ same rate as calendar");
229*bbb1b6f9SApple OSS Distributions }
230*bbb1b6f9SApple OSS Distributions 
231*bbb1b6f9SApple OSS Distributions T_DECL(mct_settimeofday, "Testing mach_continuous_time behavior over settimeofday"){
232*bbb1b6f9SApple OSS Distributions 	if (geteuid() != 0) {
233*bbb1b6f9SApple OSS Distributions 		T_SKIP("The settimeofday() test requires root privileges to run.");
234*bbb1b6f9SApple OSS Distributions 	}
235*bbb1b6f9SApple OSS Distributions 	mach_timebase_info(&tb_info);
236*bbb1b6f9SApple OSS Distributions 
237*bbb1b6f9SApple OSS Distributions 	struct timeval saved_tv;
238*bbb1b6f9SApple OSS Distributions 	struct timezone saved_tz;
239*bbb1b6f9SApple OSS Distributions 	int before, after;
240*bbb1b6f9SApple OSS Distributions 
241*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_ZERO(gettimeofday(&saved_tv, &saved_tz), NULL);
242*bbb1b6f9SApple OSS Distributions 
243*bbb1b6f9SApple OSS Distributions 	struct timeval forward_tv = saved_tv;
244*bbb1b6f9SApple OSS Distributions 	// move time forward by two minutes, ensure mach_continuous_time keeps
245*bbb1b6f9SApple OSS Distributions 	// chugging along with mach_absolute_time
246*bbb1b6f9SApple OSS Distributions 	forward_tv.tv_sec += 2 * 60;
247*bbb1b6f9SApple OSS Distributions 
248*bbb1b6f9SApple OSS Distributions 	before = (int)to_ms(mach_continuous_time());
249*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_ZERO(settimeofday(&forward_tv, &saved_tz), NULL);
250*bbb1b6f9SApple OSS Distributions 
251*bbb1b6f9SApple OSS Distributions 	after = (int)to_ms(mach_continuous_time());
252*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_ZERO(settimeofday(&saved_tv, &saved_tz), NULL);
253*bbb1b6f9SApple OSS Distributions 
254*bbb1b6f9SApple OSS Distributions 	T_ASSERT_LT(abs(before - after), 1000, "mach_continuous_time should not jump more than 1s");
255*bbb1b6f9SApple OSS Distributions }
256*bbb1b6f9SApple OSS Distributions 
257*bbb1b6f9SApple OSS Distributions #ifdef HAS_KERNEL_TIME_TRAPS
258*bbb1b6f9SApple OSS Distributions T_DECL(mct_settimeofday_kern, "Testing kernel mach_continuous_time behavior over settimeofday"){
259*bbb1b6f9SApple OSS Distributions 	if (geteuid() != 0) {
260*bbb1b6f9SApple OSS Distributions 		T_SKIP("The settimeofday() test requires root privileges to run.");
261*bbb1b6f9SApple OSS Distributions 	}
262*bbb1b6f9SApple OSS Distributions 	mach_timebase_info(&tb_info);
263*bbb1b6f9SApple OSS Distributions 
264*bbb1b6f9SApple OSS Distributions 	struct timeval saved_tv;
265*bbb1b6f9SApple OSS Distributions 	struct timezone saved_tz;
266*bbb1b6f9SApple OSS Distributions 	int before, after;
267*bbb1b6f9SApple OSS Distributions 
268*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_ZERO(gettimeofday(&saved_tv, &saved_tz), NULL);
269*bbb1b6f9SApple OSS Distributions 
270*bbb1b6f9SApple OSS Distributions 	struct timeval forward_tv = saved_tv;
271*bbb1b6f9SApple OSS Distributions 	// move time forward by two minutes, ensure mach_continuous_time keeps
272*bbb1b6f9SApple OSS Distributions 	// chugging along with mach_absolute_time
273*bbb1b6f9SApple OSS Distributions 	forward_tv.tv_sec += 2 * 60;
274*bbb1b6f9SApple OSS Distributions 
275*bbb1b6f9SApple OSS Distributions 	before = (int)to_ms(mach_continuous_time_kernel());
276*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_ZERO(settimeofday(&forward_tv, &saved_tz), NULL);
277*bbb1b6f9SApple OSS Distributions 
278*bbb1b6f9SApple OSS Distributions 	after = (int)to_ms(mach_continuous_time_kernel());
279*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_ZERO(settimeofday(&saved_tv, &saved_tz), NULL);
280*bbb1b6f9SApple OSS Distributions 
281*bbb1b6f9SApple OSS Distributions 	T_ASSERT_LT(abs(before - after), 1000, "mach_continuous_time_kernel should not jump more than 1s");
282*bbb1b6f9SApple OSS Distributions }
283*bbb1b6f9SApple OSS Distributions #endif
284*bbb1b6f9SApple OSS Distributions 
285*bbb1b6f9SApple OSS Distributions T_DECL(mct_aproximate, "Testing mach_continuous_approximate_time()",
286*bbb1b6f9SApple OSS Distributions     T_META_ALL_VALID_ARCHS(true), T_META_RUN_CONCURRENTLY(true))
287*bbb1b6f9SApple OSS Distributions {
288*bbb1b6f9SApple OSS Distributions 	mach_timebase_info(&tb_info);
289*bbb1b6f9SApple OSS Distributions 
290*bbb1b6f9SApple OSS Distributions 	uint64_t absolute = to_ns(mach_continuous_time());
291*bbb1b6f9SApple OSS Distributions 	uint64_t approximate = to_ns(mach_continuous_approximate_time());
292*bbb1b6f9SApple OSS Distributions 
293*bbb1b6f9SApple OSS Distributions 	T_EXPECT_LE(llabs((long long)absolute - (long long)approximate), (long long)(25 * NSEC_PER_MSEC), NULL);
294*bbb1b6f9SApple OSS Distributions }
295*bbb1b6f9SApple OSS Distributions 
296*bbb1b6f9SApple OSS Distributions T_DECL(mach_time_perf, "mach_time performance") {
297*bbb1b6f9SApple OSS Distributions 	{
298*bbb1b6f9SApple OSS Distributions 		dt_stat_time_t s = dt_stat_time_create("mach_absolute_time");
T_STAT_MEASURE_LOOP(s)299*bbb1b6f9SApple OSS Distributions 		T_STAT_MEASURE_LOOP(s) {
300*bbb1b6f9SApple OSS Distributions 			uint64_t t;
301*bbb1b6f9SApple OSS Distributions 			t = mach_absolute_time();
302*bbb1b6f9SApple OSS Distributions 		}
303*bbb1b6f9SApple OSS Distributions 		dt_stat_finalize(s);
304*bbb1b6f9SApple OSS Distributions 	}
305*bbb1b6f9SApple OSS Distributions 	{
306*bbb1b6f9SApple OSS Distributions 		dt_stat_time_t s = dt_stat_time_create("mach_continuous_time");
T_STAT_MEASURE_LOOP(s)307*bbb1b6f9SApple OSS Distributions 		T_STAT_MEASURE_LOOP(s) {
308*bbb1b6f9SApple OSS Distributions 			uint64_t t;
309*bbb1b6f9SApple OSS Distributions 			t = mach_continuous_time();
310*bbb1b6f9SApple OSS Distributions 		}
311*bbb1b6f9SApple OSS Distributions 		dt_stat_finalize(s);
312*bbb1b6f9SApple OSS Distributions 	}
313*bbb1b6f9SApple OSS Distributions }
314*bbb1b6f9SApple OSS Distributions 
315*bbb1b6f9SApple OSS Distributions T_DECL(mach_time_perf_instructions, "instructions retired for mach_time", T_META_TYPE_PERF, T_META_ASROOT(YES)) {
316*bbb1b6f9SApple OSS Distributions 	{
317*bbb1b6f9SApple OSS Distributions 		dt_stat_thread_instructions_t s = dt_stat_thread_instructions_create("mach_absolute_time");
T_STAT_MEASURE_LOOP(s)318*bbb1b6f9SApple OSS Distributions 		T_STAT_MEASURE_LOOP(s) {
319*bbb1b6f9SApple OSS Distributions 			uint64_t t;
320*bbb1b6f9SApple OSS Distributions 			t = mach_absolute_time();
321*bbb1b6f9SApple OSS Distributions 		}
322*bbb1b6f9SApple OSS Distributions 		dt_stat_finalize(s);
323*bbb1b6f9SApple OSS Distributions 	}
324*bbb1b6f9SApple OSS Distributions 	{
325*bbb1b6f9SApple OSS Distributions 		dt_stat_thread_instructions_t s = dt_stat_thread_instructions_create("mach_continuous_time");
T_STAT_MEASURE_LOOP(s)326*bbb1b6f9SApple OSS Distributions 		T_STAT_MEASURE_LOOP(s) {
327*bbb1b6f9SApple OSS Distributions 			uint64_t t;
328*bbb1b6f9SApple OSS Distributions 			t = mach_continuous_time();
329*bbb1b6f9SApple OSS Distributions 		}
330*bbb1b6f9SApple OSS Distributions 		dt_stat_finalize(s);
331*bbb1b6f9SApple OSS Distributions 	}
332*bbb1b6f9SApple OSS Distributions }
333*bbb1b6f9SApple OSS Distributions 
334*bbb1b6f9SApple OSS Distributions #ifdef HAS_KERNEL_TIME_TRAPS
335*bbb1b6f9SApple OSS Distributions T_DECL(mach_time_perf_kern, "kernel mach_time performance") {
336*bbb1b6f9SApple OSS Distributions 	{
337*bbb1b6f9SApple OSS Distributions 		dt_stat_time_t s = dt_stat_time_create("mach_absolute_time_kernel");
T_STAT_MEASURE_LOOP(s)338*bbb1b6f9SApple OSS Distributions 		T_STAT_MEASURE_LOOP(s) {
339*bbb1b6f9SApple OSS Distributions 			uint64_t t;
340*bbb1b6f9SApple OSS Distributions 			t = mach_absolute_time_kernel();
341*bbb1b6f9SApple OSS Distributions 		}
342*bbb1b6f9SApple OSS Distributions 		dt_stat_finalize(s);
343*bbb1b6f9SApple OSS Distributions 	}
344*bbb1b6f9SApple OSS Distributions 	{
345*bbb1b6f9SApple OSS Distributions 		dt_stat_time_t s = dt_stat_time_create("mach_continuous_time_kernel");
T_STAT_MEASURE_LOOP(s)346*bbb1b6f9SApple OSS Distributions 		T_STAT_MEASURE_LOOP(s) {
347*bbb1b6f9SApple OSS Distributions 			uint64_t t;
348*bbb1b6f9SApple OSS Distributions 			t = mach_continuous_time_kernel();
349*bbb1b6f9SApple OSS Distributions 		}
350*bbb1b6f9SApple OSS Distributions 		dt_stat_finalize(s);
351*bbb1b6f9SApple OSS Distributions 	}
352*bbb1b6f9SApple OSS Distributions }
353*bbb1b6f9SApple OSS Distributions 
354*bbb1b6f9SApple OSS Distributions T_DECL(mach_time_perf_instructions_kern, "instructions retired for kernel mach_time", T_META_TYPE_PERF, T_META_ASROOT(YES)) {
355*bbb1b6f9SApple OSS Distributions 	{
356*bbb1b6f9SApple OSS Distributions 		dt_stat_thread_instructions_t s = dt_stat_thread_instructions_create("mach_absolute_time_kernel");
T_STAT_MEASURE_LOOP(s)357*bbb1b6f9SApple OSS Distributions 		T_STAT_MEASURE_LOOP(s) {
358*bbb1b6f9SApple OSS Distributions 			uint64_t t;
359*bbb1b6f9SApple OSS Distributions 			t = mach_absolute_time_kernel();
360*bbb1b6f9SApple OSS Distributions 		}
361*bbb1b6f9SApple OSS Distributions 		dt_stat_finalize(s);
362*bbb1b6f9SApple OSS Distributions 	}
363*bbb1b6f9SApple OSS Distributions 	{
364*bbb1b6f9SApple OSS Distributions 		dt_stat_thread_instructions_t s = dt_stat_thread_instructions_create("mach_continuous_time_kernel");
T_STAT_MEASURE_LOOP(s)365*bbb1b6f9SApple OSS Distributions 		T_STAT_MEASURE_LOOP(s) {
366*bbb1b6f9SApple OSS Distributions 			uint64_t t;
367*bbb1b6f9SApple OSS Distributions 			t = mach_continuous_time_kernel();
368*bbb1b6f9SApple OSS Distributions 		}
369*bbb1b6f9SApple OSS Distributions 		dt_stat_finalize(s);
370*bbb1b6f9SApple OSS Distributions 	}
371*bbb1b6f9SApple OSS Distributions }
372*bbb1b6f9SApple OSS Distributions #endif
373