summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Warner <james.warner@comcast.net>2011-05-05 12:07:25 +0200
committerJan Görig <jgorig@redhat.com>2011-05-05 12:12:27 +0200
commit57031319d6da55055b422a079f980cb1297d31ce (patch)
tree901e93587a73655dc2a3036bb4b2691505433641
parent2a2fa20656d77014cf28ecfeaef30293c0ec3985 (diff)
downloadprocps-ng-57031319d6da55055b422a079f980cb1297d31ce.tar.gz
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>
-rw-r--r--proc/readproc.c52
-rw-r--r--proc/readproc.h2
-rw-r--r--top.1121
-rw-r--r--top.c113
-rw-r--r--top.h19
5 files changed, 170 insertions, 137 deletions
diff --git a/proc/readproc.c b/proc/readproc.c
index e12e284..10146f0 100644
--- a/proc/readproc.c
+++ b/proc/readproc.c
@@ -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;
diff --git a/proc/readproc.h b/proc/readproc.h
index 3404c19..c6c9bbe 100644
--- a/proc/readproc.h
+++ b/proc/readproc.h
@@ -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
diff --git a/top.1 b/top.1
index 91c0623..9d466e4 100644
--- a/top.1
+++ b/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.
diff --git a/top.c b/top.c
index 6f46207..b7ca132 100644
--- a/top.c
+++ b/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
diff --git a/top.h b/top.h
index c6db198..580266d 100644
--- a/top.h
+++ b/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); */