Interrupts which are not marked per CPU increment not only the per CPU statistics, but also the accumulation counter irq_desc::tot_count. Change the counter to type unsigned long so it does not produce sporadic zeros due to wrap arounds on 64-bit machines and do a quick check for non per CPU interrupts. If the counter is zero, then simply emit a full set of zero strings. That spares the evaluation of the per CPU counters completely for interrupts with zero events.
Showing the changes to kernel (1 of 2 files). Show all
Unified · Split
| @@ -523,7 +523,16 @@ int show_interrupts(struct seq_file *p, void *v) · 522 unmodified lines | ||
| 523 | 523 | return 0; |
| 524 | 524 | |
| 525 | 525 | seq_printf(p, "%*d:", prec, i); |
| 526 | − irq_proc_emit_counts(p, &desc->kstat_irqs->cnt); | |
| 526 | + | |
| 527 | + /* | |
| 528 | + * Always output per CPU interrupts. Output device interrupts only when | |
| 529 | + * desc::tot_count is not zero. | |
| 530 | + */ | |
| 531 | + if (irq_settings_is_per_cpu(desc) || irq_settings_is_per_cpu_devid(desc) || | |
| 532 | + data_race(desc->tot_count)) | |
| 533 | + irq_proc_emit_counts(p, &desc->kstat_irqs->cnt); | |
| 534 | + else | |
| 535 | + irq_proc_emit_zero_counts(p, num_online_cpus()); | |
| 527 | 536 | seq_putc(p, ' '); |
| 528 | 537 | |
| 529 | 538 | guard(raw_spinlock_irq)(&desc->lock); |