← Commit list

c229982b3

Denys Vlasenko
Denys Vlasenko
2025-08-05
SUCCESS Duration: 153s

Subject

top: fix display of very large VSZ

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

libbb/procps.c+22 -3
@@ -143,6 +143,24 @@ static unsigned long fast_strtoul_10(char **endptr)
*endptr = str + 1; /* We skip trailing space! */
return n;
}
+# if LONG_MAX < LLONG_MAX
+/* For VSZ, which can be very large */
+static unsigned long long fast_strtoull_10(char **endptr)
+{
+ unsigned char c;
+ char *str = *endptr;
+ unsigned long long n = *str - '0';
+
+ /* Need to stop on both ' ' and '\n' */
+ while ((c = *++str) > ' ')
+ n = n*10 + (c - '0');
+
+ *endptr = str + 1; /* We skip trailing space! */
+ return n;
+}
+# else
+# define fast_strtoull_10(endptr) fast_strtoul_10(endptr)
+# endif
# if ENABLE_FEATURE_FAST_TOP
static long fast_strtol_10(char **endptr)
@@ -370,7 +388,8 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
char *cp, *comm1;
int tty;
#if !ENABLE_FEATURE_FAST_TOP
- unsigned long vsz, rss;
+ unsigned long long vsz;
+ unsigned long rss;
#endif
/* see proc(5) for some details on this */
strcpy(filename_tail, "stat");
@@ -396,7 +415,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
"%ld " /* nice */
"%*s %*s " /* timeout, it_real_value */
"%lu " /* start_time */
- "%lu " /* vsize */
+ "%llu " /* vsize - can be very large */
"%lu " /* rss */
# if ENABLE_FEATURE_TOP_SMP_PROCESS
"%*s %*s %*s %*s %*s %*s " /*rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */
@@ -449,7 +468,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
cp = skip_fields(cp, 2); /* timeout, it_real_value */
sp->start_time = fast_strtoul_10(&cp);
/* vsz is in bytes and we want kb */
- sp->vsz = fast_strtoul_10(&cp) >> 10;
+ sp->vsz = fast_strtoull_10(&cp) >> 10;
/* vsz is in bytes but rss is in *PAGES*! Can you believe that? */
sp->rss = fast_strtoul_10(&cp) << sp->shift_pages_to_kb;
# if ENABLE_FEATURE_TOP_SMP_PROCESS
procps/top.c+15 -2
@@ -629,10 +629,12 @@ typedef struct { unsigned quot, rem; } bb_div_t;
*/
# define CALC_STAT(name, val) bb_div_t name = { (val) / 10, (val) % 10 }
# define SHOW_STAT(name) name.quot, '0'+name.rem
+# define SANITIZE(name) if (name.quot > 99) name.quot = 99, name.rem = (unsigned char)('+' - '0')
# define FMT "%3u.%c"
#else
# define UPSCALE 100
# define CALC_STAT(name, val) unsigned name = (val)
+# define SANITIZE(name) if (name > 99) name = 99
# define SHOW_STAT(name) name
# define FMT "%4u%%"
#endif
@@ -645,8 +647,14 @@ typedef struct { unsigned quot, rem; } bb_div_t;
" COMMAND");
lines_rem--;
- /*
- * %VSZ = s->vsz/MemTotal
+ /* %VSZ = s->vsz / MemTotal * 100%
+ * Calculate this with multiply and shift. Example:
+ * shift = 12
+ * scale = 100 * 0x1000 / total_memory
+ * percent_mem = (size_mem * scale) >> shift
+ * ~= (size_mem >> shift) * scale
+ * ~= (size_mem >> shift) * 100 * (1 << shift) / total_memory
+ * ~= size_mem * 100 / total_memory
*/
pmem_shift = BITS_PER_INT-11;
pmem_scale = UPSCALE*(1U<<(BITS_PER_INT-11)) / total_memory;
@@ -706,6 +714,11 @@ typedef struct { unsigned quot, rem; } bb_div_t;
#if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE
CALC_STAT(pcpu, (s->pcpu*pcpu_scale + pcpu_half) >> pcpu_shift);
#endif
+ /* VSZ can be much larger than total memory
+ * (seen values close to 2Tbyte), don't try to display
+ * "uses 12345.6% of MemTotal" (won't fit the column)
+ */
+ SANITIZE(pmem);
smart_ulltoa5(s->vsz, vsz_str_buf, " mgtpezy");
/* PID PPID USER STAT VSZ %VSZ [%CPU] COMMAND */