Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
[pandora-kernel.git] / tools / perf / scripts / perl / rwtop.pl
1 #!/usr/bin/perl -w
2 # (c) 2010, Tom Zanussi <tzanussi@gmail.com>
3 # Licensed under the terms of the GNU GPL License version 2
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
21 my $default_interval = 3;
22 my $nlines = 20;
23 my $print_thread;
24 my $print_pending = 0;
25
26 my %reads;
27 my %writes;
28
29 my $interval = shift;
30 if (!$interval) {
31     $interval = $default_interval;
32 }
33
34 sub syscalls::sys_exit_read
35 {
36     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
37         $common_pid, $common_comm,
38         $nr, $ret) = @_;
39
40     print_check();
41
42     if ($ret > 0) {
43         $reads{$common_pid}{bytes_read} += $ret;
44     } else {
45         if (!defined ($reads{$common_pid}{bytes_read})) {
46             $reads{$common_pid}{bytes_read} = 0;
47         }
48         $reads{$common_pid}{errors}{$ret}++;
49     }
50 }
51
52 sub syscalls::sys_enter_read
53 {
54     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
55         $common_pid, $common_comm,
56         $nr, $fd, $buf, $count) = @_;
57
58     print_check();
59
60     $reads{$common_pid}{bytes_requested} += $count;
61     $reads{$common_pid}{total_reads}++;
62     $reads{$common_pid}{comm} = $common_comm;
63 }
64
65 sub syscalls::sys_exit_write
66 {
67     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
68         $common_pid, $common_comm,
69         $nr, $ret) = @_;
70
71     print_check();
72
73     if ($ret <= 0) {
74         $writes{$common_pid}{errors}{$ret}++;
75     }
76 }
77
78 sub syscalls::sys_enter_write
79 {
80     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
81         $common_pid, $common_comm,
82         $nr, $fd, $buf, $count) = @_;
83
84     print_check();
85
86     $writes{$common_pid}{bytes_written} += $count;
87     $writes{$common_pid}{total_writes}++;
88     $writes{$common_pid}{comm} = $common_comm;
89 }
90
91 sub trace_begin
92 {
93     $SIG{ALRM} = \&set_print_pending;
94     alarm 1;
95 }
96
97 sub trace_end
98 {
99     print_unhandled();
100     print_totals();
101 }
102
103 sub print_check()
104 {
105     if ($print_pending == 1) {
106         $print_pending = 0;
107         print_totals();
108     }
109 }
110
111 sub set_print_pending()
112 {
113     $print_pending = 1;
114     alarm $interval;
115 }
116
117 sub print_totals
118 {
119     my $count;
120
121     $count = 0;
122
123     clear_term();
124
125     printf("\nread counts by pid:\n\n");
126
127     printf("%6s  %20s  %10s  %10s  %10s\n", "pid", "comm",
128            "# reads", "bytes_req", "bytes_read");
129     printf("%6s  %-20s  %10s  %10s  %10s\n", "------", "--------------------",
130            "----------", "----------", "----------");
131
132     foreach my $pid (sort { ($reads{$b}{bytes_read} || 0) <=>
133                                ($reads{$a}{bytes_read} || 0) } keys %reads) {
134         my $comm = $reads{$pid}{comm} || "";
135         my $total_reads = $reads{$pid}{total_reads} || 0;
136         my $bytes_requested = $reads{$pid}{bytes_requested} || 0;
137         my $bytes_read = $reads{$pid}{bytes_read} || 0;
138
139         printf("%6s  %-20s  %10s  %10s  %10s\n", $pid, $comm,
140                $total_reads, $bytes_requested, $bytes_read);
141
142         if (++$count == $nlines) {
143             last;
144         }
145     }
146
147     $count = 0;
148
149     printf("\nwrite counts by pid:\n\n");
150
151     printf("%6s  %20s  %10s  %13s\n", "pid", "comm",
152            "# writes", "bytes_written");
153     printf("%6s  %-20s  %10s  %13s\n", "------", "--------------------",
154            "----------", "-------------");
155
156     foreach my $pid (sort { ($writes{$b}{bytes_written} || 0) <=>
157                         ($writes{$a}{bytes_written} || 0)} keys %writes) {
158         my $comm = $writes{$pid}{comm} || "";
159         my $total_writes = $writes{$pid}{total_writes} || 0;
160         my $bytes_written = $writes{$pid}{bytes_written} || 0;
161
162         printf("%6s  %-20s  %10s  %13s\n", $pid, $comm,
163                $total_writes, $bytes_written);
164
165         if (++$count == $nlines) {
166             last;
167         }
168     }
169
170     %reads = ();
171     %writes = ();
172 }
173
174 my %unhandled;
175
176 sub print_unhandled
177 {
178     if ((scalar keys %unhandled) == 0) {
179         return;
180     }
181
182     print "\nunhandled events:\n\n";
183
184     printf("%-40s  %10s\n", "event", "count");
185     printf("%-40s  %10s\n", "----------------------------------------",
186            "-----------");
187
188     foreach my $event_name (keys %unhandled) {
189         printf("%-40s  %10d\n", $event_name, $unhandled{$event_name});
190     }
191 }
192
193 sub trace_unhandled
194 {
195     my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
196         $common_pid, $common_comm) = @_;
197
198     $unhandled{$event_name}++;
199 }