summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHisham Muhammad <hisham@gobolinux.org>2008-03-08 23:39:48 +0000
committerHisham Muhammad <hisham@gobolinux.org>2008-03-08 23:39:48 +0000
commit93f091c47e54f8d5d150770a687c4cc76761c954 (patch)
treee789f43adeaa3e77e789d639703dab082bcc6e09
parent52840406ac85943d47ed9311be8db86eedc1ea7a (diff)
BUGFIX: Fix display of CPU count for threaded processes.
When user threads are hidden, process now shows the sum of processor usage for all processors. When user threads are displayed, each thread shows its own processor usage, including the root thread. (thanks to Bert Wesarg for the report) Also, add option to display thread colors differently.
-rw-r--r--CRT.c24
-rw-r--r--CRT.h2
-rw-r--r--ChangeLog6
-rw-r--r--DisplayOptionsPanel.c1
-rw-r--r--Process.c21
-rw-r--r--ProcessList.c64
-rw-r--r--ProcessList.h3
-rw-r--r--Settings.c4
8 files changed, 88 insertions, 37 deletions
diff --git a/CRT.c b/CRT.c
index f7861e84..7d2cc10b 100644
--- a/CRT.c
+++ b/CRT.c
@@ -68,6 +68,8 @@ typedef enum ColorElements_ {
PROCESS_BASENAME,
PROCESS_HIGH_PRIORITY,
PROCESS_LOW_PRIORITY,
+ PROCESS_THREAD,
+ PROCESS_THREAD_BASENAME,
BAR_BORDER,
BAR_SHADOW,
GRAPH_1,
@@ -210,8 +212,8 @@ void CRT_setColors(int colorScheme) {
CRT_colors[FUNCTION_KEY] = A_NORMAL;
CRT_colors[PANEL_HEADER_FOCUS] = A_REVERSE;
CRT_colors[PANEL_HEADER_UNFOCUS] = A_REVERSE;
- CRT_colors[PANEL_HIGHLIGHT_FOCUS] = A_REVERSE | A_BOLD;
- CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_REVERSE;
+ CRT_colors[PANEL_HIGHLIGHT_FOCUS] = A_REVERSE;
+ CRT_colors[PANEL_HIGHLIGHT_UNFOCUS] = A_BOLD;
CRT_colors[FAILED_SEARCH] = A_REVERSE | A_BOLD;
CRT_colors[UPTIME] = A_BOLD;
CRT_colors[LARGE_NUMBER] = A_BOLD;
@@ -228,6 +230,8 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_R_STATE] = A_BOLD;
CRT_colors[PROCESS_HIGH_PRIORITY] = A_BOLD;
CRT_colors[PROCESS_LOW_PRIORITY] = A_DIM;
+ CRT_colors[PROCESS_THREAD] = A_BOLD;
+ CRT_colors[PROCESS_THREAD_BASENAME] = A_REVERSE;
CRT_colors[BAR_BORDER] = A_BOLD;
CRT_colors[BAR_SHADOW] = A_DIM;
CRT_colors[SWAP] = A_BOLD;
@@ -278,11 +282,13 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_SHADOW] = A_BOLD | ColorPair(Black,White);
CRT_colors[PROCESS_TAG] = ColorPair(White,Blue);
CRT_colors[PROCESS_MEGABYTES] = ColorPair(Blue,White);
- CRT_colors[PROCESS_BASENAME] = ColorPair(Green,White);
- CRT_colors[PROCESS_TREE] = ColorPair(Blue,White);
+ CRT_colors[PROCESS_BASENAME] = ColorPair(Blue,White);
+ CRT_colors[PROCESS_TREE] = ColorPair(Green,White);
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,White);
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,White);
CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,White);
+ CRT_colors[PROCESS_THREAD] = ColorPair(Blue,White);
+ CRT_colors[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue,White);
CRT_colors[BAR_BORDER] = ColorPair(Blue,White);
CRT_colors[BAR_SHADOW] = ColorPair(Black,White);
CRT_colors[SWAP] = ColorPair(Red,White);
@@ -338,6 +344,8 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Black);
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black);
CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,Black);
+ CRT_colors[PROCESS_THREAD] = ColorPair(Blue,Black);
+ CRT_colors[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue,Black);
CRT_colors[BAR_BORDER] = ColorPair(Blue,Black);
CRT_colors[BAR_SHADOW] = ColorPair(Black,Black);
CRT_colors[SWAP] = ColorPair(Red,Black);
@@ -393,6 +401,8 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Blue);
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Blue);
CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,Blue);
+ CRT_colors[PROCESS_THREAD] = ColorPair(Green,Blue);
+ CRT_colors[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green,Blue);
CRT_colors[BAR_BORDER] = A_BOLD | ColorPair(Yellow,Blue);
CRT_colors[BAR_SHADOW] = ColorPair(Cyan,Blue);
CRT_colors[SWAP] = ColorPair(Red,Blue);
@@ -445,6 +455,8 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_MEGABYTES] = A_BOLD | ColorPair(Green,Black);
CRT_colors[PROCESS_BASENAME] = A_BOLD | ColorPair(Green,Black);
CRT_colors[PROCESS_TREE] = ColorPair(Cyan,Black);
+ CRT_colors[PROCESS_THREAD] = ColorPair(Green,Black);
+ CRT_colors[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Blue,Black);
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Black);
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black);
CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,Black);
@@ -471,7 +483,7 @@ void CRT_setColors(int colorScheme) {
CRT_colors[CPU_NICE] = ColorPair(Blue,Black);
CRT_colors[CPU_NORMAL] = ColorPair(Green,Black);
CRT_colors[CPU_KERNEL] = ColorPair(Red,Black);
- CRT_colors[CLOCK] = A_BOLD;
+ CRT_colors[CLOCK] = ColorPair(Green,Black);
CRT_colors[CHECK_BOX] = ColorPair(Green,Black);
CRT_colors[CHECK_MARK] = A_BOLD | ColorPair(Green,Black);
CRT_colors[CHECK_TEXT] = ColorPair(Cyan,Black);
@@ -504,6 +516,8 @@ void CRT_setColors(int colorScheme) {
CRT_colors[PROCESS_R_STATE] = ColorPair(Green,Black);
CRT_colors[PROCESS_HIGH_PRIORITY] = ColorPair(Red,Black);
CRT_colors[PROCESS_LOW_PRIORITY] = ColorPair(Red,Black);
+ CRT_colors[PROCESS_THREAD] = ColorPair(Green,Black);
+ CRT_colors[PROCESS_THREAD_BASENAME] = A_BOLD | ColorPair(Green,Black);
CRT_colors[BAR_BORDER] = A_BOLD;
CRT_colors[BAR_SHADOW] = A_BOLD | ColorPair(Black,Black);
CRT_colors[SWAP] = ColorPair(Red,Black);
diff --git a/CRT.h b/CRT.h
index 41de032f..e455b3b7 100644
--- a/CRT.h
+++ b/CRT.h
@@ -70,6 +70,8 @@ typedef enum ColorElements_ {
PROCESS_BASENAME,
PROCESS_HIGH_PRIORITY,
PROCESS_LOW_PRIORITY,
+ PROCESS_THREAD,
+ PROCESS_THREAD_BASENAME,
BAR_BORDER,
BAR_SHADOW,
GRAPH_1,
diff --git a/ChangeLog b/ChangeLog
index bf07ac84..1cfbbfb8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,12 @@
What's new in version 0.7.1
+* BUGFIX: Fix display of CPU count for threaded processes.
+ When user threads are hidden, process now shows the
+ sum of processor usage for all processors. When user
+ threads are displayed, each thread shows its own
+ processor usage, including the root thread.
+ (thanks to Bert Wesarg for the report)
* BUGFIX: avoid crashing when using many meters
(thanks to David Cho for the report)
diff --git a/DisplayOptionsPanel.c b/DisplayOptionsPanel.c
index 2eeeb8aa..ceab53c4 100644
--- a/DisplayOptionsPanel.c
+++ b/DisplayOptionsPanel.c
@@ -35,6 +35,7 @@ DisplayOptionsPanel* DisplayOptionsPanel_new(Settings* settings, ScreenManager*
Panel_add(super, (Object*) CheckItem_new(String_copy("Shadow other users' processes"), &(settings->pl->shadowOtherUsers), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Hide kernel threads"), &(settings->pl->hideKernelThreads), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Hide userland threads"), &(settings->pl->hideUserlandThreads), false));
+ Panel_add(super, (Object*) CheckItem_new(String_copy("Display threads in a different color"), &(settings->pl->highlightThreads), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Highlight program \"basename\""), &(settings->pl->highlightBaseName), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Highlight megabytes in memory counters"), &(settings->pl->highlightMegabytes), false));
Panel_add(super, (Object*) CheckItem_new(String_copy("Leave a margin around header"), &(settings->header->margin), false));
diff --git a/Process.c b/Process.c
index 8721b73d..ab66d5bb 100644
--- a/Process.c
+++ b/Process.c
@@ -264,7 +264,7 @@ static void Process_printTime(RichString* str, unsigned long t) {
RichString_append(str, CRT_colors[DEFAULT_COLOR], buffer);
}
-static inline void Process_writeCommand(Process* this, int attr, RichString* str) {
+static inline void Process_writeCommand(Process* this, int attr, int baseattr, RichString* str) {
if (this->pl->highlightBaseName) {
char* firstSpace = strchr(this->comm, ' ');
if (firstSpace) {
@@ -275,10 +275,10 @@ static inline void Process_writeCommand(Process* this, int attr, RichString* str
slash++;
RichString_appendn(str, attr, this->comm, slash - this->comm);
}
- RichString_appendn(str, CRT_colors[PROCESS_BASENAME], slash, firstSpace - slash);
+ RichString_appendn(str, baseattr, slash, firstSpace - slash);
RichString_append(str, attr, firstSpace);
} else {
- RichString_append(str, CRT_colors[PROCESS_BASENAME], this->comm);
+ RichString_append(str, baseattr, this->comm);
}
} else {
RichString_append(str, attr, this->comm);
@@ -288,6 +288,7 @@ static inline void Process_writeCommand(Process* this, int attr, RichString* str
void Process_writeField(Process* this, RichString* str, ProcessField field) {
char buffer[PROCESS_COMM_LEN];
int attr = CRT_colors[DEFAULT_COLOR];
+ int baseattr = CRT_colors[PROCESS_BASENAME];
int n = PROCESS_COMM_LEN;
switch (field) {
@@ -301,8 +302,12 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
case PROCESSOR: snprintf(buffer, n, "%3d ", this->processor+1); break;
case NLWP: snprintf(buffer, n, "%4ld ", this->nlwp); break;
case COMM: {
+ if (this->pl->highlightThreads && (this->pid != this->tgid || this->m_size == 0)) {
+ attr = CRT_colors[PROCESS_THREAD];
+ baseattr = CRT_colors[PROCESS_THREAD_BASENAME];
+ }
if (!this->pl->treeView || this->indent == 0) {
- Process_writeCommand(this, attr, str);
+ Process_writeCommand(this, attr, baseattr, str);
return;
} else {
char* buf = buffer;
@@ -323,7 +328,7 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
else
snprintf(buf, n, " ,- ");
RichString_append(str, CRT_colors[PROCESS_TREE], buffer);
- Process_writeCommand(this, attr, str);
+ Process_writeCommand(this, attr, baseattr, str);
return;
}
}
@@ -376,8 +381,10 @@ void Process_writeField(Process* this, RichString* str, ProcessField field) {
case CSTIME: Process_printTime(str, this->cstime); return;
case TIME: Process_printTime(str, this->utime + this->stime); return;
case PERCENT_CPU: {
- if (this->percent_cpu > 99.9) {
- snprintf(buffer, n, "100. ");
+ if (this->percent_cpu > 999.9) {
+ snprintf(buffer, n, "%4d ", (unsigned int)this->percent_cpu);
+ } else if (this->percent_cpu > 99.9) {
+ snprintf(buffer, n, "%3d. ", (unsigned int)this->percent_cpu);
} else {
snprintf(buffer, n, "%4.1f ", this->percent_cpu);
}
diff --git a/ProcessList.c b/ProcessList.c
index 6b18e04d..66d60949 100644
--- a/ProcessList.c
+++ b/ProcessList.c
@@ -119,6 +119,7 @@ typedef struct ProcessList_ {
bool treeView;
bool highlightBaseName;
bool highlightMegabytes;
+ bool highlightThreads;
bool detailedCPUTime;
#ifdef DEBUG_PROC
FILE* traceFile;
@@ -498,13 +499,15 @@ bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname,
return true;
}
-void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, float period) {
+bool ProcessList_processEntries(ProcessList* this, char* dirname, Process* parent, float period) {
DIR* dir;
struct dirent* entry;
Process* prototype = this->prototype;
dir = opendir(dirname);
- if (!dir) return;
+ if (!dir) return false;
+ int processors = this->processorCount;
+ bool showUserlandThreads = !this->hideUserlandThreads;
while ((entry = readdir(dir)) != NULL) {
char* name = entry->d_name;
int pid;
@@ -521,35 +524,43 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
isThread = true;
}
- if (pid > 0 && pid != parent) {
- if (!this->hideUserlandThreads) {
- char subdirname[MAX_NAME+1];
- snprintf(subdirname, MAX_NAME, "%s/%s/task", dirname, name);
-
- ProcessList_processEntries(this, subdirname, pid, period);
- }
+ if (pid > 0) {
FILE* status;
char statusfilename[MAX_NAME+1];
char command[PROCESS_COMM_LEN + 1];
Process* process = NULL;
-
- assert(Hashtable_count(this->processTable) == Vector_count(this->processes));
Process* existingProcess = (Process*) Hashtable_get(this->processTable, pid);
+
if (existingProcess) {
assert(Vector_indexOf(this->processes, existingProcess, Process_pidCompare) != -1);
process = existingProcess;
assert(process->pid == pid);
} else {
- process = prototype;
- assert(process->comm == NULL);
- process->pid = pid;
- if (! ProcessList_readStatusFile(this, process, dirname, name))
- goto errorReadingProcess;
+ if (parent && parent->pid == pid) {
+ process = parent;
+ } else {
+ process = prototype;
+ assert(process->comm == NULL);
+ process->pid = pid;
+ }
}
+
+ if (showUserlandThreads && (!parent || pid != parent->pid)) {
+ char subdirname[MAX_NAME+1];
+ snprintf(subdirname, MAX_NAME, "%s/%s/task", dirname, name);
+
+ if (ProcessList_processEntries(this, subdirname, process, period))
+ continue;
+ }
+
process->updated = true;
+ if (!existingProcess)
+ if (! ProcessList_readStatusFile(this, process, dirname, name))
+ goto errorReadingProcess;
+
snprintf(statusfilename, MAX_NAME, "%s/%s/statm", dirname, name);
status = ProcessList_fopen(this, statusfilename, "r");
@@ -573,13 +584,14 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
snprintf(statusfilename, MAX_NAME, "%s/%s/stat", dirname, name);
status = ProcessList_fopen(this, statusfilename, "r");
- if (status == NULL)
+ if (status == NULL)
goto errorReadingProcess;
int success = ProcessList_readStatFile(this, process, status, command);
fclose(status);
- if(!success)
+ if(!success) {
goto errorReadingProcess;
+ }
if(!existingProcess) {
process->user = UsersTable_getRef(this->usersTable, process->st_uid);
@@ -624,8 +636,9 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
fclose(status);
}
- process->percent_cpu = (process->utime + process->stime - lasttimes) /
+ int percent_cpu = (process->utime + process->stime - lasttimes) /
period * 100.0;
+ process->percent_cpu = MAX(MIN(percent_cpu, processors*100.0), 0.0);
process->percent_mem = (process->m_resident * PAGE_SIZE) /
(float)(this->totalMem) *
@@ -637,7 +650,8 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
}
if (!existingProcess) {
- ProcessList_add(this, Process_clone(process));
+ process = Process_clone(process);
+ ProcessList_add(this, process);
}
continue;
@@ -655,6 +669,7 @@ void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, fl
}
}
closedir(dir);
+ return true;
}
void ProcessList_scan(ProcessList* this) {
@@ -665,6 +680,7 @@ void ProcessList_scan(ProcessList* this) {
char buffer[128];
status = ProcessList_fopen(this, PROCMEMINFOFILE, "r");
assert(status != NULL);
+ int processors = this->processorCount;
while (!feof(status)) {
fgets(buffer, 128, status);
@@ -701,7 +717,7 @@ void ProcessList_scan(ProcessList* this) {
status = ProcessList_fopen(this, PROCSTATFILE, "r");
assert(status != NULL);
- for (int i = 0; i <= this->processorCount; i++) {
+ for (int i = 0; i <= processors; i++) {
char buffer[256];
int cpuid;
unsigned long long int ioWait, irq, softIrq, steal;
@@ -755,7 +771,7 @@ void ProcessList_scan(ProcessList* this) {
this->stealTime[i] = steal;
this->totalTime[i] = totaltime;
}
- float period = (float)this->totalPeriod[0] / this->processorCount;
+ float period = (float)this->totalPeriod[0] / processors;
fclose(status);
// mark all process as "dirty"
@@ -766,8 +782,8 @@ void ProcessList_scan(ProcessList* this) {
this->totalTasks = 0;
this->runningTasks = 0;
-
- ProcessList_processEntries(this, PROCDIR, 0, period);
+
+ ProcessList_processEntries(this, PROCDIR, NULL, period);
for (int i = Vector_size(this->processes) - 1; i >= 0; i--) {
Process* p = (Process*) Vector_get(this->processes, i);
diff --git a/ProcessList.h b/ProcessList.h
index 578edb9e..34bdc46e 100644
--- a/ProcessList.h
+++ b/ProcessList.h
@@ -119,6 +119,7 @@ typedef struct ProcessList_ {
bool treeView;
bool highlightBaseName;
bool highlightMegabytes;
+ bool highlightThreads;
bool detailedCPUTime;
#ifdef DEBUG_PROC
FILE* traceFile;
@@ -164,7 +165,7 @@ void ProcessList_sort(ProcessList* this);
bool ProcessList_readStatusFile(ProcessList* this, Process* proc, char* dirname, char* name);
-void ProcessList_processEntries(ProcessList* this, char* dirname, int parent, float period);
+bool ProcessList_processEntries(ProcessList* this, char* dirname, Process* parent, float period);
void ProcessList_scan(ProcessList* this);
diff --git a/Settings.c b/Settings.c
index a8ddc456..380bcc76 100644
--- a/Settings.c
+++ b/Settings.c
@@ -55,6 +55,7 @@ Settings* Settings_new(ProcessList* pl, Header* header) {
Header_defaultMeters(this->header);
pl->hideKernelThreads = true;
pl->highlightMegabytes = true;
+ pl->highlightThreads = false;
}
}
return this;
@@ -137,6 +138,8 @@ bool Settings_read(Settings* this, char* fileName) {
this->pl->highlightBaseName = atoi(option[1]);
} else if (String_eq(option[0], "highlight_megabytes")) {
this->pl->highlightMegabytes = atoi(option[1]);
+ } else if (String_eq(option[0], "highlight_threads")) {
+ this->pl->highlightThreads = atoi(option[1]);
} else if (String_eq(option[0], "header_margin")) {
this->header->margin = atoi(option[1]);
} else if (String_eq(option[0], "expand_system_time")) {
@@ -198,6 +201,7 @@ bool Settings_write(Settings* this) {
fprintf(fd, "shadow_other_users=%d\n", (int) this->pl->shadowOtherUsers);
fprintf(fd, "highlight_base_name=%d\n", (int) this->pl->highlightBaseName);
fprintf(fd, "highlight_megabytes=%d\n", (int) this->pl->highlightMegabytes);
+ fprintf(fd, "highlight_threads=%d\n", (int) this->pl->highlightThreads);
fprintf(fd, "tree_view=%d\n", (int) this->pl->treeView);
fprintf(fd, "header_margin=%d\n", (int) this->header->margin);
fprintf(fd, "detailed_cpu_time=%d\n", (int) this->pl->detailedCPUTime);

© 2014-2024 Faster IT GmbH | imprint | privacy policy