227 lines
8.7 KiB
Diff
227 lines
8.7 KiB
Diff
|
Index: procps-3.2.7/top.c
|
||
|
===================================================================
|
||
|
--- procps-3.2.7.orig/top.c
|
||
|
+++ procps-3.2.7/top.c
|
||
|
@@ -23,9 +23,9 @@
|
||
|
#include <sys/resource.h>
|
||
|
#include <sys/time.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
-#include <ctype.h>
|
||
|
+// #include <ctype.h>
|
||
|
#include <curses.h>
|
||
|
#include <errno.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <signal.h>
|
||
|
@@ -223,8 +223,11 @@ SCB_NUM1(P_SHR, share)
|
||
|
SCB_NUM1(P_FLT, maj_flt)
|
||
|
SCB_NUM1(P_DRT, dt)
|
||
|
SCB_NUMx(P_STA, state)
|
||
|
|
||
|
+SCB_NUM1(P_OOM, oom_score)
|
||
|
+SCB_NUM1(P_OOA, oom_adj)
|
||
|
+
|
||
|
static int sort_P_CMD (const proc_t **P, const proc_t **Q)
|
||
|
{
|
||
|
/* if a process doesn't have a cmdline, we'll consider it a kernel thread
|
||
|
-- since displayed tasks are given special treatment, we must too */
|
||
|
@@ -315,8 +318,13 @@ static const char *tg2 (int x, int y)
|
||
|
{
|
||
|
return Cap_can_goto ? tgoto(cursor_address, x, y) : "";
|
||
|
}
|
||
|
|
||
|
+/* isupper/islower/toupper/tolower that work for '[{', '\\|', ']}', '^~' */
|
||
|
+#define isupper(x) (x < 'a'? 1: 0)
|
||
|
+#define islower(x) (x >= 'a'? 1: 0)
|
||
|
+#define toupper(x) (x < 'a'? x: x-32)
|
||
|
+#define tolower(x) (x >= 'a'? x: x+32)
|
||
|
|
||
|
/*###### Exit/Interrput routines #######################################*/
|
||
|
|
||
|
// The usual program end -- called only by functions in this section.
|
||
|
@@ -1220,8 +1228,9 @@ static proc_t **procs_refresh (proc_t **
|
||
|
// (own identifiers as documentation and protection against changes)
|
||
|
#define L_stat PROC_FILLSTAT
|
||
|
#define L_statm PROC_FILLMEM
|
||
|
#define L_status PROC_FILLSTATUS
|
||
|
+#define L_oom PROC_FILLOOM
|
||
|
#define L_CMDLINE L_EITHER | PROC_FILLARG
|
||
|
#define L_EUSER PROC_FILLUSR
|
||
|
#define L_RUSER L_status | PROC_FILLUSR
|
||
|
#define L_GROUP L_status | PROC_FILLGRP
|
||
|
@@ -1273,8 +1282,10 @@ static FLD_t Fieldstab[] = {
|
||
|
{ "XxXx", " COMMAND", " %-*.*s", -1, -1, SF(CMD), "Command name/line", L_EITHER },
|
||
|
{ "YyUu", " WCHAN ", " %-9.9s", -1, -1, SF(WCH), "Sleeping in Function", L_stat },
|
||
|
// next entry's special: the 0's will be replaced with '.'!
|
||
|
{ "ZzZz", " Flags ", " %08lx", -1, -1, SF(FLG), "Task Flags <sched.h>", L_stat },
|
||
|
+ { "[{[{", " Badness", "%8d", -1, -1, SF(OOM), "oom_score (badness)", L_oom },
|
||
|
+ { "\\|\\|", " Adj", " %3d", -1, -1, SF(OOA), "oom_adjustment (2^X)", L_oom },
|
||
|
#if 0
|
||
|
{ "..Qq", " A", " %4.4s", 4, SK_no, SF(PID), "Accessed Page count", L_stat },
|
||
|
{ "..Nn", " TRS", " %4.4s", 4, SK_Kb, SF(PID), "Code in memory (kb)", L_stat },
|
||
|
{ "..Rr", " WP", " %4.4s", 4, SK_no, SF(PID), "Unwritable Pages", L_stat },
|
||
|
@@ -1285,8 +1296,10 @@ static FLD_t Fieldstab[] = {
|
||
|
#endif
|
||
|
};
|
||
|
#undef SF
|
||
|
|
||
|
+/* Last valid lowercase letter (z is folowed by {|}~, Z by [\\]^) */
|
||
|
+#define LAST_CHR '|'
|
||
|
|
||
|
/* All right, those-that-follow -- Listen Up!
|
||
|
* For the above table keys and the following present/future rc file
|
||
|
* compatibility support, you have Mr. Albert D. Cahalan to thank.
|
||
|
@@ -1419,8 +1432,21 @@ static int rc_read_new (const char *cons
|
||
|
RCW_t *ptr = &rc->win[i];
|
||
|
cnt = sscanf(cp, "%3s\tfieldscur=%31s\n", ptr->winname, ptr->fieldscur);
|
||
|
if (cnt != 2) return 5+100*i; // OK to have less than 4 windows
|
||
|
if (WINNAMSIZ <= strlen(ptr->winname)) return -6;
|
||
|
+ /* Handle upgrade */
|
||
|
+ if (strlen(DEF_FIELDS) - strlen(ptr->fieldscur) == 2) {
|
||
|
+ const int ln = strlen(ptr->fieldscur);
|
||
|
+ const unsigned char last = ptr->fieldscur[ln-1];
|
||
|
+ /* If last field is command, insert two new fields prior to it */
|
||
|
+ if (last == 'x' || last == 'X') {
|
||
|
+ ptr->fieldscur[ln-1] = '{';
|
||
|
+ ptr->fieldscur[ln ] = '|';
|
||
|
+ ptr->fieldscur[ln+1] = last;
|
||
|
+ ptr->fieldscur[ln+2] = 0;
|
||
|
+ } else
|
||
|
+ strcat(ptr->fieldscur, "{|");
|
||
|
+ }
|
||
|
if (strlen(DEF_FIELDS) != strlen(ptr->fieldscur)) return -7;
|
||
|
cp = strchr(cp, '\n');
|
||
|
if (!cp++) return -(8+100*i);
|
||
|
|
||
|
@@ -1694,9 +1720,9 @@ static void confighlp (char *fields) {
|
||
|
else lower[c&0x1f]++;
|
||
|
}
|
||
|
|
||
|
c = 'a';
|
||
|
- while (c <= 'z') {
|
||
|
+ while (c <= LAST_CHR) {
|
||
|
if (upper[c&0x1f] && lower[c&0x1f]) {
|
||
|
lower[c&0x1f] = 0; // got both, so wipe out unseen column
|
||
|
for (;;) {
|
||
|
cp = strchr(fields, c);
|
||
|
@@ -3198,9 +3224,14 @@ static void task_show (const WIN_t *q, c
|
||
|
} else {
|
||
|
MKCOL(lookup_wchan(p->wchan, p->XXXID));
|
||
|
}
|
||
|
break;
|
||
|
-
|
||
|
+ case P_OOM:
|
||
|
+ MKCOL(p->oom_score);
|
||
|
+ break;
|
||
|
+ case P_OOA:
|
||
|
+ MKCOL(p->oom_adj);
|
||
|
+ break;
|
||
|
} /* end: switch 'procflag' */
|
||
|
|
||
|
rp = scat(rp, cbuf+advance);
|
||
|
} /* end: for 'maxpflgs' */
|
||
|
Index: procps-3.2.7/top.h
|
||
|
===================================================================
|
||
|
--- procps-3.2.7.orig/top.h
|
||
|
+++ procps-3.2.7/top.h
|
||
|
@@ -250,9 +250,10 @@ enum pflag {
|
||
|
P_PRI, P_NCE,
|
||
|
P_CPN, P_CPU, P_TME, P_TM2,
|
||
|
P_MEM, P_VRT, P_SWP, P_RES, P_COD, P_DAT, P_SHR,
|
||
|
P_FLT, P_DRT,
|
||
|
- P_STA, P_CMD, P_WCH, P_FLG
|
||
|
+ P_STA, P_CMD, P_WCH, P_FLG,
|
||
|
+ P_OOM, P_OOA,
|
||
|
};
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
@@ -350,15 +351,15 @@ typedef struct WIN_t {
|
||
|
#define RCF_EYECATCHER "RCfile for "
|
||
|
#define RCF_DEPRECATED "Id:a, "
|
||
|
|
||
|
// The default fields displayed and their order,
|
||
|
-#define DEF_FIELDS "AEHIOQTWKNMbcdfgjplrsuvyzX"
|
||
|
+#define DEF_FIELDS "AEHIOQTWKNMbcdfgjplrsuvyz{|X"
|
||
|
// Pre-configured field groupss
|
||
|
-#define JOB_FIELDS "ABcefgjlrstuvyzMKNHIWOPQDX"
|
||
|
-#define MEM_FIELDS "ANOPQRSTUVbcdefgjlmyzWHIKX"
|
||
|
-#define USR_FIELDS "ABDECGfhijlopqrstuvyzMKNWX"
|
||
|
+#define JOB_FIELDS "ABcefgjlrstuvyzMKNHIWOPQD{|X"
|
||
|
+#define MEM_FIELDS "ANOPQRSTUVbcdefgjlmyzWHIK{|X"
|
||
|
+#define USR_FIELDS "ABDECGfhijlopqrstuvyzMKNW{|X"
|
||
|
// Used by fields_sort, placed here for peace-of-mind
|
||
|
-#define NUL_FIELDS "abcdefghijklmnopqrstuvwxyz"
|
||
|
+#define NUL_FIELDS "abcdefghijklmnopqrstuvwxyz{|"
|
||
|
|
||
|
|
||
|
// The default values for the local config file
|
||
|
#define DEF_RCFILE { \
|
||
|
Index: procps-3.2.7/proc/readproc.h
|
||
|
===================================================================
|
||
|
--- procps-3.2.7.orig/proc/readproc.h
|
||
|
+++ procps-3.2.7/proc/readproc.h
|
||
|
@@ -138,9 +138,11 @@ typedef struct proc_t {
|
||
|
fuid, fgid, // status fs (used for file access only)
|
||
|
tpgid, // stat terminal process group id
|
||
|
exit_signal, // stat might not be SIGCHLD
|
||
|
processor; // stat current (or most recent?) CPU
|
||
|
- char **cgroup; // cgroup current cgroup, looks like a classic filepath
|
||
|
+ int oom_score, // oom_score (badness for OOM killer)
|
||
|
+ oom_adj; // oom_adj (adjustment to OOM score)
|
||
|
+ char **cgroup; // cgroup current cgroup, looks like a classic filepath
|
||
|
} proc_t;
|
||
|
|
||
|
// PROCTAB: data structure holding the persistent information readproc needs
|
||
|
// from openproc(). The setup is intentionally similar to the dirent interface
|
||
|
@@ -240,8 +242,9 @@ extern proc_t * get_proc_stats(pid_t pid
|
||
|
|
||
|
#define PROC_LOOSE_TASKS 0x0200 // threat threads as if they were processes
|
||
|
|
||
|
#define PROC_FILLCGROUP 0x0400 // alloc and fill in `cgroup`
|
||
|
+#define PROC_FILLOOM 0x0800 // alloc and fill in oom_score, oom_adj
|
||
|
|
||
|
// Obsolete, consider only processes with one of the passed:
|
||
|
#define PROC_PID 0x1000 // process id numbers ( 0 terminated)
|
||
|
#define PROC_UID 0x4000 // user id numbers ( length needed )
|
||
|
Index: procps-3.2.7/proc/readproc.c
|
||
|
===================================================================
|
||
|
--- procps-3.2.7.orig/proc/readproc.c
|
||
|
+++ procps-3.2.7/proc/readproc.c
|
||
|
@@ -331,8 +331,19 @@ ENTER(0x220);
|
||
|
LEAVE(0x220);
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////
|
||
|
+static void oomscore2proc(const char* S, proc_t *restrict P)
|
||
|
+{
|
||
|
+ sscanf(S, "%d", &P->oom_score);
|
||
|
+}
|
||
|
+
|
||
|
+static void oomadj2proc(const char* S, proc_t *restrict P)
|
||
|
+{
|
||
|
+ sscanf(S, "%d", &P->oom_adj);
|
||
|
+}
|
||
|
+
|
||
|
+///////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// Reads /proc/*/stat files, being careful not to trip over processes with
|
||
|
// names like ":-) 1 2 3 4 5 6".
|
||
|
static void stat2proc(const char* S, proc_t *restrict P) {
|
||
|
@@ -616,8 +627,15 @@ static proc_t* simple_readproc(PROCTAB *
|
||
|
p->environ = file2strvec(path, "environ");
|
||
|
else
|
||
|
p->environ = NULL;
|
||
|
|
||
|
+ if (unlikely(flags & PROC_FILLOOM)) {
|
||
|
+ if (likely( file2str(path, "oom_score", sbuf, sizeof sbuf) != -1 ))
|
||
|
+ oomscore2proc(sbuf, p);
|
||
|
+ if (likely( file2str(path, "oom_adj", sbuf, sizeof sbuf) != -1 ))
|
||
|
+ oomadj2proc(sbuf, p);
|
||
|
+ } /* struct has been zeroed out before, so no worries about clearing garbage here */
|
||
|
+
|
||
|
if(linux_version_code>=LINUX_VERSION(2,6,24) && (flags & PROC_FILLCGROUP)) {
|
||
|
p->cgroup = file2strvec(path, "cgroup"); /* read /proc/#/cgroup */
|
||
|
if(p->cgroup && *p->cgroup) {
|
||
|
int i = strlen(*p->cgroup);
|