xref: /xnu-12377.41.6/tests/memorystatus_is_assertion.c (revision bbb1b6f9e71b8cdde6e5cd6f4841f207dee3d828) !
1*bbb1b6f9SApple OSS Distributions #include <stdio.h>
2*bbb1b6f9SApple OSS Distributions #include <unistd.h>
3*bbb1b6f9SApple OSS Distributions #include <stdlib.h>
4*bbb1b6f9SApple OSS Distributions #include <errno.h>
5*bbb1b6f9SApple OSS Distributions #include <string.h>
6*bbb1b6f9SApple OSS Distributions #include <assert.h>
7*bbb1b6f9SApple OSS Distributions #include <signal.h>
8*bbb1b6f9SApple OSS Distributions #include <spawn.h>
9*bbb1b6f9SApple OSS Distributions #include <spawn_private.h>
10*bbb1b6f9SApple OSS Distributions #include <stdint.h>
11*bbb1b6f9SApple OSS Distributions #include <sys/sysctl.h>
12*bbb1b6f9SApple OSS Distributions #include <sys/spawn_internal.h>
13*bbb1b6f9SApple OSS Distributions #include <sys/kern_memorystatus.h>
14*bbb1b6f9SApple OSS Distributions #include <mach-o/dyld.h>
15*bbb1b6f9SApple OSS Distributions #include <os/voucher_private.h>
16*bbb1b6f9SApple OSS Distributions 
17*bbb1b6f9SApple OSS Distributions #include <darwintest.h>
18*bbb1b6f9SApple OSS Distributions #include <darwintest_multiprocess.h>
19*bbb1b6f9SApple OSS Distributions #include <darwintest_utils.h>
20*bbb1b6f9SApple OSS Distributions 
21*bbb1b6f9SApple OSS Distributions #include "memorystatus_assertion_helpers.h"
22*bbb1b6f9SApple OSS Distributions 
23*bbb1b6f9SApple OSS Distributions T_GLOBAL_META(
24*bbb1b6f9SApple OSS Distributions 	T_META_NAMESPACE("xnu.memorystatus"),
25*bbb1b6f9SApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
26*bbb1b6f9SApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("VM"),
27*bbb1b6f9SApple OSS Distributions 	T_META_CHECK_LEAKS(false),
28*bbb1b6f9SApple OSS Distributions 	T_META_RUN_CONCURRENTLY(true),
29*bbb1b6f9SApple OSS Distributions 	T_META_TAG_VM_PREFERRED,
30*bbb1b6f9SApple OSS Distributions 	T_META_BOOTARGS_SET("memstat_no_task_limit_increase=1")
31*bbb1b6f9SApple OSS Distributions 	);
32*bbb1b6f9SApple OSS Distributions 
33*bbb1b6f9SApple OSS Distributions #define IDLE_AGEOUT_S 30
34*bbb1b6f9SApple OSS Distributions #define AGEOUT_STUCK_S 35
35*bbb1b6f9SApple OSS Distributions 
36*bbb1b6f9SApple OSS Distributions /*
37*bbb1b6f9SApple OSS Distributions  * This test has multiple sub-tests that set and then verify jetsam priority transitions
38*bbb1b6f9SApple OSS Distributions  * as though they were driven by assertions. It uses the MEMORYSTATUS_CMD_SET_MEMLIMIT_PROPERTIES
39*bbb1b6f9SApple OSS Distributions  * version of the memorystatus_control() system call and specifically tests the use of the
40*bbb1b6f9SApple OSS Distributions  * MEMORYSTATUS_SET_PRIORITY_ASSERTION flag.
41*bbb1b6f9SApple OSS Distributions  *
42*bbb1b6f9SApple OSS Distributions  * The kernel will apply policy that chooses a maximum jetsam priority, resolving conflicts
43*bbb1b6f9SApple OSS Distributions  * between an assertion driven priority and clean/dirty transition policy.
44*bbb1b6f9SApple OSS Distributions  *
45*bbb1b6f9SApple OSS Distributions  * Processes that do not opt into dirty-tracking should behave as they always have.
46*bbb1b6f9SApple OSS Distributions  * This is the typical App transition behavior.
47*bbb1b6f9SApple OSS Distributions  *
48*bbb1b6f9SApple OSS Distributions  * Processes that do opt into dirty-tracking have more complex policy:
49*bbb1b6f9SApple OSS Distributions  * For example:
50*bbb1b6f9SApple OSS Distributions  * A MAX assertion priority will prevent a dirty process from transitioning to a clean
51*bbb1b6f9SApple OSS Distributions  * state if the process opts into idle-exit.
52*bbb1b6f9SApple OSS Distributions  *    See: memorystatus_schedule_idle_demotion_locked() where we note that
53*bbb1b6f9SApple OSS Distributions  *    the process isn't going to be making the trip to the lower bands.
54*bbb1b6f9SApple OSS Distributions  *
55*bbb1b6f9SApple OSS Distributions  * But a MAX assertion evaluation will not prevent a clean process from transition to dirty.
56*bbb1b6f9SApple OSS Distributions  * Assertion driven priorities should not change memory limits, they are expected to
57*bbb1b6f9SApple OSS Distributions  * just change a process's position in the jetsam priority bands.
58*bbb1b6f9SApple OSS Distributions  *
59*bbb1b6f9SApple OSS Distributions  * MEMORYSTATUS_CMD_xxx requires root (in the absence of entitlement).
60*bbb1b6f9SApple OSS Distributions  * Use T_META_ASROOT(true) to accomplish this.
61*bbb1b6f9SApple OSS Distributions  *
62*bbb1b6f9SApple OSS Distributions  * A note on test strategy.  It is not necessary to spawn a child to test these
63*bbb1b6f9SApple OSS Distributions  * assertion calls.   The test can act on itself, that is, it can make calls to
64*bbb1b6f9SApple OSS Distributions  * set and relinquish assertion state just like it can make calls to do dirty/clean
65*bbb1b6f9SApple OSS Distributions  * transitions.  Of course, in reality, we expect only runningboardd to manipulate
66*bbb1b6f9SApple OSS Distributions  * assertion based priorities.
67*bbb1b6f9SApple OSS Distributions  */
68*bbb1b6f9SApple OSS Distributions 
69*bbb1b6f9SApple OSS Distributions static void
proc_will_set_clean(pid_t pid)70*bbb1b6f9SApple OSS Distributions proc_will_set_clean(pid_t pid)
71*bbb1b6f9SApple OSS Distributions {
72*bbb1b6f9SApple OSS Distributions 	proc_set_dirty(pid, false);
73*bbb1b6f9SApple OSS Distributions 	T_LOG("pid[%d] --> now clean", pid);
74*bbb1b6f9SApple OSS Distributions 	return;
75*bbb1b6f9SApple OSS Distributions }
76*bbb1b6f9SApple OSS Distributions 
77*bbb1b6f9SApple OSS Distributions static void
proc_will_set_dirty(pid_t pid)78*bbb1b6f9SApple OSS Distributions proc_will_set_dirty(pid_t pid)
79*bbb1b6f9SApple OSS Distributions {
80*bbb1b6f9SApple OSS Distributions 	proc_set_dirty(pid, true);
81*bbb1b6f9SApple OSS Distributions 	T_LOG("pid[%d] --> now dirty", pid);
82*bbb1b6f9SApple OSS Distributions 	return;
83*bbb1b6f9SApple OSS Distributions }
84*bbb1b6f9SApple OSS Distributions 
85*bbb1b6f9SApple OSS Distributions static void
proc_set_managed(pid_t pid,bool managed)86*bbb1b6f9SApple OSS Distributions proc_set_managed(pid_t pid, bool managed)
87*bbb1b6f9SApple OSS Distributions {
88*bbb1b6f9SApple OSS Distributions 	int err;
89*bbb1b6f9SApple OSS Distributions 	err = memorystatus_control(MEMORYSTATUS_CMD_SET_PROCESS_IS_MANAGED, pid,
90*bbb1b6f9SApple OSS Distributions 	    managed, NULL, 0);
91*bbb1b6f9SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(err,
92*bbb1b6f9SApple OSS Distributions 	    "memorystatus_control(MEMORYSTATUS_CMD_SET_PROCESS_IS_MANAGED)");
93*bbb1b6f9SApple OSS Distributions }
94*bbb1b6f9SApple OSS Distributions 
95*bbb1b6f9SApple OSS Distributions /*
96*bbb1b6f9SApple OSS Distributions  * Make repetitive (eg: back-to-back) calls using MEMORYSTATUS_SET_PRIORITY_ASSERTION.
97*bbb1b6f9SApple OSS Distributions  * We know that runningboardd may try to relinquish its hold on an assertion priority
98*bbb1b6f9SApple OSS Distributions  * when it hasn't first set the assertion priority. The kernel must survive this
99*bbb1b6f9SApple OSS Distributions  * pattern even though it might be considered poor behavior on runningboardd's part.
100*bbb1b6f9SApple OSS Distributions  * When dirty tracking processes are involved, we are exercising the kernel's
101*bbb1b6f9SApple OSS Distributions  * idle-deferred paths. Only assertion state (whether or not assertion state is
102*bbb1b6f9SApple OSS Distributions  * set or relinquished) is verified in this round of tests.
103*bbb1b6f9SApple OSS Distributions  * Test is invoked three times:
104*bbb1b6f9SApple OSS Distributions  *	Scenario 1) as a non-dirty-tracking process  (like a typical app)
105*bbb1b6f9SApple OSS Distributions  *		relinquish assertion priority multiple times
106*bbb1b6f9SApple OSS Distributions  *		set same assertion priority multiple times.
107*bbb1b6f9SApple OSS Distributions  *	Scenario 2) setup a dirty-tracking process that is clean  (like a typical extension)
108*bbb1b6f9SApple OSS Distributions  *		relinquish assertion priority multiple times
109*bbb1b6f9SApple OSS Distributions  *		set same assertion priority multiple times.
110*bbb1b6f9SApple OSS Distributions  *	Scenario 3) setup dirty-tracking process that is dirty  (like a typical extension)
111*bbb1b6f9SApple OSS Distributions  *		relinquish assertion priority multiple times
112*bbb1b6f9SApple OSS Distributions  *		set same assertion priority multiple times.
113*bbb1b6f9SApple OSS Distributions  */
114*bbb1b6f9SApple OSS Distributions 
115*bbb1b6f9SApple OSS Distributions static void
memorystatus_assertion_test_repetitive(char * test,boolean_t turn_on_dirty_tracking,boolean_t start_clean)116*bbb1b6f9SApple OSS Distributions memorystatus_assertion_test_repetitive(char *test, boolean_t turn_on_dirty_tracking, boolean_t start_clean)
117*bbb1b6f9SApple OSS Distributions {
118*bbb1b6f9SApple OSS Distributions 	int count;
119*bbb1b6f9SApple OSS Distributions 	int maxcount = 3;
120*bbb1b6f9SApple OSS Distributions 	boolean_t verbose;
121*bbb1b6f9SApple OSS Distributions 	uint32_t state;
122*bbb1b6f9SApple OSS Distributions 	uint64_t user_data = 0;
123*bbb1b6f9SApple OSS Distributions 	pid_t mypid = getpid();
124*bbb1b6f9SApple OSS Distributions 
125*bbb1b6f9SApple OSS Distributions 	/* these values will remain fixed during testing */
126*bbb1b6f9SApple OSS Distributions 	int             active_limit_mb = 35;   /* arbitrary */
127*bbb1b6f9SApple OSS Distributions 	int             inactive_limit_mb = 25;  /* arbitrary */
128*bbb1b6f9SApple OSS Distributions 
129*bbb1b6f9SApple OSS Distributions 	/* these values may vary during test */
130*bbb1b6f9SApple OSS Distributions 	int             requestedpriority = 0;
131*bbb1b6f9SApple OSS Distributions 	int             assertionpriority = 0;
132*bbb1b6f9SApple OSS Distributions 
133*bbb1b6f9SApple OSS Distributions 	T_SETUPBEGIN;
134*bbb1b6f9SApple OSS Distributions 
135*bbb1b6f9SApple OSS Distributions 	requestedpriority =  JETSAM_PRIORITY_UI_SUPPORT;
136*bbb1b6f9SApple OSS Distributions 	assertionpriority =  JETSAM_PRIORITY_FOREGROUND;
137*bbb1b6f9SApple OSS Distributions 	set_memlimits(mypid, active_limit_mb, inactive_limit_mb, true, true);
138*bbb1b6f9SApple OSS Distributions 	set_priority(mypid, requestedpriority, 0, false);
139*bbb1b6f9SApple OSS Distributions 
140*bbb1b6f9SApple OSS Distributions 	if (turn_on_dirty_tracking) {
141*bbb1b6f9SApple OSS Distributions 		proc_track_dirty(mypid, (PROC_DIRTY_TRACK | PROC_DIRTY_ALLOW_IDLE_EXIT | PROC_DIRTY_DEFER));
142*bbb1b6f9SApple OSS Distributions 
143*bbb1b6f9SApple OSS Distributions 		if (start_clean) {
144*bbb1b6f9SApple OSS Distributions 			proc_will_set_clean(mypid);
145*bbb1b6f9SApple OSS Distributions 		} else {
146*bbb1b6f9SApple OSS Distributions 			proc_will_set_dirty(mypid);
147*bbb1b6f9SApple OSS Distributions 		}
148*bbb1b6f9SApple OSS Distributions 	} else {
149*bbb1b6f9SApple OSS Distributions 		/*
150*bbb1b6f9SApple OSS Distributions 		 * Do nothing.
151*bbb1b6f9SApple OSS Distributions 		 * Acts like an app with no dirty tracking
152*bbb1b6f9SApple OSS Distributions 		 * By default launches in the requested priority and is
153*bbb1b6f9SApple OSS Distributions 		 * considered idle because it's below FG band.
154*bbb1b6f9SApple OSS Distributions 		 */
155*bbb1b6f9SApple OSS Distributions 	}
156*bbb1b6f9SApple OSS Distributions 
157*bbb1b6f9SApple OSS Distributions 	proc_set_managed(mypid, true);
158*bbb1b6f9SApple OSS Distributions 
159*bbb1b6f9SApple OSS Distributions 	verbose = false;
160*bbb1b6f9SApple OSS Distributions 	(void)get_priority_props(mypid, verbose, NULL, NULL, NULL, NULL);
161*bbb1b6f9SApple OSS Distributions 
162*bbb1b6f9SApple OSS Distributions 	/* log current setup state */
163*bbb1b6f9SApple OSS Distributions 	T_LOG("SETUP STATE COMPLETE: Test %s", test);
164*bbb1b6f9SApple OSS Distributions 
165*bbb1b6f9SApple OSS Distributions 	T_SETUPEND;
166*bbb1b6f9SApple OSS Distributions 
167*bbb1b6f9SApple OSS Distributions 	int i;
168*bbb1b6f9SApple OSS Distributions 	boolean_t ret;
169*bbb1b6f9SApple OSS Distributions 	for (i = 0; i < 2; i++) {
170*bbb1b6f9SApple OSS Distributions 		if (i == 1 && turn_on_dirty_tracking) {
171*bbb1b6f9SApple OSS Distributions 			T_LOG("Avoid idle-deferred - sleeping for %d s", IDLE_AGEOUT_S);
172*bbb1b6f9SApple OSS Distributions 			sleep(IDLE_AGEOUT_S);
173*bbb1b6f9SApple OSS Distributions 
174*bbb1b6f9SApple OSS Distributions 			if (start_clean) {
175*bbb1b6f9SApple OSS Distributions 				proc_will_set_dirty(mypid);
176*bbb1b6f9SApple OSS Distributions 			} else {
177*bbb1b6f9SApple OSS Distributions 				proc_will_set_clean(mypid);
178*bbb1b6f9SApple OSS Distributions 			}
179*bbb1b6f9SApple OSS Distributions 
180*bbb1b6f9SApple OSS Distributions 			(void)get_priority_props(mypid, verbose, NULL, NULL, NULL, &state);
181*bbb1b6f9SApple OSS Distributions 		}
182*bbb1b6f9SApple OSS Distributions 
183*bbb1b6f9SApple OSS Distributions 		/*
184*bbb1b6f9SApple OSS Distributions 		 * Relinquish assertion priority even though we don't
185*bbb1b6f9SApple OSS Distributions 		 * currently hold an assertion priority.
186*bbb1b6f9SApple OSS Distributions 		 */
187*bbb1b6f9SApple OSS Distributions 		for (count = 0; count < maxcount; count++) {
188*bbb1b6f9SApple OSS Distributions 			if (relinquish_assertion_priority(mypid, user_data)) {
189*bbb1b6f9SApple OSS Distributions 				T_ASSERT_FAIL("relinquish_assertion_priority failed");
190*bbb1b6f9SApple OSS Distributions 			}
191*bbb1b6f9SApple OSS Distributions 		}
192*bbb1b6f9SApple OSS Distributions 
193*bbb1b6f9SApple OSS Distributions 		/* Verify assertion state is relinquished */
194*bbb1b6f9SApple OSS Distributions 		(void)get_priority_props(mypid, verbose, NULL, NULL, NULL, &state);
195*bbb1b6f9SApple OSS Distributions 
196*bbb1b6f9SApple OSS Distributions 		ret = verify_assertion_state(state, ASSERTION_STATE_IS_RELINQUISHED);
197*bbb1b6f9SApple OSS Distributions 		T_QUIET;
198*bbb1b6f9SApple OSS Distributions 		T_ASSERT_TRUE(ret, "verify_assertion_state failed");
199*bbb1b6f9SApple OSS Distributions 
200*bbb1b6f9SApple OSS Distributions 
201*bbb1b6f9SApple OSS Distributions 
202*bbb1b6f9SApple OSS Distributions 		/*
203*bbb1b6f9SApple OSS Distributions 		 * Set an assertion priority multiple times in a row.
204*bbb1b6f9SApple OSS Distributions 		 */
205*bbb1b6f9SApple OSS Distributions 		for (count = 0; count < maxcount; count++) {
206*bbb1b6f9SApple OSS Distributions 			if (set_assertion_priority(mypid, assertionpriority, user_data) != 0) {
207*bbb1b6f9SApple OSS Distributions 				T_ASSERT_FAIL("set_assertion_priority failed");
208*bbb1b6f9SApple OSS Distributions 			}
209*bbb1b6f9SApple OSS Distributions 		}
210*bbb1b6f9SApple OSS Distributions 
211*bbb1b6f9SApple OSS Distributions 		/* Verify state holds an assertion priority */
212*bbb1b6f9SApple OSS Distributions 		(void)get_priority_props(mypid, verbose, NULL, NULL, NULL, &state);
213*bbb1b6f9SApple OSS Distributions 
214*bbb1b6f9SApple OSS Distributions 		ret = verify_assertion_state(state, ASSERTION_STATE_IS_SET);
215*bbb1b6f9SApple OSS Distributions 		T_QUIET;
216*bbb1b6f9SApple OSS Distributions 		T_ASSERT_TRUE(ret, "verify_assertion_state failed");
217*bbb1b6f9SApple OSS Distributions 	}
218*bbb1b6f9SApple OSS Distributions }
219*bbb1b6f9SApple OSS Distributions 
220*bbb1b6f9SApple OSS Distributions /*
221*bbb1b6f9SApple OSS Distributions  * Process is dirty tracking and opts into pressured exit.
222*bbb1b6f9SApple OSS Distributions  */
223*bbb1b6f9SApple OSS Distributions static void
memorystatus_assertion_test_allow_idle_exit(void)224*bbb1b6f9SApple OSS Distributions memorystatus_assertion_test_allow_idle_exit(void)
225*bbb1b6f9SApple OSS Distributions {
226*bbb1b6f9SApple OSS Distributions 	pid_t mypid = getpid();
227*bbb1b6f9SApple OSS Distributions 
228*bbb1b6f9SApple OSS Distributions 	/* these values will remain fixed during testing */
229*bbb1b6f9SApple OSS Distributions 	int active_limit_mb   = 35; /* arbitrary */
230*bbb1b6f9SApple OSS Distributions 	int inactive_limit_mb = 25;  /* arbitrary */
231*bbb1b6f9SApple OSS Distributions 
232*bbb1b6f9SApple OSS Distributions 	/* these values may vary during test */
233*bbb1b6f9SApple OSS Distributions 	int requestedpriority = JETSAM_PRIORITY_UI_SUPPORT;
234*bbb1b6f9SApple OSS Distributions 
235*bbb1b6f9SApple OSS Distributions 	T_SETUPBEGIN;
236*bbb1b6f9SApple OSS Distributions 
237*bbb1b6f9SApple OSS Distributions 	set_memlimits(mypid, active_limit_mb, inactive_limit_mb, true, true);
238*bbb1b6f9SApple OSS Distributions 	set_priority(mypid, requestedpriority, 0, false);
239*bbb1b6f9SApple OSS Distributions 
240*bbb1b6f9SApple OSS Distributions 	proc_track_dirty(mypid, (PROC_DIRTY_TRACK | PROC_DIRTY_ALLOW_IDLE_EXIT | PROC_DIRTY_DEFER));
241*bbb1b6f9SApple OSS Distributions 	proc_set_managed(mypid, true);
242*bbb1b6f9SApple OSS Distributions 
243*bbb1b6f9SApple OSS Distributions 	proc_will_set_clean(mypid);
244*bbb1b6f9SApple OSS Distributions 
245*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_IDLE_DEFERRED, active_limit_mb, 0x0, ASSERTION_STATE_IS_RELINQUISHED, "Clean start");
246*bbb1b6f9SApple OSS Distributions 
247*bbb1b6f9SApple OSS Distributions 	T_LOG("SETUP STATE COMPLETE");
248*bbb1b6f9SApple OSS Distributions 
249*bbb1b6f9SApple OSS Distributions 	int g_jetsam_aging_policy = 0;
250*bbb1b6f9SApple OSS Distributions 	/*
251*bbb1b6f9SApple OSS Distributions 	 * Jetsam aging policy
252*bbb1b6f9SApple OSS Distributions 	 * Failure to retrieve is not fatal.
253*bbb1b6f9SApple OSS Distributions 	 */
254*bbb1b6f9SApple OSS Distributions 	size_t size = sizeof(g_jetsam_aging_policy);
255*bbb1b6f9SApple OSS Distributions 	if (sysctlbyname("kern.jetsam_aging_policy", &g_jetsam_aging_policy, &size, NULL, 0) != 0) {
256*bbb1b6f9SApple OSS Distributions 		T_LOG(__func__, true, "Unable to retrieve jetsam aging policy (not fatal)");
257*bbb1b6f9SApple OSS Distributions 	}
258*bbb1b6f9SApple OSS Distributions 
259*bbb1b6f9SApple OSS Distributions 	T_SETUPEND;
260*bbb1b6f9SApple OSS Distributions 
261*bbb1b6f9SApple OSS Distributions 	/*
262*bbb1b6f9SApple OSS Distributions 	 * Relinquish assertion priority even though we don't hold it.  No change in state expected.
263*bbb1b6f9SApple OSS Distributions 	 */
264*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test0 clean: no state change on relinquish");
265*bbb1b6f9SApple OSS Distributions 	relinquish_assertion_priority(mypid, 0xF00D);
266*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_IDLE_DEFERRED, active_limit_mb, 0xF00D, ASSERTION_STATE_IS_RELINQUISHED, "Test0");
267*bbb1b6f9SApple OSS Distributions 
268*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test1 clean: deferred now assertion[10]");
269*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_FOREGROUND, 0xFEED);
270*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test1");
271*bbb1b6f9SApple OSS Distributions 
272*bbb1b6f9SApple OSS Distributions 	/* Test2 */
273*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test2 clean:  assertion[10 -> 3]");
274*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFACE);
275*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_BACKGROUND, active_limit_mb, 0xFACE, ASSERTION_STATE_IS_SET, "Test2");
276*bbb1b6f9SApple OSS Distributions 
277*bbb1b6f9SApple OSS Distributions 	/* Test3 */
278*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test3 clean: assertion[3 -> 0], but now deferred");
279*bbb1b6f9SApple OSS Distributions 	relinquish_assertion_priority(mypid, 0xBEEF);
280*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_IDLE_DEFERRED, active_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test3");
281*bbb1b6f9SApple OSS Distributions 
282*bbb1b6f9SApple OSS Distributions 	T_LOG("Avoid idle-deferred moving forward. Sleeping for %d s", IDLE_AGEOUT_S);
283*bbb1b6f9SApple OSS Distributions 	sleep(IDLE_AGEOUT_S);
284*bbb1b6f9SApple OSS Distributions 
285*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_IDLE, inactive_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test3");
286*bbb1b6f9SApple OSS Distributions 
287*bbb1b6f9SApple OSS Distributions 	/* Test4 */
288*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test4 clean: deferred now assertion[10]");
289*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_FOREGROUND, 0xFEED);
290*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test4");
291*bbb1b6f9SApple OSS Distributions 
292*bbb1b6f9SApple OSS Distributions 
293*bbb1b6f9SApple OSS Distributions 	/* Test5 */
294*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test5 dirty: set dirty priority but assertion[10] prevails");
295*bbb1b6f9SApple OSS Distributions 	proc_will_set_dirty(mypid);   /* active priority is less than FG*/
296*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test5");
297*bbb1b6f9SApple OSS Distributions 
298*bbb1b6f9SApple OSS Distributions 	/* Test6 */
299*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test6 dirty: assertion[10 -> 3] but dirty priority prevails");
300*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFEEB);  /* active priority is > BG */
301*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_UI_SUPPORT, active_limit_mb, 0xFEEB, ASSERTION_STATE_IS_SET, "Test6");
302*bbb1b6f9SApple OSS Distributions 
303*bbb1b6f9SApple OSS Distributions 	/* Test7 */
304*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test7 dirty: assertion[3 -> 0] but dirty prevails");
305*bbb1b6f9SApple OSS Distributions 	relinquish_assertion_priority(mypid, 0xBEEF);
306*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_UI_SUPPORT, active_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test7");
307*bbb1b6f9SApple OSS Distributions 
308*bbb1b6f9SApple OSS Distributions 
309*bbb1b6f9SApple OSS Distributions 	/* Test8 */
310*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test8 dirty: assertion[0 -> 10] overrides dirty");
311*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_FOREGROUND, 0xFEED);
312*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test8");
313*bbb1b6f9SApple OSS Distributions 
314*bbb1b6f9SApple OSS Distributions 	/* Test9 */
315*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test9 dirty wants to go clean, but clean state is prevented as assertion[10] prevails");
316*bbb1b6f9SApple OSS Distributions 	proc_will_set_clean(mypid);
317*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test9");
318*bbb1b6f9SApple OSS Distributions 
319*bbb1b6f9SApple OSS Distributions 	/* Test10 */
320*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test10 dirty goes dirty and stays dirty, and assertion[10] prevails again");
321*bbb1b6f9SApple OSS Distributions 	proc_will_set_dirty(mypid);
322*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test10");
323*bbb1b6f9SApple OSS Distributions 
324*bbb1b6f9SApple OSS Distributions 	/* Test11 */
325*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test11 dirty: assertion[10 -> 3] but dirty prevails");
326*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFACE);
327*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_UI_SUPPORT, active_limit_mb, 0xFACE, ASSERTION_STATE_IS_SET, "Test11");
328*bbb1b6f9SApple OSS Distributions 
329*bbb1b6f9SApple OSS Distributions 	/* Test12 */
330*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test12 dirty: assertion[3 -> 0] but dirty prevails");
331*bbb1b6f9SApple OSS Distributions 	relinquish_assertion_priority(mypid, 0xBEEF);
332*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_UI_SUPPORT, active_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test12");
333*bbb1b6f9SApple OSS Distributions 
334*bbb1b6f9SApple OSS Distributions 
335*bbb1b6f9SApple OSS Distributions 	/* Test13 */
336*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test13 dirty goes clean: both assertion[0] and clean");
337*bbb1b6f9SApple OSS Distributions 	proc_will_set_clean(mypid);
338*bbb1b6f9SApple OSS Distributions 	/* For sysproc aging policy the daemon should be at idle deferred and with an active memory limit */
339*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_IDLE_DEFERRED, active_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test13");
340*bbb1b6f9SApple OSS Distributions }
341*bbb1b6f9SApple OSS Distributions 
342*bbb1b6f9SApple OSS Distributions /*
343*bbb1b6f9SApple OSS Distributions  * Process is dirty tracking and does not opt into pressured exit.
344*bbb1b6f9SApple OSS Distributions  * This test lives above Foreground.  Assertions will have no affect
345*bbb1b6f9SApple OSS Distributions  * except where the assertion priority bumps it above the requested priority.
346*bbb1b6f9SApple OSS Distributions  */
347*bbb1b6f9SApple OSS Distributions static void
memorystatus_assertion_test_do_not_allow_idle_exit(void)348*bbb1b6f9SApple OSS Distributions memorystatus_assertion_test_do_not_allow_idle_exit(void)
349*bbb1b6f9SApple OSS Distributions {
350*bbb1b6f9SApple OSS Distributions 	pid_t mypid = getpid();
351*bbb1b6f9SApple OSS Distributions 
352*bbb1b6f9SApple OSS Distributions 	/* these values will remain fixed during testing */
353*bbb1b6f9SApple OSS Distributions 	int             active_limit_mb = 35;   /* arbitrary */
354*bbb1b6f9SApple OSS Distributions 	int             inactive_limit_mb = 25;  /* arbitrary */
355*bbb1b6f9SApple OSS Distributions 	int             requestedpriority = JETSAM_PRIORITY_AUDIO_AND_ACCESSORY;
356*bbb1b6f9SApple OSS Distributions 
357*bbb1b6f9SApple OSS Distributions 	T_SETUPBEGIN;
358*bbb1b6f9SApple OSS Distributions 
359*bbb1b6f9SApple OSS Distributions 	set_memlimits(mypid, active_limit_mb, inactive_limit_mb, true, true);
360*bbb1b6f9SApple OSS Distributions 	set_priority(mypid, requestedpriority, 0, false);
361*bbb1b6f9SApple OSS Distributions 	proc_track_dirty(mypid, (PROC_DIRTY_TRACK));
362*bbb1b6f9SApple OSS Distributions 	proc_set_managed(mypid, true);
363*bbb1b6f9SApple OSS Distributions 
364*bbb1b6f9SApple OSS Distributions 	proc_will_set_dirty(mypid);
365*bbb1b6f9SApple OSS Distributions 
366*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, active_limit_mb, 0x0, ASSERTION_STATE_IS_RELINQUISHED, "Dirty start");
367*bbb1b6f9SApple OSS Distributions 
368*bbb1b6f9SApple OSS Distributions 	proc_will_set_clean(mypid);
369*bbb1b6f9SApple OSS Distributions 
370*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0x0, ASSERTION_STATE_IS_RELINQUISHED, "Clean transition");
371*bbb1b6f9SApple OSS Distributions 
372*bbb1b6f9SApple OSS Distributions 	T_LOG("SETUP STATE COMPLETE");
373*bbb1b6f9SApple OSS Distributions 
374*bbb1b6f9SApple OSS Distributions 	T_SETUPEND;
375*bbb1b6f9SApple OSS Distributions 
376*bbb1b6f9SApple OSS Distributions 	/*
377*bbb1b6f9SApple OSS Distributions 	 * Relinquish assertion priority even though we don't hold it.  No change in state expected.
378*bbb1b6f9SApple OSS Distributions 	 */
379*bbb1b6f9SApple OSS Distributions 
380*bbb1b6f9SApple OSS Distributions 
381*bbb1b6f9SApple OSS Distributions 	/* Test0 */
382*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test0 clean: no state change on relinquish");
383*bbb1b6f9SApple OSS Distributions 	relinquish_assertion_priority(mypid, 0xF00D);
384*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xF00D, ASSERTION_STATE_IS_RELINQUISHED, "Test0");
385*bbb1b6f9SApple OSS Distributions 
386*bbb1b6f9SApple OSS Distributions 	/* Test1 */
387*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test1 clean: assertion[0 -> 10] but inactive priority prevails");
388*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_FOREGROUND, 0xFEED);
389*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test1");
390*bbb1b6f9SApple OSS Distributions 
391*bbb1b6f9SApple OSS Distributions 	/* Test2 */
392*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test2 clean:  assertion[10 -> 3] but inactive priority prevails");
393*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFACE);
394*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xFACE, ASSERTION_STATE_IS_SET, "Test2");
395*bbb1b6f9SApple OSS Distributions 
396*bbb1b6f9SApple OSS Distributions 	/* Test3 */
397*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test3 clean: assertion[3 -> 0], but inactive priority prevails");
398*bbb1b6f9SApple OSS Distributions 	relinquish_assertion_priority(mypid, 0xBEEF);
399*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test3");
400*bbb1b6f9SApple OSS Distributions 
401*bbb1b6f9SApple OSS Distributions 	/* Test4 */
402*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test4 go dirty: assertion[0] has no affect, active priority prevails");
403*bbb1b6f9SApple OSS Distributions 	proc_will_set_dirty(mypid);
404*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, active_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test4");
405*bbb1b6f9SApple OSS Distributions 
406*bbb1b6f9SApple OSS Distributions 	/* Test5 */
407*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test5 dirty: assertion[0 -> 10] active priority prevails");
408*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_FOREGROUND, 0xFEED);
409*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test5");
410*bbb1b6f9SApple OSS Distributions 
411*bbb1b6f9SApple OSS Distributions 	/* Test6 */
412*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test6 dirty:  assertion[10 -> 3] active priority prevails");
413*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFACE);
414*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, active_limit_mb, 0xFACE, ASSERTION_STATE_IS_SET, "Test6");
415*bbb1b6f9SApple OSS Distributions 
416*bbb1b6f9SApple OSS Distributions 	/* Test 7 */
417*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test7 dirty: assertion[3 -> 0], active priority prevails");
418*bbb1b6f9SApple OSS Distributions 	relinquish_assertion_priority(mypid, 0xBEEF);
419*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, active_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test7");
420*bbb1b6f9SApple OSS Distributions 
421*bbb1b6f9SApple OSS Distributions 	/* Test8 */
422*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test8 dirty: assertion[0 -> 19], dirty but now assertion[19] prevails");
423*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_CRITICAL, 0xFEED);
424*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_CRITICAL, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test8");
425*bbb1b6f9SApple OSS Distributions 
426*bbb1b6f9SApple OSS Distributions 
427*bbb1b6f9SApple OSS Distributions 	/* Test9 */
428*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test9 go clean: inactive priority but assertion[19] prevails");
429*bbb1b6f9SApple OSS Distributions 	proc_will_set_clean(mypid);
430*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_CRITICAL, inactive_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test9");
431*bbb1b6f9SApple OSS Distributions 
432*bbb1b6f9SApple OSS Distributions 	/* Test10 */
433*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test10 clean:  assertion[19 -> 3] inactive limit prevails");
434*bbb1b6f9SApple OSS Distributions 	set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFACE);
435*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xFACE, ASSERTION_STATE_IS_SET, "Test10");
436*bbb1b6f9SApple OSS Distributions 
437*bbb1b6f9SApple OSS Distributions 
438*bbb1b6f9SApple OSS Distributions 	/* Test11 */
439*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test11 clean:  assertion[3 -> 0] inactive priority still prevails");
440*bbb1b6f9SApple OSS Distributions 	relinquish_assertion_priority(mypid, 0xBEEF);
441*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test11");
442*bbb1b6f9SApple OSS Distributions 
443*bbb1b6f9SApple OSS Distributions 	/* Test12 */
444*bbb1b6f9SApple OSS Distributions 	T_LOG("********Test12 dirty goes clean: both assertion[0] and clean");
445*bbb1b6f9SApple OSS Distributions 	proc_will_set_clean(mypid);
446*bbb1b6f9SApple OSS Distributions 	(void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test12");
447*bbb1b6f9SApple OSS Distributions }
448*bbb1b6f9SApple OSS Distributions 
449*bbb1b6f9SApple OSS Distributions T_DECL(assertion_test_bad_flags, "verify bad flag returns an error", T_META_TIMEOUT(30), T_META_ASROOT(true)) {
450*bbb1b6f9SApple OSS Distributions 	int err;
451*bbb1b6f9SApple OSS Distributions 	uint32_t flag = 0;
452*bbb1b6f9SApple OSS Distributions 
453*bbb1b6f9SApple OSS Distributions 	memorystatus_priority_properties_t mjp = { 0 };
454*bbb1b6f9SApple OSS Distributions 
455*bbb1b6f9SApple OSS Distributions 	mjp.priority = JETSAM_PRIORITY_FOREGROUND;
456*bbb1b6f9SApple OSS Distributions 	mjp.user_data = 0;
457*bbb1b6f9SApple OSS Distributions 
458*bbb1b6f9SApple OSS Distributions 	/*
459*bbb1b6f9SApple OSS Distributions 	 * init a bad flag
460*bbb1b6f9SApple OSS Distributions 	 */
461*bbb1b6f9SApple OSS Distributions 
462*bbb1b6f9SApple OSS Distributions 	flag = 0xf;
463*bbb1b6f9SApple OSS Distributions 
464*bbb1b6f9SApple OSS Distributions 	err = memorystatus_control(MEMORYSTATUS_CMD_SET_PRIORITY_PROPERTIES, getpid(), flag, &mjp, sizeof(mjp));
465*bbb1b6f9SApple OSS Distributions 
466*bbb1b6f9SApple OSS Distributions 	T_QUIET;
467*bbb1b6f9SApple OSS Distributions 	T_ASSERT_POSIX_FAILURE(err, EINVAL, "MEMORYSTATUS_CMD_SET_PRIORITY_PROPERTIES should fail with bad flags (err=%d)", err);
468*bbb1b6f9SApple OSS Distributions }
469*bbb1b6f9SApple OSS Distributions 
470*bbb1b6f9SApple OSS Distributions T_DECL(set_assertion_pri_unmanaged,
471*bbb1b6f9SApple OSS Distributions     "verify that an unmanaged process cannot have assertion-driven priority set")
472*bbb1b6f9SApple OSS Distributions {
473*bbb1b6f9SApple OSS Distributions 	int err;
474*bbb1b6f9SApple OSS Distributions 	memorystatus_priority_properties_t mjp = {
475*bbb1b6f9SApple OSS Distributions 		.priority = JETSAM_PRIORITY_FOREGROUND,
476*bbb1b6f9SApple OSS Distributions 		.user_data = 0x0
477*bbb1b6f9SApple OSS Distributions 	};
478*bbb1b6f9SApple OSS Distributions 	err = memorystatus_control(MEMORYSTATUS_CMD_SET_PRIORITY_PROPERTIES,
479*bbb1b6f9SApple OSS Distributions 	    getpid(), MEMORYSTATUS_SET_PRIORITY_ASSERTION, &mjp, sizeof(mjp));
480*bbb1b6f9SApple OSS Distributions 
481*bbb1b6f9SApple OSS Distributions 	T_EXPECT_POSIX_FAILURE(err, EPERM,
482*bbb1b6f9SApple OSS Distributions 	    "Should not be able to set assertion-driven priority of unmanaged process.");
483*bbb1b6f9SApple OSS Distributions }
484*bbb1b6f9SApple OSS Distributions 
485*bbb1b6f9SApple OSS Distributions 
486*bbb1b6f9SApple OSS Distributions #if TARGET_OS_OSX
487*bbb1b6f9SApple OSS Distributions /*
488*bbb1b6f9SApple OSS Distributions  * Idle band deferral, aka aging band/demotion, has been disabled on macOS till
489*bbb1b6f9SApple OSS Distributions  * we do the daemon hygiene work on macOS to make sure that processes don't change
490*bbb1b6f9SApple OSS Distributions  * their role after spawn e.g. apps opting into dirty-tracking/idle-exit.
491*bbb1b6f9SApple OSS Distributions  * The following set of tests rely on PROC_DIRTY_DEFER, aka aging bands, for the tests.
492*bbb1b6f9SApple OSS Distributions  */
493*bbb1b6f9SApple OSS Distributions #else /* TARGET_OS_OSX */
494*bbb1b6f9SApple OSS Distributions 
495*bbb1b6f9SApple OSS Distributions T_HELPER_DECL(idle_age_as_app_then_sysproc,
496*bbb1b6f9SApple OSS Distributions     "Launch as managed, begin idle aging, then enroll in ActivityTracking")
497*bbb1b6f9SApple OSS Distributions {
498*bbb1b6f9SApple OSS Distributions 	pid_t my_pid = getpid();
499*bbb1b6f9SApple OSS Distributions 	int32_t priority;
500*bbb1b6f9SApple OSS Distributions 
501*bbb1b6f9SApple OSS Distributions 	// Set self as managed and begin idle aging
502*bbb1b6f9SApple OSS Distributions 	proc_set_managed(my_pid, true);
503*bbb1b6f9SApple OSS Distributions 	set_priority(my_pid, JETSAM_PRIORITY_IDLE, 0, false);
504*bbb1b6f9SApple OSS Distributions 	// process must have a fatal memlimit to enroll in dirtytracking while
505*bbb1b6f9SApple OSS Distributions 	// managed
506*bbb1b6f9SApple OSS Distributions 	set_memlimits(my_pid, 100, 100, true, true);
507*bbb1b6f9SApple OSS Distributions 
508*bbb1b6f9SApple OSS Distributions 	get_priority_props(my_pid, FALSE, &priority, NULL, NULL, NULL);
509*bbb1b6f9SApple OSS Distributions 	T_EXPECT_EQ(priority, JETSAM_PRIORITY_AGING_BAND2, "Process is placed in App aging band");
510*bbb1b6f9SApple OSS Distributions 
511*bbb1b6f9SApple OSS Distributions 	// Enroll in dirty tracking
512*bbb1b6f9SApple OSS Distributions 	proc_track_dirty(my_pid,
513*bbb1b6f9SApple OSS Distributions 	    (PROC_DIRTY_TRACK | PROC_DIRTY_ALLOW_IDLE_EXIT | PROC_DIRTY_DEFER));
514*bbb1b6f9SApple OSS Distributions 
515*bbb1b6f9SApple OSS Distributions 	get_priority_props(my_pid, FALSE, &priority, NULL, NULL, NULL);
516*bbb1b6f9SApple OSS Distributions 	T_EXPECT_EQ(priority, JETSAM_PRIORITY_AGING_BAND1, "Process is placed in SysProc aging band");
517*bbb1b6f9SApple OSS Distributions 
518*bbb1b6f9SApple OSS Distributions 	T_LOG("Sleeping for %d sec...", IDLE_AGEOUT_S);
519*bbb1b6f9SApple OSS Distributions 	sleep(IDLE_AGEOUT_S);
520*bbb1b6f9SApple OSS Distributions 
521*bbb1b6f9SApple OSS Distributions 	get_priority_props(my_pid, FALSE, &priority, NULL, NULL, NULL);
522*bbb1b6f9SApple OSS Distributions 	T_EXPECT_EQ(priority, JETSAM_PRIORITY_IDLE, "Process ages to IDLE");
523*bbb1b6f9SApple OSS Distributions }
524*bbb1b6f9SApple OSS Distributions 
525*bbb1b6f9SApple OSS Distributions T_DECL(idle_aging_app_to_sysproc,
526*bbb1b6f9SApple OSS Distributions     "Processes that transition from App -> SysProc while aging are deferred properly")
527*bbb1b6f9SApple OSS Distributions {
528*bbb1b6f9SApple OSS Distributions 	dt_helper_t helper = dt_child_helper("idle_age_as_app_then_sysproc");
529*bbb1b6f9SApple OSS Distributions 
530*bbb1b6f9SApple OSS Distributions 	dt_run_helpers(&helper, 1, 90);
531*bbb1b6f9SApple OSS Distributions }
532*bbb1b6f9SApple OSS Distributions 
533*bbb1b6f9SApple OSS Distributions T_HELPER_DECL(idle_age_timeout_importance_boost,
534*bbb1b6f9SApple OSS Distributions     "Enroll in ActivityTracking, idle age with held assertion")
535*bbb1b6f9SApple OSS Distributions {
536*bbb1b6f9SApple OSS Distributions 	pid_t my_pid = getpid();
537*bbb1b6f9SApple OSS Distributions 	int32_t priority, ret;
538*bbb1b6f9SApple OSS Distributions 
539*bbb1b6f9SApple OSS Distributions 	// Set managed, enroll in dirty tracking, and pretend we have an importance assertion voucher
540*bbb1b6f9SApple OSS Distributions 	proc_set_managed(my_pid, true);
541*bbb1b6f9SApple OSS Distributions 	set_memlimits(my_pid, 100, 100, true, true);
542*bbb1b6f9SApple OSS Distributions 	proc_track_dirty(my_pid,
543*bbb1b6f9SApple OSS Distributions 	    (PROC_DIRTY_TRACK | PROC_DIRTY_ALLOW_IDLE_EXIT | PROC_DIRTY_DEFER));
544*bbb1b6f9SApple OSS Distributions 	ret = memorystatus_control(MEMORYSTATUS_CMD_SET_TESTING_PID, getpid(), MEMORYSTATUS_FLAGS_SET_IMP_TESTING_PID, NULL, 0);
545*bbb1b6f9SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "MEMORYSTATUS_CMD_SET_TESTING_PID");
546*bbb1b6f9SApple OSS Distributions 
547*bbb1b6f9SApple OSS Distributions 	get_priority_props(my_pid, FALSE, &priority, NULL, NULL, NULL);
548*bbb1b6f9SApple OSS Distributions 	T_EXPECT_EQ(priority, JETSAM_PRIORITY_AGING_BAND1, "Process is placed in SysProc aging band");
549*bbb1b6f9SApple OSS Distributions 
550*bbb1b6f9SApple OSS Distributions 	T_LOG("Sleeping for %d sec...", IDLE_AGEOUT_S);
551*bbb1b6f9SApple OSS Distributions 	sleep(IDLE_AGEOUT_S);
552*bbb1b6f9SApple OSS Distributions 
553*bbb1b6f9SApple OSS Distributions 	get_priority_props(my_pid, FALSE, &priority, NULL, NULL, NULL);
554*bbb1b6f9SApple OSS Distributions 	T_EXPECT_EQ(priority, JETSAM_PRIORITY_AGING_BAND1_STUCK, "Process ages to JETSAM_PRIORITY_AGING_BAND1_STUCK");
555*bbb1b6f9SApple OSS Distributions 
556*bbb1b6f9SApple OSS Distributions 	T_LOG("Sleeping for %d sec...", AGEOUT_STUCK_S);
557*bbb1b6f9SApple OSS Distributions 	sleep(AGEOUT_STUCK_S);
558*bbb1b6f9SApple OSS Distributions 
559*bbb1b6f9SApple OSS Distributions 	get_priority_props(my_pid, FALSE, &priority, NULL, NULL, NULL);
560*bbb1b6f9SApple OSS Distributions 	T_EXPECT_EQ(priority, JETSAM_PRIORITY_IDLE, "Process ages to JETSAM_PRIORITY_IDLE");
561*bbb1b6f9SApple OSS Distributions }
562*bbb1b6f9SApple OSS Distributions 
563*bbb1b6f9SApple OSS Distributions T_DECL(idle_aging_leaked_importance_boost,
564*bbb1b6f9SApple OSS Distributions     "Idle aging with leaked importance boost")
565*bbb1b6f9SApple OSS Distributions {
566*bbb1b6f9SApple OSS Distributions 	dt_helper_t helper = dt_child_helper("idle_age_timeout_importance_boost");
567*bbb1b6f9SApple OSS Distributions 
568*bbb1b6f9SApple OSS Distributions 	dt_run_helpers(&helper, 1, 80);
569*bbb1b6f9SApple OSS Distributions }
570*bbb1b6f9SApple OSS Distributions T_DECL(assertion_test_repetitive_non_dirty_tracking, "Scenario #1 - repetitive assertion priority on non-dirty-tracking process", T_META_TIMEOUT(60), T_META_ASROOT(true)) {
571*bbb1b6f9SApple OSS Distributions 	/*
572*bbb1b6f9SApple OSS Distributions 	 * Verify back-to-back assertion calls set assertion state as expected.
573*bbb1b6f9SApple OSS Distributions 	 * false --> non-dirty-tracking process (like a typical app)
574*bbb1b6f9SApple OSS Distributions 	 * false --> clean/dirty does not apply here
575*bbb1b6f9SApple OSS Distributions 	 */
576*bbb1b6f9SApple OSS Distributions 
577*bbb1b6f9SApple OSS Distributions 	memorystatus_assertion_test_repetitive("Scenario #1", false, false);
578*bbb1b6f9SApple OSS Distributions }
579*bbb1b6f9SApple OSS Distributions 
580*bbb1b6f9SApple OSS Distributions T_DECL(assertion_test_repetitive_dirty_tracking_clean, "Scenario #2 - repetitive assertion priority on clean dirty-tracking process", T_META_TIMEOUT(60), T_META_ASROOT(true)) {
581*bbb1b6f9SApple OSS Distributions 	/*
582*bbb1b6f9SApple OSS Distributions 	 * Verify back-to-back assertion calls set assertion state as expected.
583*bbb1b6f9SApple OSS Distributions 	 * true --> dirty-tracking process (like a typical extension/widget)
584*bbb1b6f9SApple OSS Distributions 	 * true --> start clean / inactive
585*bbb1b6f9SApple OSS Distributions 	 * This will exercise idle-deferred paths.
586*bbb1b6f9SApple OSS Distributions 	 */
587*bbb1b6f9SApple OSS Distributions 	memorystatus_assertion_test_repetitive("Scenario #2", true, true);
588*bbb1b6f9SApple OSS Distributions }
589*bbb1b6f9SApple OSS Distributions 
590*bbb1b6f9SApple OSS Distributions T_DECL(assertion_test_repetitive_dirty_tracking_dirty, "Scenario #3 - repetitive assertion priority on dirty dirty-tracking processes", T_META_TIMEOUT(60), T_META_ASROOT(true)) {
591*bbb1b6f9SApple OSS Distributions 	/*
592*bbb1b6f9SApple OSS Distributions 	 * Verify back-to-back assertion calls set assertion state as expected.
593*bbb1b6f9SApple OSS Distributions 	 * true --> dirty-tracking process (like a typical extension/widget)
594*bbb1b6f9SApple OSS Distributions 	 * false --> start dirty / active state
595*bbb1b6f9SApple OSS Distributions 	 * This will exercise idle-deferred paths.
596*bbb1b6f9SApple OSS Distributions 	 */
597*bbb1b6f9SApple OSS Distributions 	memorystatus_assertion_test_repetitive("Scenario #3", true, false);
598*bbb1b6f9SApple OSS Distributions }
599*bbb1b6f9SApple OSS Distributions 
600*bbb1b6f9SApple OSS Distributions 
601*bbb1b6f9SApple OSS Distributions T_DECL(assertion_test_allow_idle_exit, "set assertion priorities on process supporting idle exit", T_META_TIMEOUT(360), T_META_ASROOT(true)) {
602*bbb1b6f9SApple OSS Distributions 	memorystatus_assertion_test_allow_idle_exit();
603*bbb1b6f9SApple OSS Distributions }
604*bbb1b6f9SApple OSS Distributions 
605*bbb1b6f9SApple OSS Distributions T_DECL(assertion_test_do_not_allow_idle_exit, "set assertion priorities on process no idle exit allowed", T_META_TIMEOUT(360), T_META_ASROOT(true)) {
606*bbb1b6f9SApple OSS Distributions 	memorystatus_assertion_test_do_not_allow_idle_exit();
607*bbb1b6f9SApple OSS Distributions }
608*bbb1b6f9SApple OSS Distributions #endif /* TARGET_OS_OSX */
609*bbb1b6f9SApple OSS Distributions 
610*bbb1b6f9SApple OSS Distributions T_DECL(daemon_memlimits,
611*bbb1b6f9SApple OSS Distributions     "test that daemons have their memlimits set correctly according to dirtiness",
612*bbb1b6f9SApple OSS Distributions     T_META_ENABLED(TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR))
613*bbb1b6f9SApple OSS Distributions {
614*bbb1b6f9SApple OSS Distributions 	int ret;
615*bbb1b6f9SApple OSS Distributions 	const uint32_t memlimit_active = 6; /* 6 MB */
616*bbb1b6f9SApple OSS Distributions 	const uint32_t memlimit_inactive = 4; /* 4 MB */
617*bbb1b6f9SApple OSS Distributions 	pid_t pid = getpid();
618*bbb1b6f9SApple OSS Distributions 
619*bbb1b6f9SApple OSS Distributions 	set_priority(pid, JETSAM_PRIORITY_UI_SUPPORT, 0, false);
620*bbb1b6f9SApple OSS Distributions 	set_memlimits(pid, memlimit_active, memlimit_inactive, true, true);
621*bbb1b6f9SApple OSS Distributions 
622*bbb1b6f9SApple OSS Distributions 	ret = proc_track_dirty(pid, PROC_DIRTY_TRACK | PROC_DIRTY_ALLOW_IDLE_EXIT | PROC_DIRTY_DEFER);
623*bbb1b6f9SApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "proc_track_dirty()");
624*bbb1b6f9SApple OSS Distributions 
625*bbb1b6f9SApple OSS Distributions 	check_properties(pid, JETSAM_PRIORITY_IDLE_DEFERRED, memlimit_active, 0x0,
626*bbb1b6f9SApple OSS Distributions 	    false, "jetsam_test_daemon_memlimit - #1 post-track-dirty");
627*bbb1b6f9SApple OSS Distributions 
628*bbb1b6f9SApple OSS Distributions 	T_LOG("Sleeping for %d to allow idle-ageout.", IDLE_AGEOUT_S);
629*bbb1b6f9SApple OSS Distributions 	sleep(IDLE_AGEOUT_S);
630*bbb1b6f9SApple OSS Distributions 
631*bbb1b6f9SApple OSS Distributions 	check_properties(pid, JETSAM_PRIORITY_IDLE, memlimit_inactive, 0x0, false,
632*bbb1b6f9SApple OSS Distributions 	    "jetsam_test_daemon_memlimit - #4 post-sleep");
633*bbb1b6f9SApple OSS Distributions 
634*bbb1b6f9SApple OSS Distributions 	proc_set_dirty(pid, true);
635*bbb1b6f9SApple OSS Distributions 
636*bbb1b6f9SApple OSS Distributions 	check_properties(pid, JETSAM_PRIORITY_UI_SUPPORT, memlimit_active, 0x0,
637*bbb1b6f9SApple OSS Distributions 	    false, "jetsam_test_daemon_memlimit - #2 post-set-dirty");
638*bbb1b6f9SApple OSS Distributions 
639*bbb1b6f9SApple OSS Distributions 	proc_set_dirty(pid, false);
640*bbb1b6f9SApple OSS Distributions 
641*bbb1b6f9SApple OSS Distributions 	check_properties(pid, JETSAM_PRIORITY_IDLE_DEFERRED, memlimit_active, 0x0,
642*bbb1b6f9SApple OSS Distributions 	    false, "jetsam_test_daemon_memlimit - #3 post-clear-dirty");
643*bbb1b6f9SApple OSS Distributions 
644*bbb1b6f9SApple OSS Distributions 	T_LOG("Sleeping for %d s to allow idle-ageout.", IDLE_AGEOUT_S);
645*bbb1b6f9SApple OSS Distributions 	sleep(IDLE_AGEOUT_S);
646*bbb1b6f9SApple OSS Distributions 
647*bbb1b6f9SApple OSS Distributions 	check_properties(pid, JETSAM_PRIORITY_IDLE, memlimit_inactive, 0x0, false,
648*bbb1b6f9SApple OSS Distributions 	    "jetsam_test_daemon_memlimit - #4 post-sleep");
649*bbb1b6f9SApple OSS Distributions 
650*bbb1b6f9SApple OSS Distributions 	proc_set_dirty(pid, true);
651*bbb1b6f9SApple OSS Distributions 
652*bbb1b6f9SApple OSS Distributions 	check_properties(pid, JETSAM_PRIORITY_UI_SUPPORT, memlimit_active, 0x0,
653*bbb1b6f9SApple OSS Distributions 	    false, "jetsam_test_daemon_memlimit - #5 post-set-dirty-2");
654*bbb1b6f9SApple OSS Distributions 
655*bbb1b6f9SApple OSS Distributions 	proc_set_dirty(pid, false);
656*bbb1b6f9SApple OSS Distributions 
657*bbb1b6f9SApple OSS Distributions 	check_properties(pid, JETSAM_PRIORITY_IDLE_DEFERRED, memlimit_active, 0x0, false,
658*bbb1b6f9SApple OSS Distributions 	    "jetsam_test_daemon_memlimit - #6 post-clear-dirty-2");
659*bbb1b6f9SApple OSS Distributions }
660