[procps] [PATCH 4/4] Add various changes mainly for/to top

  • From: Werner Fink <werner@xxxxxxx>
  • To: undisclosed-recipients: ;
  • Date: Mon, 20 Dec 2010 15:13:56 +0100

 Top: Support more than 99 CPU's
 Top: Support hotpluggable CPU's
 Top: Fix the rc file handling
 Top: EOF from terminal is not a kernel bug
 Top: Show oom score
 Top: Ignore SIGHUP if we are in the batch mode
 Top: Save CPU states before override them
 Top: Avoid crash if window is too small for memory info
 Top/vmstat: Support systems with terabyte of physical ram
 Top: Avoid wrong error message on one detected CPU
 Only detect nummer of CPU's if really required

Signed-off-by: Werner Fink <werner@xxxxxxx>

diff --git a/proc/readproc.c b/proc/readproc.c
index f199c26..b6b74fd 100644
--- a/proc/readproc.c
+++ b/proc/readproc.c
@@ -365,6 +365,17 @@ 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".
@@ -635,6 +646,13 @@ static proc_t* simple_readproc(PROCTAB *restrict const PT, 
proc_t *restrict cons
     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) {
diff --git a/proc/readproc.h b/proc/readproc.h
index 0b2c46a..41c42b6 100644
--- a/proc/readproc.h
+++ b/proc/readproc.h
@@ -140,7 +140,9 @@ typedef struct proc_t {
        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
@@ -240,6 +242,7 @@ extern proc_t * get_proc_stats(pid_t pid, proc_t *p);
 #define PROC_FILLARG         0x0100 // alloc and fill in `cmdline'
 #define PROC_FILLCGROUP      0x0200 // alloc and fill in `cgroup`
 
+#define PROC_FILLOOM         0x0800 // alloc and fill in oom_score, oom_adj
 #define PROC_LOOSE_TASKS     0x2000 // threat threads as if they were processes
 
 // Obsolete, consider only processes with one of the passed:
diff --git a/proc/sysinfo.c b/proc/sysinfo.c
index 876ddbf..c626912 100644
--- a/proc/sysinfo.c
+++ b/proc/sysinfo.c
@@ -24,8 +24,6 @@
 #include <netinet/in.h>  /* htons */
 #endif
 
-long smp_num_cpus;     /* number of CPUs */
-
 #define BAD_OPEN_MESSAGE                                       \
 "Error: /proc must be mounted\n"                               \
 "  To mount /proc at boot you need an /etc/fstab line like:\n" \
@@ -180,7 +178,7 @@ static void old_Hertz_hack(void){
   setlocale(LC_NUMERIC, savelocale);
   jiffies = user_j + nice_j + sys_j + other_j;
   seconds = (up_1 + up_2) / 2;
-  h = (unsigned)( (double)jiffies/seconds/smp_num_cpus );
+  h = (unsigned)( (double)jiffies/seconds/smp_num_cpus() );
   /* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
   switch(h){
   case    9 ...   11 :  Hertz =   10; break; /* S/390 (sometimes) */
@@ -246,9 +244,14 @@ static int check_for_privs(void){
   return !!rc;
 }
 
-static void init_libproc(void) __attribute__((constructor (102)));
-static void init_libproc(void){
-  have_privs = check_for_privs();
+
+long smp_num_cpus(void)
+{
+  static long _smp_num_cpus=-1;     /* number of CPUs */
+
+  if (_smp_num_cpus != -1)
+    return(_smp_num_cpus);
+
   // ought to count CPUs in /proc/stat instead of relying
   // on glibc, which foolishly tries to parse /proc/cpuinfo
   //
@@ -256,8 +259,15 @@ static void init_libproc(void){
   // appears to have a non-SMP kernel on a 2-way SMP box.
   // _SC_NPROCESSORS_CONF returns 2, resulting in HZ=512
   // _SC_NPROCESSORS_ONLN returns 1, which should work OK
-  smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
-  if(smp_num_cpus<1) smp_num_cpus=1; /* SPARC glibc is buggy */
+  _smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+  if(_smp_num_cpus<1) _smp_num_cpus=1; /* SPARC glibc is buggy */
+
+  return(_smp_num_cpus);
+}
+
+static void init_libproc(void) __attribute__((constructor (102)));
+static void init_libproc(void){
+  have_privs = check_for_privs();
 
   if(linux_version_code > LINUX_VERSION(2, 4, 0)){ 
     Hertz = find_elf_note(AT_CLKTCK);
diff --git a/proc/sysinfo.h b/proc/sysinfo.h
index 97ae818..c05835f 100644
--- a/proc/sysinfo.h
+++ b/proc/sysinfo.h
@@ -7,7 +7,7 @@
 EXTERN_C_BEGIN
 
 extern unsigned long long Hertz;   /* clock tick frequency */
-extern long smp_num_cpus;     /* number of CPUs */
+extern long smp_num_cpus(void);    /* number of CPUs */
 extern int have_privs;     /* boolean, true if setuid or similar */
 
 #if 0
diff --git a/top.c b/top.c
index 1f581d1..7acf92b 100644
--- a/top.c
+++ b/top.c
@@ -24,7 +24,7 @@
 #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>
@@ -89,6 +89,10 @@ static int   Monpidsidx = 0;
 static char Msg_delayed [SMLBUFSIZ];
 static int  Msg_awaiting = 0;
 
+       /* Show memory by default as kB */
+static int shift = 10;
+#define S(X)   (unsigned long)(((unsigned long long)(X)<<10)>>shift)
+
 // This is the select() timeout. Clear it in sig handlers to avoid a race.
 // (signal happens just as we are about to select() and thus does not
 // break us out of the select(), causing us to delay until timeout)
@@ -224,6 +228,9 @@ 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
@@ -316,6 +323,11 @@ 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  #######################################*/
 
@@ -921,6 +933,7 @@ static void *alloc_r (void *q, unsigned numb)
 static CPU_t *cpus_refresh (CPU_t *cpus)
 {
    static FILE *fp = NULL;
+   static int cpu_max;
    int i;
    int num;
    // enough for a /proc/stat CPU line (not the intr line)
@@ -935,36 +948,42 @@ static CPU_t *cpus_refresh (CPU_t *cpus)
                can hold tics representing the /proc/stat cpu summary (the first
                line read) -- that slot supports our View_CPUSUM toggle */
       cpus = alloc_c((1 + Cpu_tot) * sizeof(CPU_t));
-   }
+      cpu_max = Cpu_tot;
+   } else if (cpu_max > Cpu_tot)
+      /* move saved CUPs summary to cpu_max possition */
+      memcpy(&cpus[cpu_max], &cpus[Cpu_tot], sizeof(CPU_t));
+
    rewind(fp);
    fflush(fp);
 
+ /* save the previous values of cpus[Cpu_tot](i.e. u_sav, s_sav, n_sav, i_sav,
+    * w_sav, x_sav, y_sav) to cpus[cpu_max] before any changes to cpus[], so 
these
+    * values are not overwritten when copying cpus[cpu_max] back to 
cpus[Cpu_tot]
+    * at the end of this function.
+    */
+   if (cpu_max != Cpu_tot)
+      memcpy(&cpus[cpu_max], &cpus[Cpu_tot], sizeof(CPU_t));
+
    // first value the last slot with the cpu summary line
    if (!fgets(buf, sizeof(buf), fp)) std_err("failed /proc/stat read");
-   cpus[Cpu_tot].x = 0;  // FIXME: can't tell by kernel version number
-   cpus[Cpu_tot].y = 0;  // FIXME: can't tell by kernel version number
-   cpus[Cpu_tot].z = 0;  // FIXME: can't tell by kernel version number
+   cpus[cpu_max].x = 0;  // FIXME: can't tell by kernel version number
+   cpus[cpu_max].y = 0;  // FIXME: can't tell by kernel version number
+   cpus[cpu_max].z = 0;  // FIXME: can't tell by kernel version number
    num = sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu",
-      &cpus[Cpu_tot].u,
-      &cpus[Cpu_tot].n,
-      &cpus[Cpu_tot].s,
-      &cpus[Cpu_tot].i,
-      &cpus[Cpu_tot].w,
-      &cpus[Cpu_tot].x,
-      &cpus[Cpu_tot].y,
-      &cpus[Cpu_tot].z
+      &cpus[cpu_max].u,
+      &cpus[cpu_max].n,
+      &cpus[cpu_max].s,
+      &cpus[cpu_max].i,
+      &cpus[cpu_max].w,
+      &cpus[cpu_max].x,
+      &cpus[cpu_max].y,
+      &cpus[cpu_max].z
    );
    if (num < 4)
          std_err("failed /proc/stat read");
 
-   // and just in case we're 2.2.xx compiled without SMP support...
-   if (Cpu_tot == 1) {
-      cpus[1].id = 0;
-      memcpy(cpus, &cpus[1], sizeof(CPU_t));
-   }
-
    // now value each separate cpu's tics
-   for (i = 0; 1 < Cpu_tot && i < Cpu_tot; i++) {
+   for (i = 0; ; i++) {
       if (!fgets(buf, sizeof(buf), fp)) std_err("failed /proc/stat read");
       cpus[i].x = 0;  // FIXME: can't tell by kernel version number
       cpus[i].y = 0;  // FIXME: can't tell by kernel version number
@@ -973,9 +992,28 @@ static CPU_t *cpus_refresh (CPU_t *cpus)
          &cpus[i].id,
          &cpus[i].u, &cpus[i].n, &cpus[i].s, &cpus[i].i, &cpus[i].w, 
&cpus[i].x, &cpus[i].y, &cpus[i].z
       );
-      if (num < 4)
-            std_err("failed /proc/stat read");
+      if (num < 4) {
+        Cpu_tot = i;
+        break;
+      }
+      if (i == cpu_max - 1) {
+        // Bump cpu_max and extend cpus
+        cpu_max++;
+        cpus = realloc(cpus, (1 + cpu_max) * sizeof(CPU_t));
+        if (!cpus) std_err("realloc failed");
+        memcpy(&cpus[cpu_max], &cpus[cpu_max-1], sizeof(CPU_t));
+      }
    }
+
+   if (cpu_max > Cpu_tot)
+      memcpy(&cpus[Cpu_tot], &cpus[cpu_max], sizeof(CPU_t));
+
+   // and just in case we're 2.2.xx compiled without SMP support...
+   if (Cpu_tot == 1) {
+      cpus[1].id = 0;
+      memcpy(cpus, &cpus[1], sizeof(CPU_t));
+   }
+   
    return cpus;
 }
 
@@ -1204,6 +1242,7 @@ static proc_t **procs_refresh (proc_t **table, int flags)
 #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
@@ -1237,7 +1276,7 @@ static FLD_t Fieldstab[] = {
    { "GgGg", " TTY     ",   " %-8.8s",   8,    -1, SF(TTY), "Controlling Tty", 
     L_stat   },
    { "HhHh", "  PR",        " %3d",     -1,    -1, SF(PRI), "Priority",        
     L_stat   },
    { "IiIi", "  NI",        " %3d",     -1,    -1, SF(NCE), "Nice value",      
     L_stat   },
-   { "JjYy", " #C",         " %2u",     -1,    -1, SF(CPN), "Last used cpu 
(SMP)",  L_stat   },
+   { "JjYy", " #C",         " %3u",     -1,    -1, SF(CPN), "Last used cpu 
(SMP)",  L_stat   },
    { "KkEe", " %CPU",       " %#4.1f",  -1,    -1, SF(CPU), "CPU usage",       
     L_stat   },
    { "LlWw", "   TIME",     " %6.6s",    6,    -1, SF(TME), "CPU Time",        
     L_stat   },
    { "MmRr", "    TIME+ ",  " %9.9s",    9,    -1, SF(TME), "CPU Time, 
hundredths", L_stat   },
@@ -1257,11 +1296,13 @@ static FLD_t Fieldstab[] = {
    { "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   },
-   { "Jj[{", " #C",         " %2u",     -1,    -1, SF(CPN), "Last used cpu 
(SMP)",  L_stat   },
+   { "Jj[{", " #C",         " %3u",     -1,    -1, SF(CPN), "Last used cpu 
(SMP)",  L_stat   },
    { "..\\|"," Bad",        " %2u",     -1,    -1, SF(CPN), "-- must ignore | 
--",  0        },
    { "..]}", " Bad",        " %2u",     -1,    -1, SF(CPN), "-- not used --",  
     0        },
    { "..^~", " Bad",        " %2u",     -1,    -1, SF(CPN), "-- not used --",  
     0        },
@@ -1269,6 +1310,8 @@ static FLD_t Fieldstab[] = {
 };
 #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
@@ -1403,6 +1446,19 @@ static int rc_read_new (const char *const buf, RCF_t 
*rc) {
       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);
@@ -1608,7 +1664,7 @@ static void before (char *me)
    if (Myname) ++Myname; else Myname = me;
 
       /* establish cpu particulars -- even bigger! */
-   Cpu_tot = smp_num_cpus;
+   Cpu_tot = smp_num_cpus();
    if (linux_version_code > LINUX_VERSION(2, 5, 41))
       States_fmts = STATES_line2x5;
    if (linux_version_code >= LINUX_VERSION(2, 6, 0))  // grrr... only some 
2.6.0-testX :-(
@@ -1628,15 +1684,15 @@ static void before (char *me)
 
    Fieldstab[P_CPN].head = " P";
    Fieldstab[P_CPN].fmts = " %1u";
-   if(smp_num_cpus>9){
+   if(smp_num_cpus()>9){
       Fieldstab[P_CPN].head = "  P";
       Fieldstab[P_CPN].fmts = " %2u";
    }
-   if(smp_num_cpus>99){
+   if(smp_num_cpus()>99){
       Fieldstab[P_CPN].head = "   P";
       Fieldstab[P_CPN].fmts = " %3u";
    }
-   if(smp_num_cpus>999){
+   if(smp_num_cpus()>999){
       Fieldstab[P_CPN].head = "    P";
       Fieldstab[P_CPN].fmts = " %4u";
    }
@@ -1678,7 +1734,7 @@ static void confighlp (char *fields) {
    }
 
    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 (;;) {
@@ -1783,7 +1839,7 @@ static void configs_read (void)
       confighlp(Winstk[i].rc.fieldscur);
    }
 
-   if(Rc.mode_irixps && smp_num_cpus>1){
+   if(Rc.mode_irixps && smp_num_cpus()>1){
       // good for 100 CPUs per process
       pcpu_max_value = 9999.0;
       Fieldstab[P_CPU].fmts = " %4.0f";
@@ -2476,7 +2532,10 @@ static void windows_stage2 (void)
    int i;
 
    for (i = 0; i < GROUPSMAX; i++) {
-      win_names(&Winstk[i], Winstk[i].rc.winname);
+      /* Please, never use something like sprintf(x, "%s", x); ... see 
win_names() */
+      char buf[WINNAMSIZ];
+      strncpy(buf, Winstk[i].rc.winname, WINNAMSIZ);
+      win_names(&Winstk[i], buf);
       capsmk(&Winstk[i]);
    }
    // rely on this next guy to force a call (eventually) to reframewins
@@ -2494,21 +2553,21 @@ static void do_key (unsigned c)
    static const char err_num_cpus[] = "\aSorry, terminal is not big enough";
 #ifdef WARN_NOT_SMP
    // standardized 'smp' errors
-   static const char err_smp[] = "\aSorry, only 1 cpu detected";
+   static const char err_smp[] = "\aSorry, only one cpu detected";
 #endif
 
    switch (c) {
       case '1':
          if (Cpu_tot+7 > Screen_rows && CHKw(Curwin, View_CPUSUM)) {
             show_msg(err_num_cpus);
-            break;
-         }
+         } else {
 #ifdef WARN_NOT_SMP
          if (Cpu_tot > 1) TOGw(Curwin, View_CPUSUM);
          else show_msg(err_smp);
 #else
          TOGw(Curwin, View_CPUSUM);
 #endif
+        }
          break;
 
       case 'a':
@@ -2631,7 +2690,7 @@ static void do_key (unsigned c)
          Rc.mode_irixps = !Rc.mode_irixps;
          show_msg(fmtmk("Irix mode %s", Rc.mode_irixps ? "On" : "Off"));
 #endif
-         if(Rc.mode_irixps && smp_num_cpus>1){
+         if(Rc.mode_irixps && smp_num_cpus()>1){
             // good for 100 CPUs per process
             pcpu_max_value = 9999.0;
             Fieldstab[P_CPU].fmts = " %4.0f";
@@ -2969,7 +3028,7 @@ static proc_t **summary_show (void)
    p_table = procs_refresh(p_table, Frames_libflags);
 
    // Display Uptime and Loadavg
-   if (CHKw(Curwin, View_LOADAV)) {
+   if (CHKw(Curwin, View_LOADAV) && (Screen_rows > Msg_row+2)) {
       if (!Rc.mode_altscr) {
          show_special(0, fmtmk(LOADAV_line, Myname, sprint_uptime()));
       } else {
@@ -2986,7 +3045,7 @@ static proc_t **summary_show (void)
    }
 
    // Display Task and Cpu(s) States
-   if (CHKw(Curwin, View_STATES)) {
+   if (CHKw(Curwin, View_STATES) && (Screen_rows > Msg_row+2)) {
       show_special(
          0,
          fmtmk(
@@ -3000,25 +3059,56 @@ static proc_t **summary_show (void)
 
       if (CHKw(Curwin, View_CPUSUM)) {
          // display just the 1st /proc/stat line
+         if (Screen_rows <= Msg_row+2)
+            goto skip;
          summaryhlp(&smpcpu[Cpu_tot], "Cpu(s):");
       } else {
          int i;
          char tmp[SMLBUFSIZ];
          // display each cpu's states separately
+         if (Screen_rows <= Msg_row+Cpu_tot+1) {
+            show_msg("\aSorry, terminal is not big enough\n");
+            TOGw(Curwin, View_CPUSUM);
+            goto skip;
+         }
          for (i = 0; i < Cpu_tot; i++) {
             snprintf(tmp, sizeof(tmp), "Cpu%-3d:", smpcpu[i].id);
             summaryhlp(&smpcpu[i], tmp);
          }
       }
    }
+skip:
 
    // Display Memory and Swap stats
    meminfo();
-   if (CHKw(Curwin, View_MEMORY)) {
-      show_special(0, fmtmk(MEMORY_line1
-         , kb_main_total, kb_main_used, kb_main_free, kb_main_buffers));
-      show_special(0, fmtmk(MEMORY_line2
-         , kb_swap_total, kb_swap_used, kb_swap_free, kb_main_cached));
+   if (CHKw(Curwin, View_MEMORY) && (Screen_rows > Msg_row+3)) {
+      const char *line1, *line2;
+      if (kb_main_total > 9999999)
+         shift = 20;
+      if (kb_main_total > 9999999999)
+         shift = 30;
+      switch (shift) {
+      case 20:
+        line1 = MEMORY_line1m;
+        line2 = MEMORY_line2m;
+        break;
+      case 30:
+        line1 = MEMORY_line1g;
+        line2 = MEMORY_line2g;
+        break;
+      case 0:
+        line1 = MEMORY_line1b;
+        line2 = MEMORY_line2b;
+        break;
+      default:
+      case 10:
+        line1 = MEMORY_line1k;
+        line2 = MEMORY_line2k;
+      }
+      show_special(0, fmtmk(line1
+         , S(kb_main_total), S(kb_main_used), S(kb_main_free), 
S(kb_main_buffers)));
+      show_special(0, fmtmk(line2
+         , S(kb_swap_total), S(kb_swap_used), S(kb_swap_free), 
S(kb_main_cached)));
       Msg_row += 2;
    }
 
@@ -3176,7 +3266,12 @@ static void task_show (const WIN_t *q, const proc_t *p)
                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);
@@ -3356,7 +3451,8 @@ int main (int dont_care_argc, char *argv[])
    windows_stage2();                    //                 as bottom slice
                                         //                 +-------------+
    signal(SIGALRM,  end_pgm);
-   signal(SIGHUP,   end_pgm);
+   if (!Batch)
+          signal(SIGHUP,   end_pgm);
    signal(SIGINT,   end_pgm);
    signal(SIGPIPE,  end_pgm);
    signal(SIGQUIT,  end_pgm);
@@ -3399,7 +3495,7 @@ int main (int dont_care_argc, char *argv[])
          if (rc <= 0) {
             // EOF is pretty much a "can't happen" except for a kernel bug.
             // We should quickly die via SIGHUP, and thus not spin here.
-            // if (rc == 0) end_pgm(0); /* EOF from terminal */
+            if (rc == 0) end_pgm(0); /* EOF from terminal */
             fcntl(STDIN_FILENO, F_SETFL, file_flags);
             select(1, &fs, NULL, NULL, &tv);
             fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK|file_flags);
diff --git a/top.h b/top.h
index b4ac079..5232a1d 100644
--- a/top.h
+++ b/top.h
@@ -132,6 +132,7 @@
 #define _PUFF(fmt,arg...)                               \
 do {                                                     \
    char _str[ROWBUFSIZ];                                   \
+   if (Pseudo_row >= Screen_rows-1) break;                   \
    int _len = 1 + snprintf(_str, sizeof(_str), fmt, ## arg);   \
    putp ( Batch ? _str :                                   \
    ({                                                 \
@@ -250,7 +251,8 @@ enum pflag {
    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,13 +352,13 @@ typedef struct WIN_t {
 #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
@@ -391,17 +393,29 @@ typedef struct WIN_t {
    " %#4.1f%% \02us,\03 %#4.1f%% \02sy,\03 %#4.1f%% \02ni,\03 %#4.1f%% 
\02id,\03 %#4.1f%% \02wa,\03 %#4.1f%% \02hi,\03 %#4.1f%% \02si\03\n"
 #define STATES_line2x7  "%s\03" \
    
"%#5.1f%%\02us,\03%#5.1f%%\02sy,\03%#5.1f%%\02ni,\03%#5.1f%%\02id,\03%#5.1f%%\02wa,\03%#5.1f%%\02hi,\03%#5.1f%%\02si,\03%#5.1f%%\02st\03\n"
+#define MEMORY_line1b  "Mem: \03" \
+   " %8lub \02total,\03 %8lub \02used,\03 %8lub \02free,\03 %8lub 
\02buffers\03\n"
+#define MEMORY_line2b  "Swap:\03" \
+   " %8lub \02total,\03 %8lub \02used,\03 %8lub \02free,\03 %8lub 
\02cached\03\n"
 #ifdef CASEUP_SUMMK
-#define MEMORY_line1  "Mem: \03" \
+#define MEMORY_line1k  "Mem: \03" \
    " %8luK \02total,\03 %8luK \02used,\03 %8luK \02free,\03 %8luK 
\02buffers\03\n"
-#define MEMORY_line2  "Swap:\03" \
+#define MEMORY_line2k  "Swap:\03" \
    " %8luK \02total,\03 %8luK \02used,\03 %8luK \02free,\03 %8luK 
\02cached\03\n"
 #else
-#define MEMORY_line1  "Mem: \03" \
+#define MEMORY_line1k  "Mem: \03" \
    " %8luk \02total,\03 %8luk \02used,\03 %8luk \02free,\03 %8luk 
\02buffers\03\n"
-#define MEMORY_line2  "Swap:\03" \
+#define MEMORY_line2k  "Swap:\03" \
    " %8luk \02total,\03 %8luk \02used,\03 %8luk \02free,\03 %8luk 
\02cached\03\n"
 #endif
+#define MEMORY_line1m  "Mem: \03" \
+   " %8luM \02total,\03 %8luM \02used,\03 %8luM \02free,\03 %8luM 
\02buffers\03\n"
+#define MEMORY_line2m  "Swap:\03" \
+   " %8luM \02total,\03 %8luM \02used,\03 %8luM \02free,\03 %8luM 
\02cached\03\n"
+#define MEMORY_line1g  "Mem: \03" \
+   " %8luG \02total,\03 %8luG \02used,\03 %8luG \02free,\03 %8luG 
\02buffers\03\n"
+#define MEMORY_line2g  "Swap:\03" \
+   " %8luG \02total,\03 %8luG \02used,\03 %8luG \02free,\03 %8luG 
\02cached\03\n"
 
 // Keyboard Help specially formatted string(s) --
 // see 'show_special' for syntax details + other cautions.
diff --git a/vmstat.c b/vmstat.c
index 28e3a51..772df9c 100644
--- a/vmstat.c
+++ b/vmstat.c
@@ -165,9 +165,9 @@ static void new_header(void){
 
 ////////////////////////////////////////////////////////////////////////////
 
-static unsigned long unitConvert(unsigned int size){
- float cvSize;
- cvSize=(float)size/dataUnit*((statMode==SLABSTAT)?1:1024);
+static unsigned long unitConvert(unsigned long size){
+ long double cvSize;
+ cvSize=(long double)size/dataUnit*((statMode==SLABSTAT)?1:1024);
  return ((unsigned long) cvSize);
 }
 
-- 
1.6.0.2

Other related posts:

  • » [procps] [PATCH 4/4] Add various changes mainly for/to top - Werner Fink