From: Peter Schiffer Date: Thu, 27 Aug 2015 15:52:53 +0000 (+0200) Subject: Pidstat outputs values > 100% for %CPU X-Git-Tag: v11.1.7~19^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e7447c22b4d8172b56e11bd81e49099dfab3b24b;p=sysstat Pidstat outputs values > 100% for %CPU On systems with many short living processes pidstat could run out of pre-allocated space for PIDs. This patch increases NR_PID_PREALLOC constant so more space for PIDs is pre-allocated, but also adds possibility to re-allocate this space if needed. --- diff --git a/pidstat.c b/pidstat.c index d24ae02..a8bf571 100644 --- a/pidstat.c +++ b/pidstat.c @@ -157,17 +157,37 @@ void salloc_pid_array(unsigned int len) */ void salloc_pid(unsigned int len) { - int i; + short i; for (i = 0; i < 3; i++) { - if ((st_pid_list[i] = (struct pid_stats *) malloc(PID_STATS_SIZE * len)) == NULL) { - perror("malloc"); + if ((st_pid_list[i] = (struct pid_stats *) calloc(len, PID_STATS_SIZE)) == NULL) { + perror("calloc"); exit(4); } - memset(st_pid_list[i], 0, PID_STATS_SIZE * len); } } +/* + *************************************************************************** + * Reallocate structures for PIDs to read. + *************************************************************************** + */ +void realloc_pid(void) +{ + short i; + unsigned int new_size = 2 * pid_nr; + + for (i = 0; i < 3; i++) { + if ((st_pid_list[i] = (struct pid_stats *) realloc(st_pid_list[i], PID_STATS_SIZE * new_size)) == NULL) { + perror("realloc"); + exit(4); + } + memset(st_pid_list[i] + pid_nr, 0, PID_STATS_SIZE * (new_size - pid_nr)); + } + + pid_nr = new_size; +} + /* *************************************************************************** * Free PID list structures. @@ -917,36 +937,33 @@ void read_stats(int curr) exit(4); } - while (p < pid_nr) { - - /* Get directory entries */ - while ((drp = readdir(dir)) != NULL) { - if (isdigit(drp->d_name[0])) - break; + /* Get directory entries */ + while ((drp = readdir(dir)) != NULL) { + if (!isdigit(drp->d_name[0])) { + continue; } - if (drp) { - pst = st_pid_list[curr] + p++; - pid = atoi(drp->d_name); - if (read_pid_stats(pid, pst, &thr_nr, 0)) { - /* Process has terminated */ - pst->pid = 0; - } + pst = st_pid_list[curr] + p++; + pid = atoi(drp->d_name); - else if (DISPLAY_TID(pidflag)) { - /* Read stats for threads in task subdirectory */ - read_task_stats(curr, pid, &p); - } + if (read_pid_stats(pid, pst, &thr_nr, 0)) { + /* Process has terminated */ + pst->pid = 0; + } else if (DISPLAY_TID(pidflag)) { + /* Read stats for threads in task subdirectory */ + read_task_stats(curr, pid, &p); } - else { - for (q = p; q < pid_nr; q++) { - pst = st_pid_list[curr] + q; - pst->pid = 0; - } - break; + + if (p >= pid_nr) { + realloc_pid(); } } + for (q = p; q < pid_nr; q++) { + pst = st_pid_list[curr] + q; + pst->pid = 0; + } + /* Close /proc directory */ closedir(dir); } diff --git a/pidstat.h b/pidstat.h index 0a72468..2fd5980 100644 --- a/pidstat.h +++ b/pidstat.h @@ -13,7 +13,7 @@ #define K_P_CHILD "CHILD" #define K_P_ALL "ALL" -#define NR_PID_PREALLOC 10 +#define NR_PID_PREALLOC 100 #define MAX_COMM_LEN 128 #define MAX_CMDLINE_LEN 128