top: fix display of very large VSZ
No binary (build failed)
—
(log yok)
| @@ -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 | |
| @@ -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 */ | |