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 T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
18 /* *************************************************************************************
19 * Test the task_info API.
21 * This is a functional test of the following APIs:
25 * TASK_BASIC_INFO_64_2
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 * *************************************************************************************
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
41 enum info_kind
{ INFO_32
, INFO_64
, INFO_32_2
, INFO_64_2
, INFO_MACH
, INFO_MAX
};
43 enum info_get
{ GET_SUSPEND_COUNT
, GET_RESIDENT_SIZE
, GET_VIRTUAL_SIZE
, GET_USER_TIME
, GET_SYS_TIME
, GET_POLICY
, GET_MAX_RES
};
46 * This function uses CPU cycles by doing a factorial computation.
48 static void do_factorial_task(void);
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
);
58 T_DECL(task_vm_info
, "tests task vm info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
61 task_vm_info_data_t vm_info
;
63 mach_msg_type_number_t count
= TASK_VM_INFO_COUNT
;
65 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
67 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
69 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info return value !=0 for virtual_size\n");
71 T_EXPECT_NE(vm_info
.phys_footprint
, 0ULL, "task_info return value !=0 for phys_footprint\n");
74 * Test the REV0 version of TASK_VM_INFO. It should not change the value of phys_footprint.
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
;
82 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
84 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
86 T_EXPECT_EQ(count
, TASK_VM_INFO_REV0_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV0_COUNT", count
);
88 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev0 call does not return 0 for virtual_size");
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 "
93 vm_info
.phys_footprint
, TESTPHYSFOOTPRINTVAL
);
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
);
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
);
106 * Test the REV1 version of TASK_VM_INFO.
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
;
114 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
116 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
118 T_EXPECT_EQ(count
, TASK_VM_INFO_REV1_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV1_COUNT", count
);
120 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev1 call does not return 0 for virtual_size");
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
);
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
);
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
);
138 * Test the REV2 version of TASK_VM_INFO.
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
;
146 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
148 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
150 T_EXPECT_EQ(count
, TASK_VM_INFO_REV2_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV2_COUNT\n", count
);
152 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev2 call does not return 0 for virtual_size\n");
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
);
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
);
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
);
170 * Test the REV4 version of TASK_VM_INFO.
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
;
179 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
181 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
183 T_EXPECT_EQ(count
, TASK_VM_INFO_REV4_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV4_COUNT\n", count
);
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
);
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
);
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
);
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
);
206 T_DECL(host_debug_info
, "tests host debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
209 int is_dev
= is_development_kernel();
211 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
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
);
221 T_ASSERT_MACH_SUCCESS(err
, "verify host_info call succeeded");
224 T_DECL(task_debug_info
, "tests task debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
227 int is_dev
= is_development_kernel();
229 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
233 task_debug_info_internal_data_t debug_info
;
235 mach_msg_type_number_t count
= TASK_DEBUG_INFO_INTERNAL_COUNT
;
237 err
= task_info(mach_task_self(), TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &count
);
239 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
242 T_DECL(thread_debug_info
, "tests thread debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
245 int is_dev
= is_development_kernel();
247 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
251 thread_debug_info_internal_data_t debug_info
;
253 mach_msg_type_number_t count
= THREAD_DEBUG_INFO_INTERNAL_COUNT
;
255 err
= thread_info(mach_thread_self(), THREAD_DEBUG_INFO_INTERNAL
, (thread_info_t
)&debug_info
, &count
);
257 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
266 for (i
= 1; i
<= number
; i
++) {
273 T_DECL(task_thread_times_info
, "tests task thread times info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
276 int is_dev
= is_development_kernel();
278 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
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
;
286 err
= task_info(mach_task_self(), TASK_THREAD_TIMES_INFO
, (task_info_t
)&thread_times_info_data
, &count
);
288 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
292 err
= task_info(mach_task_self(), TASK_THREAD_TIMES_INFO
, (task_info_t
)&thread_times_info_data_new
, &count
);
294 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
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
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");
307 * This is a negative case.
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.");
316 T_DECL(task_absolutetime_info
, "tests task absolute time info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
319 int is_dev
= is_development_kernel();
321 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
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
;
330 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data
, &count
);
332 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
336 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data_new
, &count
);
338 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
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
;
343 #if !(defined(__arm__) || defined(__arm64__))
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.
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");
353 if (absolute_time_info_data
.threads_user
<= 0) {
354 int precise_time_val
= 0;
355 size_t len
= sizeof(size_t);
357 T_LOG("User threads time is zero. This should only happen rarely and when precise_user_time is off");
359 err
= sysctlbyname("kern.precise_user_kernel_time", &precise_time_val
, &len
, NULL
, 0);
361 T_EXPECT_POSIX_SUCCESS(err
, "performing sysctl to check precise_user_time");
363 T_LOG("kern.precise_user_kernel_time val = %d", precise_time_val
);
365 T_EXPECT_FALSE(precise_time_val
, "user thread time should only be zero when precise_user_kernel_time is disabled");
367 T_PASS("task_info should return non-zero value for user threads time = %llu", absolute_time_info_data
.threads_user
);
370 #if !(defined(__arm__) || defined(__arm64__))
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.
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
);
380 * This is a negative case.
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.");
388 T_DECL(task_affinity_tag_info
, "tests task_affinity_tag_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
391 int is_dev
= is_development_kernel();
393 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
397 task_affinity_tag_info_data_t affinity_tag_info_data
;
398 mach_msg_type_number_t count
= TASK_AFFINITY_TAG_INFO_COUNT
;
400 err
= task_info(mach_task_self(), TASK_AFFINITY_TAG_INFO
, (task_info_t
)&affinity_tag_info_data
, &count
);
402 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
405 * The affinity is not set by default, hence expecting a zero value.
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");
411 * This is a negative case.
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.");
419 T_DECL(task_flags_info
, "tests task_flags_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
422 int is_dev
= is_development_kernel();
424 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
428 task_flags_info_data_t flags_info_data
;
429 mach_msg_type_number_t count
= TASK_FLAGS_INFO_COUNT
;
431 err
= task_info(mach_task_self(), TASK_FLAGS_INFO
, (task_info_t
)&flags_info_data
, &count
);
433 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
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");
440 * This is a negative case.
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.");
449 T_DECL(task_power_info_v2
, "tests task_power_info_v2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
452 int is_dev
= is_development_kernel();
454 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
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
;
464 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
466 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
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");
474 * Verify the cpu_energy parameters.
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");
479 #if !(defined(__arm__) || defined(__arm64__))
481 * iOS does not have system_time.
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");
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
);
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
);
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
);
502 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
505 * This is a negative case.
508 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
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
));
516 T_DECL(test_task_basic_info_32
, "tests TASK_BASIC_INFO_32", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
518 test_task_basic_info(INFO_32
);
521 T_DECL(test_task_basic_info_32_2
, "tests TASK_BASIC_INFO_32_2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
523 test_task_basic_info(INFO_32_2
);
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
))
529 test_task_basic_info(INFO_64_2
);
532 T_DECL(test_task_basic_info_64
, "tests TASK_BASIC_INFO_64", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
534 test_task_basic_info(INFO_64
);
536 #endif /* defined(__arm__) || defined(__arm64__) */
538 T_DECL(test_mach_task_basic_info
, "tests MACH_TASK_BASIC_INFO", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
540 test_task_basic_info(INFO_MACH
);
544 test_task_basic_info(enum info_kind kind
)
550 int is_dev
= is_development_kernel();
552 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
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];
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];
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
;
571 void * tmp_map
= NULL
;
573 mach_port_name_t child_task
;
575 int timeout
= 10; // change to max timeout
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
;
586 if (kind
== INFO_32_2
) {
587 flavor
= TASK_BASIC2_INFO_32
;
591 #if defined(__arm__) || defined(__arm64__)
593 T_ASSERT_FAIL("invalid basic info kind");
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
;
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
;
612 T_ASSERT_FAIL("invalid basic info kind");
614 #endif /* defined(__arm__) || defined(__arm64__) */
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
;
623 T_ASSERT_FAIL("invalid basic info kind");
627 kr
= task_info(mach_task_self(), flavor
, info_data
[BEFORE
], &count
);
629 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info succeeded");
634 * Allocate virtual and resident memory.
636 tmp_map
= mmap(0, PAGE_SIZE
, PROT_WRITE
, MAP_ANON
| MAP_PRIVATE
, -1, 0);
639 T_EXPECT_NE(tmp_map
, MAP_FAILED
, "verify mmap call is successful");
641 memset(tmp_map
, 'm', PAGE_SIZE
);
645 T_ASSERT_POSIX_SUCCESS(child_pid
, "verify process can be forked");
647 if (child_pid
== 0) {
649 * This will suspend the child process.
651 kr
= task_suspend(mach_task_self());
656 * Wait for the child process to suspend itself.
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");
664 * Verify the suspend_count for child and resume it.
667 kr
= task_info(child_task
, flavor
, info_data
[AFTER
], &count
);
668 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
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");
673 kr
= task_resume(child_task
);
674 T_ASSERT_MACH_SUCCESS(kr
, "verify task_resume succeeded");
677 * reap kr from task_suspend call in child
679 if (dt_waitpid(child_pid
, &exit_status
, NULL
, timeout
)) {
680 T_ASSERT_MACH_SUCCESS(exit_status
, "verify child task_suspend is successful");
682 T_FAIL("dt_waitpid failed");
685 kr
= task_info(mach_task_self(), flavor
, info_data
[AFTER
], &count
);
686 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
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
]);
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
695 * max resident size is a discrete field in INFO_MACH, so it's handled differently
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");
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");
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");
717 * These counters give time for threads that have terminated. We dont have any, so checking for zero.
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");
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");
727 * The default value for non-kernel tasks is TIMESHARE.
730 policy_t pt
= (policy_t
)info_get(kind
, GET_POLICY
, info_data
[BEFORE
]);
732 T_EXPECT_EQ(pt
, POLICY_TIMESHARE
, "verify task_info shows valid policy");
735 * This is a negative case.
739 kr
= task_info(mach_task_self(), flavor
, info_data
[AFTER
], &count
);
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");
747 munmap(tmp_map
, PAGE_SIZE
);
755 T_DECL(test_sigcont_task_suspend_resume
,
756 "test to verify that SIGCONT on task_suspend()-ed process works",
758 T_META_LTEPHASE(LTE_POSTINIT
))
761 int is_dev
= is_development_kernel();
763 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
766 mach_task_basic_info_data_t mach_basic_info_data
;
767 task_info_t info_data
= (task_info_t
)&mach_basic_info_data
;
769 task_debug_info_internal_data_t debug_info
;
770 mach_msg_type_number_t debug_count
= TASK_DEBUG_INFO_INTERNAL_COUNT
;
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
;
779 mach_port_name_t child_task
;
787 T_ASSERT_POSIX_SUCCESS(child_pid
, "verify process can be forked");
789 if (child_pid
== 0) {
791 * This will suspend the child process.
793 kr
= task_suspend(mach_task_self());
796 * When child resumes, it exits immediately
803 * Wait for the child process to suspend itself.
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");
811 * Verify the suspend_count for child and resume it.
814 kr
= task_info(child_task
, flavor
, info_data
, &count
);
815 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
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) ");
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");
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)");
826 posix_ret
= kill(child_pid
, SIGCONT
);
827 T_ASSERT_POSIX_SUCCESS(posix_ret
, "verify signal call succeeded");
830 * reap kr from task_suspend call in child
832 dt_waitpid(child_pid
, &exit_status
, &signal_no
, timeout
);
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");
838 T_DECL(test_sigcont_task_suspend2_resume
,
839 "test to verify that SIGCONT on task_suspend2()-ed process doesn't work",
841 T_META_LTEPHASE(LTE_POSTINIT
))
844 int is_dev
= is_development_kernel();
846 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
849 mach_task_basic_info_data_t mach_basic_info_data
;
850 task_info_t info_data
= (task_info_t
)&mach_basic_info_data
;
852 task_debug_info_internal_data_t debug_info
;
853 mach_msg_type_number_t debug_count
= TASK_DEBUG_INFO_INTERNAL_COUNT
;
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;
862 mach_port_name_t child_task
;
863 task_suspension_token_t child_token
= 0xFFFFF;
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
881 T_ASSERT_POSIX_SUCCESS(child_pid
, "verify process can be forked %d", child_pid
);
883 if (child_pid
== 0) {
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...");
891 * Wait for child to fork and block on read
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");
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");
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)");
906 kr
= task_suspend2(child_task
, &child_token
);
907 T_ASSERT_MACH_SUCCESS(kr
, "verify task_suspend2 call succeeded");
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");
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)");
916 * Verify the suspend_count for child and resume it.
919 kr
= task_info(child_task
, flavor
, info_data
, &count
);
920 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
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)");
925 posix_ret
= kill(child_pid
, SIGCONT
);
926 T_ASSERT_POSIX_SUCCESS(posix_ret
, "verify signal call succeeded");
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");
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)");
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");
938 kr
= task_resume(child_task
);
939 T_EXPECTFAIL_WITH_RADAR(33166654);
940 T_EXPECT_MACH_SUCCESS(kr
, "verify task_resume succeeded");
943 * reap kr from task_suspend call in child
946 dt_waitpid(child_pid
, &exit_status
, &signal_no
, timeout
);
948 T_ASSERT_EQ(signal_no
, SIG_DT_TIMEOUT
, "dt_waitpid timed out as expected");
950 // Resume properly using token and then wait
952 kr
= task_resume2(child_token
);
953 T_EXPECTFAIL_WITH_RADAR(33166654);
954 T_ASSERT_MACH_SUCCESS(kr
, "verify task_resume2 succeeded");
956 write(fd
[1], &pipe_msg
, sizeof(pipe_msg
));
959 * reap kr from task_suspend call in child
961 dt_waitpid(child_pid
, &exit_status
, &signal_no
, timeout
);
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");
968 info_get(enum info_kind kind
, enum info_get get
, void * data
)
971 case GET_SUSPEND_COUNT
:
975 return (uint64_t)(((task_basic_info_32_t
)data
)->suspend_count
);
976 #if defined(__arm__) || defined(__arm64__)
978 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
982 return (uint64_t)(((task_basic_info_64_2_t
)data
)->suspend_count
);
985 return (uint64_t)(((task_basic_info_64_t
)data
)->suspend_count
);
988 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
990 #endif /* defined(__arm__) || defined(__arm64__) */
992 return (uint64_t)(((mach_task_basic_info_t
)data
)->suspend_count
);
995 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
997 case GET_RESIDENT_SIZE
:
1001 return (uint64_t)(((task_basic_info_32_t
)data
)->resident_size
);
1002 #if defined(__arm__) || defined(__arm64__)
1004 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1008 return (uint64_t)(((task_basic_info_64_2_t
)data
)->resident_size
);
1011 return (uint64_t)(((task_basic_info_64_t
)data
)->resident_size
);
1014 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1016 #endif /* defined(__arm__) || defined(__arm64__) */
1018 return (uint64_t)(((mach_task_basic_info_t
)data
)->resident_size
);
1021 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1023 case GET_VIRTUAL_SIZE
:
1027 return (uint64_t)(((task_basic_info_32_t
)data
)->virtual_size
);
1028 #if defined(__arm__) || defined(__arm64__)
1030 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1034 return (uint64_t)(((task_basic_info_64_2_t
)data
)->virtual_size
);
1037 return (uint64_t)(((task_basic_info_64_t
)data
)->virtual_size
);
1040 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1042 #endif /* defined(__arm__) || defined(__arm64__) */
1044 return (uint64_t)(((mach_task_basic_info_t
)data
)->virtual_size
);
1048 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1054 return (uint64_t) &(((task_basic_info_32_t
)data
)->user_time
);
1055 #if defined(__arm__) || defined(__arm64__)
1057 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1061 return (uint64_t) &(((task_basic_info_64_2_t
)data
)->user_time
);
1064 return (uint64_t) &(((task_basic_info_64_t
)data
)->user_time
);
1067 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1069 #endif /* defined(__arm__) || defined(__arm64__) */
1071 return (uint64_t) &(((mach_task_basic_info_t
)data
)->user_time
);
1075 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1081 return (uint64_t) &(((task_basic_info_32_t
)data
)->system_time
);
1082 #if defined(__arm__) || defined(__arm64__)
1084 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1088 return (uint64_t) &(((task_basic_info_64_2_t
)data
)->system_time
);
1091 return (uint64_t) &(((task_basic_info_64_t
)data
)->system_time
);
1094 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1096 #endif /* defined(__arm__) || defined(__arm64__) */
1098 return (uint64_t) &(((mach_task_basic_info_t
)data
)->user_time
);
1101 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1107 return (uint64_t)(((task_basic_info_32_t
)data
)->policy
);
1108 #if defined(__arm__) || defined(__arm64__)
1110 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1114 return (uint64_t)(((task_basic_info_64_2_t
)data
)->policy
);
1117 return (uint64_t)(((task_basic_info_64_t
)data
)->policy
);
1120 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1122 #endif /* defined(__arm__) || defined(__arm64__) */
1124 return (uint64_t)(((mach_task_basic_info_t
)data
)->policy
);
1128 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1136 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1138 return (uint64_t)(((mach_task_basic_info_t
)data
)->resident_size_max
);
1141 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1145 __builtin_unreachable();
1149 * Determines whether we're running on a development kernel
1152 is_development_kernel(void)
1156 static int is_dev
= NOTSET
;
1158 if (is_dev
== NOTSET
) {
1160 size_t dev_size
= sizeof(dev
);
1163 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.development", &dev
, &dev_size
, NULL
, 0), NULL
);
1164 is_dev
= (dev
!= 0);