xref: /xnu-8792.81.2/tests/recount/thread_selfcounts_tests.c (revision 19c3b8c28c31cb8130e034cfb5df6bf9ba342d90)
1*19c3b8c2SApple OSS Distributions // Copyright (c) 2021 Apple Inc.  All rights reserved.
2*19c3b8c2SApple OSS Distributions 
3*19c3b8c2SApple OSS Distributions #include <darwintest.h>
4*19c3b8c2SApple OSS Distributions #include <stdlib.h>
5*19c3b8c2SApple OSS Distributions #include <sys/resource_private.h>
6*19c3b8c2SApple OSS Distributions #include <sys/sysctl.h>
7*19c3b8c2SApple OSS Distributions 
8*19c3b8c2SApple OSS Distributions #include "test_utils.h"
9*19c3b8c2SApple OSS Distributions #include "recount_test_utils.h"
10*19c3b8c2SApple OSS Distributions 
11*19c3b8c2SApple OSS Distributions T_GLOBAL_META(
12*19c3b8c2SApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
13*19c3b8c2SApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("RM"),
14*19c3b8c2SApple OSS Distributions     T_META_OWNER("mwidmann"),
15*19c3b8c2SApple OSS Distributions     T_META_CHECK_LEAKS(false));
16*19c3b8c2SApple OSS Distributions 
17*19c3b8c2SApple OSS Distributions static void
_check_cpi(struct thsc_cpi * before,struct thsc_cpi * after,const char * name)18*19c3b8c2SApple OSS Distributions _check_cpi(struct thsc_cpi *before, struct thsc_cpi *after, const char *name)
19*19c3b8c2SApple OSS Distributions {
20*19c3b8c2SApple OSS Distributions 	T_QUIET;
21*19c3b8c2SApple OSS Distributions 	T_EXPECT_GT(before->tcpi_instructions, UINT64_C(0),
22*19c3b8c2SApple OSS Distributions 	    "%s: instructions non-zero", name);
23*19c3b8c2SApple OSS Distributions 	T_QUIET;
24*19c3b8c2SApple OSS Distributions 	T_EXPECT_GT(before->tcpi_cycles, UINT64_C(0), "%s: cycles non-zero",
25*19c3b8c2SApple OSS Distributions 	    name);
26*19c3b8c2SApple OSS Distributions 
27*19c3b8c2SApple OSS Distributions 	T_EXPECT_GT(after->tcpi_instructions, before->tcpi_instructions,
28*19c3b8c2SApple OSS Distributions 	    "%s: instructions monotonically-increasing", name);
29*19c3b8c2SApple OSS Distributions 	T_EXPECT_GT(after->tcpi_cycles, before->tcpi_cycles,
30*19c3b8c2SApple OSS Distributions 	    "%s: cycles monotonically-increasing", name);
31*19c3b8c2SApple OSS Distributions }
32*19c3b8c2SApple OSS Distributions 
33*19c3b8c2SApple OSS Distributions static struct thsc_cpi
_remove_time_from_cpi(struct thsc_time_cpi * time_cpi)34*19c3b8c2SApple OSS Distributions _remove_time_from_cpi(struct thsc_time_cpi *time_cpi)
35*19c3b8c2SApple OSS Distributions {
36*19c3b8c2SApple OSS Distributions 	return (struct thsc_cpi){
37*19c3b8c2SApple OSS Distributions 		.tcpi_instructions = time_cpi->ttci_instructions,
38*19c3b8c2SApple OSS Distributions 		.tcpi_cycles = time_cpi->ttci_cycles,
39*19c3b8c2SApple OSS Distributions 	};
40*19c3b8c2SApple OSS Distributions }
41*19c3b8c2SApple OSS Distributions 
42*19c3b8c2SApple OSS Distributions static void
_check_time_cpi(struct thsc_time_cpi * before,struct thsc_time_cpi * after,const char * name)43*19c3b8c2SApple OSS Distributions _check_time_cpi(struct thsc_time_cpi *before, struct thsc_time_cpi *after,
44*19c3b8c2SApple OSS Distributions     const char *name)
45*19c3b8c2SApple OSS Distributions {
46*19c3b8c2SApple OSS Distributions 	struct thsc_cpi before_cpi = _remove_time_from_cpi(before);
47*19c3b8c2SApple OSS Distributions 	struct thsc_cpi after_cpi = _remove_time_from_cpi(after);
48*19c3b8c2SApple OSS Distributions 	_check_cpi(&before_cpi, &after_cpi, name);
49*19c3b8c2SApple OSS Distributions 
50*19c3b8c2SApple OSS Distributions 	T_EXPECT_GT(after->ttci_user_time_mach, before->ttci_user_time_mach,
51*19c3b8c2SApple OSS Distributions 			"%s: user time monotonically-increasing", name);
52*19c3b8c2SApple OSS Distributions 
53*19c3b8c2SApple OSS Distributions 	if (has_user_system_times()) {
54*19c3b8c2SApple OSS Distributions 		T_EXPECT_GT(after->ttci_system_time_mach, before->ttci_system_time_mach,
55*19c3b8c2SApple OSS Distributions 				"%s: system time monotonically-increasing", name);
56*19c3b8c2SApple OSS Distributions 	}
57*19c3b8c2SApple OSS Distributions }
58*19c3b8c2SApple OSS Distributions 
59*19c3b8c2SApple OSS Distributions static struct thsc_time_cpi
_remove_energy_from_cpi(struct thsc_time_energy_cpi * energy_cpi)60*19c3b8c2SApple OSS Distributions _remove_energy_from_cpi(struct thsc_time_energy_cpi *energy_cpi)
61*19c3b8c2SApple OSS Distributions {
62*19c3b8c2SApple OSS Distributions 	return (struct thsc_time_cpi){
63*19c3b8c2SApple OSS Distributions 		.ttci_instructions = energy_cpi->ttec_instructions,
64*19c3b8c2SApple OSS Distributions 		.ttci_cycles = energy_cpi->ttec_cycles,
65*19c3b8c2SApple OSS Distributions 		.ttci_system_time_mach = energy_cpi->ttec_system_time_mach,
66*19c3b8c2SApple OSS Distributions 		.ttci_user_time_mach = energy_cpi->ttec_user_time_mach,
67*19c3b8c2SApple OSS Distributions 	};
68*19c3b8c2SApple OSS Distributions }
69*19c3b8c2SApple OSS Distributions 
70*19c3b8c2SApple OSS Distributions static void
_check_usage(struct thsc_time_energy_cpi * before,struct thsc_time_energy_cpi * after,const char * name)71*19c3b8c2SApple OSS Distributions _check_usage(struct thsc_time_energy_cpi *before,
72*19c3b8c2SApple OSS Distributions     struct thsc_time_energy_cpi *after, const char *name)
73*19c3b8c2SApple OSS Distributions {
74*19c3b8c2SApple OSS Distributions 	struct thsc_time_cpi before_time = _remove_energy_from_cpi(before);
75*19c3b8c2SApple OSS Distributions 	struct thsc_time_cpi after_time = _remove_energy_from_cpi(after);
76*19c3b8c2SApple OSS Distributions 	_check_time_cpi(&before_time, &after_time, name);
77*19c3b8c2SApple OSS Distributions 
78*19c3b8c2SApple OSS Distributions 	if (has_energy()) {
79*19c3b8c2SApple OSS Distributions 		T_EXPECT_GT(after->ttec_energy_nj, UINT64_C(0),
80*19c3b8c2SApple OSS Distributions 				"%s: energy monotonically-increasing", name);
81*19c3b8c2SApple OSS Distributions 	}
82*19c3b8c2SApple OSS Distributions }
83*19c3b8c2SApple OSS Distributions 
84*19c3b8c2SApple OSS Distributions T_DECL(thread_selfcounts_cpi_sanity, "check the current thread's CPI",
85*19c3b8c2SApple OSS Distributions     REQUIRE_RECOUNT_PMCS)
86*19c3b8c2SApple OSS Distributions {
87*19c3b8c2SApple OSS Distributions 	int err;
88*19c3b8c2SApple OSS Distributions 	struct thsc_cpi counts[2] = { 0 };
89*19c3b8c2SApple OSS Distributions 
90*19c3b8c2SApple OSS Distributions 	err = thread_selfcounts(THSC_CPI, &counts[0], sizeof(counts[0]));
91*19c3b8c2SApple OSS Distributions 	T_ASSERT_POSIX_ZERO(err, "thread_selfcounts(THSC_CPI, ...)");
92*19c3b8c2SApple OSS Distributions 	err = thread_selfcounts(THSC_CPI, &counts[1], sizeof(counts[1]));
93*19c3b8c2SApple OSS Distributions 	T_ASSERT_POSIX_ZERO(err, "thread_selfcounts(THSC_CPI, ...)");
94*19c3b8c2SApple OSS Distributions 
95*19c3b8c2SApple OSS Distributions 	_check_cpi(&counts[0], &counts[1], "anywhere");
96*19c3b8c2SApple OSS Distributions }
97*19c3b8c2SApple OSS Distributions 
98*19c3b8c2SApple OSS Distributions T_DECL(thread_selfcounts_perf_level_sanity,
99*19c3b8c2SApple OSS Distributions     "check per-perf level time, energy, and CPI",
100*19c3b8c2SApple OSS Distributions     REQUIRE_RECOUNT_PMCS,
101*19c3b8c2SApple OSS Distributions     REQUIRE_MULTIPLE_PERF_LEVELS,
102*19c3b8c2SApple OSS Distributions     SET_THREAD_BIND_BOOTARG,
103*19c3b8c2SApple OSS Distributions     T_META_ASROOT(true))
104*19c3b8c2SApple OSS Distributions {
105*19c3b8c2SApple OSS Distributions 	unsigned int level_count = perf_level_count();
106*19c3b8c2SApple OSS Distributions 	struct thsc_time_energy_cpi *before = calloc(level_count, sizeof(*before));
107*19c3b8c2SApple OSS Distributions 	struct thsc_time_energy_cpi *after = calloc(level_count, sizeof(*after));
108*19c3b8c2SApple OSS Distributions 
109*19c3b8c2SApple OSS Distributions 	run_on_all_perf_levels();
110*19c3b8c2SApple OSS Distributions 
111*19c3b8c2SApple OSS Distributions 	int err = thread_selfcounts(THSC_TIME_ENERGY_CPI_PER_PERF_LEVEL, before,
112*19c3b8c2SApple OSS Distributions 			level_count * sizeof(*before));
113*19c3b8c2SApple OSS Distributions 	T_ASSERT_POSIX_ZERO(err,
114*19c3b8c2SApple OSS Distributions 			"thread_selfcounts(THSC_TIME_ENERGY_CPI_PER_PERF_LEVEL, ...)");
115*19c3b8c2SApple OSS Distributions 
116*19c3b8c2SApple OSS Distributions 	run_on_all_perf_levels();
117*19c3b8c2SApple OSS Distributions 
118*19c3b8c2SApple OSS Distributions 	err = thread_selfcounts(THSC_TIME_ENERGY_CPI_PER_PERF_LEVEL, after,
119*19c3b8c2SApple OSS Distributions 			level_count * sizeof(*after));
120*19c3b8c2SApple OSS Distributions 	T_ASSERT_POSIX_ZERO(err,
121*19c3b8c2SApple OSS Distributions 			"thread_selfcounts(THSC_TIME_ENERGY_CPI_PER_PERF_LEVEL, ...)");
122*19c3b8c2SApple OSS Distributions 
123*19c3b8c2SApple OSS Distributions 	for (unsigned int i = 0; i < level_count; i++) {
124*19c3b8c2SApple OSS Distributions 		_check_usage(&before[i], &after[i], perf_level_name(i));
125*19c3b8c2SApple OSS Distributions 	}
126*19c3b8c2SApple OSS Distributions 
127*19c3b8c2SApple OSS Distributions 	free(before);
128*19c3b8c2SApple OSS Distributions 	free(after);
129*19c3b8c2SApple OSS Distributions }
130*19c3b8c2SApple OSS Distributions 
131*19c3b8c2SApple OSS Distributions T_DECL(thread_selfcounts_cpi_perf,
132*19c3b8c2SApple OSS Distributions     "test the overhead of thread_selfcounts(2) THSC_CPI", T_META_TAG_PERF,
133*19c3b8c2SApple OSS Distributions     REQUIRE_RECOUNT_PMCS)
134*19c3b8c2SApple OSS Distributions {
135*19c3b8c2SApple OSS Distributions 	struct thsc_cpi counts[2];
136*19c3b8c2SApple OSS Distributions 
137*19c3b8c2SApple OSS Distributions 	T_SETUPBEGIN;
138*19c3b8c2SApple OSS Distributions 	dt_stat_t instrs = dt_stat_create("thread_selfcounts_cpi_instrs",
139*19c3b8c2SApple OSS Distributions 			"instructions");
140*19c3b8c2SApple OSS Distributions 	dt_stat_t cycles = dt_stat_create("thread_selfcounts_cpi_cycles", "cycles");
141*19c3b8c2SApple OSS Distributions 	T_SETUPEND;
142*19c3b8c2SApple OSS Distributions 
143*19c3b8c2SApple OSS Distributions 	while (!dt_stat_stable(instrs) || !dt_stat_stable(cycles)) {
144*19c3b8c2SApple OSS Distributions 		int r1 = thread_selfcounts(THSC_CPI, &counts[0], sizeof(counts[0]));
145*19c3b8c2SApple OSS Distributions 		int r2 = thread_selfcounts(THSC_CPI, &counts[1], sizeof(counts[1]));
146*19c3b8c2SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(r1, "thread_selfcounts(THSC_CPI, ...)");
147*19c3b8c2SApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_ZERO(r2, "thread_selfcounts(THSC_CPI, ...)");
148*19c3b8c2SApple OSS Distributions 
149*19c3b8c2SApple OSS Distributions 		dt_stat_add(instrs, counts[1].tcpi_instructions -
150*19c3b8c2SApple OSS Distributions 				counts[0].tcpi_instructions);
151*19c3b8c2SApple OSS Distributions 		dt_stat_add(cycles, counts[1].tcpi_cycles - counts[0].tcpi_cycles);
152*19c3b8c2SApple OSS Distributions 	}
153*19c3b8c2SApple OSS Distributions 
154*19c3b8c2SApple OSS Distributions 	dt_stat_finalize(instrs);
155*19c3b8c2SApple OSS Distributions 	dt_stat_finalize(cycles);
156*19c3b8c2SApple OSS Distributions }
157