]>
Commit | Line | Data |
---|---|---|
cb323159 A |
1 | #include <stdio.h> |
2 | #include <unistd.h> | |
3 | #include <stdlib.h> | |
4 | #include <errno.h> | |
5 | #include <string.h> | |
6 | #include <assert.h> | |
7 | #include <signal.h> | |
8 | #include <spawn.h> | |
9 | #include <spawn_private.h> | |
10 | #include <stdint.h> | |
11 | #include <sys/sysctl.h> | |
12 | #include <sys/spawn_internal.h> | |
13 | #include <sys/kern_memorystatus.h> | |
14 | #include <mach-o/dyld.h> | |
15 | ||
16 | #include <darwintest.h> | |
17 | #include <darwintest_utils.h> | |
18 | ||
19 | #include "memorystatus_assertion_helpers.h" | |
20 | ||
21 | T_GLOBAL_META( | |
22 | T_META_NAMESPACE("xnu.vm"), | |
23 | T_META_CHECK_LEAKS(false) | |
24 | ); | |
25 | ||
26 | extern char **environ; | |
27 | ||
28 | /* | |
29 | * This test has multiple sub-tests that set and then verify jetsam priority transitions | |
30 | * as though they were driven by assertions. It uses the MEMORYSTATUS_CMD_SET_MEMLIMIT_PROPERTIES | |
31 | * version of the memorystatus_control() system call and specifically tests the use of the | |
32 | * MEMORYSTATUS_SET_PRIORITY_ASSERTION flag. | |
33 | * | |
34 | * The kernel will apply policy that chooses a maximum jetsam priority, resolving conflicts | |
35 | * between an assertion driven priority and clean/dirty transition policy. | |
36 | * | |
37 | * Processes that do not opt into dirty-tracking should behave as they always have. | |
38 | * This is the typical App transition behavior. | |
39 | * | |
40 | * Processes that do opt into dirty-tracking have more complex policy: | |
41 | * For example: | |
42 | * A MAX assertion priority will prevent a dirty process from transitioning to a clean | |
43 | * state if the process opts into idle-exit. | |
44 | * See: memorystatus_schedule_idle_demotion_locked() where we note that | |
45 | * the process isn't going to be making the trip to the lower bands. | |
46 | * | |
47 | * But a MAX assertion evaluation will not prevent a clean process from transition to dirty. | |
48 | * Assertion driven priorities should not change memory limits, they are expected to | |
49 | * just change a process's position in the jetsam priority bands. | |
50 | * | |
51 | * MEMORYSTATUS_CMD_xxx requires root (in the absence of entitlement). | |
52 | * Use T_META_ASROOT(true) to accomplish this. | |
53 | * | |
54 | * A note on test strategy. It is not necessary to spawn a child to test these | |
55 | * assertion calls. The test can act on itself, that is, it can make calls to | |
56 | * set and relinquish assertion state just like it can make calls to do dirty/clean | |
57 | * transitions. Of course, in reality, we expect only runningboardd to manipulate | |
58 | * assertion based priorities. | |
59 | */ | |
60 | ||
61 | /* | |
62 | * New flag to tell kernel this is an assertion driven priority update. | |
63 | */ | |
64 | #ifndef MEMORYSTATUS_SET_PRIORITY_ASSERTION | |
65 | #define MEMORYSTATUS_SET_PRIORITY_ASSERTION 0x1 | |
66 | #endif | |
67 | ||
68 | static void | |
69 | proc_will_set_clean(pid_t pid) | |
70 | { | |
71 | proc_set_dirty(pid, false); | |
72 | T_LOG("pid[%d] --> now clean", pid); | |
73 | return; | |
74 | } | |
75 | ||
76 | static void | |
77 | proc_will_set_dirty(pid_t pid) | |
78 | { | |
79 | proc_set_dirty(pid, true); | |
80 | T_LOG("pid[%d] --> now dirty", pid); | |
81 | return; | |
82 | } | |
83 | ||
84 | #define kJetsamAgingPolicyNone (0) | |
85 | #define kJetsamAgingPolicyLegacy (1) | |
86 | #define kJetsamAgingPolicySysProcsReclaimedFirst (2) | |
87 | #define kJetsamAgingPolicyAppsReclaimedFirst (3) | |
88 | #define kJetsamAgingPolicyMax kJetsamAgingPolicyAppsReclaimedFirst | |
89 | ||
90 | #ifndef kMemorystatusAssertion | |
91 | #define kMemorystatusAssertion 0x40 | |
92 | #endif | |
93 | ||
94 | /* | |
95 | * Make repetitive (eg: back-to-back) calls using MEMORYSTATUS_SET_PRIORITY_ASSERTION. | |
96 | * We know that runningboardd may try to relinquish its hold on an assertion priority | |
97 | * when it hasn't first set the assertion priority. The kernel must survive this | |
98 | * pattern even though it might be considered poor behavior on runningboardd's part. | |
99 | * When dirty tracking processes are involved, we are exercising the kernel's | |
100 | * idle-deferred paths. Only assertion state (whether or not assertion state is | |
101 | * set or relinquished) is verified in this round of tests. | |
102 | * Test is invoked three times: | |
103 | * Scenario 1) as a non-dirty-tracking process (like a typical app) | |
104 | * relinquish assertion priority multiple times | |
105 | * set same assertion priority multiple times. | |
106 | * Scenario 2) setup a dirty-tracking process that is clean (like a typical extension) | |
107 | * relinquish assertion priority multiple times | |
108 | * set same assertion priority multiple times. | |
109 | * Scenario 3) setup dirty-tracking process that is dirty (like a typical extension) | |
110 | * relinquish assertion priority multiple times | |
111 | * set same assertion priority multiple times. | |
112 | */ | |
113 | ||
114 | static void | |
115 | memorystatus_assertion_test_repetitive(char *test, boolean_t turn_on_dirty_tracking, boolean_t start_clean) | |
116 | { | |
117 | int count; | |
118 | int maxcount = 3; | |
119 | boolean_t verbose; | |
120 | uint32_t state; | |
121 | uint64_t user_data = 0; | |
122 | pid_t mypid = getpid(); | |
123 | ||
124 | /* these values will remain fixed during testing */ | |
125 | int active_limit_mb = 15; /* arbitrary */ | |
126 | int inactive_limit_mb = 7; /* arbitrary */ | |
127 | ||
128 | /* these values may vary during test */ | |
129 | int requestedpriority = 0; | |
130 | int assertionpriority = 0; | |
131 | ||
132 | T_SETUPBEGIN; | |
133 | ||
134 | requestedpriority = JETSAM_PRIORITY_UI_SUPPORT; | |
135 | assertionpriority = JETSAM_PRIORITY_FOREGROUND; | |
136 | set_memlimits(mypid, active_limit_mb, inactive_limit_mb, true, true); | |
137 | set_priority(mypid, requestedpriority, 0, false); | |
138 | ||
139 | if (turn_on_dirty_tracking) { | |
140 | proc_track_dirty(mypid, (PROC_DIRTY_TRACK | PROC_DIRTY_ALLOW_IDLE_EXIT | PROC_DIRTY_DEFER)); | |
141 | ||
142 | if (start_clean) { | |
143 | proc_will_set_clean(mypid); | |
144 | } else { | |
145 | proc_will_set_dirty(mypid); | |
146 | } | |
147 | } else { | |
148 | /* | |
149 | * Do nothing. | |
150 | * Acts like an app with no dirty tracking | |
151 | * By default launches in the requested priority and is | |
152 | * considered idle because it's below FG band. | |
153 | */ | |
154 | } | |
155 | ||
156 | ||
157 | verbose = false; | |
158 | (void)get_priority_props(mypid, verbose, NULL, NULL, NULL, NULL); | |
159 | ||
160 | /* log current setup state */ | |
161 | T_LOG("SETUP STATE COMPLETE: Test %s", test); | |
162 | ||
163 | T_SETUPEND; | |
164 | ||
165 | int i; | |
166 | boolean_t ret; | |
167 | for (i = 0; i < 2; i++) { | |
168 | if (i == 1 && turn_on_dirty_tracking) { | |
169 | T_LOG("Avoid idle-deferred - sleeping for 20"); | |
170 | sleep(20); | |
171 | ||
172 | if (start_clean) { | |
173 | proc_will_set_dirty(mypid); | |
174 | } else { | |
175 | proc_will_set_clean(mypid); | |
176 | } | |
177 | ||
178 | (void)get_priority_props(mypid, verbose, NULL, NULL, NULL, &state); | |
179 | } | |
180 | ||
181 | /* | |
182 | * Relinquish assertion priority even though we don't | |
183 | * currently hold an assertion priority. | |
184 | */ | |
185 | for (count = 0; count < maxcount; count++) { | |
186 | if (relinquish_assertion_priority(mypid, user_data)) { | |
187 | T_ASSERT_FAIL("relinquish_assertion_priority failed"); | |
188 | } | |
189 | } | |
190 | ||
191 | /* Verify assertion state is relinquished */ | |
192 | (void)get_priority_props(mypid, verbose, NULL, NULL, NULL, &state); | |
193 | ||
194 | ret = verify_assertion_state(state, ASSERTION_STATE_IS_RELINQUISHED); | |
195 | T_QUIET; | |
196 | T_ASSERT_TRUE(ret, "verify_assertion_state failed"); | |
197 | ||
198 | ||
199 | ||
200 | /* | |
201 | * Set an assertion priority multiple times in a row. | |
202 | */ | |
203 | for (count = 0; count < maxcount; count++) { | |
204 | if (set_assertion_priority(mypid, assertionpriority, user_data) != 0) { | |
205 | T_ASSERT_FAIL("set_assertion_priority failed"); | |
206 | } | |
207 | } | |
208 | ||
209 | /* Verify state holds an assertion priority */ | |
210 | (void)get_priority_props(mypid, verbose, NULL, NULL, NULL, &state); | |
211 | ||
212 | ret = verify_assertion_state(state, ASSERTION_STATE_IS_SET); | |
213 | T_QUIET; | |
214 | T_ASSERT_TRUE(ret, "verify_assertion_state failed"); | |
215 | } | |
216 | } | |
217 | ||
218 | /* | |
219 | * Process is dirty tracking and opts into pressured exit. | |
220 | */ | |
221 | static void | |
222 | memorystatus_assertion_test_allow_idle_exit() | |
223 | { | |
224 | pid_t mypid = getpid(); | |
225 | ||
226 | /* these values will remain fixed during testing */ | |
227 | int active_limit_mb = 15; /* arbitrary */ | |
228 | int inactive_limit_mb = 7; /* arbitrary */ | |
229 | ||
230 | /* these values may vary during test */ | |
231 | int requestedpriority = JETSAM_PRIORITY_UI_SUPPORT; | |
232 | ||
233 | T_SETUPBEGIN; | |
234 | ||
235 | set_memlimits(mypid, active_limit_mb, inactive_limit_mb, true, true); | |
236 | set_priority(mypid, requestedpriority, 0, false); | |
237 | ||
238 | proc_track_dirty(mypid, (PROC_DIRTY_TRACK | PROC_DIRTY_ALLOW_IDLE_EXIT | PROC_DIRTY_DEFER)); | |
239 | ||
240 | proc_will_set_clean(mypid); | |
241 | ||
242 | (void)check_properties(mypid, JETSAM_PRIORITY_IDLE_DEFERRED, inactive_limit_mb, 0x0, ASSERTION_STATE_IS_RELINQUISHED, "Clean start"); | |
243 | ||
244 | T_LOG("SETUP STATE COMPLETE"); | |
245 | ||
246 | int g_jetsam_aging_policy = 0; | |
247 | /* | |
248 | * Jetsam aging policy | |
249 | * Failure to retrieve is not fatal. | |
250 | */ | |
251 | size_t size = sizeof(g_jetsam_aging_policy); | |
252 | if (sysctlbyname("kern.jetsam_aging_policy", &g_jetsam_aging_policy, &size, NULL, 0) != 0) { | |
253 | T_LOG(__func__, true, "Unable to retrieve jetsam aging policy (not fatal)"); | |
254 | } | |
255 | ||
256 | T_SETUPEND; | |
257 | ||
258 | /* | |
259 | * Relinquish assertion priority even though we don't hold it. No change in state expected. | |
260 | */ | |
261 | T_LOG("********Test0 clean: no state change on relinquish"); | |
262 | relinquish_assertion_priority(mypid, 0xF00D); | |
263 | (void)check_properties(mypid, JETSAM_PRIORITY_IDLE_DEFERRED, inactive_limit_mb, 0xF00D, ASSERTION_STATE_IS_RELINQUISHED, "Test0"); | |
264 | ||
265 | T_LOG("********Test1 clean: deferred now assertion[10]"); | |
266 | set_assertion_priority(mypid, JETSAM_PRIORITY_FOREGROUND, 0xFEED); | |
267 | (void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, inactive_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test1"); | |
268 | ||
269 | /* Test2 */ | |
270 | T_LOG("********Test2 clean: assertion[10 -> 3]"); | |
271 | set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFACE); | |
272 | (void)check_properties(mypid, JETSAM_PRIORITY_BACKGROUND, inactive_limit_mb, 0xFACE, ASSERTION_STATE_IS_SET, "Test2"); | |
273 | ||
274 | /* Test3 */ | |
275 | T_LOG("********Test3 clean: assertion[3 -> 0], but now deferred"); | |
276 | relinquish_assertion_priority(mypid, 0xBEEF); | |
277 | (void)check_properties(mypid, JETSAM_PRIORITY_IDLE_DEFERRED, inactive_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test3"); | |
278 | ||
279 | /* Test4 */ | |
280 | T_LOG("********Test4 clean: deferred now assertion[10]"); | |
281 | set_assertion_priority(mypid, JETSAM_PRIORITY_FOREGROUND, 0xFEED); | |
282 | (void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, inactive_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test4"); | |
283 | ||
284 | T_LOG("Avoid idle-deferred moving forward. Sleeping for 20"); | |
285 | sleep(20); | |
286 | ||
287 | /* Test5 */ | |
288 | T_LOG("********Test5 dirty: set dirty priority but assertion[10] prevails"); | |
289 | proc_will_set_dirty(mypid); /* active priority is less than FG*/ | |
290 | (void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test5"); | |
291 | ||
292 | /* Test6 */ | |
293 | T_LOG("********Test6 dirty: assertion[10 -> 3] but dirty priority prevails"); | |
294 | set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFEEB); /* active priority is > BG */ | |
295 | (void)check_properties(mypid, JETSAM_PRIORITY_UI_SUPPORT, active_limit_mb, 0xFEEB, ASSERTION_STATE_IS_SET, "Test6"); | |
296 | ||
297 | /* Test7 */ | |
298 | T_LOG("********Test7 dirty: assertion[3 -> 0] but dirty prevails"); | |
299 | relinquish_assertion_priority(mypid, 0xBEEF); | |
300 | (void)check_properties(mypid, JETSAM_PRIORITY_UI_SUPPORT, active_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test7"); | |
301 | ||
302 | ||
303 | /* Test8 */ | |
304 | T_LOG("********Test8 dirty: assertion[0 -> 10] overrides dirty"); | |
305 | set_assertion_priority(mypid, JETSAM_PRIORITY_FOREGROUND, 0xFEED); | |
306 | (void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test8"); | |
307 | ||
308 | /* Test9 */ | |
309 | T_LOG("********Test9 dirty wants to go clean, but clean state is prevented as assertion[10] prevails"); | |
310 | proc_will_set_clean(mypid); | |
311 | (void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test9"); | |
312 | ||
313 | /* Test10 */ | |
314 | T_LOG("********Test10 dirty goes dirty and stays dirty, and assertion[10] prevails again"); | |
315 | proc_will_set_dirty(mypid); | |
316 | (void)check_properties(mypid, JETSAM_PRIORITY_FOREGROUND, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test10"); | |
317 | ||
318 | /* Test11 */ | |
319 | T_LOG("********Test11 dirty: assertion[10 -> 3] but dirty prevails"); | |
320 | set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFACE); | |
321 | (void)check_properties(mypid, JETSAM_PRIORITY_UI_SUPPORT, active_limit_mb, 0xFACE, ASSERTION_STATE_IS_SET, "Test11"); | |
322 | ||
323 | /* Test12 */ | |
324 | T_LOG("********Test12 dirty: assertion[3 -> 0] but dirty prevails"); | |
325 | relinquish_assertion_priority(mypid, 0xBEEF); | |
326 | (void)check_properties(mypid, JETSAM_PRIORITY_UI_SUPPORT, active_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test12"); | |
327 | ||
328 | ||
329 | /* Test13 */ | |
330 | T_LOG("********Test13 dirty goes clean: both assertion[0] and clean"); | |
331 | proc_will_set_clean(mypid); | |
332 | if (g_jetsam_aging_policy == kJetsamAgingPolicySysProcsReclaimedFirst) { | |
333 | /* For sysproc aging policy the daemon should be at idle deferred and with an active memory limit */ | |
334 | (void)check_properties(mypid, JETSAM_PRIORITY_IDLE_DEFERRED, active_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test13"); | |
335 | } else { | |
336 | /* For the legacy aging policy, daemon should be at idle band with inactive memory limit */ | |
337 | (void)check_properties(mypid, JETSAM_PRIORITY_IDLE, inactive_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test13"); | |
338 | } | |
339 | } | |
340 | ||
341 | /* | |
342 | * Process is dirty tracking and does not opt into pressured exit. | |
343 | * This test lives above Foreground. Assertions will have no affect | |
344 | * except where the assertion priority bumps it above the requested priority. | |
345 | */ | |
346 | static void | |
347 | memorystatus_assertion_test_do_not_allow_idle_exit() | |
348 | { | |
349 | pid_t mypid = getpid(); | |
350 | ||
351 | /* these values will remain fixed during testing */ | |
352 | int active_limit_mb = 15; /* arbitrary */ | |
353 | int inactive_limit_mb = 7; /* arbitrary */ | |
354 | int requestedpriority = JETSAM_PRIORITY_AUDIO_AND_ACCESSORY; | |
355 | ||
356 | T_SETUPBEGIN; | |
357 | ||
358 | set_memlimits(mypid, active_limit_mb, inactive_limit_mb, true, true); | |
359 | set_priority(mypid, requestedpriority, 0, false); | |
360 | proc_track_dirty(mypid, (PROC_DIRTY_TRACK)); | |
361 | ||
362 | proc_will_set_dirty(mypid); | |
363 | ||
364 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, active_limit_mb, 0x0, ASSERTION_STATE_IS_RELINQUISHED, "Dirty start"); | |
365 | ||
366 | proc_will_set_clean(mypid); | |
367 | ||
368 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0x0, ASSERTION_STATE_IS_RELINQUISHED, "Clean transition"); | |
369 | ||
370 | T_LOG("SETUP STATE COMPLETE"); | |
371 | ||
372 | T_SETUPEND; | |
373 | ||
374 | /* | |
375 | * Relinquish assertion priority even though we don't hold it. No change in state expected. | |
376 | */ | |
377 | ||
378 | ||
379 | /* Test0 */ | |
380 | T_LOG("********Test0 clean: no state change on relinquish"); | |
381 | relinquish_assertion_priority(mypid, 0xF00D); | |
382 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xF00D, ASSERTION_STATE_IS_RELINQUISHED, "Test0"); | |
383 | ||
384 | /* Test1 */ | |
385 | T_LOG("********Test1 clean: assertion[0 -> 10] but inactive priority prevails"); | |
386 | set_assertion_priority(mypid, JETSAM_PRIORITY_FOREGROUND, 0xFEED); | |
387 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test1"); | |
388 | ||
389 | /* Test2 */ | |
390 | T_LOG("********Test2 clean: assertion[10 -> 3] but inactive priority prevails"); | |
391 | set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFACE); | |
392 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xFACE, ASSERTION_STATE_IS_SET, "Test2"); | |
393 | ||
394 | /* Test3 */ | |
395 | T_LOG("********Test3 clean: assertion[3 -> 0], but inactive priority prevails"); | |
396 | relinquish_assertion_priority(mypid, 0xBEEF); | |
397 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test3"); | |
398 | ||
399 | /* Test4 */ | |
400 | T_LOG("********Test4 go dirty: assertion[0] has no affect, active priority prevails"); | |
401 | proc_will_set_dirty(mypid); | |
402 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, active_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test4"); | |
403 | ||
404 | /* Test5 */ | |
405 | T_LOG("********Test5 dirty: assertion[0 -> 10] active priority prevails"); | |
406 | set_assertion_priority(mypid, JETSAM_PRIORITY_FOREGROUND, 0xFEED); | |
407 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test5"); | |
408 | ||
409 | /* Test6 */ | |
410 | T_LOG("********Test6 dirty: assertion[10 -> 3] active priority prevails"); | |
411 | set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFACE); | |
412 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, active_limit_mb, 0xFACE, ASSERTION_STATE_IS_SET, "Test6"); | |
413 | ||
414 | /* Test 7 */ | |
415 | T_LOG("********Test7 dirty: assertion[3 -> 0], active priority prevails"); | |
416 | relinquish_assertion_priority(mypid, 0xBEEF); | |
417 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, active_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test7"); | |
418 | ||
419 | /* Test8 */ | |
420 | T_LOG("********Test8 dirty: assertion[0 -> 19], dirty but now assertion[19] prevails"); | |
421 | set_assertion_priority(mypid, JETSAM_PRIORITY_CRITICAL, 0xFEED); | |
422 | (void)check_properties(mypid, JETSAM_PRIORITY_CRITICAL, active_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test8"); | |
423 | ||
424 | ||
425 | /* Test9 */ | |
426 | T_LOG("********Test9 go clean: inactive priority but assertion[19] prevails"); | |
427 | proc_will_set_clean(mypid); | |
428 | (void)check_properties(mypid, JETSAM_PRIORITY_CRITICAL, inactive_limit_mb, 0xFEED, ASSERTION_STATE_IS_SET, "Test9"); | |
429 | ||
430 | /* Test10 */ | |
431 | T_LOG("********Test10 clean: assertion[19 -> 3] inactive limit prevails"); | |
432 | set_assertion_priority(mypid, JETSAM_PRIORITY_BACKGROUND, 0xFACE); | |
433 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xFACE, ASSERTION_STATE_IS_SET, "Test10"); | |
434 | ||
435 | ||
436 | /* Test11 */ | |
437 | T_LOG("********Test11 clean: assertion[3 -> 0] inactive priority still prevails"); | |
438 | relinquish_assertion_priority(mypid, 0xBEEF); | |
439 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test11"); | |
440 | ||
441 | /* Test12 */ | |
442 | T_LOG("********Test12 dirty goes clean: both assertion[0] and clean"); | |
443 | proc_will_set_clean(mypid); | |
444 | (void)check_properties(mypid, JETSAM_PRIORITY_AUDIO_AND_ACCESSORY, inactive_limit_mb, 0xBEEF, ASSERTION_STATE_IS_RELINQUISHED, "Test12"); | |
445 | } | |
446 | ||
447 | T_DECL(assertion_test_bad_flags, "verify bad flag returns an error", T_META_TIMEOUT(30), T_META_ASROOT(true)) { | |
448 | int err; | |
449 | uint32_t flag = 0; | |
450 | ||
451 | memorystatus_priority_properties_t mjp = { 0 }; | |
452 | ||
453 | mjp.priority = JETSAM_PRIORITY_FOREGROUND; | |
454 | mjp.user_data = 0; | |
455 | ||
456 | /* | |
457 | * init a bad flag | |
458 | */ | |
459 | ||
460 | flag = 0xf; | |
461 | ||
462 | err = memorystatus_control(MEMORYSTATUS_CMD_SET_PRIORITY_PROPERTIES, getpid(), flag, &mjp, sizeof(mjp)); | |
463 | ||
464 | T_QUIET; | |
465 | T_ASSERT_POSIX_FAILURE(err, EINVAL, "MEMORYSTATUS_CMD_SET_PRIORITY_PROPERTIES should fail with bad flags (err=%d)", err); | |
466 | } | |
467 | ||
468 | ||
469 | 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)) { | |
470 | /* | |
471 | * Verify back-to-back assertion calls set assertion state as expected. | |
472 | * false --> non-dirty-tracking process (like a typical app) | |
473 | * false --> clean/dirty does not apply here | |
474 | */ | |
475 | ||
476 | memorystatus_assertion_test_repetitive("Scenario #1", false, false); | |
477 | } | |
478 | ||
479 | 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)) { | |
480 | /* | |
481 | * Verify back-to-back assertion calls set assertion state as expected. | |
482 | * true --> dirty-tracking process (like a typical extension/widget) | |
483 | * true --> start clean / inactive | |
484 | * This will exercise idle-deferred paths. | |
485 | */ | |
486 | memorystatus_assertion_test_repetitive("Scenario #2", true, true); | |
487 | } | |
488 | ||
489 | 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)) { | |
490 | /* | |
491 | * Verify back-to-back assertion calls set assertion state as expected. | |
492 | * true --> dirty-tracking process (like a typical extension/widget) | |
493 | * false --> start dirty / active state | |
494 | * This will exercise idle-deferred paths. | |
495 | */ | |
496 | memorystatus_assertion_test_repetitive("Scenario #3", true, false); | |
497 | } | |
498 | ||
499 | ||
500 | T_DECL(assertion_test_allow_idle_exit, "set assertion priorities on process supporting idle exit", T_META_TIMEOUT(360), T_META_ASROOT(true)) { | |
501 | memorystatus_assertion_test_allow_idle_exit(); | |
502 | } | |
503 | ||
504 | 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)) { | |
505 | memorystatus_assertion_test_do_not_allow_idle_exit(); | |
506 | } |