Merge branch 'newtop'

This commit is contained in:
Jan Görig 2011-05-25 11:05:04 +02:00
commit c3b7310149
14 changed files with 4502 additions and 4061 deletions

19
.gitignore vendored Normal file
View File

@ -0,0 +1,19 @@
free
kill
pgrep
pkill
pmap
proc/.depend
proc/libproc-3.2.8.so
ps/ps
pwdx
skill
slabtop
snice
sysctl
tload
top
uptime
vmstat
w
watch

View File

@ -1,545 +1,328 @@
Credit for this belongs to:
Jim / James C. Warner, <warnerjc@worldnet.att.net>
----------------------------------
Ok, ok, I yield -- most of what follows has been removed from the manual page
and packaged separately as this README (hey, it was only TEMPORARY insanity).
Of course, that means that now absolutely nobody will ever read it.
This is probably a good thing...
## Table of Contents ---------------------------------------------------##
# the only darn thing that wasn't in the man page
CUSTOMIZING the Sources
# the following carry their original topic numbers
DIFFERENCES / New Features
Interface Etiquette
Expanded Configurable Display Support
Enhanced Field/Column Management
Customization Flexibility
NOTES and Rantings
The top Binary
Comparing Performance
Cost of Stuff
The top Sources
EXAMPLES of Windows
The 'A' Mode Command Toggle
STACKIN' & WHACKIN' Windows
ALL TOGETHER Now, Window(s)
## CUSTOMIZING the Sources ---------------------------------------------##
Listed below are the conditionals available should you wish to recompile
this top. The author's favorite is: PRETEND4CPUS.
That's the #define allowing you to simulate an SMP environment, and
(perhaps) impress your friends. It's currently set to display four
separate CPUs, but could easily be changed.
Caution: do NOT use this provision in an effort to impress someone
who truly possesses such a machine! The fact that all 4
CPUs show the same dynamic results will likely have the
opposite effect.
//#define ATEOJ_REPORT /* report a bunch of stuff, at end-of-job */
//#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 PRETEND2_5_X /* pretend we're linux 2.5.x (for IO-wait) */
//#define PRETEND4CPUS /* pretend we're smp with 4 ticsers (sic) */
//#define PRETENDNOCAP /* use a terminal without essential caps */
//#define SORT_SUPRESS /* *attempt* to reduce qsort overhead */
//#define STDOUT_IOLBF /* disable our own stdout _IOFBF override */
//#define USE_LIB_STA3 /* use lib status (3 ch) vs. proc_t (1 ch) */
//#define WARN_NOT_SMP /* restrict '1' & 'I' commands to true smp */
## 6. DIFFERENCES / New Features ---------------------------------------##
The following summarizes differences between this top and your
former top. It was originally based on procps-2.0.7. However,
except for the separate/summary CPU toggle, all of these differ-
ences also apply through procps-2.0.10.
6a. Interface Etiquette
-*- Input and output are far more carefully implemented in
this top. You won't be subjected to 4 - 5 'Unknown command'
messages should you press the wrong key.
-*- You need suffer a confirmation message only when the results
of a command are not obvious by their effects on the display.
-*- The Help screen will no longer overflow, even when running
with a 24 row xterm (vt100).
-*- The fields selection/ordering screens do not carelessly
destroy important information through unintended line wraps.
-*- Should you narrow a xterm window to less than 80 columns
while this top is running, you will not be left with an
utterly worthless, embarrassing display.
6b. Expanded Configurable Display Support
-*- In an SMP environment, you can choose between a summary dis-
play or you may show each cpu separately. No longer must
this choice be irrevocably made at startup.
-*- There are new fields and with this top, any field is
selectable for sorting. Plus, your sorted column can be
instantly reversed with just a single keystroke.
-*- You may optionally apply 2 distinct types of highlighting to
running tasks and/or sorted columns. With this top, you'll
be able to instantly spot running tasks and always know the
current sort field.
-*- While you could continue to use the more familiar (and
boring) monochrome display, you might want to try this top's
new color display. You can even create your own unique col-
ors used in summaries, messages, headings and tasks, each of
which can be made persistent until you choose to change them.
-*- Up to four separate windows can be displayed simultaneously,
giving you four separate ways to sort and view the tasks cur-
rently cluttering up your system. You could have one view by
pids, another by cpu usage, yet another showing memory con-
sumption. You get the idea...
-*- Each window comes with pre-configured (but user configurable)
fields and you can size each window individually.
-*- Virtually every one of this top's options (summaries, fields,
colors, sorted column, etc.) is separately configurable for
each of those four windows.
Heck, you can even change a window's name, if you don't care
for top's choices. Your changes will be reflected not only
when you're in what top calls alternate-display mode but also
on his special new 'Windows' help screen.
-*- And, [ ** Drum-Roll + Ta-Da ** ] with just one keystroke you
can quickly switch between full-screen and multiple window
modes! Or, with a different keystroke, toggle a single win-
dow Off for now, then On again later!!
6c. Enhanced Field/Column Management
-*- Many Field/Column names have been changed to make them more
intuitive, more self-descriptive. And with this top you
won't be fooled with field choices that are "not yet imple-
mented".
-*- Task memory statistics are more meaningful and more accurate.
-*- You'll finally have complete display integrity regardless of
field selections, their order or screen width. And that
means the command column no longer need be kept as the right-
most field, lest your screen turn to <bleep> when all the
following columns get misaligned.
6d. Customization Flexibility
-*- You have complete program naming freedom with no internal
ties to a specific personal configuration file. Symbolic
links could be used to establish different configuration
files reflecting the different personalities of your cus-
tomized "tops", under whatever aliases you've used.
Thus, you could have an alias for running top in 'Batch
mode', another for when you work from the Linux console and
maybe a third used with X-Windows. All of that, yet still
just a single binary image!
-*- All of your configuration choices can be preserved in a per-
sonal configuration file, including any changes made on a
per-window basis. Thus, once you personalize things they
remain personalized until you decide to change them again.
This top has been completely cured of:
i-cant-remember-so-please-do-that-all-over-again
( and again, and again ... )
The bottom line is this: if you save your configuration
before quitting top, upon restart the display will appear
exactly as you left it. And that means you no longer have to
keep top running until-the-end-of-time (ok, a long time
anyway), lest your customizations go bye-bye.
## 7. NOTES and Rantings -----------------------------------------------##
7a. The top Binary
To whom it may (should) concern: this top, 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.
Throw source carelessly at objectives, it will
produce equally careless machine instructions.
example: (num_pages - an_address)/1024 == duh?
kicker: document result as broken, due to elf!
----------------------------------------------
I know you're out there, are you getting this?
Now, as for all those new capabilities like colors and windows and
highlighting, you'd expect this top to be the "mother of all pigs"
compared to old top -- right?
Yea, with this top expect following piglets:
. A smaller virtual image and resident footprint
. Slightly fewer major page faults
. A large reduction in minor page faults for SMP
. The same or better response time
. The same or even less CPU costs
Ideally any comparison of the old and new top should be against
the same libproc format (32-bit or 64-bit tics) and run in a true
or simulated SMP environment (producing separate CPU stats). This
latter requirement will coax old top into handling his own
'/proc/stat' access -- something this top always does, but with
less cost.
7b. Comparing Performance
Even with equivalent libraries and '/proc/stat' access, it's dif-
ficult to accurately compare tops using their own displays.
Results for these cpu-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 tim-
ing of process snapshots. For slightly 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 this top at a performance disadvantage, the
higher scheduling priority and staggered timing will periodically
yield a somewhat truer picture. You could even reverse those
roles and get similar results.
The most consistent 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, this top's cpu 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...
7c. Cost of Stuff
Colors Cost -- Nada (almost).
Once the terminfo strings are built (at and during a user's
behest) they are SAVED with each window's stuff. And while
there will be extra tty escape sequences transmitted because of
colors, it makes no difference which 'char *' is actually used.
Highlighting Cost -- Nada (maybe), or blame it on Rio.
On second thought, let's blame it on the user.
For row highlighting, there is only the cost of those extra tty
escape sequences (same as for colors). For column highlight-
ing, there is a fairly significant cost associated with column
transition management combined with even more tty output.
These increased costs are incurred on every task display row.
Sooo... hey USER -- do NOT highlight COLUMNS. You shouldn't
need a constant visual reminder of your chosen sort field.
However, if you forget which field top is sorting it can serve
as a quick visual reminder.
Windows Cost -- 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.
If we could trust the user to always select the same 'c' state,
'S' state and sort field (hey, why ya got multiple windows then
user, huh?) AND if we can trust someone to recompile top with a
#define enabled, then we could achieve 'Nada'.
Ok, not likely, so we're gonna' be doing multiple sorts. BUT,
it may not be as bad as it sounds. Those sorts involve point-
ers only. And, that's as good as it gets ! (right Mr. N?)
7d. The top Sources
top.h
Unlike his predecessor, this top has a proper header file. It
contains ONLY declarations, NOT definitions. And there are
several conditionals present to help with further customiza-
tions and experimentation. All are Off by default.
top.c
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, top.c even does a darn good
job of following the suggestions in a document hardly anybody
seems to observe.
the Linus Torvalds CodingStyle guidelines ...
-*- -*- -*- on indentation + etc. -*- -*- -*-
well almost all, except for those stinkin'...
I suppose even Linus Torvalds is entitled to err now and again.
How so you say? Tabs, me' bucko, stinkin' tabs! That, plus the
simplistic position regarding indentation espoused in that other-
wise excellent document.
-*- Rant On, and on -*-
Let's compare two approaches to the tab/indentation issue with a
small code sample using tabs then spaces. This snippet happens to
be the key to top's use of dynamic colors on many static screens,
while also ensuring screen width isn't exceeded so as to avoid
line wraps. We'll view just the first 40 columns, assuming one
wishes to occasionally provide comments to the right of actual
code (you do, don't you?).
Then YOU decide which approach makes the most SENSE!
Stinkin' Tabs versus Spaces: the Linus way
Hey, where'd my +----+----1----+----2----+----3----+----4+
many code lines | while (*sub_beg) { :
up-and-gone-to? | switch (*sub_end:
| case 0: :
Gosh, wonder if | \ Tabs Induced / :
Linus expects a | case 1: :
fellow to stick | + WASTE-Lands! + case 5: :
his comments on | :
the left side?! | + Not a Living + :
| :
Ever see source | + line-of-code + :
with not enough | :
whitespace; and | / To Be Found! \ :
this is better? | default::
| :
Oh lookie here, \ } :
there's just a hint of REAL code! ----> if (0 >= room) b:
/ } /* end: while 'subtrin:
+----------------------------------------+
Spaces versus Stinkin' Tabs: the other way
+----+----1----+----2----+----3----+----4+
Wow, now this is | while (*sub_beg) { :
Visible hackin'! | switch (*sub_end) { :
| case 0: :
Hmmm, wonder how | *(sub_end + 1) = '\0'; :
many programmers | case 1: case 2: case 3: case:
read those lines | case 5: case 6: case 7: case:
from the LEFT to | cap = Curwin->captab[(int:
the RIGHT? This | *sub_end = '\0'; :
"innovation" may | PUTP("%s%.*s%s", cap, roo:
possibly benefit | room -= (sub_end - sub_be:
those particular | sub_beg = ++sub_end; :
kinds of people, | break; :
you agree? Duh! | default: :
| ++sub_end; :
AND, there might | } :
even be room for | if (0 >= room) break; :
unseen comments! | } /* end: while 'subtrings' */ :
+----------------------------------------+
Gosh, I just don't KNOW -- it's such a TOUGH choice...
Oh you Stinkin' Tabs: correspondence, Who-Cares; documentation,
Oh-Alright; even scripts, Well-If-You-Must. But you have NO place
within the code-space of MY C-source listing! So be gone
already!!
In Summation...
- If you want to use tabs to the right of the code, go-for-it.
But PLEASE, not ever in the C-source code-space, thank-you-
kindly. Just use three little ol' spaces (exactly 3, no-more,
no-less) where you WOULD have stuck a stinkin' tab.
We'll get far more READABLE files, much less WAISTED precious
horizontal space, more consistent CURSORS and on, and ON, AND
ON! Plus, without those awful *the-devil's-own-handiwork*, the
aforementioned document need NEVER speak of their EVILS again.
- Lastly, since SPACES (not stinkin' tabs) are SO beneficial,
maybe we should use just a few more of 'em. Some of those C-
thingies are VERY sensitive -- they don't like being TOUCHED
by any other syntax element! Which ones? Why these guys:
braces, reserved words and binary operators
( it's the TRUTH, they told me themselves )
It's so EASY to keep 'em HAPPY! And lo-and-behold, the combi-
nation of <sp>thingy<sp> turns out to be a darn effective bug
repellent, too. So much so, one can actually code while
TOTALLY NUDE yet still avoid them ol' bug-bytes (sic-sic)!
step
down_from
me_punctilious
soap-box_once_again
[1 +5 +5 +5 = huh?]
## 4c. EXAMPLES of Windows ---------------------------------------------##
-*- The 'A' Mode Command Toggle -*-
Here's what you'll see when you first invoke the alternate-display
mode interactive command.
This particular display was produce on a VT100 xterm, with only 24
rows. All four task displays are visible, but they could not be sized
the same. Available lines are parceled out in the fairest way possi-
ble so the last two task displays have an extra line each.
Notice the 'current' window name in the summary area -- it's been
emphasized because the associated task display is visible. Since
1:Def has a task area, the full range of interactive commands would be
at your disposal. But remember, many of those commands will apply
only to window 1:Def.
+--------------------------------------+
1:Def name is bold, |1:Def - 15:46:37 up 16:25, 9 users, :
thus all commands |Tasks: 76 total, 1 running, 75 sle:
will be available. |Cpu(s): 0.7% user, 1.3% system, :
|Mem: 126588k total, 123688k used,:
|Swap: 265032k total, 8232k used,:
|______________________________________:
Tough luck windows |1__PID_USER______PR__NI_%CPU____TIME+_:
#1 & 2 - you lost | 7343 jtwm 16 0 0.9 0:00.59:
one line each -- | 7339 jtwm 9 0 0.0 0:00.02:
guess you'll just |__7337_root_______9___0__0.0___0:01.30:
have to learn how |2__PID__PPID_Command____________TIME+_:
to live with it. | 997 952 kdeinit 17:59.59:
| 1115 952 kdeinit 2:16.47:
|__1803__1116_led_______________1:55.30:
|3__PID_%MEM__VIRT_SWAP__RES_CODE_DATA_:
The #3 & #4 windows | 4634 12.3 15620 0 15m 860 14m :
better not gloat | 7337 11.3 14396 92 13m 36 13m :
over 1 extra line. | 923 10.6 30524 16m 13m 1120 12m :
That user could yet |___991__7.2__9492__316_9176___12_9164_:
sock 'em with the |4_UID_USER_____GROUP____TTY________PID:
'n' command and | 43 xfs xfs ? 806:
take those lines, | 0 ykde users pts/7 5561:
plus others, away! | 0 wgnome users pts/7 5560:
| 0 root root pts/7 5325:
+--------------------------------------+
So, what say we start applying some of those "full range of interac-
tive commands"?
Onward + Downward...
-*- STACKIN' & WHACKIN' Windows -*-
Whoa, hold on mate. Someone has already whacked these windows. See,
there are no task areas for windows 1:Def and 4:Usr. Well, we can at
least retrace their steps...
Here's what was done, after issuing the 'A' command and entering
alternate-display mode.
1) When #1 was the 'current' window, '-' was pressed,
toggling Off the associated task display
( if 'l t m' had been applied to its summary, too )
( then there'll be only a msg line when 'current' )
2) Then the 'w' key was struck to cycle backward,
making 4:Usr the 'current' window
(could have used 'a a a', if one likes to type)
3) Then step #1 was repeated, and bye-bye window #4
4) Finally, window #2 was made the 'current' window
( Q. how many keystrokes were used? )
( A. minimum of 2: 'a a' or 'w w'. )
+--------------------------------------+
No 'l','t','m','1' |2:Top - 15:48:35 up 16:27, 9 users, :
commands have been |Tasks: 75 total, 1 running, 74 sle:
issued here, |Cpu(s): 2.0% user, 0.7% system, :
but... |Mem: 126588k total, 123712k used,:
|Swap: 265032k total, 8232k used,:
|______________________________________:
#2's been changed; |2__PID__PPID_Command____________TIME+_:
user applied a 'c' | 997 952 kdeinit: konsol 18:00.70:
command (when it | 1115 952 kdeinit: konsol 2:16.47:
was current) - now | 1803 1116 led tiptop.HELP 1:55.30:
shows cmd lines vs. | 923 922 X :0 1:09.60:
program names; | 973 1 klaptopdaemon 0:59.63:
still seems to be | 981 952 /usr/bin/artsd 0:48.63:
sorted on TIME+ | 987 1 kdeinit: kdeskt 0:24.34:
though |___991_____1_kdeinit:_kicker___0:04.59:
|3__PID_%MEM__VIRT_SWAP__RES_CODE_DATA_:
This #3 guy appears | 4634 12.3 15620 0 15m 860 14m :
to still be running | 7337 11.3 14396 92 13m 36 13m :
with the supplied | 923 10.6 30544 16m 13m 1120 12m :
defaults, but no | 991 7.2 9492 316 9176 12 9164 :
telling what damage | 7329 7.0 9036 140 8896 36 8860 :
might have been | 1115 6.9 8956 160 8796 36 8760 :
done to it's | 987 6.4 8668 524 8144 20 8124 :
summary info stuff | 1131 6.4 8268 144 8124 36 8088 :
+--------------------------------------+
And that's what brought us to this current state. No, wait. Oh
lordy, will you look at that -- someone has changed the name of win-
dow #2 from 'Job' to 'Top'!
How'd they do that? Well, they just issued the 'g' interactive com-
mand, of course. That command is available whenever alternate-display
mode is active and always impacts just the 'current' window. Gosh,
you can even issue the 'g' command when 'l' has toggled Off the very
summary area line containing the window name!
Almost Done...
-*- ALL TOGETHER Now, Window(s) -*-
Here, the window 1:Def task display has been toggled Off but it
remains the 'current' window. Since there is no task area, many com-
mands will be restricted. However, the commands ('l', 't', 'm', '1')
affecting the summary area, as well as some other global commands
('k', 'Z', etc.), would still be active.
Notice that the Mem and Swap lines are not shown. This means that the
loser (oops, user) has, in fact, issued the 'm' command! Now, if you
were to cycle the 'current' window with the 'a' or 'w' commands, the
task display would remain the same (except possibly growing/shrinking
slightly) but the summary area would change periodically.
The comments to the left of the image provide additional insights into
how things came to be. Note especially the comments for window 4:Usr
-- the one with some empty rows...
1:Def no highlight, +--------------------------------------+
thus disabled cmds: |1:Def - 15:50:32 up 16:29, 9 users, :
b,i,n,u,x,y, etc. |Tasks: 75 total, 2 running, 73 sle:
& m = lost Mem/Swap |Cpu(s): 10.6% user, 0.0% system, :
|______________________________________:
2:Job was very busy: |2__PID__PPID_Command____________TIME+_:
'n' cmd, w/ 7 tasks | 80 1 ( khubd ) 0:00.00:
'c' cmd, cmd line | 6 0 ( kreclaimd ) 0:00.00:
'O' cmd, sort cmd | 9 1 ( mdrecoveryd ) 0:00.00:
'R' cmd, sort bkwd | 11358 1 /bin/bash/ /usr 0:00.00:
'x' cmd, hi column | 1297 1 /sbin/mingetty 0:00.00:
(when 2 WAS current) | 683 1 xinetd -stayali 0:00.00:
|___836_____1_login_--_root_____0:00.00:
3:Mem has altered |3__PID_%MEM__VIRT_SWAP__RES_CODE_DATA_:
some std defaults: | 4634 12.3 15620 0 15m 860 14m :
'y' turned Off | 7337 11.3 14396 92 13m 36 13m :
'x' turned On | 923 10.6 30544 16m 13m 1120 12m :
(when 3 WAS current) | 991 7.2 9492 316 9176 12 9164 :
|__7329__7.0__9036__140_8896___36_8860_:
Huh? 4:Usr has some |4_UID_USER_____GROUP____TTY________PID:
blank rows! ? ? ? ? | 0 jtwm root pts/2 5561:
Aha, the 'i' command | 0 root root ? 5560:
applied (when 4 WAS | :
current); could be | :
reversed with '=', | :
when 4 IS current! +--------------------------------------+
Ok now, how about that 'current' window 1:Def and its unseen tasks?
At any time, you can quickly retrieve lost tasks in a number of ways:
1) Press '-', toggling just the 'current' window
2) Press '_', toggling all visible/invisible windows
( 1:Def is the only window currently not shown )
( afterward, it'll be the only window showing! )
* 3) Press '+', forcing all task displays to become visible
4) Press 'A' to return to full-screen mode,
with only 1:Def tasks shown and without a window name
Now that should be enough ways of getting a task area visible again to
satisfy almost any user, don't ya think?
Note: Use #3 above when you've messed up your screen beyond
redemption. The four task displays will reappear, nice and even.
They will also have retained any customizations you had previously
applied, except for the 'i' (idle tasks) and 'n' (max tasks) com-
mands.
That's It ! Piece of Cake !! Enjoy them there windows !!!
This file summarizes changes to the top program and supporting documentation
introduced on March 31, 2011.
Contents:
DOCUMENT Changes
INTERNAL Improvements
EXTERNAL Improvements
BUGS Previously Fixed and Preserved
BUGS Newly/Nearly Fixed
BUGS/WISH-LISTS That Should Go Bye-bye
BUGS FIXED You Didn't Know You Had
OTHER Changes, Hopefully They Won't Bite You
BENCHMARKS
DOCUMENT Changes =========================================================
. The entire file was cleaned up, standardized and expanded to include:
- a new section "2. SUMMARY Display" added for symmetry with Fields
- nine new fields were added to section "3a. DESCRIPTIONS of Fields"
- a new section "3b. MANAGING Fields" replaced the obsolete section
"2b. SELECTING and ORDERING Columns"
- section "5c. SCROLLING a Window" was added for that new feature
. I don't know when the explanations for CODE and DATA were changed to
show 'virtual' memory, but I think there's a reason their alternate
names contain the word 'resident'. Thus they were changed back to
say 'physical memory'.
. And as I indicated in a previous email, the former string identifier
'ME' was restored as were the 'h' key/command conventions (vs. <h>).
Oops, the 'h' key/command conventions remain restored, but subsequent
testing revealed problems with the .ME string identifier. Thus, it was
changed to .WE (along with the companion .Me/.We id).
. Also previously mentioned, the 'man2html' program translates top.1 to
HTML with near perfect fidelity. I take that to mean there should be
no problems with the top.1 source on most other platforms.
To further improve translation to HTML, several .Bd and .Ed macros
were added to preserve literal (fixed width) spacing.
INTERNAL Improvements ====================================================
. The old restriction of 26 fields has been lifted. With this new-top
100+ fields are now possible. It currently supports up to 55, of
which 35 are in use. Adding a new field is almost too easy.
. Task row construction has been considerably improved -- both from
a programming perspective and a performance perspective.
. The column highlighting costs for sort field visibility were
virtually eliminated.
An optional define (USE_X_COLHDR) can be enabled to completely
eliminate any costs associated with the 'x' command toggle.
. The management of the HST_t structures, used for %cpu calculations,
was optimized with a hashing scheme. Thus the need for a qsort then
a binary search in each frame was completely eliminated.
An optional define can restore the former qsort/bsearch approach but
with an internal inlined binary search function offering substantially
better performance than the old top.
. This far more capable new-top executable is no larger than old top.
. The above combine to produce substantially improved performance
whose details are documented below under BENCHMARKS.
EXTERNAL Improvements ====================================================
. Field management has been completely redesigned. It's now embodied
on a single screen where display-ability, position and sort selection
can be handled in one place -- for all windows at one time!
This function is dependent on cursor motion keys and should a device
not have the customary arrow keys, alternatives are provided and
documented under "Operation" near the beginning of the man page.
. The following new fields have been added:
Group Id
Minor Page Faults
Number of Threads
Process Group Id
Real User Id
Saved User Id
Saved User Name
Session Id
Tty Process Group Id
. Scrolling keys now allow one to move the view of any window vertically
or horizontally to reveal any desired task or column. Previously, only
some tasks were viewable even with reversible, selectable sort columns.
Each of the four windows is capable of maintaining its own scrolled
coordinates and an optional toggle ('C') displays a message aiding
navigation within the available tasks and displayable fields.
. User interactive line oriented input now provides for true line
editing supported by these new keys:
Left/Right arrow keys, Delete key, Backspace and
Home/End keys (likely limited to xterm, not terminal)
. User filtering via the -u | -U interactive commands is now window
based which means that different windows could be used to filter
different users.
. Signal handling has been normalized and is now consistent regardless
of the particular top screen a user may have been using.
. The 'i' toggle now shows any task that has used *some* cpu since the
last screen update. It's no longer limited to just running tasks.
. The summary area 'task states' line now reflects either 'Threads'
or 'Tasks' depending on the -H toggle.
BUGS Previously Fixed and Preserved ======================================
( but not necessarily literally)
. 228822, suspending top leaves xterm in slightly messed-up state
. 256376, segfaults, if the xterm is to small
. 320289, segv on sigwinch
. 351065, wrong highlight 1st column (escape characters displayed)
. 358724, accepts extra numeric args
. 378695, seg fault if "/proc" is not mounted
. 426782, UID field is too narrow
. 458986, should check xterm for EOF/EIO
. 459890, Irix mode should use %#4.1f when threads shown
BUGS Newly/Nearly Fixed ==================================================
. 225542, 'Unknown command' message blocks further commands
The message is now displayed using usleep for 1.25 seconds, instead
of the former full 2 seconds. And while it still blocks further
commands, the delay is much more tolerable.
Can we consider this bug 'nearly' fixed?
. 410292, interface error when using backspace
Full line editing was added but could be disabled via a #define.
And via that define, even under basic termios support, the backspace
problem was cured.
. 567509, top idle command ('i') not working for threaded programs
Since the 'i' command now reflects tasks that have used *some* cpu,
and is no longer dependent on an 'R' state, I *believe/hope* this
bug has been swatted.
BUGS/WISH-LISTS That Should Go Bye-bye ===================================
. 340751, wish for hostname to benefit multiple top sessions
Craig's suggestion regarding symlinks is the perfect solution.
How dare Craig say that the solution was "not ideal" !
. 586497, wish for graceful degradation on small screen sizes
This objective could be accomplished by setting up 2 symlinks for
top, personalizing them for the 2 tiny phone displays, then writing
the respective configuration files.
I shudder at the programming effort suggested by Paul. And when it
was done you'd find everybody else would have different criteria.
BUGS FIXED You Didn't Know You Had =======================================
. Without amplifying the dirty details, the long standing occasionally
reported display corruption, and an unreported source of performance
degradation, has been eliminated. The cure is in the elimination of
the Pseudo_cols variable and the improved PUFF macro.
. Line oriented input was not sensitive to screen width. Thus a user
could hold down any key and ultimately line wrap, overwriting the
columns header and the entire screen. New top prevents this.
. User filtering (-u|-U) via a user ID (not name) now validates that
number. The old-top just made sure it was numeric, then blindly
displayed no matching users (i.e. an empty window).
. The threads toggle ('H') is no longer window based but more properly
applies to all windows. The previous implementation produced the
following aberration if multiple windows were being shown:
. -H would be acknowledged and applied to all visible windows
. keying 'a' or 'w' would silently turn it off
. then keying -H would turn it back on, but the user expected off
. If you hit ^Z on any help or fields screen to suspend old-top, after
issuing 'fg' you would then be left with a seemingly hung application
inviting ^C. In truth, one could recover with the space bar, but that
was far from intuitive.
. The old-top consistently writes 1 extra byte for each task row or 1
byte too few for columns headers, depending on your perspective.
The new top writes the same number of bytes for each.
. By failing to clear to eol, old top left the display in a terrible
state after exiting a 'fields' screen when only a few columns were
being displayed.
. The old-top used a zero value for the L_NONE library flag which could
cause repeated rebuilding of columns headers with each frame. In truth,
this was not likely to happen in real life since only two fields actually
used that flag. However, if it did happen, performance could be degraded
by 800%.
OTHER Changes, Hopefully They Won't Bite You =============================
. The undocumented TOPRC environment variable is no longer supported.
Any similar need can be met through a symlink alias.
. The use of environment variables to override terminal size is now
off by default but could be enabled through '#define TTYGETENVYES'.
. The global 'bold enable' toggle is active by default and thus agrees
with the documentation. It's been wrong ever since Al's wholesale
'cosmetic' changes in procps-3.2.2.
. Task defaults now show bold (not reverse) and row highlighting.
This agrees with what was always stated in the documentation.
. The 'H' toggle (thread mode) is not persistent. Persistence can be
achieved with a simple shell script employing the -H switch.
. Then 'g' and 'G' commands were reversed to reflect their likely use.
BENCHMARKS ===============================================================
Tested as root with nice -10 and using only common fields
( on a pretty old, slow laptop under Debian Lenny )
but rcfiles specified identical sort fields and identical
settings for the 'B', 'b', 'x' and 'y' toggles (even though
the defaults are not necessarily identical).
In every case new-top outperforms old-top, but I've shown %
improvements for only the most significant. Those cases mostly
involve colors with both row & column highlighting. I suggested
above that the highlighting cost was virtually eliminated in
new-top, and these tests bare that out.
Note the much smaller differences for new-top between the 24x80
window results and full screen (but don't mix apples_terminal
with oranges_xterm). This is a reflection of the simplification
of task row construction, also mentioned above.
It's always been the case that any top in an xterm outperforms
that top under the terminal application, even when the xterm
provides additional rows and columns. It's true below with
Gnome and it was true nine years ago under KDE.
----------------------------------------------------------
The following comparisons were run with:
100 tasks & 160 threads
-d0 -n5000
new-top old-top
xterm 24x80
a 1 win, lflgs_none 11.2 secs 51.8 secs + 462.6%
1 win, default 61.0 secs 66.8 secs
1 win, colors w/ x+y 61.3 secs 83.0 secs + 135.4%
1 win, thread mode 88.3 secs 94.2 secs
b 1 win, every field on 99.7 secs 106.0 secs
1 win, cmdline 71.2 secs 76.6 secs
4 wins, defaults 101.3 secs 107.2 secs
4 wins, colors w/ x+y 101.5 secs 122.8 secs + 121.0%
xterm, full screen (53x170)
a 1 win, lflgs_none 15.9 secs 54.2 secs + 340.9%
1 win, default 70.0 secs 73.2 secs
1 win, colors w/ x+y 69.4 secs 131.3 secs + 189.2%
1 win, thread mode 97.6 secs 102.6 secs
c 1 win, every field on 122.1 secs 128.1 secs
1 win, cmdline 80.8 secs 83.7 secs
4 wins, defaults 111.4 secs 115.8 secs
4 wins, colors w/ x+y 112.0 secs 172.9 secs + 154.4%
terminal 24x80
a 1 win, lflgs_none 8.9 secs 58.6 secs + 658.4%
1 win, default 70.1 secs 80.3 secs
1 win, colors w/ x+y 70.6 secs 157.3 secs + 222.8%
1 win, thread mode 104.7 secs 120.5 secs
b 1 win, every field on 111.2 secs 134.5 secs
1 win, cmdline 83.8 secs 94.5 secs
4 wins, defaults 125.6 secs 146.7 secs
4 wins, colors w/ x+y 125.6 secs 206.9 secs + 176.7%
terminal, full screen (39x125)
a 1 win, lflgs_none 9.1 secs 60.6 secs + 665.9%
1 win, default 74.3 secs 88.0 secs
1 win, colors w/ x+y 73.9 secs 314.5 secs + 425.6%
1 win, thread mode 113.0 secs 140.9 secs
b 1 win, every field on 117.7 secs 154.9 secs
1 win, cmdline 87.4 secs 107.2 secs
4 wins, defaults 139.1 secs 166.7 secs
4 wins, colors w/ x+y 157.3 secs 423.2 secs + 269.0%
----------------------------------------------------------
The following comarisons were run with:
300 tasks & 360 threads
-d0 -n3000
new-top old-top
xterm, full screen (53x170)
a 1 win, lflgs_none 14.3 secs 79.0 secs + 552.4%
1 win, default 101.1 secs 104.5 secs
1 win, colors w/ x+y 101.3 secs 140.0 secs + 138.2%
1 win, thread mode 120.1 secs 123.1 secs
c 1 win, every field on 179.8 secs 185.6 secs
1 win, cmdline 124.9 secs 132.8 secs
4 wins, defaults 174.8 secs 179.2 secs
4 wins, colors w/ x+y 175.0 secs 215.2 secs + 123.0%
terminal, full screen (39x125)
a 1 win, lflgs_none 12.3 secs 98.5 secs + 800.8%
1 win, default 117.4 secs 134.0 secs
1 win, colors w/ x+y 111.6 secs 296.1 secs + 265.3%
1 win, thread mode 141.3 secs 155.3 secs
b 1 win, every field on 197.7 secs 204.8 secs
1 win, cmdline 143.9 secs 157.3 secs
4 wins, defaults 204.0 secs 226.2 secs
4 wins, colors w/ x+y 216.9 secs 434.5 secs + 200.3%
. . . . . . . . . . . . . . . . . . . . . . . . . . . . .
notes:
a these results represent the library flags L_NONE zero value and
thus the hidden cost of rebuilding column headers w/ every frame
b while every common field was turned on, not all fields could be
displayed due to limited screen width
c only in a full screen xterm window could all common fields
actually be displayed

View File

@ -50,13 +50,6 @@ static int escape_str_utf8(char *restrict dst, const char *restrict src, int buf
my_cells++;
my_bytes++;
} else if (len==1) {
/* non-multibyte */
*(dst++) = isprint(*src) ? *src : '?';
src++;
my_cells++;
my_bytes++;
} else if (!iswprint(wc)) {
/* multibyte - no printable */
*(dst++) = '?';
@ -98,7 +91,7 @@ static int escape_str_utf8(char *restrict dst, const char *restrict src, int buf
}
//fprintf(stdout, "cells: %d\n", my_cells);
}
*(dst++) = '\0';
*dst = '\0';
// fprintf(stderr, "maxcells: %d, my_cells; %d\n", *maxcells, my_cells);
@ -114,14 +107,14 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m
int my_cells = 0;
int my_bytes = 0;
const char codes[] =
"Z-------------------------------"
"********************************"
"********************************"
"*******************************-"
"--------------------------------"
"********************************"
"********************************"
"********************************";
"Z..............................."
"||||||||||||||||||||||||||||||||"
"||||||||||||||||||||||||||||||||"
"|||||||||||||||||||||||||||||||."
"????????????????????????????????"
"????????????????????????????????"
"????????????????????????????????"
"????????????????????????????????";
#if (__GNU_LIBRARY__ >= 6)
static int utf_init=0;
@ -131,9 +124,10 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m
char *enc = nl_langinfo(CODESET);
utf_init = enc && strcasecmp(enc, "UTF-8")==0 ? 1 : -1;
}
if (utf_init==1)
if (utf_init==1 && MB_CUR_MAX>1) {
/* UTF8 locales */
return escape_str_utf8(dst, src, bufsize, maxcells);
}
#endif
if(bufsize > *maxcells+1) bufsize=*maxcells+1; // FIXME: assumes 8-bit locale
@ -143,12 +137,12 @@ int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *m
break;
c = (unsigned char) *(src++);
if(!c) break;
if(codes[c]=='-') c='?';
if(codes[c]!='|') c=codes[c];
my_cells++;
my_bytes++;
*(dst++) = c;
}
*(dst++) = '\0';
*dst = '\0';
*maxcells -= my_cells;
return my_bytes; // bytes of text, excluding the NUL
@ -214,3 +208,16 @@ int escape_command(char *restrict const outbuf, const proc_t *restrict const pp,
outbuf[end] = '\0';
return end; // bytes, not including the NUL
}
/////////////////////////////////////////////////
// copy an already 'escaped' string,
// using the traditional escape.h calling conventions
int escaped_copy(char *restrict dst, const char *restrict src, int bufsize, int *maxroom){
int n;
if (bufsize > *maxroom+1) bufsize = *maxroom+1;
n = snprintf(dst, bufsize, "%s", src);
if (n >= bufsize) n = bufsize-1;
*maxroom -= n;
return n;
}

View File

@ -17,6 +17,7 @@ EXTERN_C_BEGIN
extern int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t n, int *cells);
extern int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *maxcells);
extern int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int *cells, unsigned flags);
extern int escaped_copy(char *restrict dst, const char *restrict src, int bufsize, int *maxroom);
EXTERN_C_END
#endif

View File

@ -6,7 +6,7 @@ global:
__cyg_profile_func_enter; __cyg_profile_func_exit; main;
readproc; readtask; readproctab; readproctab2; look_up_our_self; escape_command;
escape_str; escape_strlist;
escape_str; escape_strlist; escaped_copy; read_cmdline;
openproc; closeproc;
tty_to_dev; dev_to_tty; open_psdb_message; open_psdb; lookup_wchan;
display_version; procps_version; linux_version_code;

View File

@ -12,6 +12,7 @@
#include "version.h"
#include "readproc.h"
#include "alloc.h"
#include "escape.h"
#include "pwcache.h"
#include "devname.h"
#include "procps.h"
@ -365,6 +366,19 @@ LEAVE(0x220);
}
///////////////////////////////////////////////////////////////////////
#ifdef OOMEM_ENABLE
static void oomscore2proc(const char* S, proc_t *restrict P)
{
sscanf(S, "%d", &P->oom_score);
}
static void oomadj2proc(const char* S, proc_t *restrict P)
{
sscanf(S, "%d", &P->oom_adj);
}
#endif
///////////////////////////////////////////////////////////////////////
// Reads /proc/*/stat files, being careful not to trip over processes with
// names like ":-) 1 2 3 4 5 6".
@ -514,13 +528,15 @@ static char** file2strvec(const char* directory, const char* what) {
return ret;
}
// warning: interface may change
int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
// this is the former under utilized 'read_cmdline', which has been
// generalized in support of these new libproc flags:
// PROC_EDITCGRPCVT, PROC_EDITCMDLCVT
static int read_unvectored(char *restrict const dst, unsigned sz, unsigned pid, const char *what, char sep) {
char name[32];
int fd;
unsigned n = 0;
dst[0] = '\0';
snprintf(name, sizeof name, "/proc/%u/cmdline", pid);
snprintf(name, sizeof name, "/proc/%u/%s", pid, what);
fd = open(name, O_RDONLY);
if(fd==-1) return 0;
for(;;){
@ -530,23 +546,86 @@ int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
break;
}
n += r;
if(n==sz) break; // filled the buffer
if(n==sz) { // filled the buffer
--n; // make room for '\0'
break;
}
if(r==0) break; // EOF
}
close(fd);
if(n){
int i;
if(n==sz) n--;
dst[n] = '\0';
i=n;
while(i--){
int c = dst[i];
if(c<' ' || c>'~') dst[i]=' ';
}
int i=n;
while(i--)
if(dst[i]=='\n' || dst[i]=='\0') dst[i]=sep;
}
dst[n] = '\0';
return n;
}
static char** vectorize_this_str (const char* src) {
#define pSZ (sizeof(char*))
char *cpy, **vec;
int adj, tot;
tot = strlen(src) + 1; // prep for our vectors
adj = (pSZ-1) - ((tot + pSZ-1) & (pSZ-1)); // calc alignment bytes
cpy = xcalloc(NULL, tot + adj + (2 * pSZ)); // get new larger buffer
snprintf(cpy, tot, "%s", src); // duplicate their string
vec = (char**)(cpy + tot + adj); // prep pointer to pointers
*vec = cpy; // point 1st vector to string
*(vec+1) = NULL; // null ptr 'list' delimit
return vec; // ==> free(*vec) to dealloc
#undef pSZ
}
// This routine reads /proc/#/cgroup for a single task.
// It is similar to file2strvec except we filter and concatenate
// the data into a single string represented as a single vector.
static void fill_cgroup_cvt (proc_t *restrict p) {
#define vMAX ( sizeof(dbuf) - (int)(dst - dbuf) )
char sbuf[1024], dbuf[1024];
char *src, *dst, *grp, *eob;
int tot, x, whackable_int = sizeof(dbuf);
*(dst = dbuf) = '\0'; // empty destination
tot = read_unvectored(sbuf, sizeof(sbuf), p->tid, "cgroup", '\0');
for (src = sbuf, eob = sbuf + tot; src < eob; src += x) {
x = 1; // loop assist
if (!*src) continue;
x = strlen((grp = src));
if ('/' == grp[x - 1]) continue; // skip empty root cgroups
#if 0
grp += strspn(grp, "0123456789:"); // jump past group number
#endif
dst += snprintf(dst, vMAX, "%s", (dst > dbuf) ? "," : "");
dst += escape_str(dst, grp, vMAX, &whackable_int);
}
p->cgroup = vectorize_this_str(dbuf[0] ? dbuf : "-");
#undef vMAX
}
// This routine reads /proc/#/cmdline for the designated task, "escapes"
// the result into a single string represented as a single vector and
// guarantees the caller a valid proc_t.cmdline pointer.
static void fill_cmdline_cvt (proc_t *restrict p) {
#define uFLG ( ESC_BRACKETS | ESC_DEFUNCT )
char sbuf[2048], dbuf[2048];
int whackable_int = sizeof(dbuf);
if (read_unvectored(sbuf, sizeof(sbuf), p->tid, "cmdline", ' '))
escape_str(dbuf, sbuf, sizeof(dbuf), &whackable_int);
else
escape_command(dbuf, p, sizeof(dbuf), &whackable_int, uFLG);
p->cmdline = vectorize_this_str(dbuf);
#undef uFLG
}
// warning: interface may change
int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid) {
return read_unvectored(dst, sz, pid, "cmdline", ' ');
}
/* These are some nice GNU C expression subscope "inline" functions.
* The can be used with arbitrary types and evaluate their arguments
* exactly once.
@ -628,21 +707,37 @@ static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict cons
}
}
if ((flags & PROC_FILLCOM) || (flags & PROC_FILLARG)) /* read+parse /proc/#/cmdline */
p->cmdline = file2strvec(path, "cmdline");
else
p->cmdline = NULL;
if (unlikely(flags & PROC_FILLENV)) /* read+parse /proc/#/environ */
p->environ = file2strvec(path, "environ");
if (unlikely(flags & PROC_FILLENV)) /* read /proc/#/environ */
p->environ = file2strvec(path, "environ");
else
p->environ = NULL;
if(linux_version_code>=LINUX_VERSION(2,6,24) && (flags & PROC_FILLCGROUP))
p->cgroup = file2strvec(path, "cgroup"); /* read /proc/#/cgroup */
else
p->cgroup = NULL;
if (flags & (PROC_FILLCOM|PROC_FILLARG)) { /* read /proc/#/cmdline */
if (flags & PROC_EDITCMDLCVT)
fill_cmdline_cvt(p);
else
p->cmdline = file2strvec(path, "cmdline");
} else
p->cmdline = NULL;
if ((flags & PROC_FILLCGROUP) /* read /proc/#/cgroup, if possible */
&& linux_version_code >= LINUX_VERSION(2,6,24)) {
if (flags & PROC_EDITCGRPCVT)
fill_cgroup_cvt(p);
else
p->cgroup = file2strvec(path, "cgroup");
} else
p->cgroup = NULL;
#ifdef OOMEM_ENABLE
if (unlikely(flags & PROC_FILLOOM)) {
if (likely( file2str(path, "oom_score", sbuf, sizeof sbuf) != -1 ))
oomscore2proc(sbuf, p);
if (likely( file2str(path, "oom_adj", sbuf, sizeof sbuf) != -1 ))
oomadj2proc(sbuf, p);
}
#endif
return p;
next_proc:
return NULL;

View File

@ -111,8 +111,9 @@ typedef struct proc_t {
cmin_flt, // stat cumulative min_flt of process and child processes
cmaj_flt; // stat cumulative maj_flt of process and child processes
char
**environ, // (special) environment string vector (/proc/#/environ)
**cmdline; // (special) command line string vector (/proc/#/cmdline)
**environ, // (special) environment string vector (/proc/#/environ)
**cmdline, // (special) command line string vector (/proc/#/cmdline)
**cgroup; // (special) cgroup string vector (/proc/#/cgroup)
char
// Be compatible: Digital allows 16 and NT allows 14 ???
euser[P_G_SZ], // stat(),status effective user name
@ -140,7 +141,11 @@ typedef struct proc_t {
tpgid, // stat terminal process group id
exit_signal, // stat might not be SIGCHLD
processor; // stat current (or most recent?) CPU
char **cgroup; // cgroup current cgroup, looks like a classic filepath
#ifdef OOMEM_ENABLE
int
oom_score, // oom_score (badness for OOM killer)
oom_adj; // oom_adj (adjustment to OOM score)
#endif
} proc_t;
// PROCTAB: data structure holding the persistent information readproc needs
@ -239,6 +244,7 @@ extern proc_t * get_proc_stats(pid_t pid, proc_t *p);
#define PROC_FILLWCHAN 0x0080 // look up WCHAN name
#define PROC_FILLARG 0x0100 // alloc and fill in `cmdline'
#define PROC_FILLCGROUP 0x0200 // alloc and fill in `cgroup`
#define PROC_FILLOOM 0x0400 // alloc and fill in oom_score, oom_adj
#define PROC_LOOSE_TASKS 0x2000 // threat threads as if they were processes
@ -246,6 +252,9 @@ extern proc_t * get_proc_stats(pid_t pid, proc_t *p);
#define PROC_PID 0x1000 // process id numbers ( 0 terminated)
#define PROC_UID 0x4000 // user id numbers ( length needed )
#define PROC_EDITCGRPCVT 0x10000 // edit `cgroup' as single vector
#define PROC_EDITCMDLCVT 0x20000 // edit `cmdline' as single vector
// it helps to give app code a few spare bits
#define PROC_SPARE_1 0x01000000
#define PROC_SPARE_2 0x02000000

View File

@ -24,7 +24,9 @@
#include <netinet/in.h> /* htons */
#endif
#ifndef OOMEM_ENABLE
long smp_num_cpus; /* number of CPUs */
#endif
#define BAD_OPEN_MESSAGE \
"Error: /proc must be mounted\n" \
@ -180,7 +182,11 @@ static void old_Hertz_hack(void){
setlocale(LC_NUMERIC, savelocale);
jiffies = user_j + nice_j + sys_j + other_j;
seconds = (up_1 + up_2) / 2;
#ifndef OOMEM_ENABLE
h = (unsigned)( (double)jiffies/seconds/smp_num_cpus );
#else
h = (unsigned)( (double)jiffies/seconds/smp_num_cpus() );
#endif
/* actual values used by 2.4 kernels: 32 64 100 128 1000 1024 1200 */
switch(h){
case 9 ... 11 : Hertz = 10; break; /* S/390 (sometimes) */
@ -246,10 +252,34 @@ static int check_for_privs(void){
return !!rc;
}
#ifdef OOMEM_ENABLE
long smp_num_cpus(void)
{
static long _smp_num_cpus=-1; /* number of CPUs */
if (_smp_num_cpus != -1)
return(_smp_num_cpus);
// ought to count CPUs in /proc/stat instead of relying
// on glibc, which foolishly tries to parse /proc/cpuinfo
//
// SourceForge has an old Alpha running Linux 2.2.20 that
// appears to have a non-SMP kernel on a 2-way SMP box.
// _SC_NPROCESSORS_CONF returns 2, resulting in HZ=512
// _SC_NPROCESSORS_ONLN returns 1, which should work OK
_smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
if(_smp_num_cpus<1) _smp_num_cpus=1; /* SPARC glibc is buggy */
return(_smp_num_cpus);
}
#endif
static void init_libproc(void) __attribute__((constructor));
static void init_libproc(void){
have_privs = check_for_privs();
init_Linux_version(); /* Must be called before we check code */
#ifndef OOMEM_ENABLE
// ought to count CPUs in /proc/stat instead of relying
// on glibc, which foolishly tries to parse /proc/cpuinfo
//
@ -259,7 +289,7 @@ static void init_libproc(void){
// _SC_NPROCESSORS_ONLN returns 1, which should work OK
smp_num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
if(smp_num_cpus<1) smp_num_cpus=1; /* SPARC glibc is buggy */
#endif
if(linux_version_code > LINUX_VERSION(2, 4, 0)){
Hertz = find_elf_note(AT_CLKTCK);
if(Hertz!=NOTE_NOT_FOUND) return;

View File

@ -7,7 +7,11 @@
EXTERN_C_BEGIN
extern unsigned long long Hertz; /* clock tick frequency */
#ifndef OOMEM_ENABLE
extern long smp_num_cpus; /* number of CPUs */
#else
extern long smp_num_cpus(void); /* number of CPUs */
#endif
extern int have_privs; /* boolean, true if setuid or similar */
#if 0

View File

@ -224,6 +224,7 @@ static unsigned task_format_needs;
#define needs_for_format (proc_format_needs|task_format_needs)
#define PROC_ONLY_FLAGS (PROC_FILLENV|PROC_FILLARG|PROC_FILLCOM|PROC_FILLMEM|PROC_FILLCGROUP)
/***** munge lists and determine openproc() flags */
static void lists_and_needs(void){
check_headers();
@ -283,11 +284,12 @@ static void lists_and_needs(void){
}
if(!unix_f_option){
proc_format_needs &= ~PROC_FILLCOM;
proc_format_needs |= PROC_EDITCMDLCVT;
needs_for_sort &= ~PROC_FILLCOM;
}
// convert ARG to COM as a standard
if(proc_format_needs & PROC_FILLARG){
proc_format_needs |= PROC_FILLCOM;
proc_format_needs |= (PROC_FILLCOM | PROC_EDITCMDLCVT);
proc_format_needs &= ~PROC_FILLARG;
}
if(bsd_e_option){

View File

@ -331,8 +331,11 @@ Modifications to the arguments are not shown.
// FIXME: some of these may hit the guard page in forest mode
/* "command" is the same thing: long unless c */
static int pr_args(char *restrict const outbuf, const proc_t *restrict const pp){
/*
* "args", "cmd", "command" are all the same: long unless c
* "comm", "ucmd", "ucomm" are all the same: short unless -f
* ( determinations are made in display.c, we just deal with results ) */
static int pr_argcom(char *restrict const outbuf, const proc_t *restrict const pp){
char *endp = outbuf;
unsigned flags;
int rightward=max_rightward;
@ -342,84 +345,30 @@ static int pr_args(char *restrict const outbuf, const proc_t *restrict const pp)
endp += fh;
rightward -= fh;
}
if(bsd_c_option) flags = ESC_DEFUNCT;
else flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS;
endp += escape_command(endp, pp, OUTBUF_SIZE, &rightward, flags);
if(pp->cmdline)
endp += escaped_copy(endp, *pp->cmdline, OUTBUF_SIZE, &rightward);
else
endp += escape_command(endp, pp, OUTBUF_SIZE, &rightward, ESC_DEFUNCT);
if(bsd_e_option && rightward>1){
const char **env = (const char**)pp->environ;
if(env && *env){
*endp++ = ' ';
rightward--;
endp += escape_strlist(endp, env, OUTBUF_SIZE, &rightward);
}
if(bsd_e_option && rightward>1) {
if(pp->environ && *pp->environ)
endp += escape_strlist(endp, pp->environ, OUTBUF_SIZE, &rightward);
}
//return endp - outbuf;
return max_rightward-rightward;
}
static int pr_cgroup(char *restrict const outbuf,const proc_t *restrict const pp) {
char *endp = outbuf;
int rightward = max_rightward;
if(pp->cgroup) {
char **pcgroup = pp->cgroup;
while(*pcgroup != NULL) {
//Skip root cgroups
if(!**pcgroup || (*pcgroup)[strlen(*pcgroup)-1] == '/') {
pcgroup++;
continue;
}
//Skip initial cgroup number
char *ccgroup = strchr(*pcgroup, ':');
if(ccgroup == NULL)
ccgroup = *pcgroup;
else
ccgroup++;
if(endp != outbuf)
endp += escape_str(endp, ";", OUTBUF_SIZE, &rightward);
endp += escape_str(endp, ccgroup, OUTBUF_SIZE, &rightward);
pcgroup++;
}
escaped_copy(outbuf, *pp->cgroup, OUTBUF_SIZE, &rightward);
return max_rightward-rightward;
}
if(endp == outbuf)
else
return pr_nop(outbuf,pp);
return (int)(endp-outbuf);
}
/* "ucomm" is the same thing: short unless -f */
static int pr_comm(char *restrict const outbuf, const proc_t *restrict const pp){
char *endp = outbuf;
unsigned flags;
int rightward=max_rightward;
if(forest_prefix){
int fh = forest_helper(outbuf);
endp += fh;
rightward -= fh;
}
if(unix_f_option) flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS;
else flags = ESC_DEFUNCT;
endp += escape_command(endp, pp, OUTBUF_SIZE, &rightward, flags);
if(bsd_e_option && rightward>1){
const char **env = (const char**)pp->environ;
if(env && *env){
*endp++ = ' ';
rightward--;
endp += escape_strlist(endp, env, OUTBUF_SIZE, &rightward);
}
}
//return endp - outbuf;
return max_rightward-rightward;
}
/* Non-standard, from SunOS 5 */
static int pr_fname(char *restrict const outbuf, const proc_t *restrict const pp){
char *endp = outbuf;
@ -1292,7 +1241,7 @@ static int pr_t_left2(char *restrict const outbuf, const proc_t *restrict const
#define GRP PROC_FILLGRP /* gid_t -> group names */
#define WCH PROC_FILLWCHAN /* do WCHAN lookup */
#define CGRP PROC_FILLCGROUP /* read cgroup */
#define CGRP PROC_FILLCGROUP | PROC_EDITCGRPCVT /* read cgroup */
/* TODO
* pull out annoying BSD aliases into another table (to macro table?)
* add sorting functions here (to unify names)
@ -1320,7 +1269,7 @@ static const format_struct format_array[] = {
{"addr_1", "ADDR", pr_nop, sr_nop, 1, 0, LNX, AN|LEFT},
{"alarm", "ALARM", pr_alarm, sr_alarm, 5, 0, LNX, AN|RIGHT},
{"argc", "ARGC", pr_nop, sr_nop, 4, 0, LNX, PO|RIGHT},
{"args", "COMMAND", pr_args, sr_cmd, 27, ARG, U98, PO|UNLIMITED}, /*command*/
{"args", "COMMAND", pr_argcom, sr_cmd, 27, ARG, U98, PO|UNLIMITED}, /*command*/
{"atime", "TIME", pr_time, sr_nop, 8, 0, SOE, ET|RIGHT}, /*cputime*/ /* was 6 wide */
{"blocked", "BLOCKED", pr_sigmask, sr_nop, 9, 0, BSD, TO|SIGNAL}, /*sigmask*/
{"bnd", "BND", pr_nop, sr_nop, 1, 0, AIX, TO|RIGHT},
@ -1332,11 +1281,11 @@ static const format_struct format_array[] = {
{"class", "CLS", pr_class, sr_sched, 3, 0, XXX, TO|LEFT},
{"cls", "CLS", pr_class, sr_sched, 3, 0, HPU, TO|RIGHT}, /*says HPUX or RT*/
{"cmaj_flt", "-", pr_nop, sr_cmaj_flt, 1, 0, LNX, AN|RIGHT},
{"cmd", "CMD", pr_args, sr_cmd, 27, ARG, DEC, PO|UNLIMITED}, /*ucomm*/
{"cmd", "CMD", pr_argcom, sr_cmd, 27, ARG, DEC, PO|UNLIMITED}, /*ucomm*/
{"cmin_flt", "-", pr_nop, sr_cmin_flt, 1, 0, LNX, AN|RIGHT},
{"cnswap", "-", pr_nop, sr_nop, 1, 0, LNX, AN|RIGHT},
{"comm", "COMMAND", pr_comm, sr_cmd, 15, COM, U98, PO|UNLIMITED}, /*ucomm*/
{"command", "COMMAND", pr_args, sr_cmd, 27, ARG, XXX, PO|UNLIMITED}, /*args*/
{"comm", "COMMAND", pr_argcom, sr_cmd, 15, COM, U98, PO|UNLIMITED}, /*ucomm*/
{"command", "COMMAND", pr_argcom, sr_cmd, 27, ARG, XXX, PO|UNLIMITED}, /*args*/
{"context", "CONTEXT", pr_context, sr_nop, 31, 0, LNX, ET|LEFT},
{"cp", "CP", pr_cp, sr_pcpu, 3, 0, DEC, ET|RIGHT}, /*cpu*/
{"cpu", "CPU", pr_nop, sr_nop, 3, 0, BSD, AN|RIGHT}, /* FIXME ... HP-UX wants this as the CPU number for SMP? */
@ -1516,8 +1465,8 @@ static const format_struct format_array[] = {
{"tty4", "TTY", pr_tty4, sr_tty, 4, 0, LNX, PO|LEFT},
{"tty8", "TTY", pr_tty8, sr_tty, 8, 0, LNX, PO|LEFT},
{"u_procp", "UPROCP", pr_nop, sr_nop, 6, 0, DEC, AN|RIGHT},
{"ucmd", "CMD", pr_comm, sr_cmd, 15, COM, DEC, PO|UNLIMITED}, /*ucomm*/
{"ucomm", "COMMAND", pr_comm, sr_cmd, 15, COM, XXX, PO|UNLIMITED}, /*comm*/
{"ucmd", "CMD", pr_argcom, sr_cmd, 15, COM, DEC, PO|UNLIMITED}, /*ucomm*/
{"ucomm", "COMMAND", pr_argcom, sr_cmd, 15, COM, XXX, PO|UNLIMITED}, /*comm*/
{"uid", "UID", pr_euid, sr_euid, 5, 0, XXX, ET|RIGHT},
{"uid_hack", "UID", pr_euser, sr_euser, 8, USR, XXX, ET|USER},
{"umask", "UMASK", pr_nop, sr_nop, 5, 0, DEC, AN|RIGHT},

1499
top.1

File diff suppressed because it is too large Load Diff

4920
top.c

File diff suppressed because it is too large Load Diff

911
top.h

File diff suppressed because it is too large Load Diff