tools/softirqs: Add event counting support
diff --git a/man/man8/softirqs.8 b/man/man8/softirqs.8
index 408c5a0..fa475f7 100644
--- a/man/man8/softirqs.8
+++ b/man/man8/softirqs.8
@@ -2,7 +2,7 @@
 .SH NAME
 softirqs \- Measure soft IRQ (soft interrupt) event time. Uses Linux eBPF/bcc.
 .SH SYNOPSIS
-.B softirqs [\-h] [\-T] [\-N] [\-d] [interval] [count]
+.B softirqs [\-h] [\-T] [\-N] [\-C] [\-d] [\-c CPU] [interval] [count]
 .SH DESCRIPTION
 This summarizes the time spent servicing soft IRQs (soft interrupts), and can
 show this time as either totals or histogram distributions. A system-wide
@@ -26,10 +26,13 @@
 Include timestamps on output.
 .TP
 \-N
-Output in nanoseconds
+Output in nanoseconds.
+.TP
+\-C
+Show the number of soft irq events.
 .TP
 \-d
-Show IRQ time distribution as histograms
+Show IRQ time distribution as histograms.
 .TP
 \-c CPU
 Trace on this CPU only.
@@ -39,6 +42,10 @@
 #
 .B softirqs
 .TP
+Show the number of soft irq events:
+#
+.B softirqs \-C
+.TP
 Show soft IRQ event time as histograms:
 #
 .B softirqs \-d
diff --git a/tools/softirqs.py b/tools/softirqs.py
index 2186277..0ed18c4 100755
--- a/tools/softirqs.py
+++ b/tools/softirqs.py
@@ -4,7 +4,7 @@
 # softirqs  Summarize soft IRQ (interrupt) event time.
 #           For Linux, uses BCC, eBPF.
 #
-# USAGE: softirqs [-h] [-T] [-N] [-d] [-c CPU] [interval] [count]
+# USAGE: softirqs [-h] [-T] [-N] [-C] [-d] [-c CPU] [interval] [count]
 #
 # Copyright (c) 2015 Brendan Gregg.
 # Licensed under the Apache License, Version 2.0 (the "License")
@@ -12,6 +12,7 @@
 # 20-Oct-2015   Brendan Gregg     Created this.
 # 03-Apr-2017   Sasha Goldshtein  Migrated to kernel tracepoints.
 # 07-Mar-2022   Rocky Xing        Added CPU filter support.
+# 24-Mar-2022   Rocky Xing        Added event counting support.
 
 from __future__ import print_function
 from bcc import BPF
@@ -22,6 +23,7 @@
 # arguments
 examples = """examples:
     ./softirqs            # sum soft irq event time
+    ./softirqs -C         # show the number of soft irq events
     ./softirqs -d         # show soft irq event time as histograms
     ./softirqs 1 10       # print 1 second summaries, 10 times
     ./softirqs -NT 1      # 1s summaries, nanoseconds, and timestamps
@@ -35,6 +37,8 @@
     help="include timestamp on output")
 parser.add_argument("-N", "--nanoseconds", action="store_true",
     help="output in nanoseconds")
+parser.add_argument("-C", "--events", action="store_true",
+    help="show the number of soft irq events")
 parser.add_argument("-d", "--dist", action="store_true",
     help="show distributions as histograms")
 parser.add_argument("-c", "--cpu", type=int,
@@ -47,7 +51,13 @@
     help=argparse.SUPPRESS)
 args = parser.parse_args()
 countdown = int(args.count)
-if args.nanoseconds:
+if args.events and (args.dist or args.nanoseconds):
+    print("The --events option can't be used with time-based options")
+    exit()
+if args.events:
+    factor = 1
+    label = "count"
+elif args.nanoseconds:
     factor = 1
     label = "nsecs"
 else:
@@ -76,7 +86,25 @@
 
 BPF_HASH(start, entry_key_t, account_val_t);
 BPF_HISTOGRAM(dist, irq_key_t);
+"""
 
+bpf_text_count = """
+TRACEPOINT_PROBE(irq, softirq_entry)
+{
+    u32 cpu = bpf_get_smp_processor_id();
+
+    FILTER_CPU
+
+    irq_key_t key = { .slot = 0 /* ignore */ };
+    key.vec = args->vec;
+
+    dist.atomic_increment(key);
+
+    return 0;
+}
+"""
+
+bpf_text_time = """
 TRACEPOINT_PROBE(irq, softirq_entry)
 {
     account_val_t val = {};
@@ -125,6 +153,11 @@
 }
 """
 
+if args.events:
+    bpf_text += bpf_text_count
+else:
+    bpf_text += bpf_text_time
+
 # code substitutions
 if args.dist:
     bpf_text = bpf_text.replace('STORE',
@@ -153,7 +186,10 @@
     return ["hi", "timer", "net_tx", "net_rx", "block", "irq_poll",
             "tasklet", "sched", "hrtimer", "rcu"][vec]
 
-print("Tracing soft irq event time... Hit Ctrl-C to end.")
+if args.events:
+    print("Tracing soft irq events... Hit Ctrl-C to end.")
+else:
+    print("Tracing soft irq event time... Hit Ctrl-C to end.")
 
 # output
 exiting = 0 if args.interval else 1
diff --git a/tools/softirqs_example.txt b/tools/softirqs_example.txt
index ef3174a..a914143 100644
--- a/tools/softirqs_example.txt
+++ b/tools/softirqs_example.txt
@@ -179,12 +179,27 @@
      16384 -> 32767      : 24       |**                                      |
 
 
+Sometimes you just want counts of events, and don't need the distribution
+of times. You can use the -C or --events option:
+
+# ./softirqs.py -C
+Tracing soft irq events... Hit Ctrl-C to end.
+^C
+SOFTIRQ          TOTAL_count
+block                      5
+tasklet                    6
+net_rx                   402
+sched                   5251
+rcu                     5748
+timer                   9530
+
+
 USAGE message:
 
 # ./softirqs -h
-usage: softirqs [-h] [-T] [-N] [-d] [interval] [count]
+usage: softirqs [-h] [-T] [-N] [-C] [-d] [-c CPU] [interval] [count]
 
-Summarize soft irq event time as histograms
+Summarize soft irq event time as histograms.
 
 positional arguments:
   interval           output interval, in seconds
@@ -194,10 +209,15 @@
   -h, --help         show this help message and exit
   -T, --timestamp    include timestamp on output
   -N, --nanoseconds  output in nanoseconds
+  -C, --events       show the number of soft irq events
   -d, --dist         show distributions as histograms
+  -c CPU, --cpu CPU  trace this CPU only
 
 examples:
     ./softirqs            # sum soft irq event time
+    ./softirqs -C         # show the number of soft irq events
     ./softirqs -d         # show soft irq event time as histograms
     ./softirqs 1 10       # print 1 second summaries, 10 times
     ./softirqs -NT 1      # 1s summaries, nanoseconds, and timestamps
+    ./softirqs -c 1       # sum soft irq event time on CPU 1 only
+