mirror of https://github.com/xzeldon/htop.git
Merge branch 'hishamhm-pull-932'
This commit is contained in:
commit
6b443c5da9
28
CPUMeter.c
28
CPUMeter.c
|
@ -28,7 +28,8 @@ typedef enum {
|
||||||
CPU_METER_STEAL = 5,
|
CPU_METER_STEAL = 5,
|
||||||
CPU_METER_GUEST = 6,
|
CPU_METER_GUEST = 6,
|
||||||
CPU_METER_IOWAIT = 7,
|
CPU_METER_IOWAIT = 7,
|
||||||
CPU_METER_ITEMCOUNT = 8, // number of entries in this enum
|
CPU_METER_FREQUENCY = 8,
|
||||||
|
CPU_METER_ITEMCOUNT = 9, // number of entries in this enum
|
||||||
} CPUMeterValues;
|
} CPUMeterValues;
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
@ -63,7 +64,30 @@ static void CPUMeter_updateValues(Meter* this, char* buffer, int size) {
|
||||||
}
|
}
|
||||||
memset(this->values, 0, sizeof(double) * CPU_METER_ITEMCOUNT);
|
memset(this->values, 0, sizeof(double) * CPU_METER_ITEMCOUNT);
|
||||||
double percent = Platform_setCPUValues(this, cpu);
|
double percent = Platform_setCPUValues(this, cpu);
|
||||||
xSnprintf(buffer, size, "%5.1f%%", percent);
|
if (this->pl->settings->showCPUFrequency) {
|
||||||
|
/* Initial frequency is in MHz. Emit it as GHz if it's larger than 1000MHz */
|
||||||
|
double cpuFrequency = this->values[CPU_METER_FREQUENCY];
|
||||||
|
char unit = 'M';
|
||||||
|
char cpuFrequencyBuffer[16];
|
||||||
|
if (cpuFrequency < 0) {
|
||||||
|
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "N/A");
|
||||||
|
} else {
|
||||||
|
if (cpuFrequency > 1000) {
|
||||||
|
cpuFrequency /= 1000;
|
||||||
|
unit = 'G';
|
||||||
|
}
|
||||||
|
xSnprintf(cpuFrequencyBuffer, sizeof(cpuFrequencyBuffer), "%.3f%cHz", cpuFrequency, unit);
|
||||||
|
}
|
||||||
|
if (this->pl->settings->showCPUUsage) {
|
||||||
|
xSnprintf(buffer, size, "%5.1f%% %s", percent, cpuFrequencyBuffer);
|
||||||
|
} else {
|
||||||
|
xSnprintf(buffer, size, "%s", cpuFrequencyBuffer);
|
||||||
|
}
|
||||||
|
} else if (this->pl->settings->showCPUUsage) {
|
||||||
|
xSnprintf(buffer, size, "%5.1f%%", percent);
|
||||||
|
} else if (size > 0) {
|
||||||
|
buffer[0] = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CPUMeter_display(Object* cast, RichString* out) {
|
static void CPUMeter_display(Object* cast, RichString* out) {
|
||||||
|
|
|
@ -20,7 +20,8 @@ typedef enum {
|
||||||
CPU_METER_STEAL = 5,
|
CPU_METER_STEAL = 5,
|
||||||
CPU_METER_GUEST = 6,
|
CPU_METER_GUEST = 6,
|
||||||
CPU_METER_IOWAIT = 7,
|
CPU_METER_IOWAIT = 7,
|
||||||
CPU_METER_ITEMCOUNT = 8, // number of entries in this enum
|
CPU_METER_FREQUENCY = 8,
|
||||||
|
CPU_METER_ITEMCOUNT = 9, // number of entries in this enum
|
||||||
} CPUMeterValues;
|
} CPUMeterValues;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,8 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
|
||||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Count CPUs from 0 instead of 1"), &(settings->countCPUsFromZero)));
|
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Count CPUs from 0 instead of 1"), &(settings->countCPUsFromZero)));
|
||||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Update process names on every refresh"), &(settings->updateProcessNames)));
|
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Update process names on every refresh"), &(settings->updateProcessNames)));
|
||||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Add guest time in CPU meter percentage"), &(settings->accountGuestInCPUMeter)));
|
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Add guest time in CPU meter percentage"), &(settings->accountGuestInCPUMeter)));
|
||||||
|
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU percentage numerically"), &(settings->showCPUUsage)));
|
||||||
|
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Also show CPU frequency"), &(settings->showCPUFrequency)));
|
||||||
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Enable the mouse"), &(settings->enableMouse)));
|
Panel_add(super, (Object*) CheckItem_newByRef(xStrdup("Enable the mouse"), &(settings->enableMouse)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
10
Settings.c
10
Settings.c
|
@ -45,6 +45,8 @@ typedef struct Settings_ {
|
||||||
|
|
||||||
bool countCPUsFromZero;
|
bool countCPUsFromZero;
|
||||||
bool detailedCPUTime;
|
bool detailedCPUTime;
|
||||||
|
bool showCPUUsage;
|
||||||
|
bool showCPUFrequency;
|
||||||
bool treeView;
|
bool treeView;
|
||||||
bool showProgramPath;
|
bool showProgramPath;
|
||||||
bool hideThreads;
|
bool hideThreads;
|
||||||
|
@ -224,6 +226,10 @@ static bool Settings_read(Settings* this, const char* fileName) {
|
||||||
this->detailedCPUTime = atoi(option[1]);
|
this->detailedCPUTime = atoi(option[1]);
|
||||||
} else if (String_eq(option[0], "cpu_count_from_zero")) {
|
} else if (String_eq(option[0], "cpu_count_from_zero")) {
|
||||||
this->countCPUsFromZero = atoi(option[1]);
|
this->countCPUsFromZero = atoi(option[1]);
|
||||||
|
} else if (String_eq(option[0], "show_cpu_usage")) {
|
||||||
|
this->showCPUUsage = atoi(option[1]);
|
||||||
|
} else if (String_eq(option[0], "show_cpu_frequency")) {
|
||||||
|
this->showCPUFrequency = atoi(option[1]);
|
||||||
} else if (String_eq(option[0], "update_process_names")) {
|
} else if (String_eq(option[0], "update_process_names")) {
|
||||||
this->updateProcessNames = atoi(option[1]);
|
this->updateProcessNames = atoi(option[1]);
|
||||||
} else if (String_eq(option[0], "account_guest_in_cpu_meter")) {
|
} else if (String_eq(option[0], "account_guest_in_cpu_meter")) {
|
||||||
|
@ -315,6 +321,8 @@ bool Settings_write(Settings* this) {
|
||||||
fprintf(fd, "header_margin=%d\n", (int) this->headerMargin);
|
fprintf(fd, "header_margin=%d\n", (int) this->headerMargin);
|
||||||
fprintf(fd, "detailed_cpu_time=%d\n", (int) this->detailedCPUTime);
|
fprintf(fd, "detailed_cpu_time=%d\n", (int) this->detailedCPUTime);
|
||||||
fprintf(fd, "cpu_count_from_zero=%d\n", (int) this->countCPUsFromZero);
|
fprintf(fd, "cpu_count_from_zero=%d\n", (int) this->countCPUsFromZero);
|
||||||
|
fprintf(fd, "show_cpu_usage=%d\n", (int) this->showCPUUsage);
|
||||||
|
fprintf(fd, "show_cpu_frequency=%d\n", (int) this->showCPUFrequency);
|
||||||
fprintf(fd, "update_process_names=%d\n", (int) this->updateProcessNames);
|
fprintf(fd, "update_process_names=%d\n", (int) this->updateProcessNames);
|
||||||
fprintf(fd, "account_guest_in_cpu_meter=%d\n", (int) this->accountGuestInCPUMeter);
|
fprintf(fd, "account_guest_in_cpu_meter=%d\n", (int) this->accountGuestInCPUMeter);
|
||||||
fprintf(fd, "color_scheme=%d\n", (int) this->colorScheme);
|
fprintf(fd, "color_scheme=%d\n", (int) this->colorScheme);
|
||||||
|
@ -344,6 +352,8 @@ Settings* Settings_new(int cpuCount) {
|
||||||
this->highlightMegabytes = false;
|
this->highlightMegabytes = false;
|
||||||
this->detailedCPUTime = false;
|
this->detailedCPUTime = false;
|
||||||
this->countCPUsFromZero = false;
|
this->countCPUsFromZero = false;
|
||||||
|
this->showCPUUsage = true;
|
||||||
|
this->showCPUFrequency = false;
|
||||||
this->updateProcessNames = false;
|
this->updateProcessNames = false;
|
||||||
this->cpuCount = cpuCount;
|
this->cpuCount = cpuCount;
|
||||||
this->showProgramPath = true;
|
this->showProgramPath = true;
|
||||||
|
|
|
@ -36,6 +36,8 @@ typedef struct Settings_ {
|
||||||
|
|
||||||
bool countCPUsFromZero;
|
bool countCPUsFromZero;
|
||||||
bool detailedCPUTime;
|
bool detailedCPUTime;
|
||||||
|
bool showCPUUsage;
|
||||||
|
bool showCPUFrequency;
|
||||||
bool treeView;
|
bool treeView;
|
||||||
bool showProgramPath;
|
bool showProgramPath;
|
||||||
bool hideThreads;
|
bool hideThreads;
|
||||||
|
|
|
@ -217,6 +217,8 @@ double Platform_setCPUValues(Meter* mtr, int cpu) {
|
||||||
/* Convert to percent and return */
|
/* Convert to percent and return */
|
||||||
total = mtr->values[CPU_METER_NICE] + mtr->values[CPU_METER_NORMAL] + mtr->values[CPU_METER_KERNEL];
|
total = mtr->values[CPU_METER_NICE] + mtr->values[CPU_METER_NORMAL] + mtr->values[CPU_METER_KERNEL];
|
||||||
|
|
||||||
|
mtr->values[CPU_METER_FREQUENCY] = -1;
|
||||||
|
|
||||||
return CLAMP(total, 0.0, 100.0);
|
return CLAMP(total, 0.0, 100.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,6 +179,9 @@ double Platform_setCPUValues(Meter* this, int cpu) {
|
||||||
|
|
||||||
percent = CLAMP(percent, 0.0, 100.0);
|
percent = CLAMP(percent, 0.0, 100.0);
|
||||||
if (isnan(percent)) percent = 0.0;
|
if (isnan(percent)) percent = 0.0;
|
||||||
|
|
||||||
|
v[CPU_METER_FREQUENCY] = -1;
|
||||||
|
|
||||||
return percent;
|
return percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,9 @@ double Platform_setCPUValues(Meter* this, int cpu) {
|
||||||
|
|
||||||
percent = CLAMP(percent, 0.0, 100.0);
|
percent = CLAMP(percent, 0.0, 100.0);
|
||||||
if (isnan(percent)) percent = 0.0;
|
if (isnan(percent)) percent = 0.0;
|
||||||
|
|
||||||
|
v[CPU_METER_FREQUENCY] = -1;
|
||||||
|
|
||||||
return percent;
|
return percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,8 @@ typedef struct CPUData_ {
|
||||||
unsigned long long int softIrqPeriod;
|
unsigned long long int softIrqPeriod;
|
||||||
unsigned long long int stealPeriod;
|
unsigned long long int stealPeriod;
|
||||||
unsigned long long int guestPeriod;
|
unsigned long long int guestPeriod;
|
||||||
|
|
||||||
|
double frequency;
|
||||||
} CPUData;
|
} CPUData;
|
||||||
|
|
||||||
typedef struct TtyDriver_ {
|
typedef struct TtyDriver_ {
|
||||||
|
@ -100,6 +102,10 @@ typedef struct LinuxProcessList_ {
|
||||||
#define PROCDIR "/proc"
|
#define PROCDIR "/proc"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef PROCCPUINFOFILE
|
||||||
|
#define PROCCPUINFOFILE PROCDIR "/cpuinfo"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PROCSTATFILE
|
#ifndef PROCSTATFILE
|
||||||
#define PROCSTATFILE PROCDIR "/stat"
|
#define PROCSTATFILE PROCDIR "/stat"
|
||||||
#endif
|
#endif
|
||||||
|
@ -1108,18 +1114,86 @@ static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) {
|
||||||
cpuData->stealTime = steal;
|
cpuData->stealTime = steal;
|
||||||
cpuData->guestTime = virtalltime;
|
cpuData->guestTime = virtalltime;
|
||||||
cpuData->totalTime = totaltime;
|
cpuData->totalTime = totaltime;
|
||||||
|
|
||||||
}
|
}
|
||||||
double period = (double)this->cpus[0].totalPeriod / cpus;
|
double period = (double)this->cpus[0].totalPeriod / cpus;
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return period;
|
return period;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline double LinuxProcessList_scanCPUFrequency(LinuxProcessList* this) {
|
||||||
|
ProcessList* pl = (ProcessList*) this;
|
||||||
|
Settings* settings = pl->settings;
|
||||||
|
|
||||||
|
int cpus = this->super.cpuCount;
|
||||||
|
assert(cpus > 0);
|
||||||
|
|
||||||
|
for (int i = 0; i <= cpus; i++) {
|
||||||
|
CPUData* cpuData = &(this->cpus[i]);
|
||||||
|
cpuData->frequency = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
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 buffer[64];
|
||||||
|
xSnprintf(buffer, sizeof(buffer), PROCCPUINFOFILE " contains out-of-range CPU number %d", cpuid);
|
||||||
|
CRT_fatalError(buffer);
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
(sscanf(buffer, "cpu MHz : %lf", &frequency) == 1) ||
|
||||||
|
(sscanf(buffer, "cpu MHz: %lf", &frequency) == 1)
|
||||||
|
) {
|
||||||
|
if (cpuid < 0) {
|
||||||
|
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;
|
||||||
|
|
||||||
LinuxProcessList_scanMemoryInfo(super);
|
LinuxProcessList_scanMemoryInfo(super);
|
||||||
double period = LinuxProcessList_scanCPUTime(this);
|
double period = LinuxProcessList_scanCPUTime(this);
|
||||||
|
|
||||||
|
LinuxProcessList_scanCPUFrequency(this);
|
||||||
|
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
gettimeofday(&tv, NULL);
|
gettimeofday(&tv, NULL);
|
||||||
LinuxProcessList_recurseProcTree(this, PROCDIR, NULL, period, tv);
|
LinuxProcessList_recurseProcTree(this, PROCDIR, NULL, period, tv);
|
||||||
|
|
|
@ -47,6 +47,8 @@ typedef struct CPUData_ {
|
||||||
unsigned long long int softIrqPeriod;
|
unsigned long long int softIrqPeriod;
|
||||||
unsigned long long int stealPeriod;
|
unsigned long long int stealPeriod;
|
||||||
unsigned long long int guestPeriod;
|
unsigned long long int guestPeriod;
|
||||||
|
|
||||||
|
double frequency;
|
||||||
} CPUData;
|
} CPUData;
|
||||||
|
|
||||||
typedef struct TtyDriver_ {
|
typedef struct TtyDriver_ {
|
||||||
|
@ -73,6 +75,10 @@ typedef struct LinuxProcessList_ {
|
||||||
#define PROCDIR "/proc"
|
#define PROCDIR "/proc"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef PROCCPUINFOFILE
|
||||||
|
#define PROCCPUINFOFILE PROCDIR "/cpuinfo"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PROCSTATFILE
|
#ifndef PROCSTATFILE
|
||||||
#define PROCSTATFILE PROCDIR "/stat"
|
#define PROCSTATFILE PROCDIR "/stat"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -198,6 +198,9 @@ double Platform_setCPUValues(Meter* this, int cpu) {
|
||||||
}
|
}
|
||||||
percent = CLAMP(percent, 0.0, 100.0);
|
percent = CLAMP(percent, 0.0, 100.0);
|
||||||
if (isnan(percent)) percent = 0.0;
|
if (isnan(percent)) percent = 0.0;
|
||||||
|
|
||||||
|
v[CPU_METER_FREQUENCY] = cpuData->frequency;
|
||||||
|
|
||||||
return percent;
|
return percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,4 @@ extern char* Platform_getProcessEnv(pid_t pid);
|
||||||
|
|
||||||
extern void Platform_getPressureStall(const char *file, bool some, double* ten, double* sixty, double* threehundred);
|
extern void Platform_getPressureStall(const char *file, bool some, double* ten, double* sixty, double* threehundred);
|
||||||
|
|
||||||
void Platform_getPressureStall(const char *file, bool some, double* ten, double* sixty, double* threehundred);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -170,6 +170,7 @@ double Platform_setCPUValues(Meter* this, int cpu) {
|
||||||
v[CPU_METER_STEAL] = 0.0;
|
v[CPU_METER_STEAL] = 0.0;
|
||||||
v[CPU_METER_GUEST] = 0.0;
|
v[CPU_METER_GUEST] = 0.0;
|
||||||
v[CPU_METER_IOWAIT] = 0.0;
|
v[CPU_METER_IOWAIT] = 0.0;
|
||||||
|
v[CPU_METER_FREQUENCY] = -1;
|
||||||
Meter_setItems(this, 8);
|
Meter_setItems(this, 8);
|
||||||
totalPercent = v[0]+v[1]+v[2]+v[3];
|
totalPercent = v[0]+v[1]+v[2]+v[3];
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -203,6 +203,9 @@ double Platform_setCPUValues(Meter* this, int cpu) {
|
||||||
|
|
||||||
percent = CLAMP(percent, 0.0, 100.0);
|
percent = CLAMP(percent, 0.0, 100.0);
|
||||||
if (isnan(percent)) percent = 0.0;
|
if (isnan(percent)) percent = 0.0;
|
||||||
|
|
||||||
|
v[CPU_METER_FREQUENCY] = -1;
|
||||||
|
|
||||||
return percent;
|
return percent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,8 +108,11 @@ int Platform_getMaxPid() {
|
||||||
}
|
}
|
||||||
|
|
||||||
double Platform_setCPUValues(Meter* this, int cpu) {
|
double Platform_setCPUValues(Meter* this, int cpu) {
|
||||||
(void) this;
|
|
||||||
(void) cpu;
|
(void) cpu;
|
||||||
|
|
||||||
|
double* v = this->values;
|
||||||
|
v[CPU_METER_FREQUENCY] = -1;
|
||||||
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue