xref: /xnu-12377.81.4/tests/recount/coalition_info_tests.c (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
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 // Don't rely on FastSim's CPMU to produce reliable data.
42 // In particular, S3_2_C15_C1_0 (instructions retired) seems to be zero on some devices (rdar://143157256).
43 static void
skip_if_fastsim(void)44 skip_if_fastsim(void)
45 {
46 	char buffer[64] = "";
47 	size_t buffer_size = sizeof(buffer);
48 
49 	int r = sysctlbyname("hw.targettype", buffer, &buffer_size, NULL, 0);
50 	if (r < 0) {
51 		T_WITH_ERRNO;
52 		T_SKIP("could not find \"hw.targettype\" sysctl");
53 	}
54 
55 	if (strstr(buffer, "sim") != NULL) {
56 		T_SKIP("CPU performance counters are unreliable on FastSim");
57 	}
58 }
59 
60 T_DECL(coalition_resource_info_counters,
61     "ensure that coalition resource info produces valid counter data", T_META_TAG_VM_NOT_ELIGIBLE)
62 {
63 	skip_if_monotonic_unsupported();
64 	skip_if_fastsim();
65 
66 	T_SETUPBEGIN;
67 
68 	struct proc_pidcoalitioninfo idinfo = {};
69 	int ret = proc_pidinfo(getpid(), PROC_PIDCOALITIONINFO, 0,
70 	    &idinfo, sizeof(idinfo));
71 	T_ASSERT_POSIX_SUCCESS(ret, "proc_pidinfo(... PROC_PIDCOALITIONINFO ...)");
72 
73 	uint64_t resid = idinfo.coalition_id[COALITION_TYPE_RESOURCE];
74 
75 	struct coalition_resource_usage coalusage[2] = {};
76 	ret = coalition_info_resource_usage(resid, &coalusage[0],
77 	    sizeof(coalusage[0]));
78 	T_ASSERT_POSIX_SUCCESS(ret, "coalition_info_resource_usage()");
79 
80 	T_SETUPEND;
81 
82 	T_EXPECT_GT(coalusage[0].cpu_instructions, UINT64_C(0),
83 	    "instruction count is non-zero");
84 	T_EXPECT_GT(coalusage[0].cpu_cycles, UINT64_C(0),
85 	    "cycle count is non-zero");
86 
87 	sleep(1);
88 
89 	T_SETUPBEGIN;
90 	ret = coalition_info_resource_usage(resid, &coalusage[1],
91 	    sizeof(coalusage[1]));
92 	T_ASSERT_POSIX_SUCCESS(ret, "coalition_info_resource_usage()");
93 	T_SETUPEND;
94 
95 	T_EXPECT_GE(coalusage[1].cpu_instructions, coalusage[0].cpu_instructions,
96 	    "instruction count is monotonically increasing (+%" PRIu64 ")",
97 	    coalusage[1].cpu_instructions - coalusage[0].cpu_instructions);
98 	T_EXPECT_GE(coalusage[1].cpu_cycles, coalusage[0].cpu_cycles,
99 	    "cycle count is monotonically increasing (+%" PRIu64 ")",
100 	    coalusage[1].cpu_cycles - coalusage[0].cpu_cycles);
101 }
102 
103 T_DECL(coalition_resource_info_kernel_ptime_sane,
104     "ensure that coalition resource info for the kernel has a sane P-CPU time", T_META_TAG_VM_PREFERRED)
105 {
106 	T_SETUPBEGIN;
107 	struct proc_pidcoalitioninfo idinfo = {};
108 	int ret = proc_pidinfo(0, PROC_PIDCOALITIONINFO, 0, &idinfo,
109 	    sizeof(idinfo));
110 	T_ASSERT_POSIX_SUCCESS(ret, "proc_pidinfo(... PROC_PIDCOALITIONINFO ...)");
111 
112 	uint64_t resid = idinfo.coalition_id[COALITION_TYPE_RESOURCE];
113 
114 	struct coalition_resource_usage coalusage = {};
115 	ret = coalition_info_resource_usage(resid, &coalusage,
116 	    sizeof(coalusage));
117 	T_ASSERT_POSIX_SUCCESS(ret, "coalition_info_resource_usage()");
118 	T_SETUPEND;
119 
120 	uint64_t non_ptime = coalusage.cpu_time - coalusage.cpu_ptime;
121 	T_LOG("CPU time = %llu, P-CPU time = %llu (non-P-CPU time = %llu/%.2g%%)",
122 	    coalusage.cpu_time, coalusage.cpu_ptime, non_ptime,
123 	    (double)non_ptime / (double)coalusage.cpu_time * 100.0);
124 	T_EXPECT_GT(coalusage.cpu_time, UINT64_C(0), "CPU time is non-zero");
125 	T_EXPECT_GT(coalusage.cpu_time, coalusage.cpu_ptime,
126 	    "P-CPU time is <= CPU time");
127 }
128