summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);