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)) {
|
if (isnan(cpuFrequency)) {
|
||||||
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A");
|
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A");
|
||||||
} else {
|
} else {
|
||||||
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%.0fMHz", cpuFrequency);
|
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%4uMHz", (unsigned)cpuFrequency);
|
||||||
}
|
}
|
||||||
if (this->pl->settings->showCPUUsage) {
|
if (this->pl->settings->showCPUUsage) {
|
||||||
xSnprintf(buffer, size, "%5.1f%% %s", percent, cpuFrequencyBuffer);
|
xSnprintf(buffer, size, "%5.1f%% %s", percent, cpuFrequencyBuffer);
|
||||||
|
|
|
@ -1145,79 +1145,105 @@ static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) {
|
||||||
return period;
|
return period;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline double LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) {
|
static int scanCPUFreqencyFromSysCPUFreq(LinuxProcessList* this) {
|
||||||
ProcessList* pl = (ProcessList*) this;
|
int cpus = this->super.cpuCount;
|
||||||
Settings* settings = pl->settings;
|
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;
|
||||||
|
int numCPUsWithFrequency = 0;
|
||||||
|
double totalFrequency = 0;
|
||||||
|
int cpuid = -1;
|
||||||
|
|
||||||
|
while (!feof(file)) {
|
||||||
|
double frequency;
|
||||||
|
char buffer[PROC_LINE_LENGTH];
|
||||||
|
|
||||||
|
if (fgets(buffer, PROC_LINE_LENGTH, file) == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (
|
||||||
|
(sscanf(buffer, "processor : %d", &cpuid) == 1) ||
|
||||||
|
(sscanf(buffer, "processor: %d", &cpuid) == 1)
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
} else if (
|
||||||
|
(sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) ||
|
||||||
|
(sscanf(buffer, "cpu MHz: %lf", &frequency) == 1)
|
||||||
|
) {
|
||||||
|
if (cpuid < 0 || cpuid > (cpus - 1))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CPUData* cpuData = &(this->cpus[cpuid + 1]);
|
||||||
|
/* do not override sysfs data */
|
||||||
|
if (isnan(cpuData->frequency))
|
||||||
|
cpuData->frequency = frequency;
|
||||||
|
numCPUsWithFrequency++;
|
||||||
|
totalFrequency += frequency;
|
||||||
|
} else if (buffer[0] == '\n') {
|
||||||
|
cpuid = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
if (numCPUsWithFrequency > 0)
|
||||||
|
this->cpus[0].frequency = totalFrequency / numCPUsWithFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) {
|
||||||
int cpus = this->super.cpuCount;
|
int cpus = this->super.cpuCount;
|
||||||
assert(cpus > 0);
|
assert(cpus > 0);
|
||||||
|
|
||||||
for (int i = 0; i <= cpus; i++) {
|
for (int i = 0; i <= cpus; i++)
|
||||||
CPUData* cpuData = &(this->cpus[i]);
|
this->cpus[i].frequency = NAN;
|
||||||
cpuData->frequency = NAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
int numCPUsWithFrequency = 0;
|
if (scanCPUFreqencyFromSysCPUFreq(this) == 0)
|
||||||
double totalFrequency = 0;
|
return;
|
||||||
|
|
||||||
if (settings->showCPUFrequency) {
|
scanCPUFreqencyFromCPUinfo(this);
|
||||||
FILE* file = fopen(PROCCPUINFOFILE, "r");
|
|
||||||
if (file == NULL) {
|
|
||||||
CRT_fatalError("Cannot open " PROCCPUINFOFILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cpuid = -1;
|
|
||||||
double frequency;
|
|
||||||
while (!feof(file)) {
|
|
||||||
char buffer[PROC_LINE_LENGTH];
|
|
||||||
char *ok = fgets(buffer, PROC_LINE_LENGTH, file);
|
|
||||||
if (!ok) 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);
|
|
||||||
}
|
|
||||||
} 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
int cpu = cpuid + 1;
|
|
||||||
CPUData* cpuData = &(this->cpus[cpu]);
|
|
||||||
cpuData->frequency = frequency;
|
|
||||||
numCPUsWithFrequency++;
|
|
||||||
totalFrequency += frequency;
|
|
||||||
} else if (buffer[0] == '\n') {
|
|
||||||
cpuid = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
if (numCPUsWithFrequency > 0) {
|
|
||||||
this->cpus[0].frequency = totalFrequency / numCPUsWithFrequency;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double period = (double)this->cpus[0].totalPeriod / cpus;
|
|
||||||
return period;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessList_goThroughEntries(ProcessList* super) {
|
void ProcessList_goThroughEntries(ProcessList* super) {
|
||||||
LinuxProcessList* this = (LinuxProcessList*) super;
|
LinuxProcessList* this = (LinuxProcessList*) super;
|
||||||
|
const Settings* settings = super->settings;
|
||||||
|
|
||||||
LinuxProcessList_scanMemoryInfo(super);
|
LinuxProcessList_scanMemoryInfo(super);
|
||||||
LinuxProcessList_scanZfsArcstats(this);
|
LinuxProcessList_scanZfsArcstats(this);
|
||||||
double period = LinuxProcessList_scanCPUTime(this);
|
double period = LinuxProcessList_scanCPUTime(this);
|
||||||
|
|
||||||
LinuxProcessList_scanCPUFrequency(this);
|
if (settings->showCPUFrequency)
|
||||||
|
LinuxProcessList_scanCPUFrequency(this);
|
||||||
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
|
|
Loading…
Reference in New Issue