[Buildroot] Add 'IRIX mode' to top.

David Laight David.Laight at ACULAB.COM
Thu Nov 11 12:28:21 UTC 2021


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 <david.laight at aculab.com>
---

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)



More information about the buildroot mailing list