From: Sebastien GODARD Date: Sat, 29 Jan 2022 08:45:30 +0000 (+0100) Subject: A_IRQ: sar: Update report output X-Git-Tag: v12.5.6~39 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d6aa851d514b9b7618ab5be0412db32f241d5135;p=sysstat A_IRQ: sar: Update report output sar now displays interrupts for each CPU, and the global value among all CPU. Signed-off-by: Sebastien GODARD --- diff --git a/pr_stats.c b/pr_stats.c index 9aecd7a..679405b 100644 --- a/pr_stats.c +++ b/pr_stats.c @@ -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 dc5021f..e53b33e 100644 --- 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 diff --git a/sa_common.c b/sa_common.c index b8d3dd6..b9ba8c6 100644 --- a/sa_common.c +++ b/sa_common.c @@ -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