xref: /xnu-8020.140.41/tests/vm/memorystatus_sort_test.c (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
1*27b03b36SApple OSS Distributions #include <signal.h>
2*27b03b36SApple OSS Distributions #include <spawn.h>
3*27b03b36SApple OSS Distributions #include <stdlib.h>
4*27b03b36SApple OSS Distributions #include <sys/sysctl.h>
5*27b03b36SApple OSS Distributions 
6*27b03b36SApple OSS Distributions #include <darwintest.h>
7*27b03b36SApple OSS Distributions #include <dispatch/dispatch.h>
8*27b03b36SApple OSS Distributions #include <mach-o/dyld.h>
9*27b03b36SApple OSS Distributions 
10*27b03b36SApple OSS Distributions /* internal */
11*27b03b36SApple OSS Distributions #include <spawn_private.h>
12*27b03b36SApple OSS Distributions #include <sys/coalition.h>
13*27b03b36SApple OSS Distributions #include <sys/kern_memorystatus.h>
14*27b03b36SApple OSS Distributions 
15*27b03b36SApple OSS Distributions T_GLOBAL_META(
16*27b03b36SApple OSS Distributions 	T_META_NAMESPACE("xnu.vm"),
17*27b03b36SApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
18*27b03b36SApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("VM"));
19*27b03b36SApple OSS Distributions 
20*27b03b36SApple OSS Distributions #define JETSAM_PRIORITY_IDLE 0
21*27b03b36SApple OSS Distributions #define JETSAM_PRIORITY_FOREGROUND 10
22*27b03b36SApple OSS Distributions 
23*27b03b36SApple OSS Distributions #define kNumProcsInCoalition 4
24*27b03b36SApple OSS Distributions typedef struct {
25*27b03b36SApple OSS Distributions 	pid_t pids[kNumProcsInCoalition]; // An array of pids in this coalition. Owned by this struct.
26*27b03b36SApple OSS Distributions 	pid_t expected_order[kNumProcsInCoalition]; // An array of pids in this coalition in proper sorted order.
27*27b03b36SApple OSS Distributions 	uint64_t ids[COALITION_NUM_TYPES];
28*27b03b36SApple OSS Distributions } coalition_info_t;
29*27b03b36SApple OSS Distributions 
30*27b03b36SApple OSS Distributions /*
31*27b03b36SApple OSS Distributions  * Children pids spawned by this test that need to be cleaned up.
32*27b03b36SApple OSS Distributions  * Has to be a global because the T_ATEND API doesn't take any arguments.
33*27b03b36SApple OSS Distributions  */
34*27b03b36SApple OSS Distributions #define kMaxChildrenProcs 16
35*27b03b36SApple OSS Distributions static pid_t children_pids[kMaxChildrenProcs];
36*27b03b36SApple OSS Distributions static size_t num_children = 0;
37*27b03b36SApple OSS Distributions 
38*27b03b36SApple OSS Distributions /*
39*27b03b36SApple OSS Distributions  * Sets up a new coalition.
40*27b03b36SApple OSS Distributions  */
41*27b03b36SApple OSS Distributions static void init_coalition(coalition_info_t*);
42*27b03b36SApple OSS Distributions 
43*27b03b36SApple OSS Distributions /*
44*27b03b36SApple OSS Distributions  * Places all procs in the coalition in the given band.
45*27b03b36SApple OSS Distributions  */
46*27b03b36SApple OSS Distributions static void place_coalition_in_band(const coalition_info_t *, int band);
47*27b03b36SApple OSS Distributions 
48*27b03b36SApple OSS Distributions /*
49*27b03b36SApple OSS Distributions  * Place the given proc in the given band.
50*27b03b36SApple OSS Distributions  */
51*27b03b36SApple OSS Distributions static void place_proc_in_band(pid_t pid, int band);
52*27b03b36SApple OSS Distributions 
53*27b03b36SApple OSS Distributions /*
54*27b03b36SApple OSS Distributions  * Cleans up any children processes.
55*27b03b36SApple OSS Distributions  */
56*27b03b36SApple OSS Distributions static void cleanup_children(void);
57*27b03b36SApple OSS Distributions 
58*27b03b36SApple OSS Distributions /*
59*27b03b36SApple OSS Distributions  * Check if we're on a kernel where we can test coalitions.
60*27b03b36SApple OSS Distributions  */
61*27b03b36SApple OSS Distributions static bool has_unrestrict_coalitions(void);
62*27b03b36SApple OSS Distributions 
63*27b03b36SApple OSS Distributions /*
64*27b03b36SApple OSS Distributions  * Unrestrict coalition syscalls.
65*27b03b36SApple OSS Distributions  */
66*27b03b36SApple OSS Distributions static void unrestrict_coalitions(void);
67*27b03b36SApple OSS Distributions 
68*27b03b36SApple OSS Distributions /*
69*27b03b36SApple OSS Distributions  * Restrict coalition syscalls
70*27b03b36SApple OSS Distributions  */
71*27b03b36SApple OSS Distributions static void restrict_coalitions(void);
72*27b03b36SApple OSS Distributions 
73*27b03b36SApple OSS Distributions /*
74*27b03b36SApple OSS Distributions  * Allocate the requested number of pages and fault them in.
75*27b03b36SApple OSS Distributions  * Used to achieve a desired footprint.
76*27b03b36SApple OSS Distributions  */
77*27b03b36SApple OSS Distributions static void *allocate_pages(int);
78*27b03b36SApple OSS Distributions 
79*27b03b36SApple OSS Distributions /*
80*27b03b36SApple OSS Distributions  * Get the vm page size.
81*27b03b36SApple OSS Distributions  */
82*27b03b36SApple OSS Distributions static int get_vmpage_size(void);
83*27b03b36SApple OSS Distributions 
84*27b03b36SApple OSS Distributions /*
85*27b03b36SApple OSS Distributions  * Launch a proc with a role in a coalition.
86*27b03b36SApple OSS Distributions  * If coalition_ids is NULL, skip adding the proc to the coalition.
87*27b03b36SApple OSS Distributions  */
88*27b03b36SApple OSS Distributions static pid_t
89*27b03b36SApple OSS Distributions launch_proc_in_coalition(uint64_t *coalition_ids, int role, int num_pages);
90*27b03b36SApple OSS Distributions 
91*27b03b36SApple OSS Distributions /*
92*27b03b36SApple OSS Distributions  * Background process that will munch some memory, signal its parent, and
93*27b03b36SApple OSS Distributions  * then sit in a loop.
94*27b03b36SApple OSS Distributions  */
95*27b03b36SApple OSS Distributions T_HELPER_DECL(coalition_member, "Mock coalition member") {
96*27b03b36SApple OSS Distributions 	int num_pages = 0;
97*27b03b36SApple OSS Distributions 	if (argc == 1) {
98*27b03b36SApple OSS Distributions 		num_pages = atoi(argv[0]);
99*27b03b36SApple OSS Distributions 	}
100*27b03b36SApple OSS Distributions 	allocate_pages(num_pages);
101*27b03b36SApple OSS Distributions 	// Signal to the parent that we've touched all of our pages.
102*27b03b36SApple OSS Distributions 	if (kill(getppid(), SIGUSR1) != 0) {
103*27b03b36SApple OSS Distributions 		T_LOG("Unable to signal to parent process!");
104*27b03b36SApple OSS Distributions 		exit(1);
105*27b03b36SApple OSS Distributions 	}
106*27b03b36SApple OSS Distributions 	while (true) {
107*27b03b36SApple OSS Distributions 		;
108*27b03b36SApple OSS Distributions 	}
109*27b03b36SApple OSS Distributions }
110*27b03b36SApple OSS Distributions 
111*27b03b36SApple OSS Distributions /*
112*27b03b36SApple OSS Distributions  * Test that sorting the fg bucket in coalition order works properly.
113*27b03b36SApple OSS Distributions  * Spawns children in the same coalition in the fg band. Each child
114*27b03b36SApple OSS Distributions  * has a different coalition role. Verifies that the coalition
115*27b03b36SApple OSS Distributions  * is sorted properly by role.
116*27b03b36SApple OSS Distributions  */
117*27b03b36SApple OSS Distributions T_DECL(memorystatus_sort_coalition, "Coalition sort order",
118*27b03b36SApple OSS Distributions     T_META_ASROOT(true)) {
119*27b03b36SApple OSS Distributions 	int ret;
120*27b03b36SApple OSS Distributions 	sig_t res;
121*27b03b36SApple OSS Distributions 	coalition_info_t coalition;
122*27b03b36SApple OSS Distributions 	if (!has_unrestrict_coalitions()) {
123*27b03b36SApple OSS Distributions 		T_SKIP("Unable to test coalitions on this kernel.");
124*27b03b36SApple OSS Distributions 	}
125*27b03b36SApple OSS Distributions 	res = signal(SIGUSR1, SIG_IGN);
126*27b03b36SApple OSS Distributions 	T_WITH_ERRNO; T_ASSERT_NE(res, SIG_ERR, "SIG_IGN SIGUSR1");
127*27b03b36SApple OSS Distributions 	unrestrict_coalitions();
128*27b03b36SApple OSS Distributions 
129*27b03b36SApple OSS Distributions 	// Set up a new coalition with various members.
130*27b03b36SApple OSS Distributions 	init_coalition(&coalition);
131*27b03b36SApple OSS Distributions 	T_ATEND(cleanup_children);
132*27b03b36SApple OSS Distributions 	T_ATEND(restrict_coalitions);
133*27b03b36SApple OSS Distributions 	// Place all procs in the coalition in the foreground band
134*27b03b36SApple OSS Distributions 	place_coalition_in_band(&coalition, JETSAM_PRIORITY_FOREGROUND);
135*27b03b36SApple OSS Distributions 	// Have the kernel sort the foreground bucket and verify that it's
136*27b03b36SApple OSS Distributions 	// sorted correctly.
137*27b03b36SApple OSS Distributions 	ret = memorystatus_control(MEMORYSTATUS_CMD_TEST_JETSAM_SORT, JETSAM_PRIORITY_FOREGROUND, 0,
138*27b03b36SApple OSS Distributions 	    coalition.expected_order, kNumProcsInCoalition * sizeof(pid_t));
139*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(ret, 0, "Error while sorting or validating sorted order.\n"
140*27b03b36SApple OSS Distributions 	    "Check os log output for details.\n"
141*27b03b36SApple OSS Distributions 	    "Look for memorystatus_verify_sort_order.");
142*27b03b36SApple OSS Distributions }
143*27b03b36SApple OSS Distributions 
144*27b03b36SApple OSS Distributions /*
145*27b03b36SApple OSS Distributions  * Test that sorting the idle bucket in footprint order works properly.
146*27b03b36SApple OSS Distributions  *
147*27b03b36SApple OSS Distributions  * Spawns some children with very different footprints in the idle band,
148*27b03b36SApple OSS Distributions  * and then ensures that they get sorted properly.
149*27b03b36SApple OSS Distributions  */
150*27b03b36SApple OSS Distributions T_DECL(memorystatus_sort_footprint, "Footprint sort order",
151*27b03b36SApple OSS Distributions     T_META_ASROOT(true)) {
152*27b03b36SApple OSS Distributions #define kNumChildren 3
153*27b03b36SApple OSS Distributions 	static const int kChildrenFootprints[kNumChildren] = {500, 0, 2500};
154*27b03b36SApple OSS Distributions 	/*
155*27b03b36SApple OSS Distributions 	 * The expected sort order of the children in the order that they were launched.
156*27b03b36SApple OSS Distributions 	 * Used to construct the expected_order pid array.
157*27b03b36SApple OSS Distributions 	 * Note that procs should be sorted in descending footprint order.
158*27b03b36SApple OSS Distributions 	 */
159*27b03b36SApple OSS Distributions 	static const int kExpectedOrder[kNumChildren] = {2, 0, 1};
160*27b03b36SApple OSS Distributions 	static const int kJetsamBand = JETSAM_PRIORITY_IDLE;
161*27b03b36SApple OSS Distributions 	__block pid_t pid;
162*27b03b36SApple OSS Distributions 	 sig_t res;
163*27b03b36SApple OSS Distributions 	dispatch_source_t ds_allocated;
164*27b03b36SApple OSS Distributions 	T_ATEND(cleanup_children);
165*27b03b36SApple OSS Distributions 
166*27b03b36SApple OSS Distributions 	// After we spawn the children, they'll signal that they've touched their pages.
167*27b03b36SApple OSS Distributions 	res = signal(SIGUSR1, SIG_IGN);
168*27b03b36SApple OSS Distributions 	T_WITH_ERRNO; T_ASSERT_NE(res, SIG_ERR, "SIG_IGN SIGUSR1");
169*27b03b36SApple OSS Distributions 	ds_allocated = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGUSR1, 0, dispatch_get_main_queue());
170*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_NOTNULL(ds_allocated, "dispatch_source_create (ds_allocated)");
171*27b03b36SApple OSS Distributions 
172*27b03b36SApple OSS Distributions 	dispatch_source_set_event_handler(ds_allocated, ^{
173*27b03b36SApple OSS Distributions 		if (num_children < kNumChildren) {
174*27b03b36SApple OSS Distributions 			pid = launch_proc_in_coalition(NULL, 0, kChildrenFootprints[num_children]);
175*27b03b36SApple OSS Distributions 			place_proc_in_band(pid, kJetsamBand);
176*27b03b36SApple OSS Distributions 		} else {
177*27b03b36SApple OSS Distributions 			pid_t expected_order[kNumChildren] = {0};
178*27b03b36SApple OSS Distributions 			int ret;
179*27b03b36SApple OSS Distributions 			for (int i = 0; i < kNumChildren; i++) {
180*27b03b36SApple OSS Distributions 				expected_order[i] = children_pids[kExpectedOrder[i]];
181*27b03b36SApple OSS Distributions 			}
182*27b03b36SApple OSS Distributions 			// Verify the sort order
183*27b03b36SApple OSS Distributions 			ret = memorystatus_control(MEMORYSTATUS_CMD_TEST_JETSAM_SORT, kJetsamBand, 0,
184*27b03b36SApple OSS Distributions 			expected_order, sizeof(expected_order));
185*27b03b36SApple OSS Distributions 			T_QUIET; T_ASSERT_EQ(ret, 0, "Error while sorting or validating sorted order.\n"
186*27b03b36SApple OSS Distributions 			    "Check os log output for details.\n"
187*27b03b36SApple OSS Distributions 			    "Look for memorystatus_verify_sort_order.");
188*27b03b36SApple OSS Distributions 			T_END;
189*27b03b36SApple OSS Distributions 		}
190*27b03b36SApple OSS Distributions 	});
191*27b03b36SApple OSS Distributions 	dispatch_activate(ds_allocated);
192*27b03b36SApple OSS Distributions 
193*27b03b36SApple OSS Distributions 	pid = launch_proc_in_coalition(NULL, 0, kChildrenFootprints[num_children]);
194*27b03b36SApple OSS Distributions 	place_proc_in_band(pid, kJetsamBand);
195*27b03b36SApple OSS Distributions 
196*27b03b36SApple OSS Distributions 	dispatch_main();
197*27b03b36SApple OSS Distributions 
198*27b03b36SApple OSS Distributions #undef kNumChildren
199*27b03b36SApple OSS Distributions }
200*27b03b36SApple OSS Distributions 
201*27b03b36SApple OSS Distributions static pid_t
launch_proc_in_coalition(uint64_t * coalition_ids,int role,int num_pages)202*27b03b36SApple OSS Distributions launch_proc_in_coalition(uint64_t *coalition_ids, int role, int num_pages)
203*27b03b36SApple OSS Distributions {
204*27b03b36SApple OSS Distributions 	int ret;
205*27b03b36SApple OSS Distributions 	posix_spawnattr_t attr;
206*27b03b36SApple OSS Distributions 	pid_t pid;
207*27b03b36SApple OSS Distributions 	char testpath[PATH_MAX];
208*27b03b36SApple OSS Distributions 	uint32_t testpath_buf_size = PATH_MAX;
209*27b03b36SApple OSS Distributions 	char num_pages_str[32] = {0};
210*27b03b36SApple OSS Distributions 	char *argv[5] = {testpath, "-n", "coalition_member", num_pages_str, NULL};
211*27b03b36SApple OSS Distributions 	extern char **environ;
212*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_LT(num_children + 1, (size_t) kMaxChildrenProcs, "Don't create too many children.");
213*27b03b36SApple OSS Distributions 	ret = posix_spawnattr_init(&attr);
214*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_ZERO(ret, "posix_spawnattr_init");
215*27b03b36SApple OSS Distributions 	if (coalition_ids != NULL) {
216*27b03b36SApple OSS Distributions 		for (int i = 0; i < COALITION_NUM_TYPES; i++) {
217*27b03b36SApple OSS Distributions 			ret = posix_spawnattr_setcoalition_np(&attr, coalition_ids[i], i, role);
218*27b03b36SApple OSS Distributions 			T_QUIET; T_ASSERT_POSIX_ZERO(ret, "posix_spawnattr_setcoalition_np");
219*27b03b36SApple OSS Distributions 		}
220*27b03b36SApple OSS Distributions 	}
221*27b03b36SApple OSS Distributions 
222*27b03b36SApple OSS Distributions 	ret = snprintf(num_pages_str, sizeof(num_pages_str), "%d", num_pages);
223*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_LE((size_t) ret, sizeof(num_pages_str), "Don't allocate too many pages.");
224*27b03b36SApple OSS Distributions 	ret = _NSGetExecutablePath(testpath, &testpath_buf_size);
225*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(ret, 0, "_NSGetExecutablePath");
226*27b03b36SApple OSS Distributions 	ret = posix_spawn(&pid, argv[0], NULL, &attr, argv, environ);
227*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_ZERO(ret, "posix_spawn");
228*27b03b36SApple OSS Distributions 	ret = posix_spawnattr_destroy(&attr);
229*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_ZERO(ret, "posix_spawnattr_destroy");
230*27b03b36SApple OSS Distributions 	children_pids[num_children++] = pid;
231*27b03b36SApple OSS Distributions 	return pid;
232*27b03b36SApple OSS Distributions }
233*27b03b36SApple OSS Distributions 
234*27b03b36SApple OSS Distributions static void
init_coalition(coalition_info_t * coalition)235*27b03b36SApple OSS Distributions init_coalition(coalition_info_t *coalition)
236*27b03b36SApple OSS Distributions {
237*27b03b36SApple OSS Distributions 	int ret;
238*27b03b36SApple OSS Distributions 	uint32_t flags = 0;
239*27b03b36SApple OSS Distributions 	memset(coalition, 0, sizeof(coalition_info_t));
240*27b03b36SApple OSS Distributions 	for (int i = 0; i < COALITION_NUM_TYPES; i++) {
241*27b03b36SApple OSS Distributions 		COALITION_CREATE_FLAGS_SET_TYPE(flags, i);
242*27b03b36SApple OSS Distributions 		ret = coalition_create(&coalition->ids[i], flags);
243*27b03b36SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(ret, "coalition_create");
244*27b03b36SApple OSS Distributions 	}
245*27b03b36SApple OSS Distributions 
246*27b03b36SApple OSS Distributions 	/*
247*27b03b36SApple OSS Distributions 	 * Spawn procs for each coalition role, and construct the expected
248*27b03b36SApple OSS Distributions 	 * sorted order.
249*27b03b36SApple OSS Distributions 	 */
250*27b03b36SApple OSS Distributions 	for (size_t i = 0; i < kNumProcsInCoalition; i++) {
251*27b03b36SApple OSS Distributions 		int role;
252*27b03b36SApple OSS Distributions 		if (i == 0) {
253*27b03b36SApple OSS Distributions 			role = COALITION_TASKROLE_LEADER;
254*27b03b36SApple OSS Distributions 		} else if (i == 1) {
255*27b03b36SApple OSS Distributions 			role = COALITION_TASKROLE_EXT;
256*27b03b36SApple OSS Distributions 		} else if (i == 2) {
257*27b03b36SApple OSS Distributions 			role = COALITION_TASKROLE_UNDEF;
258*27b03b36SApple OSS Distributions 		} else {
259*27b03b36SApple OSS Distributions 			role = COALITION_TASKROLE_XPC;
260*27b03b36SApple OSS Distributions 		}
261*27b03b36SApple OSS Distributions 		pid_t pid = launch_proc_in_coalition(coalition->ids, role, 0);
262*27b03b36SApple OSS Distributions 		coalition->pids[i] = pid;
263*27b03b36SApple OSS Distributions 		/*
264*27b03b36SApple OSS Distributions 		 * Determine the expected sorted order.
265*27b03b36SApple OSS Distributions 		 * After a bucket has been coalition sorted, coalition members should
266*27b03b36SApple OSS Distributions 		 * be in the following kill order:
267*27b03b36SApple OSS Distributions 		 * undefined coalition members, extensions, xpc services, leader
268*27b03b36SApple OSS Distributions 		 */
269*27b03b36SApple OSS Distributions 		if (role == COALITION_TASKROLE_LEADER) {
270*27b03b36SApple OSS Distributions 			coalition->expected_order[3] = pid;
271*27b03b36SApple OSS Distributions 		} else if (role == COALITION_TASKROLE_XPC) {
272*27b03b36SApple OSS Distributions 			coalition->expected_order[2] = pid;
273*27b03b36SApple OSS Distributions 		} else if (role == COALITION_TASKROLE_EXT) {
274*27b03b36SApple OSS Distributions 			coalition->expected_order[1] = pid;
275*27b03b36SApple OSS Distributions 		} else {
276*27b03b36SApple OSS Distributions 			coalition->expected_order[0] = pid;
277*27b03b36SApple OSS Distributions 		}
278*27b03b36SApple OSS Distributions 	}
279*27b03b36SApple OSS Distributions }
280*27b03b36SApple OSS Distributions 
281*27b03b36SApple OSS Distributions static void
place_proc_in_band(pid_t pid,int band)282*27b03b36SApple OSS Distributions place_proc_in_band(pid_t pid, int band)
283*27b03b36SApple OSS Distributions {
284*27b03b36SApple OSS Distributions 	memorystatus_priority_properties_t props = {0};
285*27b03b36SApple OSS Distributions 	int ret;
286*27b03b36SApple OSS Distributions 	props.priority = band;
287*27b03b36SApple OSS Distributions 	props.user_data = 0;
288*27b03b36SApple OSS Distributions 	ret = memorystatus_control(MEMORYSTATUS_CMD_SET_PRIORITY_PROPERTIES, pid, 0, &props, sizeof(props));
289*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "move proc to band");
290*27b03b36SApple OSS Distributions }
291*27b03b36SApple OSS Distributions 
292*27b03b36SApple OSS Distributions 
293*27b03b36SApple OSS Distributions static void
place_coalition_in_band(const coalition_info_t * coalition,int band)294*27b03b36SApple OSS Distributions place_coalition_in_band(const coalition_info_t *coalition, int band)
295*27b03b36SApple OSS Distributions {
296*27b03b36SApple OSS Distributions 	for (size_t i = 0; i < kNumProcsInCoalition; i++) {
297*27b03b36SApple OSS Distributions 		pid_t curr = coalition->pids[i];
298*27b03b36SApple OSS Distributions 		place_proc_in_band(curr, band);
299*27b03b36SApple OSS Distributions 	}
300*27b03b36SApple OSS Distributions }
301*27b03b36SApple OSS Distributions 
302*27b03b36SApple OSS Distributions static void
cleanup_children(void)303*27b03b36SApple OSS Distributions cleanup_children(void)
304*27b03b36SApple OSS Distributions {
305*27b03b36SApple OSS Distributions 	int ret, status;
306*27b03b36SApple OSS Distributions 	for (size_t i = 0; i < num_children; i++) {
307*27b03b36SApple OSS Distributions 		pid_t exited_pid = 0;
308*27b03b36SApple OSS Distributions 		pid_t curr = children_pids[i];
309*27b03b36SApple OSS Distributions 		ret = kill(curr, SIGKILL);
310*27b03b36SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "kill");
311*27b03b36SApple OSS Distributions 		while (exited_pid == 0) {
312*27b03b36SApple OSS Distributions 			exited_pid = waitpid(curr, &status, 0);
313*27b03b36SApple OSS Distributions 		}
314*27b03b36SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(exited_pid, "waitpid");
315*27b03b36SApple OSS Distributions 		T_QUIET; T_ASSERT_TRUE(WIFSIGNALED(status), "proc was signaled.");
316*27b03b36SApple OSS Distributions 		T_QUIET; T_ASSERT_EQ(WTERMSIG(status), SIGKILL, "proc was killed");
317*27b03b36SApple OSS Distributions 	}
318*27b03b36SApple OSS Distributions }
319*27b03b36SApple OSS Distributions 
320*27b03b36SApple OSS Distributions static bool
has_unrestrict_coalitions()321*27b03b36SApple OSS Distributions has_unrestrict_coalitions()
322*27b03b36SApple OSS Distributions {
323*27b03b36SApple OSS Distributions 	int ret, val;
324*27b03b36SApple OSS Distributions 	size_t val_sz;
325*27b03b36SApple OSS Distributions 
326*27b03b36SApple OSS Distributions 	val = 0;
327*27b03b36SApple OSS Distributions 	val_sz = sizeof(val);
328*27b03b36SApple OSS Distributions 	ret = sysctlbyname("kern.unrestrict_coalitions", &val, &val_sz, NULL, 0);
329*27b03b36SApple OSS Distributions 	return ret >= 0;
330*27b03b36SApple OSS Distributions }
331*27b03b36SApple OSS Distributions 
332*27b03b36SApple OSS Distributions static void
unrestrict_coalitions()333*27b03b36SApple OSS Distributions unrestrict_coalitions()
334*27b03b36SApple OSS Distributions {
335*27b03b36SApple OSS Distributions 	int ret, val = 1;
336*27b03b36SApple OSS Distributions 	size_t val_sz;
337*27b03b36SApple OSS Distributions 	val_sz = sizeof(val);
338*27b03b36SApple OSS Distributions 	ret = sysctlbyname("kern.unrestrict_coalitions", NULL, 0, &val, val_sz);
339*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "kern.unrestrict_coalitions <- 1");
340*27b03b36SApple OSS Distributions }
341*27b03b36SApple OSS Distributions 
342*27b03b36SApple OSS Distributions static void
restrict_coalitions()343*27b03b36SApple OSS Distributions restrict_coalitions()
344*27b03b36SApple OSS Distributions {
345*27b03b36SApple OSS Distributions 	int ret, val = 0;
346*27b03b36SApple OSS Distributions 	size_t val_sz;
347*27b03b36SApple OSS Distributions 	val_sz = sizeof(val);
348*27b03b36SApple OSS Distributions 	ret = sysctlbyname("kern.unrestrict_coalitions", NULL, 0, &val, val_sz);
349*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "kern.unrestrict_coalitions <- 0");
350*27b03b36SApple OSS Distributions }
351*27b03b36SApple OSS Distributions 
352*27b03b36SApple OSS Distributions static void *
allocate_pages(int num_pages)353*27b03b36SApple OSS Distributions allocate_pages(int num_pages)
354*27b03b36SApple OSS Distributions {
355*27b03b36SApple OSS Distributions 	int page_size, i;
356*27b03b36SApple OSS Distributions 	unsigned char *buf;
357*27b03b36SApple OSS Distributions 
358*27b03b36SApple OSS Distributions 	page_size = get_vmpage_size();
359*27b03b36SApple OSS Distributions 	buf = malloc((unsigned long)(num_pages * page_size));
360*27b03b36SApple OSS Distributions 	for (i = 0; i < num_pages; i++) {
361*27b03b36SApple OSS Distributions 		((volatile unsigned char *)buf)[i * page_size] = 1;
362*27b03b36SApple OSS Distributions 	}
363*27b03b36SApple OSS Distributions 	return buf;
364*27b03b36SApple OSS Distributions }
365*27b03b36SApple OSS Distributions 
366*27b03b36SApple OSS Distributions static int
get_vmpage_size()367*27b03b36SApple OSS Distributions get_vmpage_size()
368*27b03b36SApple OSS Distributions {
369*27b03b36SApple OSS Distributions 	int vmpage_size;
370*27b03b36SApple OSS Distributions 	size_t size = sizeof(vmpage_size);
371*27b03b36SApple OSS Distributions 	int ret = sysctlbyname("vm.pagesize", &vmpage_size, &size, NULL, 0);
372*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "failed to query vm.pagesize");
373*27b03b36SApple OSS Distributions 	T_QUIET; T_ASSERT_GT(vmpage_size, 0, "vm.pagesize is not > 0");
374*27b03b36SApple OSS Distributions 	return vmpage_size;
375*27b03b36SApple OSS Distributions }
376