Merge tag 'i3c/for-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux
[sfrench/cifs-2.6.git] / tools / perf / scripts / perl / rwtop.pl
1 #!/usr/bin/perl -w
2 # SPDX-License-Identifier: GPL-2.0-only
3 # (c) 2010, Tom Zanussi <tzanussi@gmail.com>
4
5 # read/write top
6 #
7 # Periodically displays system-wide r/w call activity, broken down by
8 # pid.  If an [interval] arg is specified, the display will be
9 # refreshed every [interval] seconds.  The default interval is 3
10 # seconds.
11
12 use 5.010000;
13 use strict;
14 use warnings;
15
16 use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
17 use lib "./Perf-Trace-Util/lib";
18 use Perf::Trace::Core;
19 use Perf::Trace::Util;
20 use POSIX qw/SIGALRM SA_RESTART/;
21
22 my $default_interval = 3;
23 my $nlines = 20;
24 my $print_thread;
25 my $print_pending = 0;
26
27 my %reads;
28 my %writes;
29
30 my $interval = shift;
31 if (!$interval) {
32     $interval = $default_interval;
33 }
34
35 sub syscalls::sys_exit_read
36 {
37     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
38         $common_pid, $common_comm,
39         $nr, $ret) = @_;
40
41     print_check();
42
43     if ($ret > 0) {
44         $reads{$common_pid}{bytes_read} += $ret;
45     } else {
46         if (!defined ($reads{$common_pid}{bytes_read})) {
47             $reads{$common_pid}{bytes_read} = 0;
48         }
49         $reads{$common_pid}{errors}{$ret}++;
50     }
51 }
52
53 sub syscalls::sys_enter_read
54 {
55     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
56         $common_pid, $common_comm,
57         $nr, $fd, $buf, $count) = @_;
58
59     print_check();
60
61     $reads{$common_pid}{bytes_requested} += $count;
62     $reads{$common_pid}{total_reads}++;
63     $reads{$common_pid}{comm} = $common_comm;
64 }
65
66 sub syscalls::sys_exit_write
67 {
68     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
69         $common_pid, $common_comm,
70         $nr, $ret) = @_;
71
72     print_check();
73
74     if ($ret <= 0) {
75         $writes{$common_pid}{errors}{$ret}++;
76     }
77 }
78
79 sub syscalls::sys_enter_write
80 {
81     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
82         $common_pid, $common_comm,
83         $nr, $fd, $buf, $count) = @_;
84
85     print_check();
86
87     $writes{$common_pid}{bytes_written} += $count;
88     $writes{$common_pid}{total_writes}++;
89     $writes{$common_pid}{comm} = $common_comm;
90 }
91
92 sub trace_begin
93 {
94     my $sa = POSIX::SigAction->new(\&set_print_pending);
95     $sa->flags(SA_RESTART);
96     $sa->safe(1);
97     POSIX::sigaction(SIGALRM, $sa) or die "Can't set SIGALRM handler: $!\n";
98     alarm 1;
99 }
100
101 sub trace_end
102 {
103     print_unhandled();
104     print_totals();
105 }
106
107 sub print_check()
108 {
109     if ($print_pending == 1) {
110         $print_pending = 0;
111         print_totals();
112     }
113 }
114
115 sub set_print_pending()
116 {
117     $print_pending = 1;
118     alarm $interval;
119 }
120
121 sub print_totals
122 {
123     my $count;
124
125     $count = 0;
126
127     clear_term();
128
129     printf("\nread counts by pid:\n\n");
130
131     printf("%6s  %20s  %10s  %10s  %10s\n", "pid", "comm",
132            "# reads", "bytes_req", "bytes_read");
133     printf("%6s  %-20s  %10s  %10s  %10s\n", "------", "--------------------",
134            "----------", "----------", "----------");
135
136     foreach my $pid (sort { ($reads{$b}{bytes_read} || 0) <=>
137                                ($reads{$a}{bytes_read} || 0) } keys %reads) {
138         my $comm = $reads{$pid}{comm} || "";
139         my $total_reads = $reads{$pid}{total_reads} || 0;
140         my $bytes_requested = $reads{$pid}{bytes_requested} || 0;
141         my $bytes_read = $reads{$pid}{bytes_read} || 0;
142
143         printf("%6s  %-20s  %10s  %10s  %10s\n", $pid, $comm,
144                $total_reads, $bytes_requested, $bytes_read);
145
146         if (++$count == $nlines) {
147             last;
148         }
149     }
150
151     $count = 0;
152
153     printf("\nwrite counts by pid:\n\n");
154
155     printf("%6s  %20s  %10s  %13s\n", "pid", "comm",
156            "# writes", "bytes_written");
157     printf("%6s  %-20s  %10s  %13s\n", "------", "--------------------",
158            "----------", "-------------");
159
160     foreach my $pid (sort { ($writes{$b}{bytes_written} || 0) <=>
161                         ($writes{$a}{bytes_written} || 0)} keys %writes) {
162         my $comm = $writes{$pid}{comm} || "";
163         my $total_writes = $writes{$pid}{total_writes} || 0;
164         my $bytes_written = $writes{$pid}{bytes_written} || 0;
165
166         printf("%6s  %-20s  %10s  %13s\n", $pid, $comm,
167                $total_writes, $bytes_written);
168
169         if (++$count == $nlines) {
170             last;
171         }
172     }
173
174     %reads = ();
175     %writes = ();
176 }
177
178 my %unhandled;
179
180 sub print_unhandled
181 {
182     if ((scalar keys %unhandled) == 0) {
183         return;
184     }
185
186     print "\nunhandled events:\n\n";
187
188     printf("%-40s  %10s\n", "event", "count");
189     printf("%-40s  %10s\n", "----------------------------------------",
190            "-----------");
191
192     foreach my $event_name (keys %unhandled) {
193         printf("%-40s  %10d\n", $event_name, $unhandled{$event_name});
194     }
195 }
196
197 sub trace_unhandled
198 {
199     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
200         $common_pid, $common_comm) = @_;
201
202     $unhandled{$event_name}++;
203 }