tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
Source file repositories/reference/linux-study-clean/tools/power/cpupower/utils/idle_monitor/mperf_monitor.c
File Facts
- System
- Linux kernel
- Corpus path
tools/power/cpupower/utils/idle_monitor/mperf_monitor.c- Extension
.c- Size
- 10703 bytes
- Lines
- 383
- Domain
- Support Tooling And Documentation
- Bucket
- tools
- Inferred role
- Support Tooling And Documentation: implementation source
- Status
- source implementation candidate
Why This File Exists
Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
stdio.hstdint.hstdlib.hstring.hlimits.hcpufreq.hhelpers/helpers.hidle_monitor/cpupower-monitor.h
Detected Declarations
enum mperf_idenum MAX_FREQ_MODEfunction mperf_get_tscfunction get_aperf_mperffunction read_msrfunction mperf_init_statsfunction mperf_measure_statsfunction mperf_get_count_percentfunction mperf_get_count_freqfunction mperf_startfunction mperf_stopfunction P0function mperf_unregister
Annotated Snippet
if (ret != 0) {
dprint("TSC read 0x%x failed - assume TSC working\n",
MSR_AMD_HWCR);
return 0;
} else if (1 & (hwcr >> 24)) {
max_freq_mode = MAX_FREQ_TSC_REF;
return 0;
} else { /* Use sysfs max frequency if available */ }
} else if (cpupower_cpu_info.vendor == X86_VENDOR_INTEL) {
/*
* On Intel we assume mperf (in C0) is ticking at same
* rate than TSC
*/
max_freq_mode = MAX_FREQ_TSC_REF;
return 0;
}
use_sysfs:
if (cpufreq_get_hardware_limits(0, &min, &max_frequency)) {
dprint("Cannot retrieve max freq from cpufreq kernel "
"subsystem\n");
return -1;
}
max_freq_mode = MAX_FREQ_SYSFS;
max_frequency /= 1000; /* Default automatically to MHz value */
return 0;
}
/*
* This monitor provides:
*
* 1) Average frequency a CPU resided in
* This always works if the CPU has aperf/mperf capabilities
*
* 2) C0 and Cx (any sleep state) time a CPU resided in
* Works if mperf timer stops ticking in sleep states which
* seem to be the case on all current HW.
* Both is directly retrieved from HW registers and is independent
* from kernel statistics.
*/
struct cpuidle_monitor mperf_monitor;
struct cpuidle_monitor *mperf_register(void)
{
if (!(cpupower_cpu_info.caps & CPUPOWER_CAP_APERF))
return NULL;
if (init_maxfreq_mode())
return NULL;
if (cpupower_cpu_info.vendor == X86_VENDOR_AMD)
mperf_monitor.flags.per_cpu_schedule = 1;
/* Free this at program termination */
is_valid = calloc(cpu_count, sizeof(int));
mperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
aperf_previous_count = calloc(cpu_count, sizeof(unsigned long long));
mperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
aperf_current_count = calloc(cpu_count, sizeof(unsigned long long));
tsc_at_measure_start = calloc(cpu_count, sizeof(unsigned long long));
tsc_at_measure_end = calloc(cpu_count, sizeof(unsigned long long));
time_start = calloc(cpu_count, sizeof(struct timespec));
time_end = calloc(cpu_count, sizeof(struct timespec));
mperf_monitor.name_len = strlen(mperf_monitor.name);
return &mperf_monitor;
}
void mperf_unregister(void)
{
free(mperf_previous_count);
free(aperf_previous_count);
free(mperf_current_count);
free(aperf_current_count);
free(tsc_at_measure_start);
free(tsc_at_measure_end);
free(time_start);
free(time_end);
free(is_valid);
}
struct cpuidle_monitor mperf_monitor = {
.name = "Mperf",
.hw_states_num = MPERF_CSTATE_COUNT,
.hw_states = mperf_cstates,
.start = mperf_start,
.stop = mperf_stop,
.do_register = mperf_register,
.unregister = mperf_unregister,
.flags.needs_root = 1,
.overflow_s = 922000000 /* 922337203 seconds TSC overflow
at 20GHz */
};
Annotation
- Immediate include surface: `stdio.h`, `stdint.h`, `stdlib.h`, `string.h`, `limits.h`, `cpufreq.h`, `helpers/helpers.h`, `idle_monitor/cpupower-monitor.h`.
- Detected declarations: `enum mperf_id`, `enum MAX_FREQ_MODE`, `function mperf_get_tsc`, `function get_aperf_mperf`, `function read_msr`, `function mperf_init_stats`, `function mperf_measure_stats`, `function mperf_get_count_percent`, `function mperf_get_count_freq`, `function mperf_start`.
- Atlas domain: Support Tooling And Documentation / tools.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.