mirror of
https://gitlab.com/procps-ng/procps.git
synced 2025-01-25 01:04:24 +08:00
cgroup support migrated to libproc, plus miscellaneous re-formatting
This source patchset addresses the following: Library Extension (readproc) . added PROC_EDITCGRPCVT flag . added an internal (static) fill_cgroup_cvt function: . reads AND parses /proc/#/cgroup . returns result as a single string in a single vector . thus no changes to proc_t structure or free memory logic Program Enhancements (top) . removed parse_cgroup logic in favor of libproc . eliminated cgroup sort recurring overhead . converted WCHAN field to variable width . generalized variable width field logic in task_show . real-time notation under P col more distinctive as 'rt' Program Cosmetic (top) . CGROUP now known as CGROUPS (plural) . moved jan's attribution from top.c to 'Notes' in top.h . numerous comments tweaked Document Enhancements (top) . documented CGROUPS field (required renumbering all fields) . adapted narratives for the 3 current variable width fields . expanded real-time scheduling notes, 'RT' now shown as 'rt' Signed-off-by: Jan Görig <jgorig@redhat.com>
This commit is contained in:
parent
2a2fa20656
commit
57031319d6
@ -560,6 +560,46 @@ int read_cmdline(char *restrict const dst, unsigned sz, unsigned pid){
|
||||
return n;
|
||||
}
|
||||
|
||||
// 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 char** fill_cgroup_cvt(const char* directory) {
|
||||
#define vMAX ( sizeof(dbuf) - (int)(dst - dbuf) )
|
||||
char sbuf[1024], dbuf[1024];
|
||||
char *src, *dst, *grp, *eob, **ret, **q;
|
||||
int align, tot, x;
|
||||
|
||||
*(dst = dbuf) = '\0'; // empty destination
|
||||
tot = file2str(directory, "cgroup", sbuf, sizeof(sbuf));
|
||||
if (0 < tot) { // ignore true errors
|
||||
eob = sbuf + tot;
|
||||
for (src = sbuf; src < eob; src++) // disappear those darn nl's
|
||||
if ('\n' == *src) *src = 0;
|
||||
for (src = sbuf; 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 // ( undecided on the next! )
|
||||
if (strchr(grp, ':')) ++grp; // jump past hierarchy number
|
||||
#endif // ( we'll keep it for now! )
|
||||
dst += snprintf(dst, vMAX, "%s%s", (dst > dbuf) ? "," : "", grp);
|
||||
}
|
||||
}
|
||||
if (!dbuf[0]) strncpy(dbuf, "-", sizeof(dbuf));
|
||||
tot = strlen(dbuf) + 1; // prep for our vectors
|
||||
align = (sizeof(char*)-1) - ((tot + sizeof(char*)-1) & (sizeof(char*)-1));
|
||||
dst = xcalloc(NULL, tot + align + (2 * sizeof(char*)));
|
||||
strncpy(dst, dbuf, tot); // propogate our handiwork
|
||||
eob = dst + tot + align; // point to vectors home
|
||||
q = ret = (char**)(eob);
|
||||
*q++ = dst; // point 1st vector to string
|
||||
*q = 0; // delimit 2nd (last) vector
|
||||
return ret; // ==> free(*ret) to dealloc
|
||||
#undef vMAX
|
||||
}
|
||||
|
||||
|
||||
/* These are some nice GNU C expression subscope "inline" functions.
|
||||
* The can be used with arbitrary types and evaluate their arguments
|
||||
* exactly once.
|
||||
@ -658,11 +698,15 @@ static proc_t* simple_readproc(PROCTAB *restrict const PT, proc_t *restrict cons
|
||||
oomadj2proc(sbuf, p);
|
||||
} /* struct has been zeroed out before, so no worries about clearing garbage here */
|
||||
#endif
|
||||
if(linux_version_code>=LINUX_VERSION(2,6,24) && (flags & PROC_FILLCGROUP))
|
||||
p->cgroup = file2strvec(path, "cgroup"); /* read /proc/#/cgroup */
|
||||
else
|
||||
if(linux_version_code>=LINUX_VERSION(2,6,24) && (flags & PROC_FILLCGROUP)) {
|
||||
if((flags & PROC_EDITCGRPCVT)) {
|
||||
p->cgroup = fill_cgroup_cvt(path); /* read /proc/#/cgroup and edit results */
|
||||
} else {
|
||||
p->cgroup = file2strvec(path, "cgroup"); /* read /proc/#/cgroup */
|
||||
}
|
||||
} else
|
||||
p->cgroup = NULL;
|
||||
|
||||
|
||||
return p;
|
||||
next_proc:
|
||||
return NULL;
|
||||
|
@ -251,6 +251,8 @@ 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
|
||||
|
||||
// it helps to give app code a few spare bits
|
||||
#define PROC_SPARE_1 0x01000000
|
||||
#define PROC_SPARE_2 0x02000000
|
||||
|
121
top.1
121
top.1
@ -194,8 +194,12 @@ Header which needs no further explanation.
|
||||
.PP
|
||||
\*(NT the width of \*(We's display will be limited to \*(WX positions.
|
||||
Displaying all fields requires \*(WF characters.
|
||||
The remaining width is used for the 'COMMAND' column which can display the
|
||||
program name or a complete command line, reflecting path and arguments.
|
||||
The remaining width is allocated to variable width columns currently being
|
||||
displayed which can expand to show additional information.
|
||||
|
||||
An example would be the COMMAND field which could show the program name
|
||||
only or a complete command line reflecting path and arguments.
|
||||
Other variable width columns are noted in topic 3a. DESCRIPTIONS of Fields.
|
||||
|
||||
.\" ......................................................................
|
||||
.SS Startup Defaults
|
||||
@ -403,12 +407,27 @@ For additional information on sort provisions
|
||||
\*(Xt 4c. TASK AREA Commands, SORTING.
|
||||
|
||||
.TP 4
|
||||
1.\fB CODE \*(Em Code Size (kb) \fR
|
||||
1.\fB CGROUPS \*(Em Code Size (kb) \fR
|
||||
Control groups provide for allocating resources (cpu, memory, network
|
||||
bandwidth, etc.) among installation-defined groups of processes.
|
||||
They enable fine-grained control over allocating, denying, prioritizing,
|
||||
managing and monitoring those resources.
|
||||
|
||||
Many different hierarchies of cgroups can exist simultaneously on a system
|
||||
and each hierarchy is attached to one or more subsystems.
|
||||
A subsystem represents a single resource.
|
||||
|
||||
\*(NT The 'CGROUPS' field/column, unlike most columns, is not fixed-width.
|
||||
When displayed, it plus any other variable width columns will be allocated
|
||||
all remaining screen width (up to the maximum \*(WX characters).
|
||||
|
||||
.TP 4
|
||||
2.\fB CODE \*(Em Code Size (kb) \fR
|
||||
The amount of \*(MP devoted to executable code, also known as
|
||||
the 'text resident set' size or TRS.
|
||||
|
||||
.TP 4
|
||||
2.\fB COMMAND \*(Em Command\fB Name\fR or Command\fB Line \fR
|
||||
3.\fB COMMAND \*(Em Command\fB Name\fR or Command\fB Line \fR
|
||||
Display the command line used to start a task or the name of the associated
|
||||
program.
|
||||
You toggle between command\fI line\fR and\fI name\fR with 'c', which is both
|
||||
@ -424,13 +443,12 @@ fit in this field's current width.
|
||||
That width depends upon other fields selected, their order and the current
|
||||
screen width.
|
||||
|
||||
\*(NT The 'COMMAND' field/column is unique, in that it is not fixed-width.
|
||||
When displayed, this column will be allocated all remaining screen width
|
||||
(up to the maximum \*(WX characters) to provide for the potential growth
|
||||
of program names into command lines.
|
||||
\*(NT The 'COMMAND' field/column, unlike most columns, is not fixed-width.
|
||||
When displayed, it plus any other variable width columns will be allocated
|
||||
all remaining screen width (up to the maximum \*(WX characters).
|
||||
|
||||
.TP 4
|
||||
3.\fB %CPU \*(Em \*(PU Usage \fR
|
||||
4.\fB %CPU \*(Em \*(PU Usage \fR
|
||||
The task's share of the elapsed \*(PU time since the last screen update,
|
||||
expressed as a percentage of total \*(PU time.
|
||||
In a true SMP environment, if 'Irix mode' is \*F, \*(We will operate
|
||||
@ -439,30 +457,30 @@ number of \*(PUs.
|
||||
You toggle 'Irix/Solaris' modes with the 'I' \*(CI.
|
||||
|
||||
.TP 4
|
||||
4.\fB DATA \*(Em Data + Stack Size (kb) \fR
|
||||
5.\fB DATA \*(Em Data + Stack Size (kb) \fR
|
||||
The amount of \*(MP devoted to other than executable code, also known as
|
||||
the 'data resident set' size or DRS.
|
||||
|
||||
.TP 4
|
||||
5.\fB Flags \*(Em Task Flags \fR
|
||||
6.\fB Flags \*(Em Task Flags \fR
|
||||
This column represents the task's current scheduling flags which are
|
||||
expressed in hexadecimal notation and with zeros suppressed.
|
||||
These flags are officially documented in <linux/sched.h>.
|
||||
|
||||
.TP 4
|
||||
6.\fB GID \*(Em Group Id \fR
|
||||
7.\fB GID \*(Em Group Id \fR
|
||||
The\fI effective\fR group ID.
|
||||
|
||||
.TP 4
|
||||
7.\fB GROUP \*(Em Group Name \fR
|
||||
8.\fB GROUP \*(Em Group Name \fR
|
||||
The\fI effective\fR group name.
|
||||
|
||||
.TP 4
|
||||
8.\fB %MEM \*(Em Memory Usage (RES) \fR
|
||||
9.\fB %MEM \*(Em Memory Usage (RES) \fR
|
||||
A task's currently used share of available \*(MP.
|
||||
|
||||
.TP 4
|
||||
9.\fB NI \*(Em Nice Value \fR
|
||||
10.\fB NI \*(Em Nice Value \fR
|
||||
The nice value of the task.
|
||||
A negative nice value means higher priority, whereas a positive nice value
|
||||
means lower priority.
|
||||
@ -470,14 +488,14 @@ Zero in this field simply means priority will not be adjusted in determining
|
||||
a task's dispatch-ability.
|
||||
|
||||
.TP 4
|
||||
10.\fB nDRT \*(Em Dirty Pages Count \fR
|
||||
11.\fB nDRT \*(Em Dirty Pages Count \fR
|
||||
The number of pages that have been modified since they were last
|
||||
written to \*(AS.
|
||||
Dirty pages must be written to \*(AS before the corresponding physical
|
||||
memory location can be used for some other virtual page.
|
||||
|
||||
.TP 4
|
||||
11.\fB nMaj \*(Em Major Page Fault Count \fR
|
||||
12.\fB nMaj \*(Em Major Page Fault Count \fR
|
||||
The number of\fB major\fR page faults that have occurred for a task.
|
||||
A page fault occurs when a process attempts to read from or write to a
|
||||
virtual page that is not currently present in its address space.
|
||||
@ -485,7 +503,7 @@ A major page fault is when \*(AS access is involved in making that
|
||||
page available.
|
||||
|
||||
.TP 4
|
||||
12.\fB nMin \*(Em Minor Page Fault count \fR
|
||||
13.\fB nMin \*(Em Minor Page Fault count \fR
|
||||
The number of\fB minor\fR page faults that have occurred for a task.
|
||||
A page fault occurs when a process attempts to read from or write to a
|
||||
virtual page that is not currently present in its address space.
|
||||
@ -493,11 +511,11 @@ A minor page fault does not involve \*(AS access in making that
|
||||
page available.
|
||||
|
||||
.TP 4
|
||||
13.\fB nTH \*(Em Number of Threads \fR
|
||||
14.\fB nTH \*(Em Number of Threads \fR
|
||||
The number of threads associated with a process.
|
||||
|
||||
.TP 4
|
||||
14.\fB P \*(Em Last used \*(PU (SMP) \fR
|
||||
15.\fB P \*(Em Last used \*(PU (SMP) \fR
|
||||
A number representing the last used processor.
|
||||
In a true SMP environment this will likely change frequently since the kernel
|
||||
intentionally uses weak affinity.
|
||||
@ -506,7 +524,7 @@ processes to change \*(PUs more often (because of the extra demand for
|
||||
\*(Pu time).
|
||||
|
||||
.TP 4
|
||||
15.\fB PGRP \*(Em Process Group Id \fR
|
||||
16.\fB PGRP \*(Em Process Group Id \fR
|
||||
Every process is member of a unique process group which is used for
|
||||
distribution of signals and by terminals to arbitrate requests for their
|
||||
input and output.
|
||||
@ -516,7 +534,7 @@ By convention, this value equals the process ID (\*(Xa PID) of the first
|
||||
member of a process group, called the process group leader.
|
||||
|
||||
.TP 4
|
||||
16.\fB PID \*(Em Process Id \fR
|
||||
17.\fB PID \*(Em Process Id \fR
|
||||
The task's unique process ID, which periodically wraps, though never
|
||||
restarting at zero.
|
||||
|
||||
@ -525,27 +543,33 @@ a session ID for the session leader (\*(Xa SID);
|
||||
and a TTY process group ID for the process group leader (\*(Xa TPGID).
|
||||
|
||||
.TP 4
|
||||
17.\fB PPID \*(Em Parent Process pid \fR
|
||||
18.\fB PPID \*(Em Parent Process pid \fR
|
||||
The process ID of a task's parent.
|
||||
|
||||
.TP 4
|
||||
18.\fB PR \*(Em Priority \fR
|
||||
The priority of the task.
|
||||
19.\fB PR \*(Em Priority \fR
|
||||
The scheduling priority of the task.
|
||||
If you see 'rt' in this field, it means the task is running under
|
||||
'real time' scheduling priority.
|
||||
|
||||
Under linux, real time priority is somewhat misleading since traditionally
|
||||
the operating itself was not preemptable.
|
||||
And while the 2.6 kernel can be made mostly preemptable, it is not always so.
|
||||
|
||||
.TP 4
|
||||
19.\fB RES \*(Em Resident Memory Size (kb) \fR
|
||||
20.\fB RES \*(Em Resident Memory Size (kb) \fR
|
||||
The non-swapped \*(MP a task has used.
|
||||
|
||||
.TP 4
|
||||
20.\fB RUID \*(Em Real User Id \fR
|
||||
21.\fB RUID \*(Em Real User Id \fR
|
||||
The\fI real\fR user ID.
|
||||
|
||||
.TP 4
|
||||
21.\fB RUSER \*(Em Real User Name \fR
|
||||
22.\fB RUSER \*(Em Real User Name \fR
|
||||
The\fI real\fR user name.
|
||||
|
||||
.TP 4
|
||||
22.\fB S \*(Em Process Status \fR
|
||||
23.\fB S \*(Em Process Status \fR
|
||||
The status of the task which can be one of:
|
||||
'\fBD\fR' = uninterruptible sleep
|
||||
'\fBR\fR' = running
|
||||
@ -559,14 +583,14 @@ Even without a true SMP machine, you may see numerous tasks in this state
|
||||
depending on \*(We's delay interval and nice value.
|
||||
|
||||
.TP 4
|
||||
23.\fB SHR \*(Em Shared Memory Size (kb) \fR
|
||||
24.\fB SHR \*(Em Shared Memory Size (kb) \fR
|
||||
The amount of \*(MS available to a task, not all of which is
|
||||
typically resident.
|
||||
It simply reflects memory that could be potentially shared with
|
||||
other processes.
|
||||
|
||||
.TP 4
|
||||
24.\fB SID \*(Em Session Id \fR
|
||||
25.\fB SID \*(Em Session Id \fR
|
||||
A session is a collection of process groups (\*(Xa PGRP),
|
||||
usually established by the login shell.
|
||||
A newly forked process joins the session of its creator.
|
||||
@ -575,21 +599,21 @@ member of the session, called the session leader, which is usually the
|
||||
login shell.
|
||||
|
||||
.TP 4
|
||||
25.\fB SUID \*(Em Saved User Id \fR
|
||||
26.\fB SUID \*(Em Saved User Id \fR
|
||||
The\fI saved\fR user ID.
|
||||
|
||||
.TP 4
|
||||
26.\fB SUSER \*(Em Saved User Name \fR
|
||||
27.\fB SUSER \*(Em Saved User Name \fR
|
||||
The\fI saved\fR user name.
|
||||
|
||||
.TP 4
|
||||
27.\fB SWAP \*(Em Swapped Size (kb) \fR
|
||||
28.\fB SWAP \*(Em Swapped Size (kb) \fR
|
||||
The non-resident portion of a task's address space.
|
||||
|
||||
SWAP = VIRT - RES.
|
||||
|
||||
.TP 4
|
||||
28.\fB TIME \*(Em \*(PU Time \fR
|
||||
29.\fB TIME \*(Em \*(PU Time \fR
|
||||
Total \*(PU time the task has used since it started.
|
||||
When 'Cumulative mode' is \*O, each process is listed with the \*(Pu
|
||||
time that it and its dead children have used.
|
||||
@ -597,19 +621,19 @@ You toggle 'Cumulative mode' with 'S', which is both a \*(CO and an \*(CI.
|
||||
\*(XC 'S' \*(CI for additional information regarding this mode.
|
||||
|
||||
.TP 4
|
||||
29.\fB TIME+ \*(Em \*(PU Time, hundredths \fR
|
||||
30.\fB TIME+ \*(Em \*(PU Time, hundredths \fR
|
||||
The same as 'TIME', but reflecting more granularity through hundredths
|
||||
of a second.
|
||||
|
||||
.TP 4
|
||||
30.\fB TPGID \*(Em Tty Process Group Id \fR
|
||||
31.\fB TPGID \*(Em Tty Process Group Id \fR
|
||||
The process group ID of the foreground process for the connected tty,
|
||||
or -1 if a process is not connected to a terminal.
|
||||
By convention, this value equals the process ID (\*(Xa PID) of the
|
||||
the process group leader (\*(Xa PGRP).
|
||||
|
||||
.TP 4
|
||||
31.\fB TTY \*(Em Controlling Tty \fR
|
||||
32.\fB TTY \*(Em Controlling Tty \fR
|
||||
The name of the controlling terminal.
|
||||
This is usually the device (serial port, pty, etc.) from which the
|
||||
process was started, and which it uses for input or output.
|
||||
@ -617,15 +641,15 @@ However, a task need not be associated with a terminal, in which case
|
||||
you'll see '?' displayed.
|
||||
|
||||
.TP 4
|
||||
32.\fB UID \*(Em User Id \fR
|
||||
33.\fB UID \*(Em User Id \fR
|
||||
The\fI effective\fR user ID of the task's owner.
|
||||
|
||||
.TP 4
|
||||
33.\fB USER \*(Em User Name \fR
|
||||
34.\fB USER \*(Em User Name \fR
|
||||
The\fI effective\fR user name of the task's owner.
|
||||
|
||||
.TP 4
|
||||
34.\fB VIRT \*(Em Virtual Memory Size (kb) \fR
|
||||
35.\fB VIRT \*(Em Virtual Memory Size (kb) \fR
|
||||
The total amount of \*(MV used by the task.
|
||||
It includes all code, data and shared libraries plus pages that have been
|
||||
swapped out and pages that have been mapped but not used.
|
||||
@ -633,15 +657,20 @@ swapped out and pages that have been mapped but not used.
|
||||
VIRT = SWAP + RES.
|
||||
|
||||
.TP 4
|
||||
35.\fB WCHAN \*(Em Sleeping in Function \fR
|
||||
36.\fB WCHAN \*(Em Sleeping in Function \fR
|
||||
Depending on the availability of the kernel link map ('System.map'), this
|
||||
field will show the name or the address of the kernel function in which the
|
||||
task is currently sleeping.
|
||||
Running tasks will display a dash ('-') in this column.
|
||||
|
||||
\*(NT By displaying this field, \*(We's own working set will be increased by
|
||||
over 700Kb.
|
||||
Your only means of reducing that overhead will be to stop and restart \*(We.
|
||||
By displaying this field, \*(We's own working set could be increased by over
|
||||
700Kb, depending on the kernel version.
|
||||
Should that occur, your only means of reducing that overhead will be to stop
|
||||
and restart \*(We.
|
||||
|
||||
\*(NT The 'WCHAN' field/column, unlike most columns, is not fixed-width.
|
||||
When displayed, it plus any other variable width columns will be allocated
|
||||
all remaining screen width (up to the maximum \*(WX characters).
|
||||
|
||||
.\" ......................................................................
|
||||
.SS 3b. MANAGING Fields
|
||||
@ -1251,7 +1280,7 @@ entire window.
|
||||
\fBLeft\fR,\fBRight\fR :\fIScroll-Columns \fR
|
||||
Move the view of displayable fields horizontally one column at a time.
|
||||
|
||||
\*(NT As a reminder, the 'COMMAND' field is not fixed-width but
|
||||
\*(NT As a reminder, some fields/columns are not fixed-width but
|
||||
allocated all remaining screen width when visible.
|
||||
When scrolling right or left, that feature may produce some
|
||||
unexpected results initially.
|
||||
|
113
top.c
113
top.c
@ -186,43 +186,6 @@ static int *PHash_sav = HHash_one, // alternating 'old/new' hash tables
|
||||
*PHash_new = HHash_two;
|
||||
#endif
|
||||
|
||||
/*###### Temporary Placement ###########################################*/
|
||||
|
||||
/* For cgroup support inauguration, thanks to:
|
||||
Jan Gorig <jgorig@redhat.com> */
|
||||
/*
|
||||
* Create string from cgroup array --
|
||||
* ( eventually to find a home in libproc ? ) */
|
||||
static void parse_cgroup (char *dst, size_t max, const proc_t *p) {
|
||||
int whackable_int = max;
|
||||
char *ccgroup, *endp = dst;
|
||||
|
||||
*dst = '\0';
|
||||
if (p->cgroup) {
|
||||
char **pcgroup = p->cgroup;
|
||||
|
||||
while (*pcgroup != NULL) {
|
||||
// skip root cgroups
|
||||
if (!**pcgroup || (*pcgroup)[strlen(*pcgroup) - 1] == '/') {
|
||||
pcgroup++;
|
||||
continue;
|
||||
}
|
||||
// skip initial cgroup number
|
||||
ccgroup = strchr(*pcgroup, ':');
|
||||
if (ccgroup == NULL)
|
||||
ccgroup = *pcgroup;
|
||||
else
|
||||
ccgroup++;
|
||||
|
||||
if (endp != dst)
|
||||
endp += escape_str(endp, ";", max, &whackable_int);
|
||||
endp += escape_str(endp, ccgroup, max, &whackable_int);
|
||||
pcgroup++;
|
||||
}
|
||||
}
|
||||
if (!*dst) strncpy(dst, "-", max);
|
||||
}
|
||||
|
||||
/*###### Sort callbacks ################################################*/
|
||||
|
||||
/*
|
||||
@ -231,14 +194,7 @@ static void parse_cgroup (char *dst, size_t max, const proc_t *p) {
|
||||
* routine may serve more than one column.
|
||||
*/
|
||||
|
||||
static int SCB_NAME(CGR) (const proc_t **P, const proc_t **Q) {
|
||||
char p[SCREENMAX], q[SCREENMAX];
|
||||
/* we won't always re-parse these cgroups -- besides, it's only
|
||||
a recurring burden when CGROUP is chosen as the sort column! */
|
||||
parse_cgroup(p, sizeof(p), *P);
|
||||
parse_cgroup(q, sizeof(q), *Q);
|
||||
return Frame_srtflg * STRSORTCMP(q, p);
|
||||
}
|
||||
SCB_STRV(CGR, cgroup)
|
||||
static int SCB_NAME(CMD) (const proc_t **P, const proc_t **Q) {
|
||||
/* if a process doesn't have a cmdline, we'll consider it a kernel thread
|
||||
-- since displayed tasks are given special treatment, we must too */
|
||||
@ -385,7 +341,7 @@ static void bye_bye (const char *str) {
|
||||
"\n\t Hertz = %u (%u bytes, %u-bit time)"
|
||||
"\n\t Page_size = %d, Cpu_tot = %d"
|
||||
"\n\t sizeof(CPU_t) = %u, sizeof(HST_t) = %u (%u HST_t's/Page), HHist_siz = %u"
|
||||
"\n\t sizeof(proc_t) = %u, sizeof(proc_t.cmd) = %u"
|
||||
"\n\t sizeof(proc_t) = %u, sizeof(proc_t.cmd) = %u, sizeof(proc_t *) = %u"
|
||||
"\n\t Frames_libflags = %08lX"
|
||||
"\n\t SCREENMAX = %u, ROWMINSIZ = %u, ROWMAXSIZ = %u"
|
||||
"\n\tTerminal: %s"
|
||||
@ -417,7 +373,7 @@ static void bye_bye (const char *str) {
|
||||
, (unsigned)Hertz, (unsigned)sizeof(Hertz), (unsigned)sizeof(Hertz) * 8
|
||||
, Page_size, Cpu_tot
|
||||
, (unsigned) sizeof(CPU_t), (unsigned)sizeof(HST_t), Page_size / (unsigned)sizeof(HST_t), HHist_siz
|
||||
, (unsigned)sizeof(*p), (unsigned)sizeof(p->cmd)
|
||||
, (unsigned)sizeof(*p), (unsigned)sizeof(p->cmd), (unsigned)sizeof(p)
|
||||
, (long)Frames_libflags
|
||||
, (unsigned)SCREENMAX, (unsigned)ROWMINSIZ, (unsigned)ROWMAXSIZ
|
||||
#ifdef PRETENDNOCAP
|
||||
@ -1212,7 +1168,7 @@ static inline int user_matched (WIN_t *q, const proc_t *p) {
|
||||
#define L_stat PROC_FILLSTAT
|
||||
#define L_statm PROC_FILLMEM
|
||||
#define L_status PROC_FILLSTATUS
|
||||
#define L_CGROUP PROC_FILLCGROUP
|
||||
#define L_CGROUP PROC_EDITCGRPCVT | PROC_FILLCGROUP
|
||||
#define L_CMDLINE PROC_FILLARG
|
||||
#define L_EUSER PROC_FILLUSR
|
||||
#define L_OUSER PROC_FILLSTATUS | PROC_FILLUSR
|
||||
@ -1275,9 +1231,9 @@ static FLD_t Fieldstab[] = {
|
||||
{ "nMin ", "%4.4s ", 4, SK_no, SF(FL2), L_stat, "Minor Page Faults" },
|
||||
{ "nDRT ", "%4.4s ", 4, SK_no, SF(DRT), L_statm, "Dirty Pages Count" },
|
||||
{ "S ", "%c ", -1, -1, SF(STA), L_EITHER, "Process Status" },
|
||||
// next entry's special: '.head' is variable width (see calibrate_fields)
|
||||
{ "COMMAND ", NULL, -1, -1, SF(CMD), L_EITHER, "Command Name/Line" },
|
||||
{ "WCHAN ", "%-9.9s ", -1, -1, SF(WCH), L_stat, "Sleeping in Function" },
|
||||
// next 2 entries are special: '.head' is variable width (see calibrate_fields)
|
||||
{ "COMMAND ", NULL, -1, -1, SF(CMD), L_EITHER, "Command Name/Line" },
|
||||
{ "WCHAN ", NULL, -1, -1, SF(WCH), L_stat, "Sleeping in Function" },
|
||||
// next entry's special: the 0's will be replaced with '.'!
|
||||
#ifdef CASEUP_HEXES
|
||||
{ "Flags ", "%08lX ", -1, -1, SF(FLG), L_stat, "Task Flags <sched.h>" },
|
||||
@ -1285,7 +1241,7 @@ static FLD_t Fieldstab[] = {
|
||||
{ "Flags ", "%08lx ", -1, -1, SF(FLG), L_stat, "Task Flags <sched.h>" },
|
||||
#endif
|
||||
// next entry's like P_CMD, and '.head' must be the same length -- they share varcolsz
|
||||
{ "CGROUP ", NULL, -1, -1, SF(CGR), L_CGROUP, "Control Group" }
|
||||
{ "CGROUPS ", NULL, -1, -1, SF(CGR), L_CGROUP, "Control Groups" }
|
||||
#ifdef ZAP_SUSEONLY
|
||||
#define L_oom PROC_FILLOOM
|
||||
,{ "Adj ", "%3d ", -1, -1, SF(OOA), L_oom, "oom_adjustment (2^X)" }
|
||||
@ -1394,8 +1350,7 @@ static void calibrate_fields (void) {
|
||||
|
||||
do {
|
||||
if (VIZISw(w)) {
|
||||
w->hdrcaplen = 0; // > 0 only with USE_X_COLHDR but ref'd throughout
|
||||
// ( we were proliferating way too many #ifdef's )
|
||||
w->hdrcaplen = 0; // really only used with USE_X_COLHDR
|
||||
// build window's pflgsall array, establish upper bounds for maxpflgs
|
||||
for (i = 0, w->totpflgs = 0; i < P_MAXPFLGS; i++) {
|
||||
if (FLDviz(w, i)) {
|
||||
@ -1432,7 +1387,7 @@ static void calibrate_fields (void) {
|
||||
}
|
||||
|
||||
/* establish the final maxpflgs and prepare to grow the variable column
|
||||
heading(s) via varcolsz - it may be a fib if their pflags wern't
|
||||
heading(s) via varcolsz - it may be a fib if their pflags weren't
|
||||
encountered, but that's ok because they won't be displayed anyway */
|
||||
w->maxpflgs = i;
|
||||
w->varcolsz += Screen_cols - strlen(w->columnhdr);
|
||||
@ -1453,8 +1408,8 @@ static void calibrate_fields (void) {
|
||||
w->endpflg = i;
|
||||
}
|
||||
|
||||
/* finally, we can build the true run-time columns header, format the
|
||||
command column heading, if P_CMD is really being displayed, and
|
||||
/* finally, we can build the true run-time columns header, format any
|
||||
variable column heading(s), if they're really being displayed, and
|
||||
rebuild the all-important PROC_FILLxxx flags that will be used
|
||||
until/if we're we're called again */
|
||||
memset((s = w->columnhdr), 0, sizeof(w->columnhdr));
|
||||
@ -1530,6 +1485,7 @@ static void calibrate_fields (void) {
|
||||
* Display each field represented in the current window's fieldscur
|
||||
* array along with its description. Mark with bold and a leading
|
||||
* asterisk those fields associated with the "on" or "active" state.
|
||||
*
|
||||
* Special highlighting will be accorded the "focus" field with such
|
||||
* highlighting potentially extended to include the description.
|
||||
*
|
||||
@ -1593,14 +1549,14 @@ static void display_fields (int focus, int extend, const char *xtra) {
|
||||
* Manage all fields aspects (order/toggle/sort), for all windows. */
|
||||
static void fields_utility (void) {
|
||||
#define unSCRL w->begpflg = 0;
|
||||
#define swapEM { unSCRL; c = w->rc.fieldscur[i]; \
|
||||
#define swapEM { char c; unSCRL; c = w->rc.fieldscur[i]; \
|
||||
w->rc.fieldscur[i] = *p; *p = c; p = &w->rc.fieldscur[i]; }
|
||||
#define spewFI { f = w->rc.sortindx; t = strchr(w->rc.fieldscur, f + FLD_OFFSET); \
|
||||
#define spewFI { char *t; f = w->rc.sortindx; t = strchr(w->rc.fieldscur, f + FLD_OFFSET); \
|
||||
if (!t) t = strchr(w->rc.fieldscur, (f + FLD_OFFSET) | 0x80); \
|
||||
i = (t) ? (int)(t - w->rc.fieldscur) : 0; }
|
||||
WIN_t *w = Curwin; // avoid gcc bloat with a local copy
|
||||
char c, *t, *p = NULL;
|
||||
const char *h = NULL;
|
||||
char *p = NULL;
|
||||
int i, key;
|
||||
FLG_t f;
|
||||
|
||||
@ -1724,7 +1680,7 @@ static CPU_t *cpus_refresh (CPU_t *cpus) {
|
||||
char buf[MEDBUFSIZ]; // enough for /proc/stat CPU line (not the intr line)
|
||||
int i;
|
||||
|
||||
// *** hotplug_cpu_acclimated ***
|
||||
/*** hotplug_acclimated ***/
|
||||
if (smp_sav != SMP_NUM_CPUS) {
|
||||
Cpu_tot = smp_sav = SMP_NUM_CPUS;
|
||||
zap_fieldstab();
|
||||
@ -3105,6 +3061,7 @@ static void summaryhlp (CPU_t *cpu, const char *pfx) {
|
||||
* and then, returning a pointer to the pointers to the proc_t's! */
|
||||
static proc_t **summary_show (void) {
|
||||
#define isROOM(f,n) (CHKw(w, f) && Msg_row + (n) < Screen_rows - 1)
|
||||
#define anyFLG 0xffffff
|
||||
static proc_t **p_table = NULL;
|
||||
static CPU_t *smpcpu = NULL;
|
||||
WIN_t *w = Curwin; // avoid gcc bloat with a local copy
|
||||
@ -3152,7 +3109,7 @@ static proc_t **summary_show (void) {
|
||||
snprintf(tmp, sizeof(tmp), "Cpu%-3d:", smpcpu[i].id);
|
||||
summaryhlp(&smpcpu[i], tmp);
|
||||
Msg_row += 1;
|
||||
if (!isROOM(-1, 1)) break;
|
||||
if (!isROOM(anyFLG, 1)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3165,7 +3122,7 @@ static proc_t **summary_show (void) {
|
||||
const char *which = "Kb";
|
||||
int shift = 0;
|
||||
|
||||
// *** hotplug_mem_acclimated ***
|
||||
/*** hotplug_acclimated ***/
|
||||
if (kb_main_total > 9999999) { which = "Mb"; shift = 10; }
|
||||
if (kb_main_total > 9999999999) { which = "Gb"; shift = 20; }
|
||||
|
||||
@ -3179,16 +3136,16 @@ static proc_t **summary_show (void) {
|
||||
|
||||
return p_table;
|
||||
#undef isROOM
|
||||
#undef anyFLG
|
||||
} // end: summary_show
|
||||
|
||||
|
||||
/*
|
||||
* Display information for a single task row. */
|
||||
static void task_show (const WIN_t *q, const proc_t *p) {
|
||||
/* the following macro is our means to 'inline' emitting a column -- next to
|
||||
procs_refresh, that's the most frequent and costly part of top's job ! */
|
||||
#define makeCOL(va...) snprintf(cbuf, sizeof(cbuf), f, ## va)
|
||||
#define pages2K(n) (unsigned long)( (n) << Pg2K_shft )
|
||||
#define makeCOL(va...) snprintf(cbuf, sizeof(cbuf), f, ## va)
|
||||
#define makeVAR(v) { f = VARCOL_fmts; makeCOL(q->varcolsz, q->varcolsz, v); }
|
||||
#define pages2K(n) (unsigned long)( (n) << Pg2K_shft )
|
||||
char rbuf[ROWMINSIZ], *rp;
|
||||
int j, x;
|
||||
|
||||
@ -3203,7 +3160,6 @@ static void task_show (const WIN_t *q, const proc_t *p) {
|
||||
int s = Fieldstab[i].scale; // string must be altered !
|
||||
int w = Fieldstab[i].width;
|
||||
|
||||
if (!f) f = VARCOL_fmts; // ah ha, a variable width field
|
||||
switch (i) {
|
||||
#ifndef USE_X_COLHDR
|
||||
// these 2 aren't real procflgs, they're used in column highlighting!
|
||||
@ -3216,10 +3172,8 @@ static void task_show (const WIN_t *q, const proc_t *p) {
|
||||
continue;
|
||||
#endif
|
||||
case P_CGR:
|
||||
{ char tmp[SCREENMAX];
|
||||
parse_cgroup(tmp, sizeof(tmp), p);
|
||||
makeCOL(q->varcolsz, q->varcolsz, tmp);
|
||||
}
|
||||
// our kernel may not support cgroups
|
||||
makeVAR(p->cgroup ? p->cgroup[0] : "n/a");
|
||||
break;
|
||||
case P_CMD:
|
||||
{ char tmp[SCREENMAX];
|
||||
@ -3228,7 +3182,7 @@ static void task_show (const WIN_t *q, const proc_t *p) {
|
||||
if (CHKw(q, Show_CMDLIN)) flags = ESC_DEFUNCT | ESC_BRACKETS | ESC_ARGS;
|
||||
else flags = ESC_DEFUNCT;
|
||||
escape_command(tmp, p, sizeof(tmp), &whackable_int, flags);
|
||||
makeCOL(q->varcolsz, q->varcolsz, tmp);
|
||||
makeVAR(tmp);
|
||||
}
|
||||
break;
|
||||
case P_COD:
|
||||
@ -3294,7 +3248,7 @@ static void task_show (const WIN_t *q, const proc_t *p) {
|
||||
break;
|
||||
case P_PRI:
|
||||
if (-99 > p->priority || 999 < p->priority) {
|
||||
f = " RT ";
|
||||
f = " rt ";
|
||||
makeCOL("");
|
||||
} else
|
||||
makeCOL((int)p->priority);
|
||||
@ -3357,14 +3311,12 @@ static void task_show (const WIN_t *q, const proc_t *p) {
|
||||
case P_WCH:
|
||||
if (No_ksyms) {
|
||||
#ifdef CASEUP_HEXES
|
||||
f = "%08lX ";
|
||||
makeVAR(fmtmk("%010lX", (unsigned long)(unsigned int)p->wchan))
|
||||
#else
|
||||
f = "%08lx ";
|
||||
makeVAR(fmtmk("%010lx", (unsigned long)(unsigned int)p->wchan))
|
||||
#endif
|
||||
makeCOL((long)p->wchan);
|
||||
} else {
|
||||
makeCOL(lookup_wchan(p->wchan, p->tid));
|
||||
}
|
||||
} else
|
||||
makeVAR(lookup_wchan(p->wchan, p->tid))
|
||||
break;
|
||||
default: // keep gcc happy
|
||||
break;
|
||||
@ -3379,6 +3331,7 @@ static void task_show (const WIN_t *q, const proc_t *p) {
|
||||
, rbuf
|
||||
, Caps_endline);
|
||||
#undef makeCOL
|
||||
#undef makeVAR
|
||||
#undef pages2K
|
||||
} // end: task_show
|
||||
|
||||
|
19
top.h
19
top.h
@ -43,14 +43,16 @@
|
||||
|
||||
/*###### Notes, etc. ###################################################*/
|
||||
|
||||
/* The following conventions are used to identify areas where
|
||||
/* The following convention is used to identify those areas where
|
||||
adaptations for hotplugging are to be found ...
|
||||
*** hotplug_cpu_acclimated ***
|
||||
*** hotplug_mem_acclimated ***
|
||||
( hopefully libproc will also be supportive of our efforts ) */
|
||||
*** hotplug_acclimated ***
|
||||
( hopefully libproc will also be supportive of our efforts ) */
|
||||
|
||||
/* And there are still some of these lurking here and there...
|
||||
FIXME - blah, blah... */
|
||||
FIXME - blah, blah... */
|
||||
|
||||
/* For introducing inaugural cgroup support, thanks to:
|
||||
Jan Gorig <jgorig@redhat.com> - April, 2011 */
|
||||
|
||||
|
||||
#ifdef PRETEND2_5_X
|
||||
@ -373,6 +375,11 @@ typedef struct WIN_t {
|
||||
#define SCB_STRS(f,s) \
|
||||
static int SCB_NAME(f) (const proc_t **P, const proc_t **Q) { \
|
||||
return Frame_srtflg * STRSORTCMP((*Q)->s, (*P)->s); }
|
||||
#define SCB_STRV(f,s) \
|
||||
static int SCB_NAME(f) (const proc_t **P, const proc_t **Q) { \
|
||||
if (!(*P)->s || !(*Q)->s) \
|
||||
return SORT_eq; \
|
||||
return Frame_srtflg * STRSORTCMP((*Q)->s[0], (*P)->s[0]); }
|
||||
|
||||
/*
|
||||
* The following two macros are used to 'inline' those portions of the
|
||||
@ -635,8 +642,6 @@ typedef struct WIN_t {
|
||||
/*###### Some Prototypes (ha!) #########################################*/
|
||||
|
||||
/* These 'prototypes' are here solely for documentation purposes */
|
||||
/*------ Temporary Placement -------------------------------------------*/
|
||||
//atic void parse_cgroup (char *dst, size_t max, const proc_t *p);
|
||||
/*------ Sort callbacks ------------------------------------------------*/
|
||||
/* for each possible field, in the form of: */
|
||||
/*atic int sort_P_XXX (const proc_t **P, const proc_t **Q); */
|
||||
|
Loading…
Reference in New Issue
Block a user