procps/procps-3.2.7-oom.diff

227 lines
8.7 KiB
Diff
Raw Normal View History

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);