]> granicus.if.org Git - sysstat/commitdiff
A_IRQ: sar: Update report output
authorSebastien GODARD <sysstat@users.noreply.github.com>
Sat, 29 Jan 2022 08:45:30 +0000 (09:45 +0100)
committerSebastien GODARD <sysstat@users.noreply.github.com>
Sat, 29 Jan 2022 08:45:30 +0000 (09:45 +0100)
sar now displays interrupts for each CPU, and the global value among all
CPU.

Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>
pr_stats.c
sa.h
sa_common.c

index 9aecd7a2c28255c465ed029d8e34360a9711d417..679405b993c9b864e1c03d0b9ac93725752e2555 100644 (file)
@@ -338,49 +338,71 @@ __print_funct_t print_pcsw_stats(struct activity *a, int prev, int curr,
 __print_funct_t print_irq_stats(struct activity *a, int prev, int curr,
                                unsigned long long itv)
 {
-       int i;
-       struct stats_irq *sic, *sip;
+       int c, i;
+       struct stats_irq *stc_cpu_irq, *stp_cpu_irq, *stc_cpuall_irq, *stp_cpuall_irq;
+       unsigned char masked_cpu_bitmap[BITMAP_SIZE(NR_CPUS)] = {0};
+
+       /*
+        * @nr[curr] cannot normally be greater than @nr_ini
+        * (since @nr_ini counts up all CPU, even those offline).
+        * If this happens, it may be because the machine has been
+        * restarted with more CPU and no LINUX_RESTART has been
+        * inserted in file.
+        */
+       if (a->nr[curr] > a->nr_ini) {
+               a->nr_ini = a->nr[curr];
+       }
+
+       /* Identify offline and unselected CPU, and keep persistent statistics values */
+       get_global_int_statistics(a, prev, curr, flags, masked_cpu_bitmap);
 
        if (dish || DISPLAY_ZERO_OMIT(flags)) {
-               print_hdr_line(timestamp[!curr], a, FIRST, 0, 9, NULL); // TODO: Check for offline CPU
+               print_hdr_line(timestamp[!curr], a, FIRST, DISPLAY_PRETTY(flags) ? -1 : 0, 9,
+                              masked_cpu_bitmap);
        }
 
-       for (i = 0; (i < a->nr[curr]) && (i < a->bitmap->b_size + 1); i++) {
+       for (i = 0; i < a->nr2; i++) {
 
-               /*
-                * If @nr[curr] > @nr[prev] then we consider that previous
-                * interrupt value was 0.
-                */
-               sic = (struct stats_irq *) ((char *) a->buf[curr] + i * a->msize);
-               sip = (struct stats_irq *) ((char *) a->buf[prev] + i * a->msize);
+               stc_cpuall_irq = (struct stats_irq *) ((char *) a->buf[curr] + i * a->msize);
 
-               /*
-                * Note: @nr[curr] gives the number of interrupts read (1 .. NR_IRQS + 1).
-                * Bitmap size is provided for (NR_IRQS + 1) interrupts.
-                * Anyway, NR_IRQS may vary between the version of sysstat
-                * used by sadc to create a file, and the version of sysstat
-                * used by sar to read it...
-                */
+               if (a->item_list != NULL) {
+                       /* A list of devices has been entered on the command line */
+                       if (!search_list_item(a->item_list, stc_cpuall_irq->irq_name))
+                               /* Device not found */
+                               continue;
+               }
 
-               /* Should current interrupt (including int "sum") be displayed? */
-               if (a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))) {
+               stp_cpuall_irq = (struct stats_irq *) ((char *) a->buf[prev] + i * a->msize);
 
-                       if (DISPLAY_ZERO_OMIT(flags) && !memcmp(sip, sic, STATS_IRQ_SIZE))
+               if (DISPLAY_ZERO_OMIT(flags) && (stc_cpuall_irq->irq_nr == stp_cpuall_irq->irq_nr))
+                       continue;
+
+               printf("%-11s", timestamp[curr]);
+
+               if (!DISPLAY_PRETTY(flags)) {
+                       cprintf_in(IS_STR, " %9s", i ? stc_cpuall_irq->irq_name : "sum", 0);
+               }
+
+               for (c = 0; (c < a->nr[curr]) && (c < a->bitmap->b_size + 1); c++) {
+
+                       stc_cpu_irq = (struct stats_irq *) ((char *) a->buf[curr] + c * a->msize * a->nr2
+                                                                                 + i * a->msize);
+                       stp_cpu_irq = (struct stats_irq *) ((char *) a->buf[prev] + c * a->msize * a->nr2
+                                                                                 + i * a->msize);
+
+                       /* Should current CPU (including CPU "all") be displayed? */
+                       if (masked_cpu_bitmap[c >> 3] & (1 << (c & 0x07)))
+                               /* No */
                                continue;
 
                        /* Yes: Display it */
-                       printf("%-11s", timestamp[curr]);
-                       if (!i) {
-                               /* This is interrupt "sum" */
-                               cprintf_in(IS_STR, " %s", "      sum", 0);
-                       }
-                       else {
-                               cprintf_in(IS_INT, " %9d", "", i -1);
-                       }
+                       cprintf_f(NO_UNIT, 1, 9, 2, S_VALUE(stp_cpu_irq->irq_nr, stc_cpu_irq->irq_nr, itv));
 
-                       cprintf_f(NO_UNIT, 1, 9, 2, S_VALUE(sip->irq_nr, sic->irq_nr, itv));
-                       printf("\n");
+                       if (DISPLAY_PRETTY(flags)) {
+                               cprintf_in(IS_STR, " %9s", i ? stc_cpuall_irq->irq_name : "sum", 0);
+                       }
                }
+               printf("\n");
        }
 }
 
diff --git a/sa.h b/sa.h
index dc5021f87c56f1f076c5fc0d2cc00f31dfdde51d..e53b33e5ca4776b7181e8b4f63b1e2c80384cf78 100644 (file)
--- a/sa.h
+++ b/sa.h
@@ -1529,6 +1529,8 @@ char *get_fs_name_to_display
        (struct activity *, uint64_t, struct stats_filesystem *);
 unsigned long long get_global_cpu_statistics
        (struct activity *, int, int, uint64_t, unsigned char []);
+void get_global_int_statistics
+       (struct activity *, int, int, uint64_t, unsigned char []);
 void get_global_soft_statistics
        (struct activity *, int, int, uint64_t, unsigned char []);
 void get_itv_value
index b8d3dd6586f9e69afa810b11a675ccf0ec16e180..b9ba8c67ec27a200cc22da53b4fdd3b237521aac 100644 (file)
@@ -3265,6 +3265,64 @@ void get_global_soft_statistics(struct activity *a, int prev, int curr,
        }
 }
 
+/*
+ ***************************************************************************
+ * Identify offline CPU (those for which all interrupts are 0) and keep
+ * interrupts statistics (their values are persistent). Include also CPU
+ * which have not been selected (this is necessary so that the header of the
+ * interrupts statistics report can be displayed).
+ *
+ * IN:
+ * @a          Activity structure with statistics.
+ * @prev       Index in array where stats used as reference are.
+ * @curr       Index in array for current sample statistics.
+ * @flags      Flags for common options and system state.
+ * @masked_cpu_bitmap
+ *             CPU bitmap for offline and unselected CPU.
+ *
+ * OUT:
+ * @a          Activity structure with updated statistics (those for global
+ *             CPU, and also those for offline CPU).
+ * @masked_cpu_bitmap
+ *             CPU bitmap with offline and unselected CPU.
+ ***************************************************************************
+ */
+void get_global_int_statistics(struct activity *a, int prev, int curr,
+                              uint64_t flags, unsigned char masked_cpu_bitmap[])
+{
+       int i;
+       struct stats_irq *stc_cpu_sum, *stp_cpu_sum;
+
+       for (i = 1; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {
+
+               /*
+                * The size of a->buf[...] CPU structure may be different from the default
+                * sizeof(struct stats_irq) value if data have been read from a file!
+                * That's why we don't use a syntax like:
+                * stc_cpu_sum = (struct stats_irq *) a->buf[...] + i;
+                 */
+               stc_cpu_sum = (struct stats_irq *) ((char *) a->buf[curr] + i * a->msize * a->nr2);
+               stp_cpu_sum = (struct stats_irq *) ((char *) a->buf[prev] + i * a->msize * a->nr2);
+
+               if (stc_cpu_sum->irq_nr == 0) {
+                       /* Assume current CPU is offline */
+                       masked_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
+                       memcpy(stc_cpu_sum, stp_cpu_sum, a->msize * a->nr2);
+                       continue;
+               }
+
+               /*
+                * Check if current CPU is back online but with no previous sample for it,
+                * or if it has not been selected.
+                */
+               if (((stp_cpu_sum->irq_nr == 0) && !WANT_SINCE_BOOT(flags)) ||
+                   (!(a->bitmap->b_array[i >> 3] & (1 << (i & 0x07))))) {
+                       /* CPU should not be displayed */
+                       masked_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
+               }
+       }
+}
+
 /*
  ***************************************************************************
  * Get filesystem name to display. This may be either the persistent name