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 //////////////////////////////////////////////////////////////// .\" Setup ////////////////////////////////////////////////////////////////
\# ** Comment out '.nr' or set to 0 to eliminate WIDTH fiddlin' ! \# ** 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]) . ll +(\n[half_xtra] + \n[half_xtra])
. .
@ -79,7 +79,7 @@
\# - hey, these two ain't too shabby, either \# - hey, these two ain't too shabby, either
. ds Us this\ \*(Me . ds Us this\ \*(Me
. ds US \fBthis\fR\ \*(Me . ds US \fBthis\fR\ \*(Me
\# - other misc strings for consistent usage \# - other misc strings for consistent usage/emphasis
. ds F \fIOff\fR . ds F \fIOff\fR
. ds O \fIOn\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 \*(ME \-\fBhv\fR | \-\fBbcisS\fR \-\fBd\fI delay\fR \-\fBn\fI
iterations\fR \-\fBp\fI pid\fR [,\fI pid\fR ...] 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 .SS Expanded Configurable Display Support
.New .New
In an SMP environment, you can choose between a\fB summary\fR display or In an SMP environment, screen height may be insufficient to simultaneously
you may show\fB each \*(Pu\fR separately. accommodate all \*(Pu states plus a meaningful \*(TD.
This could be an important provision for a massively-parallel machine, where So with \*(Us, you can alternate between a\fB summary\fR display or one
screen height is insufficient to simultaneously accommodate all \*(Pu showing\fB each \*(Pu\fR separately.
states plus a meaningful \*(TD. No longer must this choice be irrevocably made at startup.
.New .New
There are new fields. There are new fields and with \*(Us,\fB any\fR field is selectable for sorting.
With \*(Us,\fB any\fR field is selectable for sorting and your sorted Plus, your sorted column can be\fB instantly reversed\fR with just a
column can be\fB instantly reversed\fR. single keystroke.
.New .New
You may optionally apply 2 distinct types of\fB highlighting\fR to 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) * 'c' - Command line \fBOff\fR (name, not cmdline)
* 'i' - Idle tasks On\ \ (show all tasks) * 'i' - Idle tasks On\ \ (show all tasks)
'R' - Reverse sort On\ \ (sort pids high-to-low) '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) 'x' - Column hilite \fBOff\fR\ (no, sort field)
'y' - Row hilite On\ \ (yes, running tasks) 'y' - Row hilite On\ \ (yes, running tasks)
'z' - color/mono \fBOff\fR\ (no, colors) 'z' - color/mono \fBOff\fR\ (no, colors)
@ -392,8 +392,8 @@ Remaining Table of Contents
b. SELECTING and ORDERING Columns b. SELECTING and ORDERING Columns
3.\fB INTERACTIVE Commands\fR 3.\fB INTERACTIVE Commands\fR
a. GLOBAL Commands a. GLOBAL Commands
b. SUMMARY Display Commands b. SUMMARY Area Commands
c. TASK Display Commands c. TASK Area Commands
d. COLOR Mapping d. COLOR Mapping
4.\fB ALTERNATE\-DISPLAY Mode\fR 4.\fB ALTERNATE\-DISPLAY Mode\fR
a. WINDOWS Overview a. WINDOWS Overview
@ -410,8 +410,10 @@ Remaining Table of Contents
b. Bouncing Windows b. Bouncing Windows
c. The Big Bird Window c. The Big Bird Window
7.\fB NOTES and Rantings\fR 7.\fB NOTES and Rantings\fR
a. The top BINARY a. The top Binary
b. The top SOURCES b. Comparing Performance
c. Cost of Stuff
d. The top Sources
-*- Rant On, and on -*- -*- Rant On, and on -*-
lastly,\fB the usual\fR... lastly,\fB the usual\fR...
8. BUGS, 9. HISTORY Former top, 10. AUTHOR, 11. SEE ALSO 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 Starts \*(Me in 'Batch mode', which could be useful for sending output
from \*(Me to other programs or to a file. from \*(Me to other programs or to a file.
In this mode, \*(Me will\fB not\fR accept input and runs until the iterations 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. Output is plain text suitable for any dumb terminal.
.br .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. to test the nifty\fI delayed message handling\fR \*(Us employs during bootstrap.
Oh, you wanna' see? Oh, you wanna' see?
Test thus:\ \ top\fB d.1s\fR Test thus:\ \ \*(Me\fB d.1s\fR
.Rjb 3 .Rjb 3
( see, NO '-' & 'sp' but ) ( see, NO '-' & 'sp' but )
( you\fB can't change delay\fR ) ( you\fB can't change delay\fR )
@ -524,14 +526,14 @@ Test thus:\ \ top\fB d.1s\fR
.Rje .Rje
Don't bother trying that precise command line with your old top 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. he-sees-poorly-but-won't-wear-glasses.
.TP 5 .TP 5
\-\fBS\fR :\fB Cumulative time mode\fR toggle \-\fBS\fR :\fB Cumulative time mode\fR toggle
Starts \*(Me with the last remembered '\fBS\fR' state reversed. Starts \*(Me with the last remembered '\fBS\fR' state reversed.
When 'Cumulative mode' is \*O, each process is listed with the \*(Pu 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. \*(XC 'S' \*(CI for additional information regarding this mode.
.TP 5 .TP 5
@ -547,11 +549,12 @@ Show library version and the usage prompt, then quit.
.\" ---------------------------------------------------------------------- .\" ----------------------------------------------------------------------
Listed below are \*(Us's\fB available\fR fields. Listed below are \*(Us's\fB available\fR fields.
They are always associated with the letter shown, regardless of the position 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 Any field is selectable as the\fB sort field\fR, and you control whether they
are sorted high-to-low or low-to-high. 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 .TP 3
a:\fB PID\fR \*(EM Process Id\fR a:\fB PID\fR \*(EM Process Id\fR
@ -564,7 +567,8 @@ The process ID of a task's parent.
.TP 3 .TP 3
c:\fB PGID\fR \*(EM Process Group Id\fR 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. There is one process group per pipeline.
.TP 3 .TP 3
@ -723,12 +727,11 @@ to provide for the potential growth of program names into command lines!
.TP 3 .TP 3
y:\fB WCHAN\fR \*(EM Sleeping in Function y:\fB WCHAN\fR \*(EM Sleeping in Function
Depending on the availability of\fI /boot/System.map\fR (the kernel link map) Depending on the availability of the kernel link map ('System.map'),
or\fI /boot/psdatabase\fR, this field will show the \fB name\fR or this field will show the \fB name\fR or the\fB address\fR of the kernel
the\fB address\fR of the kernel function in which the task is function in which the task is currently sleeping.
currently sleeping. Running tasks will display a dash ('-') in this column (but only if you're
Running tasks will display a dash '-' in this column (but only if you're using using the best, the most proper libproc).
the best, the most proper libproc).
.in +4 .in +4
\*(NT By displaying this field, \*(Me's own working set will be increased by \*(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 z:\fB Flags\fR \*(EM Task Flags
This column represents the task's current scheduling flags which \*(Us This column represents the task's current scheduling flags which \*(Us
expresses in hexadecimal notation, but with zeros suppressed. 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' Less formal documentation can also be found on the 'Fields select'
and 'Order fields' screens \*(EM the next topic. and 'Order fields' screens \*(EM the next topic.
@ -933,7 +936,7 @@ These commands always impact just the \*(CW/field group.
.TP 7 .TP 7
\ \ \'\fBl\fR\' :\fIToggle_Load_Average/Uptime\fR \*(EM On/Off \ \ \'\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. operating in \*(FM or the \*(CW name when operating in \*(AM.
If you murder-this-line, \*(Me will prosecute you. 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 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, field and \*(Us hopes that you always run with 'column highlight' \*F,
due to the cost in path-length. due to the cost in path-length.
However, if you forget which field \*(Me is sorting it can serve as a However, if you forget which field \*(Me is sorting this command can serve
quick visual reminder. as a quick visual reminder.
.TP 7 .TP 7
\ \ \'\fBy\fR\' :\fIRow_Highlight_toggle\fR \ \ \'\fBy\fR\' :\fIRow_Highlight_toggle\fR
Please use this toggle \*(EM highlight running tasks! Please use this toggle \*(EM highlight running tasks!
It's an important insight into your system's health and there is no extra It's an important insight into your system's health and it was largely this
run-time cost associated with its use. provision that was responsible for your-brand-new-top.
Besides, it is this provision alone that is largely responsible for You'll make the program author a happy guy.
your-brand-new-top and you'll make the program author a happy guy.
.TP 7 .TP 7
\ \ \'\fBz\fR\' :\fIColor/Monochrome_toggle\fR \ \ \'\fBz\fR\' :\fIColor/Monochrome_toggle\fR
@ -1030,7 +1032,7 @@ For additional information on these \*(CIs
.TP 7 .TP 7
\ \ \'\fBS\fR\' :\fICumulative_Time_Mode_toggle\fR \ \ \'\fBS\fR\' :\fICumulative_Time_Mode_toggle\fR
When 'Cumulative mode' is \*O, each process is listed with the \*(Pu 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 When \*F, programs that fork into many separate tasks will appear
less demanding. less demanding.
@ -1079,7 +1081,7 @@ over the size of each currently visible \*(TD.
.br .br
.in +2 .in +2
Before using any of these sort provisions, \*(Me suggests that you 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. That will help ensure that the actual sort environment matches your intent.
The following \*(CIs will\fB only\fR be honored when the 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, However, depending upon your screen width and the order of your fields,
this sort field may not be displayable. 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. when running \*(Me with column highlighting turned \*F.
.TP 7 .TP 7
@ -1133,6 +1135,12 @@ Try this:\ \ using 'R' you can\fI alternate\fR between high-to-low
and low-to-high sorts. and low-to-high sorts.
Lose no sleep over 'reverse' and 'normal', ok? 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 .SS 3d. COLOR Mapping
.Scr .Scr
@ -1156,7 +1164,7 @@ in\fB all\fR four windows before returning to the \*(Me display.
.Img .Img
+\fB--------------------------------------\fR+ +\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 : Target Window ----->\fR |current window:\fB 1:Def\fR :
-*- | : -*- | :
a\fB Sample Screen\fR with | color - 04:25:44 up 8 days, 50 min,: 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: (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: |\fI___836_____1_\fBlogin_--_root\fI_____0:00.00\fR:
3:Mem has altered |\fI3__PID_%MEM__VIRT_SWAP__RES_CODE_DATA_\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 : some std defaults: | 4634\fB 12.3\fR 15620 0 15m 860 14m :
'y' turned Off | 7337\fB 11.3\fR 14396 92\fB 13m\fR 36 13m : 'y' turned Off | 7337\fB 11.3\fR 14396 92 13m 36 13m :
'x' turned On | 923\fB 10.6\fR 30544 16m\fB 13m\fR 1120 12m : '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\fB 9176\fR 12 9164 : (when 3\fB WAS\fR current) | 991\fB 7.2\fR 9492 316 9176 12 9164 :
|\fI__7329__\fB7.0\fI__9036__140_\fB8896\fR___36_8860_\fR: |\fI__7329__\fB7.0\fI__9036__140_8896___36_8860_\fR:
Huh? 4:Usr has some |\fI4_UID_USER_____GROUP____TTY________PID\fR: Huh? 4:Usr has some |\fI4_UID_USER_____GROUP____TTY________PID\fR:
\fBblank rows\fR! ? ? ? ? | \fB 0 jtwm root pts/2 5561\fR: \fBblank rows\fR! ? ? ? ? | \fB 0 jtwm root pts/2 5561\fR:
Aha, the 'i' command | \fB 0 root root ? 5560\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. For this experiment, under x-windows open an xterm and maximize it.
Then do the following: 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 nice -n -10 top -d.09
. keep sorted column highlighting \*F . keep sorted column highlighting \*F to minimize
to minimize path length path length
. turn \*O reverse row highlighting for emphasis . turn \*O reverse row highlighting for emphasis
. try various sort columns (TIME/MEM work well), . try various sort columns (TIME/MEM work well),
and normal or reverse sorts to bring and normal or reverse sorts to bring the most
the most active processes into view active processes into view
What you'll see is a\fB very busy Linux\fR doing what he's always done 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). 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 .SH 7. NOTES and Rantings
.\" ---------------------------------------------------------------------- .\" ----------------------------------------------------------------------
.\" ...................................................................... .\" ......................................................................
.SS 7a. The top BINARY .SS 7a. The top Binary
To whom it may/\fBshould\fR concern: \*(Us, even with its vastly expanded .PP
capabilities, is essentially the same size as the old top. 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 Were it not for extensive help text and additional sort callbacks, it would
be smaller. be smaller.
.Rjb 6 .Rjb 6
Throw source carelessly at objectives, it\fI will\fR 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? example: (num_\fBpages\fR - an_\fBaddress\fR)/1024 == duh?
kicker: \fBdocument\fR result as broken, due to\fB elf\fR! kicker: \fBdocument\fR result as broken, due to\fB elf\fR!
\fB----------------------------------------------\fR \fB----------------------------------------------\fR
I know you're out there, are you getting this? I know you're out there, are you getting this?
.Rje .Rje
.PP
Now, as for all those new capabilities like colors and windows and 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? highlighting, you'd expect \*(Us to be the "mother of all pigs"
.br compared to old \*(Me \*(EM right?
Hmmm, let's see...
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 .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) Once the terminfo strings are built (\fIat\fR and\fI during\fR a user's behest)
they are SAVED with each window's stuff. they are SAVED with each window's stuff.
And while there will be a few extra tty escape sequences transmitted because And while there will be extra tty escape sequences transmitted because
of colors, it makes NO difference which 'char *' is actually used. of colors, it makes no difference which 'char *' is actually used.
.TP 3 .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. 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 row\fR highlighting, there is only the cost of those extra tty
For\fI column\fR highlighting, there is a fairly\fB significant cost\fR for escape sequences (same as for colors).
column transition management incurred on every \*(TD row. 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. Sooo... hey USER \*(EM \fIdo NOT highlight COLUMNS\fR.
You shouldn't need a constant visual reminder of your chosen sort field. 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. quick visual reminder.
.TP 3 .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. If more than 1 window, almost certainly NOT Nada so blame it on reality.
Colors are not an issue, but those sort fields are. 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?) 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 .TP 3
.B top.h\fR: .B top.h\fR
Unlike his predecessor, \*(Us has a proper header file. Unlike his predecessor, \*(Us has a proper header file.
It contains ONLY declarations, NOT definitions. It contains ONLY declarations, NOT definitions.
And there are several conditionals present to help with further customizations And there are several conditionals present to help with further customizations
@ -1715,9 +1775,8 @@ and experimentation.
All are \*F by default. All are \*F by default.
.TP 3 .TP 3
.B top.c\fR: .B top.c\fR
Hopefully proves that source code needn't be a disorganized, Hopefully proves that source code needn't be a disorganized, misaligned MESS.
misaligned MESS.
And, WHO says a source listing shouldn't occasionally make you SMILE? 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 Why, \*(Me.c even does a darn good job of following the suggestions in a
document hardly anybody seems to observe. 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. aforementioned document need NEVER speak of their EVILS again.
.Jbu .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. 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 Some of those C-thingies are VERY sensitive \*(EM they don't like being TOUCHED
by any other syntax element! by any other syntax element!
@ -1890,8 +1949,8 @@ With invaluable help from:
.\" ---------------------------------------------------------------------- .\" ----------------------------------------------------------------------
.SH 11. SEE ALSO .SH 11. SEE ALSO
.\" ---------------------------------------------------------------------- .\" ----------------------------------------------------------------------
.BR ps (1),
.BR free (1), .BR free (1),
.BR ps (1),
.BR uptime (1), .BR uptime (1),
.BR vmstat (8), .BR vmstat (8),
.BR w (1). .BR w (1).

383
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 */ Loops = -1, /* number of iterations, -1 loops forever */
Secure_mode = 0; /* set if some functionality restricted */ Secure_mode = 0; /* set if some functionality restricted */
/* Miscellaneous global stuff ####################################*/
/* Some cap's stuff to reduce runtime calls -- /* Some cap's stuff to reduce runtime calls --
to accomodate 'Batch' mode, they begin life as empty strings */ to accomodate 'Batch' mode, they begin life as empty strings */
static char Cap_bold [CAPBUFSIZ] = "", static char Cap_bold [CAPBUFSIZ] = "",
@ -139,10 +137,6 @@ static char Cap_bold [CAPBUFSIZ] = "",
Caps_off [CAPBUFSIZ] = ""; Caps_off [CAPBUFSIZ] = "";
static int Cap_can_goto = 0; 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 ---------------*/ /* Special Section: multiple windows/field groups ---------------*/
@ -165,10 +159,14 @@ static int Frame_maxtask, /* last known number of active tasks */
/*###### Sort callbacks ################################################*/ /*###### Sort callbacks ################################################*/
/* These happen to be coded in the same order as the enum 'pflag' /*
values -- but the only positionally dependent sort callback is * These happen to be coded in the same order as the enum 'pflag'
the 'pid' guy who MAY be invoked under return SORT_eq * values -- but the only positionally dependent sort callback is
(2 of these routines serve double duty -- 2 columns each) */ * 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_PID, pid)
_SC_NUM1(P_PPD, ppid) _SC_NUM1(P_PPD, ppid)
_SC_NUM1(P_PGD, pgrp) _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) 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; 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) if (sp)
while ((p = strpbrk(str, ws))) *p = ' '; while ((p = strpbrk(str, ws))) *p = ' ';
else 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) 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:" "\nbye_bye's Summary report:"
"\n\tProgram" "\n\tProgram"
"\n\t Page_size = %d, Cpu_tot = %d" "\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 sizeof(CPUS_t) = %u, sizeof(HIST_t) = %u (%u HIST_t's/Page)"
"\n\t CPU_FMTS_JUST1 = %s" "\n\t CPU_FMTS_JUST1 = %s"
" \t CPU_FMTS_MULTI = %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 * 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'), /* 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 it probably means caller wants to retain cursor position on this final
line -- ok then, we'll just do our 'fit-to-screen' thingy... */ 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); fflush(stdout);
} }
@ -709,7 +708,7 @@ static char *scale_num (unsigned num, const unsigned width, const unsigned type)
return buf; return buf;
} }
/* well shoot, this outta' fit... */ /* 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 */ /* try successively higher units until it fits */
t = tics / Hertz; t = tics / Hertz;
sprintf(buf, "%u:%02u.%02u" /* minutes:seconds.hundredths */ sprintf(buf, "%u:%02u.%02u" /* mins:secs.hundredths */
, t/60, t%60, (unsigned)((tics*100)/Hertz)%100); , t / 60, t % 60, (unsigned)((tics * 100) / Hertz) % 100);
if (strlen(buf) <= width) if (strlen(buf) <= width)
return buf; 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) if (strlen(buf) <= width)
return buf; return buf;
@ -751,7 +750,7 @@ static char *scale_tics (TICS_t tics, const unsigned width)
return buf; return buf;
}; };
/* well shoot, this outta' fit... */ /* 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 * Handle our own memory stuff without the risk of leaving the
* user's terminal in an ugly state should things go sour. */ * 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) static void *alloc_c (unsigned numb)
{ {
@ -787,7 +785,7 @@ static void *alloc_c (unsigned numb)
if (!numb) ++numb; if (!numb) ++numb;
if (!(p = calloc(1, numb))) if (!(p = calloc(1, numb)))
std_err(fmtmk(alloc_msg, numb)); std_err("failed memory allocate");
return p; return p;
} }
@ -798,13 +796,59 @@ static void *alloc_r (void *q, unsigned numb)
if (!numb) ++numb; if (!numb) ++numb;
if (!(p = realloc(q, numb))) if (!(p = realloc(q, numb)))
std_err(fmtmk(alloc_msg, numb)); std_err("failed memory allocate");
return p; 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 * 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> */ * for our specific needs and to avoid the use of <stdarg.h> */
static proc_t **refreshprocs (proc_t **tbl) static proc_t **refreshprocs (proc_t **tbl)
@ -933,7 +977,7 @@ static void configs_read (void)
fgets(fbuf, sizeof(fbuf), fp); /* ignore shameless advertisement */ fgets(fbuf, sizeof(fbuf), fp); /* ignore shameless advertisement */
if (5 != (fscanf(fp, "Id:%c, " if (5 != (fscanf(fp, "Id:%c, "
"Mode_altscr=%d, Mode_irixps=%d, Delay_time=%f, Curwin=%d\n" "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)); std_err(fmtmk(err_rc, RCfile));
/* you saw that, right? (fscanf stickin' it to 'i') */ /* 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! 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 we might not have been so lucky if our WIN_t was laid out
differently and statically allocated or stack based!! */ 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)) || strlen(DEF_FIELDS) != strlen(Winstk[i]->fieldscur))
std_err(fmtmk(err_rc, RCfile)); std_err(fmtmk(err_rc, RCfile));
fscanf(fp, "\twinflags=%d, sortindx=%d, maxtasks=%d \n" 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 . no deprecated/illegal use of 'breakargv:' with goto
. bunched args are actually handled properly and none are ignored . bunched args are actually handled properly and none are ignored
. we tolerate NO whitespace and NO switches -- maybe too tolerant? */ . 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; float tmp_delay = MAXFLOAT;
char *p; char *p;
@ -1017,7 +1062,7 @@ static void parse_args (char **args)
break; break;
case 'h': case 'H': case 'h': case 'H':
case 'v': case 'V': 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)); , procps_version, Myname, usage));
case 'i': case 'i':
TOGw(Curwin, Show_IDLEPS); TOGw(Curwin, Show_IDLEPS);
@ -1083,14 +1128,14 @@ static void whack_terminal (void)
/* first the curses part... */ /* first the curses part... */
#ifdef PRETENDNOCAP #ifdef PRETENDNOCAP
setupterm((char *)"dumb", STDOUT_FILENO, NULL); setupterm("dumb", STDOUT_FILENO, NULL);
#else #else
setupterm(NULL, STDOUT_FILENO, NULL); setupterm(NULL, STDOUT_FILENO, NULL);
#endif #endif
/* now our part... */ /* now our part... */
if (!Batch) { if (!Batch) {
if (-1 == tcgetattr(STDIN_FILENO, &Savedtty)) if (-1 == tcgetattr(STDIN_FILENO, &Savedtty))
std_err("tcgetattr() failed"); std_err("failed tty get");
newtty = Savedtty; newtty = Savedtty;
newtty.c_lflag &= ~ICANON; newtty.c_lflag &= ~ICANON;
newtty.c_lflag &= ~ECHO; newtty.c_lflag &= ~ECHO;
@ -1100,7 +1145,7 @@ static void whack_terminal (void)
Ttychanged = 1; Ttychanged = 1;
if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &newtty)) { if (-1 == tcsetattr(STDIN_FILENO, TCSAFLUSH, &newtty)) {
putp(Cap_clr_scr); 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); tcgetattr(STDIN_FILENO, &Rawtty);
putp(Cap_clr_scr); putp(Cap_clr_scr);
@ -1208,7 +1253,7 @@ static void display_fields (const char *fields, const char *xtra)
static void fields_reorder (void) static void fields_reorder (void)
{ {
static const char *prompt = 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; char c, *p;
int i; int i;
@ -1241,10 +1286,10 @@ static void fields_sort (void)
"Select sort field via field letter, type any other key to return"; "Select sort field via field letter, type any other key to return";
char phoney[PFLAGSSIZ]; char phoney[PFLAGSSIZ];
char c, *p; char c, *p;
int i; int i, x;
strcpy(phoney, NUL_FIELDS); strcpy(phoney, NUL_FIELDS);
i = Curwin->sortindx; x = i = Curwin->sortindx;
printf("%s%s", Cap_clr_scr, Cap_curs_huge); printf("%s%s", Cap_clr_scr, Cap_curs_huge);
do { do {
p = phoney + i; p = phoney + i;
@ -1256,10 +1301,11 @@ static void fields_sort (void)
i = toupper(c) - 'A'; i = toupper(c) - 'A';
if (i < 0 || i >= MAXTBL(Fieldstab)) break; if (i < 0 || i >= MAXTBL(Fieldstab)) break;
*p = tolower(*p); *p = tolower(*p);
if ((p = strchr(Curwin->fieldscur, i + 'a'))) x = i;
*p = i + 'A';
Curwin->sortindx = i;
} while (1); } while (1);
if ((p = strchr(Curwin->fieldscur, x + 'a')))
*p = x + 'A';
Curwin->sortindx = x;
putp(Cap_curs_norm); putp(Cap_curs_norm);
} }
@ -1302,7 +1348,7 @@ static void win_colsheads (WIN_t *q)
int i, needpsdb = 0; int i, needpsdb = 0;
/* build window's procflags array and establish a tentative maxpflgs */ /* 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])) if (isupper(q->fieldscur[i]))
q->procflags[q->maxpflgs++] = q->fieldscur[i] - 'A'; 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 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 */ encountered, but that's ok because it won't be displayed anyway */
q->maxpflgs = i; q->maxpflgs = i;
q->procflags[i] = '\0';
q->maxcmdln = Screen_cols q->maxcmdln = Screen_cols
- (strlen(q->columnhdr) - strlen(Fieldstab[P_CMD].head)) - 1; - (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. */ * Just warn the user when a command can't be honored. */
static int win_warn (void) static int win_warn (void)
{ {
show_msg(fmtmk("\aCommand disabled, activate window #%d with '-' or '_'" show_msg(fmtmk("\aCommand disabled, activate %s with '-' or '_'"
, Curwin->winnum)); , Curwin->grpname));
/* we gotta' return false 'cause we're somewhat well known within /* we gotta' return false 'cause we're somewhat well known within
macro society, by way of that sassy little tertiary operator... */ macro society, by way of that sassy little tertiary operator... */
return 0; return 0;
@ -1514,27 +1559,20 @@ static void wins_reflag (int what, int flg)
TOGw(w, flg); TOGw(w, flg);
break; break;
case Flags_SET: /* Ummmm, i can't find anybody */ case Flags_SET: /* Ummmm, i can't find anybody */
SETw(w, flg); /* who uses Flags_set -- maybe */ SETw(w, flg); /* who uses Flags_set ... */
break; /* ol' gcc will opt it away... */ break;
case Flags_OFF: case Flags_OFF:
OFFw(w, flg); OFFw(w, flg);
break; break;
} }
w = w->next; /* a flag with special significance -- user wants to rebalance
} while (w != Curwin); display so we gotta' 'off' one number then force on two flags... */
if (EQUWINS_cwo == flg) {
/* 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?) */
if (EQUWINS_cwo == flg) {
w = Curwin;
do {
w->maxtasks = 0; w->maxtasks = 0;
SETw(w, Show_IDLEPS | VISIBLE_tsk); SETw(w, Show_IDLEPS | VISIBLE_tsk);
w = w->next; }
} while (w != Curwin); 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 -- * Set up the raw/incomplete field group windows --
* they'll be finished off after startup completes. * they'll be finished off after startup completes.
* (and very likely that will override most/all of our efforts) * [ and very likely that will override most/all of our efforts ]
* ( --- life-is-NOT-fair --- ) */ * [ --- life-is-NOT-fair --- ] */
static void windows_stage1 (void) static void windows_stage1 (void)
{ {
static struct { static struct {
@ -1629,7 +1667,7 @@ static void windows_stage2 (void)
if (Batch) { if (Batch) {
Mode_altscr = 0; Mode_altscr = 0;
OFFw(Curwin, Show_COLORS); OFFw(Curwin, Show_COLORS | Show_HICOLS | Show_HIROWS);
} }
wins_resize(0); wins_resize(0);
for (i = 0; i < GROUPSMAX; i++) { 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 * 2 - modest smp boxes with room for each cpu's percentages
* 3 - massive smp guys leaving little or no room for process * 3 - massive smp guys leaving little or no room for process
* display and thus requiring the cpu summary toggle */ * 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, /* we'll trim to zero if we get negative time ticks,
which has happened with some SMP kernels (pre-2.4?) */ which has happened with some SMP kernels (pre-2.4?) */
#define TRIMz(x) ((tz = (STIC_t)x) < 0 ? 0 : tz) #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; STIC_t u_frme, s_frme, n_frme, i_frme, tot_frme, tz;
#ifdef PRETEND4CPUS u_frme = TRIMz(cpu->u - cpu->u_sav);
rewind(fp); s_frme = TRIMz(cpu->s - cpu->s_sav);
fmt = CPU_FMTS_JUST1; n_frme = TRIMz(cpu->n - cpu->n_sav);
#endif i_frme = TRIMz(cpu->i - cpu->i_sav);
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);
tot_frme = u_frme + s_frme + n_frme + i_frme; tot_frme = u_frme + s_frme + n_frme + i_frme;
if (1 > tot_frme) tot_frme = 1; 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; Msg_row += 1;
/* remember for next time around */ /* remember for next time around */
cpu->u = u_tics; cpu->u_sav = cpu->u;
cpu->s = s_tics; cpu->s_sav = cpu->s;
cpu->n = n_tics; cpu->n_sav = cpu->n;
cpu->i = i_tics; cpu->i_sav = cpu->i;
#undef TRIMz #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 percent cpu usage for each task (pcpu)
* Calc the cpu(s) percent in each state (user, system, nice, idle) * Calc the cpu(s) percent in each state (user, system, nice, idle)
* AND establish the total number of tasks for this frame! */ * 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 HIST_t *hist_sav = NULL;
static unsigned hist_siz; static unsigned hist_siz;
static CPUS_t *smpcpu;
HIST_t *hist_new; HIST_t *hist_new;
unsigned total, running, sleeping, stopped, zombie; unsigned total, running, sleeping, stopped, zombie;
float etime; float etime;
@ -1710,19 +1739,15 @@ static void frame_states (proc_t **p, int show)
Frame_maxtask = 0; Frame_maxtask = 0;
hist_siz = (Page_size / sizeof(HIST_t)); hist_siz = (Page_size / sizeof(HIST_t));
hist_sav = alloc_c(hist_siz); 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); hist_new = alloc_c(hist_siz);
total = running = sleeping = stopped = zombie = 0; total = running = sleeping = stopped = zombie = 0;
etime = time_elapsed(); etime = time_elapsed();
/* make a pass through the data to get stats */ /* make a pass through the data to get stats */
while (-1 != p[total]->pid) { /* calculations //// */ while (-1 != ppt[total]->pid) { /* calculations //// */
TICS_t tics; TICS_t tics;
proc_t *this = p[total]; proc_t *this = ppt[total];
switch (this->state) { switch (this->state) {
case 'S': case 'S':
@ -1770,33 +1795,29 @@ static void frame_states (proc_t **p, int show)
if (show) { /* display ///////// */ if (show) { /* display ///////// */
FILE *fp; static CPUS_t *smpcpu = NULL;
/* display Task states */ /* display Task states */
show_special(fmtmk(STATES_line1 show_special(fmtmk(STATES_line1
, total, running, sleeping, stopped, zombie)); , total, running, sleeping, stopped, zombie));
Msg_row += 1; Msg_row += 1;
if (!(fp = fopen("/proc/stat", "r"))) /* refresh our /proc/stat data... */
std_err(fmtmk("Failed /proc/stat open: %s", strerror(errno))); smpcpu = refreshcpus(smpcpu);
if (CHKw(Curwin, View_CPUSUM)) { if (CHKw(Curwin, View_CPUSUM)) {
/* retrieve and display just the 1st /proc/stat line */ /* display just the 1st /proc/stat line */
cpudo(fp, CPU_FMTS_JUST1, &smpcpu[Cpu_tot], "Cpu(s) state:"); cpudo(&smpcpu[Cpu_tot], "Cpu(s) state:");
} else { } else {
char tmp[SMLBUFSIZ]; char tmp[SMLBUFSIZ];
/* display each cpu's states separately */
/* 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 */
for (i = 0; i < Cpu_tot; i++) { for (i = 0; i < Cpu_tot; i++) {
sprintf(tmp, "%-6scpu%-2d:" /* [ cpu states as ] */ sprintf(tmp, "%-6scpu%-2d:" /* [ cpu states as ] */
, i ? " " : "State" /* 'State cpu0 : ... ' */ , i ? " " : "State" /* 'State cpu0 : ... ' */
, Mode_irixps ? i : Cpu_map[i]); /* ' cpu1 : ... ' */ , Mode_irixps ? i : Cpu_map[i]); /* ' cpu1 : ... ' */
cpudo(fp, CPU_FMTS_MULTI, &smpcpu[i], tmp); cpudo(&smpcpu[i], tmp);
} }
} }
fclose(fp);
} /* end: if 'show' */ } /* end: if 'show' */
/* save this frame's information */ /* save this frame's information */
@ -1819,7 +1840,7 @@ static void frame_storage (void)
unsigned long long **memarray; unsigned long long **memarray;
if (!(memarray = meminfo())) if (!(memarray = meminfo()))
std_err("Failed /proc/meminfo read"); std_err("failed /proc/meminfo read");
if (CHKw(Curwin, View_MEMORY)) { if (CHKw(Curwin, View_MEMORY)) {
show_special(fmtmk(MEMORY_line1 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_list va;
va_start(va, buf); 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) { if (!CHKw(q, Show_HICOLS) || q->sortindx != idx) {
vsprintf(buf, Fieldstab[idx].fmts, va); vsprintf(buf, Fieldstab[idx].fmts, va);
} else { } 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. */ * Display information for a single task row. */
static void show_a_task (WIN_t *q, proc_t *task) 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]; char rbuf[ROWBUFSIZ];
int i, x, pad; int j, x, pad;
/* since win_colsheads adds a number to the window's column header, /* since win_colsheads adds a number to the window's column header,
we must begin a row with that in mind... */ we must begin a row with that in mind... */
pad = Mode_altscr; pad = Mode_altscr;
if (pad) strcpy(rbuf, " "); else rbuf[0] = '\0'; 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]; char cbuf[COLBUFSIZ];
PFLG_t f; char a = task->state; /* we'll use local var's so */
unsigned s, w; 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'; cbuf[0] = '\0';
f = q->procflags[i]; switch (i) {
s = Fieldstab[f].scale;
w = Fieldstab[f].width;
switch (f) {
case P_CMD: case P_CMD:
{ char *cmdptr, cmdnam[ROWBUFSIZ]; { char *cmdptr, cmdnam[ROWBUFSIZ];
@ -1912,104 +1942,98 @@ static void show_a_task (WIN_t *q, proc_t *task)
else { else {
cmdnam[0] = '\0'; cmdnam[0] = '\0';
if (task->cmdline) { if (task->cmdline) {
x = 0; j = 0;
do { do {
/* during a kernel build, parts of the make will create /* during a kernel build, parts of the make will create
cmdlines in excess of 3000 bytes but *without* the cmdlines in excess of 3000 bytes but *without* the
intervening nulls -- so we must limit our strcat... */ intervening nulls -- so we must limit our strcat... */
strcat(cmdnam 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 /* whoa, gnome's xscreensaver had a ^I in his cmdline
creating a line wrap when the window was maximized & creating a line wrap when the window was maximized &
the tab came into view -- so whack those suckers... */ the tab came into view -- so whack those suckers... */
strim(1, cmdnam); strim(1, cmdnam);
if (q->maxcmdln < (int)strlen(cmdnam)) break; if (q->maxcmdln < (int)strlen(cmdnam)) break;
} while (task->cmdline[x]); } while (task->cmdline[j]);
} else { } else {
/* if cmdline is absent, consider it a kernel thread and /* if cmdline is absent, consider it a kernel thread and
display it uniquely (we'll need sort_cmd's complicity) */ display it uniquely (need sort callback's complicity) */
strcpy(cmdnam, fmtmk("( %s )", task->cmd)); strcpy(cmdnam, fmtmk(CMDLINE_FMTS, task->cmd));
} }
cmdptr = cmdnam; cmdptr = cmdnam;
} }
mkcol(q, f, task->state, &pad MKCOL(q, i, a, &pad, cbuf, q->maxcmdln, q->maxcmdln, cmdptr);
, cbuf, q->maxcmdln, q->maxcmdln, cmdptr);
} }
break; break;
case P_COD: case P_COD:
mkcol(q, f, task->state, &pad, cbuf MKCOL(q, i, a, &pad, cbuf, scale_num(PAGES_2K(task->trs), w, s));
, scale_num(PAGES_2K(task->trs), w, s));
break; break;
case P_CPN: case P_CPN:
#ifdef UGH_ITS_4_RH #ifdef UGH_ITS_4_RH
mkcol(q, f, task->state, &pad, cbuf, task->lproc); MKCOL(q, i, a, &pad, cbuf, task->lproc);
#else #else
mkcol(q, f, task->state, &pad, cbuf, task->processor); MKCOL(q, i, a, &pad, cbuf, task->processor);
#endif #endif
break; break;
case P_CPU: 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; break;
case P_DAT: case P_DAT:
mkcol(q, f, task->state, &pad, cbuf MKCOL(q, i, a, &pad, cbuf, scale_num(PAGES_2K(task->drs), w, s));
, scale_num(PAGES_2K(task->drs), w, s));
break; break;
case P_DRT: case P_DRT:
mkcol(q, f, task->state, &pad, cbuf MKCOL(q, i, a, &pad, cbuf, scale_num((unsigned)task->dt, w, s));
, scale_num((unsigned)task->dt, w, s));
break; break;
case P_FLG: case P_FLG:
mkcol(q, f, task->state, &pad, cbuf, task->flags); MKCOL(q, i, a, &pad, cbuf, (long)task->flags);
for (x = 0; x < (int)strlen(cbuf); x++) for (j = 0; cbuf[j]; j++)
if ('0' == cbuf[x]) cbuf[x] = '.'; if ('0' == cbuf[j]) cbuf[j] = '.';
break; break;
case P_FLT: case P_FLT:
mkcol(q, f, task->state, &pad, cbuf MKCOL(q, i, a, &pad, cbuf, scale_num(task->maj_flt, w, s));
, scale_num(task->maj_flt, w, s));
break; break;
case P_GRP: case P_GRP:
mkcol(q, f, task->state, &pad, cbuf, task->egroup); MKCOL(q, i, a, &pad, cbuf, task->egroup);
break; break;
case P_MEM: case P_MEM:
mkcol(q, f, task->state, &pad, cbuf
#ifdef UGH_ITS_4_RH #ifdef UGH_ITS_4_RH
MKCOL(q, i, a, &pad, cbuf
, (float)task->resident * 100 / Mem_pages); , (float)task->resident * 100 / Mem_pages);
#else #else
MKCOL(q, i, a, &pad, cbuf
, (float)PAGES_2K(task->resident) * 100 / kb_main_total); , (float)PAGES_2K(task->resident) * 100 / kb_main_total);
#endif #endif
break; break;
case P_NCE: case P_NCE:
mkcol(q, f, task->state, &pad, cbuf, task->nice); MKCOL(q, i, a, &pad, cbuf, (long)task->nice);
break; break;
case P_PGD: case P_PGD:
mkcol(q, f, task->state, &pad, cbuf, task->pgrp); MKCOL(q, i, a, &pad, cbuf, task->pgrp);
break; break;
case P_PID: case P_PID:
mkcol(q, f, task->state, &pad, cbuf, task->pid); MKCOL(q, i, a, &pad, cbuf, task->pid);
break; break;
case P_PPD: case P_PPD:
mkcol(q, f, task->state, &pad, cbuf, task->ppid); MKCOL(q, i, a, &pad, cbuf, task->ppid);
break; break;
case P_PRI: case P_PRI:
mkcol(q, f, task->state, &pad, cbuf, task->priority); MKCOL(q, i, a, &pad, cbuf, (long)task->priority);
break; break;
case P_RES: case P_RES:
mkcol(q, f, task->state, &pad, cbuf MKCOL(q, i, a, &pad, cbuf, scale_num(PAGES_2K(task->resident), w, s));
, scale_num(PAGES_2K(task->resident), w, s));
break; break;
case P_SHR: case P_SHR:
mkcol(q, f, task->state, &pad, cbuf MKCOL(q, i, a, &pad, cbuf, scale_num(PAGES_2K(task->share), w, s));
, scale_num(PAGES_2K(task->share), w, s));
break; break;
case P_STA: case P_STA:
#ifdef USE_LIB_STA3 #ifdef USE_LIB_STA3
mkcol(q, f, task->state, &pad, cbuf, status(task)); MKCOL(q, i, a, &pad, cbuf, status(task));
#else #else
mkcol(q, f, task->state, &pad, cbuf, task->state); MKCOL(q, i, a, &pad, cbuf, task->state);
#endif #endif
break; break;
case P_SWP: 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)); , scale_num(PAGES_2K(task->size - task->resident), w, s));
break; break;
case P_TME: case P_TME:
@ -2019,40 +2043,38 @@ static void show_a_task (WIN_t *q, proc_t *task)
t = task->utime + task->stime; t = task->utime + task->stime;
if (CHKw(q, Show_CTIMES)) if (CHKw(q, Show_CTIMES))
t += (task->cutime + task->cstime); 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; break;
case P_TTY: case P_TTY:
{ char tmp[TNYBUFSIZ]; { char tmp[TNYBUFSIZ];
dev_to_tty(tmp, (int)w, task->tty, task->pid, ABBREV_DEV); 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; break;
case P_UID: case P_UID:
mkcol(q, f, task->state, &pad, cbuf, task->euid); MKCOL(q, i, a, &pad, cbuf, task->euid);
break; break;
case P_USR: case P_USR:
mkcol(q, f, task->state, &pad, cbuf, task->euser); MKCOL(q, i, a, &pad, cbuf, task->euser);
break; break;
case P_VRT: case P_VRT:
mkcol(q, f, task->state, &pad, cbuf MKCOL(q, i, a, &pad, cbuf, scale_num(PAGES_2K(task->size), w, s));
, scale_num(PAGES_2K(task->size), w, s));
break; break;
case P_WCH: case P_WCH:
if (No_ksyms) if (No_ksyms) {
#ifdef CASEUP_HEXES #ifdef CASEUP_HEXES
mkcol(q, f, task->state, &pad, cbuf MKCOL(q, i, a, &pad, cbuf, fmtmk("x%08lX", (long)task->wchan));
, fmtmk("x%08lX", (long)task->wchan));
#else #else
mkcol(q, f, task->state, &pad, cbuf MKCOL(q, i, a, &pad, cbuf, fmtmk("x%08lx", (long)task->wchan));
, fmtmk("x%08lx", (long)task->wchan));
#endif #endif
else } else {
mkcol(q, f, task->state, &pad, cbuf, wchan(task->wchan)); MKCOL(q, i, a, &pad, cbuf, wchan(task->wchan));
}
break; break;
} /* end: switch 'flg' */ } /* end: switch 'procflag' */
strcat(rbuf, cbuf); strcat(rbuf, cbuf);
} /* end: for 'maxpflgs' */ } /* end: for 'maxpflgs' */
@ -2067,6 +2089,7 @@ static void show_a_task (WIN_t *q, proc_t *task)
, Caps_off , Caps_off
, Cap_clr_eol); , 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) static void do_key (unsigned c)
{ {
/* standardized 'secure mode' errors */ /* 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 #ifdef WARN_NOT_SMP
/* standardized 'smp' errors */ /* standardized 'smp' errors */
const char *err_smp = "\aSorry, only 1 cpu detected"; static const char *err_smp = "\aSorry, only 1 cpu detected";
#endif #endif
switch (c) { switch (c) {
@ -2122,7 +2145,7 @@ static void do_key (unsigned c)
case 'd': case 'd':
case 's': case 's':
if (Secure_mode) if (Secure_mode)
show_msg(fmtmk(err_secure, "change delay")); show_msg(err_secure);
else { else {
float tmp = float tmp =
get_float(fmtmk("Change delay from %.1f to", Delay_time)); 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! */ /* this string is well above ISO C89's minimum requirements! */
show_special(fmtmk(KEYS_help show_special(fmtmk(KEYS_help
, procps_version , procps_version
, Curwin->winname , Curwin->grpname
, CHKw(Curwin, Show_CTIMES) ? "On" : "Off" , CHKw(Curwin, Show_CTIMES) ? "On" : "Off"
, Delay_time , Delay_time
, Secure_mode ? "On" : "Off" , Secure_mode ? "On" : "Off"
@ -2208,7 +2231,7 @@ static void do_key (unsigned c)
case 'k': case 'k':
if (Secure_mode) { if (Secure_mode) {
show_msg(fmtmk(err_secure, "kill")); show_msg(err_secure);
} else { } else {
int sig, pid = get_int("PID to kill"); int sig, pid = get_int("PID to kill");
@ -2263,7 +2286,7 @@ static void do_key (unsigned c)
case 'r': case 'r':
if (Secure_mode) if (Secure_mode)
show_msg(fmtmk(err_secure, "renice")); show_msg(err_secure);
else { else {
int pid, val; int pid, val;
@ -2356,32 +2379,24 @@ static void do_key (unsigned c)
wins_colors(); wins_colors();
break; break;
case '-': /* 'Dash' lower case ----------------------- */ case '-':
if (Mode_altscr) if (Mode_altscr)
TOGw(Curwin, VISIBLE_tsk); TOGw(Curwin, VISIBLE_tsk);
break; break;
case '_': /* 'Dash' upper case ----------------------- */ case '_':
if (Mode_altscr) /* switcharoo, all viz & inviz ............ */ if (Mode_altscr)
wins_reflag(Flags_TOG, VISIBLE_tsk); wins_reflag(Flags_TOG, VISIBLE_tsk);
break; break;
case '=': /* 'Equals' lower case --------------------- */ 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! */
Curwin->maxtasks = 0; Curwin->maxtasks = 0;
SETw(Curwin, Show_IDLEPS | VISIBLE_tsk); 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; Monpidsidx = 0;
break; break;
case '+': /* 'Equals' upper case --------------------- */ case '+':
if (Mode_altscr) /* equalize ALL task wins (& make viz) .... */ if (Mode_altscr)
SETw(Curwin, EQUWINS_cwo); SETw(Curwin, EQUWINS_cwo);
break; break;
@ -2403,8 +2418,8 @@ static void do_key (unsigned c)
} }
break; break;
case '\n': /* just ignore these */ case '\n': /* just ignore these, they'll have the effect */
case ' ': case ' ': /* of refreshing display after waking us up ! */
break; break;
default: default:
@ -2449,7 +2464,7 @@ static proc_t **do_summary (void)
/* /*
** Display Tasks and Cpu(s) states and also calc 'pcpu', ** 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); p_table = refreshprocs(p_table);
frame_states(p_table, CHKw(Curwin, View_STATES)); frame_states(p_table, CHKw(Curwin, View_STATES));

75
top.h
View File

@ -27,6 +27,7 @@
//#define CASEUP_HEXES /* show any hex values in upper case */ //#define CASEUP_HEXES /* show any hex values in upper case */
//#define CASEUP_SCALE /* show scaled time/num suffix upper case */ //#define CASEUP_SCALE /* show scaled time/num suffix upper case */
//#define CASEUP_SUMMK /* show memory summary kilobytes with 'K' */ //#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 QUIT_NORMALQ /* use 'q' to quit, not new default 'Q' */
//#define SORT_SUPRESS /* *attempt* to reduce qsort overhead */ //#define SORT_SUPRESS /* *attempt* to reduce qsort overhead */
//#define TICS_64_BITS /* accommodate Linux 2.5.xx 64-bit jiffies */ //#define TICS_64_BITS /* accommodate Linux 2.5.xx 64-bit jiffies */
@ -64,6 +65,7 @@
#define SMLBUFSIZ 256 #define SMLBUFSIZ 256
#define MEDBUFSIZ 512 #define MEDBUFSIZ 512
#define OURPATHSZ 1024 #define OURPATHSZ 1024
#define STATBUFSZ 1024
#define BIGBUFSIZ 2048 #define BIGBUFSIZ 2048
#define RCFBUFSIZ SMLBUFSIZ #define RCFBUFSIZ SMLBUFSIZ
#define USRNAMSIZ GETBUFSIZ #define USRNAMSIZ GETBUFSIZ
@ -105,7 +107,7 @@
if ( ((*P)->n1 - (*P)->n2) > ((*Q)->n1 - (*Q)->n2) ) return SORT_gt; \ if ( ((*P)->n1 - (*P)->n2) > ((*Q)->n1 - (*Q)->n2) ) return SORT_gt; \
return SORT_eq; } return SORT_eq; }
#define _SC_STRZ(f,s) \ #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_lt; \
if ( 0 < strcmp((*P)->s, (*Q)->s) ) return SORT_gt; \ if ( 0 < strcmp((*P)->s, (*Q)->s) ) return SORT_gt; \
return SORT_eq; } return SORT_eq; }
@ -159,15 +161,18 @@ typedef struct {
TICS_t tics; TICS_t tics;
} HIST_t; } 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 calculations. It exists primarily for SMP support but serves
all environments. There will always Cpu_tot + 1 allocated all environments. */
-- see frame_states for details. */
typedef struct { typedef struct {
TICS_t u, /* ticks count as represented in /proc/stat */ TICS_t u, /* ticks count as represented in /proc/stat */
n, /* (not in the order of our display) */ n, /* (not in the order of our display) */
s, s,
i; i;
TICS_t u_sav, /* tics count in the order of our display */
s_sav,
n_sav,
i_sav;
} CPUS_t; } CPUS_t;
/* The scaling 'type' used with scale_num() -- this is how /* 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 Show_IDLEPS 0x0020 /* 'i' - show idle processes (all tasks) */
#define Qsrt_NORMAL 0x0010 /* 'R' - reversed column sort (high to low) */ #define Qsrt_NORMAL 0x0010 /* 'R' - reversed column sort (high to low) */
/* these flag(s) have no command as such - they're for internal use */ /* 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 NEWFRAM_cwo 0x0004 /* new frame (if anyone cares) - in Curwin */
#define EQUWINS_cwo 0x0002 /* rebalance tasks next frame (off 'i'/ 'n') */ #define EQUWINS_cwo 0x0002 /* rebalance tasks next frame (off 'i'/ 'n') */
/* ...set in Curwin, but impacts all windows */ /* ...set in Curwin, but impacts all windows */
@ -285,7 +290,7 @@ typedef struct win {
/* An rcfile 'footprint' used to invalidate existing local rcfile /* An rcfile 'footprint' used to invalidate existing local rcfile
and the global rcfile path + name */ and the global rcfile path + name */
#define RCF_FILEID 'i' #define RCF_FILEID 'j'
#define SYS_RCFILE "/etc/toprc" #define SYS_RCFILE "/etc/toprc"
/* The default fields displayed and their order, /* The default fields displayed and their order,
@ -299,13 +304,22 @@ typedef struct win {
#define NUL_FIELDS "abcdefghijklmnopqrstuvwxyz" #define NUL_FIELDS "abcdefghijklmnopqrstuvwxyz"
/* These are the possible fscanf formats used in /proc/stat /* 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 #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 #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 #endif
/* Summary Lines specially formatted string(s) -- /* Summary Lines specially formatted string(s) --
@ -343,14 +357,14 @@ typedef struct win {
#endif #endif
#define KEYS_help \ #define KEYS_help \
"Help for Interactive Commands\02 - %s\n" \ "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" \ "\n" \
" l,t,m Toggle Summary: '\01l\02' load avg; '\01t\02' task/cpu stats; '\01m\02' mem info\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" \ " 1,I Toggle SMP view: '\0011\02' single/separate states; '\01I\02' Irix/Solaris mode\n" \
" Z\05 Change color mappings\n" \ " Z\05 Change color mappings\n" \
"\n" \ "\n" \
" f,o . Fields change: '\01f\02' fields select; '\01o\02' order fields\n" \ " f,o . Fields/Columns: '\01f\02' add or remove; '\01o\02' change display order\n" \
" F or O . Fields select sort\n" \ " F or O . Select sort field\n" \
" <,> . Move sort field: '\01<\02' next col left; '\01>\02' next col right\n" \ " <,> . Move sort field: '\01<\02' next col left; '\01>\02' next col right\n" \
" R . Toggle normal/reverse sort\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" \ " 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" \ " z,b\05 . Toggle: '\01z\02' color/mono; '\01b\02' bold/reverse (only if 'x' or 'y')\n" \
" u . Show specific user only\n" \ " u . Show specific user only\n" \
" n or # . Set maximum tasks displayed\n" \ " n or # . Set maximum tasks displayed\n" \
" ( commands shown with '.' require a \01visible\02 task display \01window\02 ) \n" \
"\n" \ "\n" \
"%s" \ "%s" \
" W Write configuration file\n" \ " W Write configuration file\n" \
HELP_Qkey "Quit\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" \ "Press '\01h\02' or '\01?\02' for help with \01Windows\02,\n" \
"any other key to continue " \ "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 \ #define KEYS_help_unsecured \
" k,r Manipulate tasks: '\01k\02' kill; '\01r\02' renice\n" \ " k,r Manipulate tasks: '\01k\02' kill; '\01r\02' renice\n" \
" d or s Set update interval\n" \ " d or s Set update interval\n" \
@ -421,11 +435,11 @@ typedef struct win {
" within viewable range is chosen.\n" \ " within viewable range is chosen.\n" \
"\n" \ "\n" \
"Note2:\n" \ "Note2:\n" \
" The WCHAN field will display a name\n" \ " Field sorting uses internal values,\n" \
" if the System.map exists, but it is\n" \ " not those in column display. Thus,\n" \
" always sorted as an address. Thus,\n" \ " the TTY & WCHAN fields will violate\n" \
" alphabetic sequence will not apply.\n" \ " strict ASCII collating sequence.\n" \
" ( shame on you if you choose this )\n" \ " (shame on you if WCHAN is chosen)\n" \
"" ""
/* Colors Help specially formatted string(s) -- /* Colors Help specially formatted string(s) --
@ -459,7 +473,7 @@ typedef struct win {
/* Windows/Field Group Help specially formatted string(s) -- /* Windows/Field Group Help specially formatted string(s) --
see 'show_special' for syntax details + other cautions. */ see 'show_special' for syntax details + other cautions. */
#define WINDOWS_help \ #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" \ "\n" \
". Use multiple \01windows\02, each with separate config opts (color,fields,sort,etc)\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" \ ". 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" \ " . 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" \ " 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" \ ". 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" \ ". 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" \ " 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" \ " 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" \ ". 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" \ " (this also forces the \01current\02 or \01every\02 window to become visible)\n" \
"\n" \ "\n" \
"In '\01A\02' mode, '\01*\04' keys are your \01essential\02 commands. Please try the '\01a\02' and '\01w\02'\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 stop (int dont_care_sig);
//atic void std_err (const char *str); //atic void std_err (const char *str);
//atic void suspend (int dont_care_sig); //atic void suspend (int dont_care_sig);
/*------ Misc Color/Highlighting support -------------------------------*/ /*------ Misc Color/Display support ------------------------------------*/
//atic void capsmk (WIN_t *q); //atic void capsmk (WIN_t *q);
//atic void msg_save (const char *fmts, ...); //atic void msg_save (const char *fmts, ...);
//atic void show_msg (const char *str); //atic void show_msg (const char *str);
@ -521,6 +535,7 @@ typedef struct win {
/*------ Library Alternatives ------------------------------------------*/ /*------ Library Alternatives ------------------------------------------*/
//atic void *alloc_c (unsigned numb); //atic void *alloc_c (unsigned numb);
//atic void *alloc_r (void *q, unsigned numb); //atic void *alloc_r (void *q, unsigned numb);
//atic CPUS_t *refreshcpus (CPUS_t *cpus);
//atic proc_t **refreshprocs (proc_t **tbl); //atic proc_t **refreshprocs (proc_t **tbl);
/*------ Startup routines ----------------------------------------------*/ /*------ Startup routines ----------------------------------------------*/
//atic void before (char *me); //atic void before (char *me);
@ -545,8 +560,8 @@ typedef struct win {
//atic void windows_stage1 (void); //atic void windows_stage1 (void);
//atic void windows_stage2 (void); //atic void windows_stage2 (void);
/*------ Per-Frame Display support -------------------------------------*/ /*------ Per-Frame Display support -------------------------------------*/
//atic void cpudo (FILE *fp, const char *fmt, CPUS_t *cpu, const char *pfx); //atic void cpudo (CPUS_t *cpu, const char *pfx);
//atic void frame_states (proc_t **p, int show); //atic void frame_states (proc_t **ppt, int show);
//atic void frame_storage (void); //atic void frame_storage (void);
//atic void mkcol (WIN_t *q, PFLG_t idx, int sta, int *pad, char *buf, ...); //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); //atic void show_a_task (WIN_t *q, proc_t *task);