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