1 #include <darwintest.h>
2 #include <darwintest_utils.h>
3 #include <dispatch/dispatch.h>
4 #include <perfdata/perfdata.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdbool.h>
8 #include <errno.h>
9 #include "sched_test_utils.h"
10 #include "test_utils.h"
11
12 T_GLOBAL_META(
13 T_META_TAG_PERF,
14 T_META_RUN_CONCURRENTLY(false),
15 /* <rdar://137716223> */
16 T_META_BOOTARGS_SET("enable_skstsct=1 cpu-dynamic-cluster-power-down=0"),
17 T_META_CHECK_LEAKS(false),
18 T_META_ASROOT(true),
19 T_META_REQUIRES_SYSCTL_EQ("kern.hv_vmm_present", 0),
20 T_META_NAMESPACE("xnu.scheduler"),
21 T_META_RADAR_COMPONENT_NAME("xnu"),
22 T_META_RADAR_COMPONENT_VERSION("scheduler"),
23 T_META_OWNER("m_zinn"),
24 T_META_TAG_VM_NOT_ELIGIBLE
25 );
26
27 static void
log_cmd(char ** cmd)28 log_cmd(char **cmd)
29 {
30 #define MAX_CMD_STR 1024
31 char cmd_str[MAX_CMD_STR] = "";
32 char *s;
33
34 while ((s = *cmd) != NULL) {
35 strlcat(cmd_str, s, MAX_CMD_STR);
36 strlcat(cmd_str, " ", MAX_CMD_STR);
37 cmd++;
38 }
39 T_LOG("%s\n", cmd_str);
40 }
41
42 static void
run_zn(char * name,char ** cmd,int argc,char * const argv[])43 run_zn(char *name, char **cmd, int argc, char *const argv[])
44 {
45 log_cmd(cmd);
46
47 trace_handle_t trace = begin_collect_trace_fmt(COLLECT_TRACE_FLAG_DISABLE_SYSCALLS | COLLECT_TRACE_FLAG_DISABLE_CLUTCH, argc, argv, name);
48
49 __block bool test_failed = true;
50 __block bool test_skipped = false;
51 __block dispatch_semaphore_t stdout_finished_sem = dispatch_semaphore_create(0);
52 T_QUIET; T_ASSERT_NOTNULL(stdout_finished_sem, "dispatch_semaphore_create()");
53
54 dt_launch_pipe_t *pipes = NULL;
55 pid_t test_pid;
56 test_pid = dt_launch_tool_pipe(cmd, false, &pipes, NULL, NULL, NULL, NULL);
57 T_QUIET; T_ASSERT_NE(test_pid, 0, "dt_launch_tool_pipe() failed unexpectedly with errno %d", errno);
58 T_QUIET; T_ASSERT_NOTNULL(pipes, "dt_launch_tool_pipe returned non-null pipes");
59
60 dispatch_block_t cleanup_handler =
61 ^{ dispatch_semaphore_signal(stdout_finished_sem); };
62
63 dt_pipe_data_handler_t stdout_handler = ^bool (char *data, __unused size_t data_size, __unused dt_pipe_data_handler_context_t *context) {
64 T_LOG("%s", data);
65 if (strstr(data, "TEST PASSED")) {
66 test_failed = false;
67 return true;
68 }
69 if (strstr(data, "TEST FAILED")) {
70 test_failed = true;
71 return true;
72 }
73 if (strstr(data, "TEST SKIPPED")) {
74 test_skipped = true;
75 return true;
76 }
77 return false;
78 };
79
80 dt_pipe_data_handler_t stderr_handler = ^bool (char *data, __unused size_t data_size, __unused dt_pipe_data_handler_context_t *context) {
81 T_LOG("%s", data);
82 return false;
83 };
84
85 dispatch_source_t stdout_reader = dt_create_dispatch_file_reader(pipes->pipe_out[0], BUFFER_PATTERN_LINE, stdout_handler, cleanup_handler, NULL);
86 T_QUIET; T_ASSERT_NOTNULL(stdout_reader, "create darwintest dispatch file reader for stdout");
87
88 dispatch_source_t stderr_reader = dt_create_dispatch_file_reader(pipes->pipe_err[0], BUFFER_PATTERN_LINE, stderr_handler, ^{}, NULL);
89 T_QUIET; T_ASSERT_NOTNULL(stderr_reader, "create darwintest dispatch file reader for stderr");
90
91 /* Wait for zero-to-n to exit, and check its return value. */
92 int exitstatus;
93 if (!dt_waitpid(test_pid, &exitstatus, NULL, 0) || exitstatus != 0) {
94 T_FAIL("zero-to-n exitstatus=%d\n", exitstatus);
95 }
96
97 /* Test exited, end the trace. */
98 end_collect_trace(trace);
99
100 /* Wait for the readers to finish. */
101 intptr_t rv = dispatch_semaphore_wait(stdout_finished_sem, dispatch_time(DISPATCH_TIME_NOW, 30 * NSEC_PER_SEC));
102 T_QUIET; T_ASSERT_EQ((uint64_t) rv, 0ULL, "zn should finish within 30 seconds");
103
104 /* Free the pipes. */
105 free(pipes);
106
107 if (test_skipped) {
108 T_SKIP("%s", name);
109 } else if (test_failed) {
110 T_FAIL("%s", name);
111 } else {
112 T_PASS("%s", name);
113 }
114
115 T_END;
116 }
117
118 T_DECL(zn_rt, "Schedule 1 RT thread per performance core, and test max latency",
119 XNU_T_META_SOC_SPECIFIC)
120 {
121 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
122 "0", "broadcast-single-sem", "realtime", "1000",
123 "--spin-time", "200000",
124 "--spin-all",
125 "--test-rt",
126 #if defined(__arm64__)
127 "--bind", "P", /* <rdar://137716223> */
128 "--trace", "500000",
129 #elif defined(__x86_64__)
130 "--trace", "2000000",
131 #endif
132 NULL};
133
134 run_zn("zn_rt", cmd, argc, argv);
135 }
136
137 T_DECL(zn_rt_ival, "Schedule 1 RT thread per performance core, and test max latency",
138 XNU_T_META_SOC_SPECIFIC,
139 T_META_ENABLED(false) /* TODO: Enable once <rdar://145756951> is fixed. */)
140 {
141 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
142 "0", "broadcast-single-sem", "realtime", "1000",
143 "--spin-time", "200000",
144 "--spin-all",
145 "--test-rt",
146 "--rt-interval",
147 #if defined(__x86_64__)
148 "--trace", "2000000",
149 #else
150 "--trace", "500000",
151 #endif
152 NULL};
153
154 run_zn("zn_rt_ival", cmd, argc, argv);
155 }
156
157 T_DECL(zn_rt_ival_ll, "Schedule 1 RT thread per performance core, and test max latency",
158 XNU_T_META_SOC_SPECIFIC)
159 {
160 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
161 "0", "broadcast-single-sem", "realtime", "1000",
162 "--spin-time", "200000",
163 "--spin-all",
164 "--test-rt",
165 "--rt-interval",
166 "--rt-ll",
167 #if defined(__x86_64__)
168 "--trace", "2000000",
169 #else
170 "--trace", "500000",
171 #endif
172 NULL};
173
174 run_zn("zn_rt_ival_ll", cmd, argc, argv);
175 }
176
177 T_DECL(zn_rt_smt, "Schedule 1 RT thread per primary core, verify that the secondaries are idle iff the RT threads are running",
178 T_META_ENABLED(TARGET_CPU_X86_64))
179 {
180 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
181 "0", "broadcast-single-sem", "realtime", "1000",
182 "--spin-time", "200000",
183 "--spin-all",
184 "--churn-pri", "4",
185 "--test-rt-smt",
186 "--trace", "2000000",
187 NULL};
188
189 run_zn("zn_rt_smt", cmd, argc, argv);
190 }
191
192 T_DECL(zn_rt_ival_smt, "Schedule 1 RT thread per primary core, verify that the secondaries are idle iff the RT threads are running",
193 T_META_ENABLED(TARGET_CPU_X86_64))
194 {
195 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
196 "0", "broadcast-single-sem", "realtime", "1000",
197 "--spin-time", "200000",
198 "--spin-all",
199 "--churn-pri", "4",
200 "--test-rt-smt",
201 "--rt-interval",
202 "--trace", "2000000",
203 NULL};
204
205 run_zn("zn_rt_ival_smt", cmd, argc, argv);
206 }
207
208 T_DECL(zn_rt_avoid0, "Schedule 1 RT thread per primary core except for CPU 0",
209 T_META_ENABLED(TARGET_CPU_X86_64))
210 {
211 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
212 "0", "broadcast-single-sem", "realtime", "1000",
213 "--spin-time", "200000",
214 "--spin-all",
215 "--test-rt-avoid0",
216 "--trace", "2000000",
217 NULL};
218
219 run_zn("zn_rt_avoid0", cmd, argc, argv);
220 }
221
222 T_DECL(zn_rt_ival_avoid0, "Schedule 1 RT thread per primary core except for CPU 0",
223 T_META_ENABLED(TARGET_CPU_X86_64))
224 {
225 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
226 "0", "broadcast-single-sem", "realtime", "1000",
227 "--spin-time", "200000",
228 "--spin-all",
229 "--test-rt-avoid0",
230 "--rt-interval",
231 "--trace", "2000000",
232 NULL};
233
234 run_zn("zn_rt_ival_avoid0", cmd, argc, argv);
235 }
236
237 T_DECL(zn_rt_apt, "Emulate AVID Pro Tools with default latency deadlines")
238 {
239 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
240 "0", "chain", "realtime", "1000",
241 "--extra-thread-count", "-3",
242 "--spin-time", "200000",
243 "--spin-all",
244 "--churn-pri", "31", "--churn-random",
245 "--test-rt",
246 #if defined(__arm64__)
247 "--bind", "P", /* <rdar://137716223> */
248 "--trace", "500000",
249 #elif defined(__x86_64__)
250 "--trace", "2000000",
251 #endif
252 NULL};
253
254 run_zn("zn_rt_apt", cmd, argc, argv);
255 }
256
257 T_DECL(zn_rt_ival_apt, "Emulate AVID Pro Tools with default latency deadlines",
258 T_META_ENABLED(false) /* TODO: Enable once <rdar://145756951> is fixed. */)
259 {
260 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
261 "0", "chain", "realtime", "1000",
262 "--extra-thread-count", "-3",
263 "--spin-time", "200000",
264 "--spin-all",
265 "--churn-pri", "31", "--churn-random",
266 "--test-rt",
267 "--rt-interval",
268 #if defined(__x86_64__)
269 "--trace", "2000000",
270 #else
271 "--trace", "500000",
272 #endif
273 NULL};
274
275 run_zn("zn_rt_ival_apt", cmd, argc, argv);
276 }
277
278 T_DECL(zn_rt_apt_ll, "Emulate AVID Pro Tools with low latency deadlines",
279 XNU_T_META_SOC_SPECIFIC)
280 {
281 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
282 "0", "chain", "realtime", "1000",
283 "--extra-thread-count", "-3",
284 "--spin-time", "200000",
285 "--spin-all",
286 "--churn-pri", "31", "--churn-random",
287 "--test-rt",
288 "--rt-ll",
289 #if defined(__arm64__)
290 "--bind", "P", /* <rdar://137716223> */
291 #endif /* __arm64__*/
292 "--trace", "500000",
293 NULL};
294
295 run_zn("zn_rt_apt_ll", cmd, argc, argv);
296 }
297
298 T_DECL(zn_rt_ival_apt_ll, "Emulate AVID Pro Tools with low latency deadlines",
299 XNU_T_META_SOC_SPECIFIC)
300 {
301 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
302 "0", "chain", "realtime", "1000",
303 "--extra-thread-count", "-3",
304 "--spin-time", "200000",
305 "--spin-all",
306 "--churn-pri", "31", "--churn-random",
307 "--test-rt",
308 "--rt-ll",
309 "--rt-interval",
310 "--trace", "500000",
311 NULL};
312
313 run_zn("zn_rt_ival_apt_ll", cmd, argc, argv);
314 }
315
316 T_DECL(zn_rt_edf, "Test max latency of earliest deadline RT threads in the presence of later deadline threads",
317 XNU_T_META_SOC_SPECIFIC)
318 {
319 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
320 "0", "broadcast-single-sem", "realtime", "1000",
321 "--extra-thread-count", "-1",
322 "--spin-time", "200000",
323 "--spin-all",
324 "--rt-churn",
325 "--test-rt",
326 #if defined(__arm64__)
327 "--bind", "P", /* <rdar://137716223> */
328 "--trace", "500000",
329 #elif defined(__x86_64__)
330 "--trace", "2000000",
331 #endif
332 NULL};
333
334 run_zn("zn_rt_edf", cmd, argc, argv);
335 }
336
337 T_DECL(zn_rt_ival_edf, "Test max latency of earliest deadline RT threads in the presence of later deadline threads",
338 XNU_T_META_SOC_SPECIFIC)
339 {
340 char *cmd[] = {"/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
341 "0", "broadcast-single-sem", "realtime", "1000",
342 "--extra-thread-count", "-1",
343 "--spin-time", "200000",
344 "--spin-all",
345 "--rt-churn",
346 "--test-rt",
347 "--rt-ll", /* TODO: remove low-latency constraint once <rdar://145756951> is fixed */
348 "--rt-interval",
349 #if defined(__x86_64__)
350 "--trace", "2000000",
351 #else
352 "--trace", "500000",
353 #endif
354 NULL};
355
356 run_zn("zn_rt_ival_edf", cmd, argc, argv);
357 }
358
359