From bb04019510a97e7ead25892a62361ee51d552a3a Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Thu, 3 Sep 2015 00:00:00 -0500 Subject: [PATCH] top: utilize a library result struct for 'forest view' When top was originally adapted to use that 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 --- top/top.c | 67 +++++++++++++++++++++++++++---------------------------- top/top.h | 4 ++-- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/top/top.c b/top/top.c index b726b453..6dc9130f 100644 --- a/top/top.c +++ b/top/top.c @@ -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') +static int Tree_idx; // frame_make resets to zero /* * 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; } diff --git a/top/top.h b/top/top.h index f59201f1..14b6070f 100644 --- a/top/top.h +++ b/top/top.h @@ -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);