]> git.saurik.com Git - apple/xnu.git/blob - tests/task_info.c
xnu-6153.11.26.tar.gz
[apple/xnu.git] / tests / task_info.c
1 #include <darwintest.h>
2 #include <darwintest_utils.h>
3 #include <errno.h>
4 #include <mach/mach.h>
5 #include <mach/mach_error.h>
6 #include <mach/policy.h>
7 #include <mach/task_info.h>
8 #include <mach/thread_info.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <sys/mman.h>
13 #include <sys/sysctl.h>
14 #include <unistd.h>
15
16 T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
17
18 /* *************************************************************************************
19 * Test the task_info API.
20 *
21 * This is a functional test of the following APIs:
22 * TASK_BASIC_INFO_32
23 * TASK_BASIC2_INFO_32
24 * TASK_BASIC_INFO_64
25 * TASK_BASIC_INFO_64_2
26 * TASK_POWER_INFO_V2
27 * TASK_FLAGS_INFO
28 * TASK_AFFINITY_TAG_INFO
29 * TASK_THREAD_TIMES_INFO
30 * TASK_ABSOLUTE_TIME_INFO
31 * <rdar://problem/22242021> Add tests to increase code coverage for the task_info API
32 * *************************************************************************************
33 */
34 #define TESTPHYSFOOTPRINTVAL 5
35 #define CANARY 0x0f0f0f0f0f0f0f0fULL
36 #if !defined(CONFIG_EMBEDDED)
37 #define ABSOLUTE_MIN_USER_TIME_DIFF 150
38 #define ABSOLUTE_MIN_SYSTEM_TIME_DIFF 300
39 #endif
40
41 enum info_kind { INFO_32, INFO_64, INFO_32_2, INFO_64_2, INFO_MACH, INFO_MAX };
42
43 enum info_get { GET_SUSPEND_COUNT, GET_RESIDENT_SIZE, GET_VIRTUAL_SIZE, GET_USER_TIME, GET_SYS_TIME, GET_POLICY, GET_MAX_RES };
44
45 /*
46 * This function uses CPU cycles by doing a factorial computation.
47 */
48 static void do_factorial_task(void);
49
50 void test_task_basic_info_32(void);
51 void test_task_basic_info_64(void);
52 void task_basic_info_32_debug(void);
53 void task_basic2_info_32_warmup(void);
54 static int is_development_kernel(void);
55 void test_task_basic_info(enum info_kind kind);
56 uint64_t info_get(enum info_kind kind, enum info_get get, void * data);
57
58 T_DECL(task_vm_info, "tests task vm info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
59 {
60 kern_return_t err;
61 task_vm_info_data_t vm_info;
62
63 mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
64
65 err = task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, &count);
66
67 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
68
69 T_EXPECT_NE(vm_info.virtual_size, 0ULL, "task_info return value !=0 for virtual_size\n");
70
71 T_EXPECT_NE(vm_info.phys_footprint, 0ULL, "task_info return value !=0 for phys_footprint\n");
72
73 /*
74 * Test the REV0 version of TASK_VM_INFO. It should not change the value of phys_footprint.
75 */
76
77 count = TASK_VM_INFO_REV0_COUNT;
78 vm_info.phys_footprint = TESTPHYSFOOTPRINTVAL;
79 vm_info.min_address = CANARY;
80 vm_info.max_address = CANARY;
81
82 err = task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, &count);
83
84 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
85
86 T_EXPECT_EQ(count, TASK_VM_INFO_REV0_COUNT, "task_info count(%d) is equal to TASK_VM_INFO_REV0_COUNT", count);
87
88 T_EXPECT_NE(vm_info.virtual_size, 0ULL, "task_info --rev0 call does not return 0 for virtual_size");
89
90 T_EXPECT_EQ(vm_info.phys_footprint, (unsigned long long)TESTPHYSFOOTPRINTVAL,
91 "task_info --rev0 call returned value %llu for vm_info.phys_footprint. Expected %u since this value should not be "
92 "modified by rev0",
93 vm_info.phys_footprint, TESTPHYSFOOTPRINTVAL);
94
95 T_EXPECT_EQ(vm_info.min_address, CANARY,
96 "task_info --rev0 call returned value 0x%llx for vm_info.min_address. Expected 0x%llx since this value should not "
97 "be modified by rev0",
98 vm_info.min_address, CANARY);
99
100 T_EXPECT_EQ(vm_info.max_address, CANARY,
101 "task_info --rev0 call returned value 0x%llx for vm_info.max_address. Expected 0x%llx since this value should not "
102 "be modified by rev0",
103 vm_info.max_address, CANARY);
104
105 /*
106 * Test the REV1 version of TASK_VM_INFO.
107 */
108
109 count = TASK_VM_INFO_REV1_COUNT;
110 vm_info.phys_footprint = TESTPHYSFOOTPRINTVAL;
111 vm_info.min_address = CANARY;
112 vm_info.max_address = CANARY;
113
114 err = task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, &count);
115
116 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
117
118 T_EXPECT_EQ(count, TASK_VM_INFO_REV1_COUNT, "task_info count(%d) is equal to TASK_VM_INFO_REV1_COUNT", count);
119
120 T_EXPECT_NE(vm_info.virtual_size, 0ULL, "task_info --rev1 call does not return 0 for virtual_size");
121
122 T_EXPECT_NE(vm_info.phys_footprint, (unsigned long long)TESTPHYSFOOTPRINTVAL,
123 "task_info --rev1 call returned value %llu for vm_info.phys_footprint. Expected value is anything other than %u "
124 "since this value should not be modified by rev1",
125 vm_info.phys_footprint, TESTPHYSFOOTPRINTVAL);
126
127 T_EXPECT_EQ(vm_info.min_address, CANARY,
128 "task_info --rev1 call returned value 0x%llx for vm_info.min_address. Expected 0x%llx since this value should not "
129 "be modified by rev1",
130 vm_info.min_address, CANARY);
131
132 T_EXPECT_EQ(vm_info.max_address, CANARY,
133 "task_info --rev1 call returned value 0x%llx for vm_info.max_address. Expected 0x%llx since this value should not "
134 "be modified by rev1",
135 vm_info.max_address, CANARY);
136
137 /*
138 * Test the REV2 version of TASK_VM_INFO.
139 */
140
141 count = TASK_VM_INFO_REV2_COUNT;
142 vm_info.phys_footprint = TESTPHYSFOOTPRINTVAL;
143 vm_info.min_address = CANARY;
144 vm_info.max_address = CANARY;
145
146 err = task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, &count);
147
148 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
149
150 T_EXPECT_EQ(count, TASK_VM_INFO_REV2_COUNT, "task_info count(%d) is equal to TASK_VM_INFO_REV2_COUNT\n", count);
151
152 T_EXPECT_NE(vm_info.virtual_size, 0ULL, "task_info --rev2 call does not return 0 for virtual_size\n");
153
154 T_EXPECT_NE(vm_info.phys_footprint, (unsigned long long)TESTPHYSFOOTPRINTVAL,
155 "task_info --rev2 call returned value %llu for vm_info.phys_footprint. Expected anything other than %u since this "
156 "value should be modified by rev2",
157 vm_info.phys_footprint, TESTPHYSFOOTPRINTVAL);
158
159 T_EXPECT_NE(vm_info.min_address, CANARY,
160 "task_info --rev2 call returned value 0x%llx for vm_info.min_address. Expected anything other than 0x%llx since "
161 "this value should be modified by rev2",
162 vm_info.min_address, CANARY);
163
164 T_EXPECT_NE(vm_info.max_address, CANARY,
165 "task_info --rev2 call returned value 0x%llx for vm_info.max_address. Expected anything other than 0x%llx since "
166 "this value should be modified by rev2",
167 vm_info.max_address, CANARY);
168
169 /*
170 * Test the REV4 version of TASK_VM_INFO.
171 */
172
173 count = TASK_VM_INFO_REV4_COUNT;
174 vm_info.phys_footprint = TESTPHYSFOOTPRINTVAL;
175 vm_info.min_address = CANARY;
176 vm_info.max_address = CANARY;
177 vm_info.limit_bytes_remaining = CANARY;
178
179 err = task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE, (task_info_t)&vm_info, &count);
180
181 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
182
183 T_EXPECT_EQ(count, TASK_VM_INFO_REV4_COUNT, "task_info count(%d) is equal to TASK_VM_INFO_REV4_COUNT\n", count);
184
185 T_EXPECT_NE(vm_info.phys_footprint, (unsigned long long)TESTPHYSFOOTPRINTVAL,
186 "task_info --rev4 call returned value %llu for vm_info.phys_footprint. Expected anything other than %u since this "
187 "value should be modified by rev4",
188 vm_info.phys_footprint, TESTPHYSFOOTPRINTVAL);
189
190 T_EXPECT_NE(vm_info.min_address, CANARY,
191 "task_info --rev4 call returned value 0x%llx for vm_info.min_address. Expected anything other than 0x%llx since "
192 "this value should be modified by rev4",
193 vm_info.min_address, CANARY);
194
195 T_EXPECT_NE(vm_info.max_address, CANARY,
196 "task_info --rev4 call returned value 0x%llx for vm_info.max_address. Expected anything other than 0x%llx since "
197 "this value should be modified by rev4",
198 vm_info.max_address, CANARY);
199
200 T_EXPECT_NE(vm_info.limit_bytes_remaining, CANARY,
201 "task_info --rev4 call returned value 0x%llx for vm_info.limit_bytes_remaining. Expected anything other than 0x%llx since "
202 "this value should be modified by rev4",
203 vm_info.limit_bytes_remaining, CANARY);
204 }
205
206 T_DECL(host_debug_info, "tests host debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
207 {
208 T_SETUPBEGIN;
209 int is_dev = is_development_kernel();
210 T_QUIET;
211 T_ASSERT_TRUE(is_dev, "verify development kernel is running");
212 T_SETUPEND;
213
214 kern_return_t err;
215 mach_port_t host;
216 host_debug_info_internal_data_t debug_info;
217 mach_msg_type_number_t count = HOST_DEBUG_INFO_INTERNAL_COUNT;
218 host = mach_host_self();
219 err = host_info(host, HOST_DEBUG_INFO_INTERNAL, (host_info_t)&debug_info, &count);
220
221 T_ASSERT_MACH_SUCCESS(err, "verify host_info call succeeded");
222 }
223
224 T_DECL(task_debug_info, "tests task debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
225 {
226 T_SETUPBEGIN;
227 int is_dev = is_development_kernel();
228 T_QUIET;
229 T_ASSERT_TRUE(is_dev, "verify development kernel is running");
230 T_SETUPEND;
231
232 kern_return_t err;
233 task_debug_info_internal_data_t debug_info;
234
235 mach_msg_type_number_t count = TASK_DEBUG_INFO_INTERNAL_COUNT;
236
237 err = task_info(mach_task_self(), TASK_DEBUG_INFO_INTERNAL, (task_info_t)&debug_info, &count);
238
239 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
240 }
241
242 T_DECL(thread_debug_info, "tests thread debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
243 {
244 T_SETUPBEGIN;
245 int is_dev = is_development_kernel();
246 T_QUIET;
247 T_ASSERT_TRUE(is_dev, "verify development kernel is running");
248 T_SETUPEND;
249
250 kern_return_t err;
251 thread_debug_info_internal_data_t debug_info;
252
253 mach_msg_type_number_t count = THREAD_DEBUG_INFO_INTERNAL_COUNT;
254
255 err = thread_info(mach_thread_self(), THREAD_DEBUG_INFO_INTERNAL, (thread_info_t)&debug_info, &count);
256
257 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
258 }
259
260 static void
261 do_factorial_task()
262 {
263 int number = 20;
264 int factorial = 1;
265 int i;
266 for (i = 1; i <= number; i++) {
267 factorial *= i;
268 }
269
270 return;
271 }
272
273 T_DECL(task_thread_times_info, "tests task thread times info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
274 {
275 T_SETUPBEGIN;
276 int is_dev = is_development_kernel();
277 T_QUIET;
278 T_ASSERT_TRUE(is_dev, "verify development kernel is running");
279 T_SETUPEND;
280
281 kern_return_t err;
282 task_thread_times_info_data_t thread_times_info_data;
283 task_thread_times_info_data_t thread_times_info_data_new;
284 mach_msg_type_number_t count = TASK_THREAD_TIMES_INFO_COUNT;
285
286 err = task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t)&thread_times_info_data, &count);
287
288 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
289
290 do_factorial_task();
291
292 err = task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t)&thread_times_info_data_new, &count);
293
294 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
295
296 /*
297 * The difference is observed to be less than 30 microseconds for user_time
298 * and less than 50 microseconds for system_time. This observation was done for over
299 * 1000 runs.
300 */
301
302 T_EXPECT_FALSE((thread_times_info_data_new.user_time.seconds - thread_times_info_data.user_time.seconds) != 0 ||
303 (thread_times_info_data_new.system_time.seconds - thread_times_info_data.system_time.seconds) != 0,
304 "Tests whether the difference between thread times is greater than the allowed limit");
305
306 /*
307 * This is a negative case.
308 */
309
310 count--;
311 err = task_info(mach_task_self(), TASK_THREAD_TIMES_INFO, (task_info_t)&thread_times_info_data, &count);
312 T_ASSERT_MACH_ERROR(err, KERN_INVALID_ARGUMENT,
313 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
314 }
315
316 T_DECL(task_absolutetime_info, "tests task absolute time info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
317 {
318 T_SETUPBEGIN;
319 int is_dev = is_development_kernel();
320 T_QUIET;
321 T_ASSERT_TRUE(is_dev, "verify development kernel is running");
322 T_SETUPEND;
323
324 kern_return_t err;
325 uint64_t user_time_diff, system_time_diff;
326 task_absolutetime_info_data_t absolute_time_info_data;
327 task_absolutetime_info_data_t absolute_time_info_data_new;
328 mach_msg_type_number_t count = TASK_ABSOLUTETIME_INFO_COUNT;
329
330 err = task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO, (task_info_t)&absolute_time_info_data, &count);
331
332 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
333
334 do_factorial_task();
335
336 err = task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO, (task_info_t)&absolute_time_info_data_new, &count);
337
338 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
339
340 user_time_diff = absolute_time_info_data_new.total_user - absolute_time_info_data.total_user;
341 system_time_diff = absolute_time_info_data_new.total_system - absolute_time_info_data.total_system;
342
343 #if !(defined(__arm__) || defined(__arm64__))
344 /*
345 * On embedded devices the difference is always zero.
346 * On non-embedded devices the difference occurs in this range. This was observed over ~10000 runs.
347 */
348
349 T_EXPECT_FALSE(user_time_diff < ABSOLUTE_MIN_USER_TIME_DIFF || system_time_diff < ABSOLUTE_MIN_SYSTEM_TIME_DIFF,
350 "Tests whether the difference between thread times is greater than the expected range");
351 #endif
352
353 if (absolute_time_info_data.threads_user <= 0) {
354 int precise_time_val = 0;
355 size_t len = sizeof(size_t);
356
357 T_LOG("User threads time is zero. This should only happen rarely and when precise_user_time is off");
358
359 err = sysctlbyname("kern.precise_user_kernel_time", &precise_time_val, &len, NULL, 0);
360
361 T_EXPECT_POSIX_SUCCESS(err, "performing sysctl to check precise_user_time");
362
363 T_LOG("kern.precise_user_kernel_time val = %d", precise_time_val);
364
365 T_EXPECT_FALSE(precise_time_val, "user thread time should only be zero when precise_user_kernel_time is disabled");
366 } else {
367 T_PASS("task_info should return non-zero value for user threads time = %llu", absolute_time_info_data.threads_user);
368 }
369
370 #if !(defined(__arm__) || defined(__arm64__))
371 /*
372 * On iOS, system threads are always zero. On OS X this value can be some large positive number.
373 * There is no real way to estimate the exact amount.
374 */
375 T_EXPECT_NE(absolute_time_info_data.threads_system, 0ULL,
376 "task_info should return non-zero value for system threads time = %llu", absolute_time_info_data.threads_system);
377 #endif
378
379 /*
380 * This is a negative case.
381 */
382 count--;
383 err = task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO, (task_info_t)&absolute_time_info_data_new, &count);
384 T_ASSERT_MACH_ERROR(err, KERN_INVALID_ARGUMENT,
385 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
386 }
387
388 T_DECL(task_affinity_tag_info, "tests task_affinity_tag_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
389 {
390 T_SETUPBEGIN;
391 int is_dev = is_development_kernel();
392 T_QUIET;
393 T_ASSERT_TRUE(is_dev, "verify development kernel is running");
394 T_SETUPEND;
395
396 kern_return_t err;
397 task_affinity_tag_info_data_t affinity_tag_info_data;
398 mach_msg_type_number_t count = TASK_AFFINITY_TAG_INFO_COUNT;
399
400 err = task_info(mach_task_self(), TASK_AFFINITY_TAG_INFO, (task_info_t)&affinity_tag_info_data, &count);
401
402 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
403
404 /*
405 * The affinity is not set by default, hence expecting a zero value.
406 */
407 T_ASSERT_FALSE(affinity_tag_info_data.min != 0 || affinity_tag_info_data.max != 0,
408 "task_info call returns non-zero min or max value");
409
410 /*
411 * This is a negative case.
412 */
413 count--;
414 err = task_info(mach_task_self(), TASK_AFFINITY_TAG_INFO, (task_info_t)&affinity_tag_info_data, &count);
415 T_ASSERT_MACH_ERROR(err, KERN_INVALID_ARGUMENT,
416 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
417 }
418
419 T_DECL(task_flags_info, "tests task_flags_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
420 {
421 T_SETUPBEGIN;
422 int is_dev = is_development_kernel();
423 T_QUIET;
424 T_ASSERT_TRUE(is_dev, "verify development kernel is running");
425 T_SETUPEND;
426
427 kern_return_t err;
428 task_flags_info_data_t flags_info_data;
429 mach_msg_type_number_t count = TASK_FLAGS_INFO_COUNT;
430
431 err = task_info(mach_task_self(), TASK_FLAGS_INFO, (task_info_t)&flags_info_data, &count);
432
433 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
434
435 /* Change for 32-bit arch possibility?*/
436 T_ASSERT_EQ((flags_info_data.flags & (unsigned int)(~(TF_LP64 | TF_64B_DATA))), 0U,
437 "task_info should only give out 64-bit addr/data flags");
438
439 /*
440 * This is a negative case.
441 */
442
443 count--;
444 err = task_info(mach_task_self(), TASK_FLAGS_INFO, (task_info_t)&flags_info_data, &count);
445 T_ASSERT_MACH_ERROR(err, KERN_INVALID_ARGUMENT,
446 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
447 }
448
449 T_DECL(task_power_info_v2, "tests task_power_info_v2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
450 {
451 T_SETUPBEGIN;
452 int is_dev = is_development_kernel();
453 T_QUIET;
454 T_ASSERT_TRUE(is_dev, "verify development kernel is running");
455 T_SETUPEND;
456
457 kern_return_t err;
458 task_power_info_v2_data_t power_info_data_v2;
459 task_power_info_v2_data_t power_info_data_v2_new;
460 mach_msg_type_number_t count = TASK_POWER_INFO_V2_COUNT;
461
462 sleep(1);
463
464 err = task_info(mach_task_self(), TASK_POWER_INFO_V2, (task_info_t)&power_info_data_v2, &count);
465
466 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
467
468 T_ASSERT_LE(power_info_data_v2.gpu_energy.task_gpu_utilisation, 0ULL,
469 "verified task_info call shows zero GPU utilization for non-GPU task");
470
471 do_factorial_task();
472
473 /*
474 * Verify the cpu_energy parameters.
475 */
476 err = task_info(mach_task_self(), TASK_POWER_INFO_V2, (task_info_t)&power_info_data_v2_new, &count);
477 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
478
479 #if !(defined(__arm__) || defined(__arm64__))
480 /*
481 * iOS does not have system_time.
482 */
483 T_ASSERT_GT(power_info_data_v2_new.cpu_energy.total_user, power_info_data_v2.cpu_energy.total_user,
484 "task_info call returns valid user time");
485 T_ASSERT_GT(power_info_data_v2_new.cpu_energy.total_system, power_info_data_v2.cpu_energy.total_system,
486 "task_info call returns valid system time");
487 #endif
488
489 T_ASSERT_GE(power_info_data_v2.cpu_energy.task_interrupt_wakeups, 1ULL,
490 "verify task_info call returns non-zero value for interrupt_wakeup (ret value = %llu)",
491 power_info_data_v2.cpu_energy.task_interrupt_wakeups);
492
493 #if !(defined(__arm__) || defined(__arm64__))
494 if (power_info_data_v2.cpu_energy.task_platform_idle_wakeups != 0) {
495 T_LOG("task_info call returned %llu for platform_idle_wakeup", power_info_data_v2.cpu_energy.task_platform_idle_wakeups);
496 }
497 #endif
498
499 count = TASK_POWER_INFO_V2_COUNT_OLD;
500 err = task_info(mach_task_self(), TASK_POWER_INFO_V2, (task_info_t)&power_info_data_v2, &count);
501
502 T_ASSERT_MACH_SUCCESS(err, "verify task_info call succeeded");
503
504 /*
505 * This is a negative case.
506 */
507 count--;
508 err = task_info(mach_task_self(), TASK_POWER_INFO_V2, (task_info_t)&power_info_data_v2, &count);
509
510 T_ASSERT_MACH_ERROR(err, KERN_INVALID_ARGUMENT,
511 "Negative test case: task_info should verify that count is at least equal to what is defined in API. Call "
512 "returns errno %d:%s",
513 err, mach_error_string(err));
514 }
515
516 T_DECL(test_task_basic_info_32, "tests TASK_BASIC_INFO_32", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
517 {
518 test_task_basic_info(INFO_32);
519 }
520
521 T_DECL(test_task_basic_info_32_2, "tests TASK_BASIC_INFO_32_2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
522 {
523 test_task_basic_info(INFO_32_2);
524 }
525
526 #if defined(__arm__) || defined(__arm64__)
527 T_DECL(test_task_basic_info_64i_2, "tests TASK_BASIC_INFO_64_2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
528 {
529 test_task_basic_info(INFO_64_2);
530 }
531 #else
532 T_DECL(test_task_basic_info_64, "tests TASK_BASIC_INFO_64", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
533 {
534 test_task_basic_info(INFO_64);
535 }
536 #endif /* defined(__arm__) || defined(__arm64__) */
537
538 T_DECL(test_mach_task_basic_info, "tests MACH_TASK_BASIC_INFO", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT))
539 {
540 test_task_basic_info(INFO_MACH);
541 }
542
543 void
544 test_task_basic_info(enum info_kind kind)
545 {
546 #define BEFORE 0
547 #define AFTER 1
548
549 T_SETUPBEGIN;
550 int is_dev = is_development_kernel();
551 T_QUIET;
552 T_ASSERT_TRUE(is_dev, "verify development kernel is running");
553 T_SETUPEND;
554
555 task_info_t info_data[2];
556 task_basic_info_32_data_t basic_info_32_data[2];
557 #if defined(__arm__) || defined(__arm64__)
558 task_basic_info_64_2_data_t basic_info_64_2_data[2];
559 #else
560 task_basic_info_64_data_t basic_info_64_data[2];
561 #endif /* defined(__arm__) || defined(__arm64__) */
562 mach_task_basic_info_data_t mach_basic_info_data[2];
563
564 kern_return_t kr;
565 mach_msg_type_number_t count;
566 task_flavor_t flavor = 0;
567 integer_t suspend_count;
568 uint64_t resident_size_diff;
569 uint64_t virtual_size_diff;
570
571 void * tmp_map = NULL;
572 pid_t child_pid;
573 mach_port_name_t child_task;
574 /*for dt_waitpid*/
575 int timeout = 10; // change to max timeout
576 int exit_status = 0;
577
578 switch (kind) {
579 case INFO_32:
580 case INFO_32_2:
581 info_data[BEFORE] = (task_info_t)&basic_info_32_data[BEFORE];
582 info_data[AFTER] = (task_info_t)&basic_info_32_data[AFTER];
583 count = TASK_BASIC_INFO_32_COUNT;
584 flavor = TASK_BASIC_INFO_32;
585
586 if (kind == INFO_32_2) {
587 flavor = TASK_BASIC2_INFO_32;
588 }
589
590 break;
591 #if defined(__arm__) || defined(__arm64__)
592 case INFO_64:
593 T_ASSERT_FAIL("invalid basic info kind");
594 break;
595
596 case INFO_64_2:
597 info_data[BEFORE] = (task_info_t)&basic_info_64_2_data[BEFORE];
598 info_data[AFTER] = (task_info_t)&basic_info_64_2_data[AFTER];
599 count = TASK_BASIC_INFO_64_2_COUNT;
600 flavor = TASK_BASIC_INFO_64_2;
601 break;
602
603 #else
604 case INFO_64:
605 info_data[BEFORE] = (task_info_t)&basic_info_64_data[BEFORE];
606 info_data[AFTER] = (task_info_t)&basic_info_64_data[AFTER];
607 count = TASK_BASIC_INFO_64_COUNT;
608 flavor = TASK_BASIC_INFO_64;
609 break;
610
611 case INFO_64_2:
612 T_ASSERT_FAIL("invalid basic info kind");
613 break;
614 #endif /* defined(__arm__) || defined(__arm64__) */
615 case INFO_MACH:
616 info_data[BEFORE] = (task_info_t)&mach_basic_info_data[BEFORE];
617 info_data[AFTER] = (task_info_t)&mach_basic_info_data[AFTER];
618 count = MACH_TASK_BASIC_INFO_COUNT;
619 flavor = MACH_TASK_BASIC_INFO;
620 break;
621 case INFO_MAX:
622 default:
623 T_ASSERT_FAIL("invalid basic info kind");
624 break;
625 }
626
627 kr = task_info(mach_task_self(), flavor, info_data[BEFORE], &count);
628
629 T_ASSERT_MACH_SUCCESS(kr, "verify task_info succeeded");
630
631 do_factorial_task();
632
633 /*
634 * Allocate virtual and resident memory.
635 */
636 tmp_map = mmap(0, PAGE_SIZE, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
637
638 T_WITH_ERRNO;
639 T_EXPECT_NE(tmp_map, MAP_FAILED, "verify mmap call is successful");
640
641 memset(tmp_map, 'm', PAGE_SIZE);
642
643 child_pid = fork();
644
645 T_ASSERT_POSIX_SUCCESS(child_pid, "verify process can be forked");
646
647 if (child_pid == 0) {
648 /*
649 * This will suspend the child process.
650 */
651 kr = task_suspend(mach_task_self());
652 exit(kr);
653 }
654
655 /*
656 * Wait for the child process to suspend itself.
657 */
658 sleep(1);
659
660 kr = task_for_pid(mach_task_self(), child_pid, &child_task);
661 T_ASSERT_MACH_SUCCESS(kr, "verify task_for_pid succeeded. check sudo if failed");
662
663 /*
664 * Verify the suspend_count for child and resume it.
665 */
666
667 kr = task_info(child_task, flavor, info_data[AFTER], &count);
668 T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded");
669
670 suspend_count = (integer_t)(info_get(kind, GET_SUSPEND_COUNT, info_data[AFTER]));
671 T_ASSERT_EQ(suspend_count, 1, "verify task_info shows correct suspend_count");
672
673 kr = task_resume(child_task);
674 T_ASSERT_MACH_SUCCESS(kr, "verify task_resume succeeded");
675
676 /*
677 * reap kr from task_suspend call in child
678 */
679 if (dt_waitpid(child_pid, &exit_status, NULL, timeout)) {
680 T_ASSERT_MACH_SUCCESS(exit_status, "verify child task_suspend is successful");
681 } else {
682 T_FAIL("dt_waitpid failed");
683 }
684
685 kr = task_info(mach_task_self(), flavor, info_data[AFTER], &count);
686 T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded");
687
688 resident_size_diff = info_get(kind, GET_RESIDENT_SIZE, info_data[AFTER]) - info_get(kind, GET_RESIDENT_SIZE, info_data[BEFORE]);
689 virtual_size_diff = info_get(kind, GET_VIRTUAL_SIZE, info_data[AFTER]) - info_get(kind, GET_VIRTUAL_SIZE, info_data[BEFORE]);
690
691 /*
692 * INFO_32_2 gets the max resident size instead of the current resident size
693 * 32 KB tolerance built into test. The returned value is generally between 0 and 16384
694 *
695 * max resident size is a discrete field in INFO_MACH, so it's handled differently
696 */
697 if (kind == INFO_32_2) {
698 T_EXPECT_EQ(resident_size_diff % 4096, 0ULL, "verify task_info returns valid max resident_size");
699 T_EXPECT_GE(resident_size_diff, 0ULL, "verify task_info returns non-negative max resident_size");
700 T_EXPECT_GE(virtual_size_diff, (unsigned long long)PAGE_SIZE, "verify task_info returns valid virtual_size");
701 } else {
702 T_EXPECT_GE(resident_size_diff, (unsigned long long)PAGE_SIZE, "task_info returns valid resident_size");
703 T_EXPECT_GE(virtual_size_diff, (unsigned long long)PAGE_SIZE, "task_info returns valid virtual_size");
704 }
705
706 if (kind == INFO_MACH) {
707 resident_size_diff = info_get(kind, GET_MAX_RES, info_data[AFTER]) - info_get(kind, GET_MAX_RES, info_data[BEFORE]);
708 T_EXPECT_EQ(resident_size_diff % 4096, 0ULL, "verify task_info returns valid max resident_size");
709 T_EXPECT_GE(resident_size_diff, 0ULL, "verify task_info returns non-negative max resident_size");
710 T_EXPECT_GE(info_get(kind, GET_MAX_RES, info_data[AFTER]), info_get(kind, GET_RESIDENT_SIZE, info_data[AFTER]),
711 "verify max resident size is greater than or equal to curr resident size");
712 }
713
714 do_factorial_task();
715
716 /*
717 * These counters give time for threads that have terminated. We dont have any, so checking for zero.
718 */
719
720 time_value_t * user_tv = (time_value_t *)(info_get(kind, GET_USER_TIME, info_data[BEFORE]));
721 T_EXPECT_EQ((user_tv->seconds + user_tv->microseconds / 1000000), 0, "verify task_info shows valid user time");
722
723 time_value_t * sys_tv = (time_value_t *)(info_get(kind, GET_SYS_TIME, info_data[BEFORE]));
724 T_EXPECT_EQ(sys_tv->seconds + (sys_tv->microseconds / 1000000), 0, "verify task_info shows valid system time");
725
726 /*
727 * The default value for non-kernel tasks is TIMESHARE.
728 */
729
730 policy_t pt = (policy_t)info_get(kind, GET_POLICY, info_data[BEFORE]);
731
732 T_EXPECT_EQ(pt, POLICY_TIMESHARE, "verify task_info shows valid policy");
733
734 /*
735 * This is a negative case.
736 */
737
738 count--;
739 kr = task_info(mach_task_self(), flavor, info_data[AFTER], &count);
740
741 T_ASSERT_MACH_ERROR(kr, KERN_INVALID_ARGUMENT,
742 "Negative test case: task_info should verify that count is at least equal to what is defined in API");
743
744 /*
745 * deallocate memory
746 */
747 munmap(tmp_map, PAGE_SIZE);
748
749 return;
750
751 #undef BEFORE
752 #undef AFTER
753 }
754
755 T_DECL(test_sigcont_task_suspend_resume,
756 "test to verify that SIGCONT on task_suspend()-ed process works",
757 T_META_ASROOT(true),
758 T_META_LTEPHASE(LTE_POSTINIT))
759 {
760 T_SETUPBEGIN;
761 int is_dev = is_development_kernel();
762 T_QUIET;
763 T_ASSERT_TRUE(is_dev, "verify development kernel is running");
764 T_SETUPEND;
765
766 mach_task_basic_info_data_t mach_basic_info_data;
767 task_info_t info_data = (task_info_t)&mach_basic_info_data;
768
769 task_debug_info_internal_data_t debug_info;
770 mach_msg_type_number_t debug_count = TASK_DEBUG_INFO_INTERNAL_COUNT;
771
772 kern_return_t kr;
773 int posix_ret;
774 mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT;
775 task_flavor_t flavor = MACH_TASK_BASIC_INFO;
776 integer_t suspend_count;
777 integer_t debug_suspend_count;
778 pid_t child_pid = 0;
779 mach_port_name_t child_task;
780 /*for dt_waitpid*/
781 int timeout = 5;
782 int exit_status = 0;
783 int signal_no = 0;
784
785 child_pid = fork();
786
787 T_ASSERT_POSIX_SUCCESS(child_pid, "verify process can be forked");
788
789 if (child_pid == 0) {
790 /*
791 * This will suspend the child process.
792 */
793 kr = task_suspend(mach_task_self());
794
795 /*
796 * When child resumes, it exits immediately
797 */
798
799 exit(kr);
800 }
801
802 /*
803 * Wait for the child process to suspend itself.
804 */
805 sleep(1);
806
807 kr = task_for_pid(mach_task_self(), child_pid, &child_task);
808 T_ASSERT_MACH_SUCCESS(kr, "verify task_for_pid succeeded. check sudo if failed");
809
810 /*
811 * Verify the suspend_count for child and resume it.
812 */
813
814 kr = task_info(child_task, flavor, info_data, &count);
815 T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded");
816
817 suspend_count = (integer_t)(info_get(INFO_MACH, GET_SUSPEND_COUNT, info_data));
818 T_ASSERT_EQ(suspend_count, 1, "verify task_info shows correct suspend_count (1) (actually user stop count) ");
819
820 kr = task_info(child_task, TASK_DEBUG_INFO_INTERNAL, (task_info_t)&debug_info, &debug_count);
821 T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded");
822
823 debug_suspend_count = debug_info.suspend_count;
824 T_ASSERT_EQ(debug_info.suspend_count, 1, "verify debug_info shows correct suspend_count(1)");
825
826 posix_ret = kill(child_pid, SIGCONT);
827 T_ASSERT_POSIX_SUCCESS(posix_ret, "verify signal call succeeded");
828
829 /*
830 * reap kr from task_suspend call in child
831 */
832 dt_waitpid(child_pid, &exit_status, &signal_no, timeout);
833
834 T_ASSERT_EQ(signal_no, 0, "child should be resumed and exit without signal");
835 T_ASSERT_EQ(exit_status, 0, "child should exit with 0");
836 }
837
838 T_DECL(test_sigcont_task_suspend2_resume,
839 "test to verify that SIGCONT on task_suspend2()-ed process doesn't work",
840 T_META_ASROOT(true),
841 T_META_LTEPHASE(LTE_POSTINIT))
842 {
843 T_SETUPBEGIN;
844 int is_dev = is_development_kernel();
845 T_QUIET;
846 T_ASSERT_TRUE(is_dev, "verify development kernel is running");
847 T_SETUPEND;
848
849 mach_task_basic_info_data_t mach_basic_info_data;
850 task_info_t info_data = (task_info_t)&mach_basic_info_data;
851
852 task_debug_info_internal_data_t debug_info;
853 mach_msg_type_number_t debug_count = TASK_DEBUG_INFO_INTERNAL_COUNT;
854
855 kern_return_t kr;
856 int posix_ret;
857 mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT;
858 task_flavor_t flavor = MACH_TASK_BASIC_INFO;
859 integer_t suspend_count = 0;
860 integer_t debug_suspend_count = 0;
861 pid_t child_pid = 0;
862 mach_port_name_t child_task;
863 task_suspension_token_t child_token = 0xFFFFF;
864
865 /*
866 * for dt_waitpid
867 * We expect the test to fail right now, so I've set timeout to
868 * be shorter than we may want it to be when the issue is fixed
869 */
870 int timeout = 1;
871 int exit_status = 0;
872 int signal_no = 0;
873
874 /* for pipe */
875 int fd[2];
876 pipe(fd);
877 int pipe_msg = 0;
878
879 child_pid = fork();
880
881 T_ASSERT_POSIX_SUCCESS(child_pid, "verify process can be forked %d", child_pid);
882
883 if (child_pid == 0) {
884 close(fd[1]);
885 T_LOG("Waiting to read from parent...");
886 read(fd[0], &pipe_msg, sizeof(pipe_msg));
887 T_LOG("Done reading from parent, about to exit...");
888 exit(0);
889 }
890 /*
891 * Wait for child to fork and block on read
892 */
893 sleep(1);
894
895 close(fd[0]);
896
897 kr = task_for_pid(mach_task_self(), child_pid, &child_task);
898 T_ASSERT_MACH_SUCCESS(kr, "verify task_for_pid succeeded. check sudo if failed");
899
900 kr = task_info(child_task, TASK_DEBUG_INFO_INTERNAL, (task_info_t)&debug_info, &debug_count);
901 T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded");
902
903 debug_suspend_count = debug_info.suspend_count;
904 T_EXPECT_EQ(debug_suspend_count, 0, "verify debug_info shows correct (true) suspend_count(0)");
905
906 kr = task_suspend2(child_task, &child_token);
907 T_ASSERT_MACH_SUCCESS(kr, "verify task_suspend2 call succeeded");
908
909 kr = task_info(child_task, TASK_DEBUG_INFO_INTERNAL, (task_info_t)&debug_info, &debug_count);
910 T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded");
911
912 debug_suspend_count = debug_info.suspend_count;
913 T_ASSERT_EQ(debug_suspend_count, 1, "verify debug_info shows correct (true) suspend_count(1)");
914
915 /*
916 * Verify the suspend_count for child and resume it.
917 */
918
919 kr = task_info(child_task, flavor, info_data, &count);
920 T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded");
921
922 suspend_count = (integer_t)(info_get(INFO_MACH, GET_SUSPEND_COUNT, info_data));
923 T_EXPECT_EQ(suspend_count, 1, "verify task_info shows correct (user_stop_count) suspend_count (1)");
924
925 posix_ret = kill(child_pid, SIGCONT);
926 T_ASSERT_POSIX_SUCCESS(posix_ret, "verify signal call succeeded");
927
928 kr = task_info(child_task, TASK_DEBUG_INFO_INTERNAL, (task_info_t)&debug_info, &debug_count);
929 T_EXPECT_MACH_SUCCESS(kr, "verify task_info call succeeded");
930
931 debug_suspend_count = debug_info.suspend_count;
932 T_EXPECTFAIL_WITH_RADAR(33166654);
933 T_EXPECT_EQ(debug_suspend_count, 1, "verify debug_info shows correct (true) suspend_count (1)");
934
935 suspend_count = (integer_t)(info_get(INFO_MACH, GET_SUSPEND_COUNT, info_data));
936 T_ASSERT_EQ(suspend_count, 1, "verify task_info shows correct (user_stop_count) suspend_count (1) after SIG_CONT");
937
938 kr = task_resume(child_task);
939 T_EXPECTFAIL_WITH_RADAR(33166654);
940 T_EXPECT_MACH_SUCCESS(kr, "verify task_resume succeeded");
941
942 /*
943 * reap kr from task_suspend call in child
944 */
945
946 dt_waitpid(child_pid, &exit_status, &signal_no, timeout);
947
948 T_ASSERT_EQ(signal_no, SIG_DT_TIMEOUT, "dt_waitpid timed out as expected");
949
950 // Resume properly using token and then wait
951
952 kr = task_resume2(child_token);
953 T_EXPECTFAIL_WITH_RADAR(33166654);
954 T_ASSERT_MACH_SUCCESS(kr, "verify task_resume2 succeeded");
955
956 write(fd[1], &pipe_msg, sizeof(pipe_msg));
957
958 /*
959 * reap kr from task_suspend call in child
960 */
961 dt_waitpid(child_pid, &exit_status, &signal_no, timeout);
962
963 T_ASSERT_EQ(signal_no, 0, "child should be resumed and no signal should be returned");
964 T_ASSERT_EQ(exit_status, 0, "child should exit with 0");
965 }
966
967 uint64_t
968 info_get(enum info_kind kind, enum info_get get, void * data)
969 {
970 switch (get) {
971 case GET_SUSPEND_COUNT:
972 switch (kind) {
973 case INFO_32:
974 case INFO_32_2:
975 return (uint64_t)(((task_basic_info_32_t)data)->suspend_count);
976 #if defined(__arm__) || defined(__arm64__)
977 case INFO_64:
978 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
979 break;
980
981 case INFO_64_2:
982 return (uint64_t)(((task_basic_info_64_2_t)data)->suspend_count);
983 #else
984 case INFO_64:
985 return (uint64_t)(((task_basic_info_64_t)data)->suspend_count);
986
987 case INFO_64_2:
988 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
989 break;
990 #endif /* defined(__arm__) || defined(__arm64__) */
991 case INFO_MACH:
992 return (uint64_t)(((mach_task_basic_info_t)data)->suspend_count);
993 case INFO_MAX:
994 default:
995 T_ASSERT_FAIL("unhandled info_get %d %d", kind, get);
996 }
997 case GET_RESIDENT_SIZE:
998 switch (kind) {
999 case INFO_32:
1000 case INFO_32_2:
1001 return (uint64_t)(((task_basic_info_32_t)data)->resident_size);
1002 #if defined(__arm__) || defined(__arm64__)
1003 case INFO_64:
1004 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
1005 break;
1006
1007 case INFO_64_2:
1008 return (uint64_t)(((task_basic_info_64_2_t)data)->resident_size);
1009 #else
1010 case INFO_64:
1011 return (uint64_t)(((task_basic_info_64_t)data)->resident_size);
1012
1013 case INFO_64_2:
1014 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
1015 break;
1016 #endif /* defined(__arm__) || defined(__arm64__) */
1017 case INFO_MACH:
1018 return (uint64_t)(((mach_task_basic_info_t)data)->resident_size);
1019 case INFO_MAX:
1020 default:
1021 T_ASSERT_FAIL("unhandled info_get %d %d", kind, get);
1022 }
1023 case GET_VIRTUAL_SIZE:
1024 switch (kind) {
1025 case INFO_32:
1026 case INFO_32_2:
1027 return (uint64_t)(((task_basic_info_32_t)data)->virtual_size);
1028 #if defined(__arm__) || defined(__arm64__)
1029 case INFO_64:
1030 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
1031 break;
1032
1033 case INFO_64_2:
1034 return (uint64_t)(((task_basic_info_64_2_t)data)->virtual_size);
1035 #else
1036 case INFO_64:
1037 return (uint64_t)(((task_basic_info_64_t)data)->virtual_size);
1038
1039 case INFO_64_2:
1040 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
1041 break;
1042 #endif /* defined(__arm__) || defined(__arm64__) */
1043 case INFO_MACH:
1044 return (uint64_t)(((mach_task_basic_info_t)data)->virtual_size);
1045
1046 case INFO_MAX:
1047 default:
1048 T_ASSERT_FAIL("unhandled info_get %d %d", kind, get);
1049 }
1050 case GET_USER_TIME:
1051 switch (kind) {
1052 case INFO_32:
1053 case INFO_32_2:
1054 return (uint64_t) &(((task_basic_info_32_t)data)->user_time);
1055 #if defined(__arm__) || defined(__arm64__)
1056 case INFO_64:
1057 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
1058 break;
1059
1060 case INFO_64_2:
1061 return (uint64_t) &(((task_basic_info_64_2_t)data)->user_time);
1062 #else
1063 case INFO_64:
1064 return (uint64_t) &(((task_basic_info_64_t)data)->user_time);
1065
1066 case INFO_64_2:
1067 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
1068 break;
1069 #endif /* defined(__arm__) || defined(__arm64__) */
1070 case INFO_MACH:
1071 return (uint64_t) &(((mach_task_basic_info_t)data)->user_time);
1072
1073 case INFO_MAX:
1074 default:
1075 T_ASSERT_FAIL("unhandled info_get %d %d", kind, get);
1076 }
1077 case GET_SYS_TIME:
1078 switch (kind) {
1079 case INFO_32:
1080 case INFO_32_2:
1081 return (uint64_t) &(((task_basic_info_32_t)data)->system_time);
1082 #if defined(__arm__) || defined(__arm64__)
1083 case INFO_64:
1084 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
1085 break;
1086
1087 case INFO_64_2:
1088 return (uint64_t) &(((task_basic_info_64_2_t)data)->system_time);
1089 #else
1090 case INFO_64:
1091 return (uint64_t) &(((task_basic_info_64_t)data)->system_time);
1092
1093 case INFO_64_2:
1094 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
1095 break;
1096 #endif /* defined(__arm__) || defined(__arm64__) */
1097 case INFO_MACH:
1098 return (uint64_t) &(((mach_task_basic_info_t)data)->user_time);
1099 case INFO_MAX:
1100 default:
1101 T_ASSERT_FAIL("unhandled info_get %d %d", kind, get);
1102 }
1103 case GET_POLICY:
1104 switch (kind) {
1105 case INFO_32:
1106 case INFO_32_2:
1107 return (uint64_t)(((task_basic_info_32_t)data)->policy);
1108 #if defined(__arm__) || defined(__arm64__)
1109 case INFO_64:
1110 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
1111 break;
1112
1113 case INFO_64_2:
1114 return (uint64_t)(((task_basic_info_64_2_t)data)->policy);
1115 #else
1116 case INFO_64:
1117 return (uint64_t)(((task_basic_info_64_t)data)->policy);
1118
1119 case INFO_64_2:
1120 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
1121 break;
1122 #endif /* defined(__arm__) || defined(__arm64__) */
1123 case INFO_MACH:
1124 return (uint64_t)(((mach_task_basic_info_t)data)->policy);
1125
1126 case INFO_MAX:
1127 default:
1128 T_ASSERT_FAIL("unhandled info_get %d %d", kind, get);
1129 }
1130 case GET_MAX_RES:
1131 switch (kind) {
1132 case INFO_32:
1133 case INFO_32_2:
1134 case INFO_64:
1135 case INFO_64_2:
1136 T_ASSERT_FAIL("illegal info_get %d %d", kind, get);
1137 case INFO_MACH:
1138 return (uint64_t)(((mach_task_basic_info_t)data)->resident_size_max);
1139 case INFO_MAX:
1140 default:
1141 T_ASSERT_FAIL("unhandled info_get %d %d", kind, get);
1142 }
1143 }
1144
1145 __builtin_unreachable();
1146 }
1147
1148 /*
1149 * Determines whether we're running on a development kernel
1150 */
1151 static int
1152 is_development_kernel(void)
1153 {
1154 #define NOTSET -1
1155
1156 static int is_dev = NOTSET;
1157
1158 if (is_dev == NOTSET) {
1159 int dev;
1160 size_t dev_size = sizeof(dev);
1161
1162 T_QUIET;
1163 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.development", &dev, &dev_size, NULL, 0), NULL);
1164 is_dev = (dev != 0);
1165
1166 return is_dev;
1167 } else {
1168 return is_dev;
1169 }
1170 #undef NOTSET
1171 }