mirror of https://github.com/xzeldon/htop.git
Read CPU frequency from sysfs by default
Use the more portable sysfs node /sys/devices/system/cpu/cpuX/cpufreq/scaling_cur_freq to get the CPU frequency. In case of an error fall back to /proc/cpuinfo . Also use a fixed width of 4 for the frequency to avoid position jumps in case the frequency moves in the range 900-1100 MHz.
This commit is contained in:
parent
f4e1f4619f
commit
edf1b10d2c
|
@ -45,7 +45,7 @@ static void CPUMeter_updateValues(Meter* this, char* buffer, int size) {
|
|||
if (isnan(cpuFrequency)) {
|
||||
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A");
|
||||
} else {
|
||||
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%.0fMHz", cpuFrequency);
|
||||
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%4uMHz", (unsigned)cpuFrequency);
|
||||
}
|
||||
if (this->pl->settings->showCPUUsage) {
|
||||
xSnprintf(buffer, size, "%5.1f%% %s", percent, cpuFrequencyBuffer);
|
||||
|
|
|
@ -1145,53 +1145,69 @@ static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) {
|
|||
return period;
|
||||
}
|
||||
|
||||
static inline double LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) {
|
||||
ProcessList* pl = (ProcessList*) this;
|
||||
Settings* settings = pl->settings;
|
||||
static int scanCPUFreqencyFromSysCPUFreq(LinuxProcessList* this) {
|
||||
int cpus = this->super.cpuCount;
|
||||
int numCPUsWithFrequency = 0;
|
||||
unsigned long totalFrequency = 0;
|
||||
|
||||
for (int i = 0; i < cpus; ++i) {
|
||||
char pathBuffer[64];
|
||||
xSnprintf(pathBuffer, sizeof(pathBuffer), "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i);
|
||||
|
||||
FILE* file = fopen(pathBuffer, "r");
|
||||
if (!file)
|
||||
return -errno;
|
||||
|
||||
unsigned long frequency;
|
||||
if (fscanf(file, "%lu", &frequency) == 1) {
|
||||
/* convert kHz to MHz */
|
||||
frequency = frequency / 1000;
|
||||
this->cpus[i + 1].frequency = frequency;
|
||||
numCPUsWithFrequency++;
|
||||
totalFrequency += frequency;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
if (numCPUsWithFrequency > 0)
|
||||
this->cpus[0].frequency = (double)totalFrequency / numCPUsWithFrequency;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void scanCPUFreqencyFromCPUinfo(LinuxProcessList* this) {
|
||||
FILE* file = fopen(PROCCPUINFOFILE, "r");
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
int cpus = this->super.cpuCount;
|
||||
assert(cpus > 0);
|
||||
|
||||
for (int i = 0; i <= cpus; i++) {
|
||||
CPUData* cpuData = &(this->cpus[i]);
|
||||
cpuData->frequency = NAN;
|
||||
}
|
||||
|
||||
int numCPUsWithFrequency = 0;
|
||||
double totalFrequency = 0;
|
||||
|
||||
if (settings->showCPUFrequency) {
|
||||
FILE* file = fopen(PROCCPUINFOFILE, "r");
|
||||
if (file == NULL) {
|
||||
CRT_fatalError("Cannot open " PROCCPUINFOFILE);
|
||||
}
|
||||
|
||||
int cpuid = -1;
|
||||
double frequency;
|
||||
|
||||
while (!feof(file)) {
|
||||
double frequency;
|
||||
char buffer[PROC_LINE_LENGTH];
|
||||
char *ok = fgets(buffer, PROC_LINE_LENGTH, file);
|
||||
if (!ok) break;
|
||||
|
||||
if (fgets(buffer, PROC_LINE_LENGTH, file) == NULL)
|
||||
break;
|
||||
|
||||
if (
|
||||
(sscanf(buffer, "processor : %d", &cpuid) == 1) ||
|
||||
(sscanf(buffer, "processor: %d", &cpuid) == 1)
|
||||
) {
|
||||
if (cpuid < 0 || cpuid > (cpus - 1)) {
|
||||
char tmpbuffer[64];
|
||||
xSnprintf(tmpbuffer, sizeof(tmpbuffer), PROCCPUINFOFILE " contains out-of-range CPU number %d", cpuid);
|
||||
CRT_fatalError(tmpbuffer);
|
||||
}
|
||||
continue;
|
||||
} else if (
|
||||
(sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) ||
|
||||
(sscanf(buffer, "cpu MHz: %lf", &frequency) == 1)
|
||||
) {
|
||||
if (cpuid < 0 || cpuid > (cpus - 1)) {
|
||||
CRT_fatalError(PROCCPUINFOFILE " is malformed: cpu MHz line without corresponding processor line");
|
||||
}
|
||||
if (cpuid < 0 || cpuid > (cpus - 1))
|
||||
continue;
|
||||
|
||||
int cpu = cpuid + 1;
|
||||
CPUData* cpuData = &(this->cpus[cpu]);
|
||||
CPUData* cpuData = &(this->cpus[cpuid + 1]);
|
||||
/* do not override sysfs data */
|
||||
if (isnan(cpuData->frequency))
|
||||
cpuData->frequency = frequency;
|
||||
numCPUsWithFrequency++;
|
||||
totalFrequency += frequency;
|
||||
|
@ -1201,22 +1217,32 @@ static inline double LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) {
|
|||
}
|
||||
fclose(file);
|
||||
|
||||
if (numCPUsWithFrequency > 0) {
|
||||
if (numCPUsWithFrequency > 0)
|
||||
this->cpus[0].frequency = totalFrequency / numCPUsWithFrequency;
|
||||
}
|
||||
}
|
||||
|
||||
double period = (double)this->cpus[0].totalPeriod / cpus;
|
||||
return period;
|
||||
static void LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) {
|
||||
int cpus = this->super.cpuCount;
|
||||
assert(cpus > 0);
|
||||
|
||||
for (int i = 0; i <= cpus; i++)
|
||||
this->cpus[i].frequency = NAN;
|
||||
|
||||
if (scanCPUFreqencyFromSysCPUFreq(this) == 0)
|
||||
return;
|
||||
|
||||
scanCPUFreqencyFromCPUinfo(this);
|
||||
}
|
||||
|
||||
void ProcessList_goThroughEntries(ProcessList* super) {
|
||||
LinuxProcessList* this = (LinuxProcessList*) super;
|
||||
const Settings* settings = super->settings;
|
||||
|
||||
LinuxProcessList_scanMemoryInfo(super);
|
||||
LinuxProcessList_scanZfsArcstats(this);
|
||||
double period = LinuxProcessList_scanCPUTime(this);
|
||||
|
||||
if (settings->showCPUFrequency)
|
||||
LinuxProcessList_scanCPUFrequency(this);
|
||||
|
||||
struct timeval tv;
|
||||
|
|
Loading…
Reference in New Issue