xref: /xnu-10002.81.5/tests/vm/compression_sweep.c (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587) !
1 #include <darwintest.h>
2 #include <errno.h>
3 #include <TargetConditionals.h>
4 #include <mach/mach.h>
5 #include <sys/types.h>
6 #include <sys/sysctl.h>
7 #include <stdio.h>
8 #include <unistd.h>
9 #include <string.h>
10 #include <sys/proc.h>
11 
12 T_GLOBAL_META(
13 	T_META_NAMESPACE("xnu.vm"),
14 	T_META_RADAR_COMPONENT_NAME("xnu"),
15 	T_META_RADAR_COMPONENT_VERSION("VM"));
16 
17 static int orig_age = 0;
18 static const char *ripe_target_age_sysctl = "vm.vm_ripe_target_age_in_secs";
19 
20 static void
cleanup_ripe_age(void)21 cleanup_ripe_age(void)
22 {
23 	int ret = sysctlbyname(ripe_target_age_sysctl, NULL, NULL, &orig_age,
24 	    sizeof(orig_age));
25 	if (ret == -1) {
26 		T_LOG("non-fatal: failed to reset %s: %s", ripe_target_age_sysctl,
27 		    strerror(errno));
28 	}
29 }
30 
31 T_DECL(compression_sweep,
32     "ensure some pages are compressed due to pid_hibernate",
33     T_META_ASROOT(true),
34     T_META_ENABLED(!TARGET_OS_OSX && !TARGET_OS_WATCH && !TARGET_OS_TV))
35 {
36 	/*
37 	 * Change the system to sweep out compressed pages that are older than
38 	 * `compressed_page_target_age_secs` seconds and induce `sweep_count` sweeps
39 	 * every `sleep_dur_secs` seconds.
40 	 */
41 
42 	int compressed_page_target_age_secs = 1;
43 	const int sweep_period_secs = 10;
44 	T_QUIET; T_ASSERT_GT(sweep_period_secs, compressed_page_target_age_secs,
45 	    "should sleep longer than target age");
46 	const int sweep_count = 3;
47 
48 	vm_statistics64_data_t vm_stat_before;
49 	unsigned int count = HOST_VM_INFO64_COUNT;
50 	kern_return_t kret = host_statistics64(mach_host_self(), HOST_VM_INFO64,
51 	    (host_info64_t)&vm_stat_before, &count);
52 	T_QUIET; T_ASSERT_MACH_SUCCESS(kret, "host_statistics64");
53 
54 	size_t size = sizeof(orig_age);
55 	int ret = sysctlbyname(ripe_target_age_sysctl, &orig_age, &size,
56 	    &compressed_page_target_age_secs,
57 	    sizeof(compressed_page_target_age_secs));
58 	T_ASSERT_POSIX_SUCCESS(ret, "temporarily set sysctl(%s) to %d",
59 	    ripe_target_age_sysctl, compressed_page_target_age_secs);
60 	T_ATEND(cleanup_ripe_age);
61 
62 	for (int i = 0; i < sweep_count; i++) {
63 		const int sweep_out_unused_compressed_command = -2;
64 		ret = pid_hibernate(sweep_out_unused_compressed_command);
65 		T_ASSERT_POSIX_SUCCESS(ret, "pid_hibernate(sweep-unused-compressed)");
66 		sleep(sweep_period_secs);
67 	}
68 
69 	vm_statistics64_data_t vm_stat_after;
70 	count = HOST_VM_INFO64_COUNT;
71 	kret = host_statistics64(mach_host_self(), HOST_VM_INFO64,
72 	    (host_info64_t)&vm_stat_after, &count);
73 	T_QUIET; T_ASSERT_MACH_SUCCESS(kret, "host_statistics64");
74 
75 	T_LOG("compressed %llu pages",
76 	    vm_stat_after.compressions - vm_stat_before.swapouts);
77 	T_EXPECT_GT(vm_stat_after.compressions, vm_stat_before.compressions,
78 	    "should have compressed some pages during sweeps");
79 	// rdar://71454311 (Compression sweep swap outs are flaky, should induce compressions)
80 	T_MAYFAIL;
81 	T_EXPECT_GT(vm_stat_after.swapouts, vm_stat_before.swapouts,
82 	    "should have swapped out some pages during sweeps");
83 }
84