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