1 // Copyright 2021 (c) Apple Inc. All rights reserved.
2
3 #include <darwintest.h>
4 #include <inttypes.h>
5 #include <mach/coalition.h>
6 #include <stdint.h>
7 #include <sys/coalition.h>
8 #include <sys/sysctl.h>
9 #include <libproc.h>
10 #include <unistd.h>
11
12 #include "test_utils.h"
13
14 T_GLOBAL_META(
15 T_META_RADAR_COMPONENT_NAME("xnu"),
16 T_META_RADAR_COMPONENT_VERSION("RM"),
17 T_META_OWNER("mwidmann"),
18 T_META_RUN_CONCURRENTLY(true),
19 T_META_ASROOT(true),
20 T_META_CHECK_LEAKS(false));
21
22 static void
skip_if_monotonic_unsupported(void)23 skip_if_monotonic_unsupported(void)
24 {
25 int r;
26 int supported = 0;
27 size_t supported_size = sizeof(supported);
28
29 r = sysctlbyname("kern.monotonic.supported", &supported, &supported_size,
30 NULL, 0);
31 if (r < 0) {
32 T_WITH_ERRNO;
33 T_SKIP("could not find \"kern.monotonic.supported\" sysctl");
34 }
35
36 if (!supported) {
37 T_SKIP("monotonic is not supported on this platform");
38 }
39 }
40
41 T_DECL(coalition_resource_info_counters,
42 "ensure that coalition resource info produces valid counter data")
43 {
44 skip_if_monotonic_unsupported();
45
46 T_SETUPBEGIN;
47
48 struct proc_pidcoalitioninfo idinfo = {};
49 int ret = proc_pidinfo(getpid(), PROC_PIDCOALITIONINFO, 0,
50 &idinfo, sizeof(idinfo));
51 T_ASSERT_POSIX_SUCCESS(ret, "proc_pidinfo(... PROC_PIDCOALITIONINFO ...)");
52
53 uint64_t resid = idinfo.coalition_id[COALITION_TYPE_RESOURCE];
54
55 struct coalition_resource_usage coalusage[2] = {};
56 ret = coalition_info_resource_usage(resid, &coalusage[0],
57 sizeof(coalusage[0]));
58 T_ASSERT_POSIX_SUCCESS(ret, "coalition_info_resource_usage()");
59
60 T_SETUPEND;
61
62 T_EXPECT_GT(coalusage[0].cpu_instructions, UINT64_C(0),
63 "instruction count is non-zero");
64 T_EXPECT_GT(coalusage[0].cpu_cycles, UINT64_C(0),
65 "cycle count is non-zero");
66
67 sleep(1);
68
69 T_SETUPBEGIN;
70 ret = coalition_info_resource_usage(resid, &coalusage[1],
71 sizeof(coalusage[1]));
72 T_ASSERT_POSIX_SUCCESS(ret, "coalition_info_resource_usage()");
73 T_SETUPEND;
74
75 T_EXPECT_GE(coalusage[1].cpu_instructions, coalusage[0].cpu_instructions,
76 "instruction count is monotonically increasing (+%" PRIu64 ")",
77 coalusage[1].cpu_instructions - coalusage[0].cpu_instructions);
78 T_EXPECT_GE(coalusage[1].cpu_cycles, coalusage[0].cpu_cycles,
79 "cycle count is monotonically increasing (+%" PRIu64 ")",
80 coalusage[1].cpu_cycles - coalusage[0].cpu_cycles);
81 }
82
83 T_DECL(coalition_resource_info_kernel_ptime_sane,
84 "ensure that coalition resource info for the kernel has a sane P-CPU time")
85 {
86 T_SETUPBEGIN;
87 struct proc_pidcoalitioninfo idinfo = {};
88 int ret = proc_pidinfo(0, PROC_PIDCOALITIONINFO, 0, &idinfo,
89 sizeof(idinfo));
90 T_ASSERT_POSIX_SUCCESS(ret, "proc_pidinfo(... PROC_PIDCOALITIONINFO ...)");
91
92 uint64_t resid = idinfo.coalition_id[COALITION_TYPE_RESOURCE];
93
94 struct coalition_resource_usage coalusage = {};
95 ret = coalition_info_resource_usage(resid, &coalusage,
96 sizeof(coalusage));
97 T_ASSERT_POSIX_SUCCESS(ret, "coalition_info_resource_usage()");
98 T_SETUPEND;
99
100 uint64_t non_ptime = coalusage.cpu_time - coalusage.cpu_ptime;
101 T_LOG("CPU time = %llu, P-CPU time = %llu (non-P-CPU time = %llu/%.2g%%)",
102 coalusage.cpu_time, coalusage.cpu_ptime, non_ptime,
103 (double)non_ptime / (double)coalusage.cpu_time * 100.0);
104 T_EXPECT_GT(coalusage.cpu_time, UINT64_C(0), "CPU time is non-zero");
105 T_EXPECT_GT(coalusage.cpu_time, coalusage.cpu_ptime,
106 "P-CPU time is <= CPU time");
107 }
108