mirror of https://github.com/xzeldon/htop.git
Add Linux process column for context switches
Displays the incremental sum of voluntary_ctxt_switches and nonvoluntary_ctxt_switches.
This commit is contained in:
parent
ffc65b3827
commit
98ee833932
|
@ -386,6 +386,9 @@ Which cgroup the process is in.
|
||||||
.B OOM
|
.B OOM
|
||||||
OOM killer score.
|
OOM killer score.
|
||||||
.TP
|
.TP
|
||||||
|
.B CTXT
|
||||||
|
Incremental sum of voluntary and nonvoluntary context switches.
|
||||||
|
.TP
|
||||||
.B IO_PRIORITY (IO)
|
.B IO_PRIORITY (IO)
|
||||||
The I/O scheduling class followed by the priority if the class supports it:
|
The I/O scheduling class followed by the priority if the class supports it:
|
||||||
\fBR\fR for Realtime
|
\fBR\fR for Realtime
|
||||||
|
|
|
@ -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_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_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, },
|
[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, },
|
[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_IO_DELAY: LinuxProcess_printDelay(lp->blkio_delay_percent, buffer, n); break;
|
||||||
case PERCENT_SWAP_DELAY: LinuxProcess_printDelay(lp->swapin_delay_percent, buffer, n); break;
|
case PERCENT_SWAP_DELAY: LinuxProcess_printDelay(lp->swapin_delay_percent, buffer, n); break;
|
||||||
#endif
|
#endif
|
||||||
|
case CTXT:
|
||||||
|
if (lp->ctxt_diff > 1000)
|
||||||
|
attr |= A_BOLD;
|
||||||
|
xSnprintf(buffer, n, "%5lu ", lp->ctxt_diff);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Process_writeField((Process*)this, str, field);
|
Process_writeField((Process*)this, str, field);
|
||||||
return;
|
return;
|
||||||
|
@ -359,6 +365,8 @@ long LinuxProcess_compare(const void* v1, const void* v2) {
|
||||||
#endif
|
#endif
|
||||||
case IO_PRIORITY:
|
case IO_PRIORITY:
|
||||||
return LinuxProcess_effectiveIOPriority(p1) - LinuxProcess_effectiveIOPriority(p2);
|
return LinuxProcess_effectiveIOPriority(p1) - LinuxProcess_effectiveIOPriority(p2);
|
||||||
|
case CTXT:
|
||||||
|
return ((long)p2->ctxt_diff - (long)p1->ctxt_diff);
|
||||||
default:
|
default:
|
||||||
return Process_compare(v1, v2);
|
return Process_compare(v1, v2);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ in the source distribution for its full text.
|
||||||
#define PROCESS_FLAG_LINUX_CGROUP 0x0800
|
#define PROCESS_FLAG_LINUX_CGROUP 0x0800
|
||||||
#define PROCESS_FLAG_LINUX_OOM 0x1000
|
#define PROCESS_FLAG_LINUX_OOM 0x1000
|
||||||
#define PROCESS_FLAG_LINUX_SMAPS 0x2000
|
#define PROCESS_FLAG_LINUX_SMAPS 0x2000
|
||||||
|
#define PROCESS_FLAG_LINUX_CTXT 0x4000
|
||||||
|
|
||||||
typedef enum UnsupportedProcessFields {
|
typedef enum UnsupportedProcessFields {
|
||||||
FLAGS = 9,
|
FLAGS = 9,
|
||||||
|
@ -80,7 +81,8 @@ typedef enum LinuxProcessFields {
|
||||||
M_PSS = 119,
|
M_PSS = 119,
|
||||||
M_SWAP = 120,
|
M_SWAP = 120,
|
||||||
M_PSSWP = 121,
|
M_PSSWP = 121,
|
||||||
LAST_PROCESSFIELD = 122,
|
CTXT = 122,
|
||||||
|
LAST_PROCESSFIELD = 123,
|
||||||
} LinuxProcessField;
|
} LinuxProcessField;
|
||||||
|
|
||||||
#include "IOPriority.h"
|
#include "IOPriority.h"
|
||||||
|
@ -138,6 +140,8 @@ typedef struct LinuxProcess_ {
|
||||||
float blkio_delay_percent;
|
float blkio_delay_percent;
|
||||||
float swapin_delay_percent;
|
float swapin_delay_percent;
|
||||||
#endif
|
#endif
|
||||||
|
unsigned long ctxt_total;
|
||||||
|
unsigned long ctxt_diff;
|
||||||
} LinuxProcess;
|
} LinuxProcess;
|
||||||
|
|
||||||
#define Process_isKernelThread(_process) (((LinuxProcess*)(_process))->isKernelThread)
|
#define Process_isKernelThread(_process) (((LinuxProcess*)(_process))->isKernelThread)
|
||||||
|
|
|
@ -588,6 +588,32 @@ static void LinuxProcessList_readOomData(LinuxProcess* process, const char* dirn
|
||||||
fclose(file);
|
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
|
#ifdef HAVE_DELAYACCT
|
||||||
|
|
||||||
static int handleNetlinkMsg(struct nl_msg *nlmsg, void *linuxProcess) {
|
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)
|
if (settings->flags & PROCESS_FLAG_LINUX_OOM)
|
||||||
LinuxProcessList_readOomData(lp, dirname, name);
|
LinuxProcessList_readOomData(lp, dirname, name);
|
||||||
|
|
||||||
|
if (settings->flags & PROCESS_FLAG_LINUX_CTXT)
|
||||||
|
LinuxProcessList_readCtxtData(lp, dirname, name);
|
||||||
|
|
||||||
if (proc->state == 'Z' && (proc->basenameOffset == 0)) {
|
if (proc->state == 'Z' && (proc->basenameOffset == 0)) {
|
||||||
proc->basenameOffset = -1;
|
proc->basenameOffset = -1;
|
||||||
setCommand(proc, command, commLen);
|
setCommand(proc, command, commLen);
|
||||||
|
|
Loading…
Reference in New Issue