summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2020-09-11 15:02:00 +0200
committercgzones <cgzones@googlemail.com>2020-09-17 21:53:15 +0200
commit98ee833932ad90532246c95daf5859bdcf65dec9 (patch)
treed24676d96bacca04466c3050c509162fd74fb270
parentffc65b382753a1d61b8f43e4d86f5415b7bfb415 (diff)
Add Linux process column for context switches
Displays the incremental sum of voluntary_ctxt_switches and nonvoluntary_ctxt_switches.
-rw-r--r--htop.1.in3
-rw-r--r--linux/LinuxProcess.c8
-rw-r--r--linux/LinuxProcess.h6
-rw-r--r--linux/LinuxProcessList.c29
4 files changed, 45 insertions, 1 deletions
diff --git a/htop.1.in b/htop.1.in
index c5b131bb..1ae1208f 100644
--- a/htop.1.in
+++ b/htop.1.in
@@ -386,6 +386,9 @@ Which cgroup the process is in.
.B OOM
OOM killer score.
.TP
+.B CTXT
+Incremental sum of voluntary and nonvoluntary context switches.
+.TP
.B IO_PRIORITY (IO)
The I/O scheduling class followed by the priority if the class supports it:
\fBR\fR for Realtime
diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c
index 377aa5bb..bef648a9 100644
--- a/linux/LinuxProcess.c
+++ b/linux/LinuxProcess.c
@@ -107,6 +107,7 @@ ProcessFieldData Process_fields[] = {
[M_PSS] = { .name = "M_PSS", .title = " PSS ", .description = "proportional set size, same as M_RESIDENT but each page is divided by the number of processes sharing it.", .flags = PROCESS_FLAG_LINUX_SMAPS, },
[M_SWAP] = { .name = "M_SWAP", .title = " SWAP ", .description = "Size of the process's swapped pages", .flags = PROCESS_FLAG_LINUX_SMAPS, },
[M_PSSWP] = { .name = "M_PSSWP", .title = " PSSWP ", .description = "shows proportional swap share of this mapping, Unlike \"Swap\", this does not take into account swapped out page of underlying shmem objects.", .flags = PROCESS_FLAG_LINUX_SMAPS, },
+ [CTXT] = { .name = "CTXT", .title = " CTXT ", .description = "Context switches (incremental sum of voluntary_ctxt_switches and nonvoluntary_ctxt_switches)", .flags = PROCESS_FLAG_LINUX_CTXT, },
[LAST_PROCESSFIELD] = { .name = "*** report bug! ***", .title = NULL, .description = NULL, .flags = 0, },
};
@@ -276,6 +277,11 @@ void LinuxProcess_writeField(Process* this, RichString* str, ProcessField field)
case PERCENT_IO_DELAY: LinuxProcess_printDelay(lp->blkio_delay_percent, buffer, n); break;
case PERCENT_SWAP_DELAY: LinuxProcess_printDelay(lp->swapin_delay_percent, buffer, n); break;
#endif
+ case CTXT:
+ if (lp->ctxt_diff > 1000)
+ attr |= A_BOLD;
+ xSnprintf(buffer, n, "%5lu ", lp->ctxt_diff);
+ break;
default:
Process_writeField((Process*)this, str, field);
return;
@@ -359,6 +365,8 @@ long LinuxProcess_compare(const void* v1, const void* v2) {
#endif
case IO_PRIORITY:
return LinuxProcess_effectiveIOPriority(p1) - LinuxProcess_effectiveIOPriority(p2);
+ case CTXT:
+ return ((long)p2->ctxt_diff - (long)p1->ctxt_diff);
default:
return Process_compare(v1, v2);
}
diff --git a/linux/LinuxProcess.h b/linux/LinuxProcess.h
index 021cae7c..9972ee84 100644
--- a/linux/LinuxProcess.h
+++ b/linux/LinuxProcess.h
@@ -14,6 +14,7 @@ in the source distribution for its full text.
#define PROCESS_FLAG_LINUX_CGROUP 0x0800
#define PROCESS_FLAG_LINUX_OOM 0x1000
#define PROCESS_FLAG_LINUX_SMAPS 0x2000
+#define PROCESS_FLAG_LINUX_CTXT 0x4000
typedef enum UnsupportedProcessFields {
FLAGS = 9,
@@ -80,7 +81,8 @@ typedef enum LinuxProcessFields {
M_PSS = 119,
M_SWAP = 120,
M_PSSWP = 121,
- LAST_PROCESSFIELD = 122,
+ CTXT = 122,
+ LAST_PROCESSFIELD = 123,
} LinuxProcessField;
#include "IOPriority.h"
@@ -138,6 +140,8 @@ typedef struct LinuxProcess_ {
float blkio_delay_percent;
float swapin_delay_percent;
#endif
+ unsigned long ctxt_total;
+ unsigned long ctxt_diff;
} LinuxProcess;
#define Process_isKernelThread(_process) (((LinuxProcess*)(_process))->isKernelThread)
diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c
index cf91900b..89746e17 100644
--- a/linux/LinuxProcessList.c
+++ b/linux/LinuxProcessList.c
@@ -588,6 +588,32 @@ static void LinuxProcessList_readOomData(LinuxProcess* process, const char* dirn
fclose(file);
}
+static void LinuxProcessList_readCtxtData(LinuxProcess* process, const char* dirname, const char* name) {
+ char filename[MAX_NAME+1];
+ xSnprintf(filename, MAX_NAME, "%s/%s/status", dirname, name);
+ FILE* file = fopen(filename, "r");
+ if (!file)
+ return;
+ char buffer[PROC_LINE_LENGTH + 1];
+ unsigned long ctxt = 0;
+ while (fgets(buffer, PROC_LINE_LENGTH, file)) {
+ if (String_startsWith(buffer, "voluntary_ctxt_switches:")) {
+ unsigned long vctxt;
+ int ok = sscanf(buffer, "voluntary_ctxt_switches:\t%lu", &vctxt);
+ if (ok >= 1)
+ ctxt += vctxt;
+ } else if (String_startsWith(buffer, "nonvoluntary_ctxt_switches:")) {
+ unsigned long nvctxt;
+ int ok = sscanf(buffer, "nonvoluntary_ctxt_switches:\t%lu", &nvctxt);
+ if (ok >= 1)
+ ctxt += nvctxt;
+ }
+ }
+ fclose(file);
+ process->ctxt_diff = (ctxt > process->ctxt_total) ? (ctxt - process->ctxt_total) : 0;
+ process->ctxt_total = ctxt;
+}
+
#ifdef HAVE_DELAYACCT
static int handleNetlinkMsg(struct nl_msg *nlmsg, void *linuxProcess) {
@@ -885,6 +911,9 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, const char*
if (settings->flags & PROCESS_FLAG_LINUX_OOM)
LinuxProcessList_readOomData(lp, dirname, name);
+ if (settings->flags & PROCESS_FLAG_LINUX_CTXT)
+ LinuxProcessList_readCtxtData(lp, dirname, name);
+
if (proc->state == 'Z' && (proc->basenameOffset == 0)) {
proc->basenameOffset = -1;
setCommand(proc, command, commLen);

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