1*a325d9c4SApple OSS Distributions #include <stdio.h>
2*a325d9c4SApple OSS Distributions #include <signal.h>
3*a325d9c4SApple OSS Distributions #include <sys/sysctl.h>
4*a325d9c4SApple OSS Distributions #include <sys/kern_memorystatus.h>
5*a325d9c4SApple OSS Distributions #include <mach-o/dyld.h>
6*a325d9c4SApple OSS Distributions #include <perfcheck_keys.h>
7*a325d9c4SApple OSS Distributions
8*a325d9c4SApple OSS Distributions #ifdef T_NAMESPACE
9*a325d9c4SApple OSS Distributions #undef T_NAMESPACE
10*a325d9c4SApple OSS Distributions #endif
11*a325d9c4SApple OSS Distributions #include <darwintest.h>
12*a325d9c4SApple OSS Distributions #include <darwintest_utils.h>
13*a325d9c4SApple OSS Distributions
14*a325d9c4SApple OSS Distributions T_GLOBAL_META(
15*a325d9c4SApple OSS Distributions T_META_NAMESPACE("xnu.vm.perf"),
16*a325d9c4SApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
17*a325d9c4SApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("VM"),
18*a325d9c4SApple OSS Distributions T_META_CHECK_LEAKS(false),
19*a325d9c4SApple OSS Distributions T_META_TAG_PERF
20*a325d9c4SApple OSS Distributions );
21*a325d9c4SApple OSS Distributions
22*a325d9c4SApple OSS Distributions enum {
23*a325d9c4SApple OSS Distributions ALL_ZEROS,
24*a325d9c4SApple OSS Distributions MOSTLY_ZEROS,
25*a325d9c4SApple OSS Distributions RANDOM,
26*a325d9c4SApple OSS Distributions TYPICAL
27*a325d9c4SApple OSS Distributions };
28*a325d9c4SApple OSS Distributions
29*a325d9c4SApple OSS Distributions #define CREATE_LIST(X) \
30*a325d9c4SApple OSS Distributions X(SUCCESS) \
31*a325d9c4SApple OSS Distributions X(TOO_FEW_ARGUMENTS) \
32*a325d9c4SApple OSS Distributions X(SYSCTL_VM_PAGESIZE_FAILED) \
33*a325d9c4SApple OSS Distributions X(VM_PAGESIZE_IS_ZERO) \
34*a325d9c4SApple OSS Distributions X(UNKNOWN_PAGE_TYPE) \
35*a325d9c4SApple OSS Distributions X(DISPATCH_SOURCE_CREATE_FAILED) \
36*a325d9c4SApple OSS Distributions X(INITIAL_SIGNAL_TO_PARENT_FAILED) \
37*a325d9c4SApple OSS Distributions X(SIGNAL_TO_PARENT_FAILED) \
38*a325d9c4SApple OSS Distributions X(MEMORYSTATUS_CONTROL_FAILED) \
39*a325d9c4SApple OSS Distributions X(IS_FREEZABLE_NOT_AS_EXPECTED) \
40*a325d9c4SApple OSS Distributions X(EXIT_CODE_MAX)
41*a325d9c4SApple OSS Distributions
42*a325d9c4SApple OSS Distributions #define EXIT_CODES_ENUM(VAR) VAR,
43*a325d9c4SApple OSS Distributions enum exit_codes_num {
44*a325d9c4SApple OSS Distributions CREATE_LIST(EXIT_CODES_ENUM)
45*a325d9c4SApple OSS Distributions };
46*a325d9c4SApple OSS Distributions
47*a325d9c4SApple OSS Distributions #define EXIT_CODES_STRING(VAR) #VAR,
48*a325d9c4SApple OSS Distributions static const char *exit_codes_str[] = {
49*a325d9c4SApple OSS Distributions CREATE_LIST(EXIT_CODES_STRING)
50*a325d9c4SApple OSS Distributions };
51*a325d9c4SApple OSS Distributions
52*a325d9c4SApple OSS Distributions #define SYSCTL_FREEZE_TO_MEMORY "kern.memorystatus_freeze_to_memory=1"
53*a325d9c4SApple OSS Distributions
54*a325d9c4SApple OSS Distributions static pid_t pid = -1;
55*a325d9c4SApple OSS Distributions static dt_stat_t ratio;
56*a325d9c4SApple OSS Distributions static dt_stat_time_t compr_time;
57*a325d9c4SApple OSS Distributions static dt_stat_time_t decompr_time;
58*a325d9c4SApple OSS Distributions
59*a325d9c4SApple OSS Distributions void allocate_zero_pages(char **buf, int num_pages, int vmpgsize);
60*a325d9c4SApple OSS Distributions void allocate_mostly_zero_pages(char **buf, int num_pages, int vmpgsize);
61*a325d9c4SApple OSS Distributions void allocate_random_pages(char **buf, int num_pages, int vmpgsize);
62*a325d9c4SApple OSS Distributions void allocate_representative_pages(char **buf, int num_pages, int vmpgsize);
63*a325d9c4SApple OSS Distributions void run_compressor_test(int size_mb, int page_type);
64*a325d9c4SApple OSS Distributions void freeze_helper_process(void);
65*a325d9c4SApple OSS Distributions void cleanup(void);
66*a325d9c4SApple OSS Distributions
67*a325d9c4SApple OSS Distributions void
allocate_zero_pages(char ** buf,int num_pages,int vmpgsize)68*a325d9c4SApple OSS Distributions allocate_zero_pages(char **buf, int num_pages, int vmpgsize)
69*a325d9c4SApple OSS Distributions {
70*a325d9c4SApple OSS Distributions int i;
71*a325d9c4SApple OSS Distributions
72*a325d9c4SApple OSS Distributions for (i = 0; i < num_pages; i++) {
73*a325d9c4SApple OSS Distributions buf[i] = (char*)malloc((size_t)vmpgsize * sizeof(char));
74*a325d9c4SApple OSS Distributions memset(buf[i], 0, vmpgsize);
75*a325d9c4SApple OSS Distributions }
76*a325d9c4SApple OSS Distributions }
77*a325d9c4SApple OSS Distributions
78*a325d9c4SApple OSS Distributions void
allocate_mostly_zero_pages(char ** buf,int num_pages,int vmpgsize)79*a325d9c4SApple OSS Distributions allocate_mostly_zero_pages(char **buf, int num_pages, int vmpgsize)
80*a325d9c4SApple OSS Distributions {
81*a325d9c4SApple OSS Distributions int i, j;
82*a325d9c4SApple OSS Distributions
83*a325d9c4SApple OSS Distributions for (i = 0; i < num_pages; i++) {
84*a325d9c4SApple OSS Distributions buf[i] = (char*)malloc((size_t)vmpgsize * sizeof(char));
85*a325d9c4SApple OSS Distributions memset(buf[i], 0, vmpgsize);
86*a325d9c4SApple OSS Distributions for (j = 0; j < 40; j++) {
87*a325d9c4SApple OSS Distributions buf[i][j] = (char)(j + 1);
88*a325d9c4SApple OSS Distributions }
89*a325d9c4SApple OSS Distributions }
90*a325d9c4SApple OSS Distributions }
91*a325d9c4SApple OSS Distributions
92*a325d9c4SApple OSS Distributions void
allocate_random_pages(char ** buf,int num_pages,int vmpgsize)93*a325d9c4SApple OSS Distributions allocate_random_pages(char **buf, int num_pages, int vmpgsize)
94*a325d9c4SApple OSS Distributions {
95*a325d9c4SApple OSS Distributions int i;
96*a325d9c4SApple OSS Distributions
97*a325d9c4SApple OSS Distributions for (i = 0; i < num_pages; i++) {
98*a325d9c4SApple OSS Distributions buf[i] = (char*)malloc((size_t)vmpgsize * sizeof(char));
99*a325d9c4SApple OSS Distributions arc4random_buf((void*)buf[i], (size_t)vmpgsize);
100*a325d9c4SApple OSS Distributions }
101*a325d9c4SApple OSS Distributions }
102*a325d9c4SApple OSS Distributions
103*a325d9c4SApple OSS Distributions // Gives us the compression ratio we see in the typical case (~2.7)
104*a325d9c4SApple OSS Distributions void
allocate_representative_pages(char ** buf,int num_pages,int vmpgsize)105*a325d9c4SApple OSS Distributions allocate_representative_pages(char **buf, int num_pages, int vmpgsize)
106*a325d9c4SApple OSS Distributions {
107*a325d9c4SApple OSS Distributions int i, j;
108*a325d9c4SApple OSS Distributions char val;
109*a325d9c4SApple OSS Distributions
110*a325d9c4SApple OSS Distributions for (j = 0; j < num_pages; j++) {
111*a325d9c4SApple OSS Distributions buf[j] = (char*)malloc((size_t)vmpgsize * sizeof(char));
112*a325d9c4SApple OSS Distributions val = 0;
113*a325d9c4SApple OSS Distributions for (i = 0; i < vmpgsize; i += 16) {
114*a325d9c4SApple OSS Distributions memset(&buf[j][i], val, 16);
115*a325d9c4SApple OSS Distributions if (i < 3400 * (vmpgsize / 4096)) {
116*a325d9c4SApple OSS Distributions val++;
117*a325d9c4SApple OSS Distributions }
118*a325d9c4SApple OSS Distributions }
119*a325d9c4SApple OSS Distributions }
120*a325d9c4SApple OSS Distributions }
121*a325d9c4SApple OSS Distributions
122*a325d9c4SApple OSS Distributions void
freeze_helper_process(void)123*a325d9c4SApple OSS Distributions freeze_helper_process(void)
124*a325d9c4SApple OSS Distributions {
125*a325d9c4SApple OSS Distributions int ret, freeze_enabled;
126*a325d9c4SApple OSS Distributions int64_t compressed_before, compressed_after, input_before, input_after;
127*a325d9c4SApple OSS Distributions size_t length;
128*a325d9c4SApple OSS Distributions int errno_sysctl_freeze;
129*a325d9c4SApple OSS Distributions
130*a325d9c4SApple OSS Distributions length = sizeof(compressed_before);
131*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_compressed_bytes", &compressed_before, &length, NULL, 0),
132*a325d9c4SApple OSS Distributions "failed to query vm.compressor_compressed_bytes");
133*a325d9c4SApple OSS Distributions length = sizeof(input_before);
134*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_input_bytes", &input_before, &length, NULL, 0),
135*a325d9c4SApple OSS Distributions "failed to query vm.compressor_input_bytes");
136*a325d9c4SApple OSS Distributions
137*a325d9c4SApple OSS Distributions T_STAT_MEASURE(compr_time) {
138*a325d9c4SApple OSS Distributions ret = sysctlbyname("kern.memorystatus_freeze", NULL, NULL, &pid, sizeof(pid));
139*a325d9c4SApple OSS Distributions errno_sysctl_freeze = errno;
140*a325d9c4SApple OSS Distributions };
141*a325d9c4SApple OSS Distributions
142*a325d9c4SApple OSS Distributions length = sizeof(compressed_after);
143*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_compressed_bytes", &compressed_after, &length, NULL, 0),
144*a325d9c4SApple OSS Distributions "failed to query vm.compressor_compressed_bytes");
145*a325d9c4SApple OSS Distributions length = sizeof(input_after);
146*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_input_bytes", &input_after, &length, NULL, 0),
147*a325d9c4SApple OSS Distributions "failed to query vm.compressor_input_bytes");
148*a325d9c4SApple OSS Distributions
149*a325d9c4SApple OSS Distributions length = sizeof(freeze_enabled);
150*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.freeze_enabled", &freeze_enabled, &length, NULL, 0),
151*a325d9c4SApple OSS Distributions "failed to query vm.freeze_enabled");
152*a325d9c4SApple OSS Distributions if (freeze_enabled) {
153*a325d9c4SApple OSS Distributions errno = errno_sysctl_freeze;
154*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl kern.memorystatus_freeze failed");
155*a325d9c4SApple OSS Distributions } else {
156*a325d9c4SApple OSS Distributions /* If freezer is disabled, skip the test. This can happen due to disk space shortage. */
157*a325d9c4SApple OSS Distributions T_LOG("Freeze has been disabled. Terminating early.");
158*a325d9c4SApple OSS Distributions T_END;
159*a325d9c4SApple OSS Distributions }
160*a325d9c4SApple OSS Distributions
161*a325d9c4SApple OSS Distributions dt_stat_add(ratio, (double)(input_after - input_before) / (double)(compressed_after - compressed_before));
162*a325d9c4SApple OSS Distributions
163*a325d9c4SApple OSS Distributions ret = sysctlbyname("kern.memorystatus_thaw", NULL, NULL, &pid, sizeof(pid));
164*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl kern.memorystatus_thaw failed");
165*a325d9c4SApple OSS Distributions
166*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(kill(pid, SIGUSR1), "failed to send SIGUSR1 to child process");
167*a325d9c4SApple OSS Distributions }
168*a325d9c4SApple OSS Distributions
169*a325d9c4SApple OSS Distributions void
cleanup(void)170*a325d9c4SApple OSS Distributions cleanup(void)
171*a325d9c4SApple OSS Distributions {
172*a325d9c4SApple OSS Distributions /* No helper process. */
173*a325d9c4SApple OSS Distributions if (pid == -1) {
174*a325d9c4SApple OSS Distributions return;
175*a325d9c4SApple OSS Distributions }
176*a325d9c4SApple OSS Distributions /* Kill the helper process. */
177*a325d9c4SApple OSS Distributions kill(pid, SIGKILL);
178*a325d9c4SApple OSS Distributions }
179*a325d9c4SApple OSS Distributions
180*a325d9c4SApple OSS Distributions void
run_compressor_test(int size_mb,int page_type)181*a325d9c4SApple OSS Distributions run_compressor_test(int size_mb, int page_type)
182*a325d9c4SApple OSS Distributions {
183*a325d9c4SApple OSS Distributions int ret;
184*a325d9c4SApple OSS Distributions char sz_str[50];
185*a325d9c4SApple OSS Distributions char pt_str[50];
186*a325d9c4SApple OSS Distributions char **launch_tool_args;
187*a325d9c4SApple OSS Distributions char testpath[PATH_MAX];
188*a325d9c4SApple OSS Distributions uint32_t testpath_buf_size;
189*a325d9c4SApple OSS Distributions dispatch_source_t ds_freeze, ds_proc, ds_decompr;
190*a325d9c4SApple OSS Distributions int freeze_enabled;
191*a325d9c4SApple OSS Distributions size_t length;
192*a325d9c4SApple OSS Distributions __block bool decompr_latency_is_stable = false;
193*a325d9c4SApple OSS Distributions
194*a325d9c4SApple OSS Distributions length = sizeof(freeze_enabled);
195*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.freeze_enabled", &freeze_enabled, &length, NULL, 0),
196*a325d9c4SApple OSS Distributions "failed to query vm.freeze_enabled");
197*a325d9c4SApple OSS Distributions if (!freeze_enabled) {
198*a325d9c4SApple OSS Distributions /* If freezer is disabled, skip the test. This can happen due to disk space shortage. */
199*a325d9c4SApple OSS Distributions T_SKIP("Freeze has been disabled. Skipping test.");
200*a325d9c4SApple OSS Distributions }
201*a325d9c4SApple OSS Distributions
202*a325d9c4SApple OSS Distributions T_ATEND(cleanup);
203*a325d9c4SApple OSS Distributions
204*a325d9c4SApple OSS Distributions ratio = dt_stat_create("(input bytes / compressed bytes)", "compression_ratio");
205*a325d9c4SApple OSS Distributions compr_time = dt_stat_time_create("compressor_latency");
206*a325d9c4SApple OSS Distributions
207*a325d9c4SApple OSS Distributions // This sets the A/B failure threshold at 50% of baseline for compressor_latency
208*a325d9c4SApple OSS Distributions dt_stat_set_variable((struct dt_stat *)compr_time, kPCFailureThresholdPctVar, 50.0);
209*a325d9c4SApple OSS Distributions
210*a325d9c4SApple OSS Distributions signal(SIGUSR2, SIG_IGN);
211*a325d9c4SApple OSS Distributions ds_decompr = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGUSR2, 0, dispatch_get_main_queue());
212*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_NOTNULL(ds_decompr, "dispatch_source_create (ds_decompr)");
213*a325d9c4SApple OSS Distributions
214*a325d9c4SApple OSS Distributions dispatch_source_set_event_handler(ds_decompr, ^{
215*a325d9c4SApple OSS Distributions decompr_latency_is_stable = true;
216*a325d9c4SApple OSS Distributions });
217*a325d9c4SApple OSS Distributions dispatch_activate(ds_decompr);
218*a325d9c4SApple OSS Distributions
219*a325d9c4SApple OSS Distributions signal(SIGUSR1, SIG_IGN);
220*a325d9c4SApple OSS Distributions ds_freeze = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGUSR1, 0, dispatch_get_main_queue());
221*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_NOTNULL(ds_freeze, "dispatch_source_create (ds_freeze)");
222*a325d9c4SApple OSS Distributions
223*a325d9c4SApple OSS Distributions dispatch_source_set_event_handler(ds_freeze, ^{
224*a325d9c4SApple OSS Distributions if (!(dt_stat_stable(compr_time) && decompr_latency_is_stable)) {
225*a325d9c4SApple OSS Distributions freeze_helper_process();
226*a325d9c4SApple OSS Distributions } else {
227*a325d9c4SApple OSS Distributions dt_stat_finalize(compr_time);
228*a325d9c4SApple OSS Distributions dt_stat_finalize(ratio);
229*a325d9c4SApple OSS Distributions
230*a325d9c4SApple OSS Distributions kill(pid, SIGKILL);
231*a325d9c4SApple OSS Distributions dispatch_source_cancel(ds_freeze);
232*a325d9c4SApple OSS Distributions dispatch_source_cancel(ds_decompr);
233*a325d9c4SApple OSS Distributions }
234*a325d9c4SApple OSS Distributions });
235*a325d9c4SApple OSS Distributions dispatch_activate(ds_freeze);
236*a325d9c4SApple OSS Distributions
237*a325d9c4SApple OSS Distributions testpath_buf_size = sizeof(testpath);
238*a325d9c4SApple OSS Distributions ret = _NSGetExecutablePath(testpath, &testpath_buf_size);
239*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_ZERO(ret, "_NSGetExecutablePath");
240*a325d9c4SApple OSS Distributions T_LOG("Executable path: %s", testpath);
241*a325d9c4SApple OSS Distributions
242*a325d9c4SApple OSS Distributions sprintf(sz_str, "%d", size_mb);
243*a325d9c4SApple OSS Distributions sprintf(pt_str, "%d", page_type);
244*a325d9c4SApple OSS Distributions launch_tool_args = (char *[]){
245*a325d9c4SApple OSS Distributions testpath,
246*a325d9c4SApple OSS Distributions "-n",
247*a325d9c4SApple OSS Distributions "allocate_pages",
248*a325d9c4SApple OSS Distributions "--",
249*a325d9c4SApple OSS Distributions sz_str,
250*a325d9c4SApple OSS Distributions pt_str,
251*a325d9c4SApple OSS Distributions NULL
252*a325d9c4SApple OSS Distributions };
253*a325d9c4SApple OSS Distributions
254*a325d9c4SApple OSS Distributions /* Spawn the child process. Suspend after launch until the exit proc handler has been set up. */
255*a325d9c4SApple OSS Distributions ret = dt_launch_tool(&pid, launch_tool_args, true, NULL, NULL);
256*a325d9c4SApple OSS Distributions if (ret != 0) {
257*a325d9c4SApple OSS Distributions T_LOG("dt_launch tool returned %d with error code %d", ret, errno);
258*a325d9c4SApple OSS Distributions }
259*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(pid, "dt_launch_tool");
260*a325d9c4SApple OSS Distributions
261*a325d9c4SApple OSS Distributions ds_proc = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, (uintptr_t)pid, DISPATCH_PROC_EXIT, dispatch_get_main_queue());
262*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_NOTNULL(ds_proc, "dispatch_source_create (ds_proc)");
263*a325d9c4SApple OSS Distributions
264*a325d9c4SApple OSS Distributions dispatch_source_set_event_handler(ds_proc, ^{
265*a325d9c4SApple OSS Distributions int status = 0, code = 0;
266*a325d9c4SApple OSS Distributions pid_t rc = waitpid(pid, &status, 0);
267*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_EQ(rc, pid, "waitpid");
268*a325d9c4SApple OSS Distributions code = WEXITSTATUS(status);
269*a325d9c4SApple OSS Distributions
270*a325d9c4SApple OSS Distributions if (code == 0) {
271*a325d9c4SApple OSS Distributions T_END;
272*a325d9c4SApple OSS Distributions } else if (code > 0 && code < EXIT_CODE_MAX) {
273*a325d9c4SApple OSS Distributions T_ASSERT_FAIL("Child exited with %s", exit_codes_str[code]);
274*a325d9c4SApple OSS Distributions } else {
275*a325d9c4SApple OSS Distributions T_ASSERT_FAIL("Child exited with unknown exit code %d", code);
276*a325d9c4SApple OSS Distributions }
277*a325d9c4SApple OSS Distributions });
278*a325d9c4SApple OSS Distributions dispatch_activate(ds_proc);
279*a325d9c4SApple OSS Distributions
280*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(kill(pid, SIGCONT), "failed to send SIGCONT to child process");
281*a325d9c4SApple OSS Distributions dispatch_main();
282*a325d9c4SApple OSS Distributions }
283*a325d9c4SApple OSS Distributions
284*a325d9c4SApple OSS Distributions T_HELPER_DECL(allocate_pages, "allocates pages to compress") {
285*a325d9c4SApple OSS Distributions int i, j, ret, size_mb, page_type, vmpgsize, freezable_state;
286*a325d9c4SApple OSS Distributions size_t vmpgsize_length;
287*a325d9c4SApple OSS Distributions __block int num_pages;
288*a325d9c4SApple OSS Distributions __block char **buf;
289*a325d9c4SApple OSS Distributions dispatch_source_t ds_signal;
290*a325d9c4SApple OSS Distributions
291*a325d9c4SApple OSS Distributions vmpgsize_length = sizeof(vmpgsize);
292*a325d9c4SApple OSS Distributions ret = sysctlbyname("vm.pagesize", &vmpgsize, &vmpgsize_length, NULL, 0);
293*a325d9c4SApple OSS Distributions if (ret != 0) {
294*a325d9c4SApple OSS Distributions exit(SYSCTL_VM_PAGESIZE_FAILED);
295*a325d9c4SApple OSS Distributions }
296*a325d9c4SApple OSS Distributions if (vmpgsize == 0) {
297*a325d9c4SApple OSS Distributions exit(VM_PAGESIZE_IS_ZERO);
298*a325d9c4SApple OSS Distributions }
299*a325d9c4SApple OSS Distributions
300*a325d9c4SApple OSS Distributions if (argc < 2) {
301*a325d9c4SApple OSS Distributions exit(TOO_FEW_ARGUMENTS);
302*a325d9c4SApple OSS Distributions }
303*a325d9c4SApple OSS Distributions
304*a325d9c4SApple OSS Distributions size_mb = atoi(argv[0]);
305*a325d9c4SApple OSS Distributions page_type = atoi(argv[1]);
306*a325d9c4SApple OSS Distributions num_pages = size_mb * 1024 * 1024 / vmpgsize;
307*a325d9c4SApple OSS Distributions buf = (char**)malloc(sizeof(char*) * (size_t)num_pages);
308*a325d9c4SApple OSS Distributions
309*a325d9c4SApple OSS Distributions // Switch on the type of page requested
310*a325d9c4SApple OSS Distributions switch (page_type) {
311*a325d9c4SApple OSS Distributions case ALL_ZEROS:
312*a325d9c4SApple OSS Distributions allocate_zero_pages(buf, num_pages, vmpgsize);
313*a325d9c4SApple OSS Distributions break;
314*a325d9c4SApple OSS Distributions case MOSTLY_ZEROS:
315*a325d9c4SApple OSS Distributions allocate_mostly_zero_pages(buf, num_pages, vmpgsize);
316*a325d9c4SApple OSS Distributions break;
317*a325d9c4SApple OSS Distributions case RANDOM:
318*a325d9c4SApple OSS Distributions allocate_random_pages(buf, num_pages, vmpgsize);
319*a325d9c4SApple OSS Distributions break;
320*a325d9c4SApple OSS Distributions case TYPICAL:
321*a325d9c4SApple OSS Distributions allocate_representative_pages(buf, num_pages, vmpgsize);
322*a325d9c4SApple OSS Distributions break;
323*a325d9c4SApple OSS Distributions default:
324*a325d9c4SApple OSS Distributions exit(UNKNOWN_PAGE_TYPE);
325*a325d9c4SApple OSS Distributions }
326*a325d9c4SApple OSS Distributions
327*a325d9c4SApple OSS Distributions for (j = 0; j < num_pages; j++) {
328*a325d9c4SApple OSS Distributions i = buf[j][0];
329*a325d9c4SApple OSS Distributions }
330*a325d9c4SApple OSS Distributions
331*a325d9c4SApple OSS Distributions decompr_time = dt_stat_time_create("decompression_latency");
332*a325d9c4SApple OSS Distributions
333*a325d9c4SApple OSS Distributions /* Opt in to freezing. */
334*a325d9c4SApple OSS Distributions printf("[%d] Setting state to freezable\n", getpid());
335*a325d9c4SApple OSS Distributions if (memorystatus_control(MEMORYSTATUS_CMD_SET_PROCESS_IS_FREEZABLE, getpid(), 1, NULL, 0) != KERN_SUCCESS) {
336*a325d9c4SApple OSS Distributions exit(MEMORYSTATUS_CONTROL_FAILED);
337*a325d9c4SApple OSS Distributions }
338*a325d9c4SApple OSS Distributions
339*a325d9c4SApple OSS Distributions /* Verify that the state has been set correctly */
340*a325d9c4SApple OSS Distributions freezable_state = memorystatus_control(MEMORYSTATUS_CMD_GET_PROCESS_IS_FREEZABLE, getpid(), 0, NULL, 0);
341*a325d9c4SApple OSS Distributions if (freezable_state != 1) {
342*a325d9c4SApple OSS Distributions exit(IS_FREEZABLE_NOT_AS_EXPECTED);
343*a325d9c4SApple OSS Distributions }
344*a325d9c4SApple OSS Distributions
345*a325d9c4SApple OSS Distributions dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC), dispatch_get_main_queue(), ^{
346*a325d9c4SApple OSS Distributions /* Signal to the parent that we're done allocating and it's ok to freeze us */
347*a325d9c4SApple OSS Distributions printf("[%d] Sending initial signal to parent to begin freezing\n", getpid());
348*a325d9c4SApple OSS Distributions if (kill(getppid(), SIGUSR1) != 0) {
349*a325d9c4SApple OSS Distributions exit(INITIAL_SIGNAL_TO_PARENT_FAILED);
350*a325d9c4SApple OSS Distributions }
351*a325d9c4SApple OSS Distributions });
352*a325d9c4SApple OSS Distributions
353*a325d9c4SApple OSS Distributions signal(SIGUSR1, SIG_IGN);
354*a325d9c4SApple OSS Distributions ds_signal = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGUSR1, 0, dispatch_get_main_queue());
355*a325d9c4SApple OSS Distributions if (ds_signal == NULL) {
356*a325d9c4SApple OSS Distributions exit(DISPATCH_SOURCE_CREATE_FAILED);
357*a325d9c4SApple OSS Distributions }
358*a325d9c4SApple OSS Distributions
359*a325d9c4SApple OSS Distributions __block bool collect_dt_stat_measurements = true;
360*a325d9c4SApple OSS Distributions
361*a325d9c4SApple OSS Distributions dispatch_source_set_event_handler(ds_signal, ^{
362*a325d9c4SApple OSS Distributions volatile int tmp;
363*a325d9c4SApple OSS Distributions uint64_t decompr_start_time, decompr_end_time;
364*a325d9c4SApple OSS Distributions
365*a325d9c4SApple OSS Distributions decompr_start_time = mach_absolute_time();
366*a325d9c4SApple OSS Distributions
367*a325d9c4SApple OSS Distributions /* Make sure all the pages are accessed before trying to freeze again */
368*a325d9c4SApple OSS Distributions for (int x = 0; x < num_pages; x++) {
369*a325d9c4SApple OSS Distributions tmp = buf[x][0];
370*a325d9c4SApple OSS Distributions }
371*a325d9c4SApple OSS Distributions
372*a325d9c4SApple OSS Distributions decompr_end_time = mach_absolute_time();
373*a325d9c4SApple OSS Distributions
374*a325d9c4SApple OSS Distributions if (collect_dt_stat_measurements) {
375*a325d9c4SApple OSS Distributions if (dt_stat_stable(decompr_time)) {
376*a325d9c4SApple OSS Distributions collect_dt_stat_measurements = false;
377*a325d9c4SApple OSS Distributions dt_stat_finalize(decompr_time);
378*a325d9c4SApple OSS Distributions if (kill(getppid(), SIGUSR2) != 0) {
379*a325d9c4SApple OSS Distributions exit(SIGNAL_TO_PARENT_FAILED);
380*a325d9c4SApple OSS Distributions }
381*a325d9c4SApple OSS Distributions } else {
382*a325d9c4SApple OSS Distributions dt_stat_mach_time_add(decompr_time, decompr_end_time - decompr_start_time);
383*a325d9c4SApple OSS Distributions }
384*a325d9c4SApple OSS Distributions }
385*a325d9c4SApple OSS Distributions
386*a325d9c4SApple OSS Distributions if (kill(getppid(), SIGUSR1) != 0) {
387*a325d9c4SApple OSS Distributions exit(SIGNAL_TO_PARENT_FAILED);
388*a325d9c4SApple OSS Distributions }
389*a325d9c4SApple OSS Distributions });
390*a325d9c4SApple OSS Distributions dispatch_activate(ds_signal);
391*a325d9c4SApple OSS Distributions
392*a325d9c4SApple OSS Distributions dispatch_main();
393*a325d9c4SApple OSS Distributions }
394*a325d9c4SApple OSS Distributions
395*a325d9c4SApple OSS Distributions // Numbers for 10MB and above are fairly reproducible. Anything smaller shows a lot of variation.
396*a325d9c4SApple OSS Distributions
397*a325d9c4SApple OSS Distributions // Keeping just the 100MB version for iOSMark
398*a325d9c4SApple OSS Distributions #ifndef DT_IOSMARK
399*a325d9c4SApple OSS Distributions T_DECL(compr_10MB_zero,
400*a325d9c4SApple OSS Distributions "Compression latency for 10MB - zero pages",
401*a325d9c4SApple OSS Distributions T_META_ASROOT(true),
402*a325d9c4SApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_FREEZE_TO_MEMORY)) {
403*a325d9c4SApple OSS Distributions run_compressor_test(10, ALL_ZEROS);
404*a325d9c4SApple OSS Distributions }
405*a325d9c4SApple OSS Distributions
406*a325d9c4SApple OSS Distributions T_DECL(compr_10MB_mostly_zero,
407*a325d9c4SApple OSS Distributions "Compression latency for 10MB - mostly zero pages",
408*a325d9c4SApple OSS Distributions T_META_ASROOT(true),
409*a325d9c4SApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_FREEZE_TO_MEMORY)) {
410*a325d9c4SApple OSS Distributions run_compressor_test(10, MOSTLY_ZEROS);
411*a325d9c4SApple OSS Distributions }
412*a325d9c4SApple OSS Distributions
413*a325d9c4SApple OSS Distributions T_DECL(compr_10MB_random,
414*a325d9c4SApple OSS Distributions "Compression latency for 10MB - random pages",
415*a325d9c4SApple OSS Distributions T_META_ASROOT(true),
416*a325d9c4SApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_FREEZE_TO_MEMORY)) {
417*a325d9c4SApple OSS Distributions run_compressor_test(10, RANDOM);
418*a325d9c4SApple OSS Distributions }
419*a325d9c4SApple OSS Distributions
420*a325d9c4SApple OSS Distributions T_DECL(compr_10MB_typical,
421*a325d9c4SApple OSS Distributions "Compression latency for 10MB - typical pages",
422*a325d9c4SApple OSS Distributions T_META_ASROOT(true),
423*a325d9c4SApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_FREEZE_TO_MEMORY)) {
424*a325d9c4SApple OSS Distributions run_compressor_test(10, TYPICAL);
425*a325d9c4SApple OSS Distributions }
426*a325d9c4SApple OSS Distributions
427*a325d9c4SApple OSS Distributions T_DECL(compr_100MB_zero,
428*a325d9c4SApple OSS Distributions "Compression latency for 100MB - zero pages",
429*a325d9c4SApple OSS Distributions T_META_ASROOT(true),
430*a325d9c4SApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_FREEZE_TO_MEMORY)) {
431*a325d9c4SApple OSS Distributions run_compressor_test(100, ALL_ZEROS);
432*a325d9c4SApple OSS Distributions }
433*a325d9c4SApple OSS Distributions
434*a325d9c4SApple OSS Distributions T_DECL(compr_100MB_mostly_zero,
435*a325d9c4SApple OSS Distributions "Compression latency for 100MB - mostly zero pages",
436*a325d9c4SApple OSS Distributions T_META_ASROOT(true),
437*a325d9c4SApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_FREEZE_TO_MEMORY)) {
438*a325d9c4SApple OSS Distributions run_compressor_test(100, MOSTLY_ZEROS);
439*a325d9c4SApple OSS Distributions }
440*a325d9c4SApple OSS Distributions
441*a325d9c4SApple OSS Distributions T_DECL(compr_100MB_random,
442*a325d9c4SApple OSS Distributions "Compression latency for 100MB - random pages",
443*a325d9c4SApple OSS Distributions T_META_ASROOT(true),
444*a325d9c4SApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_FREEZE_TO_MEMORY)) {
445*a325d9c4SApple OSS Distributions run_compressor_test(100, RANDOM);
446*a325d9c4SApple OSS Distributions }
447*a325d9c4SApple OSS Distributions #endif
448*a325d9c4SApple OSS Distributions
449*a325d9c4SApple OSS Distributions T_DECL(compr_100MB_typical,
450*a325d9c4SApple OSS Distributions "Compression latency for 100MB - typical pages",
451*a325d9c4SApple OSS Distributions T_META_ASROOT(true),
452*a325d9c4SApple OSS Distributions T_META_SYSCTL_INT(SYSCTL_FREEZE_TO_MEMORY)) {
453*a325d9c4SApple OSS Distributions run_compressor_test(100, TYPICAL);
454*a325d9c4SApple OSS Distributions }
455