xref: /xnu-11215.81.4/tests/memorystatus/memorystatus_experiment_factors.c (revision d4514f0bc1d3f944c22d92e68b646ac3fb40d452)
1*d4514f0bSApple OSS Distributions /*
2*d4514f0bSApple OSS Distributions  * Copyright (c) 2024 Apple Inc. All rights reserved.
3*d4514f0bSApple OSS Distributions  *
4*d4514f0bSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*d4514f0bSApple OSS Distributions  *
6*d4514f0bSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*d4514f0bSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*d4514f0bSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*d4514f0bSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*d4514f0bSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*d4514f0bSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*d4514f0bSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*d4514f0bSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*d4514f0bSApple OSS Distributions  *
15*d4514f0bSApple OSS Distributions  * Please obtain a copy of the License at
16*d4514f0bSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*d4514f0bSApple OSS Distributions  *
18*d4514f0bSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*d4514f0bSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*d4514f0bSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*d4514f0bSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*d4514f0bSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*d4514f0bSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*d4514f0bSApple OSS Distributions  * limitations under the License.
25*d4514f0bSApple OSS Distributions  *
26*d4514f0bSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*d4514f0bSApple OSS Distributions  */
28*d4514f0bSApple OSS Distributions 
29*d4514f0bSApple OSS Distributions #include <darwintest.h>
30*d4514f0bSApple OSS Distributions #include <darwintest_posix.h>
31*d4514f0bSApple OSS Distributions #include <mach/boolean.h>
32*d4514f0bSApple OSS Distributions #include <mach/vm_page_size.h>
33*d4514f0bSApple OSS Distributions #include <stdint.h>
34*d4514f0bSApple OSS Distributions #include <sys/kern_memorystatus.h>
35*d4514f0bSApple OSS Distributions #include <sys/sysctl.h>
36*d4514f0bSApple OSS Distributions 
37*d4514f0bSApple OSS Distributions T_GLOBAL_META(
38*d4514f0bSApple OSS Distributions 	T_META_NAMESPACE("xnu.memorystatus"),
39*d4514f0bSApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
40*d4514f0bSApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("VM"),
41*d4514f0bSApple OSS Distributions 	T_META_CHECK_LEAKS(false),
42*d4514f0bSApple OSS Distributions 	T_META_RUN_CONCURRENTLY(true),
43*d4514f0bSApple OSS Distributions 	T_META_TAG_VM_PREFERRED,
44*d4514f0bSApple OSS Distributions 	T_META_ASROOT(false),
45*d4514f0bSApple OSS Distributions 	T_META_ENABLED(!TARGET_OS_OSX));
46*d4514f0bSApple OSS Distributions 
47*d4514f0bSApple OSS Distributions T_DECL(page_shortage_threshold_update,
48*d4514f0bSApple OSS Distributions     "Verify that page shortage thresholds can be read/written-to")
49*d4514f0bSApple OSS Distributions {
50*d4514f0bSApple OSS Distributions 	int ret;
51*d4514f0bSApple OSS Distributions 	uint32_t threshold_mb, expected_threshold_pages, threshold_pages;
52*d4514f0bSApple OSS Distributions 	size_t threshold_size = sizeof(threshold_size);
53*d4514f0bSApple OSS Distributions 
54*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.critical_threshold_mb",
55*d4514f0bSApple OSS Distributions 	    &threshold_mb, &threshold_size, NULL, 0);
56*d4514f0bSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "Critical threshold can be read");
57*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.critical_threshold_mb",
58*d4514f0bSApple OSS Distributions 	    NULL, 0, &threshold_mb, threshold_size);
59*d4514f0bSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "Critical threshold can be written to");
60*d4514f0bSApple OSS Distributions 	expected_threshold_pages = (threshold_mb << 20) / vm_kernel_page_size;
61*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.critical_threshold_pages",
62*d4514f0bSApple OSS Distributions 	    &threshold_pages, &threshold_size, NULL, 0);
63*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret,
64*d4514f0bSApple OSS Distributions 	    "sysctl(kern.memorystatus.critical_threshold_pages)");
65*d4514f0bSApple OSS Distributions 	T_EXPECT_EQ(threshold_pages, expected_threshold_pages,
66*d4514f0bSApple OSS Distributions 	    "Critical threshold is converted to pages");
67*d4514f0bSApple OSS Distributions 
68*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.idle_threshold_mb",
69*d4514f0bSApple OSS Distributions 	    &threshold_mb, &threshold_size, NULL, 0);
70*d4514f0bSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "Idle threshold can be read");
71*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.idle_threshold_mb",
72*d4514f0bSApple OSS Distributions 	    NULL, 0, &threshold_mb, threshold_size);
73*d4514f0bSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "Idle threshold can be written to");
74*d4514f0bSApple OSS Distributions 	expected_threshold_pages = (threshold_mb << 20) / vm_kernel_page_size;
75*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.idle_threshold_pages",
76*d4514f0bSApple OSS Distributions 	    &threshold_pages, &threshold_size, NULL, 0);
77*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret,
78*d4514f0bSApple OSS Distributions 	    "sysctl(kern.memorystatus.idle_threshold_pages)");
79*d4514f0bSApple OSS Distributions 	T_EXPECT_EQ(threshold_pages, expected_threshold_pages,
80*d4514f0bSApple OSS Distributions 	    "Idle threshold is converted to pages");
81*d4514f0bSApple OSS Distributions 
82*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.soft_threshold_mb",
83*d4514f0bSApple OSS Distributions 	    &threshold_mb, &threshold_size, NULL, 0);
84*d4514f0bSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "Soft threshold can be read");
85*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.soft_threshold_mb",
86*d4514f0bSApple OSS Distributions 	    NULL, 0, &threshold_mb, threshold_size);
87*d4514f0bSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "Soft threshold can be written to");
88*d4514f0bSApple OSS Distributions 	expected_threshold_pages = (threshold_mb << 20) / vm_kernel_page_size;
89*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.soft_threshold_pages",
90*d4514f0bSApple OSS Distributions 	    &threshold_pages, &threshold_size, NULL, 0);
91*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret,
92*d4514f0bSApple OSS Distributions 	    "sysctl(kern.memorystatus.soft_threshold_pages)");
93*d4514f0bSApple OSS Distributions 	T_EXPECT_EQ(threshold_pages, expected_threshold_pages,
94*d4514f0bSApple OSS Distributions 	    "Soft threshold is converted to pages");
95*d4514f0bSApple OSS Distributions }
96*d4514f0bSApple OSS Distributions 
97*d4514f0bSApple OSS Distributions static boolean_t ballast_drained;
98*d4514f0bSApple OSS Distributions static uint32_t prev_offset_mb;
99*d4514f0bSApple OSS Distributions 
100*d4514f0bSApple OSS Distributions static void
ballast_offset_teardown(void)101*d4514f0bSApple OSS Distributions ballast_offset_teardown(void)
102*d4514f0bSApple OSS Distributions {
103*d4514f0bSApple OSS Distributions 	int ret;
104*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.ballast_offset_mb",
105*d4514f0bSApple OSS Distributions 	    NULL, 0, &prev_offset_mb, sizeof(prev_offset_mb));
106*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl(kern.memorystatus.ballast_offset_mb)");
107*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.ballast_drained",
108*d4514f0bSApple OSS Distributions 	    NULL, 0, &ballast_drained, sizeof(ballast_drained));
109*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl(kern.memorystatus.ballast_drained)");
110*d4514f0bSApple OSS Distributions }
111*d4514f0bSApple OSS Distributions 
112*d4514f0bSApple OSS Distributions T_DECL(ballast_offset, "Verify that the ballast offset can be set and toggled")
113*d4514f0bSApple OSS Distributions {
114*d4514f0bSApple OSS Distributions 	int ret;
115*d4514f0bSApple OSS Distributions 	uint32_t threshold_mb, expected_threshold_pages, threshold_pages;
116*d4514f0bSApple OSS Distributions 	size_t threshold_size = sizeof(threshold_mb);
117*d4514f0bSApple OSS Distributions 	size_t ballast_size = sizeof(ballast_drained);
118*d4514f0bSApple OSS Distributions 
119*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.ballast_offset_mb",
120*d4514f0bSApple OSS Distributions 	    &prev_offset_mb, &threshold_size, NULL, 0);
121*d4514f0bSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "Ballast offset can be read");
122*d4514f0bSApple OSS Distributions 
123*d4514f0bSApple OSS Distributions 	threshold_mb = 128;
124*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.ballast_offset_mb",
125*d4514f0bSApple OSS Distributions 	    NULL, 0, &threshold_mb, threshold_size);
126*d4514f0bSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "Ballast offset can be written to");
127*d4514f0bSApple OSS Distributions 
128*d4514f0bSApple OSS Distributions 	expected_threshold_pages = (threshold_mb << 20) / vm_kernel_page_size;
129*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.ballast_offset_pages",
130*d4514f0bSApple OSS Distributions 	    &threshold_pages, &threshold_size, NULL, 0);
131*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret,
132*d4514f0bSApple OSS Distributions 	    "sysctl(kern.memorystatus.ballast_offset_pages)");
133*d4514f0bSApple OSS Distributions 	T_EXPECT_EQ(threshold_pages, expected_threshold_pages,
134*d4514f0bSApple OSS Distributions 	    "Ballast offset is converted to pages");
135*d4514f0bSApple OSS Distributions 
136*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.ballast_drained",
137*d4514f0bSApple OSS Distributions 	    &ballast_drained, &ballast_size, NULL, 0);
138*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl(kern.memorystatus.ballast_drained)");
139*d4514f0bSApple OSS Distributions 	T_LOG("Ballast drained: %d", ballast_drained);
140*d4514f0bSApple OSS Distributions 
141*d4514f0bSApple OSS Distributions 	uint32_t critical_before, idle_before, soft_before;
142*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.soft_threshold_pages",
143*d4514f0bSApple OSS Distributions 	    &soft_before, &threshold_size, NULL, 0);
144*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret,
145*d4514f0bSApple OSS Distributions 	    "sysctl(kern.memorystatus.soft_threshold_pages)");
146*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.idle_threshold_pages",
147*d4514f0bSApple OSS Distributions 	    &idle_before, &threshold_size, NULL, 0);
148*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret,
149*d4514f0bSApple OSS Distributions 	    "sysctl(kern.memorystatus.idle_threshold_pages)");
150*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.critical_threshold_pages",
151*d4514f0bSApple OSS Distributions 	    &critical_before, &threshold_size, NULL, 0);
152*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret,
153*d4514f0bSApple OSS Distributions 	    "sysctl(kern.memorystatus.critical_threshold_pages)");
154*d4514f0bSApple OSS Distributions 	T_LOG("Pre-toggle: crit=%u idle=%u soft=%u", critical_before, idle_before, soft_before);
155*d4514f0bSApple OSS Distributions 
156*d4514f0bSApple OSS Distributions 	T_LOG("Toggling ballast");
157*d4514f0bSApple OSS Distributions 	boolean_t toggled_ballast_drained = !ballast_drained;
158*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.ballast_drained",
159*d4514f0bSApple OSS Distributions 	    NULL, 0, &toggled_ballast_drained, sizeof(prev_offset_mb));
160*d4514f0bSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "sysctl(kern.memorystatus.ballast_drained");
161*d4514f0bSApple OSS Distributions 	T_ATEND(ballast_offset_teardown);
162*d4514f0bSApple OSS Distributions 
163*d4514f0bSApple OSS Distributions 	uint32_t critical_after, idle_after, soft_after;
164*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.soft_threshold_pages",
165*d4514f0bSApple OSS Distributions 	    &soft_after, &threshold_size, NULL, 0);
166*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret,
167*d4514f0bSApple OSS Distributions 	    "sysctl(kern.memorystatus.soft_threshold_pages)");
168*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.idle_threshold_pages",
169*d4514f0bSApple OSS Distributions 	    &idle_after, &threshold_size, NULL, 0);
170*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret,
171*d4514f0bSApple OSS Distributions 	    "sysctl(kern.memorystatus.idle_threshold_pages)");
172*d4514f0bSApple OSS Distributions 	ret = sysctlbyname("kern.memorystatus.critical_threshold_pages",
173*d4514f0bSApple OSS Distributions 	    &critical_after, &threshold_size, NULL, 0);
174*d4514f0bSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret,
175*d4514f0bSApple OSS Distributions 	    "sysctl(kern.memorystatus.critical_threshold_pages)");
176*d4514f0bSApple OSS Distributions 	T_LOG("Post-toggle: crit=%u idle=%u soft=%u", critical_after, idle_after, soft_after);
177*d4514f0bSApple OSS Distributions 
178*d4514f0bSApple OSS Distributions 	if (ballast_drained) {
179*d4514f0bSApple OSS Distributions 		T_QUIET; T_ASSERT_GT(soft_before, soft_after, "Soft threshold decreased");
180*d4514f0bSApple OSS Distributions 		T_EXPECT_EQ(soft_before - soft_after, threshold_pages, "Soft threshold is raised by ballast offset");
181*d4514f0bSApple OSS Distributions 		T_QUIET; T_ASSERT_GT(idle_before, idle_after, "Idle threshold decreased");
182*d4514f0bSApple OSS Distributions 		T_EXPECT_EQ(idle_before - idle_after, threshold_pages, "Idle threshold is raised by ballast offset");
183*d4514f0bSApple OSS Distributions 	} else {
184*d4514f0bSApple OSS Distributions 		T_QUIET; T_ASSERT_LT(soft_before, soft_after, "Soft threshold increased");
185*d4514f0bSApple OSS Distributions 		T_EXPECT_EQ(soft_after - soft_before, threshold_pages, "Soft threshold is raised by ballast offset");
186*d4514f0bSApple OSS Distributions 		T_QUIET; T_ASSERT_LT(idle_before, idle_after, "Idle threshold increased");
187*d4514f0bSApple OSS Distributions 		T_EXPECT_EQ(idle_after - idle_before, threshold_pages, "Idle threshold is raised by ballast offset");
188*d4514f0bSApple OSS Distributions 	}
189*d4514f0bSApple OSS Distributions 
190*d4514f0bSApple OSS Distributions 	T_EXPECT_EQ(critical_before, critical_after, "Critical threshold is unchanged");
191*d4514f0bSApple OSS Distributions }
192