]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
genirq/proc: Avoid formatting zero counts in /proc/interrupts
authorThomas Gleixner <tglx@kernel.org>
Sun, 17 May 2026 20:01:38 +0000 (22:01 +0200)
committerThomas Gleixner <tglx@kernel.org>
Tue, 26 May 2026 14:21:11 +0000 (16:21 +0200)
A large portion of interrupt count entries are zero. There is no point in
formatting the zero value as it is way cheeper to just emit a constant
string.

Collect the number of consecutive zero counts and emit them in one go
before a non-zero count and at the end of the line.

Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Tested-by: Michael Kelley <mhklinux@outlook.com>
Reviewed-by: Dmitry Ilvokhin <d@ilvokhin.com>
Reviewed-by: Radu Rendec <radu@rendec.net>
Reviewed-by: Shrikanth Hegde <sshegde@linux.ibm.com>
Link: https://patch.msgid.link/20260517194931.034728540@kernel.org
include/linux/interrupt.h
kernel/irq/proc.c

index 6cd26ffb0505f00d09f3ff2a0a29e94d5eec40ac..3bf969ad8fe078d502d8bb690d5cbd35b27ccff9 100644 (file)
@@ -864,6 +864,7 @@ static inline void init_irq_proc(void)
 struct seq_file;
 int show_interrupts(struct seq_file *p, void *v);
 int arch_show_interrupts(struct seq_file *p, int prec);
+void irq_proc_emit_counts(struct seq_file *p, unsigned int __percpu *cnts);
 
 extern int early_irq_init(void);
 extern int arch_probe_nr_irqs(void);
index dfa0b07236429f97cdebca0fdc987a7e0c8f9f03..378b523a1b00bd2e949df77d86e155fa76745ae2 100644 (file)
@@ -451,6 +451,43 @@ int __weak arch_show_interrupts(struct seq_file *p, int prec)
 # define ACTUAL_NR_IRQS irq_get_nr_irqs()
 #endif
 
+/* Same as seq_put_decimal_ull_width(p, " ", cnt, 10) */
+#define ZSTR1 "          0"
+#define ZSTR1_LEN      (sizeof(ZSTR1) - 1)
+#define ZSTR16         ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 \
+                       ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1 ZSTR1
+#define ZSTR256                ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 \
+                       ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16 ZSTR16
+
+static inline void irq_proc_emit_zero_counts(struct seq_file *p, unsigned int zeros)
+{
+       if (!zeros)
+               return;
+
+       for (unsigned int n = min(zeros, 256); n; zeros -= n, n = min(zeros, 256))
+               seq_write(p, ZSTR256, n * ZSTR1_LEN);
+}
+
+static inline unsigned int irq_proc_emit_count(struct seq_file *p, unsigned int cnt,
+                                              unsigned int zeros)
+{
+       if (!cnt)
+               return zeros + 1;
+
+       irq_proc_emit_zero_counts(p, zeros);
+       seq_put_decimal_ull_width(p, " ", cnt, 10);
+       return 0;
+}
+
+void irq_proc_emit_counts(struct seq_file *p, unsigned int __percpu *cnts)
+{
+       unsigned int cpu, zeros = 0;
+
+       for_each_online_cpu(cpu)
+               zeros = irq_proc_emit_count(p, per_cpu(*cnts, cpu), zeros);
+       irq_proc_emit_zero_counts(p, zeros);
+}
+
 int show_interrupts(struct seq_file *p, void *v)
 {
        const unsigned int nr_irqs = irq_get_nr_irqs();
@@ -486,11 +523,7 @@ int show_interrupts(struct seq_file *p, void *v)
                return 0;
 
        seq_printf(p, "%*d:", prec, i);
-       for_each_online_cpu(j) {
-               unsigned int cnt = desc->kstat_irqs ? per_cpu(desc->kstat_irqs->cnt, j) : 0;
-
-               seq_put_decimal_ull_width(p, " ", cnt, 10);
-       }
+       irq_proc_emit_counts(p, &desc->kstat_irqs->cnt);
        seq_putc(p, ' ');
 
        guard(raw_spinlock_irq)(&desc->lock);