]> granicus.if.org Git - procps-ng/commitdiff
top can show loose tasks now
authoralbert <>
Tue, 21 Jun 2005 19:20:39 +0000 (19:20 +0000)
committeralbert <>
Tue, 21 Jun 2005 19:20:39 +0000 (19:20 +0000)
NEWS
top.c
top.h

diff --git a/NEWS b/NEWS
index 4edaa8bf1afefa1c2cd1356081fc8b29ef7a0e59..cd5d2775357044a85a99f799d2f92dacb7956eef 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,6 @@
 procps-3.2.5 --> procps-3.2.6
 
+top can do per-task display -- thanks John Blackwood     rh114012
 more MIPS crud  -- thanks Jim Gifford and Ryan Oliver
 begin prep for setuid
 
diff --git a/top.c b/top.c
index 4aa3ac2d75f224d3965c105664439c4047783ce1..de83c3dee508e4a87c0bb57defc57c39e7c73f9d 100644 (file)
--- a/top.c
+++ b/top.c
@@ -1081,6 +1081,7 @@ static proc_t **procs_refresh (proc_t **table, int flags)
    proc_t *ptsk = (proc_t *)-1;         // first time, Force: (ii)
    unsigned curmax = 0;                 // every time  (jeeze)
    PROCTAB* PT;
+   static int show_threads_was_enabled = 0; // optimization
 
    prochlp(NULL);                       // prep for a new frame
    if (Monpidsidx)
@@ -1089,24 +1090,75 @@ static proc_t **procs_refresh (proc_t **table, int flags)
       PT = openproc(flags);
 
    // i) Allocated Chunks:  *Existing* table;  refresh + reuse
-   while (curmax < savmax) {
-      if (table[curmax]->cmdline) {
-         free(*table[curmax]->cmdline);
-         table[curmax]->cmdline = NULL;
+   if (!(CHKw(Curwin, Show_THREADS))) {
+      while (curmax < savmax) {
+         if (table[curmax]->cmdline) {
+            unsigned idx;
+            // Skip if Show_THREADS was never enabled
+            if (show_threads_was_enabled) {
+               for (idx = curmax + 1; idx < savmax; idx++) {
+                  if (table[idx]->cmdline == table[curmax]->cmdline)
+                     table[idx]->cmdline = NULL;
+               }
+            }
+            free(*table[curmax]->cmdline);
+            table[curmax]->cmdline = NULL;
+         }
+         if (unlikely(!(ptsk = readproc(PT, table[curmax])))) break;
+         prochlp(ptsk);                    // tally & complete this proc_t
+         ++curmax;
+      }
+   }
+   else {                          // show each thread in a process separately
+      while (curmax < savmax) {
+         proc_t *ttsk;
+         if (unlikely(!(ptsk = readproc(PT, NULL)))) break;
+         show_threads_was_enabled = 1;
+         while (curmax < savmax) {
+            unsigned idx;
+            if (table[curmax]->cmdline) {
+               // threads share the same cmdline storage.  'table' is
+               // qsort()ed, so must look through the rest of the table.
+               for (idx = curmax + 1; idx < savmax; idx++) {
+                  if (table[idx]->cmdline == table[curmax]->cmdline)
+                     table[idx]->cmdline = NULL;
+               }
+               free(*table[curmax]->cmdline);  // only free once
+               table[curmax]->cmdline = NULL;
+            }
+            if (!(ttsk = readtask(PT, ptsk, table[curmax]))) break;
+            prochlp(ttsk);
+            ++curmax;
+         }
+         free(ptsk);  // readproc() proc_t not used
       }
-      if (unlikely(!(ptsk = readproc(PT, table[curmax])))) break;
-      prochlp(ptsk);                    // tally & complete this proc_t
-      ++curmax;
    }
 
    // ii) Unallocated Chunks:  *New* or *Existing* table;  extend + fill
-   while (ptsk) {
-      // realloc as we go, keeping 'table' ahead of 'currmax++'
-      table = alloc_r(table, (curmax + 1) * PTRsz);
-      // here, readproc will allocate the underlying proc_t stg
-      if (likely(ptsk = readproc(PT, NULL))) {
-         prochlp(ptsk);                 // tally & complete this proc_t
-         table[curmax++] = ptsk;
+   if (!(CHKw(Curwin, Show_THREADS))) {
+      while (ptsk) {
+         // realloc as we go, keeping 'table' ahead of 'currmax++'
+         table = alloc_r(table, (curmax + 1) * PTRsz);
+         // here, readproc will allocate the underlying proc_t stg
+         if (likely(ptsk = readproc(PT, NULL))) {
+            prochlp(ptsk);                 // tally & complete this proc_t
+            table[curmax++] = ptsk;
+         }
+      }
+   }
+   else {                          // show each thread in a process separately
+      while (ptsk) {
+         proc_t *ttsk;
+         if (likely(ptsk = readproc(PT, NULL))) {
+            show_threads_was_enabled = 1;
+            while (1) {
+               table = alloc_r(table, (curmax + 1) * PTRsz);
+               if (!(ttsk = readtask(PT, ptsk, NULL))) break;
+               prochlp(ttsk);
+               table[curmax++] = ttsk;
+            }
+            free(ptsk);   // readproc() proc_t not used
+         }
       }
    }
    closeproc(PT);
@@ -1427,8 +1479,8 @@ static int rc_read_old (const char *const buf, RCF_t *rc) {
          case 'i':
             rc->win[0].winflags &= ~Show_IDLEPS;
             break;
-         case 'H':                      // 'H' = show threads (yea, sure)
-            //rc->win[0].winflags |= ;
+         case 'H':
+            rc->win[0].winflags |= Show_THREADS;
             break;
          case 'm':
             rc->win[0].winflags &= ~View_MEMORY;
@@ -1742,7 +1794,7 @@ static void parse_args (char **args)
       .  bunched args are actually handled properly and none are ignored
       .  we tolerate NO whitespace and NO switches -- maybe too tolerant? */
    static const char usage[] =
-      " -hv | -bcisS -d delay -n iterations [-u user | -U user] -p pid [,pid ...]";
+      " -hv | -bcisSH -d delay -n iterations [-u user | -U user] -p pid [,pid ...]";
    float tmp_delay = MAXFLOAT;
    char *p;
 
@@ -1768,7 +1820,10 @@ static void parse_args (char **args)
                if (sscanf(cp, "%f", &tmp_delay) != 1)
                   std_err(fmtmk("bad delay '%s'", cp));
                break;
-            case 'h': case 'H':
+            case 'H':
+               TOGw(Curwin, Show_THREADS);
+               break;
+            case 'h':
             case 'v': case 'V':
                std_out(fmtmk("%s\nusage:\t%s%s", procps_version, Myname, usage));
             case 'i':
@@ -2482,6 +2537,14 @@ static void do_key (unsigned c)
          win_select(0);
          break;
 
+      case 'H':
+         if (VIZCHKc) {
+            TOGw(Curwin, Show_THREADS);
+            show_msg(fmtmk("Show threads %s"
+               , CHKw(Curwin, Show_THREADS) ? "On" : "Off"));
+         }
+         break;
+
       case 'h':
       case '?':
       {  char ch;
diff --git a/top.h b/top.h
index f242cf5e78dc91018ba63e1ac68e0829c5d6829b..f6387c9e7e9c3c256e41ad28892163152919aa6c 100644 (file)
--- a/top.h
+++ b/top.h
@@ -277,6 +277,7 @@ enum pflag {
 #define View_NOBOLD  0x0001     // 'B' - disable 'bold' attribute globally
 
 // 'Show_' & 'Qsrt_' flags are for task display in a visible window
+#define Show_THREADS 0x10000    // 'H' - show threads in each task
 #define Show_COLORS  0x0800     // 'z' - show in color (vs. mono)
 #define Show_HIBOLD  0x0400     // 'b' - rows and/or cols bold (vs. reverse)
 #define Show_HICOLS  0x0200     // 'x' - show sort column highlighted
@@ -413,7 +414,7 @@ typedef struct WIN_t {
    "  f,o     . Fields/Columns: '\01f\02' add or remove; '\01o\02' change display order\n" \
    "  F or O  . Select sort field\n" \
    "  <,>     . Move sort field: '\01<\02' next col left; '\01>\02' next col right\n" \
-   "  R       . Toggle normal/reverse sort\n" \
+   "  R,H     . Toggle: '\01R\02' normal/reverse sort; '\01H\02' show threads\n" \
    "  c,i,S   . Toggle: '\01c\02' cmd name/line; '\01i\02' idle tasks; '\01S\02' cumulative time\n" \
    "  x\05,\01y\05     . Toggle highlights: '\01x\02' sort field; '\01y\02' running tasks\n" \
    "  z\05,\01b\05     . Toggle: '\01z\02' color/mono; '\01b\02' bold/reverse (only if 'x' or 'y')\n" \