mpstat: fix total par-cpu IRQ counts
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 30 Jul 2010 11:38:46 +0000 (13:38 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 30 Jul 2010 11:38:46 +0000 (13:38 +0200)
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
procps/mpstat.c

index a1f3937..d19abee 100644 (file)
@@ -163,6 +163,7 @@ static double percent_value(data_t prev, data_t curr, data_t itv)
 
 static double hz_value(data_t prev, data_t curr, data_t itv)
 {
+       //bb_error_msg("curr:%lld prev:%lld G.hz:%u", curr, prev, G.hz);
        return ((double)overflow_safe_sub(prev, curr)) / itv * G.hz;
 }
 
@@ -413,6 +414,8 @@ static void write_stats_core(int prev, int current,
                                        continue;
                                }
                        }
+                       //bb_error_msg("G.st_irq[%u][%u].irq_nr:%lld - G.st_irq[%u][%u].irq_nr:%lld",
+                       // current, cpu, G.st_irq[prev][cpu].irq_nr, prev, cpu, G.st_irq[current][cpu].irq_nr);
                        printf(" %9.2f\n", hz_value(G.st_irq[prev][cpu].irq_nr, G.st_irq[current][cpu].irq_nr, per_cpu_itv));
                }
        }
@@ -523,16 +526,23 @@ static void get_cpu_statistics(struct stats_cpu *cpu, data_t *up, data_t *up0)
 static void get_irqs_from_stat(struct stats_irq *irq)
 {
        FILE *fp;
+       unsigned cpu;
        char buf[1024];
 
+       for (cpu = 1; cpu <= G.cpu_nr; cpu++) {
+               irq->irq_nr = 0;
+       }
+
        fp = fopen_for_read(PROCFS_STAT);
        if (!fp)
                return;
 
        while (fgets(buf, sizeof(buf), fp)) {
-               if (strncmp(buf, "intr ", 5) == 0)
+               //bb_error_msg("/proc/stat:'%s'", buf);
+               if (strncmp(buf, "intr ", 5) == 0) {
                        /* Read total number of IRQs since system boot */
                        sscanf(buf + 5, "%"FMT_DATA"u", &irq->irq_nr);
+               }
        }
 
        fclose(fp);
@@ -554,12 +564,20 @@ static void get_irqs_from_interrupts(const char *fname,
        unsigned irq;
        int cpu_index[G.cpu_nr];
        int iindex;
-       int len, digit;
 
-       for (cpu = 1; cpu <= G.cpu_nr; cpu++) {
-               irq_i = &G.st_irq[current][cpu];
-               irq_i->irq_nr = 0;
-       }
+// Moved to get_irqs_from_stat(), which is called once, not twice,
+// unlike get_irqs_from_interrupts().
+// Otherwise reading of /proc/softirqs
+// was resetting counts to 0 after we painstakingly collected them from
+// /proc/interrupts. Which resulted in:
+// 01:32:47 PM  CPU    intr/s
+// 01:32:47 PM  all    591.47
+// 01:32:47 PM    0      0.00 <= ???
+// 01:32:47 PM    1      0.00 <= ???
+//     for (cpu = 1; cpu <= G.cpu_nr; cpu++) {
+//             G.st_irq[current][cpu].irq_nr = 0;
+//             //bb_error_msg("G.st_irq[%u][%u].irq_nr=0", current, cpu);
+//     }
 
        fp = fopen_for_read(fname);
        if (!fp)
@@ -587,11 +605,15 @@ static void get_irqs_from_interrupts(const char *fname,
        while (fgets(buf, buflen, fp)
         && irq < irqs_per_cpu
        ) {
+               int len;
+               char last_char;
                char *cp;
-               /* Skip over "<irq>:" */
+
+               /* Skip over "IRQNAME:" */
                cp = strchr(buf, ':');
                if (!cp)
                        continue;
+               last_char = cp[-1];
 
                ic = &per_cpu_stats[current][irq];
                len = cp - buf;
@@ -600,7 +622,6 @@ static void get_irqs_from_interrupts(const char *fname,
                }
                safe_strncpy(ic->irq_name, buf, len + 1);
                //bb_error_msg("%s: irq%d:'%s' buf:'%s'", fname, irq, ic->irq_name, buf);
-               digit = isdigit(buf[len - 1]);
                cp++;
 
                for (cpu = 0; cpu < iindex; cpu++) {
@@ -608,9 +629,11 @@ static void get_irqs_from_interrupts(const char *fname,
                        ic = &per_cpu_stats[current][cpu_index[cpu] * irqs_per_cpu + irq];
                        irq_i = &G.st_irq[current][cpu_index[cpu] + 1];
                        ic->interrupt = strtoul(cp, &next, 10);
-                       if (digit) {
-                               /* Do not count non-numerical IRQs */
+                       /* Count only numerical IRQs */
+                       if (isdigit(last_char)) {
                                irq_i->irq_nr += ic->interrupt;
+                               //bb_error_msg("G.st_irq[%u][%u].irq_nr + %u = %lld",
+                               // current, cpu_index[cpu] + 1, ic->interrupt, irq_i->irq_nr);
                        }
                        cp = next;
                }