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>
13 #include <sys/sysctl.h>
16 #include "test_utils.h"
18 T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
20 /* *************************************************************************************
21 * Test the task_info API.
23 * This is a functional test of the following APIs:
27 * TASK_BASIC_INFO_64_2
30 * TASK_AFFINITY_TAG_INFO
31 * TASK_THREAD_TIMES_INFO
32 * TASK_ABSOLUTE_TIME_INFO
33 * <rdar://problem/22242021> Add tests to increase code coverage for the task_info API
34 * *************************************************************************************
36 #define TESTPHYSFOOTPRINTVAL 5
37 #define CANARY 0x0f0f0f0f0f0f0f0fULL
38 #if !defined(CONFIG_EMBEDDED)
39 #define ABSOLUTE_MIN_USER_TIME_DIFF 150
40 #define ABSOLUTE_MIN_SYSTEM_TIME_DIFF 300
43 enum info_kind
{ INFO_32
, INFO_64
, INFO_32_2
, INFO_64_2
, INFO_MACH
, INFO_MAX
};
45 enum info_get
{ GET_SUSPEND_COUNT
, GET_RESIDENT_SIZE
, GET_VIRTUAL_SIZE
, GET_USER_TIME
, GET_SYS_TIME
, GET_POLICY
, GET_MAX_RES
};
48 * This function uses CPU cycles by doing a factorial computation.
50 static void do_factorial_task(void);
52 void test_task_basic_info_32(void);
53 void test_task_basic_info_64(void);
54 void task_basic_info_32_debug(void);
55 void task_basic2_info_32_warmup(void);
56 void test_task_basic_info(enum info_kind kind
);
57 uint64_t info_get(enum info_kind kind
, enum info_get get
, void * data
);
59 T_DECL(task_vm_info
, "tests task vm info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
62 task_vm_info_data_t vm_info
;
64 mach_msg_type_number_t count
= TASK_VM_INFO_COUNT
;
66 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
68 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
70 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info return value !=0 for virtual_size\n");
72 T_EXPECT_NE(vm_info
.phys_footprint
, 0ULL, "task_info return value !=0 for phys_footprint\n");
75 * Test the REV0 version of TASK_VM_INFO. It should not change the value of phys_footprint.
78 count
= TASK_VM_INFO_REV0_COUNT
;
79 vm_info
.phys_footprint
= TESTPHYSFOOTPRINTVAL
;
80 vm_info
.min_address
= CANARY
;
81 vm_info
.max_address
= CANARY
;
83 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
85 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
87 T_EXPECT_EQ(count
, TASK_VM_INFO_REV0_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV0_COUNT", count
);
89 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev0 call does not return 0 for virtual_size");
91 T_EXPECT_EQ(vm_info
.phys_footprint
, (unsigned long long)TESTPHYSFOOTPRINTVAL
,
92 "task_info --rev0 call returned value %llu for vm_info.phys_footprint. Expected %u since this value should not be "
94 vm_info
.phys_footprint
, TESTPHYSFOOTPRINTVAL
);
96 T_EXPECT_EQ(vm_info
.min_address
, CANARY
,
97 "task_info --rev0 call returned value 0x%llx for vm_info.min_address. Expected 0x%llx since this value should not "
98 "be modified by rev0",
99 vm_info
.min_address
, CANARY
);
101 T_EXPECT_EQ(vm_info
.max_address
, CANARY
,
102 "task_info --rev0 call returned value 0x%llx for vm_info.max_address. Expected 0x%llx since this value should not "
103 "be modified by rev0",
104 vm_info
.max_address
, CANARY
);
107 * Test the REV1 version of TASK_VM_INFO.
110 count
= TASK_VM_INFO_REV1_COUNT
;
111 vm_info
.phys_footprint
= TESTPHYSFOOTPRINTVAL
;
112 vm_info
.min_address
= CANARY
;
113 vm_info
.max_address
= CANARY
;
115 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
117 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
119 T_EXPECT_EQ(count
, TASK_VM_INFO_REV1_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV1_COUNT", count
);
121 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev1 call does not return 0 for virtual_size");
123 T_EXPECT_NE(vm_info
.phys_footprint
, (unsigned long long)TESTPHYSFOOTPRINTVAL
,
124 "task_info --rev1 call returned value %llu for vm_info.phys_footprint. Expected value is anything other than %u "
125 "since this value should not be modified by rev1",
126 vm_info
.phys_footprint
, TESTPHYSFOOTPRINTVAL
);
128 T_EXPECT_EQ(vm_info
.min_address
, CANARY
,
129 "task_info --rev1 call returned value 0x%llx for vm_info.min_address. Expected 0x%llx since this value should not "
130 "be modified by rev1",
131 vm_info
.min_address
, CANARY
);
133 T_EXPECT_EQ(vm_info
.max_address
, CANARY
,
134 "task_info --rev1 call returned value 0x%llx for vm_info.max_address. Expected 0x%llx since this value should not "
135 "be modified by rev1",
136 vm_info
.max_address
, CANARY
);
139 * Test the REV2 version of TASK_VM_INFO.
142 count
= TASK_VM_INFO_REV2_COUNT
;
143 vm_info
.phys_footprint
= TESTPHYSFOOTPRINTVAL
;
144 vm_info
.min_address
= CANARY
;
145 vm_info
.max_address
= CANARY
;
147 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
149 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
151 T_EXPECT_EQ(count
, TASK_VM_INFO_REV2_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV2_COUNT\n", count
);
153 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev2 call does not return 0 for virtual_size\n");
155 T_EXPECT_NE(vm_info
.phys_footprint
, (unsigned long long)TESTPHYSFOOTPRINTVAL
,
156 "task_info --rev2 call returned value %llu for vm_info.phys_footprint. Expected anything other than %u since this "
157 "value should be modified by rev2",
158 vm_info
.phys_footprint
, TESTPHYSFOOTPRINTVAL
);
160 T_EXPECT_NE(vm_info
.min_address
, CANARY
,
161 "task_info --rev2 call returned value 0x%llx for vm_info.min_address. Expected anything other than 0x%llx since "
162 "this value should be modified by rev2",
163 vm_info
.min_address
, CANARY
);
165 T_EXPECT_NE(vm_info
.max_address
, CANARY
,
166 "task_info --rev2 call returned value 0x%llx for vm_info.max_address. Expected anything other than 0x%llx since "
167 "this value should be modified by rev2",
168 vm_info
.max_address
, CANARY
);
171 * Test the REV4 version of TASK_VM_INFO.
174 count
= TASK_VM_INFO_REV4_COUNT
;
175 vm_info
.phys_footprint
= TESTPHYSFOOTPRINTVAL
;
176 vm_info
.min_address
= CANARY
;
177 vm_info
.max_address
= CANARY
;
178 vm_info
.limit_bytes_remaining
= CANARY
;
180 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
182 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
184 T_EXPECT_EQ(count
, TASK_VM_INFO_REV4_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV4_COUNT\n", count
);
186 T_EXPECT_NE(vm_info
.phys_footprint
, (unsigned long long)TESTPHYSFOOTPRINTVAL
,
187 "task_info --rev4 call returned value %llu for vm_info.phys_footprint. Expected anything other than %u since this "
188 "value should be modified by rev4",
189 vm_info
.phys_footprint
, TESTPHYSFOOTPRINTVAL
);
191 T_EXPECT_NE(vm_info
.min_address
, CANARY
,
192 "task_info --rev4 call returned value 0x%llx for vm_info.min_address. Expected anything other than 0x%llx since "
193 "this value should be modified by rev4",
194 vm_info
.min_address
, CANARY
);
196 T_EXPECT_NE(vm_info
.max_address
, CANARY
,
197 "task_info --rev4 call returned value 0x%llx for vm_info.max_address. Expected anything other than 0x%llx since "
198 "this value should be modified by rev4",
199 vm_info
.max_address
, CANARY
);
201 T_EXPECT_NE(vm_info
.limit_bytes_remaining
, CANARY
,
202 "task_info --rev4 call returned value 0x%llx for vm_info.limit_bytes_remaining. Expected anything other than 0x%llx since "
203 "this value should be modified by rev4",
204 vm_info
.limit_bytes_remaining
, CANARY
);
207 T_DECL(host_debug_info
, "tests host debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
210 int is_dev
= is_development_kernel();
212 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
217 host_debug_info_internal_data_t debug_info
;
218 mach_msg_type_number_t count
= HOST_DEBUG_INFO_INTERNAL_COUNT
;
219 host
= mach_host_self();
220 err
= host_info(host
, HOST_DEBUG_INFO_INTERNAL
, (host_info_t
)&debug_info
, &count
);
222 T_ASSERT_MACH_SUCCESS(err
, "verify host_info call succeeded");
225 T_DECL(task_debug_info
, "tests task debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
228 int is_dev
= is_development_kernel();
230 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
234 task_debug_info_internal_data_t debug_info
;
236 mach_msg_type_number_t count
= TASK_DEBUG_INFO_INTERNAL_COUNT
;
238 err
= task_info(mach_task_self(), TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &count
);
240 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
243 T_DECL(thread_debug_info
, "tests thread debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
246 int is_dev
= is_development_kernel();
248 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
252 thread_debug_info_internal_data_t debug_info
;
254 mach_msg_type_number_t count
= THREAD_DEBUG_INFO_INTERNAL_COUNT
;
256 err
= thread_info(mach_thread_self(), THREAD_DEBUG_INFO_INTERNAL
, (thread_info_t
)&debug_info
, &count
);
258 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
267 for (i
= 1; i
<= number
; i
++) {
274 T_DECL(task_thread_times_info
, "tests task thread times info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
277 int is_dev
= is_development_kernel();
279 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
283 task_thread_times_info_data_t thread_times_info_data
;
284 task_thread_times_info_data_t thread_times_info_data_new
;
285 mach_msg_type_number_t count
= TASK_THREAD_TIMES_INFO_COUNT
;
287 err
= task_info(mach_task_self(), TASK_THREAD_TIMES_INFO
, (task_info_t
)&thread_times_info_data
, &count
);
289 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
293 err
= task_info(mach_task_self(), TASK_THREAD_TIMES_INFO
, (task_info_t
)&thread_times_info_data_new
, &count
);
295 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
298 * The difference is observed to be less than 30 microseconds for user_time
299 * and less than 50 microseconds for system_time. This observation was done for over
303 T_EXPECT_FALSE((thread_times_info_data_new
.user_time
.seconds
- thread_times_info_data
.user_time
.seconds
) != 0 ||
304 (thread_times_info_data_new
.system_time
.seconds
- thread_times_info_data
.system_time
.seconds
) != 0,
305 "Tests whether the difference between thread times is greater than the allowed limit");
308 * This is a negative case.
312 err
= task_info(mach_task_self(), TASK_THREAD_TIMES_INFO
, (task_info_t
)&thread_times_info_data
, &count
);
313 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
314 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
317 T_DECL(task_absolutetime_info
, "tests task absolute time info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
320 int is_dev
= is_development_kernel();
322 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
326 uint64_t user_time_diff
, system_time_diff
;
327 task_absolutetime_info_data_t absolute_time_info_data
;
328 task_absolutetime_info_data_t absolute_time_info_data_new
;
329 mach_msg_type_number_t count
= TASK_ABSOLUTETIME_INFO_COUNT
;
331 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data
, &count
);
333 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
337 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data_new
, &count
);
339 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
341 user_time_diff
= absolute_time_info_data_new
.total_user
- absolute_time_info_data
.total_user
;
342 system_time_diff
= absolute_time_info_data_new
.total_system
- absolute_time_info_data
.total_system
;
344 #if !(defined(__arm__) || defined(__arm64__))
346 * On embedded devices the difference is always zero.
347 * On non-embedded devices the difference occurs in this range. This was observed over ~10000 runs.
350 T_EXPECT_FALSE(user_time_diff
< ABSOLUTE_MIN_USER_TIME_DIFF
|| system_time_diff
< ABSOLUTE_MIN_SYSTEM_TIME_DIFF
,
351 "Tests whether the difference between thread times is greater than the expected range");
354 if (absolute_time_info_data
.threads_user
<= 0) {
355 int precise_time_val
= 0;
356 size_t len
= sizeof(size_t);
358 T_LOG("User threads time is zero. This should only happen rarely and when precise_user_time is off");
360 err
= sysctlbyname("kern.precise_user_kernel_time", &precise_time_val
, &len
, NULL
, 0);
362 T_EXPECT_POSIX_SUCCESS(err
, "performing sysctl to check precise_user_time");
364 T_LOG("kern.precise_user_kernel_time val = %d", precise_time_val
);
366 T_EXPECT_FALSE(precise_time_val
, "user thread time should only be zero when precise_user_kernel_time is disabled");
368 T_PASS("task_info should return non-zero value for user threads time = %llu", absolute_time_info_data
.threads_user
);
371 #if !(defined(__arm__) || defined(__arm64__))
373 * On iOS, system threads are always zero. On OS X this value can be some large positive number.
374 * There is no real way to estimate the exact amount.
376 T_EXPECT_NE(absolute_time_info_data
.threads_system
, 0ULL,
377 "task_info should return non-zero value for system threads time = %llu", absolute_time_info_data
.threads_system
);
381 * This is a negative case.
384 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data_new
, &count
);
385 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
386 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
389 T_DECL(task_affinity_tag_info
, "tests task_affinity_tag_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
392 int is_dev
= is_development_kernel();
394 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
398 task_affinity_tag_info_data_t affinity_tag_info_data
;
399 mach_msg_type_number_t count
= TASK_AFFINITY_TAG_INFO_COUNT
;
401 err
= task_info(mach_task_self(), TASK_AFFINITY_TAG_INFO
, (task_info_t
)&affinity_tag_info_data
, &count
);
403 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
406 * The affinity is not set by default, hence expecting a zero value.
408 T_ASSERT_FALSE(affinity_tag_info_data
.min
!= 0 || affinity_tag_info_data
.max
!= 0,
409 "task_info call returns non-zero min or max value");
412 * This is a negative case.
415 err
= task_info(mach_task_self(), TASK_AFFINITY_TAG_INFO
, (task_info_t
)&affinity_tag_info_data
, &count
);
416 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
417 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
420 T_DECL(task_flags_info
, "tests task_flags_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
423 int is_dev
= is_development_kernel();
425 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
429 task_flags_info_data_t flags_info_data
;
430 mach_msg_type_number_t count
= TASK_FLAGS_INFO_COUNT
;
432 err
= task_info(mach_task_self(), TASK_FLAGS_INFO
, (task_info_t
)&flags_info_data
, &count
);
434 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
436 /* Change for 32-bit arch possibility?*/
437 T_ASSERT_EQ((flags_info_data
.flags
& (unsigned int)(~(TF_LP64
| TF_64B_DATA
))), 0U,
438 "task_info should only give out 64-bit addr/data flags");
441 * This is a negative case.
445 err
= task_info(mach_task_self(), TASK_FLAGS_INFO
, (task_info_t
)&flags_info_data
, &count
);
446 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
447 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
450 T_DECL(task_power_info_v2
, "tests task_power_info_v2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
453 int is_dev
= is_development_kernel();
455 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
459 task_power_info_v2_data_t power_info_data_v2
;
460 task_power_info_v2_data_t power_info_data_v2_new
;
461 mach_msg_type_number_t count
= TASK_POWER_INFO_V2_COUNT
;
465 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
467 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
469 T_ASSERT_LE(power_info_data_v2
.gpu_energy
.task_gpu_utilisation
, 0ULL,
470 "verified task_info call shows zero GPU utilization for non-GPU task");
475 * Verify the cpu_energy parameters.
477 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2_new
, &count
);
478 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
480 #if !(defined(__arm__) || defined(__arm64__))
482 * iOS does not have system_time.
484 T_ASSERT_GT(power_info_data_v2_new
.cpu_energy
.total_user
, power_info_data_v2
.cpu_energy
.total_user
,
485 "task_info call returns valid user time");
486 T_ASSERT_GT(power_info_data_v2_new
.cpu_energy
.total_system
, power_info_data_v2
.cpu_energy
.total_system
,
487 "task_info call returns valid system time");
490 T_ASSERT_GE(power_info_data_v2
.cpu_energy
.task_interrupt_wakeups
, 1ULL,
491 "verify task_info call returns non-zero value for interrupt_wakeup (ret value = %llu)",
492 power_info_data_v2
.cpu_energy
.task_interrupt_wakeups
);
494 #if !(defined(__arm__) || defined(__arm64__))
495 if (power_info_data_v2
.cpu_energy
.task_platform_idle_wakeups
!= 0) {
496 T_LOG("task_info call returned %llu for platform_idle_wakeup", power_info_data_v2
.cpu_energy
.task_platform_idle_wakeups
);
500 count
= TASK_POWER_INFO_V2_COUNT_OLD
;
501 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
503 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
506 * This is a negative case.
509 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
511 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
512 "Negative test case: task_info should verify that count is at least equal to what is defined in API. Call "
513 "returns errno %d:%s",
514 err
, mach_error_string(err
));
517 T_DECL(test_task_basic_info_32
, "tests TASK_BASIC_INFO_32", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
519 test_task_basic_info(INFO_32
);
522 T_DECL(test_task_basic_info_32_2
, "tests TASK_BASIC_INFO_32_2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
524 test_task_basic_info(INFO_32_2
);
527 #if defined(__arm__) || defined(__arm64__)
528 T_DECL(test_task_basic_info_64i_2
, "tests TASK_BASIC_INFO_64_2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
530 test_task_basic_info(INFO_64_2
);
533 T_DECL(test_task_basic_info_64
, "tests TASK_BASIC_INFO_64", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
535 test_task_basic_info(INFO_64
);
537 #endif /* defined(__arm__) || defined(__arm64__) */
539 T_DECL(test_mach_task_basic_info
, "tests MACH_TASK_BASIC_INFO", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
541 test_task_basic_info(INFO_MACH
);
545 test_task_basic_info(enum info_kind kind
)
551 int is_dev
= is_development_kernel();
553 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
556 task_info_t info_data
[2];
557 task_basic_info_32_data_t basic_info_32_data
[2];
558 #if defined(__arm__) || defined(__arm64__)
559 task_basic_info_64_2_data_t basic_info_64_2_data
[2];
561 task_basic_info_64_data_t basic_info_64_data
[2];
562 #endif /* defined(__arm__) || defined(__arm64__) */
563 mach_task_basic_info_data_t mach_basic_info_data
[2];
566 mach_msg_type_number_t count
;
567 task_flavor_t flavor
= 0;
568 integer_t suspend_count
;
569 uint64_t resident_size_diff
;
570 uint64_t virtual_size_diff
;
572 void * tmp_map
= NULL
;
574 mach_port_name_t child_task
;
576 int timeout
= 10; // change to max timeout
582 info_data
[BEFORE
] = (task_info_t
)&basic_info_32_data
[BEFORE
];
583 info_data
[AFTER
] = (task_info_t
)&basic_info_32_data
[AFTER
];
584 count
= TASK_BASIC_INFO_32_COUNT
;
585 flavor
= TASK_BASIC_INFO_32
;
587 if (kind
== INFO_32_2
) {
588 flavor
= TASK_BASIC2_INFO_32
;
592 #if defined(__arm__) || defined(__arm64__)
594 T_ASSERT_FAIL("invalid basic info kind");
598 info_data
[BEFORE
] = (task_info_t
)&basic_info_64_2_data
[BEFORE
];
599 info_data
[AFTER
] = (task_info_t
)&basic_info_64_2_data
[AFTER
];
600 count
= TASK_BASIC_INFO_64_2_COUNT
;
601 flavor
= TASK_BASIC_INFO_64_2
;
606 info_data
[BEFORE
] = (task_info_t
)&basic_info_64_data
[BEFORE
];
607 info_data
[AFTER
] = (task_info_t
)&basic_info_64_data
[AFTER
];
608 count
= TASK_BASIC_INFO_64_COUNT
;
609 flavor
= TASK_BASIC_INFO_64
;
613 T_ASSERT_FAIL("invalid basic info kind");
615 #endif /* defined(__arm__) || defined(__arm64__) */
617 info_data
[BEFORE
] = (task_info_t
)&mach_basic_info_data
[BEFORE
];
618 info_data
[AFTER
] = (task_info_t
)&mach_basic_info_data
[AFTER
];
619 count
= MACH_TASK_BASIC_INFO_COUNT
;
620 flavor
= MACH_TASK_BASIC_INFO
;
624 T_ASSERT_FAIL("invalid basic info kind");
628 kr
= task_info(mach_task_self(), flavor
, info_data
[BEFORE
], &count
);
630 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info succeeded");
635 * Allocate virtual and resident memory.
637 tmp_map
= mmap(0, PAGE_SIZE
, PROT_WRITE
, MAP_ANON
| MAP_PRIVATE
, -1, 0);
640 T_EXPECT_NE(tmp_map
, MAP_FAILED
, "verify mmap call is successful");
642 memset(tmp_map
, 'm', PAGE_SIZE
);
646 T_ASSERT_POSIX_SUCCESS(child_pid
, "verify process can be forked");
648 if (child_pid
== 0) {
650 * This will suspend the child process.
652 kr
= task_suspend(mach_task_self());
657 * Wait for the child process to suspend itself.
661 kr
= task_for_pid(mach_task_self(), child_pid
, &child_task
);
662 T_ASSERT_MACH_SUCCESS(kr
, "verify task_for_pid succeeded. check sudo if failed");
665 * Verify the suspend_count for child and resume it.
668 kr
= task_info(child_task
, flavor
, info_data
[AFTER
], &count
);
669 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
671 suspend_count
= (integer_t
)(info_get(kind
, GET_SUSPEND_COUNT
, info_data
[AFTER
]));
672 T_ASSERT_EQ(suspend_count
, 1, "verify task_info shows correct suspend_count");
674 kr
= task_resume(child_task
);
675 T_ASSERT_MACH_SUCCESS(kr
, "verify task_resume succeeded");
678 * reap kr from task_suspend call in child
680 if (dt_waitpid(child_pid
, &exit_status
, NULL
, timeout
)) {
681 T_ASSERT_MACH_SUCCESS(exit_status
, "verify child task_suspend is successful");
683 T_FAIL("dt_waitpid failed");
686 kr
= task_info(mach_task_self(), flavor
, info_data
[AFTER
], &count
);
687 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
689 resident_size_diff
= info_get(kind
, GET_RESIDENT_SIZE
, info_data
[AFTER
]) - info_get(kind
, GET_RESIDENT_SIZE
, info_data
[BEFORE
]);
690 virtual_size_diff
= info_get(kind
, GET_VIRTUAL_SIZE
, info_data
[AFTER
]) - info_get(kind
, GET_VIRTUAL_SIZE
, info_data
[BEFORE
]);
693 * INFO_32_2 gets the max resident size instead of the current resident size
694 * 32 KB tolerance built into test. The returned value is generally between 0 and 16384
696 * max resident size is a discrete field in INFO_MACH, so it's handled differently
698 if (kind
== INFO_32_2
) {
699 T_EXPECT_EQ(resident_size_diff
% 4096, 0ULL, "verify task_info returns valid max resident_size");
700 T_EXPECT_GE(resident_size_diff
, 0ULL, "verify task_info returns non-negative max resident_size");
701 T_EXPECT_GE(virtual_size_diff
, (unsigned long long)PAGE_SIZE
, "verify task_info returns valid virtual_size");
703 T_EXPECT_GE(resident_size_diff
, (unsigned long long)PAGE_SIZE
, "task_info returns valid resident_size");
704 T_EXPECT_GE(virtual_size_diff
, (unsigned long long)PAGE_SIZE
, "task_info returns valid virtual_size");
707 if (kind
== INFO_MACH
) {
708 resident_size_diff
= info_get(kind
, GET_MAX_RES
, info_data
[AFTER
]) - info_get(kind
, GET_MAX_RES
, info_data
[BEFORE
]);
709 T_EXPECT_EQ(resident_size_diff
% 4096, 0ULL, "verify task_info returns valid max resident_size");
710 T_EXPECT_GE(resident_size_diff
, 0ULL, "verify task_info returns non-negative max resident_size");
711 T_EXPECT_GE(info_get(kind
, GET_MAX_RES
, info_data
[AFTER
]), info_get(kind
, GET_RESIDENT_SIZE
, info_data
[AFTER
]),
712 "verify max resident size is greater than or equal to curr resident size");
718 * These counters give time for threads that have terminated. We dont have any, so checking for zero.
721 time_value_t
* user_tv
= (time_value_t
*)(info_get(kind
, GET_USER_TIME
, info_data
[BEFORE
]));
722 T_EXPECT_EQ((user_tv
->seconds
+ user_tv
->microseconds
/ 1000000), 0, "verify task_info shows valid user time");
724 time_value_t
* sys_tv
= (time_value_t
*)(info_get(kind
, GET_SYS_TIME
, info_data
[BEFORE
]));
725 T_EXPECT_EQ(sys_tv
->seconds
+ (sys_tv
->microseconds
/ 1000000), 0, "verify task_info shows valid system time");
728 * The default value for non-kernel tasks is TIMESHARE.
731 policy_t pt
= (policy_t
)info_get(kind
, GET_POLICY
, info_data
[BEFORE
]);
733 T_EXPECT_EQ(pt
, POLICY_TIMESHARE
, "verify task_info shows valid policy");
736 * This is a negative case.
740 kr
= task_info(mach_task_self(), flavor
, info_data
[AFTER
], &count
);
742 T_ASSERT_MACH_ERROR(kr
, KERN_INVALID_ARGUMENT
,
743 "Negative test case: task_info should verify that count is at least equal to what is defined in API");
748 munmap(tmp_map
, PAGE_SIZE
);
756 T_DECL(test_sigcont_task_suspend_resume
,
757 "test to verify that SIGCONT on task_suspend()-ed process works",
759 T_META_LTEPHASE(LTE_POSTINIT
))
762 int is_dev
= is_development_kernel();
764 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
767 mach_task_basic_info_data_t mach_basic_info_data
;
768 task_info_t info_data
= (task_info_t
)&mach_basic_info_data
;
770 task_debug_info_internal_data_t debug_info
;
771 mach_msg_type_number_t debug_count
= TASK_DEBUG_INFO_INTERNAL_COUNT
;
775 mach_msg_type_number_t count
= MACH_TASK_BASIC_INFO_COUNT
;
776 task_flavor_t flavor
= MACH_TASK_BASIC_INFO
;
777 integer_t suspend_count
;
778 integer_t debug_suspend_count
;
780 mach_port_name_t child_task
;
788 T_ASSERT_POSIX_SUCCESS(child_pid
, "verify process can be forked");
790 if (child_pid
== 0) {
792 * This will suspend the child process.
794 kr
= task_suspend(mach_task_self());
797 * When child resumes, it exits immediately
804 * Wait for the child process to suspend itself.
808 kr
= task_for_pid(mach_task_self(), child_pid
, &child_task
);
809 T_ASSERT_MACH_SUCCESS(kr
, "verify task_for_pid succeeded. check sudo if failed");
812 * Verify the suspend_count for child and resume it.
815 kr
= task_info(child_task
, flavor
, info_data
, &count
);
816 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
818 suspend_count
= (integer_t
)(info_get(INFO_MACH
, GET_SUSPEND_COUNT
, info_data
));
819 T_ASSERT_EQ(suspend_count
, 1, "verify task_info shows correct suspend_count (1) (actually user stop count) ");
821 kr
= task_info(child_task
, TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &debug_count
);
822 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
824 debug_suspend_count
= debug_info
.suspend_count
;
825 T_ASSERT_EQ(debug_info
.suspend_count
, 1, "verify debug_info shows correct suspend_count(1)");
827 posix_ret
= kill(child_pid
, SIGCONT
);
828 T_ASSERT_POSIX_SUCCESS(posix_ret
, "verify signal call succeeded");
831 * reap kr from task_suspend call in child
833 dt_waitpid(child_pid
, &exit_status
, &signal_no
, timeout
);
835 T_ASSERT_EQ(signal_no
, 0, "child should be resumed and exit without signal");
836 T_ASSERT_EQ(exit_status
, 0, "child should exit with 0");
839 T_DECL(test_sigcont_task_suspend2_resume
,
840 "test to verify that SIGCONT on task_suspend2()-ed process doesn't work",
842 T_META_LTEPHASE(LTE_POSTINIT
))
845 int is_dev
= is_development_kernel();
847 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
850 mach_task_basic_info_data_t mach_basic_info_data
;
851 task_info_t info_data
= (task_info_t
)&mach_basic_info_data
;
853 task_debug_info_internal_data_t debug_info
;
854 mach_msg_type_number_t debug_count
= TASK_DEBUG_INFO_INTERNAL_COUNT
;
858 mach_msg_type_number_t count
= MACH_TASK_BASIC_INFO_COUNT
;
859 task_flavor_t flavor
= MACH_TASK_BASIC_INFO
;
860 integer_t suspend_count
= 0;
861 integer_t debug_suspend_count
= 0;
863 mach_port_name_t child_task
;
864 task_suspension_token_t child_token
= 0xFFFFF;
868 * We expect the test to fail right now, so I've set timeout to
869 * be shorter than we may want it to be when the issue is fixed
882 T_ASSERT_POSIX_SUCCESS(child_pid
, "verify process can be forked %d", child_pid
);
884 if (child_pid
== 0) {
886 T_LOG("Waiting to read from parent...");
887 read(fd
[0], &pipe_msg
, sizeof(pipe_msg
));
888 T_LOG("Done reading from parent, about to exit...");
892 * Wait for child to fork and block on read
898 kr
= task_for_pid(mach_task_self(), child_pid
, &child_task
);
899 T_ASSERT_MACH_SUCCESS(kr
, "verify task_for_pid succeeded. check sudo if failed");
901 kr
= task_info(child_task
, TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &debug_count
);
902 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
904 debug_suspend_count
= debug_info
.suspend_count
;
905 T_EXPECT_EQ(debug_suspend_count
, 0, "verify debug_info shows correct (true) suspend_count(0)");
907 kr
= task_suspend2(child_task
, &child_token
);
908 T_ASSERT_MACH_SUCCESS(kr
, "verify task_suspend2 call succeeded");
910 kr
= task_info(child_task
, TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &debug_count
);
911 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
913 debug_suspend_count
= debug_info
.suspend_count
;
914 T_ASSERT_EQ(debug_suspend_count
, 1, "verify debug_info shows correct (true) suspend_count(1)");
917 * Verify the suspend_count for child and resume it.
920 kr
= task_info(child_task
, flavor
, info_data
, &count
);
921 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
923 suspend_count
= (integer_t
)(info_get(INFO_MACH
, GET_SUSPEND_COUNT
, info_data
));
924 T_EXPECT_EQ(suspend_count
, 1, "verify task_info shows correct (user_stop_count) suspend_count (1)");
926 posix_ret
= kill(child_pid
, SIGCONT
);
927 T_ASSERT_POSIX_SUCCESS(posix_ret
, "verify signal call succeeded");
929 kr
= task_info(child_task
, TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &debug_count
);
930 T_EXPECT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
932 debug_suspend_count
= debug_info
.suspend_count
;
933 T_EXPECTFAIL_WITH_RADAR(33166654);
934 T_EXPECT_EQ(debug_suspend_count
, 1, "verify debug_info shows correct (true) suspend_count (1)");
936 suspend_count
= (integer_t
)(info_get(INFO_MACH
, GET_SUSPEND_COUNT
, info_data
));
937 T_ASSERT_EQ(suspend_count
, 1, "verify task_info shows correct (user_stop_count) suspend_count (1) after SIG_CONT");
939 kr
= task_resume(child_task
);
940 T_EXPECTFAIL_WITH_RADAR(33166654);
941 T_EXPECT_MACH_SUCCESS(kr
, "verify task_resume succeeded");
944 * reap kr from task_suspend call in child
947 dt_waitpid(child_pid
, &exit_status
, &signal_no
, timeout
);
949 T_ASSERT_EQ(signal_no
, SIG_DT_TIMEOUT
, "dt_waitpid timed out as expected");
951 // Resume properly using token and then wait
953 kr
= task_resume2(child_token
);
954 T_EXPECTFAIL_WITH_RADAR(33166654);
955 T_ASSERT_MACH_SUCCESS(kr
, "verify task_resume2 succeeded");
957 write(fd
[1], &pipe_msg
, sizeof(pipe_msg
));
960 * reap kr from task_suspend call in child
962 dt_waitpid(child_pid
, &exit_status
, &signal_no
, timeout
);
964 T_ASSERT_EQ(signal_no
, 0, "child should be resumed and no signal should be returned");
965 T_ASSERT_EQ(exit_status
, 0, "child should exit with 0");
969 info_get(enum info_kind kind
, enum info_get get
, void * data
)
972 case GET_SUSPEND_COUNT
:
976 return (uint64_t)(((task_basic_info_32_t
)data
)->suspend_count
);
977 #if defined(__arm__) || defined(__arm64__)
979 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
983 return (uint64_t)(((task_basic_info_64_2_t
)data
)->suspend_count
);
986 return (uint64_t)(((task_basic_info_64_t
)data
)->suspend_count
);
989 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
991 #endif /* defined(__arm__) || defined(__arm64__) */
993 return (uint64_t)(((mach_task_basic_info_t
)data
)->suspend_count
);
996 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
998 case GET_RESIDENT_SIZE
:
1002 return (uint64_t)(((task_basic_info_32_t
)data
)->resident_size
);
1003 #if defined(__arm__) || defined(__arm64__)
1005 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1009 return (uint64_t)(((task_basic_info_64_2_t
)data
)->resident_size
);
1012 return (uint64_t)(((task_basic_info_64_t
)data
)->resident_size
);
1015 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1017 #endif /* defined(__arm__) || defined(__arm64__) */
1019 return (uint64_t)(((mach_task_basic_info_t
)data
)->resident_size
);
1022 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1024 case GET_VIRTUAL_SIZE
:
1028 return (uint64_t)(((task_basic_info_32_t
)data
)->virtual_size
);
1029 #if defined(__arm__) || defined(__arm64__)
1031 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1035 return (uint64_t)(((task_basic_info_64_2_t
)data
)->virtual_size
);
1038 return (uint64_t)(((task_basic_info_64_t
)data
)->virtual_size
);
1041 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1043 #endif /* defined(__arm__) || defined(__arm64__) */
1045 return (uint64_t)(((mach_task_basic_info_t
)data
)->virtual_size
);
1049 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1055 return (uint64_t) &(((task_basic_info_32_t
)data
)->user_time
);
1056 #if defined(__arm__) || defined(__arm64__)
1058 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1062 return (uint64_t) &(((task_basic_info_64_2_t
)data
)->user_time
);
1065 return (uint64_t) &(((task_basic_info_64_t
)data
)->user_time
);
1068 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1070 #endif /* defined(__arm__) || defined(__arm64__) */
1072 return (uint64_t) &(((mach_task_basic_info_t
)data
)->user_time
);
1076 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1082 return (uint64_t) &(((task_basic_info_32_t
)data
)->system_time
);
1083 #if defined(__arm__) || defined(__arm64__)
1085 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1089 return (uint64_t) &(((task_basic_info_64_2_t
)data
)->system_time
);
1092 return (uint64_t) &(((task_basic_info_64_t
)data
)->system_time
);
1095 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1097 #endif /* defined(__arm__) || defined(__arm64__) */
1099 return (uint64_t) &(((mach_task_basic_info_t
)data
)->user_time
);
1102 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1108 return (uint64_t)(((task_basic_info_32_t
)data
)->policy
);
1109 #if defined(__arm__) || defined(__arm64__)
1111 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1115 return (uint64_t)(((task_basic_info_64_2_t
)data
)->policy
);
1118 return (uint64_t)(((task_basic_info_64_t
)data
)->policy
);
1121 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1123 #endif /* defined(__arm__) || defined(__arm64__) */
1125 return (uint64_t)(((mach_task_basic_info_t
)data
)->policy
);
1129 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1137 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1139 return (uint64_t)(((mach_task_basic_info_t
)data
)->resident_size_max
);
1142 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1146 __builtin_unreachable();