Add 'IRIX mode' to top. On a multi-cpu system 'IRIX mode' displays a singled threaded process that is spinning as using 100% cpu. This is generally more useful than the current 'Solaris mode' that reports 100/num_cpu% cpu.
A multi-threaded program that is busy on multiple cpu will show a cpu use > 100%. Enabled by -I on the command line or 'i' on stdin. Remove some (uint16_t) casts from the 'delta jiffies' value. With enough cpu, fast enough HZ, and long enough delay I think 64k can be exceeded. I doubt intended efficiency of 16x16 multiple makes any difference. Signed-off-by: David Laight <[email protected]> --- It might be worth adding an extra column for processes with a lot of busy threads on systems with a lot of cpu. Note that this is a normal diff from an installed tree. I don't have the git tree. --- top.c.1.33 2021-11-11 09:49:08.165982660 +0000 +++ top.c 2021-11-11 11:28:50.155674293 +0000 @@ -166,6 +166,7 @@ #endif #if ENABLE_FEATURE_TOP_SMP_CPU smallint smp_cpu_info; /* one/many cpu info lines? */ + smallint irix_mode; /* 100% => one cpu busy */ #endif unsigned lines; /* screen height */ #if ENABLE_FEATURE_TOP_INTERACTIVE @@ -202,6 +203,7 @@ #define sort_field (G.sort_field ) #define inverted (G.inverted ) #define smp_cpu_info (G.smp_cpu_info ) +#define irix_mode (G.irix_mode ) #define initial_settings (G.initial_settings ) #define sort_function (G.sort_function ) #define prev_hist (G.prev_hist ) @@ -223,8 +225,9 @@ OPT_n = (1 << 1), OPT_b = (1 << 2), OPT_H = (1 << 3), - OPT_m = (1 << 4), - OPT_EOF = (1 << 5), /* pseudo: "we saw EOF in stdin" */ + OPT_I = (1 << 4), + OPT_m = (1 << 5), + OPT_EOF = (1 << 6), /* pseudo: "we saw EOF in stdin" */ }; #define OPT_BATCH_MODE (option_mask32 & OPT_b) @@ -314,6 +317,13 @@ return; #else if (!smp_cpu_info) { + if (irix_mode && !num_cpus) { + jiffy_counts_t dummy_jif; + while (read_cpu_jiffy(fp, &dummy_jif) >= 4) + num_cpus++; + if (!num_cpus) + irix_mode = 0; + } fclose(fp); return; } @@ -328,8 +338,10 @@ break; num_cpus++; } - if (num_cpus == 0) /* /proc/stat with only "cpu ..." line?! */ + if (num_cpus == 0) { /* /proc/stat with only "cpu ..." line?! */ smp_cpu_info = 0; + irix_mode = 0; + } cpu_prev_jif = xzalloc(sizeof(cpu_prev_jif[0]) * num_cpus); @@ -602,6 +614,28 @@ return meminfo[MI_MEMTOTAL]; } +#if ENABLE_FEATURE_TOP_DECIMALS +# define UPSCALE 1000 +# define FMT "%s" +# define SHOW_STAT(name, buf_id) fmt_proc_pc(name, buf_id) +static NOINLINE const char *fmt_proc_pc(unsigned value, unsigned buf_id) +{ + static char bufs[2][16]; + char *buf = bufs[buf_id]; + + if (value >= 1000) + snprintf(buf, 16, "%5u", value/10); + else + snprintf(buf, 16, "%3u.%c", value/10, '0' + (value % 10)); + return buf; +} + +#else +# define UPSCALE 100 +# define FMT "%4u%%" +# define SHOW_STAT(name, buf_id) name +#endif + static NOINLINE void display_process_list(int lines_rem, int scr_width) { enum { @@ -627,17 +661,6 @@ " COMMAND"); lines_rem--; -#if ENABLE_FEATURE_TOP_DECIMALS -# define UPSCALE 1000 -# define CALC_STAT(name, val) div_t name = div((val), 10) -# define SHOW_STAT(name) name.quot, '0'+name.rem -# define FMT "%3u.%c" -#else -# define UPSCALE 100 -# define CALC_STAT(name, val) unsigned name = (val) -# define SHOW_STAT(name) name -# define FMT "%4u%%" -#endif /* * %VSZ = s->vsz/MemTotal */ @@ -664,14 +687,18 @@ * we assume that unsigned is at least 32-bit. */ pcpu_shift = 6; - pcpu_scale = UPSCALE*64 * (uint16_t)busy_jifs; + pcpu_scale = UPSCALE*64 * busy_jifs; if (pcpu_scale == 0) pcpu_scale = 1; while (pcpu_scale < (1U << (BITS_PER_INT-2))) { pcpu_scale *= 4; pcpu_shift += 2; } - tmp_unsigned = (uint16_t)(cur_jif.total - prev_jif.total) * total_pcpu; + tmp_unsigned = (cur_jif.total - prev_jif.total) * total_pcpu; +#if ENABLE_FEATURE_TOP_SMP_CPU + if (irix_mode && num_cpus) + tmp_unsigned /= num_cpus; +#endif if (tmp_unsigned != 0) pcpu_scale /= tmp_unsigned; /* we want (s->pcpu * pcpu_scale) to never overflow */ @@ -692,9 +719,9 @@ char vsz_str_buf[8]; unsigned col; - CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); + unsigned pmem = (s->vsz*pmem_scale + pmem_half) >> pmem_shift; #if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE - CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift); + unsigned pcpu = (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift; #endif smart_ulltoa5(s->vsz, vsz_str_buf, " mgtpezy"); @@ -706,9 +733,9 @@ " ", s->pid, s->ppid, get_cached_username(s->uid), s->state, vsz_str_buf, - SHOW_STAT(pmem) + SHOW_STAT(pmem, 0) IF_FEATURE_TOP_SMP_PROCESS(, s->last_seen_on_cpu) - IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu)) + IF_FEATURE_TOP_CPU_USAGE_PERCENTAGE(, SHOW_STAT(pcpu, 1)) ); if ((int)(scr_width - col) > 1) read_cmdline(line_buf + col, scr_width - col, s->pid, s->comm); @@ -1034,6 +1061,10 @@ get_jiffy_counts(); continue; } + if (c == 'i') { + irix_mode ^= 1; + continue; + } # endif # endif break; /* unknown key -> force refresh */ @@ -1120,7 +1151,7 @@ /* all args are options; -n NUM */ make_all_argv_opts(argv); /* options can be specified w/o dash */ - col = getopt32(argv, "d:n:bHm", &str_interval, &str_iterations); + col = getopt32(argv, "d:n:bHIm", &str_interval, &str_iterations); /* NB: -m and -H are accepted even if not configured */ #if ENABLE_FEATURE_TOPMEM if (col & OPT_m) /* -m (busybox specific) */ @@ -1145,6 +1176,10 @@ scan_mask |= PSSCAN_TASKS; } #endif +#if ENABLE_FEATURE_TOP_SMP_CPU + if (col & OPT_I) + irix_mode = 1; +#endif /* change to /proc */ xchdir("/proc"); - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales) _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
