1 #include <darwintest.h>
2 #include <darwintest_utils.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <stdbool.h>
6 #include <errno.h>
7
8 #if defined(__arm64__)
9 T_GLOBAL_META(
10 T_META_TAG_PERF,
11 T_META_RUN_CONCURRENTLY(false),
12 T_META_BOOTARGS_SET("enable_skstsct=1"),
13 T_META_CHECK_LEAKS(false),
14 T_META_ASROOT(true),
15 T_META_REQUIRES_SYSCTL_EQ("kern.hv_vmm_present", 0),
16 T_META_RADAR_COMPONENT_NAME("xnu"),
17 T_META_RADAR_COMPONENT_VERSION("scheduler"),
18 T_META_OWNER("ngamble")
19 );
20 #else
21 T_GLOBAL_META(
22 T_META_TAG_PERF,
23 T_META_RUN_CONCURRENTLY(false),
24 T_META_CHECK_LEAKS(false),
25 T_META_ASROOT(true),
26 T_META_REQUIRES_SYSCTL_EQ("kern.hv_vmm_present", 0),
27 T_META_RADAR_COMPONENT_NAME("xnu"),
28 T_META_RADAR_COMPONENT_VERSION("scheduler"),
29 T_META_OWNER("ngamble")
30 );
31 #endif
32
33 static void
log_cmd(char ** cmd)34 log_cmd(char **cmd)
35 {
36 #define MAX_CMD_STR 1024
37 char cmd_str[MAX_CMD_STR] = "";
38 char *s;
39
40 while ((s = *cmd) != NULL) {
41 strlcat(cmd_str, s, MAX_CMD_STR);
42 strlcat(cmd_str, " ", MAX_CMD_STR);
43 cmd++;
44 }
45 T_LOG("%s\n", cmd_str);
46 }
47
48 static void
run_zn(char * name,char ** cmd)49 run_zn(char *name, char **cmd)
50 {
51 char tracefile_path[MAXPATHLEN] = "zn.artrace";
52 snprintf(tracefile_path, MAXPATHLEN, "%s.artrace", name);
53
54 int ret = dt_resultfile(tracefile_path, sizeof(tracefile_path));
55 if (ret) {
56 T_ASSERT_FAIL("get file path for trace file failed with errno %d", errno);
57 }
58
59 cmd[3] = tracefile_path;
60 log_cmd(cmd);
61
62 __block bool test_failed = true;
63 __block bool test_skipped = false;
64
65 pid_t test_pid;
66 test_pid = dt_launch_tool_pipe(cmd, false, NULL, ^bool (__unused char *data, __unused size_t data_size, __unused dt_pipe_data_handler_context_t *context) {
67 T_LOG("%s", data);
68 if (strstr(data, "TEST PASSED")) {
69 test_failed = false;
70 }
71 if (strstr(data, "TEST FAILED")) {
72 test_failed = true;
73 }
74 if (strstr(data, "TEST SKIPPED")) {
75 test_skipped = true;
76 }
77 return false;
78 }, ^bool (__unused char *data, __unused size_t data_size, __unused dt_pipe_data_handler_context_t *context) {
79 T_LOG("%s", data);
80 return false;
81 }, BUFFER_PATTERN_LINE, NULL);
82
83 if (test_pid == 0) {
84 T_ASSERT_FAIL("dt_launch_tool_pipe() failed unexpectedly with errno %d", errno);
85 }
86
87 int exitstatus;
88 dt_waitpid(test_pid, &exitstatus, NULL, 0);
89 if (exitstatus != 0) {
90 T_LOG("ktrace artrace exitstatus=%d\n", exitstatus);
91 }
92 if (test_skipped) {
93 unlink(tracefile_path);
94 T_SKIP("%s", name);
95 } else if (test_failed) {
96 T_FAIL("%s", name);
97 } else {
98 unlink(tracefile_path);
99 T_PASS("%s", name);
100 }
101 T_END;
102 }
103
104 T_DECL(zn_rt, "Schedule 1 RT thread per performance core, and test max latency", T_META_ENABLED(!TARGET_OS_TV))
105 {
106 char *cmd[] = {"/usr/bin/ktrace", "artrace", "-o", "zn.artrace", "-c",
107 "/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
108 "0", "broadcast-single-sem", "realtime", "1000",
109 "--spin-time", "200000",
110 "--spin-all",
111 "--test-rt",
112 #if defined(__x86_64__)
113 "--trace", "2000000",
114 #else
115 "--trace", "500000",
116 #endif
117 NULL};
118
119 run_zn("zn_rt", cmd);
120 }
121
122 T_DECL(zn_rt_smt, "Schedule 1 RT thread per primary core, verify that the secondaries are idle iff the RT threads are running", T_META_ASROOT(true), T_META_ENABLED(TARGET_CPU_X86_64))
123 {
124 char *cmd[] = {"/usr/bin/ktrace", "artrace", "-o", "zn.artrace", "-c",
125 "/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
126 "0", "broadcast-single-sem", "realtime", "1000",
127 "--spin-time", "200000",
128 "--spin-all",
129 "--churn-pri", "4",
130 "--test-rt-smt",
131 "--trace", "2000000",
132 NULL};
133
134 run_zn("zn_rt_smt", cmd);
135 }
136
137 T_DECL(zn_rt_avoid0, "Schedule 1 RT thread per primary core except for CPU 0", T_META_ASROOT(true), T_META_ENABLED(TARGET_CPU_X86_64))
138 {
139 char *cmd[] = {"/usr/bin/ktrace", "artrace", "-o", "zn.artrace", "-c",
140 "/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
141 "0", "broadcast-single-sem", "realtime", "1000",
142 "--spin-time", "200000",
143 "--spin-all",
144 "--test-rt-avoid0",
145 "--trace", "2000000",
146 NULL};
147
148 run_zn("zn_rt_avoid0", cmd);
149 }
150
151 T_DECL(zn_rt_apt, "Emulate AVID Pro Tools with default latency deadlines", T_META_ENABLED(!TARGET_OS_TV))
152 {
153 char *cmd[] = {"/usr/bin/ktrace", "artrace", "-o", "zn.artrace", "-c",
154 "/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
155 "0", "chain", "realtime", "1000",
156 "--extra-thread-count", "-3",
157 "--spin-time", "200000",
158 "--spin-all",
159 "--churn-pri", "31", "--churn-random",
160 "--test-rt",
161 #if defined(__x86_64__)
162 "--trace", "2000000",
163 #else
164 "--trace", "500000",
165 #endif
166 NULL};
167
168 run_zn("zn_rt_apt", cmd);
169 }
170
171 T_DECL(zn_rt_apt_ll, "Emulate AVID Pro Tools with low latency deadlines")
172 {
173 char *cmd[] = {"/usr/bin/ktrace", "artrace", "-o", "zn.artrace", "-c",
174 "/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
175 "0", "chain", "realtime", "1000",
176 "--extra-thread-count", "-3",
177 "--spin-time", "200000",
178 "--spin-all",
179 "--churn-pri", "31", "--churn-random",
180 "--test-rt",
181 "--rt-ll",
182 "--trace", "500000",
183 NULL};
184
185 run_zn("zn_rt_apt_ll", cmd);
186 }
187
188 T_DECL(zn_rt_edf, "Test max latency of earliest deadline RT threads in the presence of later deadline threads", T_META_ENABLED(!TARGET_OS_TV))
189 {
190 char *cmd[] = {"/usr/bin/ktrace", "artrace", "-o", "zn.artrace", "-c",
191 "/AppleInternal/CoreOS/tests/xnu/zero-to-n/zn",
192 "0", "broadcast-single-sem", "realtime", "1000",
193 "--extra-thread-count", "-1",
194 "--spin-time", "200000",
195 "--spin-all",
196 "--rt-churn",
197 "--test-rt",
198 #if defined(__x86_64__)
199 "--trace", "2000000",
200 #else
201 "--trace", "500000",
202 #endif
203 NULL};
204
205 run_zn("zn_rt_edf", cmd);
206 }
207