__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");
}
}
}
}
+/*
+ ***************************************************************************
+ * 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