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 /* *************************************************************************************
17 * Test the task_info API.
19 * This is a functional test of the following APIs:
23 * TASK_BASIC_INFO_64_2
26 * TASK_AFFINITY_TAG_INFO
27 * TASK_THREAD_TIMES_INFO
28 * TASK_ABSOLUTE_TIME_INFO
29 * <rdar://problem/22242021> Add tests to increase code coverage for the task_info API
30 * *************************************************************************************
32 #define TESTPHYSFOOTPRINTVAL 5
33 #define CANARY 0x0f0f0f0f0f0f0f0fULL
34 #if !defined(CONFIG_EMBEDDED)
35 #define ABSOLUTE_MIN_USER_TIME_DIFF 150
36 #define ABSOLUTE_MIN_SYSTEM_TIME_DIFF 300
39 enum info_kind
{ INFO_32
, INFO_64
, INFO_32_2
, INFO_64_2
, INFO_MACH
, INFO_MAX
};
41 enum info_get
{ GET_SUSPEND_COUNT
, GET_RESIDENT_SIZE
, GET_VIRTUAL_SIZE
, GET_USER_TIME
, GET_SYS_TIME
, GET_POLICY
, GET_MAX_RES
};
44 * This function uses CPU cycles by doing a factorial computation.
46 static void do_factorial_task(void);
48 void test_task_basic_info_32(void);
49 void test_task_basic_info_64(void);
50 void task_basic_info_32_debug(void);
51 void task_basic2_info_32_warmup(void);
52 static int is_development_kernel(void);
53 void test_task_basic_info(enum info_kind kind
);
54 uint64_t info_get(enum info_kind kind
, enum info_get get
, void * data
);
56 T_DECL(task_vm_info
, "tests task vm info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
59 task_vm_info_data_t vm_info
;
61 mach_msg_type_number_t count
= TASK_VM_INFO_COUNT
;
63 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
65 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
67 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info return value !=0 for virtual_size\n");
69 T_EXPECT_NE(vm_info
.phys_footprint
, 0ULL, "task_info return value !=0 for phys_footprint\n");
72 * Test the REV0 version of TASK_VM_INFO. It should not change the value of phys_footprint.
75 count
= TASK_VM_INFO_REV0_COUNT
;
76 vm_info
.phys_footprint
= TESTPHYSFOOTPRINTVAL
;
77 vm_info
.min_address
= CANARY
;
78 vm_info
.max_address
= CANARY
;
80 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
82 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
84 T_EXPECT_EQ(count
, TASK_VM_INFO_REV0_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV0_COUNT", count
);
86 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev0 call does not return 0 for virtual_size");
88 T_EXPECT_EQ(vm_info
.phys_footprint
, (unsigned long long)TESTPHYSFOOTPRINTVAL
,
89 "task_info --rev0 call returned value %llu for vm_info.phys_footprint. Expected %u since this value should not be "
91 vm_info
.phys_footprint
, TESTPHYSFOOTPRINTVAL
);
93 T_EXPECT_EQ(vm_info
.min_address
, CANARY
,
94 "task_info --rev0 call returned value 0x%llx for vm_info.min_address. Expected 0x%llx since this value should not "
95 "be modified by rev0",
96 vm_info
.min_address
, CANARY
);
98 T_EXPECT_EQ(vm_info
.max_address
, CANARY
,
99 "task_info --rev0 call returned value 0x%llx for vm_info.max_address. Expected 0x%llx since this value should not "
100 "be modified by rev0",
101 vm_info
.max_address
, CANARY
);
104 * Test the REV1 version of TASK_VM_INFO.
107 count
= TASK_VM_INFO_REV1_COUNT
;
108 vm_info
.phys_footprint
= TESTPHYSFOOTPRINTVAL
;
109 vm_info
.min_address
= CANARY
;
110 vm_info
.max_address
= CANARY
;
112 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
114 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
116 T_EXPECT_EQ(count
, TASK_VM_INFO_REV1_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV1_COUNT", count
);
118 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev1 call does not return 0 for virtual_size");
120 T_EXPECT_NE(vm_info
.phys_footprint
, (unsigned long long)TESTPHYSFOOTPRINTVAL
,
121 "task_info --rev1 call returned value %llu for vm_info.phys_footprint. Expected value is anything other than %u "
122 "since this value should not be modified by rev1",
123 vm_info
.phys_footprint
, TESTPHYSFOOTPRINTVAL
);
125 T_EXPECT_EQ(vm_info
.min_address
, CANARY
,
126 "task_info --rev1 call returned value 0x%llx for vm_info.min_address. Expected 0x%llx since this value should not "
127 "be modified by rev1",
128 vm_info
.min_address
, CANARY
);
130 T_EXPECT_EQ(vm_info
.max_address
, CANARY
,
131 "task_info --rev1 call returned value 0x%llx for vm_info.max_address. Expected 0x%llx since this value should not "
132 "be modified by rev1",
133 vm_info
.max_address
, CANARY
);
136 * Test the REV2 version of TASK_VM_INFO.
139 count
= TASK_VM_INFO_REV2_COUNT
;
140 vm_info
.phys_footprint
= TESTPHYSFOOTPRINTVAL
;
141 vm_info
.min_address
= CANARY
;
142 vm_info
.max_address
= CANARY
;
144 err
= task_info(mach_task_self(), TASK_VM_INFO_PURGEABLE
, (task_info_t
)&vm_info
, &count
);
146 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
148 T_EXPECT_EQ(count
, TASK_VM_INFO_REV2_COUNT
, "task_info count(%d) is equal to TASK_VM_INFO_REV2_COUNT\n", count
);
150 T_EXPECT_NE(vm_info
.virtual_size
, 0ULL, "task_info --rev2 call does not return 0 for virtual_size\n");
152 T_EXPECT_NE(vm_info
.phys_footprint
, (unsigned long long)TESTPHYSFOOTPRINTVAL
,
153 "task_info --rev2 call returned value %llu for vm_info.phys_footprint. Expected anything other than %u since this "
154 "value should be modified by rev2",
155 vm_info
.phys_footprint
, TESTPHYSFOOTPRINTVAL
);
157 T_EXPECT_NE(vm_info
.min_address
, CANARY
,
158 "task_info --rev2 call returned value 0x%llx for vm_info.min_address. Expected anything other than 0x%llx since "
159 "this value should be modified by rev2",
160 vm_info
.min_address
, CANARY
);
162 T_EXPECT_NE(vm_info
.max_address
, CANARY
,
163 "task_info --rev2 call returned value 0x%llx for vm_info.max_address. Expected anything other than 0x%llx since "
164 "this value should be modified by rev2",
165 vm_info
.max_address
, CANARY
);
168 T_DECL(host_debug_info
, "tests host debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
171 int is_dev
= is_development_kernel();
173 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
178 host_debug_info_internal_data_t debug_info
;
179 mach_msg_type_number_t count
= HOST_DEBUG_INFO_INTERNAL_COUNT
;
180 host
= mach_host_self();
181 err
= host_info(host
, HOST_DEBUG_INFO_INTERNAL
, (host_info_t
)&debug_info
, &count
);
183 T_ASSERT_MACH_SUCCESS(err
, "verify host_info call succeeded");
186 T_DECL(task_debug_info
, "tests task debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
189 int is_dev
= is_development_kernel();
191 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
195 task_debug_info_internal_data_t debug_info
;
197 mach_msg_type_number_t count
= TASK_DEBUG_INFO_INTERNAL_COUNT
;
199 err
= task_info(mach_task_self(), TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &count
);
201 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
204 T_DECL(thread_debug_info
, "tests thread debug info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
207 int is_dev
= is_development_kernel();
209 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
213 thread_debug_info_internal_data_t debug_info
;
215 mach_msg_type_number_t count
= THREAD_DEBUG_INFO_INTERNAL_COUNT
;
217 err
= thread_info(mach_thread_self(), THREAD_DEBUG_INFO_INTERNAL
, (thread_info_t
)&debug_info
, &count
);
219 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
228 for (i
= 1; i
<= number
; i
++) {
235 T_DECL(task_thread_times_info
, "tests task thread times info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
238 int is_dev
= is_development_kernel();
240 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
244 task_thread_times_info_data_t thread_times_info_data
;
245 task_thread_times_info_data_t thread_times_info_data_new
;
246 mach_msg_type_number_t count
= TASK_THREAD_TIMES_INFO_COUNT
;
248 err
= task_info(mach_task_self(), TASK_THREAD_TIMES_INFO
, (task_info_t
)&thread_times_info_data
, &count
);
250 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
254 err
= task_info(mach_task_self(), TASK_THREAD_TIMES_INFO
, (task_info_t
)&thread_times_info_data_new
, &count
);
256 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
259 * The difference is observed to be less than 30 microseconds for user_time
260 * and less than 50 microseconds for system_time. This observation was done for over
264 T_EXPECT_FALSE((thread_times_info_data_new
.user_time
.seconds
- thread_times_info_data
.user_time
.seconds
) != 0 ||
265 (thread_times_info_data_new
.system_time
.seconds
- thread_times_info_data
.system_time
.seconds
) != 0,
266 "Tests whether the difference between thread times is greater than the allowed limit");
269 * This is a negative case.
273 err
= task_info(mach_task_self(), TASK_THREAD_TIMES_INFO
, (task_info_t
)&thread_times_info_data
, &count
);
274 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
275 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
278 T_DECL(task_absolutetime_info
, "tests task absolute time info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
281 int is_dev
= is_development_kernel();
283 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
287 uint64_t user_time_diff
, system_time_diff
;
288 task_absolutetime_info_data_t absolute_time_info_data
;
289 task_absolutetime_info_data_t absolute_time_info_data_new
;
290 mach_msg_type_number_t count
= TASK_ABSOLUTETIME_INFO_COUNT
;
292 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data
, &count
);
294 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
298 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data_new
, &count
);
300 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
302 user_time_diff
= absolute_time_info_data_new
.total_user
- absolute_time_info_data
.total_user
;
303 system_time_diff
= absolute_time_info_data_new
.total_system
- absolute_time_info_data
.total_system
;
305 #if !(defined(__arm__) || defined(__arm64__))
307 * On embedded devices the difference is always zero.
308 * On non-embedded devices the difference occurs in this range. This was observed over ~10000 runs.
311 T_EXPECT_FALSE(user_time_diff
< ABSOLUTE_MIN_USER_TIME_DIFF
|| system_time_diff
< ABSOLUTE_MIN_SYSTEM_TIME_DIFF
,
312 "Tests whether the difference between thread times is greater than the expected range");
315 if (absolute_time_info_data
.threads_user
<= 0) {
316 int precise_time_val
= 0;
317 size_t len
= sizeof(size_t);
319 T_LOG("User threads time is zero. This should only happen rarely and when precise_user_time is off");
321 err
= sysctlbyname("kern.precise_user_kernel_time", &precise_time_val
, &len
, NULL
, 0);
323 T_EXPECT_POSIX_SUCCESS(err
, "performing sysctl to check precise_user_time");
325 T_LOG("kern.precise_user_kernel_time val = %d", precise_time_val
);
327 T_EXPECT_FALSE(precise_time_val
, "user thread time should only be zero when precise_user_kernel_time is disabled");
329 T_PASS("task_info should return non-zero value for user threads time = %llu", absolute_time_info_data
.threads_user
);
332 #if !(defined(__arm__) || defined(__arm64__))
334 * On iOS, system threads are always zero. On OS X this value can be some large positive number.
335 * There is no real way to estimate the exact amount.
337 T_EXPECT_NE(absolute_time_info_data
.threads_system
, 0ULL,
338 "task_info should return non-zero value for system threads time = %llu", absolute_time_info_data
.threads_system
);
342 * This is a negative case.
345 err
= task_info(mach_task_self(), TASK_ABSOLUTETIME_INFO
, (task_info_t
)&absolute_time_info_data_new
, &count
);
346 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
347 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
350 T_DECL(task_affinity_tag_info
, "tests task_affinity_tag_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
353 int is_dev
= is_development_kernel();
355 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
359 task_affinity_tag_info_data_t affinity_tag_info_data
;
360 mach_msg_type_number_t count
= TASK_AFFINITY_TAG_INFO_COUNT
;
362 err
= task_info(mach_task_self(), TASK_AFFINITY_TAG_INFO
, (task_info_t
)&affinity_tag_info_data
, &count
);
364 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
367 * The affinity is not set by default, hence expecting a zero value.
369 T_ASSERT_FALSE(affinity_tag_info_data
.min
!= 0 || affinity_tag_info_data
.max
!= 0,
370 "task_info call returns non-zero min or max value");
373 * This is a negative case.
376 err
= task_info(mach_task_self(), TASK_AFFINITY_TAG_INFO
, (task_info_t
)&affinity_tag_info_data
, &count
);
377 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
378 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
381 T_DECL(task_flags_info
, "tests task_flags_info", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
384 int is_dev
= is_development_kernel();
386 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
390 task_flags_info_data_t flags_info_data
;
391 mach_msg_type_number_t count
= TASK_FLAGS_INFO_COUNT
;
393 err
= task_info(mach_task_self(), TASK_FLAGS_INFO
, (task_info_t
)&flags_info_data
, &count
);
395 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
397 /* Change for 32-bit arch possibility?*/
398 T_ASSERT_EQ((flags_info_data
.flags
& (unsigned int)(~TF_LP64
)), 0U, "task_info should only give out 64-bit addr flag");
401 * This is a negative case.
405 err
= task_info(mach_task_self(), TASK_FLAGS_INFO
, (task_info_t
)&flags_info_data
, &count
);
406 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
407 "Negative test case: task_info should verify that count is at least equal to what is defined in API.");
410 T_DECL(task_power_info_v2
, "tests task_power_info_v2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
413 int is_dev
= is_development_kernel();
415 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
419 task_power_info_v2_data_t power_info_data_v2
;
420 task_power_info_v2_data_t power_info_data_v2_new
;
421 mach_msg_type_number_t count
= TASK_POWER_INFO_V2_COUNT
;
425 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
427 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
429 T_ASSERT_LE(power_info_data_v2
.gpu_energy
.task_gpu_utilisation
, 0ULL,
430 "verified task_info call shows zero GPU utilization for non-GPU task");
435 * Verify the cpu_energy parameters.
437 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2_new
, &count
);
438 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
440 #if !(defined(__arm__) || defined(__arm64__))
442 * iOS does not have system_time.
444 T_ASSERT_GT(power_info_data_v2_new
.cpu_energy
.total_user
, power_info_data_v2
.cpu_energy
.total_user
,
445 "task_info call returns valid user time");
446 T_ASSERT_GT(power_info_data_v2_new
.cpu_energy
.total_system
, power_info_data_v2
.cpu_energy
.total_system
,
447 "task_info call returns valid system time");
450 T_ASSERT_GE(power_info_data_v2
.cpu_energy
.task_interrupt_wakeups
, 1ULL,
451 "verify task_info call returns non-zero value for interrupt_wakeup (ret value = %llu)",
452 power_info_data_v2
.cpu_energy
.task_interrupt_wakeups
);
454 #if !(defined(__arm__) || defined(__arm64__))
455 if (power_info_data_v2
.cpu_energy
.task_platform_idle_wakeups
!= 0) {
456 T_LOG("task_info call returned %llu for platform_idle_wakeup", power_info_data_v2
.cpu_energy
.task_platform_idle_wakeups
);
460 count
= TASK_POWER_INFO_V2_COUNT_OLD
;
461 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
463 T_ASSERT_MACH_SUCCESS(err
, "verify task_info call succeeded");
466 * This is a negative case.
469 err
= task_info(mach_task_self(), TASK_POWER_INFO_V2
, (task_info_t
)&power_info_data_v2
, &count
);
471 T_ASSERT_MACH_ERROR(err
, KERN_INVALID_ARGUMENT
,
472 "Negative test case: task_info should verify that count is at least equal to what is defined in API. Call "
473 "returns errno %d:%s",
474 err
, mach_error_string(err
));
477 T_DECL(test_task_basic_info_32
, "tests TASK_BASIC_INFO_32", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
479 test_task_basic_info(INFO_32
);
482 T_DECL(test_task_basic_info_32_2
, "tests TASK_BASIC_INFO_32_2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
484 test_task_basic_info(INFO_32_2
);
487 #if defined(__arm__) || defined(__arm64__)
488 T_DECL(test_task_basic_info_64i_2
, "tests TASK_BASIC_INFO_64_2", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
490 test_task_basic_info(INFO_64_2
);
493 T_DECL(test_task_basic_info_64
, "tests TASK_BASIC_INFO_64", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
495 test_task_basic_info(INFO_64
);
497 #endif /* defined(__arm__) || defined(__arm64__) */
499 T_DECL(test_mach_task_basic_info
, "tests MACH_TASK_BASIC_INFO", T_META_ASROOT(true), T_META_LTEPHASE(LTE_POSTINIT
))
501 test_task_basic_info(INFO_MACH
);
505 test_task_basic_info(enum info_kind kind
)
511 int is_dev
= is_development_kernel();
513 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
516 task_info_t info_data
[2];
517 task_basic_info_32_data_t basic_info_32_data
[2];
518 #if defined(__arm__) || defined(__arm64__)
519 task_basic_info_64_2_data_t basic_info_64_2_data
[2];
521 task_basic_info_64_data_t basic_info_64_data
[2];
522 #endif /* defined(__arm__) || defined(__arm64__) */
523 mach_task_basic_info_data_t mach_basic_info_data
[2];
526 mach_msg_type_number_t count
;
527 task_flavor_t flavor
= 0;
528 integer_t suspend_count
;
529 uint64_t resident_size_diff
;
530 uint64_t virtual_size_diff
;
532 void * tmp_map
= NULL
;
534 mach_port_name_t child_task
;
536 int timeout
= 10; // change to max timeout
542 info_data
[BEFORE
] = (task_info_t
)&basic_info_32_data
[BEFORE
];
543 info_data
[AFTER
] = (task_info_t
)&basic_info_32_data
[AFTER
];
544 count
= TASK_BASIC_INFO_32_COUNT
;
545 flavor
= TASK_BASIC_INFO_32
;
547 if (kind
== INFO_32_2
) {
548 flavor
= TASK_BASIC2_INFO_32
;
552 #if defined(__arm__) || defined(__arm64__)
554 T_ASSERT_FAIL("invalid basic info kind");
558 info_data
[BEFORE
] = (task_info_t
)&basic_info_64_2_data
[BEFORE
];
559 info_data
[AFTER
] = (task_info_t
)&basic_info_64_2_data
[AFTER
];
560 count
= TASK_BASIC_INFO_64_2_COUNT
;
561 flavor
= TASK_BASIC_INFO_64_2
;
566 info_data
[BEFORE
] = (task_info_t
)&basic_info_64_data
[BEFORE
];
567 info_data
[AFTER
] = (task_info_t
)&basic_info_64_data
[AFTER
];
568 count
= TASK_BASIC_INFO_64_COUNT
;
569 flavor
= TASK_BASIC_INFO_64
;
573 T_ASSERT_FAIL("invalid basic info kind");
575 #endif /* defined(__arm__) || defined(__arm64__) */
577 info_data
[BEFORE
] = (task_info_t
)&mach_basic_info_data
[BEFORE
];
578 info_data
[AFTER
] = (task_info_t
)&mach_basic_info_data
[AFTER
];
579 count
= MACH_TASK_BASIC_INFO_COUNT
;
580 flavor
= MACH_TASK_BASIC_INFO
;
584 T_ASSERT_FAIL("invalid basic info kind");
588 kr
= task_info(mach_task_self(), flavor
, info_data
[BEFORE
], &count
);
590 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info succeeded");
595 * Allocate virtual and resident memory.
597 tmp_map
= mmap(0, PAGE_SIZE
, PROT_WRITE
, MAP_ANON
| MAP_PRIVATE
, -1, 0);
600 T_EXPECT_NE(tmp_map
, MAP_FAILED
, "verify mmap call is successful");
602 memset(tmp_map
, 'm', PAGE_SIZE
);
606 T_ASSERT_POSIX_SUCCESS(child_pid
, "verify process can be forked");
608 if (child_pid
== 0) {
610 * This will suspend the child process.
612 kr
= task_suspend(mach_task_self());
617 * Wait for the child process to suspend itself.
621 kr
= task_for_pid(mach_task_self(), child_pid
, &child_task
);
622 T_ASSERT_MACH_SUCCESS(kr
, "verify task_for_pid succeeded. check sudo if failed");
625 * Verify the suspend_count for child and resume it.
628 kr
= task_info(child_task
, flavor
, info_data
[AFTER
], &count
);
629 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
631 suspend_count
= (integer_t
)(info_get(kind
, GET_SUSPEND_COUNT
, info_data
[AFTER
]));
632 T_ASSERT_EQ(suspend_count
, 1, "verify task_info shows correct suspend_count");
634 kr
= task_resume(child_task
);
635 T_ASSERT_MACH_SUCCESS(kr
, "verify task_resume succeeded");
638 * reap kr from task_suspend call in child
640 if (dt_waitpid(child_pid
, &exit_status
, NULL
, timeout
)) {
641 T_ASSERT_MACH_SUCCESS(exit_status
, "verify child task_suspend is successful");
643 T_FAIL("dt_waitpid failed");
646 kr
= task_info(mach_task_self(), flavor
, info_data
[AFTER
], &count
);
647 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
649 resident_size_diff
= info_get(kind
, GET_RESIDENT_SIZE
, info_data
[AFTER
]) - info_get(kind
, GET_RESIDENT_SIZE
, info_data
[BEFORE
]);
650 virtual_size_diff
= info_get(kind
, GET_VIRTUAL_SIZE
, info_data
[AFTER
]) - info_get(kind
, GET_VIRTUAL_SIZE
, info_data
[BEFORE
]);
653 * INFO_32_2 gets the max resident size instead of the current resident size
654 * 32 KB tolerance built into test. The returned value is generally between 0 and 16384
656 * max resident size is a discrete field in INFO_MACH, so it's handled differently
658 if (kind
== INFO_32_2
) {
659 T_EXPECT_EQ(resident_size_diff
% 4096, 0ULL, "verify task_info returns valid max resident_size");
660 T_EXPECT_GE(resident_size_diff
, 0ULL, "verify task_info returns non-negative max resident_size");
661 T_EXPECT_GE(virtual_size_diff
, (unsigned long long)PAGE_SIZE
, "verify task_info returns valid virtual_size");
663 T_EXPECT_GE(resident_size_diff
, (unsigned long long)PAGE_SIZE
, "task_info returns valid resident_size");
664 T_EXPECT_GE(virtual_size_diff
, (unsigned long long)PAGE_SIZE
, "task_info returns valid virtual_size");
667 if (kind
== INFO_MACH
) {
668 resident_size_diff
= info_get(kind
, GET_MAX_RES
, info_data
[AFTER
]) - info_get(kind
, GET_MAX_RES
, info_data
[BEFORE
]);
669 T_EXPECT_EQ(resident_size_diff
% 4096, 0ULL, "verify task_info returns valid max resident_size");
670 T_EXPECT_GE(resident_size_diff
, 0ULL, "verify task_info returns non-negative max resident_size");
671 T_EXPECT_GE(info_get(kind
, GET_MAX_RES
, info_data
[AFTER
]), info_get(kind
, GET_RESIDENT_SIZE
, info_data
[AFTER
]),
672 "verify max resident size is greater than or equal to curr resident size");
678 * These counters give time for threads that have terminated. We dont have any, so checking for zero.
681 time_value_t
* user_tv
= (time_value_t
*)(info_get(kind
, GET_USER_TIME
, info_data
[BEFORE
]));
682 T_EXPECT_EQ((user_tv
->seconds
+ user_tv
->microseconds
/ 1000000), 0, "verify task_info shows valid user time");
684 time_value_t
* sys_tv
= (time_value_t
*)(info_get(kind
, GET_SYS_TIME
, info_data
[BEFORE
]));
685 T_EXPECT_EQ(sys_tv
->seconds
+ (sys_tv
->microseconds
/ 1000000), 0, "verify task_info shows valid system time");
688 * The default value for non-kernel tasks is TIMESHARE.
691 policy_t pt
= (policy_t
)info_get(kind
, GET_POLICY
, info_data
[BEFORE
]);
693 T_EXPECT_EQ(pt
, POLICY_TIMESHARE
, "verify task_info shows valid policy");
696 * This is a negative case.
700 kr
= task_info(mach_task_self(), flavor
, info_data
[AFTER
], &count
);
702 T_ASSERT_MACH_ERROR(kr
, KERN_INVALID_ARGUMENT
,
703 "Negative test case: task_info should verify that count is at least equal to what is defined in API");
708 munmap(tmp_map
, PAGE_SIZE
);
716 T_DECL(test_sigcont_task_suspend_resume
,
717 "test to verify that SIGCONT on task_suspend()-ed process works",
719 T_META_LTEPHASE(LTE_POSTINIT
))
722 int is_dev
= is_development_kernel();
724 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
727 mach_task_basic_info_data_t mach_basic_info_data
;
728 task_info_t info_data
= (task_info_t
)&mach_basic_info_data
;
730 task_debug_info_internal_data_t debug_info
;
731 mach_msg_type_number_t debug_count
= TASK_DEBUG_INFO_INTERNAL_COUNT
;
735 mach_msg_type_number_t count
= MACH_TASK_BASIC_INFO_COUNT
;
736 task_flavor_t flavor
= MACH_TASK_BASIC_INFO
;
737 integer_t suspend_count
;
738 integer_t debug_suspend_count
;
740 mach_port_name_t child_task
;
748 T_ASSERT_POSIX_SUCCESS(child_pid
, "verify process can be forked");
750 if (child_pid
== 0) {
752 * This will suspend the child process.
754 kr
= task_suspend(mach_task_self());
757 * When child resumes, it exits immediately
764 * Wait for the child process to suspend itself.
768 kr
= task_for_pid(mach_task_self(), child_pid
, &child_task
);
769 T_ASSERT_MACH_SUCCESS(kr
, "verify task_for_pid succeeded. check sudo if failed");
772 * Verify the suspend_count for child and resume it.
775 kr
= task_info(child_task
, flavor
, info_data
, &count
);
776 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
778 suspend_count
= (integer_t
)(info_get(INFO_MACH
, GET_SUSPEND_COUNT
, info_data
));
779 T_ASSERT_EQ(suspend_count
, 1, "verify task_info shows correct suspend_count (1) (actually user stop count) ");
781 kr
= task_info(child_task
, TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &debug_count
);
782 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
784 debug_suspend_count
= debug_info
.suspend_count
;
785 T_ASSERT_EQ(debug_info
.suspend_count
, 1, "verify debug_info shows correct suspend_count(1)");
787 posix_ret
= kill(child_pid
, SIGCONT
);
788 T_ASSERT_POSIX_SUCCESS(posix_ret
, "verify signal call succeeded");
791 * reap kr from task_suspend call in child
793 dt_waitpid(child_pid
, &exit_status
, &signal_no
, timeout
);
795 T_ASSERT_EQ(signal_no
, 0, "child should be resumed and exit without signal");
796 T_ASSERT_EQ(exit_status
, 0, "child should exit with 0");
800 T_DECL(test_sigcont_task_suspend2_resume
,
801 "test to verify that SIGCONT on task_suspend2()-ed process doesn't work",
803 T_META_LTEPHASE(LTE_POSTINIT
))
806 int is_dev
= is_development_kernel();
808 T_ASSERT_TRUE(is_dev
, "verify development kernel is running");
811 mach_task_basic_info_data_t mach_basic_info_data
;
812 task_info_t info_data
= (task_info_t
)&mach_basic_info_data
;
814 task_debug_info_internal_data_t debug_info
;
815 mach_msg_type_number_t debug_count
= TASK_DEBUG_INFO_INTERNAL_COUNT
;
819 mach_msg_type_number_t count
= MACH_TASK_BASIC_INFO_COUNT
;
820 task_flavor_t flavor
= MACH_TASK_BASIC_INFO
;
821 integer_t suspend_count
= 0;
822 integer_t debug_suspend_count
= 0;
824 mach_port_name_t child_task
;
825 task_suspension_token_t child_token
= 0xFFFFF;
829 * We expect the test to fail right now, so I've set timeout to
830 * be shorter than we may want it to be when the issue is fixed
843 T_ASSERT_POSIX_SUCCESS(child_pid
, "verify process can be forked %d", child_pid
);
845 if (child_pid
== 0) {
847 T_LOG("Waiting to read from parent...");
848 read(fd
[0], &pipe_msg
, sizeof(pipe_msg
));
849 T_LOG("Done reading from parent, about to exit...");
853 * Wait for child to fork and block on read
859 kr
= task_for_pid(mach_task_self(), child_pid
, &child_task
);
860 T_ASSERT_MACH_SUCCESS(kr
, "verify task_for_pid succeeded. check sudo if failed");
862 kr
= task_info(child_task
, TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &debug_count
);
863 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
865 debug_suspend_count
= debug_info
.suspend_count
;
866 T_EXPECT_EQ(debug_suspend_count
, 0, "verify debug_info shows correct (true) suspend_count(0)");
868 kr
= task_suspend2(child_task
, &child_token
);
869 T_ASSERT_MACH_SUCCESS(kr
, "verify task_suspend2 call succeeded");
871 kr
= task_info(child_task
, TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &debug_count
);
872 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
874 debug_suspend_count
= debug_info
.suspend_count
;
875 T_ASSERT_EQ(debug_suspend_count
, 1, "verify debug_info shows correct (true) suspend_count(1)");
878 * Verify the suspend_count for child and resume it.
881 kr
= task_info(child_task
, flavor
, info_data
, &count
);
882 T_ASSERT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
884 suspend_count
= (integer_t
)(info_get(INFO_MACH
, GET_SUSPEND_COUNT
, info_data
));
885 T_EXPECT_EQ(suspend_count
, 1, "verify task_info shows correct (user_stop_count) suspend_count (1)");
887 posix_ret
= kill(child_pid
, SIGCONT
);
888 T_ASSERT_POSIX_SUCCESS(posix_ret
, "verify signal call succeeded");
890 kr
= task_info(child_task
, TASK_DEBUG_INFO_INTERNAL
, (task_info_t
)&debug_info
, &debug_count
);
891 T_EXPECT_MACH_SUCCESS(kr
, "verify task_info call succeeded");
893 debug_suspend_count
= debug_info
.suspend_count
;
894 T_EXPECTFAIL_WITH_RADAR(33166654);
895 T_EXPECT_EQ(debug_suspend_count
, 1, "verify debug_info shows correct (true) suspend_count (1)");
897 suspend_count
= (integer_t
)(info_get(INFO_MACH
, GET_SUSPEND_COUNT
, info_data
));
898 T_ASSERT_EQ(suspend_count
, 1, "verify task_info shows correct (user_stop_count) suspend_count (1) after SIG_CONT");
900 kr
= task_resume(child_task
);
901 T_EXPECTFAIL_WITH_RADAR(33166654);
902 T_EXPECT_MACH_SUCCESS(kr
, "verify task_resume succeeded");
905 * reap kr from task_suspend call in child
908 dt_waitpid(child_pid
, &exit_status
, &signal_no
, timeout
);
910 T_ASSERT_EQ(signal_no
, SIG_DT_TIMEOUT
, "dt_waitpid timed out as expected");
912 // Resume properly using token and then wait
914 kr
= task_resume2(child_token
);
915 T_EXPECTFAIL_WITH_RADAR(33166654);
916 T_ASSERT_MACH_SUCCESS(kr
, "verify task_resume2 succeeded");
918 write(fd
[1], &pipe_msg
, sizeof(pipe_msg
));
921 * reap kr from task_suspend call in child
923 dt_waitpid(child_pid
, &exit_status
, &signal_no
, timeout
);
925 T_ASSERT_EQ(signal_no
, 0, "child should be resumed and no signal should be returned");
926 T_ASSERT_EQ(exit_status
, 0, "child should exit with 0");
931 info_get(enum info_kind kind
, enum info_get get
, void * data
)
934 case GET_SUSPEND_COUNT
:
938 return (uint64_t)(((task_basic_info_32_t
)data
)->suspend_count
);
939 #if defined(__arm__) || defined(__arm64__)
941 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
945 return (uint64_t)(((task_basic_info_64_2_t
)data
)->suspend_count
);
948 return (uint64_t)(((task_basic_info_64_t
)data
)->suspend_count
);
951 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
953 #endif /* defined(__arm__) || defined(__arm64__) */
955 return (uint64_t)(((mach_task_basic_info_t
)data
)->suspend_count
);
958 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
960 case GET_RESIDENT_SIZE
:
964 return (uint64_t)(((task_basic_info_32_t
)data
)->resident_size
);
965 #if defined(__arm__) || defined(__arm64__)
967 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
971 return (uint64_t)(((task_basic_info_64_2_t
)data
)->resident_size
);
974 return (uint64_t)(((task_basic_info_64_t
)data
)->resident_size
);
977 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
979 #endif /* defined(__arm__) || defined(__arm64__) */
981 return (uint64_t)(((mach_task_basic_info_t
)data
)->resident_size
);
984 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
986 case GET_VIRTUAL_SIZE
:
990 return (uint64_t)(((task_basic_info_32_t
)data
)->virtual_size
);
991 #if defined(__arm__) || defined(__arm64__)
993 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
997 return (uint64_t)(((task_basic_info_64_2_t
)data
)->virtual_size
);
1000 return (uint64_t)(((task_basic_info_64_t
)data
)->virtual_size
);
1003 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1005 #endif /* defined(__arm__) || defined(__arm64__) */
1007 return (uint64_t)(((mach_task_basic_info_t
)data
)->virtual_size
);
1011 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1017 return (uint64_t) & (((task_basic_info_32_t
)data
)->user_time
);
1018 #if defined(__arm__) || defined(__arm64__)
1020 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1024 return (uint64_t) & (((task_basic_info_64_2_t
)data
)->user_time
);
1027 return (uint64_t) & (((task_basic_info_64_t
)data
)->user_time
);
1030 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1032 #endif /* defined(__arm__) || defined(__arm64__) */
1034 return (uint64_t) & (((mach_task_basic_info_t
)data
)->user_time
);
1038 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1044 return (uint64_t) & (((task_basic_info_32_t
)data
)->system_time
);
1045 #if defined(__arm__) || defined(__arm64__)
1047 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1051 return (uint64_t) & (((task_basic_info_64_2_t
)data
)->system_time
);
1054 return (uint64_t) & (((task_basic_info_64_t
)data
)->system_time
);
1057 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1059 #endif /* defined(__arm__) || defined(__arm64__) */
1061 return (uint64_t) & (((mach_task_basic_info_t
)data
)->user_time
);
1064 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1070 return (uint64_t)(((task_basic_info_32_t
)data
)->policy
);
1071 #if defined(__arm__) || defined(__arm64__)
1073 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1077 return (uint64_t)(((task_basic_info_64_2_t
)data
)->policy
);
1080 return (uint64_t)(((task_basic_info_64_t
)data
)->policy
);
1083 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1085 #endif /* defined(__arm__) || defined(__arm64__) */
1087 return (uint64_t)(((mach_task_basic_info_t
)data
)->policy
);
1091 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1099 T_ASSERT_FAIL("illegal info_get %d %d", kind
, get
);
1101 return (uint64_t)(((mach_task_basic_info_t
)data
)->resident_size_max
);
1104 T_ASSERT_FAIL("unhandled info_get %d %d", kind
, get
);
1108 __builtin_unreachable();
1112 * Determines whether we're running on a development kernel
1115 is_development_kernel(void)
1119 static int is_dev
= NOTSET
;
1121 if (is_dev
== NOTSET
) {
1123 size_t dev_size
= sizeof(dev
);
1126 T_ASSERT_POSIX_SUCCESS(sysctlbyname("kern.development", &dev
, &dev_size
, NULL
, 0), NULL
);
1127 is_dev
= (dev
!= 0);