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