1 #include <darwintest.h>
2 #include <darwintest_utils.h>
5 #include <mach/mach_error.h>
6 #include <mach/policy.h>
7 #include <mach/task_info.h>
8 #include <mach/thread_info.h>
12 #include <sys/sysctl.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");
314 if (absolute_time_info_data
.threads_user
<= 0) {
315 int precise_time_val
= 0;
316 size_t len
= sizeof(size_t);
318 T_LOG("User threads time is zero. This should only happen rarely and when precise_user_time is off");
320 err
= sysctlbyname("kern.precise_user_kernel_time", &precise_time_val
, &len
, NULL
, 0);
322 T_EXPECT_POSIX_SUCCESS(err
, "performing sysctl to check precise_user_time");
324 T_LOG("kern.precise_user_kernel_time val = %d", precise_time_val
);
326 T_EXPECT_FALSE(precise_time_val
, "user thread time should only be zero when precise_user_kernel_time is disabled");
328 T_PASS("task_info should return non-zero value for user threads time = %llu", absolute_time_info_data
.threads_user
);
331 #if !(defined(__arm__) || defined(__arm64__))
333 * On iOS, system threads are always zero. On OS X this value can be some large positive number.
334 * There is no real way to estimate the exact amount.
336 T_EXPECT_NE(absolute_time_info_data
.threads_system
, 0ULL,
337 "task_info should return non-zero value for system threads time = %llu", absolute_time_info_data
.threads_system
);
341 * This is a negative case.
344 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data_new
, &count
);
345 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
346 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
349 T_DECL(task_affinity_tag_info
, "tests task_affinity_tag_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
352 int is_dev
= is_development_kernel();
354 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
358 task_affinity_tag_info_data_t affinity_tag_info_data
;
359 mach_msg_type_number_t count
= TASK_AFFINITY_TAG_INFO_COUNT
;
361 err
= task_info(mach_task_self(), TASK_AFFINITY_TAG_INFO
, (task_info_t
)&affinity_tag_info_data
, &count
);
363 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
366 * The affinity is not set by default, hence expecting a zero value.
368 T_ASSERT_FALSE(affinity_tag_info_data
.min
!= 0 || affinity_tag_info_data
.max
!= 0,
369 "task_info call returns non-zero min or max value");
372 * This is a negative case.
375 err
= task_info(mach_task_self(), TASK_AFFINITY_TAG_INFO
, (task_info_t
)&affinity_tag_info_data
, &count
);
376 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
377 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
380 T_DECL(task_flags_info
, "tests task_flags_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
383 int is_dev
= is_development_kernel();
385 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
389 task_flags_info_data_t flags_info_data
;
390 mach_msg_type_number_t count
= TASK_FLAGS_INFO_COUNT
;
392 err
= task_info(mach_task_self(), TASK_FLAGS_INFO
, (task_info_t
)&flags_info_data
, &count
);
394 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
396 /* Change for 32-bit arch possibility?*/
397 T_ASSERT_EQ((flags_info_data
.flags
& (unsigned int)(~TF_LP64
)), 0U, "task_info should only give out 64-bit addr flag");
400 * This is a negative case.
404 err
= task_info(mach_task_self(), TASK_FLAGS_INFO
, (task_info_t
)&flags_info_data
, &count
);
405 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
406 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
409 T_DECL(task_power_info_v2
, "tests task_power_info_v2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
412 int is_dev
= is_development_kernel();
414 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
418 task_power_info_v2_data_t power_info_data_v2
;
419 task_power_info_v2_data_t power_info_data_v2_new
;
420 mach_msg_type_number_t count
= TASK_POWER_INFO_V2_COUNT
;
424 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
426 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
428 T_ASSERT_LE(power_info_data_v2
.gpu_energy
.task_gpu_utilisation
, 0ULL,
429 "verified task_info call shows zero GPU utilization for non-GPU task");
434 * Verify the cpu_energy parameters.
436 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2_new
, &count
);
437 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
439 #if !(defined(__arm__) || defined(__arm64__))
441 * iOS does not have system_time.
443 T_ASSERT_GT(power_info_data_v2_new
.cpu_energy
.total_user
, power_info_data_v2
.cpu_energy
.total_user
,
444 "task_info call returns valid user time");
445 T_ASSERT_GT(power_info_data_v2_new
.cpu_energy
.total_system
, power_info_data_v2
.cpu_energy
.total_system
,
446 "task_info call returns valid system time");
449 T_ASSERT_GE(power_info_data_v2
.cpu_energy
.task_interrupt_wakeups
, 1ULL,
450 "verify task_info call returns non-zero value for interrupt_wakeup (ret value = %llu)",
451 power_info_data_v2
.cpu_energy
.task_interrupt_wakeups
);
453 #if !(defined(__arm__) || defined(__arm64__))
454 if (power_info_data_v2
.cpu_energy
.task_platform_idle_wakeups
!= 0) {
455 T_LOG("task_info call returned %llu for platform_idle_wakeup", power_info_data_v2
.cpu_energy
.task_platform_idle_wakeups
);
459 count
= TASK_POWER_INFO_V2_COUNT_OLD
;
460 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
462 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
465 * This is a negative case.
468 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
470 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
471 "Negative test case: task_info should verify that count is at least equal to what is defined in API. Call "
472 "returns errno %d:%s",
473 err
, mach_error_string(err
));
476 T_DECL(test_task_basic_info_32
, "tests TASK_BASIC_INFO_32", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
478 test_task_basic_info(INFO_32
);
481 T_DECL(test_task_basic_info_32_2
, "tests TASK_BASIC_INFO_32_2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
483 test_task_basic_info(INFO_32_2
);
486 #if defined(__arm__) || defined(__arm64__)
487 T_DECL(test_task_basic_info_64i_2
, "tests TASK_BASIC_INFO_64_2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
489 test_task_basic_info(INFO_64_2
);
492 T_DECL(test_task_basic_info_64
, "tests TASK_BASIC_INFO_64", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
494 test_task_basic_info(INFO_64
);
496 #endif /* defined(__arm__) || defined(__arm64__) */
498 T_DECL(test_mach_task_basic_info
, "tests MACH_TASK_BASIC_INFO", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
500 test_task_basic_info(INFO_MACH
);
504 test_task_basic_info(enum info_kind kind
)
510 int is_dev
= is_development_kernel();
512 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
515 task_info_t info_data
[2];
516 task_basic_info_32_data_t basic_info_32_data
[2];
517 #if defined(__arm__) || defined(__arm64__)
518 task_basic_info_64_2_data_t basic_info_64_2_data
[2];
520 task_basic_info_64_data_t basic_info_64_data
[2];
521 #endif /* defined(__arm__) || defined(__arm64__) */
522 mach_task_basic_info_data_t mach_basic_info_data
[2];
525 mach_msg_type_number_t count
;
526 task_flavor_t flavor
= 0;
527 integer_t suspend_count
;
528 uint64_t resident_size_diff
;
529 uint64_t virtual_size_diff
;
531 void * tmp_map
= NULL
;
533 mach_port_name_t child_task
;
535 int timeout
= 10; // change to max timeout
541 info_data
[BEFORE
] = (task_info_t
)&basic_info_32_data
[BEFORE
];
542 info_data
[AFTER
] = (task_info_t
)&basic_info_32_data
[AFTER
];
543 count
= TASK_BASIC_INFO_32_COUNT
;
544 flavor
= TASK_BASIC_INFO_32
;
546 if (kind
== INFO_32_2
) {
547 flavor
= TASK_BASIC2_INFO_32
;
551 #if defined(__arm__) || defined(__arm64__)
553 T_ASSERT_FAIL("invalid basic info kind");
557 info_data
[BEFORE
] = (task_info_t
)&basic_info_64_2_data
[BEFORE
];
558 info_data
[AFTER
] = (task_info_t
)&basic_info_64_2_data
[AFTER
];
559 count
= TASK_BASIC_INFO_64_2_COUNT
;
560 flavor
= TASK_BASIC_INFO_64_2
;
565 info_data
[BEFORE
] = (task_info_t
)&basic_info_64_data
[BEFORE
];
566 info_data
[AFTER
] = (task_info_t
)&basic_info_64_data
[AFTER
];
567 count
= TASK_BASIC_INFO_64_COUNT
;
568 flavor
= TASK_BASIC_INFO_64
;
572 T_ASSERT_FAIL("invalid basic info kind");
574 #endif /* defined(__arm__) || defined(__arm64__) */
576 info_data
[BEFORE
] = (task_info_t
)&mach_basic_info_data
[BEFORE
];
577 info_data
[AFTER
] = (task_info_t
)&mach_basic_info_data
[AFTER
];
578 count
= MACH_TASK_BASIC_INFO_COUNT
;
579 flavor
= MACH_TASK_BASIC_INFO
;
583 T_ASSERT_FAIL("invalid basic info kind");
587 kr
= task_info(mach_task_self(), flavor
, info_data
[BEFORE
], &count
);
589 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info succeeded");
594 * Allocate virtual and resident memory.
596 tmp_map
= mmap(0, PAGE_SIZE
, PROT_WRITE
, MAP_ANON
| MAP_PRIVATE
, -1, 0);
599 T_EXPECT_NE(tmp_map
, MAP_FAILED
, "verify mmap call is successful");
601 memset(tmp_map
, 'm', PAGE_SIZE
);
605 T_ASSERT_POSIX_SUCCESS(child_pid
, "verify process can be forked");
607 if (child_pid
== 0) {
609 * This will suspend the child process.
611 kr
= task_suspend(mach_task_self());
616 * Wait for the child process to suspend itself.
620 kr
= task_for_pid(mach_task_self(), child_pid
, &child_task
);
621 T_ASSERT_MACH_SUCCESS(kr
, "verify task_for_pid succeeded. check sudo if failed");
624 * Verify the suspend_count for child and resume it.
627 kr
= task_info(child_task
, flavor
, info_data
[AFTER
], &count
);
628 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
630 suspend_count
= (integer_t
)(info_get(kind
, GET_SUSPEND_COUNT
, info_data
[AFTER
]));
631 T_ASSERT_EQ(suspend_count
, 1, "verify task_info shows correct suspend_count");
633 kr
= task_resume(child_task
);
634 T_ASSERT_MACH_SUCCESS(kr
, "verify task_resume succeeded");
637 * reap kr from task_suspend call in child
639 if (dt_waitpid(child_pid
, &exit_status
, NULL
, timeout
)) {
640 T_ASSERT_MACH_SUCCESS(exit_status
, "verify child task_suspend is successful");
642 T_FAIL("dt_waitpid failed");
645 kr
= task_info(mach_task_self(), flavor
, info_data
[AFTER
], &count
);
646 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
648 resident_size_diff
= info_get(kind
, GET_RESIDENT_SIZE
, info_data
[AFTER
]) - info_get(kind
, GET_RESIDENT_SIZE
, info_data
[BEFORE
]);
649 virtual_size_diff
= info_get(kind
, GET_VIRTUAL_SIZE
, info_data
[AFTER
]) - info_get(kind
, GET_VIRTUAL_SIZE
, info_data
[BEFORE
]);
652 * INFO_32_2 gets the max resident size instead of the current resident size
653 * 32 KB tolerance built into test. The returned value is generally between 0 and 16384
655 * max resident size is a discrete field in INFO_MACH, so it's handled differently
657 if (kind
== INFO_32_2
) {
658 T_EXPECT_EQ(resident_size_diff
% 4096, 0ULL, "verify task_info returns valid max resident_size");
659 T_EXPECT_GE(resident_size_diff
, 0ULL, "verify task_info returns non-negative max resident_size");
660 T_EXPECT_GE(virtual_size_diff
, (unsigned long long)PAGE_SIZE
, "verify task_info returns valid virtual_size");
662 T_EXPECT_GE(resident_size_diff
, (unsigned long long)PAGE_SIZE
, "task_info returns valid resident_size");
663 T_EXPECT_GE(virtual_size_diff
, (unsigned long long)PAGE_SIZE
, "task_info returns valid virtual_size");
666 if (kind
== INFO_MACH
) {
667 resident_size_diff
= info_get(kind
, GET_MAX_RES
, info_data
[AFTER
]) - info_get(kind
, GET_MAX_RES
, info_data
[BEFORE
]);
668 T_EXPECT_EQ(resident_size_diff
% 4096, 0ULL, "verify task_info returns valid max resident_size");
669 T_EXPECT_GE(resident_size_diff
, 0ULL, "verify task_info returns non-negative max resident_size");
670 T_EXPECT_GE(info_get(kind
, GET_MAX_RES
, info_data
[AFTER
]), info_get(kind
, GET_RESIDENT_SIZE
, info_data
[AFTER
]),
671 "verify max resident size is greater than or equal to curr resident size");
677 * These counters give time for threads that have terminated. We dont have any, so checking for zero.
680 time_value_t
* user_tv
= (time_value_t
*)(info_get(kind
, GET_USER_TIME
, info_data
[BEFORE
]));
681 T_EXPECT_EQ((user_tv
->seconds
+ user_tv
->microseconds
/ 1000000), 0, "verify task_info shows valid user time");
683 time_value_t
* sys_tv
= (time_value_t
*)(info_get(kind
, GET_SYS_TIME
, info_data
[BEFORE
]));
684 T_EXPECT_EQ(sys_tv
->seconds
+ (sys_tv
->microseconds
/ 1000000), 0, "verify task_info shows valid system time");
687 * The default value for non-kernel tasks is TIMESHARE.
690 policy_t pt
= (policy_t
)info_get(kind
, GET_POLICY
, info_data
[BEFORE
]);
692 T_EXPECT_EQ(pt
, POLICY_TIMESHARE
, "verify task_info shows valid policy");
695 * This is a negative case.
699 kr
= task_info(mach_task_self(), flavor
, info_data
[AFTER
], &count
);
701 T_ASSERT_MACH_ERROR(kr
, KERN_INVALID_ARGUMENT
,
702 "Negative test case: task_info should verify that count is at least equal to what is defined in API");
707 munmap(tmp_map
, PAGE_SIZE
);
716 info_get(enum info_kind kind
, enum info_get get
, void * data
)
719 case GET_SUSPEND_COUNT
:
723 return (uint64_t)(((task_basic_info_32_t
)data
)->suspend_count
);
724 #if defined(__arm__) || defined(__arm64__)
726 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
730 return (uint64_t)(((task_basic_info_64_2_t
)data
)->suspend_count
);
733 return (uint64_t)(((task_basic_info_64_t
)data
)->suspend_count
);
736 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
738 #endif /* defined(__arm__) || defined(__arm64__) */
740 return (uint64_t)(((mach_task_basic_info_t
)data
)->suspend_count
);
743 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
745 case GET_RESIDENT_SIZE
:
749 return (uint64_t)(((task_basic_info_32_t
)data
)->resident_size
);
750 #if defined(__arm__) || defined(__arm64__)
752 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
756 return (uint64_t)(((task_basic_info_64_2_t
)data
)->resident_size
);
759 return (uint64_t)(((task_basic_info_64_t
)data
)->resident_size
);
762 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
764 #endif /* defined(__arm__) || defined(__arm64__) */
766 return (uint64_t)(((mach_task_basic_info_t
)data
)->resident_size
);
769 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
771 case GET_VIRTUAL_SIZE
:
775 return (uint64_t)(((task_basic_info_32_t
)data
)->virtual_size
);
776 #if defined(__arm__) || defined(__arm64__)
778 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
782 return (uint64_t)(((task_basic_info_64_2_t
)data
)->virtual_size
);
785 return (uint64_t)(((task_basic_info_64_t
)data
)->virtual_size
);
788 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
790 #endif /* defined(__arm__) || defined(__arm64__) */
792 return (uint64_t)(((mach_task_basic_info_t
)data
)->virtual_size
);
796 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
802 return (uint64_t) & (((task_basic_info_32_t
)data
)->user_time
);
803 #if defined(__arm__) || defined(__arm64__)
805 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
809 return (uint64_t) & (((task_basic_info_64_2_t
)data
)->user_time
);
812 return (uint64_t) & (((task_basic_info_64_t
)data
)->user_time
);
815 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
817 #endif /* defined(__arm__) || defined(__arm64__) */
819 return (uint64_t) & (((mach_task_basic_info_t
)data
)->user_time
);
823 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
829 return (uint64_t) & (((task_basic_info_32_t
)data
)->system_time
);
830 #if defined(__arm__) || defined(__arm64__)
832 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
836 return (uint64_t) & (((task_basic_info_64_2_t
)data
)->system_time
);
839 return (uint64_t) & (((task_basic_info_64_t
)data
)->system_time
);
842 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
844 #endif /* defined(__arm__) || defined(__arm64__) */
846 return (uint64_t) & (((mach_task_basic_info_t
)data
)->user_time
);
849 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
855 return (uint64_t)(((task_basic_info_32_t
)data
)->policy
);
856 #if defined(__arm__) || defined(__arm64__)
858 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
862 return (uint64_t)(((task_basic_info_64_2_t
)data
)->policy
);
865 return (uint64_t)(((task_basic_info_64_t
)data
)->policy
);
868 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
870 #endif /* defined(__arm__) || defined(__arm64__) */
872 return (uint64_t)(((mach_task_basic_info_t
)data
)->policy
);
876 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
884 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
886 return (uint64_t)(((mach_task_basic_info_t
)data
)->resident_size_max
);
889 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
893 __builtin_unreachable();
897 * Determines whether we're running on a development kernel
900 is_development_kernel(void)
904 static int is_dev
= NOTSET
;
906 if (is_dev
== NOTSET
) {
908 size_t dev_size
= sizeof(dev
);
911 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.development", &dev
, &dev_size
, NULL
, 0), NULL
);