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