2 #include <mach/task_info.h>
3 #include <mach/thread_info.h>
4 #include <mach/mach_error.h>
10 #include <mach/policy.h>
11 #include <darwintest.h>
12 #include <sys/sysctl.h>
13 #include <darwintest_utils.h>
15 /* *************************************************************************************
16 * Test the task_info API.
18 * This is a functional test of the following APIs:
22 * TASK_BASIC_INFO_64_2
25 * TASK_AFFINITY_TAG_INFO
26 * TASK_THREAD_TIMES_INFO
27 * TASK_ABSOLUTE_TIME_INFO
28 * <rdar://problem/22242021> Add tests to increase code coverage for the task_info API
29 * *************************************************************************************
31 #define TESTPHYSFOOTPRINTVAL 5
32 #define CANARY 0x0f0f0f0f0f0f0f0fULL
33 #if !defined(CONFIG_EMBEDDED)
34 #define ABSOLUTE_MIN_USER_TIME_DIFF 150
35 #define ABSOLUTE_MIN_SYSTEM_TIME_DIFF 300
38 enum info_kind
{ INFO_32
, INFO_64
, INFO_32_2
, INFO_64_2
, INFO_MACH
, INFO_MAX
};
40 enum info_get
{ GET_SUSPEND_COUNT
, GET_RESIDENT_SIZE
, GET_VIRTUAL_SIZE
, GET_USER_TIME
, GET_SYS_TIME
, GET_POLICY
, GET_MAX_RES
};
43 * This function uses CPU cycles by doing a factorial computation.
45 static void do_factorial_task(void);
47 void test_task_basic_info_32(void);
48 void test_task_basic_info_64(void);
49 void task_basic_info_32_debug(void);
50 void task_basic2_info_32_warmup(void);
51 static int is_development_kernel(void);
52 void test_task_basic_info(enum info_kind kind
);
53 uint64_t info_get(enum info_kind kind
, enum info_get get
, void * data
);
55 T_DECL(task_vm_info
, "tests task vm info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
58 task_vm_info_data_t vm_info
;
60 mach_msg_type_number_t count
= TASK_VM_INFO_COUNT
;
62 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
64 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
66 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info return value !=0 for virtual_size\n");
68 T_EXPECT_NE(vm_info
.phys_footprint
, 0ULL, "task_info return value !=0 for phys_footprint\n");
71 * Test the REV0 version of TASK_VM_INFO. It should not change the value of phys_footprint.
74 count
= TASK_VM_INFO_REV0_COUNT
;
75 vm_info
.phys_footprint
= TESTPHYSFOOTPRINTVAL
;
76 vm_info
.min_address
= CANARY
;
77 vm_info
.max_address
= CANARY
;
79 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
81 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
83 T_EXPECT_EQ(count
, TASK_VM_INFO_REV0_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV0_COUNT", count
);
85 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev0 call does not return 0 for virtual_size");
87 T_EXPECT_EQ(vm_info
.phys_footprint
, (unsigned long long)TESTPHYSFOOTPRINTVAL
,
88 "task_info --rev0 call returned value %llu for vm_info.phys_footprint. Expected %u since this value should not be "
90 vm_info
.phys_footprint
, TESTPHYSFOOTPRINTVAL
);
92 T_EXPECT_EQ(vm_info
.min_address
, CANARY
,
93 "task_info --rev0 call returned value 0x%llx for vm_info.min_address. Expected 0x%llx since this value should not "
94 "be modified by rev0",
95 vm_info
.min_address
, CANARY
);
97 T_EXPECT_EQ(vm_info
.max_address
, CANARY
,
98 "task_info --rev0 call returned value 0x%llx for vm_info.max_address. Expected 0x%llx since this value should not "
99 "be modified by rev0",
100 vm_info
.max_address
, CANARY
);
103 * Test the REV1 version of TASK_VM_INFO.
106 count
= TASK_VM_INFO_REV1_COUNT
;
107 vm_info
.phys_footprint
= TESTPHYSFOOTPRINTVAL
;
108 vm_info
.min_address
= CANARY
;
109 vm_info
.max_address
= CANARY
;
111 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
113 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
115 T_EXPECT_EQ(count
, TASK_VM_INFO_REV1_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV1_COUNT", count
);
117 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev1 call does not return 0 for virtual_size");
119 T_EXPECT_NE(vm_info
.phys_footprint
, (unsigned long long)TESTPHYSFOOTPRINTVAL
,
120 "task_info --rev1 call returned value %llu for vm_info.phys_footprint. Expected value is anything other than %u "
121 "since this value should not be modified by rev1",
122 vm_info
.phys_footprint
, TESTPHYSFOOTPRINTVAL
);
124 T_EXPECT_EQ(vm_info
.min_address
, CANARY
,
125 "task_info --rev1 call returned value 0x%llx for vm_info.min_address. Expected 0x%llx since this value should not "
126 "be modified by rev1",
127 vm_info
.min_address
, CANARY
);
129 T_EXPECT_EQ(vm_info
.max_address
, CANARY
,
130 "task_info --rev1 call returned value 0x%llx for vm_info.max_address. Expected 0x%llx since this value should not "
131 "be modified by rev1",
132 vm_info
.max_address
, CANARY
);
135 * Test the REV2 version of TASK_VM_INFO.
138 count
= TASK_VM_INFO_REV2_COUNT
;
139 vm_info
.phys_footprint
= TESTPHYSFOOTPRINTVAL
;
140 vm_info
.min_address
= CANARY
;
141 vm_info
.max_address
= CANARY
;
143 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
145 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
147 T_EXPECT_EQ(count
, TASK_VM_INFO_REV2_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV2_COUNT\n", count
);
149 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev2 call does not return 0 for virtual_size\n");
151 T_EXPECT_NE(vm_info
.phys_footprint
, (unsigned long long)TESTPHYSFOOTPRINTVAL
,
152 "task_info --rev2 call returned value %llu for vm_info.phys_footprint. Expected anything other than %u since this "
153 "value should be modified by rev2",
154 vm_info
.phys_footprint
, TESTPHYSFOOTPRINTVAL
);
156 T_EXPECT_NE(vm_info
.min_address
, CANARY
,
157 "task_info --rev2 call returned value 0x%llx for vm_info.min_address. Expected anything other than 0x%llx since "
158 "this value should be modified by rev2",
159 vm_info
.min_address
, CANARY
);
161 T_EXPECT_NE(vm_info
.max_address
, CANARY
,
162 "task_info --rev2 call returned value 0x%llx for vm_info.max_address. Expected anything other than 0x%llx since "
163 "this value should be modified by rev2",
164 vm_info
.max_address
, CANARY
);
167 T_DECL(host_debug_info
, "tests host debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
170 int is_dev
= is_development_kernel();
172 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
177 host_debug_info_internal_data_t debug_info
;
178 mach_msg_type_number_t count
= HOST_DEBUG_INFO_INTERNAL_COUNT
;
179 host
= mach_host_self();
180 err
= host_info(host
, HOST_DEBUG_INFO_INTERNAL
, (host_info_t
)&debug_info
, &count
);
182 T_ASSERT_MACH_SUCCESS(err
, "verify host_info call succeeded");
185 T_DECL(task_debug_info
, "tests task debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
188 int is_dev
= is_development_kernel();
190 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
194 task_debug_info_internal_data_t debug_info
;
196 mach_msg_type_number_t count
= TASK_DEBUG_INFO_INTERNAL_COUNT
;
198 err
= task_info(mach_task_self(), TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &count
);
200 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
203 T_DECL(thread_debug_info
, "tests thread debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
206 int is_dev
= is_development_kernel();
208 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
212 thread_debug_info_internal_data_t debug_info
;
214 mach_msg_type_number_t count
= THREAD_DEBUG_INFO_INTERNAL_COUNT
;
216 err
= thread_info(mach_thread_self(), THREAD_DEBUG_INFO_INTERNAL
, (thread_info_t
)&debug_info
, &count
);
218 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
227 for (i
= 1; i
<= number
; i
++) {
234 T_DECL(task_thread_times_info
, "tests task thread times info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
237 int is_dev
= is_development_kernel();
239 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
243 task_thread_times_info_data_t thread_times_info_data
;
244 task_thread_times_info_data_t thread_times_info_data_new
;
245 mach_msg_type_number_t count
= TASK_THREAD_TIMES_INFO_COUNT
;
247 err
= task_info(mach_task_self(), TASK_THREAD_TIMES_INFO
, (task_info_t
)&thread_times_info_data
, &count
);
249 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
253 err
= task_info(mach_task_self(), TASK_THREAD_TIMES_INFO
, (task_info_t
)&thread_times_info_data_new
, &count
);
255 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
258 * The difference is observed to be less than 30 microseconds for user_time
259 * and less than 50 microseconds for system_time. This observation was done for over
263 T_EXPECT_FALSE((thread_times_info_data_new
.user_time
.seconds
- thread_times_info_data
.user_time
.seconds
) != 0 ||
264 (thread_times_info_data_new
.system_time
.seconds
- thread_times_info_data
.system_time
.seconds
) != 0,
265 "Tests whether the difference between thread times is greater than the allowed limit");
268 * This is a negative case.
272 err
= task_info(mach_task_self(), TASK_THREAD_TIMES_INFO
, (task_info_t
)&thread_times_info_data
, &count
);
273 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
274 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
277 T_DECL(task_absolutetime_info
, "tests task absolute time info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
280 int is_dev
= is_development_kernel();
282 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
286 uint64_t user_time_diff
, system_time_diff
;
287 task_absolutetime_info_data_t absolute_time_info_data
;
288 task_absolutetime_info_data_t absolute_time_info_data_new
;
289 mach_msg_type_number_t count
= TASK_ABSOLUTETIME_INFO_COUNT
;
291 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data
, &count
);
293 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
297 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data_new
, &count
);
299 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
301 user_time_diff
= absolute_time_info_data_new
.total_user
- absolute_time_info_data
.total_user
;
302 system_time_diff
= absolute_time_info_data_new
.total_system
- absolute_time_info_data
.total_system
;
304 #if !(defined(__arm__) || defined(__arm64__))
306 * On embedded devices the difference is always zero.
307 * On non-embedded devices the difference occurs in this range. This was observed over ~10000 runs.
310 T_EXPECT_FALSE(user_time_diff
< ABSOLUTE_MIN_USER_TIME_DIFF
|| system_time_diff
< ABSOLUTE_MIN_SYSTEM_TIME_DIFF
,
311 "Tests whether the difference between thread times is greater than the expected range");
315 * There is no way of estimating the exact number of threads, hence checking the counter to be non-zero for now.
318 T_EXPECT_NE(absolute_time_info_data
.threads_user
, 0ULL, "task_info should return non-zero number of user threads");
320 #if !(defined(__arm__) || defined(__arm64__))
322 * On iOS, system threads are always zero. On OS X this value can be some large positive number.
323 * There is no real way to estimate the exact amount.
325 T_EXPECT_NE(absolute_time_info_data
.threads_system
, 0ULL, "task_info should return non-zero number of system threads");
329 * This is a negative case.
332 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data_new
, &count
);
333 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
334 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
337 T_DECL(task_affinity_tag_info
, "tests task_affinity_tag_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
340 int is_dev
= is_development_kernel();
342 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
346 task_affinity_tag_info_data_t affinity_tag_info_data
;
347 mach_msg_type_number_t count
= TASK_AFFINITY_TAG_INFO_COUNT
;
349 err
= task_info(mach_task_self(), TASK_AFFINITY_TAG_INFO
, (task_info_t
)&affinity_tag_info_data
, &count
);
351 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
354 * The affinity is not set by default, hence expecting a zero value.
356 T_ASSERT_FALSE(affinity_tag_info_data
.min
!= 0 || affinity_tag_info_data
.max
!= 0,
357 "task_info call returns non-zero min or max value");
360 * This is a negative case.
363 err
= task_info(mach_task_self(), TASK_AFFINITY_TAG_INFO
, (task_info_t
)&affinity_tag_info_data
, &count
);
364 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
365 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
368 T_DECL(task_flags_info
, "tests task_flags_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
371 int is_dev
= is_development_kernel();
373 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
377 task_flags_info_data_t flags_info_data
;
378 mach_msg_type_number_t count
= TASK_FLAGS_INFO_COUNT
;
380 err
= task_info(mach_task_self(), TASK_FLAGS_INFO
, (task_info_t
)&flags_info_data
, &count
);
382 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
384 /* Change for 32-bit arch possibility?*/
385 T_ASSERT_EQ((flags_info_data
.flags
& (unsigned int)(~TF_LP64
)), 0U, "task_info should only give out 64-bit addr flag");
388 * This is a negative case.
392 err
= task_info(mach_task_self(), TASK_FLAGS_INFO
, (task_info_t
)&flags_info_data
, &count
);
393 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
394 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
397 T_DECL(task_power_info_v2
, "tests task_power_info_v2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
400 int is_dev
= is_development_kernel();
402 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
406 task_power_info_v2_data_t power_info_data_v2
;
407 task_power_info_v2_data_t power_info_data_v2_new
;
408 mach_msg_type_number_t count
= TASK_POWER_INFO_V2_COUNT
;
412 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
414 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
416 T_ASSERT_LE(power_info_data_v2
.gpu_energy
.task_gpu_utilisation
, 0ULL,
417 "verified task_info call shows zero GPU utilization for non-GPU task");
422 * Verify the cpu_energy parameters.
424 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2_new
, &count
);
425 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
427 #if !(defined(__arm__) || defined(__arm64__))
429 * iOS does not have system_time.
431 T_ASSERT_GT(power_info_data_v2_new
.cpu_energy
.total_user
, power_info_data_v2
.cpu_energy
.total_user
,
432 "task_info call returns valid user time");
433 T_ASSERT_GT(power_info_data_v2_new
.cpu_energy
.total_system
, power_info_data_v2
.cpu_energy
.total_system
,
434 "task_info call returns valid system time");
437 T_ASSERT_GE(power_info_data_v2
.cpu_energy
.task_interrupt_wakeups
, 1ULL,
438 "verify task_info call returns non-zero value for interrupt_wakeup (ret value = %llu)",
439 power_info_data_v2
.cpu_energy
.task_interrupt_wakeups
);
441 #if !(defined(__arm__) || defined(__arm64__))
442 if (power_info_data_v2
.cpu_energy
.task_platform_idle_wakeups
!= 0) {
443 T_LOG("task_info call returned %llu for platform_idle_wakeup", power_info_data_v2
.cpu_energy
.task_platform_idle_wakeups
);
447 count
= TASK_POWER_INFO_V2_COUNT_OLD
;
448 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
450 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
453 * This is a negative case.
456 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
458 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
459 "Negative test case: task_info should verify that count is at least equal to what is defined in API. Call "
460 "returns errno %d:%s",
461 err
, mach_error_string(err
));
464 T_DECL(test_task_basic_info_32
, "tests TASK_BASIC_INFO_32", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
466 test_task_basic_info(INFO_32
);
469 T_DECL(test_task_basic_info_32_2
, "tests TASK_BASIC_INFO_32_2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
471 test_task_basic_info(INFO_32_2
);
474 #if defined(__arm__) || defined(__arm64__)
475 T_DECL(test_task_basic_info_64i_2
, "tests TASK_BASIC_INFO_64_2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
477 test_task_basic_info(INFO_64_2
);
480 T_DECL(test_task_basic_info_64
, "tests TASK_BASIC_INFO_64", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
482 test_task_basic_info(INFO_64
);
484 #endif /* defined(__arm__) || defined(__arm64__) */
486 T_DECL(test_mach_task_basic_info
, "tests MACH_TASK_BASIC_INFO", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
488 test_task_basic_info(INFO_MACH
);
492 test_task_basic_info(enum info_kind kind
)
498 int is_dev
= is_development_kernel();
500 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
503 task_info_t info_data
[2];
504 task_basic_info_32_data_t basic_info_32_data
[2];
505 #if defined(__arm__) || defined(__arm64__)
506 task_basic_info_64_2_data_t basic_info_64_2_data
[2];
508 task_basic_info_64_data_t basic_info_64_data
[2];
509 #endif /* defined(__arm__) || defined(__arm64__) */
510 mach_task_basic_info_data_t mach_basic_info_data
[2];
513 mach_msg_type_number_t count
;
514 task_flavor_t flavor
= 0;
515 integer_t suspend_count
;
516 uint64_t resident_size_diff
;
517 uint64_t virtual_size_diff
;
519 void * tmp_map
= NULL
;
521 mach_port_name_t child_task
;
523 int timeout
= 10; // change to max timeout
529 info_data
[BEFORE
] = (task_info_t
)&basic_info_32_data
[BEFORE
];
530 info_data
[AFTER
] = (task_info_t
)&basic_info_32_data
[AFTER
];
531 count
= TASK_BASIC_INFO_32_COUNT
;
532 flavor
= TASK_BASIC_INFO_32
;
534 if (kind
== INFO_32_2
) {
535 flavor
= TASK_BASIC2_INFO_32
;
539 #if defined(__arm__) || defined(__arm64__)
541 T_ASSERT_FAIL("invalid basic info kind");
545 info_data
[BEFORE
] = (task_info_t
)&basic_info_64_2_data
[BEFORE
];
546 info_data
[AFTER
] = (task_info_t
)&basic_info_64_2_data
[AFTER
];
547 count
= TASK_BASIC_INFO_64_2_COUNT
;
548 flavor
= TASK_BASIC_INFO_64_2
;
553 info_data
[BEFORE
] = (task_info_t
)&basic_info_64_data
[BEFORE
];
554 info_data
[AFTER
] = (task_info_t
)&basic_info_64_data
[AFTER
];
555 count
= TASK_BASIC_INFO_64_COUNT
;
556 flavor
= TASK_BASIC_INFO_64
;
560 T_ASSERT_FAIL("invalid basic info kind");
562 #endif /* defined(__arm__) || defined(__arm64__) */
564 info_data
[BEFORE
] = (task_info_t
)&mach_basic_info_data
[BEFORE
];
565 info_data
[AFTER
] = (task_info_t
)&mach_basic_info_data
[AFTER
];
566 count
= MACH_TASK_BASIC_INFO_COUNT
;
567 flavor
= MACH_TASK_BASIC_INFO
;
571 T_ASSERT_FAIL("invalid basic info kind");
575 kr
= task_info(mach_task_self(), flavor
, info_data
[BEFORE
], &count
);
577 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info succeeded");
582 * Allocate virtual and resident memory.
584 tmp_map
= mmap(0, PAGE_SIZE
, PROT_WRITE
, MAP_ANON
| MAP_PRIVATE
, -1, 0);
587 T_EXPECT_NE(tmp_map
, MAP_FAILED
, "verify mmap call is successful");
589 memset(tmp_map
, 'm', PAGE_SIZE
);
593 T_ASSERT_POSIX_SUCCESS(child_pid
, "verify process can be forked");
595 if (child_pid
== 0) {
597 * This will suspend the child process.
599 kr
= task_suspend(mach_task_self());
604 * Wait for the child process to suspend itself.
608 kr
= task_for_pid(mach_task_self(), child_pid
, &child_task
);
609 T_ASSERT_MACH_SUCCESS(kr
, "verify task_for_pid succeeded. check sudo if failed");
612 * Verify the suspend_count for child and resume it.
615 kr
= task_info(child_task
, flavor
, info_data
[AFTER
], &count
);
616 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
618 suspend_count
= (integer_t
)(info_get(kind
, GET_SUSPEND_COUNT
, info_data
[AFTER
]));
619 T_ASSERT_EQ(suspend_count
, 1, "verify task_info shows correct suspend_count");
621 kr
= task_resume(child_task
);
622 T_ASSERT_MACH_SUCCESS(kr
, "verify task_resume succeeded");
625 * reap kr from task_suspend call in child
627 if (dt_waitpid(child_pid
, &exit_status
, NULL
, timeout
)) {
628 T_ASSERT_MACH_SUCCESS(exit_status
, "verify child task_suspend is successful");
630 T_FAIL("dt_waitpid failed");
633 kr
= task_info(mach_task_self(), flavor
, info_data
[AFTER
], &count
);
634 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
636 resident_size_diff
= info_get(kind
, GET_RESIDENT_SIZE
, info_data
[AFTER
]) - info_get(kind
, GET_RESIDENT_SIZE
, info_data
[BEFORE
]);
637 virtual_size_diff
= info_get(kind
, GET_VIRTUAL_SIZE
, info_data
[AFTER
]) - info_get(kind
, GET_VIRTUAL_SIZE
, info_data
[BEFORE
]);
640 * INFO_32_2 gets the max resident size instead of the current resident size
641 * 32 KB tolerance built into test. The returned value is generally between 0 and 16384
643 * max resident size is a discrete field in INFO_MACH, so it's handled differently
645 if (kind
== INFO_32_2
) {
646 T_EXPECT_EQ(resident_size_diff
% 4096, 0ULL, "verify task_info returns valid max resident_size");
647 T_EXPECT_GE(resident_size_diff
, 0ULL, "verify task_info returns non-negative max resident_size");
648 T_EXPECT_GE(virtual_size_diff
, (unsigned long long)PAGE_SIZE
, "verify task_info returns valid virtual_size");
650 T_EXPECT_GE(resident_size_diff
, (unsigned long long)PAGE_SIZE
, "task_info returns valid resident_size");
651 T_EXPECT_GE(virtual_size_diff
, (unsigned long long)PAGE_SIZE
, "task_info returns valid virtual_size");
654 if (kind
== INFO_MACH
) {
655 resident_size_diff
= info_get(kind
, GET_MAX_RES
, info_data
[AFTER
]) - info_get(kind
, GET_MAX_RES
, info_data
[BEFORE
]);
656 T_EXPECT_EQ(resident_size_diff
% 4096, 0ULL, "verify task_info returns valid max resident_size");
657 T_EXPECT_GE(resident_size_diff
, 0ULL, "verify task_info returns non-negative max resident_size");
658 T_EXPECT_GE(info_get(kind
, GET_MAX_RES
, info_data
[AFTER
]), info_get(kind
, GET_RESIDENT_SIZE
, info_data
[AFTER
]),
659 "verify max resident size is greater than or equal to curr resident size");
665 * These counters give time for threads that have terminated. We dont have any, so checking for zero.
668 time_value_t
* user_tv
= (time_value_t
*)(info_get(kind
, GET_USER_TIME
, info_data
[BEFORE
]));
669 T_EXPECT_EQ((user_tv
->seconds
+ user_tv
->microseconds
/ 1000000), 0, "verify task_info shows valid user time");
671 time_value_t
* sys_tv
= (time_value_t
*)(info_get(kind
, GET_SYS_TIME
, info_data
[BEFORE
]));
672 T_EXPECT_EQ(sys_tv
->seconds
+ (sys_tv
->microseconds
/ 1000000), 0, "verify task_info shows valid system time");
675 * The default value for non-kernel tasks is TIMESHARE.
678 policy_t pt
= (policy_t
)info_get(kind
, GET_POLICY
, info_data
[BEFORE
]);
680 T_EXPECT_EQ(pt
, POLICY_TIMESHARE
, "verify task_info shows valid policy");
683 * This is a negative case.
687 kr
= task_info(mach_task_self(), flavor
, info_data
[AFTER
], &count
);
689 T_ASSERT_MACH_ERROR(kr
, KERN_INVALID_ARGUMENT
,
690 "Negative test case: task_info should verify that count is at least equal to what is defined in API");
695 munmap(tmp_map
, PAGE_SIZE
);
704 info_get(enum info_kind kind
, enum info_get get
, void * data
)
707 case GET_SUSPEND_COUNT
:
711 return (uint64_t)(((task_basic_info_32_t
)data
)->suspend_count
);
712 #if defined(__arm__) || defined(__arm64__)
714 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
718 return (uint64_t)(((task_basic_info_64_2_t
)data
)->suspend_count
);
721 return (uint64_t)(((task_basic_info_64_t
)data
)->suspend_count
);
724 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
726 #endif /* defined(__arm__) || defined(__arm64__) */
728 return (uint64_t)(((mach_task_basic_info_t
)data
)->suspend_count
);
731 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
733 case GET_RESIDENT_SIZE
:
737 return (uint64_t)(((task_basic_info_32_t
)data
)->resident_size
);
738 #if defined(__arm__) || defined(__arm64__)
740 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
744 return (uint64_t)(((task_basic_info_64_2_t
)data
)->resident_size
);
747 return (uint64_t)(((task_basic_info_64_t
)data
)->resident_size
);
750 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
752 #endif /* defined(__arm__) || defined(__arm64__) */
754 return (uint64_t)(((mach_task_basic_info_t
)data
)->resident_size
);
757 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
759 case GET_VIRTUAL_SIZE
:
763 return (uint64_t)(((task_basic_info_32_t
)data
)->virtual_size
);
764 #if defined(__arm__) || defined(__arm64__)
766 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
770 return (uint64_t)(((task_basic_info_64_2_t
)data
)->virtual_size
);
773 return (uint64_t)(((task_basic_info_64_t
)data
)->virtual_size
);
776 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
778 #endif /* defined(__arm__) || defined(__arm64__) */
780 return (uint64_t)(((mach_task_basic_info_t
)data
)->virtual_size
);
784 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
790 return (uint64_t) & (((task_basic_info_32_t
)data
)->user_time
);
791 #if defined(__arm__) || defined(__arm64__)
793 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
797 return (uint64_t) & (((task_basic_info_64_2_t
)data
)->user_time
);
800 return (uint64_t) & (((task_basic_info_64_t
)data
)->user_time
);
803 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
805 #endif /* defined(__arm__) || defined(__arm64__) */
807 return (uint64_t) & (((mach_task_basic_info_t
)data
)->user_time
);
811 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
817 return (uint64_t) & (((task_basic_info_32_t
)data
)->system_time
);
818 #if defined(__arm__) || defined(__arm64__)
820 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
824 return (uint64_t) & (((task_basic_info_64_2_t
)data
)->system_time
);
827 return (uint64_t) & (((task_basic_info_64_t
)data
)->system_time
);
830 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
832 #endif /* defined(__arm__) || defined(__arm64__) */
834 return (uint64_t) & (((mach_task_basic_info_t
)data
)->user_time
);
837 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
843 return (uint64_t)(((task_basic_info_32_t
)data
)->policy
);
844 #if defined(__arm__) || defined(__arm64__)
846 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
850 return (uint64_t)(((task_basic_info_64_2_t
)data
)->policy
);
853 return (uint64_t)(((task_basic_info_64_t
)data
)->policy
);
856 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
858 #endif /* defined(__arm__) || defined(__arm64__) */
860 return (uint64_t)(((mach_task_basic_info_t
)data
)->policy
);
864 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
872 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
874 return (uint64_t)(((mach_task_basic_info_t
)data
)->resident_size_max
);
877 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
881 __builtin_unreachable();
885 * Determines whether we're running on a development kernel
888 is_development_kernel(void)
892 static int is_dev
= NOTSET
;
894 if (is_dev
== NOTSET
) {
896 size_t dev_size
= sizeof(dev
);
899 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.development", &dev
, &dev_size
, NULL
, 0), NULL
);