]> granicus.if.org Git - procps-ng/commitdiff
handle Linux 2.5.xx ABI
authoralbert <>
Sun, 6 Oct 2002 16:46:06 +0000 (16:46 +0000)
committeralbert <>
Sun, 6 Oct 2002 16:46:06 +0000 (16:46 +0000)
oldtop.c
proc/sysinfo.c
proc/sysinfo.h
top.c
top.h
vmstat.c

index 2faaf0cfbc40c857f28b4b2a17bcf05bd0f2c8d0..5593d671dead35f2a5cc253190123379cc7a6ca1 100644 (file)
--- a/oldtop.c
+++ b/oldtop.c
@@ -1303,6 +1303,52 @@ static void show_meminfo(void)
 }
 
 
+/***********************************************************************
+ * The /proc filesystem calculates idle=jiffies-(user+nice+sys) and we
+ * recover jiffies by adding up the 4 numbers we are given. SMP kernels
+ * (as of pre-2.4 era) can report idle time going backwards, perhaps due
+ * to non-atomic reads and updates. There is no locking for these values.
+ */
+#ifndef NAN
+#define NAN (-0.0)
+#endif
+#define JT unsigned long long
+static void four_cpu_numbers(double *uret, double *nret, double *sret, double *iret){
+    double tmp_u, tmp_n, tmp_s, tmp_i;
+    double scale;  /* scale values to % */
+    static JT old_u, old_n, old_s, old_i;
+    JT new_u, new_n, new_s, new_i;
+    JT ticks_past; /* avoid div-by-0 by not calling too often :-( */
+    FILE_TO_BUF(STAT_FILE,stat_fd);
+    sscanf(buf, "cpu %Lu %Lu %Lu %Lu", &new_u, &new_n, &new_s, &new_i);
+    ticks_past = (new_u+new_n+new_s+new_i)-(old_u+old_n+old_s+old_i);
+    if(ticks_past){
+      scale = 100.0 / (double)ticks_past;
+      tmp_u = ( (double)new_u - (double)old_u ) * scale;
+      tmp_n = ( (double)new_n - (double)old_n ) * scale;
+      tmp_s = ( (double)new_s - (double)old_s ) * scale;
+      tmp_i = ( (double)new_i - (double)old_i ) * scale;
+    }else{
+      tmp_u = NAN;
+      tmp_n = NAN;
+      tmp_s = NAN;
+      tmp_i = NAN;
+    }
+    SET_IF_DESIRED(uret, tmp_u);
+    SET_IF_DESIRED(nret, tmp_n);
+    SET_IF_DESIRED(sret, tmp_s);
+    SET_IF_DESIRED(iret, tmp_i);
+    old_u=new_u;
+    old_n=new_n;
+    old_s=new_s;
+    old_i=new_i;
+}
+#undef JT
+
+/***********************************************************************/
+
+
 /*
  * Calculates the number of tasks in each state (running, sleeping, etc.).
  * Calculates the CPU time in each state (system, user, nice, etc).
index 972383f33b5b94b9c334492dc2f2c77701588dec..be05d5c8a0280f4942312b036ab62830e0af9d37 100644 (file)
@@ -39,6 +39,8 @@ static int uptime_fd = -1;
 static int loadavg_fd = -1;
 #define MEMINFO_FILE "/proc/meminfo"
 static int meminfo_fd = -1;
+#define VMINFO_FILE "/proc/vmstat"
+static int vminfo_fd = -1;
 
 static char buf[1024];
 
@@ -170,7 +172,7 @@ static void init_Hertz_value(void){
 
 /***********************************************************************
  * The /proc filesystem calculates idle=jiffies-(user+nice+sys) and we
- * recover jiffies by adding up the 4 numbers we are given. SMP kernels
+ * recover jiffies by adding up the 4 or 5 numbers we are given. SMP kernels
  * (as of pre-2.4 era) can report idle time going backwards, perhaps due
  * to non-atomic reads and updates. There is no locking for these values.
  */
@@ -178,36 +180,40 @@ static void init_Hertz_value(void){
 #define NAN (-0.0)
 #endif
 #define JT unsigned long long
-void four_cpu_numbers(double *uret, double *nret, double *sret, double *iret){
-    double tmp_u, tmp_n, tmp_s, tmp_i;
+void five_cpu_numbers(double *uret, double *nret, double *sret, double *iret, double *Iret){
+    double tmp_u, tmp_n, tmp_s, tmp_i, tmp_I;
     double scale;  /* scale values to % */
-    static JT old_u, old_n, old_s, old_i;
-    JT new_u, new_n, new_s, new_i;
+    static JT old_u, old_n, old_s, old_i, old_I;
+    JT new_u, new_n, new_s, new_i, new_I;
     JT ticks_past; /* avoid div-by-0 by not calling too often :-( */
  
     FILE_TO_BUF(STAT_FILE,stat_fd);
-    sscanf(buf, "cpu %Lu %Lu %Lu %Lu", &new_u, &new_n, &new_s, &new_i);
-    ticks_past = (new_u+new_n+new_s+new_i)-(old_u+old_n+old_s+old_i);
+    sscanf(buf, "cpu %Lu %Lu %Lu %Lu %Lu", &new_u, &new_n, &new_s, &new_i, &new_I);
+    ticks_past = (new_u+new_n+new_s+new_i+new_I)-(old_u+old_n+old_s+old_i+old_I);
     if(ticks_past){
       scale = 100.0 / (double)ticks_past;
       tmp_u = ( (double)new_u - (double)old_u ) * scale;
       tmp_n = ( (double)new_n - (double)old_n ) * scale;
       tmp_s = ( (double)new_s - (double)old_s ) * scale;
       tmp_i = ( (double)new_i - (double)old_i ) * scale;
+      tmp_I = ( (double)new_I - (double)old_I ) * scale;
     }else{
       tmp_u = NAN;
       tmp_n = NAN;
       tmp_s = NAN;
       tmp_i = NAN;
+      tmp_I = NAN;
     }
     SET_IF_DESIRED(uret, tmp_u);
     SET_IF_DESIRED(nret, tmp_n);
     SET_IF_DESIRED(sret, tmp_s);
     SET_IF_DESIRED(iret, tmp_i);
+    SET_IF_DESIRED(iret, tmp_I);
     old_u=new_u;
     old_n=new_n;
     old_s=new_s;
     old_i=new_i;
+    old_i=new_I;
 }
 #undef JT
 
@@ -267,6 +273,14 @@ static int compare_mem_table_structs(const void *a, const void *b){
  * LowFree:          1436 kB
  * SwapTotal:      122580 kB    old
  * SwapFree:        60352 kB    old
+ * Inactive:        20420 kB    2.5.41+
+ * Dirty:               0 kB    2.5.41+
+ * Writeback:           0 kB    2.5.41+
+ * Mapped:           9792 kB    2.5.41+
+ * Slab:             4564 kB    2.5.41+
+ * Committed_AS:     8440 kB    2.5.41+
+ * PageTables:        304 kB    2.5.41+
+ * ReverseMaps:      5738       2.5.41+
  */
 
 /* obsolete */
@@ -292,6 +306,16 @@ unsigned kb_swap_cached;  /* late 2.4 only */
 /* derived values */
 unsigned kb_swap_used;
 unsigned kb_main_used;
+/* 2.5.41+ */
+unsigned kb_writeback;
+unsigned kb_slab;
+unsigned nr_reversemaps;
+unsigned kb_active;
+unsigned kb_committed_as;
+unsigned kb_dirty;
+unsigned kb_inactive;
+unsigned kb_mapped;
+unsigned kb_pagetables;
 
 void meminfo(void){
   char namebuf[16]; /* big enough to hold any row name */
@@ -303,24 +327,34 @@ void meminfo(void){
   {"Active",       &kb_active},
   {"Buffers",      &kb_main_buffers},
   {"Cached",       &kb_main_cached},
+  {"Committed_AS", &kb_committed_as},
+  {"Dirty",        &kb_dirty},
   {"HighFree",     &kb_high_free},
   {"HighTotal",    &kb_high_total},
   {"Inact_clean",  &kb_inact_clean},
   {"Inact_dirty",  &kb_inact_dirty},
   {"Inact_target", &kb_inact_target},
+  {"Inactive",     &kb_inactive},
   {"LowFree",      &kb_low_free},
   {"LowTotal",     &kb_low_total},
+  {"Mapped",       &kb_mapped},
   {"MemFree",      &kb_main_free},
   {"MemShared",    &kb_main_shared},
   {"MemTotal",     &kb_main_total},
+  {"PageTables",   &kb_pagetables},
+  {"ReverseMaps",  &nr_reversemaps},
+  {"Slab",         &kb_slab},
   {"SwapCached",   &kb_swap_cached},
   {"SwapFree",     &kb_swap_free},
-  {"SwapTotal",    &kb_swap_total}
+  {"SwapTotal",    &kb_swap_total},
+  {"Writeback",    &kb_writeback}
   };
   const int mem_table_count = sizeof(mem_table)/sizeof(mem_table_struct);
 
   FILE_TO_BUF(MEMINFO_FILE,meminfo_fd);
 
+  kb_inactive = -1;
+
   head = buf;
   for(;;){
     tail = strchr(head, ':');
@@ -346,6 +380,109 @@ nextline:
     kb_low_total = kb_main_total;
     kb_low_free  = kb_main_free;
   }
+  if(kb_inactive==-1){
+    kb_inactive = kb_inact_dirty + kb_inact_clean;
+  }
   kb_swap_used = kb_swap_total - kb_swap_free;
   kb_main_used = kb_main_total - kb_main_free;
 }
+
+/*****************************************************************/
+
+/* read /proc/vminfo only for 2.5.41 and above */
+
+typedef struct vm_table_struct {
+  const char *name;     /* VM statistic name */
+  const unsigned *slot; /* slot in return struct */
+} vm_table_struct;
+
+static int compare_vm_table_structs(const void *a, const void *b){
+  return strcmp(((vm_table_struct*)a)->name,((vm_table_struct*)b)->name);
+}
+
+unsigned vm_nr_dirty;
+unsigned vm_nr_writeback;
+unsigned vm_nr_pagecache;
+unsigned vm_nr_page_table_pages;
+unsigned vm_nr_reverse_maps;
+unsigned vm_nr_mapped;
+unsigned vm_nr_slab;
+unsigned vm_pgpgin;
+unsigned vm_pgpgout;
+unsigned vm_pswpin;  /* same as 1st num on /proc/stat swap line */
+unsigned vm_pswpout; /* same as 2nd num on /proc/stat swap line */
+unsigned vm_pgalloc;
+unsigned vm_pgfree;
+unsigned vm_pgactivate;
+unsigned vm_pgdeactivate;
+unsigned vm_pgfault;
+unsigned vm_pgmajfault;
+unsigned vm_pgscan;
+unsigned vm_pgrefill;
+unsigned vm_pgsteal;
+unsigned vm_kswapd_steal;
+unsigned vm_pageoutrun;
+unsigned vm_allocstall;
+
+void vminfo(void){
+  char namebuf[16]; /* big enough to hold any row name */
+  vm_table_struct findme = { namebuf, NULL};
+  vm_table_struct *found;
+  char *head;
+  char *tail;
+  static const vm_table_struct vm_table[] = {
+  {"allocstall",          &vm_allocstall},
+  {"kswapd_steal",        &vm_kswapd_steal},
+  {"nr_dirty",            &vm_nr_dirty},
+  {"nr_mapped",           &vm_nr_mapped},
+  {"nr_page_table_pages", &vm_nr_page_table_pages},
+  {"nr_pagecache",        &vm_nr_pagecache},
+  {"nr_reverse_maps",     &vm_nr_reverse_maps},
+  {"nr_slab",             &vm_nr_slab},
+  {"nr_writeback",        &vm_nr_writeback},
+  {"pageoutrun",          &vm_pageoutrun},
+  {"pgactivate",          &vm_pgactivate},
+  {"pgalloc",             &vm_pgalloc},
+  {"pgdeactivate",        &vm_pgdeactivate},
+  {"pgfault",             &vm_pgfault},
+  {"pgfree",              &vm_pgfree},
+  {"pgmajfault",          &vm_pgmajfault},
+  {"pgpgin",              &vm_pgpgin},
+  {"pgpgout",             &vm_pgpgout},
+  {"pgrefill",            &vm_pgrefill},
+  {"pgscan",              &vm_pgscan},
+  {"pgsteal",             &vm_pgsteal},
+  {"pswpin",              &vm_pswpin},
+  {"pswpout",             &vm_pswpout}
+  };
+  const int vm_table_count = sizeof(vm_table)/sizeof(vm_table_struct);
+
+  FILE_TO_BUF(VMINFO_FILE,vminfo_fd);
+
+  head = buf;
+  for(;;){
+    tail = strchr(head, ' ');
+    if(!tail) break;
+    *tail = '\0';
+    if(strlen(head) >= sizeof(namebuf)){
+      head = tail+1;
+      goto nextline;
+    }
+    strcpy(namebuf,head);
+    found = bsearch(&findme, vm_table, vm_table_count,
+        sizeof(vm_table_struct), compare_vm_table_structs
+    );
+    head = tail+1;
+    if(!found) goto nextline;
+    *(found->slot) = strtoul(head,&tail,10);
+nextline:
+
+//if(found) fprintf(stderr,"%s=%d\n",found->name,*(found->slot));
+//else      fprintf(stderr,"%s not found\n",findme.name);
+
+    tail = strchr(head, '\n');
+    if(!tail) break;
+    head = tail+1;
+  }
+}
+/*****************************************************************/
index c4af4f46f01c220b73d28c33e81ca64067ad8f2a..cf701e25804e213061059c005a50a738e368e3a2 100644 (file)
@@ -5,7 +5,7 @@ extern unsigned long long Hertz;   /* clock tick frequency */
 extern long smp_num_cpus;     /* number of CPUs */
 
 #define JT double
-extern void four_cpu_numbers(JT *uret, JT *nret, JT *sret, JT *iret);
+extern void five_cpu_numbers(JT *uret, JT *nret, JT *sret, JT *iret, JT *Iret);
 #undef JT
 
 extern int        uptime (double *uptime_secs, double *idle_secs);
@@ -35,7 +35,44 @@ extern unsigned kb_swap_cached;  /* late 2.4 only */
 /* derived values */
 extern unsigned kb_swap_used;
 extern unsigned kb_main_used;
+/* 2.5.41+ */
+extern unsigned kb_writeback;
+extern unsigned kb_slab;
+extern unsigned nr_reversemaps;
+extern unsigned kb_active;
+extern unsigned kb_committed_as;
+extern unsigned kb_dirty;
+extern unsigned kb_inactive;
+extern unsigned kb_mapped;
+extern unsigned kb_pagetables;
 
 extern void meminfo(void);
 
+
+extern unsigned vm_nr_dirty;
+extern unsigned vm_nr_writeback;
+extern unsigned vm_nr_pagecache;
+extern unsigned vm_nr_page_table_pages;
+extern unsigned vm_nr_reverse_maps;
+extern unsigned vm_nr_mapped;
+extern unsigned vm_nr_slab;
+extern unsigned vm_pgpgin;
+extern unsigned vm_pgpgout;
+extern unsigned vm_pswpin;
+extern unsigned vm_pswpout;
+extern unsigned vm_pgalloc;
+extern unsigned vm_pgfree;
+extern unsigned vm_pgactivate;
+extern unsigned vm_pgdeactivate;
+extern unsigned vm_pgfault;
+extern unsigned vm_pgmajfault;
+extern unsigned vm_pgscan;
+extern unsigned vm_pgrefill;
+extern unsigned vm_pgsteal;
+extern unsigned vm_kswapd_steal;
+extern unsigned vm_pageoutrun;
+extern unsigned vm_allocstall;
+
+extern void vminfo(void);
+
 #endif /* SYSINFO_H */
diff --git a/top.c b/top.c
index f95a9ece78006cce03c3e5c0ddb40865147d0796..c7d9db71028d1332776e024c458aa52c9b4fa0f1 100644 (file)
--- a/top.c
+++ b/top.c
@@ -812,6 +812,7 @@ static CPUS_t *refreshcpus (CPUS_t *cpus)
 {
    static FILE *fp = NULL;
    int i;
+   char buf[256]; /* enough for a /proc/stat CPU line (not the intr line) */
 
       /* by opening this file once, we'll avoid the hit on minor page faults
          (sorry Linux, but you'll have to close it for us) */
@@ -827,19 +828,22 @@ static CPUS_t *refreshcpus (CPUS_t *cpus)
    fflush(fp);
 
       /* first value the last slot with the cpu summary line */
-   if (4 != fscanf(fp, CPU_FMTS_JUST1
-      , &cpus[Cpu_tot].u, &cpus[Cpu_tot].n, &cpus[Cpu_tot].s, &cpus[Cpu_tot].i))
+   if(!fgets(buf, sizeof(buf), fp)) std_err("failed /proc/stat read");
+   if (4 > sscanf(buf, CPU_FMTS_JUST1
+      , &cpus[Cpu_tot].u, &cpus[Cpu_tot].n, &cpus[Cpu_tot].s, &cpus[Cpu_tot].i, &cpus[Cpu_tot].I))
          std_err("failed /proc/stat read");
 
       /* and now value each separate cpu's tics */
    for (i = 0; i < Cpu_tot; i++) {
 #ifdef PRETEND4CPUS
       rewind(fp);
-      if (4 != fscanf(fp, CPU_FMTS_JUST1
+      if(!fgets(buf, sizeof(buf), fp)) std_err("failed /proc/stat read");
+      if (4 > sscanf(buf, CPU_FMTS_JUST1
 #else
-      if (4 != fscanf(fp, CPU_FMTS_MULTI
+      if(!fgets(buf, sizeof(buf), fp)) std_err("failed /proc/stat read");
+      if (4 > sscanf(buf, CPU_FMTS_MULTI
 #endif
-         , &cpus[i].u, &cpus[i].n, &cpus[i].s, &cpus[i].i))
+         , &cpus[i].u, &cpus[i].n, &cpus[i].s, &cpus[i].i, &cpus[i].I))
             std_err("failed /proc/stat read");
    }
 
@@ -1692,13 +1696,14 @@ static void cpudo (CPUS_t *cpu, const char *pfx)
         /* we'll trim to zero if we get negative time ticks,
            which has happened with some SMP kernels (pre-2.4?) */
 #define TRIMz(x)  ((tz = (STIC_t)x) < 0 ? 0 : tz)
-   STIC_t u_frme, s_frme, n_frme, i_frme, tot_frme, tz;
+   STIC_t u_frme, s_frme, n_frme, i_frme, I_frme, tot_frme, tz;
 
    u_frme = TRIMz(cpu->u - cpu->u_sav);
    s_frme = TRIMz(cpu->s - cpu->s_sav);
    n_frme = TRIMz(cpu->n - cpu->n_sav);
    i_frme = TRIMz(cpu->i - cpu->i_sav);
-   tot_frme = u_frme + s_frme + n_frme + i_frme;
+   I_frme = TRIMz(cpu->I - cpu->I_sav);
+   tot_frme = u_frme + s_frme + n_frme + i_frme + I_frme;
    if (1 > tot_frme) tot_frme = 1;
 
       /* display some kinda' cpu state percentages
@@ -1708,7 +1713,8 @@ static void cpudo (CPUS_t *cpu, const char *pfx)
       , (float)u_frme * 100 / tot_frme
       , (float)s_frme * 100 / tot_frme
       , (float)n_frme * 100 / tot_frme
-      , (float)i_frme * 100 / tot_frme));
+      , (float)i_frme * 100 / tot_frme
+      , (float)I_frme * 100 / tot_frme));
    Msg_row += 1;
 
       /* remember for next time around */
@@ -1716,6 +1722,7 @@ static void cpudo (CPUS_t *cpu, const char *pfx)
    cpu->s_sav = cpu->s;
    cpu->n_sav = cpu->n;
    cpu->i_sav = cpu->i;
+   cpu->I_sav = cpu->I;
 
 #undef TRIMz
 }
@@ -1807,14 +1814,12 @@ static void frame_states (proc_t **ppt, int show)
 
       if (CHKw(Curwin, View_CPUSUM)) {
             /* display just the 1st /proc/stat line */
-         cpudo(&smpcpu[Cpu_tot], "Cpu(s) state:");
+         cpudo(&smpcpu[Cpu_tot], "CPU use:");
       } else {
          char tmp[SMLBUFSIZ];
             /* display each cpu's states separately */
          for (i = 0; i < Cpu_tot; i++) {
-            sprintf(tmp, "%-6scpu%-2d:"         /* [ cpu states as ]      */
-               , i ? " " : "State"              /*    'State cpu0 : ... ' */
-               , Mode_irixps ? i : Cpu_map[i]); /*    '      cpu1 : ... ' */
+            sprintf(tmp, "CPU%4d:", Mode_irixps ? i : Cpu_map[i]);
             cpudo(&smpcpu[i], tmp);
          }
       }
diff --git a/top.h b/top.h
index eb2d8cbe0870feeb6a16ea8201060e4befa5aee7..5da8171d276ce23b26671e70de61ad656dbb9416 100644 (file)
--- a/top.h
+++ b/top.h
@@ -167,11 +167,13 @@ typedef struct {
    TICS_t u,            /* ticks count as represented in /proc/stat */
           n,            /* (not in the order of our display) */
           s,
-          i;
+          i,
+          I;
    TICS_t u_sav,        /* tics count in the order of our display */
           s_sav,
           n_sav,
-          i_sav;
+          i_sav,
+          I_sav;
 } CPUS_t;
 
         /* The scaling 'type' used with scale_num() -- this is how
@@ -306,11 +308,11 @@ typedef struct win {
            reads during history processing.
            ( 5th number added in anticipation of kernel change ) */
 #ifdef TICS_64_BITS
-#define CPU_FMTS_JUST1  "cpu %Lu %Lu %Lu %Lu \n"
-#define CPU_FMTS_MULTI  "cpu%*d %Lu %Lu %Lu %Lu %*d \n"
+#define CPU_FMTS_JUST1  "cpu %Lu %Lu %Lu %Lu %Lu"
+#define CPU_FMTS_MULTI  "cpu%*d %Lu %Lu %Lu %Lu %Lu"
 #else
-#define CPU_FMTS_JUST1  "cpu %lu %lu %lu %lu \n"
-#define CPU_FMTS_MULTI  "cpu%*d %lu %lu %lu %lu %*d \n"
+#define CPU_FMTS_JUST1  "cpu %lu %lu %lu %lu %lu"
+#define CPU_FMTS_MULTI  "cpu%*d %lu %lu %lu %lu %lu"
 #endif
 
         /* This is the format for 'command line' display in the absence
@@ -330,7 +332,7 @@ typedef struct win {
    " %3u \02stopped,\03 %3u \02zombie\03\n"
 #define STATES_line2  "%s\03" \
    " %#5.1f%% \02user,\03 %#5.1f%% \02system,\03" \
-   " %#5.1f%% \02nice,\03 %#5.1f%% \02idle\03\n"
+   " %#5.1f%% \02nice,\03 %#5.1f%% \02idle,\03 %#5.1f%% \02IO-wait\03\n"
 #ifdef CASEUP_SUMMK
 #define MEMORY_line1  "Mem: \03" \
    " %8uK \02total,\03 %8uK \02used,\03" \
index f900024547406662d58347d75181cb2577e03e18..1300bfca20794488024f53b32c189de05ef5df3e 100644 (file)
--- a/vmstat.c
+++ b/vmstat.c
  * Ideally, blocks in & out would be counted in 1k increments, rather than
    by block: this only makes a difference for CDs and is a problematic fix.
 */
-/* PROCPS
-   This is part of the procps package maintained by Michael K. Johnson
-   <johnsonm@redhat.com>; report bugs to <acahalan@cs.uml.edu>.
-*/
    
 #include "proc/sysinfo.h"
 #include "proc/version.h"
@@ -46,6 +42,7 @@ static char buff[BUFFSIZE]; /* used in the procedures */
 
 typedef unsigned long jiff;
 
+static int a_option; /* "-a" means "show active/inactive" */
 
 /****************************************************************/
 
@@ -54,6 +51,7 @@ static void usage(void) {
   fprintf(stderr,"usage: %s [-V] [-n] [delay [count]]\n",PROGNAME);
   fprintf(stderr,"              -V prints version.\n");
   fprintf(stderr,"              -n causes the headers not to be reprinted regularly.\n");
+  fprintf(stderr,"              -a print inactive/active page stats.\n");
   fprintf(stderr,"              delay is the delay between updates in seconds. \n");
   fprintf(stderr,"              count is the number of updates.\n");
   exit(EXIT_FAILURE);
@@ -76,14 +74,16 @@ static int winhi(void) {
 
 
 static void showheader(void){
-  printf("%8s%28s%8s%12s%11s%12s\n",
+  printf("%8s%28s%10s%12s%11s%9s\n",
         "procs","memory","swap","io","system","cpu");
-  printf("%2s %2s %2s %6s %6s %6s %6s %3s %3s %5s %5s %4s %5s %3s %3s %3s\n",
-        "r","b","w","swpd","free","buff","cache","si","so","bi","bo",
+  printf("%2s %2s %2s %6s %6s %6s %6s %4s %4s %5s %5s %4s %5s %2s %2s %2s\n",
+        "r","b","w","swpd","free",
+        a_option?"inact":"buff", a_option?"active":"cache",
+        "si","so","bi","bo",
         "in","cs","us","sy","id");
 }
 
-static void getstat(jiff *cuse, jiff *cice, jiff *csys, jiff long *cide,
+static void getstat(jiff *cuse, jiff *cice, jiff *csys, jiff long *cide, jiff long *ciow,
             unsigned *pin, unsigned *pout, unsigned *s_in, unsigned *sout,
             unsigned *itot, unsigned *i1, unsigned *ct) {
   static int Stat;
@@ -95,20 +95,28 @@ static void getstat(jiff *cuse, jiff *cice, jiff *csys, jiff long *cide,
     close(Stat);
     *itot = 0; 
     *i1 = 1;   /* ensure assert below will fail if the sscanf bombs */
+    *ciow = 0;  /* not separated out until the 2.5.41 kernel */
     b = strstr(buff, "cpu ");
-    sscanf(b, "cpu  %lu %lu %lu %lu", cuse, cice, csys, cide);
+    if(b) sscanf(b,  "cpu  %lu %lu %lu %lu %lu", cuse, cice, csys, cide, ciow);
     b = strstr(buff, "page ");
-    sscanf(b, "page %u %u", pin, pout);
+    if(b) sscanf(b,  "page %u %u", pin, pout);
     b = strstr(buff, "swap ");
-    sscanf(b, "swap %u %u", s_in, sout);
+    if(b) sscanf(b,  "swap %u %u", s_in, sout);
     b = strstr(buff, "intr ");
-    sscanf(b, "intr %u %u", itot, i1);
+    if(b) sscanf(b,  "intr %u %u", itot, i1);
     b = strstr(buff, "ctxt ");
-    sscanf(b, "ctxt %u", ct);
+    if(b) sscanf(b,  "ctxt %u", ct);
   }
   else {
     crash("/proc/stat");
   }
+  if(1){
+    vminfo();
+    *pin  = vm_pgpgout;
+    *pout = vm_pgpgin;
+    *s_in = vm_pswpout;
+    *sout = vm_pswpin;
+  }
 }
 
 static void getrunners(unsigned int *running, unsigned int *blocked, 
@@ -131,7 +139,15 @@ static void getrunners(unsigned int *running, unsigned int *blocked,
       sprintf(filename, "/proc/%s/stat", ent->d_name);
       if ((fd = open(filename, O_RDONLY, 0)) != -1) { /*this weeds the rest*/
        read(fd,buff,BUFFSIZE-1);
-       sscanf(buff, "%*d %*s %c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*d %*d %*d %*d %*d %*d %*u %*u %*d %*u %u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u\n",&c,&size);
+       sscanf(
+         buff,
+         "%*d %*s %c "
+         "%*d %*d %*d %*d %*d %*u %*u"
+         " %*u %*u %*u %*d %*d %*d %*d %*d %*d %*u %*u %*d %*u %u"
+         /*  " %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u %*u\n"  */ ,
+         &c,
+         &size
+       );
        close(fd);
 
        if (c=='R') {
@@ -159,7 +175,7 @@ static void getrunners(unsigned int *running, unsigned int *blocked,
 
 int main(int argc, char *argv[]) {
 
-  const char format[]="%2u %2u %2u %6u %6u %6u %6u %3u %3u %5u %5u %4u %5u %3u %3u %3u\n";
+  const char format[]="%2u %2u %2u %6u %6u %6u %6u %4u %4u %5u %5u %4u %5u %2u %2u %2u\n";
   unsigned int height=22; /* window height, reset later if needed. */
 #if 0
   unsigned long int args[2]={0,0};
@@ -168,7 +184,7 @@ int main(int argc, char *argv[]) {
   unsigned int tog=0; /* toggle switch for cleaner code */
   unsigned int i,hz;
   unsigned int running,blocked,swapped;
-  jiff cpu_use[2], cpu_nic[2], cpu_sys[2], cpu_idl[2];
+  jiff cpu_use[2], cpu_nic[2], cpu_sys[2], cpu_idl[2], cpu_iow[2];
   jiff duse,dsys,didl,Div,divo2;
   unsigned int pgpgin[2], pgpgout[2], pswpin[2], pswpout[2];
   unsigned int inter[2],ticks[2],ctxt[2];
@@ -183,13 +199,17 @@ int main(int argc, char *argv[]) {
   for (argv++;*argv;argv++) {
     if ('-' ==(**argv)) {
       switch (*(++(*argv))) {
-       case 'V':
+      case 'V':
        display_version();
        exit(0);
+      case 'a':
+       /* active/inactive mode */
+       a_option=1;
+        break;
       case 'n':
        /* print only one header */
        moreheaders=FALSE;
-      break;
+        break;
       default:
        /* no other aguments defined yet. */
        usage();
@@ -220,18 +240,20 @@ int main(int argc, char *argv[]) {
   showheader();
   getrunners(&running,&blocked,&swapped);
   meminfo();
-  getstat(cpu_use,cpu_nic,cpu_sys,cpu_idl,
+  getstat(cpu_use,cpu_nic,cpu_sys,cpu_idl,cpu_iow,
          pgpgin,pgpgout,pswpin,pswpout,
          inter,ticks,ctxt);
   duse= *cpu_use + *cpu_nic; 
-  dsys= *cpu_sys;
+  dsys= *cpu_sys + *cpu_iow;  /* ADC -- add IO-wait here? */
   didl= *cpu_idl;
   Div= duse+dsys+didl;
-  hz=sysconf(_SC_CLK_TCK); /* get ticks/s from system */
+  hz=Hertz; /* get ticks/s from libproc */
   divo2= Div/2UL;
   printf(format,
         running,blocked,swapped,
-        kb_swap_used,kb_main_free,kb_main_buffers,kb_main_cached,
+        kb_swap_used,kb_main_free,
+        a_option?kb_inactive:kb_main_buffers,
+        a_option?kb_active:kb_main_cached,
         (*pswpin *kb_per_page*hz+divo2)/Div,
         (*pswpout*kb_per_page*hz+divo2)/Div,
         (*pgpgin             *hz+divo2)/Div,
@@ -249,11 +271,11 @@ int main(int argc, char *argv[]) {
     tog= !tog;
     getrunners(&running,&blocked,&swapped);
     meminfo();
-    getstat(cpu_use+tog,cpu_nic+tog,cpu_sys+tog,cpu_idl+tog,
+    getstat(cpu_use+tog,cpu_nic+tog,cpu_sys+tog,cpu_idl+tog,cpu_iow+tog,
          pgpgin+tog,pgpgout+tog,pswpin+tog,pswpout+tog,
          inter+tog,ticks+tog,ctxt+tog);
     duse= cpu_use[tog]-cpu_use[!tog] + cpu_nic[tog]-cpu_nic[!tog];
-    dsys= cpu_sys[tog]-cpu_sys[!tog];
+    dsys= cpu_sys[tog]-cpu_sys[!tog] + cpu_iow[tog]-cpu_iow[!tog];
     didl= cpu_idl[tog]-cpu_idl[!tog];
     /* idle can run backwards for a moment -- kernel "feature" */
     if(cpu_idl[tog]<cpu_idl[!tog]) didl=0;