@@ -43,35 +43,39 @@ static int cpuidle_get_count_percent(unsigned int id, double *percent,
static int cpuidle_start(void)
{
- int cpu, state;
clock_gettime(CLOCK_REALTIME, &start_time);
- for (cpu = 0; cpu < cpu_count; cpu++) {
- for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
- state++) {
- previous_count[cpu][state] =
- cpuidle_state_time(cpu, state);
- dprint("CPU %d - State: %d - Val: %llu\n",
- cpu, state, previous_count[cpu][state]);
- }
- }
return 0;
}
static int cpuidle_stop(void)
{
- int cpu, state;
struct timespec end_time;
+
clock_gettime(CLOCK_REALTIME, &end_time);
timediff = timespec_diff_us(start_time, end_time);
+ return 0;
+}
- for (cpu = 0; cpu < cpu_count; cpu++) {
- for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num;
- state++) {
- current_count[cpu][state] =
- cpuidle_state_time(cpu, state);
- dprint("CPU %d - State: %d - Val: %llu\n",
- cpu, state, previous_count[cpu][state]);
- }
+static int cpuidle_cpu_start(unsigned int cpu)
+{
+ int state;
+
+ for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num; state++) {
+ previous_count[cpu][state] = cpuidle_state_time(cpu, state);
+ dprint("CPU %d - State: %d - Val: %llu\n",
+ cpu, state, previous_count[cpu][state]);
+ }
+ return 0;
+}
+
+static int cpuidle_cpu_stop(unsigned int cpu)
+{
+ int state;
+
+ for (state = 0; state < cpuidle_sysfs_monitor.hw_states_num; state++) {
+ current_count[cpu][state] = cpuidle_state_time(cpu, state);
+ dprint("CPU %d - State: %d - Val: %llu\n",
+ cpu, state, current_count[cpu][state]);
}
return 0;
}
@@ -205,6 +209,8 @@ struct cpuidle_monitor cpuidle_sysfs_monitor = {
.hw_states = cpuidle_cstates,
.start = cpuidle_start,
.stop = cpuidle_stop,
+ .cpu_start = cpuidle_cpu_start,
+ .cpu_stop = cpuidle_cpu_stop,
.do_register = cpuidle_register,
.unregister = cpuidle_unregister,
.flags.needs_root = 0,
@@ -304,12 +304,29 @@ int fork_it(char **argv)
unsigned long long timediff;
pid_t child_pid;
struct timespec start, end;
+ int cpu;
child_pid = fork();
clock_gettime(CLOCK_REALTIME, &start);
- for (num = 0; num < avail_monitors; num++)
- monitors[num]->start();
+ /* Call global start callbacks first */
+ for (num = 0; num < avail_monitors; num++) {
+ if (monitors[num]->start)
+ monitors[num]->start();
+ }
+
+ /* Call per-CPU start callbacks */
+ for (num = 0; num < avail_monitors; num++) {
+ if (monitors[num]->cpu_start) {
+ for (cpu = 0; cpu < cpu_count; cpu++) {
+ if (monitors[num]->flags.per_cpu_schedule) {
+ if (bind_cpu(cpu))
+ continue;
+ }
+ monitors[num]->cpu_start(cpu);
+ }
+ }
+ }
if (!child_pid) {
/* child */
@@ -332,8 +349,25 @@ int fork_it(char **argv)
}
}
clock_gettime(CLOCK_REALTIME, &end);
- for (num = 0; num < avail_monitors; num++)
- monitors[num]->stop();
+
+ /* Call per-CPU stop callbacks */
+ for (num = 0; num < avail_monitors; num++) {
+ if (monitors[num]->cpu_stop) {
+ for (cpu = 0; cpu < cpu_count; cpu++) {
+ if (monitors[num]->flags.per_cpu_schedule) {
+ if (bind_cpu(cpu))
+ continue;
+ }
+ monitors[num]->cpu_stop(cpu);
+ }
+ }
+ }
+
+ /* Call global stop callbacks */
+ for (num = 0; num < avail_monitors; num++) {
+ if (monitors[num]->stop)
+ monitors[num]->stop();
+ }
timediff = timespec_diff_us(start, end);
if (WIFEXITED(status))
@@ -352,10 +386,25 @@ int do_interval_measure(int i)
for (cpu = 0; cpu < cpu_count; cpu++)
bind_cpu(cpu);
+ /* Call global start callbacks first */
for (num = 0; num < avail_monitors; num++) {
dprint("HW C-state residency monitor: %s - States: %d\n",
monitors[num]->name, monitors[num]->hw_states_num);
- monitors[num]->start();
+ if (monitors[num]->start)
+ monitors[num]->start();
+ }
+
+ /* Call per-CPU start callbacks */
+ for (num = 0; num < avail_monitors; num++) {
+ if (monitors[num]->cpu_start) {
+ for (cpu = 0; cpu < cpu_count; cpu++) {
+ if (monitors[num]->flags.per_cpu_schedule) {
+ if (bind_cpu(cpu))
+ continue;
+ }
+ monitors[num]->cpu_start(cpu);
+ }
+ }
}
sleep(i);
@@ -364,9 +413,24 @@ int do_interval_measure(int i)
for (cpu = 0; cpu < cpu_count; cpu++)
bind_cpu(cpu);
- for (num = 0; num < avail_monitors; num++)
- monitors[num]->stop();
+ /* Call per-CPU stop callbacks */
+ for (num = 0; num < avail_monitors; num++) {
+ if (monitors[num]->cpu_stop) {
+ for (cpu = 0; cpu < cpu_count; cpu++) {
+ if (monitors[num]->flags.per_cpu_schedule) {
+ if (bind_cpu(cpu))
+ continue;
+ }
+ monitors[num]->cpu_stop(cpu);
+ }
+ }
+ }
+ /* Call global stop callbacks */
+ for (num = 0; num < avail_monitors; num++) {
+ if (monitors[num]->stop)
+ monitors[num]->stop();
+ }
return 0;
}
@@ -57,6 +57,8 @@ struct cpuidle_monitor {
cstate_t *hw_states;
int (*start) (void);
int (*stop) (void);
+ int (*cpu_start) (unsigned int cpu);
+ int (*cpu_stop) (unsigned int cpu);
struct cpuidle_monitor* (*do_register) (void);
void (*unregister)(void);
unsigned int overflow_s;
@@ -224,27 +224,27 @@ static int mperf_get_count_freq(unsigned int id, unsigned long long *count,
static int mperf_start(void)
{
- int cpu;
-
- for (cpu = 0; cpu < cpu_count; cpu++) {
- clock_gettime(CLOCK_REALTIME, &time_start[cpu]);
- mperf_get_tsc(&tsc_at_measure_start[cpu]);
- mperf_init_stats(cpu);
- }
-
return 0;
}
static int mperf_stop(void)
{
- int cpu;
+ return 0;
+}
- for (cpu = 0; cpu < cpu_count; cpu++) {
- mperf_measure_stats(cpu);
- mperf_get_tsc(&tsc_at_measure_end[cpu]);
- clock_gettime(CLOCK_REALTIME, &time_end[cpu]);
- }
+static int mperf_cpu_start(unsigned int cpu)
+{
+ clock_gettime(CLOCK_REALTIME, &time_start[cpu]);
+ mperf_get_tsc(&tsc_at_measure_start[cpu]);
+ mperf_init_stats(cpu);
+ return 0;
+}
+static int mperf_cpu_stop(unsigned int cpu)
+{
+ mperf_measure_stats(cpu);
+ mperf_get_tsc(&tsc_at_measure_end[cpu]);
+ clock_gettime(CLOCK_REALTIME, &time_end[cpu]);
return 0;
}
@@ -373,6 +373,8 @@ struct cpuidle_monitor mperf_monitor = {
.hw_states = mperf_cstates,
.start = mperf_start,
.stop = mperf_stop,
+ .cpu_start = mperf_cpu_start,
+ .cpu_stop = mperf_cpu_stop,
.do_register = mperf_register,
.unregister = mperf_unregister,
.flags.needs_root = 1,
Move per-CPU logic from inside individual monitors to the main monitoring framework by adding cpu_start() and cpu_stop() callback functions to the cpuidle_monitor structure. This refactoring allows the framework to handle per-CPU scheduling and gives higher priority to fork_it operations as mentioned in the TODO. Individual monitors now only need to implement per-CPU initialization and cleanup logic without managing the CPU iteration themselves. Changes made: - Add cpu_start()/cpu_stop() function pointers to cpuidle_monitor struct - Update monitoring framework to call per-CPU callbacks for each CPU - Refactor cpuidle_sysfs and mperf monitors to use new callback pattern - Maintain backward compatibility for monitors without per-CPU callbacks This addresses the TODO item: "Add cpu_start()/cpu_stop() callbacks for monitor -> This is to move the per_cpu logic from inside the monitor to outside it." Signed-off-by: Rohan Lambture <rohanlambture13@gmail.com> --- .../utils/idle_monitor/cpuidle_sysfs.c | 44 ++++++----- .../utils/idle_monitor/cpupower-monitor.c | 78 +++++++++++++++++-- .../utils/idle_monitor/cpupower-monitor.h | 2 + .../utils/idle_monitor/mperf_monitor.c | 30 +++---- 4 files changed, 114 insertions(+), 40 deletions(-)