updated top to Jims wj code

This commit is contained in:
csmall 2002-10-02 00:10:30 +00:00
parent 76086a7b87
commit bbdb12e639
3 changed files with 377 additions and 288 deletions

207
top.1
View File

@ -23,7 +23,7 @@
.
.\" Setup ////////////////////////////////////////////////////////////////
\# ** Comment out '.nr' or set to 0 to eliminate WIDTH fiddlin' !
.nr half_xtra 4
.nr half_xtra 0
.
. ll +(\n[half_xtra] + \n[half_xtra])
.
@ -79,7 +79,7 @@
\# - hey, these two ain't too shabby, either
. ds Us this\ \*(Me
. ds US \fBthis\fR\ \*(Me
\# - other misc strings for consistent usage
\# - other misc strings for consistent usage/emphasis
. ds F \fIOff\fR
. ds O \fIOn\fR
.
@ -108,7 +108,7 @@
.
.\" //////////////////////////////////////////////////////////////////////
.\" ----------------------------------------------------------------------
.TH TOP 1 "June 2002" "Linux" "Linux User's Manual"
.TH TOP 1 "September 2002" "Linux" "Linux User's Manual"
.\" ----------------------------------------------------------------------
@ -124,7 +124,7 @@ top \- display Linux tasks
\*(ME \-\fBhv\fR | \-\fBbcisS\fR \-\fBd\fI delay\fR \-\fBn\fI
iterations\fR \-\fBp\fI pid\fR [,\fI pid\fR ...]
The traditional switches '-' and even whitespace are optional.
The traditional switches '-' and whitespace are optional.
.\" ----------------------------------------------------------------------
@ -158,16 +158,16 @@ Details regarding their exploitation will be covered in later sections.
.\" ......................................................................
.SS Expanded Configurable Display Support
.New
In an SMP environment, you can choose between a\fB summary\fR display or
you may show\fB each \*(Pu\fR separately.
This could be an important provision for a massively-parallel machine, where
screen height is insufficient to simultaneously accommodate all \*(Pu
states plus a meaningful \*(TD.
In an SMP environment, screen height may be insufficient to simultaneously
accommodate all \*(Pu states plus a meaningful \*(TD.
So with \*(Us, you can alternate between a\fB summary\fR display or one
showing\fB each \*(Pu\fR separately.
No longer must this choice be irrevocably made at startup.
.New
There are new fields.
With \*(Us,\fB any\fR field is selectable for sorting and your sorted
column can be\fB instantly reversed\fR.
There are new fields and with \*(Us,\fB any\fR field is selectable for sorting.
Plus, your sorted column can be\fB instantly reversed\fR with just a
single keystroke.
.New
You may optionally apply 2 distinct types of\fB highlighting\fR to
@ -358,7 +358,7 @@ command line\fR \*(EM a subject soon to be dealt with.
* 'c' - Command line \fBOff\fR (name, not cmdline)
* 'i' - Idle tasks On\ \ (show all tasks)
'R' - Reverse sort On\ \ (sort pids high-to-low)
* 'S' - Cumulative time \fBOff\fR (exclude dead child)
* 'S' - Cumulative time \fBOff\fR (exclude dead children)
'x' - Column hilite \fBOff\fR\ (no, sort field)
'y' - Row hilite On\ \ (yes, running tasks)
'z' - color/mono \fBOff\fR\ (no, colors)
@ -392,8 +392,8 @@ Remaining Table of Contents
b. SELECTING and ORDERING Columns
3.\fB INTERACTIVE Commands\fR
a. GLOBAL Commands
b. SUMMARY Display Commands
c. TASK Display Commands
b. SUMMARY Area Commands
c. TASK Area Commands
d. COLOR Mapping
4.\fB ALTERNATE\-DISPLAY Mode\fR
a. WINDOWS Overview
@ -410,8 +410,10 @@ Remaining Table of Contents
b. Bouncing Windows
c. The Big Bird Window
7.\fB NOTES and Rantings\fR
a. The top BINARY
b. The top SOURCES
a. The top Binary
b. Comparing Performance
c. Cost of Stuff
d. The top Sources
-*- Rant On, and on -*-
lastly,\fB the usual\fR...
8. BUGS, 9. HISTORY Former top, 10. AUTHOR, 11. SEE ALSO
@ -432,7 +434,7 @@ optional.
Starts \*(Me in 'Batch mode', which could be useful for sending output
from \*(Me to other programs or to a file.
In this mode, \*(Me will\fB not\fR accept input and runs until the iterations
limit you've set with the 'n' option or until killed.
limit you've set with the '-n' \*(CO or until killed.
Output is plain text suitable for any dumb terminal.
.br
@ -516,7 +518,7 @@ In fact, one could argue that this switch has little practical use\fB except\fR
to test the nifty\fI delayed message handling\fR \*(Us employs during bootstrap.
Oh, you wanna' see?
Test thus:\ \ top\fB d.1s\fR
Test thus:\ \ \*(Me\fB d.1s\fR
.Rjb 3
( see, NO '-' & 'sp' but )
( you\fB can't change delay\fR )
@ -524,14 +526,14 @@ Test thus:\ \ top\fB d.1s\fR
.Rje
Don't bother trying that precise command line with your old top
\*(EM he'll completely overlook that 's' option because
\*(EM he'll completely overlook that 's' \*(CO because
he-sees-poorly-but-won't-wear-glasses.
.TP 5
\-\fBS\fR :\fB Cumulative time mode\fR toggle
Starts \*(Me with the last remembered '\fBS\fR' state reversed.
When 'Cumulative mode' is \*O, each process is listed with the \*(Pu
time that it\fB and\fR its dead children has used.
time that it\fB and\fR its dead children have used.
\*(XC 'S' \*(CI for additional information regarding this mode.
.TP 5
@ -547,11 +549,12 @@ Show library version and the usage prompt, then quit.
.\" ----------------------------------------------------------------------
Listed below are \*(Us's\fB available\fR fields.
They are always associated with the letter shown, regardless of the position
you may have established for them with the 'o' (Order fields) \*(CI.
you may have established for them with the 'o' (Order fields) \*(CI, reviewed
in the following topic.
Any field is selectable as the\fB sort field\fR, and you control whether they
are sorted high-to-low or low-to-high.
For additional information on sort provisions \*(Xt 3c. TASK Display Commands.
For additional information on sort provisions \*(Xt 3c. TASK Area Commands.
.TP 3
a:\fB PID\fR \*(EM Process Id\fR
@ -564,7 +567,8 @@ The process ID of a task's parent.
.TP 3
c:\fB PGID\fR \*(EM Process Group Id\fR
The group to which a task belongs which in turn is part of job control.
The grouping of tasks which becomes part of job control.
It is used for distribution of signals and to arbitrate terminal I/O requests.
There is one process group per pipeline.
.TP 3
@ -723,12 +727,11 @@ to provide for the potential growth of program names into command lines!
.TP 3
y:\fB WCHAN\fR \*(EM Sleeping in Function
Depending on the availability of\fI /boot/System.map\fR (the kernel link map)
or\fI /boot/psdatabase\fR, this field will show the \fB name\fR or
the\fB address\fR of the kernel function in which the task is
currently sleeping.
Running tasks will display a dash '-' in this column (but only if you're using
the best, the most proper libproc).
Depending on the availability of the kernel link map ('System.map'),
this field will show the \fB name\fR or the\fB address\fR of the kernel
function in which the task is currently sleeping.
Running tasks will display a dash ('-') in this column (but only if you're
using the best, the most proper libproc).
.in +4
\*(NT By displaying this field, \*(Me's own working set will be increased by
@ -740,7 +743,7 @@ Your only means of reducing that overhead will be to stop and restart \*(Me.
z:\fB Flags\fR \*(EM Task Flags
This column represents the task's current scheduling flags which \*(Us
expresses in hexadecimal notation, but with zeros suppressed.
These flags are officially documented in <sched.h>.
These flags are officially documented in <linux/sched.h>.
Less formal documentation can also be found on the 'Fields select'
and 'Order fields' screens \*(EM the next topic.
@ -933,7 +936,7 @@ These commands always impact just the \*(CW/field group.
.TP 7
\ \ \'\fBl\fR\' :\fIToggle_Load_Average/Uptime\fR \*(EM On/Off
This is the line containing the program name (possibly an alias) when
This is also the line containing the program name (possibly an alias) when
operating in \*(FM or the \*(CW name when operating in \*(AM.
If you murder-this-line, \*(Me will prosecute you.
@ -992,16 +995,15 @@ Further, it will only be available when at least one of those toggles is \*O.
You probably don't need a constant visual reminder of your chosen sort
field and \*(Us hopes that you always run with 'column highlight' \*F,
due to the cost in path-length.
However, if you forget which field \*(Me is sorting it can serve as a
quick visual reminder.
However, if you forget which field \*(Me is sorting this command can serve
as a quick visual reminder.
.TP 7
\ \ \'\fBy\fR\' :\fIRow_Highlight_toggle\fR
Please use this toggle \*(EM highlight running tasks!
It's an important insight into your system's health and there is no extra
run-time cost associated with its use.
Besides, it is this provision alone that is largely responsible for
your-brand-new-top and you'll make the program author a happy guy.
It's an important insight into your system's health and it was largely this
provision that was responsible for your-brand-new-top.
You'll make the program author a happy guy.
.TP 7
\ \ \'\fBz\fR\' :\fIColor/Monochrome_toggle\fR
@ -1030,7 +1032,7 @@ For additional information on these \*(CIs
.TP 7
\ \ \'\fBS\fR\' :\fICumulative_Time_Mode_toggle\fR
When 'Cumulative mode' is \*O, each process is listed with the \*(Pu
time that it\fB and\fR its dead children\fR has used.
time that it\fB and\fR its dead children\fR have used.
When \*F, programs that fork into many separate tasks will appear
less demanding.
@ -1079,7 +1081,7 @@ over the size of each currently visible \*(TD.
.br
.in +2
Before using any of these sort provisions, \*(Me suggests that you
\fItemporarily\fR turn on column highlighting using the '\fBx\fR' \*(CI.
temporarily turn on column highlighting using the '\fBx\fR' \*(CI.
That will help ensure that the actual sort environment matches your intent.
The following \*(CIs will\fB only\fR be honored when the
@ -1115,7 +1117,7 @@ be forced \*O when you return to the \*(Me display.
However, depending upon your screen width and the order of your fields,
this sort field may not be displayable.
These \*(CIs can be a convienent way to simply verify the current sort field,
This \*(CI can be a convienent way to simply verify the current sort field,
when running \*(Me with column highlighting turned \*F.
.TP 7
@ -1133,6 +1135,12 @@ Try this:\ \ using 'R' you can\fI alternate\fR between high-to-low
and low-to-high sorts.
Lose no sleep over 'reverse' and 'normal', ok?
.PP
.in +2
\*(NT Field sorting uses internal values, not those in column display.
Thus, the TTY and WCHAN fields will violate strict ASCII collating sequence.
.in
.\" ......................................................................
.SS 3d. COLOR Mapping
.Scr
@ -1156,7 +1164,7 @@ in\fB all\fR four windows before returning to the \*(Me display.
.Img
+\fB--------------------------------------\fR+
this shows you the |top's\fB Help for color mapping\fR - procps :\fB
this shows you the |\fBHelp for color mapping\fR - procps versio:\fB
Target Window ----->\fR |current window:\fB 1:Def\fR :
-*- | :
a\fB Sample Screen\fR with | color - 04:25:44 up 8 days, 50 min,:
@ -1470,11 +1478,11 @@ empty rows...
(when 2\fB WAS\fR current) | 683 1\fB xinetd -stayali\fR 0:00.00:
|\fI___836_____1_\fBlogin_--_root\fI_____0:00.00\fR:
3:Mem has altered |\fI3__PID_%MEM__VIRT_SWAP__RES_CODE_DATA_\fR:
some std defaults: | 4634\fB 12.3\fR 15620 0\fB 15m\fR 860 14m :
'y' turned Off | 7337\fB 11.3\fR 14396 92\fB 13m\fR 36 13m :
'x' turned On | 923\fB 10.6\fR 30544 16m\fB 13m\fR 1120 12m :
(when 3\fB WAS\fR current) | 991\fB 7.2\fR 9492 316\fB 9176\fR 12 9164 :
|\fI__7329__\fB7.0\fI__9036__140_\fB8896\fR___36_8860_\fR:
some std defaults: | 4634\fB 12.3\fR 15620 0 15m 860 14m :
'y' turned Off | 7337\fB 11.3\fR 14396 92 13m 36 13m :
'x' turned On | 923\fB 10.6\fR 30544 16m 13m 1120 12m :
(when 3\fB WAS\fR current) | 991\fB 7.2\fR 9492 316 9176 12 9164 :
|\fI__7329__\fB7.0\fI__9036__140_8896___36_8860_\fR:
Huh? 4:Usr has some |\fI4_UID_USER_____GROUP____TTY________PID\fR:
\fBblank rows\fR! ? ? ? ? | \fB 0 jtwm root pts/2 5561\fR:
Aha, the 'i' command | \fB 0 root root ? 5560\fR:
@ -1581,14 +1589,14 @@ seconds or less.
For this experiment, under x-windows open an xterm and maximize it.
Then do the following:
. provide a scheduling boost + tiny delay via:
. provide a scheduling boost and tiny delay via:
nice -n -10 top -d.09
. keep sorted column highlighting \*F
to minimize path length
. keep sorted column highlighting \*F to minimize
path length
. turn \*O reverse row highlighting for emphasis
. try various sort columns (TIME/MEM work well),
and normal or reverse sorts to bring
the most active processes into view
and normal or reverse sorts to bring the most
active processes into view
What you'll see is a\fB very busy Linux\fR doing what he's always done
for you, but there was no program available to illustrate this (until now).
@ -1650,39 +1658,91 @@ Then ponder this:
.SH 7. NOTES and Rantings
.\" ----------------------------------------------------------------------
.\" ......................................................................
.SS 7a. The top BINARY
To whom it may/\fBshould\fR concern: \*(Us, even with its vastly expanded
capabilities, is essentially the same size as the old top.
.SS 7a. The top Binary
.PP
To whom it may (should) concern: \*(Us, even with its vastly expanded
capabilities, is only slightly larger than the old top.
Were it not for extensive help text and additional sort callbacks, it would
be smaller.
.Rjb 6
Throw source carelessly at objectives, it\fI will\fR
produce equally careless machine instructions!
produce equally careless machine instructions.
example: (num_\fBpages\fR - an_\fBaddress\fR)/1024 == duh?
kicker: \fBdocument\fR result as broken, due to\fB elf\fR!
\fB----------------------------------------------\fR
I know you're out there, are you getting this?
.Rje
.PP
Now, as for all those new capabilities like colors and windows and
highlighting, just what are the\fB additional\fR run-time\fB costs\fR?
.br
Hmmm, let's see...
highlighting, you'd expect \*(Us to be the "mother of all pigs"
compared to old \*(Me \*(EM right?
Yea, with \*(US expect following piglets:
.br
\ \. A\fI smaller\fR virtual image and resident footprint
.br
\ \. Slightly\fI fewer\fR major page faults
.br
\ \. A\fI large reduction\fR in minor page faults for SMP
.br
\ \. The\fI same\fR or better response time
.br
\ \. The same or\fI even less\fR \*(PU costs
Ideally any comparison of the old and new \*(Me should be against the same
libproc format (32-bit or 64-bit tics) and run in a true or simulated SMP
environment (producing separate \*(PU stats).
This latter requirement will coax old \*(Me into handling his own '/proc/stat'
access \*(EM something \*(Us always does, but with less cost.
.\" ......................................................................
.SS 7b. Comparing Performance
.PP
Even with equivalent libraries and '/proc/stat' access, it's difficult to
accurately compare tops using their \fBown displays\fR.
Results for these \*(Pu\-intensive programs (who frequently exceed their
time-slice) generally show a wide disparity in %CPU.
This is due to differing call patterns, kernel preemptions and the timing
of process snapshots.
For\fI slightly\fR better results, start each program with the following
commands:
./old-top -d 0.5
nice -n-10 ./new-top -d 0.4
While actually putting \*(Us at a performance disadvantage, the higher
scheduling priority and staggered timing will\fI periodically\fR yield
a somewhat truer picture.
You could even reverse those roles and get similar results.
The most\fI consistent\fR performance results will be obtained 'off-line',
using your shell's time pipe or the time program itself.
And even in a single processor environment or without equivalent libraries,
total cpu costs (user time + system time) are similar.
However, \*(Us's \*(Pu costs ARE influenced by the capabilities you choose
to exploit, even if they don't SEEM to be reflected in such timings.
So let's examine some...
.\" ......................................................................
.SS 7c. Cost of Stuff
.TP 3
.B Colors\fR \*(EM Nada.
.B Colors Cost\fR \*(EM Nada (almost).
Once the terminfo strings are built (\fIat\fR and\fI during\fR a user's behest)
they are SAVED with each window's stuff.
And while there will be a few extra tty escape sequences transmitted because
of colors, it makes NO difference which 'char *' is actually used.
And while there will be extra tty escape sequences transmitted because
of colors, it makes no difference which 'char *' is actually used.
.TP 3
.B Highlighting\fR \*(EM Maybe Nada, or blame it on Rio.
.B Highlighting Cost\fR \*(EM Nada (maybe), or blame it on Rio.
On second thought, let's blame it on the user.
For\fI row\fR highlighting, there is NO extra cost (same reason as for colors).
For\fI column\fR highlighting, there is a fairly\fB significant cost\fR for
column transition management incurred on every \*(TD row.
For\fI row\fR highlighting, there is only the cost of those extra tty
escape sequences (same as for colors).
For\fI column\fR highlighting, there is a fairly\fB significant cost\fR
associated with column transition management combined with even more
tty output.
These increased costs are incurred on every \*(TD row.
Sooo... hey USER \*(EM \fIdo NOT highlight COLUMNS\fR.
You shouldn't need a constant visual reminder of your chosen sort field.
@ -1690,7 +1750,7 @@ However, if you forget which field \*(Me is sorting it can serve as a
quick visual reminder.
.TP 3
.B Windows\fR \*(EM If just 1 window, Nada.
.B Windows Cost\fR \*(EM Nada (if just 1 window).
If more than 1 window, almost certainly NOT Nada so blame it on reality.
Colors are not an issue, but those sort fields are.
@ -1705,9 +1765,9 @@ Those sorts involve\fB pointers only\fR.
And,\fI that's as good as it gets\fR\ !\ \ (right Mr. N?)
.\" ......................................................................
.SS 7b. The top SOURCES
.SS 7d. The top Sources
.TP 3
.B top.h\fR:
.B top.h\fR
Unlike his predecessor, \*(Us has a proper header file.
It contains ONLY declarations, NOT definitions.
And there are several conditionals present to help with further customizations
@ -1715,9 +1775,8 @@ and experimentation.
All are \*F by default.
.TP 3
.B top.c\fR:
Hopefully proves that source code needn't be a disorganized,
misaligned MESS.
.B top.c\fR
Hopefully proves that source code needn't be a disorganized, misaligned MESS.
And, WHO says a source listing shouldn't occasionally make you SMILE?
Why, \*(Me.c even does a darn good job of following the suggestions in a
document hardly anybody seems to observe.
@ -1816,7 +1875,7 @@ Plus, without those awful *the-devil's-own-handiwork*, the
aforementioned document need NEVER speak of their EVILS again.
.Jbu
Lastly, since SPACES (not\fB stinkin' tabs\fR) are SO beneficial, maybe
Lastly, since SPACES (not stinkin' tabs) are SO beneficial, maybe
we should use just a\fB few more\fR of 'em.
Some of those C-thingies are VERY sensitive \*(EM they don't like being TOUCHED
by any other syntax element!
@ -1890,8 +1949,8 @@ With invaluable help from:
.\" ----------------------------------------------------------------------
.SH 11. SEE ALSO
.\" ----------------------------------------------------------------------
.BR ps (1),
.BR free (1),
.BR ps (1),
.BR uptime (1),
.BR vmstat (8),
.BR w (1).

375
top.c
View File

@ -123,8 +123,6 @@ static int No_ksyms = -1, /* set to '0' if ksym avail, '1' otherwise */
Loops = -1, /* number of iterations, -1 loops forever */
Secure_mode = 0; /* set if some functionality restricted */
/* Miscellaneous global stuff ####################################*/
/* Some cap's stuff to reduce runtime calls --
to accomodate 'Batch' mode, they begin life as empty strings */
static char Cap_bold [CAPBUFSIZ] = "",
@ -139,10 +137,6 @@ static char Cap_bold [CAPBUFSIZ] = "",
Caps_off [CAPBUFSIZ] = "";
static int Cap_can_goto = 0;
/* Just to get gcc off our back and eliminate warnings about
'... discards qualifiers from pointer target type' */
static char Empty_str[] = "";
static char Question_mark[] = "?";
/* ////////////////////////////////////////////////////////////// */
/* Special Section: multiple windows/field groups ---------------*/
@ -165,10 +159,14 @@ static int Frame_maxtask, /* last known number of active tasks */
/*###### Sort callbacks ################################################*/
/* These happen to be coded in the same order as the enum 'pflag'
values -- but the only positionally dependent sort callback is
the 'pid' guy who MAY be invoked under return SORT_eq
(2 of these routines serve double duty -- 2 columns each) */
/*
* These happen to be coded in the same order as the enum 'pflag'
* values -- but the only positionally dependent sort callback is
* the 'pid' guy who MAY be invoked under 'return SORT_eq' and
* thus must be first.
*
* Note: 2 of these routines serve double duty -- 2 columns each.
*/
_SC_NUM1(P_PID, pid)
_SC_NUM1(P_PPD, ppid)
_SC_NUM1(P_PGD, pgrp)
@ -275,16 +273,15 @@ static const char *fmtmk (const char *fmts, ...)
/*
* What need be said... */
* This guy was originally designed just to trim the rc file lines and
* any 'open_psdb_message' result which arrived with an inappropriate
* newline (thanks to 'sysmap_mmap') -- but when tabs (^I) were found
* in some proc cmdlines, a choice was offered twix space or null. */
static char *strim (int sp, char *str)
{
const char *ws = "\b\f\n\r\t\v";
static const char *ws = "\b\f\n\r\t\v";
char *p;
/* this guy was originally designed just to trim the rc file lines and
any 'open_psdb_message' result which arrived with an inappropriate
newline (thanks to 'sysmap_mmap') -- but when tabs (^I) were found
in some proc cmdlines, a choice was offered twix space or null... */
if (sp)
while ((p = strpbrk(str, ws))) *p = ' ';
else
@ -294,10 +291,12 @@ static char *strim (int sp, char *str)
/*
* This guy just facilitates Batch and protects against dumb ttys. */
* This guy just facilitates Batch and protects against dumb ttys
* -- we'd 'inline' him but he's only called twice per frame,
* yet used in many other locations. */
static char *tg2 (int x, int y)
{
return Cap_can_goto ? tgoto(cursor_address, x, y) : Empty_str;
return Cap_can_goto ? tgoto(cursor_address, x, y) : "";
}
@ -321,7 +320,7 @@ static void bye_bye (int eno, const char *str)
"\nbye_bye's Summary report:"
"\n\tProgram"
"\n\t Page_size = %d, Cpu_tot = %d"
"\n\t %s, Hertz = %u (size %u bytes, %u-bit time)"
"\n\t %s, using Hertz = %u (%u bytes, %u-bit time)"
"\n\t sizeof(CPUS_t) = %u, sizeof(HIST_t) = %u (%u HIST_t's/Page)"
"\n\t CPU_FMTS_JUST1 = %s"
" \t CPU_FMTS_MULTI = %s"
@ -424,7 +423,7 @@ static void suspend (int dont_care_sig)
}
/*###### Misc Color/Highlighting support ###############################*/
/*###### Misc Color/Display support ####################################*/
/*
* Make the appropriate caps/color strings and set some
@ -612,7 +611,7 @@ static void show_special (const char *glob)
/* if there's anything left in the glob (by virtue of no trailing '\n'),
it probably means caller wants to retain cursor position on this final
line -- ok then, we'll just do our 'fit-to-screen' thingy... */
if (strlen(glob)) printf("%.*s", Screen_cols, glob);
if (*glob) printf("%.*s", Screen_cols, glob);
fflush(stdout);
}
@ -709,7 +708,7 @@ static char *scale_num (unsigned num, const unsigned width, const unsigned type)
return buf;
}
/* well shoot, this outta' fit... */
return Question_mark;
return "?";
}
@ -734,12 +733,12 @@ static char *scale_tics (TICS_t tics, const unsigned width)
/* try successively higher units until it fits */
t = tics / Hertz;
sprintf(buf, "%u:%02u.%02u" /* minutes:seconds.hundredths */
, t/60, t%60, (unsigned)((tics*100)/Hertz)%100);
sprintf(buf, "%u:%02u.%02u" /* mins:secs.hundredths */
, t / 60, t % 60, (unsigned)((tics * 100) / Hertz) % 100);
if (strlen(buf) <= width)
return buf;
sprintf(buf, "%u:%02u", t/60, t%60); /* minutes:seconds */
sprintf(buf, "%u:%02u", t / 60, t % 60); /* minutes:seconds */
if (strlen(buf) <= width)
return buf;
@ -751,7 +750,7 @@ static char *scale_tics (TICS_t tics, const unsigned width)
return buf;
};
/* well shoot, this outta' fit... */
return Question_mark;
return "?";
}
@ -779,7 +778,6 @@ static float time_elapsed (void)
/*
* Handle our own memory stuff without the risk of leaving the
* user's terminal in an ugly state should things go sour. */
static const char *alloc_msg = "Failed memory allocate (%d bytes)";
static void *alloc_c (unsigned numb)
{
@ -787,7 +785,7 @@ static void *alloc_c (unsigned numb)
if (!numb) ++numb;
if (!(p = calloc(1, numb)))
std_err(fmtmk(alloc_msg, numb));
std_err("failed memory allocate");
return p;
}
@ -798,13 +796,59 @@ static void *alloc_r (void *q, unsigned numb)
if (!numb) ++numb;
if (!(p = realloc(q, numb)))
std_err(fmtmk(alloc_msg, numb));
std_err("failed memory allocate");
return p;
}
/*
* This guy is modeled on libproc's readproctab function except
* This guy's modeled on libproc's 'four_cpu_numbers' function except
* we preserve all cpu data in our CPUS_t array which is organized
* as follows:
* cpus[0] thru cpus[n] == tics for each separate cpu
* cpus[Cpu_tot] == tics from the 1st /proc/stat line */
static CPUS_t *refreshcpus (CPUS_t *cpus)
{
#include <fcntl.h>
static FILE *fp = NULL;
int i;
/* 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) */
if (!fp) {
if (!(fp = fopen("/proc/stat", "r")))
std_err(fmtmk("Failed /proc/stat open: %s", strerror(errno)));
/* note: we allocate one more CPUS_t than Cpu_tot so that the last slot
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(CPUS_t));
}
rewind(fp);
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))
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
#else
if (4 != fscanf(fp, CPU_FMTS_MULTI
#endif
, &cpus[i].u, &cpus[i].n, &cpus[i].s, &cpus[i].i))
std_err("failed /proc/stat read");
}
return cpus;
}
/*
* This guy's modeled on libproc's 'readproctab' function except
* we reuse and extend any prior proc_t's. He's been customized
* for our specific needs and to avoid the use of <stdarg.h> */
static proc_t **refreshprocs (proc_t **tbl)
@ -933,7 +977,7 @@ static void configs_read (void)
fgets(fbuf, sizeof(fbuf), fp); /* ignore shameless advertisement */
if (5 != (fscanf(fp, "Id:%c, "
"Mode_altscr=%d, Mode_irixps=%d, Delay_time=%f, Curwin=%d\n"
, &id, &Mode_altscr, &Mode_irixps, &delay, &i)))
, &id, &Mode_altscr, &Mode_irixps, &delay, &i)) || RCF_FILEID != id)
std_err(fmtmk(err_rc, RCfile));
/* you saw that, right? (fscanf stickin' it to 'i') */
@ -951,7 +995,7 @@ static void configs_read (void)
then we catch it with strlen and end via std_err - no worries!
we might not have been so lucky if our WIN_t was laid out
differently and statically allocated or stack based!! */
if (RCF_FILEID != id || WINNAMSIZ <= strlen(Winstk[i]->winname)
if (WINNAMSIZ <= strlen(Winstk[i]->winname)
|| strlen(DEF_FIELDS) != strlen(Winstk[i]->fieldscur))
std_err(fmtmk(err_rc, RCfile));
fscanf(fp, "\twinflags=%d, sortindx=%d, maxtasks=%d \n"
@ -989,7 +1033,8 @@ static void parse_args (char **args)
. no deprecated/illegal use of 'breakargv:' with goto
. bunched args are actually handled properly and none are ignored
. we tolerate NO whitespace and NO switches -- maybe too tolerant? */
const char *usage = " -hv | -bcisS -d delay -n iterations -p pid [,pid ...]\n";
static const char *usage =
" -hv | -bcisS -d delay -n iterations -p pid [,pid ...]";
float tmp_delay = MAXFLOAT;
char *p;
@ -1017,7 +1062,7 @@ static void parse_args (char **args)
break;
case 'h': case 'H':
case 'v': case 'V':
std_err(fmtmk("\t%s\nusage:\t%s%s"
std_err(fmtmk("%s\nusage:\t%s%s"
, procps_version, Myname, usage));
case 'i':
TOGw(Curwin, Show_IDLEPS);
@ -1083,14 +1128,14 @@ static void whack_terminal (void)
/* first the curses part... */
#ifdef PRETENDNOCAP
setupterm((char *)"dumb", STDOUT_FILENO, NULL);
setupterm("dumb", STDOUT_FILENO, NULL);
#else
setupterm(NULL, STDOUT_FILENO, NULL);
#endif
/* now our part... */
if (!Batch) {
if (-1 == tcgetattr(STDIN_FILENO, &Savedtty))
std_err("tcgetattr() failed");
std_err("failed tty get");
newtty = Savedtty;
newtty.c_lflag &= ~ICANON;
newtty.c_lflag &= ~ECHO;
@ -1100,7 +1145,7 @@ static void whack_terminal (void)
Ttychanged = 1;
if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &newtty)) {
putp(Cap_clr_scr);
std_err(fmtmk("Failed tty set: %s", strerror(errno)));
std_err(fmtmk("failed tty set: %s", strerror(errno)));
}
tcgetattr(STDIN_FILENO, &Rawtty);
putp(Cap_clr_scr);
@ -1208,7 +1253,7 @@ static void display_fields (const char *fields, const char *xtra)
static void fields_reorder (void)
{
static const char *prompt =
"Upper case characters move field left, lower case right";
"Upper case letter moves field left, lower case right";
char c, *p;
int i;
@ -1241,10 +1286,10 @@ static void fields_sort (void)
"Select sort field via field letter, type any other key to return";
char phoney[PFLAGSSIZ];
char c, *p;
int i;
int i, x;
strcpy(phoney, NUL_FIELDS);
i = Curwin->sortindx;
x = i = Curwin->sortindx;
printf("%s%s", Cap_clr_scr, Cap_curs_huge);
do {
p = phoney + i;
@ -1256,10 +1301,11 @@ static void fields_sort (void)
i = toupper(c) - 'A';
if (i < 0 || i >= MAXTBL(Fieldstab)) break;
*p = tolower(*p);
if ((p = strchr(Curwin->fieldscur, i + 'a')))
*p = i + 'A';
Curwin->sortindx = i;
x = i;
} while (1);
if ((p = strchr(Curwin->fieldscur, x + 'a')))
*p = x + 'A';
Curwin->sortindx = x;
putp(Cap_curs_norm);
}
@ -1302,7 +1348,7 @@ static void win_colsheads (WIN_t *q)
int i, needpsdb = 0;
/* build window's procflags array and establish a tentative maxpflgs */
for (i = 0, q->maxpflgs = 0; i < (int)strlen(q->fieldscur); i++) {
for (i = 0, q->maxpflgs = 0; q->fieldscur[i]; i++) {
if (isupper(q->fieldscur[i]))
q->procflags[q->maxpflgs++] = q->fieldscur[i] - 'A';
}
@ -1321,7 +1367,6 @@ static void win_colsheads (WIN_t *q)
column heading via maxcmdln -- it may be a fib if P_CMD wasn't
encountered, but that's ok because it won't be displayed anyway */
q->maxpflgs = i;
q->procflags[i] = '\0';
q->maxcmdln = Screen_cols
- (strlen(q->columnhdr) - strlen(Fieldstab[P_CMD].head)) - 1;
@ -1398,8 +1443,8 @@ static void win_select (int ch)
* Just warn the user when a command can't be honored. */
static int win_warn (void)
{
show_msg(fmtmk("\aCommand disabled, activate window #%d with '-' or '_'"
, Curwin->winnum));
show_msg(fmtmk("\aCommand disabled, activate %s with '-' or '_'"
, Curwin->grpname));
/* we gotta' return false 'cause we're somewhat well known within
macro society, by way of that sassy little tertiary operator... */
return 0;
@ -1514,27 +1559,20 @@ static void wins_reflag (int what, int flg)
TOGw(w, flg);
break;
case Flags_SET: /* Ummmm, i can't find anybody */
SETw(w, flg); /* who uses Flags_set -- maybe */
break; /* ol' gcc will opt it away... */
SETw(w, flg); /* who uses Flags_set ... */
break;
case Flags_OFF:
OFFw(w, flg);
break;
}
w = w->next;
} while (w != Curwin);
/* a flag with special significance -- user wants to rebalance display
so darn it, we gotta' spin thru all those windows one mo' time and
'off' one number then force on two flags... */
/* (jeeze, doesn't this idiot know there are just 4 windows?) */
/* a flag with special significance -- user wants to rebalance
display so we gotta' 'off' one number then force on two flags... */
if (EQUWINS_cwo == flg) {
w = Curwin;
do {
w->maxtasks = 0;
SETw(w, Show_IDLEPS | VISIBLE_tsk);
}
w = w->next;
} while (w != Curwin);
}
}
@ -1564,8 +1602,8 @@ static void wins_resize (int dont_care_sig)
/*
* Set up the raw/incomplete field group windows --
* they'll be finished off after startup completes.
* (and very likely that will override most/all of our efforts)
* ( --- life-is-NOT-fair --- ) */
* [ and very likely that will override most/all of our efforts ]
* [ --- life-is-NOT-fair --- ] */
static void windows_stage1 (void)
{
static struct {
@ -1629,7 +1667,7 @@ static void windows_stage2 (void)
if (Batch) {
Mode_altscr = 0;
OFFw(Curwin, Show_COLORS);
OFFw(Curwin, Show_COLORS | Show_HICOLS | Show_HIROWS);
}
wins_resize(0);
for (i = 0; i < GROUPSMAX; i++) {
@ -1649,25 +1687,17 @@ static void windows_stage2 (void)
* 2 - modest smp boxes with room for each cpu's percentages
* 3 - massive smp guys leaving little or no room for process
* display and thus requiring the cpu summary toggle */
static void cpudo (FILE *fp, const char *fmt, CPUS_t *cpu, const char *pfx)
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)
TICS_t u_tics, s_tics, n_tics, i_tics;
STIC_t u_frme, s_frme, n_frme, i_frme, tot_frme, tz;
#ifdef PRETEND4CPUS
rewind(fp);
fmt = CPU_FMTS_JUST1;
#endif
if (4 != fscanf(fp, fmt, &u_tics, &n_tics, &s_tics, &i_tics))
std_err("Failed /proc/stat read");
u_frme = TRIMz(u_tics - cpu->u);
s_frme = TRIMz(s_tics - cpu->s);
n_frme = TRIMz(n_tics - cpu->n);
i_frme = TRIMz(i_tics - cpu->i);
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;
if (1 > tot_frme) tot_frme = 1;
@ -1682,10 +1712,10 @@ static void cpudo (FILE *fp, const char *fmt, CPUS_t *cpu, const char *pfx)
Msg_row += 1;
/* remember for next time around */
cpu->u = u_tics;
cpu->s = s_tics;
cpu->n = n_tics;
cpu->i = i_tics;
cpu->u_sav = cpu->u;
cpu->s_sav = cpu->s;
cpu->n_sav = cpu->n;
cpu->i_sav = cpu->i;
#undef TRIMz
}
@ -1696,11 +1726,10 @@ static void cpudo (FILE *fp, const char *fmt, CPUS_t *cpu, const char *pfx)
* Calc percent cpu usage for each task (pcpu)
* Calc the cpu(s) percent in each state (user, system, nice, idle)
* AND establish the total number of tasks for this frame! */
static void frame_states (proc_t **p, int show)
static void frame_states (proc_t **ppt, int show)
{
static HIST_t *hist_sav = NULL;
static unsigned hist_siz;
static CPUS_t *smpcpu;
HIST_t *hist_new;
unsigned total, running, sleeping, stopped, zombie;
float etime;
@ -1710,19 +1739,15 @@ static void frame_states (proc_t **p, int show)
Frame_maxtask = 0;
hist_siz = (Page_size / sizeof(HIST_t));
hist_sav = alloc_c(hist_siz);
/* note: we allocate one more CPUS_t than Cpu_tot so that the last
slot can hold tics representing the /proc/stat cpu summary
(first line read) -- that slot supports summary cpu info */
smpcpu = alloc_c((1 + Cpu_tot) * sizeof(CPUS_t));
}
hist_new = alloc_c(hist_siz);
total = running = sleeping = stopped = zombie = 0;
etime = time_elapsed();
/* make a pass through the data to get stats */
while (-1 != p[total]->pid) { /* calculations //// */
while (-1 != ppt[total]->pid) { /* calculations //// */
TICS_t tics;
proc_t *this = p[total];
proc_t *this = ppt[total];
switch (this->state) {
case 'S':
@ -1770,33 +1795,29 @@ static void frame_states (proc_t **p, int show)
if (show) { /* display ///////// */
FILE *fp;
static CPUS_t *smpcpu = NULL;
/* display Task states */
show_special(fmtmk(STATES_line1
, total, running, sleeping, stopped, zombie));
Msg_row += 1;
if (!(fp = fopen("/proc/stat", "r")))
std_err(fmtmk("Failed /proc/stat open: %s", strerror(errno)));
/* refresh our /proc/stat data... */
smpcpu = refreshcpus(smpcpu);
if (CHKw(Curwin, View_CPUSUM)) {
/* retrieve and display just the 1st /proc/stat line */
cpudo(fp, CPU_FMTS_JUST1, &smpcpu[Cpu_tot], "Cpu(s) state:");
/* display just the 1st /proc/stat line */
cpudo(&smpcpu[Cpu_tot], "Cpu(s) state:");
} else {
char tmp[SMLBUFSIZ];
/* skip the 1st line, which reflects total cpu states */
if (!fgets(tmp, sizeof(tmp), fp)) std_err("Failed /proc/stat read");
/* now do each cpu's states separately */
/* 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 : ... ' */
cpudo(fp, CPU_FMTS_MULTI, &smpcpu[i], tmp);
cpudo(&smpcpu[i], tmp);
}
}
fclose(fp);
} /* end: if 'show' */
/* save this frame's information */
@ -1819,7 +1840,7 @@ static void frame_storage (void)
unsigned long long **memarray;
if (!(memarray = meminfo()))
std_err("Failed /proc/meminfo read");
std_err("failed /proc/meminfo read");
if (CHKw(Curwin, View_MEMORY)) {
show_special(fmtmk(MEMORY_line1
@ -1866,6 +1887,9 @@ static void mkcol (WIN_t *q, PFLG_t idx, int sta, int *pad, char *buf, ...)
va_list va;
va_start(va, buf);
/* this conditional is for piece-of-mind only, it should NOT be needed
given the macro employed by show_a_task (which calls us only when
the target column is the current sort field and Show_HICOLS is on) */
if (!CHKw(q, Show_HICOLS) || q->sortindx != idx) {
vsprintf(buf, Fieldstab[idx].fmts, va);
} else {
@ -1885,25 +1909,31 @@ static void mkcol (WIN_t *q, PFLG_t idx, int sta, int *pad, char *buf, ...)
* Display information for a single task row. */
static void show_a_task (WIN_t *q, proc_t *task)
{
/* the following macro is our means to 'inline' emitting a column -- that's
far and away the most frequent and costly part of top's entire job! */
#define MKCOL(q,idx,sta,pad,buf,arg...) \
if (!b) \
sprintf(buf, f, ## arg); \
else mkcol(q, idx, sta, pad, buf, ## arg);
char rbuf[ROWBUFSIZ];
int i, x, pad;
int j, x, pad;
/* since win_colsheads adds a number to the window's column header,
we must begin a row with that in mind... */
pad = Mode_altscr;
if (pad) strcpy(rbuf, " "); else rbuf[0] = '\0';
for (i = 0; i < q->maxpflgs; i++) {
for (x = 0; x < q->maxpflgs; x++) {
char cbuf[COLBUFSIZ];
PFLG_t f;
unsigned s, w;
char a = task->state; /* we'll use local var's so */
PFLG_t i = q->procflags[x]; /* gcc doesn't reinvent the */
unsigned s = Fieldstab[i].scale; /* wheel -- yields a cryptic */
unsigned w = Fieldstab[i].width; /* mkcol, but saves +1k code */
const char *f = Fieldstab[i].fmts; /* (this & next macro only) */
int b = (CHKw(q, Show_HICOLS) && q->sortindx == i);
cbuf[0] = '\0';
f = q->procflags[i];
s = Fieldstab[f].scale;
w = Fieldstab[f].width;
switch (f) {
switch (i) {
case P_CMD:
{ char *cmdptr, cmdnam[ROWBUFSIZ];
@ -1912,104 +1942,98 @@ static void show_a_task (WIN_t *q, proc_t *task)
else {
cmdnam[0] = '\0';
if (task->cmdline) {
x = 0;
j = 0;
do {
/* during a kernel build, parts of the make will create
cmdlines in excess of 3000 bytes but *without* the
intervening nulls -- so we must limit our strcat... */
strcat(cmdnam
, fmtmk("%.*s ", q->maxcmdln, task->cmdline[x++]));
, fmtmk("%.*s ", q->maxcmdln, task->cmdline[j++]));
/* whoa, gnome's xscreensaver had a ^I in his cmdline
creating a line wrap when the window was maximized &
the tab came into view -- so whack those suckers... */
strim(1, cmdnam);
if (q->maxcmdln < (int)strlen(cmdnam)) break;
} while (task->cmdline[x]);
} while (task->cmdline[j]);
} else {
/* if cmdline is absent, consider it a kernel thread and
display it uniquely (we'll need sort_cmd's complicity) */
strcpy(cmdnam, fmtmk("( %s )", task->cmd));
display it uniquely (need sort callback's complicity) */
strcpy(cmdnam, fmtmk(CMDLINE_FMTS, task->cmd));
}
cmdptr = cmdnam;
}
mkcol(q, f, task->state, &pad
, cbuf, q->maxcmdln, q->maxcmdln, cmdptr);
MKCOL(q, i, a, &pad, cbuf, q->maxcmdln, q->maxcmdln, cmdptr);
}
break;
case P_COD:
mkcol(q, f, task->state, &pad, cbuf
, scale_num(PAGES_2K(task->trs), w, s));
MKCOL(q, i, a, &pad, cbuf, scale_num(PAGES_2K(task->trs), w, s));
break;
case P_CPN:
#ifdef UGH_ITS_4_RH
mkcol(q, f, task->state, &pad, cbuf, task->lproc);
MKCOL(q, i, a, &pad, cbuf, task->lproc);
#else
mkcol(q, f, task->state, &pad, cbuf, task->processor);
MKCOL(q, i, a, &pad, cbuf, task->processor);
#endif
break;
case P_CPU:
mkcol(q, f, task->state, &pad, cbuf, (float)task->pcpu / 10);
MKCOL(q, i, a, &pad, cbuf, (float)task->pcpu / 10);
break;
case P_DAT:
mkcol(q, f, task->state, &pad, cbuf
, scale_num(PAGES_2K(task->drs), w, s));
MKCOL(q, i, a, &pad, cbuf, scale_num(PAGES_2K(task->drs), w, s));
break;
case P_DRT:
mkcol(q, f, task->state, &pad, cbuf
, scale_num((unsigned)task->dt, w, s));
MKCOL(q, i, a, &pad, cbuf, scale_num((unsigned)task->dt, w, s));
break;
case P_FLG:
mkcol(q, f, task->state, &pad, cbuf, task->flags);
for (x = 0; x < (int)strlen(cbuf); x++)
if ('0' == cbuf[x]) cbuf[x] = '.';
MKCOL(q, i, a, &pad, cbuf, (long)task->flags);
for (j = 0; cbuf[j]; j++)
if ('0' == cbuf[j]) cbuf[j] = '.';
break;
case P_FLT:
mkcol(q, f, task->state, &pad, cbuf
, scale_num(task->maj_flt, w, s));
MKCOL(q, i, a, &pad, cbuf, scale_num(task->maj_flt, w, s));
break;
case P_GRP:
mkcol(q, f, task->state, &pad, cbuf, task->egroup);
MKCOL(q, i, a, &pad, cbuf, task->egroup);
break;
case P_MEM:
mkcol(q, f, task->state, &pad, cbuf
#ifdef UGH_ITS_4_RH
MKCOL(q, i, a, &pad, cbuf
, (float)task->resident * 100 / Mem_pages);
#else
MKCOL(q, i, a, &pad, cbuf
, (float)PAGES_2K(task->resident) * 100 / kb_main_total);
#endif
break;
case P_NCE:
mkcol(q, f, task->state, &pad, cbuf, task->nice);
MKCOL(q, i, a, &pad, cbuf, (long)task->nice);
break;
case P_PGD:
mkcol(q, f, task->state, &pad, cbuf, task->pgrp);
MKCOL(q, i, a, &pad, cbuf, task->pgrp);
break;
case P_PID:
mkcol(q, f, task->state, &pad, cbuf, task->pid);
MKCOL(q, i, a, &pad, cbuf, task->pid);
break;
case P_PPD:
mkcol(q, f, task->state, &pad, cbuf, task->ppid);
MKCOL(q, i, a, &pad, cbuf, task->ppid);
break;
case P_PRI:
mkcol(q, f, task->state, &pad, cbuf, task->priority);
MKCOL(q, i, a, &pad, cbuf, (long)task->priority);
break;
case P_RES:
mkcol(q, f, task->state, &pad, cbuf
, scale_num(PAGES_2K(task->resident), w, s));
MKCOL(q, i, a, &pad, cbuf, scale_num(PAGES_2K(task->resident), w, s));
break;
case P_SHR:
mkcol(q, f, task->state, &pad, cbuf
, scale_num(PAGES_2K(task->share), w, s));
MKCOL(q, i, a, &pad, cbuf, scale_num(PAGES_2K(task->share), w, s));
break;
case P_STA:
#ifdef USE_LIB_STA3
mkcol(q, f, task->state, &pad, cbuf, status(task));
MKCOL(q, i, a, &pad, cbuf, status(task));
#else
mkcol(q, f, task->state, &pad, cbuf, task->state);
MKCOL(q, i, a, &pad, cbuf, task->state);
#endif
break;
case P_SWP:
mkcol(q, f, task->state, &pad, cbuf
MKCOL(q, i, a, &pad, cbuf
, scale_num(PAGES_2K(task->size - task->resident), w, s));
break;
case P_TME:
@ -2019,40 +2043,38 @@ static void show_a_task (WIN_t *q, proc_t *task)
t = task->utime + task->stime;
if (CHKw(q, Show_CTIMES))
t += (task->cutime + task->cstime);
mkcol(q, f, task->state, &pad, cbuf, scale_tics(t, w));
MKCOL(q, i, a, &pad, cbuf, scale_tics(t, w));
}
break;
case P_TTY:
{ char tmp[TNYBUFSIZ];
dev_to_tty(tmp, (int)w, task->tty, task->pid, ABBREV_DEV);
mkcol(q, f, task->state, &pad, cbuf, tmp);
MKCOL(q, i, a, &pad, cbuf, tmp);
}
break;
case P_UID:
mkcol(q, f, task->state, &pad, cbuf, task->euid);
MKCOL(q, i, a, &pad, cbuf, task->euid);
break;
case P_USR:
mkcol(q, f, task->state, &pad, cbuf, task->euser);
MKCOL(q, i, a, &pad, cbuf, task->euser);
break;
case P_VRT:
mkcol(q, f, task->state, &pad, cbuf
, scale_num(PAGES_2K(task->size), w, s));
MKCOL(q, i, a, &pad, cbuf, scale_num(PAGES_2K(task->size), w, s));
break;
case P_WCH:
if (No_ksyms)
if (No_ksyms) {
#ifdef CASEUP_HEXES
mkcol(q, f, task->state, &pad, cbuf
, fmtmk("x%08lX", (long)task->wchan));
MKCOL(q, i, a, &pad, cbuf, fmtmk("x%08lX", (long)task->wchan));
#else
mkcol(q, f, task->state, &pad, cbuf
, fmtmk("x%08lx", (long)task->wchan));
MKCOL(q, i, a, &pad, cbuf, fmtmk("x%08lx", (long)task->wchan));
#endif
else
mkcol(q, f, task->state, &pad, cbuf, wchan(task->wchan));
} else {
MKCOL(q, i, a, &pad, cbuf, wchan(task->wchan));
}
break;
} /* end: switch 'flg' */
} /* end: switch 'procflag' */
strcat(rbuf, cbuf);
} /* end: for 'maxpflgs' */
@ -2067,6 +2089,7 @@ static void show_a_task (WIN_t *q, proc_t *task)
, Caps_off
, Cap_clr_eol);
#undef MKCOL
}
@ -2077,10 +2100,10 @@ static void show_a_task (WIN_t *q, proc_t *task)
static void do_key (unsigned c)
{
/* standardized 'secure mode' errors */
const char *err_secure = "\aCan't %s in secure mode";
static const char *err_secure = "\aUnavailable in secure mode";
#ifdef WARN_NOT_SMP
/* standardized 'smp' errors */
const char *err_smp = "\aSorry, only 1 cpu detected";
static const char *err_smp = "\aSorry, only 1 cpu detected";
#endif
switch (c) {
@ -2122,7 +2145,7 @@ static void do_key (unsigned c)
case 'd':
case 's':
if (Secure_mode)
show_msg(fmtmk(err_secure, "change delay"));
show_msg(err_secure);
else {
float tmp =
get_float(fmtmk("Change delay from %.1f to", Delay_time));
@ -2166,7 +2189,7 @@ static void do_key (unsigned c)
/* this string is well above ISO C89's minimum requirements! */
show_special(fmtmk(KEYS_help
, procps_version
, Curwin->winname
, Curwin->grpname
, CHKw(Curwin, Show_CTIMES) ? "On" : "Off"
, Delay_time
, Secure_mode ? "On" : "Off"
@ -2208,7 +2231,7 @@ static void do_key (unsigned c)
case 'k':
if (Secure_mode) {
show_msg(fmtmk(err_secure, "kill"));
show_msg(err_secure);
} else {
int sig, pid = get_int("PID to kill");
@ -2263,7 +2286,7 @@ static void do_key (unsigned c)
case 'r':
if (Secure_mode)
show_msg(fmtmk(err_secure, "renice"));
show_msg(err_secure);
else {
int pid, val;
@ -2356,32 +2379,24 @@ static void do_key (unsigned c)
wins_colors();
break;
case '-': /* 'Dash' lower case ----------------------- */
case '-':
if (Mode_altscr)
TOGw(Curwin, VISIBLE_tsk);
break;
case '_': /* 'Dash' upper case ----------------------- */
if (Mode_altscr) /* switcharoo, all viz & inviz ............ */
case '_':
if (Mode_altscr)
wins_reflag(Flags_TOG, VISIBLE_tsk);
break;
case '=': /* 'Equals' lower case --------------------- */
/* special Key: equalize current window (& make viz) ...
. began life as 'windows' oriented and restricted to Mode_altscr!
. but symbiosis of documenting and further testing led to lifting
of restrictions -- we feel MUCH better now, thank-you-SO-much! */
case '=':
Curwin->maxtasks = 0;
SETw(Curwin, Show_IDLEPS | VISIBLE_tsk);
/* special Provision:
. escape from monitoring selected pids ('-p' cmdline switch)
-- just seems to go naturally with these new provisions
. and who knows, maybe the man doc will NOT be overlooked */
Monpidsidx = 0;
break;
case '+': /* 'Equals' upper case --------------------- */
if (Mode_altscr) /* equalize ALL task wins (& make viz) .... */
case '+':
if (Mode_altscr)
SETw(Curwin, EQUWINS_cwo);
break;
@ -2403,8 +2418,8 @@ static void do_key (unsigned c)
}
break;
case '\n': /* just ignore these */
case ' ':
case '\n': /* just ignore these, they'll have the effect */
case ' ': /* of refreshing display after waking us up ! */
break;
default:
@ -2449,7 +2464,7 @@ static proc_t **do_summary (void)
/*
** Display Tasks and Cpu(s) states and also calc 'pcpu',
** but NO p_table sort yet -- that's done on a per window basis! */
** but NO table sort yet -- that's done on a per window basis! */
p_table = refreshprocs(p_table);
frame_states(p_table, CHKw(Curwin, View_STATES));

71
top.h
View File

@ -27,6 +27,7 @@
//#define CASEUP_HEXES /* show any hex values in upper case */
//#define CASEUP_SCALE /* show scaled time/num suffix upper case */
//#define CASEUP_SUMMK /* show memory summary kilobytes with 'K' */
//#define POSIX_CMDLIN /* use '[ ]' for kernel threads, not '( )' */
//#define QUIT_NORMALQ /* use 'q' to quit, not new default 'Q' */
//#define SORT_SUPRESS /* *attempt* to reduce qsort overhead */
//#define TICS_64_BITS /* accommodate Linux 2.5.xx 64-bit jiffies */
@ -64,6 +65,7 @@
#define SMLBUFSIZ 256
#define MEDBUFSIZ 512
#define OURPATHSZ 1024
#define STATBUFSZ 1024
#define BIGBUFSIZ 2048
#define RCFBUFSIZ SMLBUFSIZ
#define USRNAMSIZ GETBUFSIZ
@ -105,7 +107,7 @@
if ( ((*P)->n1 - (*P)->n2) > ((*Q)->n1 - (*Q)->n2) ) return SORT_gt; \
return SORT_eq; }
#define _SC_STRZ(f,s) \
static int sort_ ## f(const proc_t **P, const proc_t **Q) { \
static int sort_ ## f (const proc_t **P, const proc_t **Q) { \
if ( 0 > strcmp((*P)->s, (*Q)->s) ) return SORT_lt; \
if ( 0 < strcmp((*P)->s, (*Q)->s) ) return SORT_gt; \
return SORT_eq; }
@ -159,15 +161,18 @@ typedef struct {
TICS_t tics;
} HIST_t;
/* This structure stores the prior frame's tics used in history
/* This structure stores a frame's cpu tics used in history
calculations. It exists primarily for SMP support but serves
all environments. There will always Cpu_tot + 1 allocated
-- see frame_states for details. */
all environments. */
typedef struct {
TICS_t u, /* ticks count as represented in /proc/stat */
n, /* (not in the order of our display) */
s,
i;
TICS_t u_sav, /* tics count in the order of our display */
s_sav,
n_sav,
i_sav;
} CPUS_t;
/* The scaling 'type' used with scale_num() -- this is how
@ -221,7 +226,7 @@ enum pflag {
#define Show_IDLEPS 0x0020 /* 'i' - show idle processes (all tasks) */
#define Qsrt_NORMAL 0x0010 /* 'R' - reversed column sort (high to low) */
/* these flag(s) have no command as such - they're for internal use */
#define VISIBLE_tsk 0x0008 /* tasks are showable in 'Show_altscr' mode */
#define VISIBLE_tsk 0x0008 /* tasks are showable when in 'Mode_altscr' */
#define NEWFRAM_cwo 0x0004 /* new frame (if anyone cares) - in Curwin */
#define EQUWINS_cwo 0x0002 /* rebalance tasks next frame (off 'i'/ 'n') */
/* ...set in Curwin, but impacts all windows */
@ -285,7 +290,7 @@ typedef struct win {
/* An rcfile 'footprint' used to invalidate existing local rcfile
and the global rcfile path + name */
#define RCF_FILEID 'i'
#define RCF_FILEID 'j'
#define SYS_RCFILE "/etc/toprc"
/* The default fields displayed and their order,
@ -299,13 +304,22 @@ typedef struct win {
#define NUL_FIELDS "abcdefghijklmnopqrstuvwxyz"
/* These are the possible fscanf formats used in /proc/stat
reads during history processing. */
reads during history processing.
( 5th number added in anticipation of kernel change ) */
#ifdef TICS_64_BITS
#define CPU_FMTS_MULTI "cpu%*d %Lu %Lu %Lu %Lu\n"
#define CPU_FMTS_JUST1 "cpu %Lu %Lu %Lu %Lu\n"
#define CPU_FMTS_JUST1 "cpu %Lu %Lu %Lu %Lu \n"
#define CPU_FMTS_MULTI "cpu%*d %Lu %Lu %Lu %Lu %*d \n"
#else
#define CPU_FMTS_MULTI "cpu%*d %lu %lu %lu %lu\n"
#define CPU_FMTS_JUST1 "cpu %lu %lu %lu %lu\n"
#define CPU_FMTS_JUST1 "cpu %lu %lu %lu %lu \n"
#define CPU_FMTS_MULTI "cpu%*d %lu %lu %lu %lu %*d \n"
#endif
/* This is the format for 'command line' display in the absence
of a command line (kernel thread). */
#ifdef POSIX_CMDLIN
#define CMDLINE_FMTS "[%s]"
#else
#define CMDLINE_FMTS "( %s )"
#endif
/* Summary Lines specially formatted string(s) --
@ -343,14 +357,14 @@ typedef struct win {
#endif
#define KEYS_help \
"Help for Interactive Commands\02 - %s\n" \
"Window %s\06: \01Cumulative mode \03%s\02. \01System\06: \01Delay time \03%.1f secs\02; \01Secure mode \03%s\02.\n" \
"Window \01%s\06: \01Cumulative mode \03%s\02. \01System\06: \01Delay \03%.1f secs\02; \01Secure mode \03%s\02.\n" \
"\n" \
" l,t,m Toggle Summary: '\01l\02' load avg; '\01t\02' task/cpu stats; '\01m\02' mem info\n" \
" 1,I Toggle SMP view: '\0011\02' single/separate states; '\01I\02' Irix/Solaris mode\n" \
" Z\05 Change color mappings\n" \
"\n" \
" f,o . Fields change: '\01f\02' fields select; '\01o\02' order fields\n" \
" F or O . Fields select sort\n" \
" f,o . Fields/Columns: '\01f\02' add or remove; '\01o\02' change display order\n" \
" F or O . Select sort field\n" \
" <,> . Move sort field: '\01<\02' next col left; '\01>\02' next col right\n" \
" R . Toggle normal/reverse sort\n" \
" c,i,S . Toggle: '\01c\02' cmd name/line; '\01i\02' idle tasks; '\01S\02' cumulative time\n" \
@ -358,16 +372,16 @@ typedef struct win {
" z,b\05 . Toggle: '\01z\02' color/mono; '\01b\02' bold/reverse (only if 'x' or 'y')\n" \
" u . Show specific user only\n" \
" n or # . Set maximum tasks displayed\n" \
" ( commands shown with '.' require a \01visible\02 task display \01window\02 ) \n" \
"\n" \
"%s" \
" W Write configuration file\n" \
HELP_Qkey "Quit\n" \
" ( commands shown with '.' require a \01visible\02 task display \01window\02 ) \n" \
"Press '\01h\02' or '\01?\02' for help with \01Windows\02,\n" \
"any other key to continue " \
""
/* This guy goes above the 'u' help text (maybe) */
/* This guy goes into the help text (maybe) */
#define KEYS_help_unsecured \
" k,r Manipulate tasks: '\01k\02' kill; '\01r\02' renice\n" \
" d or s Set update interval\n" \
@ -421,11 +435,11 @@ typedef struct win {
" within viewable range is chosen.\n" \
"\n" \
"Note2:\n" \
" The WCHAN field will display a name\n" \
" if the System.map exists, but it is\n" \
" always sorted as an address. Thus,\n" \
" alphabetic sequence will not apply.\n" \
" ( shame on you if you choose this )\n" \
" Field sorting uses internal values,\n" \
" not those in column display. Thus,\n" \
" the TTY & WCHAN fields will violate\n" \
" strict ASCII collating sequence.\n" \
" (shame on you if WCHAN is chosen)\n" \
""
/* Colors Help specially formatted string(s) --
@ -459,7 +473,7 @@ typedef struct win {
/* Windows/Field Group Help specially formatted string(s) --
see 'show_special' for syntax details + other cautions. */
#define WINDOWS_help \
"Help for Windows / Field Groups\02 - \"Current\" = \01 %s \06\n" \
"Help for Windows / Field Groups\02 - \"Current Window\" = \01 %s \06\n" \
"\n" \
". Use multiple \01windows\02, each with separate config opts (color,fields,sort,etc)\n" \
". The 'current' window controls the \01Summary Area\02 and responds to your \01Commands\02\n" \
@ -467,9 +481,9 @@ typedef struct win {
" . with \01NO\02 task display, some commands will be \01disabled\02 ('i','R','n','c', etc)\n" \
" until a \01different window\02 has been activated, making it the 'current' window\n" \
". You \01change\02 the 'current' window by: \01 1\02) cycling forward/backward;\01 2\02) choosing\n" \
" a specific window with 'O' or 'F'; or\01 3\02) exiting the color mapping screen\n" \
" a specific field group; or\01 3\02) exiting the color mapping screen\n" \
". Commands \01available anytime -------------\02\n" \
" \01A\02 . Alternate display mode toggle, show \01Single\02 / \01Multiple\02 windows\n" \
" A . Alternate display mode toggle, show \01Single\02 / \01Multiple\02 windows\n" \
" G . Choose another field group and make it 'current', or change now\n" \
" by selecting a number from: \01 1\02 =%s;\01 2\02 =%s;\01 3\02 =%s; or\01 4\02 =%s\n" \
". Commands \01requiring\02 '\01A\02' mode\01 -------------\02\n" \
@ -482,7 +496,7 @@ typedef struct win {
" (this also forces the \01current\02 or \01every\02 window to become visible)\n" \
"\n" \
"In '\01A\02' mode, '\01*\04' keys are your \01essential\02 commands. Please try the '\01a\02' and '\01w\02'\n" \
"commands plus the 'F' sub-commands NOW. Press <Enter> to make 'Current' " \
"commands plus the 'G' sub-commands NOW. Press <Enter> to make 'Current' " \
""
@ -505,7 +519,7 @@ typedef struct win {
//atic void stop (int dont_care_sig);
//atic void std_err (const char *str);
//atic void suspend (int dont_care_sig);
/*------ Misc Color/Highlighting support -------------------------------*/
/*------ Misc Color/Display support ------------------------------------*/
//atic void capsmk (WIN_t *q);
//atic void msg_save (const char *fmts, ...);
//atic void show_msg (const char *str);
@ -521,6 +535,7 @@ typedef struct win {
/*------ Library Alternatives ------------------------------------------*/
//atic void *alloc_c (unsigned numb);
//atic void *alloc_r (void *q, unsigned numb);
//atic CPUS_t *refreshcpus (CPUS_t *cpus);
//atic proc_t **refreshprocs (proc_t **tbl);
/*------ Startup routines ----------------------------------------------*/
//atic void before (char *me);
@ -545,8 +560,8 @@ typedef struct win {
//atic void windows_stage1 (void);
//atic void windows_stage2 (void);
/*------ Per-Frame Display support -------------------------------------*/
//atic void cpudo (FILE *fp, const char *fmt, CPUS_t *cpu, const char *pfx);
//atic void frame_states (proc_t **p, int show);
//atic void cpudo (CPUS_t *cpu, const char *pfx);
//atic void frame_states (proc_t **ppt, int show);
//atic void frame_storage (void);
//atic void mkcol (WIN_t *q, PFLG_t idx, int sta, int *pad, char *buf, ...);
//atic void show_a_task (WIN_t *q, proc_t *task);