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