top: utilize a library result struct for 'forest view'

When top was originally adapted to use that <pids> API,
the forest view support was redesigned since the proc_t
pad_3 byte could no longer be employed to hold a task's
nesting level. The redesign required additional arrays.

Now that the dust is settling on those initial efforts,
that PROCPS_PIDS_noop item was used as a substitute for
the old pad_3 along with a return to the former design.
But, while it proved adequate, the invariant nature for
that item required of top an extra initialization step.

So the library was coaxed into adding one more pid_item
(PROCPS_PIDS_extra) which will, unlike that 'noop' guy,
be reset with each reap. Everybody should be happy now.

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2015-09-03 00:00:00 -05:00 committed by Craig Small
parent 07ec0b4e09
commit bb04019510
2 changed files with 35 additions and 36 deletions

View File

@ -1590,12 +1590,12 @@ static struct {
#define eu_TICS_ALL_C EU_LXC +2
#define eu_TIME_START EU_LXC +3
#define eu_ID_FUID EU_LXC +4
#define eu_NOOP EU_LXC +5
#define eu_XTRA EU_LXC +5
{ -1, -1, -1, -1, -1, PROCPS_PIDS_CMDLINE }, // str ( if Show_CMDLIN )
{ -1, -1, -1, -1, -1, PROCPS_PIDS_TICS_ALL_C }, // ull_int ( if Show_CTIMES )
{ -1, -1, -1, -1, -1, PROCPS_PIDS_TIME_START }, // ull_int ( if Show_FOREST )
{ -1, -1, -1, -1, -1, PROCPS_PIDS_ID_FUID }, // u_int ( if a usrseltyp )
{ -1, -1, -1, -1, -1, PROCPS_PIDS_noop } // n/a ( why not? )
{ -1, -1, -1, -1, -1, PROCPS_PIDS_extra } // u_int ( if Show_FOREST )
#undef A_left
#undef A_right
};
@ -1751,7 +1751,7 @@ static void build_headers (void) {
// for 'busy' only processes, we'll need elapsed tics
if (!CHKw(w, Show_IDLEPS)) ckITEM(EU_CPU);
// with forest view mode, we'll need pid, tgid, ppid & start_time...
if (CHKw(w, Show_FOREST)) { ckITEM(EU_PPD); ckITEM(EU_TGD); ckITEM(eu_TIME_START); }
if (CHKw(w, Show_FOREST)) { ckITEM(EU_PPD); ckITEM(EU_TGD); ckITEM(eu_TIME_START); ckITEM(eu_XTRA); }
// for 'cumulative' times, we'll need equivalent of cutime & cstime
if (Fieldstab[EU_TME].esel && CHKw(w, Show_CTIMES)) ckITEM(eu_TICS_ALL_C);
if (Fieldstab[EU_TM2].esel && CHKw(w, Show_CTIMES)) ckITEM(eu_TICS_ALL_C);
@ -3800,7 +3800,7 @@ static inline int find_ofs (const WIN_t *q, const char *buf) {
/* This is currently the one true prototype require by top.
It is placed here, instead of top.h, so as to avoid a compiler
warning when top_nls.c is compiled. */
static const char *task_show (const WIN_t *, const int);
static const char *task_show (const WIN_t *q, struct pids_stack *p);
static void find_string (int ch) {
#define reDUX (found) ? N_txt(WORD_another_txt) : ""
@ -3825,7 +3825,7 @@ static void find_string (int ch) {
if (Curwin->findstr[0]) {
SETw(Curwin, INFINDS_xxx);
for (i = Curwin->begtask; i < Pids_cnts->total; i++) {
const char *row = task_show(Curwin, i);
const char *row = task_show(Curwin, Curwin->ppt[i]);
if (*row && -1 < find_ofs(Curwin, row)) {
found = 1;
if (i == Curwin->begtask) continue;
@ -4532,29 +4532,27 @@ static void keys_xtra (int ch) {
/*
* We try to keep most existing code unaware of our activities
* ( plus, maintain alphabetical order with carefully chosen )
* ( function names: forest_a, forest_b, forest_c & forest_d )
* ( function names like such: forest_b, forest_c & forest_d )
* ( each with exactly one letter more than its predecessor! ) */
static struct pids_stack **Seed_ppt; // temporary win stacks ptrs
static struct pids_stack **Seed_ppt; // temporary win ppt pointer
static struct pids_stack **Tree_ppt; // forest_create will resize
static int Tree_idx; // frame_make resets to zero
static int *Seed_lvl; // level array for Seeds ('from')
static int *Tree_lvl; // level array for Trees ('to')
/*
* This little recursive guy is the real forest view workhorse.
* He fills in the Tree_ppt array and also sets the child indent
* level which is stored in the same slot of separate array. */
* level which is stored in an 'extra' result struct as a u_int. */
static void forest_begin (const int self, int level) {
// a tailored 'results stack value' extractor macro
// tailored 'results stack value' extractor macros
#define rSv(E,X) PID_VAL(E, s_int, Seed_ppt[X])
#define rLevel PID_VAL(eu_XTRA, u_int, Tree_ppt[Tree_idx])
int i;
if (Tree_idx < Pids_cnts->total) { // immunize against insanity
if (level > 100) level = 101; // our arbitrary nests limit
Tree_ppt[Tree_idx] = Seed_ppt[self]; // add this as root or child
Tree_lvl[Tree_idx++] = level; // while recording its level
Seed_lvl[self] = level; // then, note it's been seen
rLevel = level; // while recording its level
++Tree_idx;
#ifdef TREE_SCANALL
for (i = 0; i < Pids_cnts->total; i++) {
if (i == self) continue;
@ -4567,6 +4565,7 @@ static void forest_begin (const int self, int level) {
}
}
#undef rSv
#undef rLevel
} // end: forest_begin
@ -4576,7 +4575,8 @@ static void forest_begin (const int self, int level) {
* he'll replace the original window ppt with our specially
* ordered forest version. */
static void forest_create (WIN_t *q) {
static int *lvl_arrays; // supports both 'lvl' arrays
// tailored 'results stack value' extractor macro
#define rLevel PID_VAL(eu_XTRA, u_int, Seed_ppt[i])
static int hwmsav;
int i;
@ -4585,30 +4585,28 @@ static void forest_create (WIN_t *q) {
if (hwmsav < Pids_cnts->total) { // grow, but never shrink
hwmsav = Pids_cnts->total;
Tree_ppt = alloc_r(Tree_ppt, sizeof(void*) * hwmsav);
lvl_arrays = alloc_r(lvl_arrays, sizeof(int) * hwmsav * 2);
}
memset(lvl_arrays, 0, sizeof(int) * Pids_cnts->total * 2);
Tree_lvl = lvl_arrays;
Seed_lvl = Tree_lvl + Pids_cnts->total;
#ifndef TREE_SCANALL
if (!(procps_pids_stacks_sort(Pids_ctx, Seed_ppt, Pids_cnts->total
, PROCPS_PIDS_TIME_START, PROCPS_SORT_ASCEND)))
error_exit(fmtmk(N_fmt(LIB_errorpid_fmt),__LINE__));
#endif
for (i = 0; i < Pids_cnts->total; i++) // avoid any hidepid distortions
if (!Seed_lvl[i]) // identify real or pretend trees
if (!rLevel) // identify real or pretend trees
forest_begin(i, 1); // add as parent plus its children
}
memcpy(Seed_ppt, Tree_ppt, sizeof(void*) * Pids_cnts->total);
#undef rLevel
} // end: forest_create
/*
* This guy adds the artwork to either a 'cmd' or 'cmdline'
* when in forest view mode, otherwise he just returns 'em. */
static inline const char *forest_display (const WIN_t *q, const int idx) {
// a tailored 'results stack value' extractor macro
#define rSv(E) PID_VAL(E, str, q->ppt[idx])
static inline const char *forest_display (const WIN_t *q, struct pids_stack *p) {
// tailored 'results stack value' extractor macros
#define rSv(E) PID_VAL(E, str, p)
#define rLevel PID_VAL(eu_XTRA, u_int, p)
#ifndef SCROLLVAR_NO
static char buf[1024*64*2]; // the same as libray's max buffer size
#else
@ -4616,11 +4614,12 @@ static inline const char *forest_display (const WIN_t *q, const int idx) {
#endif
const char *which = (CHKw(q, Show_CMDLIN)) ? rSv(eu_CMDLINE) : rSv(EU_CMD);
if (!CHKw(q, Show_FOREST) || Tree_lvl[idx] < 2) return which;
if (Tree_lvl[idx] > 100) snprintf(buf, sizeof(buf), "%400s%s", " + ", which);
else snprintf(buf, sizeof(buf), "%*s%s", 4 * (Tree_lvl[idx] - 1), " `- ", which);
if (!CHKw(q, Show_FOREST) || 1 == rLevel) return which;
if (rLevel > 100) snprintf(buf, sizeof(buf), "%400s%s", " + ", which);
else snprintf(buf, sizeof(buf), "%*s%s", 4 * (rLevel - 1), " `- ", which);
return buf;
#undef rSv
#undef rLevel
} // end: forest_display
/*###### Main Screen routines ##########################################*/
@ -4940,14 +4939,14 @@ numa_nope:
/*
* Build the information for a single task row and
* display the results or return them to the caller. */
static const char *task_show (const WIN_t *q, const int idx) {
static const char *task_show (const WIN_t *q, struct pids_stack *p) {
// a tailored 'results stack value' extractor macro
#define rSv(E,T) PID_VAL(E, T, q->ppt[idx])
#define rSv(E,T) PID_VAL(E, T, p)
#ifndef SCROLLVAR_NO
#define makeVAR(P) { if (!q->varcolbeg) cp = make_str(P, q->varcolsz, Js, AUTOX_NO); \
else cp = make_str(q->varcolbeg < (int)strlen(P) ? P + q->varcolbeg : "", q->varcolsz, Js, AUTOX_NO); }
#define makeVAR(S) { if (!q->varcolbeg) cp = make_str(S, q->varcolsz, Js, AUTOX_NO); \
else cp = make_str(q->varcolbeg < (int)strlen(S) ? S + q->varcolbeg : "", q->varcolsz, Js, AUTOX_NO); }
#else
#define makeVAR(P) cp = make_str(P, q->varcolsz, Js, AUTOX_NO)
#define makeVAR(S) cp = make_str(S, q->varcolsz, Js, AUTOX_NO)
#endif
static char rbuf[ROWMINSIZ];
char *rp;
@ -5100,7 +5099,7 @@ static const char *task_show (const WIN_t *q, const int idx) {
break;
/* str, make_str with varialbe width + additional decoration */
case EU_CMD:
makeVAR(forest_display(q, idx));
makeVAR(forest_display(q, p));
break;
default: // keep gcc happy
continue;
@ -5179,14 +5178,14 @@ static int window_show (WIN_t *q, int wmax) {
checking some stuff with each iteration and check it just once... */
if (CHKw(q, Show_IDLEPS) && !q->usrseltyp)
while (i < Pids_cnts->total && lwin < wmax) {
if (*task_show(q, i++))
if (*task_show(q, q->ppt[i++]))
++lwin;
}
else
while (i < Pids_cnts->total && lwin < wmax) {
if ((CHKw(q, Show_IDLEPS) || isBUSY(q->ppt[i]))
&& wins_usrselect(q, q->ppt[i])
&& *task_show(q, i))
&& *task_show(q, q->ppt[i]))
++lwin;
++i;
}

View File

@ -684,12 +684,12 @@ typedef struct WIN_t {
/*------ Forest View support -------------------------------------------*/
//atic void forest_begin (const int self, int level);
//atic void forest_create (WIN_t *q);
//atic inline const char *forest_display (const WIN_t *q, const int idx);
//atic inline const char *forest_display (const WIN_t *q, struct pids_stack *p);
/*------ Main Screen routines ------------------------------------------*/
//atic void do_key (int ch);
//atic void summary_hlp (struct procps_jiffs_hist *cpu, const char *pfx);
//atic void summary_show (void);
//atic const char *task_show (const WIN_t *q, const int idx);
//atic const char *task_show (const WIN_t *q, struct pids_stack *p);
//atic int window_show (WIN_t *q, int wmax);
/*------ Entry point plus two ------------------------------------------*/
//atic void frame_hlp (int wix, int max);