X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=libbb%2Fprocps.c;h=fd19621db00be01eedf72d2402ad2875abadbc7d;hb=e357d2ae6833e3ca306f3aa6e12c6ddf2ff1eae2;hp=8d3aea3325c84a3dd8fb42ea6ad7429a196f18d9;hpb=512499c8cab30684785c6b116abbb7c868ac5be9;p=oweals%2Fbusybox.git diff --git a/libbb/procps.c b/libbb/procps.c index 8d3aea332..fd19621db 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -30,7 +30,7 @@ static void clear_cache(cache_t *cp) cp->cache = NULL; cp->size = 0; } -void clear_username_cache(void) +void FAST_FUNC clear_username_cache(void) { clear_cache(&username); clear_cache(&groupname); @@ -46,13 +46,13 @@ static int get_cached(cache_t *cp, unsigned id) if (cp->cache[i].id == id) return i; i = cp->size++; - cp->cache = xrealloc(cp->cache, cp->size * sizeof(*cp->cache)); + cp->cache = xrealloc_vector(cp->cache, 2, i); cp->cache[i++].id = id; return -i; } #endif -typedef char* ug_func(char *name, int bufsize, long uid); +typedef char* FAST_FUNC ug_func(char *name, int bufsize, long uid); static char* get_cached(cache_t *cp, unsigned id, ug_func* fp) { int i; @@ -60,17 +60,17 @@ static char* get_cached(cache_t *cp, unsigned id, ug_func* fp) if (cp->cache[i].id == id) return cp->cache[i].name; i = cp->size++; - cp->cache = xrealloc(cp->cache, cp->size * sizeof(*cp->cache)); + cp->cache = xrealloc_vector(cp->cache, 2, i); cp->cache[i].id = id; /* Never fails. Generates numeric string if name isn't found */ fp(cp->cache[i].name, sizeof(cp->cache[i].name), id); return cp->cache[i].name; } -const char* get_cached_username(uid_t uid) +const char* FAST_FUNC get_cached_username(uid_t uid) { return get_cached(&username, uid, bb_getpwuid); } -const char* get_cached_groupname(gid_t gid) +const char* FAST_FUNC get_cached_groupname(gid_t gid) { return get_cached(&groupname, gid, bb_getgrgid); } @@ -93,7 +93,7 @@ static int read_to_buf(const char *filename, void *buf) return ret; } -procps_status_t *alloc_procps_scan(int flags) +static procps_status_t* FAST_FUNC alloc_procps_scan(void) { unsigned n = getpagesize(); procps_status_t* sp = xzalloc(sizeof(procps_status_t)); @@ -107,7 +107,7 @@ procps_status_t *alloc_procps_scan(int flags) return sp; } -void free_procps_scan(procps_status_t* sp) +void FAST_FUNC free_procps_scan(procps_status_t* sp) { closedir(sp->dir); free(sp->argv0); @@ -115,6 +115,28 @@ void free_procps_scan(procps_status_t* sp) free(sp); } +#if ENABLE_FEATURE_TOPMEM +static unsigned long fast_strtoul_16(char **endptr) +{ + unsigned char c; + char *str = *endptr; + unsigned long n = 0; + + while ((c = *str++) != ' ') { + c = ((c|0x20) - '0'); + if (c > 9) + // c = c + '0' - 'a' + 10: + c = c - ('a' - '0' - 10); + n = n*16 + c; + } + *endptr = str; /* We skip trailing space! */ + return n; +} +/* TOPMEM uses fast_strtoul_10, so... */ +#undef ENABLE_FEATURE_FAST_TOP +#define ENABLE_FEATURE_FAST_TOP 1 +#endif + #if ENABLE_FEATURE_FAST_TOP /* We cut a lot of corners here for speed */ static unsigned long fast_strtoul_10(char **endptr) @@ -141,7 +163,7 @@ static char *skip_fields(char *str, int count) #endif void BUG_comm_size(void); -procps_status_t *procps_scan(procps_status_t* sp, int flags) +procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) { struct dirent *entry; char buf[PROCPS_BUFSIZE]; @@ -153,7 +175,7 @@ procps_status_t *procps_scan(procps_status_t* sp, int flags) struct stat sb; if (!sp) - sp = alloc_procps_scan(flags); + sp = alloc_procps_scan(); for (;;) { entry = readdir(sp->dir); @@ -221,7 +243,8 @@ procps_status_t *procps_scan(procps_status_t* sp, int flags) "%lu %lu " /* utime, stime */ "%*s %*s %*s " /* cutime, cstime, priority */ "%ld " /* nice */ - "%*s %*s %*s " /* timeout, it_real_value, start_time */ + "%*s %*s " /* timeout, it_real_value */ + "%lu " /* start_time */ "%lu " /* vsize */ "%lu " /* rss */ /* "%lu %lu %lu %lu %lu %lu " rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip */ @@ -232,9 +255,10 @@ procps_status_t *procps_scan(procps_status_t* sp, int flags) &sp->pgid, &sp->sid, &tty, &sp->utime, &sp->stime, &tasknice, + &sp->start_time, &vsz, &rss); - if (n != 10) + if (n != 11) break; /* vsz is in bytes and we want kb */ sp->vsz = vsz >> 10; @@ -258,7 +282,8 @@ procps_status_t *procps_scan(procps_status_t* sp, int flags) sp->stime = fast_strtoul_10(&cp); cp = skip_fields(cp, 3); /* cutime, cstime, priority */ tasknice = fast_strtoul_10(&cp); - cp = skip_fields(cp, 3); /* timeout, it_real_value, start_time */ + 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; /* vsz is in bytes but rss is in *PAGES*! Can you believe that? */ @@ -278,16 +303,63 @@ procps_status_t *procps_scan(procps_status_t* sp, int flags) } +#if ENABLE_FEATURE_TOPMEM + if (flags & (PSSCAN_SMAPS)) { + FILE *file; + + strcpy(filename_tail, "/smaps"); + file = fopen_for_read(filename); + if (!file) + break; + while (fgets(buf, sizeof(buf), file)) { + unsigned long sz; + char *tp; + char w; +#define SCAN(str, name) \ + if (strncmp(buf, str, sizeof(str)-1) == 0) { \ + tp = skip_whitespace(buf + sizeof(str)-1); \ + sp->name += fast_strtoul_10(&tp); \ + continue; \ + } + SCAN("Shared_Clean:" , shared_clean ); + SCAN("Shared_Dirty:" , shared_dirty ); + SCAN("Private_Clean:", private_clean); + SCAN("Private_Dirty:", private_dirty); +#undef SCAN + // f7d29000-f7d39000 rw-s ADR M:m OFS FILE + tp = strchr(buf, '-'); + if (tp) { + *tp = ' '; + tp = buf; + sz = fast_strtoul_16(&tp); /* start */ + sz = (fast_strtoul_16(&tp) - sz) >> 10; /* end - start */ + // tp -> "rw-s" string + w = tp[1]; + // skipping "rw-s ADR M:m OFS " + tp = skip_whitespace(skip_fields(tp, 4)); + // filter out /dev/something (something != zero) + if (strncmp(tp, "/dev/", 5) != 0 || strcmp(tp, "/dev/zero\n") == 0) { + if (w == 'w') { + sp->mapped_rw += sz; + } else if (w == '-') { + sp->mapped_ro += sz; + } + } +//else printf("DROPPING %s (%s)\n", buf, tp); + if (strcmp(tp, "[stack]\n") == 0) + sp->stack += sz; + } + } + fclose(file); + } +#endif /* TOPMEM */ + #if 0 /* PSSCAN_CMD is not used */ if (flags & (PSSCAN_CMD|PSSCAN_ARGV0)) { - if (sp->argv0) { - free(sp->argv0); - sp->argv0 = NULL; - } - if (sp->cmd) { - free(sp->cmd); - sp->cmd = NULL; - } + free(sp->argv0); + sp->argv0 = NULL; + free(sp->cmd); + sp->cmd = NULL; strcpy(filename_tail, "/cmdline"); /* TODO: to get rid of size limits, read into malloc buf, * then realloc it down to real size. */ @@ -306,17 +378,22 @@ procps_status_t *procps_scan(procps_status_t* sp, int flags) } } #else - if (flags & PSSCAN_ARGV0) { - if (sp->argv0) { - free(sp->argv0); - sp->argv0 = NULL; - } + if (flags & (PSSCAN_ARGV0|PSSCAN_ARGVN)) { + free(sp->argv0); + sp->argv0 = NULL; strcpy(filename_tail, "/cmdline"); n = read_to_buf(filename, buf); if (n <= 0) break; - if (flags & PSSCAN_ARGV0) + if (flags & PSSCAN_ARGVN) { + sp->argv_len = n; + sp->argv0 = xmalloc(n + 1); + memcpy(sp->argv0, buf, n + 1); + /* sp->argv0[n] = '\0'; - buf has it */ + } else { + sp->argv_len = 0; sp->argv0 = xstrdup(buf); + } } #endif break; @@ -324,7 +401,7 @@ procps_status_t *procps_scan(procps_status_t* sp, int flags) return sp; } -void read_cmdline(char *buf, int col, unsigned pid, const char *comm) +void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm) { ssize_t sz; char filename[sizeof("/proc//cmdline") + sizeof(int)*3];