]> granicus.if.org Git - sysstat/blobdiff - mpstat.c
Merge branch 'scop-grep-E'
[sysstat] / mpstat.c
index d2f612a0b6d2686365d2a0b8ce4b3eb6c5d052bb..2ad621b5510924a959926ae1f556846f9b0dd667 100644 (file)
--- a/mpstat.c
+++ b/mpstat.c
@@ -1,6 +1,6 @@
 /*
  * mpstat: per-processor statistics
- * (C) 2000-2020 by Sebastien GODARD (sysstat <at> orange.fr)
+ * (C) 2000-2021 by Sebastien GODARD (sysstat <at> orange.fr)
  *
  ***************************************************************************
  * This program is free software; you can redistribute it and/or modify it *
@@ -135,7 +135,7 @@ void usage(char *progname)
                progname);
 
        fprintf(stderr, _("Options are:\n"
-                         "[ -A ] [ -n ] [-T] [ -u ] [ -V ]\n"
+                         "[ -A ] [ -n ] [ -T ] [ -u ] [ -V ]\n"
                          "[ -I { SUM | CPU | SCPU | ALL } ] [ -N { <node_list> | ALL } ]\n"
                          "[ --dec={ 0 | 1 | 2 } ] [ -o JSON ] [ -P { <cpu_list> | ALL } ]\n"));
        exit(1);
@@ -541,7 +541,7 @@ unsigned long long get_global_cpu_mpstats(int prev, int curr,
                                scp->cpu_steal + scp->cpu_softirq;
 
                /*
-                * If the CPU is offline then it is omited from /proc/stat:
+                * If the CPU is offline then it is omitted from /proc/stat:
                 * All the fields couldn't have been read and the sum of them is zero.
                 */
                if (tot_jiffies_c == 0) {
@@ -1161,10 +1161,12 @@ void write_node_stats(int dis, unsigned long long deltot_jiffies, int prev, int
  * @curr_string        String displayed at the beginning of current sample stats.
  *             This is the timestamp of the current sample, or "Average"
  *             when displaying average stats.
+ * @offline_cpu_bitmap
+ *             CPU bitmap for offline CPU.
  ***************************************************************************
  */
 void write_plain_isumcpu_stats(int dis, unsigned long long itv, int prev, int curr,
-                              char *prev_string, char *curr_string)
+                              char *prev_string, char *curr_string, unsigned char offline_cpu_bitmap[])
 {
        struct stats_cpu *scc, *scp;
        struct stats_irq *sic, *sip;
@@ -1193,17 +1195,10 @@ void write_plain_isumcpu_stats(int dis, unsigned long long itv, int prev, int cu
                scp = st_cpu[prev] + cpu;
 
                /* Check if we want stats about this CPU */
-               if (!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07))))
+               if (!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07))) ||
+                   offline_cpu_bitmap[cpu >> 3] & (1 << (cpu & 0x07)))
                        continue;
 
-               if ((scc->cpu_user    + scc->cpu_nice + scc->cpu_sys   +
-                    scc->cpu_iowait  + scc->cpu_idle + scc->cpu_steal +
-                    scc->cpu_hardirq + scc->cpu_softirq) == 0) {
-
-                       /* This is an offline CPU */
-                       continue;
-               }
-
                printf("%-11s", curr_string);
                cprintf_in(IS_INT, " %4d", "", cpu - 1);
 
@@ -1235,9 +1230,12 @@ void write_plain_isumcpu_stats(int dis, unsigned long long itv, int prev, int cu
  *             Stats used as reference may be the previous ones read, or
  *             the very first ones when calculating the average.
  * @curr       Position in array where current statistics will be saved.
+ * @offline_cpu_bitmap
+ *             CPU bitmap for offline CPU.
  ***************************************************************************
  */
-void write_json_isumcpu_stats(int tab, unsigned long long itv, int prev, int curr)
+void write_json_isumcpu_stats(int tab, unsigned long long itv, int prev, int curr,
+                             unsigned char offline_cpu_bitmap[])
 {
        struct stats_cpu *scc, *scp;
        struct stats_irq *sic, *sip;
@@ -1263,7 +1261,8 @@ void write_json_isumcpu_stats(int tab, unsigned long long itv, int prev, int cur
                scp = st_cpu[prev] + cpu;
 
                /* Check if we want stats about this CPU */
-               if (!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07))))
+               if (!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07))) ||
+                   offline_cpu_bitmap[cpu >> 3] & (1 << (cpu & 0x07)))
                        continue;
 
                if (next) {
@@ -1271,14 +1270,6 @@ void write_json_isumcpu_stats(int tab, unsigned long long itv, int prev, int cur
                }
                next = TRUE;
 
-               if ((scc->cpu_user    + scc->cpu_nice + scc->cpu_sys   +
-                    scc->cpu_iowait  + scc->cpu_idle + scc->cpu_steal +
-                    scc->cpu_hardirq + scc->cpu_softirq) == 0) {
-
-                       /* This is an offline CPU */
-                       continue;
-               }
-
                /* Recalculate itv for current proc */
                pc_itv = get_per_cpu_interval(scc, scp);
 
@@ -1318,20 +1309,24 @@ void write_json_isumcpu_stats(int tab, unsigned long long itv, int prev, int cur
  * @tab                Number of tabs to print (JSON format only).
  * @next       TRUE is a previous activity has been displayed (JSON format
  *             only).
+ * @offline_cpu_bitmap
+ *             CPU bitmap for offline CPU.
  ***************************************************************************
  */
 void write_isumcpu_stats(int dis, unsigned long long itv, int prev, int curr,
-                    char *prev_string, char *curr_string, int tab, int *next)
+                        char *prev_string, char *curr_string, int tab, int *next,
+                        unsigned char offline_cpu_bitmap[])
 {
        if (DISPLAY_JSON_OUTPUT(flags)) {
                if (*next) {
                        printf(",\n");
                }
                *next = TRUE;
-               write_json_isumcpu_stats(tab, itv, prev, curr);
+               write_json_isumcpu_stats(tab, itv, prev, curr, offline_cpu_bitmap);
        }
        else {
-               write_plain_isumcpu_stats(dis, itv, prev, curr, prev_string, curr_string);
+               write_plain_isumcpu_stats(dis, itv, prev, curr, prev_string, curr_string,
+                                         offline_cpu_bitmap);
        }
 }
 
@@ -1354,13 +1349,14 @@ void write_isumcpu_stats(int dis, unsigned long long itv, int prev, int curr,
  * @curr_string        String displayed at the beginning of current sample stats.
  *             This is the timestamp of the current sample, or "Average"
  *             when displaying average stats.
+ * @offline_cpu_bitmap
+ *             CPU bitmap for offline CPU.
  ***************************************************************************
  */
 void write_plain_irqcpu_stats(struct stats_irqcpu *st_ic[], int ic_nr, int dis,
                              unsigned long long itv, int prev, int curr,
-                             char *prev_string, char *curr_string)
+                             char *prev_string, char *curr_string, unsigned char offline_cpu_bitmap[])
 {
-       struct stats_cpu *scc;
        int j = ic_nr, offset, cpu, colwidth[NR_IRQS];
        struct stats_irqcpu *p, *q, *p0, *q0;
 
@@ -1418,20 +1414,13 @@ void write_plain_irqcpu_stats(struct stats_irqcpu *st_ic[], int ic_nr, int dis,
 
        for (cpu = 1; cpu <= cpu_nr; cpu++) {
 
-               scc = st_cpu[curr] + cpu;
-
                /*
                 * Check if we want stats about this CPU.
                 * CPU must have been explicitly selected using option -P,
-                * else we display every CPU.
+                * else we display every CPU (unless it's offline).
                 */
-               if (!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07))) && USE_OPTION_P(flags))
-                       continue;
-
-               if ((scc->cpu_user    + scc->cpu_nice + scc->cpu_sys   +
-                    scc->cpu_iowait  + scc->cpu_idle + scc->cpu_steal +
-                    scc->cpu_hardirq + scc->cpu_softirq) == 0)
-                       /* Offline CPU found */
+               if ((!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07))) && USE_OPTION_P(flags)) ||
+                   offline_cpu_bitmap[cpu >> 3] & (1 << (cpu & 0x07)))
                        continue;
 
                printf("%-11s", curr_string);
@@ -1499,12 +1488,14 @@ void write_plain_irqcpu_stats(struct stats_irqcpu *st_ic[], int ic_nr, int dis,
  *             the very first ones when calculating the average.
  * @curr       Position in array where current statistics will be saved.
  * @type       Activity (M_D_IRQ_CPU or M_D_SOFTIRQS).
+ * @offline_cpu_bitmap
+ *             CPU bitmap for offline CPU.
  ***************************************************************************
  */
 void write_json_irqcpu_stats(int tab, struct stats_irqcpu *st_ic[], int ic_nr,
-                            unsigned long long itv, int prev, int curr, int type)
+                            unsigned long long itv, int prev, int curr, int type,
+                            unsigned char offline_cpu_bitmap[])
 {
-       struct stats_cpu *scc;
        int j = ic_nr, offset, cpu;
        struct stats_irqcpu *p, *q, *p0, *q0;
        int nextcpu = FALSE, nextirq;
@@ -1518,20 +1509,13 @@ void write_json_irqcpu_stats(int tab, struct stats_irqcpu *st_ic[], int ic_nr,
 
        for (cpu = 1; cpu <= cpu_nr; cpu++) {
 
-               scc = st_cpu[curr] + cpu;
-
                /*
                 * Check if we want stats about this CPU.
                 * CPU must have been explicitly selected using option -P,
-                * else we display every CPU.
+                * else we display every CPU (unless it's offline).
                 */
-               if (!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07))) && USE_OPTION_P(flags))
-                       continue;
-
-               if ((scc->cpu_user    + scc->cpu_nice + scc->cpu_sys   +
-                    scc->cpu_iowait  + scc->cpu_idle + scc->cpu_steal +
-                    scc->cpu_hardirq + scc->cpu_softirq) == 0)
-                       /* Offline CPU found */
+               if ((!(*(cpu_bitmap + (cpu >> 3)) & (1 << (cpu & 0x07))) && USE_OPTION_P(flags)) ||
+                   offline_cpu_bitmap[cpu >> 3] & (1 << (cpu & 0x07)))
                        continue;
 
                if (nextcpu) {
@@ -1623,23 +1607,26 @@ void write_json_irqcpu_stats(int tab, struct stats_irqcpu *st_ic[], int ic_nr,
  * @next       TRUE is a previous activity has been displayed (JSON format
  *             only).
  * @type       Activity (M_D_IRQ_CPU or M_D_SOFTIRQS).
+ * @offline_cpu_bitmap
+ *             CPU bitmap for offline CPU.
  ***************************************************************************
  */
 void write_irqcpu_stats(struct stats_irqcpu *st_ic[], int ic_nr, int dis,
                        unsigned long long itv, int prev, int curr,
                        char *prev_string, char *curr_string, int tab,
-                       int *next, int type)
+                       int *next, int type, unsigned char offline_cpu_bitmap[])
 {
        if (DISPLAY_JSON_OUTPUT(flags)) {
                if (*next) {
                        printf(",\n");
                }
                *next = TRUE;
-               write_json_irqcpu_stats(tab, st_ic, ic_nr, itv, prev, curr, type);
+               write_json_irqcpu_stats(tab, st_ic, ic_nr, itv, prev, curr, type,
+                                       offline_cpu_bitmap);
        }
        else {
                write_plain_irqcpu_stats(st_ic, ic_nr, dis, itv, prev, curr,
-                                        prev_string, curr_string);
+                                        prev_string, curr_string, offline_cpu_bitmap);
        }
 }
 
@@ -1701,17 +1688,19 @@ void write_stats_core(int prev, int curr, int dis,
        /* Print total number of interrupts per processor */
        if (DISPLAY_IRQ_SUM(actflags)) {
                write_isumcpu_stats(dis, itv, prev, curr, prev_string, curr_string,
-                                   tab, &next);
+                                   tab, &next, offline_cpu_bitmap);
        }
 
        /* Display each interrupt value for each CPU */
        if (DISPLAY_IRQ_CPU(actflags)) {
                write_irqcpu_stats(st_irqcpu, irqcpu_nr, dis, itv, prev, curr,
-                                  prev_string, curr_string, tab, &next, M_D_IRQ_CPU);
+                                  prev_string, curr_string, tab, &next, M_D_IRQ_CPU,
+                                  offline_cpu_bitmap);
        }
        if (DISPLAY_SOFTIRQS(actflags)) {
                write_irqcpu_stats(st_softirqcpu, softirqcpu_nr, dis, itv, prev, curr,
-                                  prev_string, curr_string, tab, &next, M_D_SOFTIRQS);
+                                  prev_string, curr_string, tab, &next, M_D_SOFTIRQS,
+                                  offline_cpu_bitmap);
        }
 
        if (DISPLAY_JSON_OUTPUT(flags)) {
@@ -1889,9 +1878,6 @@ void rw_mpstat_loop(int dis_hdr, int rows)
        int curr = 1, dis = 1;
        unsigned long lines = rows;
 
-       /* Dont buffer data if redirected to a pipe */
-       setbuf(stdout, NULL);
-
        /* Read system uptime and CPU stats */
        read_uptime(&(uptime_cs[0]));
        read_stat_cpu(st_cpu[0], cpu_nr + 1);
@@ -2313,6 +2299,13 @@ int main(int argc, char **argv)
        /* Get time */
        get_localtime(&(mp_tstamp[0]), 0);
 
+       /*
+        * Don't buffer data if redirected to a pipe.
+        * Note: With musl-c, the behavior of this function is undefined except
+        * when it is the first operation on the stream.
+        */
+       setbuf(stdout, NULL);
+
        /* Get system name, release number and hostname */
        __uname(&header);
        print_gal_header(&(mp_tstamp[0]), header.sysname, header.release,