aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/scripts
diff options
context:
space:
mode:
authorMichal Marek <mmarek@suse.cz>2011-03-09 10:15:44 -0500
committerMichal Marek <mmarek@suse.cz>2011-03-09 10:15:44 -0500
commit2d8ad8719591fa803b0d589ed057fa46f49b7155 (patch)
tree4ae051577dad1161c91dafbf4207bb10a9dc91bb /tools/perf/scripts
parent9b4ce7bce5f30712fd926ab4599a803314a07719 (diff)
parentc56eb8fb6dccb83d9fe62fd4dc00c834de9bc470 (diff)
Merge commit 'v2.6.38-rc1' into kbuild/packaging
Diffstat (limited to 'tools/perf/scripts')
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Context.c7
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Context.xs5
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/README4
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm2
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm4
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm12
-rw-r--r--tools/perf/scripts/perl/bin/check-perf-trace-record7
-rw-r--r--tools/perf/scripts/perl/bin/check-perf-trace-report6
-rw-r--r--tools/perf/scripts/perl/bin/failed-syscalls-record2
-rw-r--r--tools/perf/scripts/perl/bin/failed-syscalls-report10
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-file-record3
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-file-report11
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-pid-record2
-rw-r--r--tools/perf/scripts/perl/bin/rw-by-pid-report5
-rw-r--r--tools/perf/scripts/perl/bin/rwtop-record2
-rw-r--r--tools/perf/scripts/perl/bin/rwtop-report20
-rw-r--r--tools/perf/scripts/perl/bin/wakeup-latency-record2
-rw-r--r--tools/perf/scripts/perl/bin/wakeup-latency-report5
-rw-r--r--tools/perf/scripts/perl/bin/workqueue-stats-record2
-rw-r--r--tools/perf/scripts/perl/bin/workqueue-stats-report6
-rw-r--r--tools/perf/scripts/perl/check-perf-trace.pl2
-rw-r--r--tools/perf/scripts/perl/failed-syscalls.pl42
-rw-r--r--tools/perf/scripts/perl/rw-by-file.pl2
-rw-r--r--tools/perf/scripts/perl/rw-by-pid.pl60
-rw-r--r--tools/perf/scripts/perl/rwtop.pl199
-rw-r--r--tools/perf/scripts/perl/wakeup-latency.pl12
-rw-r--r--tools/perf/scripts/perl/workqueue-stats.pl14
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/Context.c88
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py121
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py184
-rw-r--r--tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py86
-rw-r--r--tools/perf/scripts/python/bin/failed-syscalls-by-pid-record2
-rw-r--r--tools/perf/scripts/python/bin/failed-syscalls-by-pid-report10
-rw-r--r--tools/perf/scripts/python/bin/futex-contention-record2
-rw-r--r--tools/perf/scripts/python/bin/futex-contention-report4
-rw-r--r--tools/perf/scripts/python/bin/netdev-times-record8
-rw-r--r--tools/perf/scripts/python/bin/netdev-times-report5
-rw-r--r--tools/perf/scripts/python/bin/sched-migration-record2
-rw-r--r--tools/perf/scripts/python/bin/sched-migration-report3
-rw-r--r--tools/perf/scripts/python/bin/sctop-record2
-rw-r--r--tools/perf/scripts/python/bin/sctop-report24
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-by-pid-record2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-by-pid-report10
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-record2
-rw-r--r--tools/perf/scripts/python/bin/syscall-counts-report10
-rw-r--r--tools/perf/scripts/python/check-perf-trace.py82
-rw-r--r--tools/perf/scripts/python/failed-syscalls-by-pid.py73
-rw-r--r--tools/perf/scripts/python/futex-contention.py50
-rw-r--r--tools/perf/scripts/python/netdev-times.py464
-rw-r--r--tools/perf/scripts/python/sched-migration.py461
-rw-r--r--tools/perf/scripts/python/sctop.py75
-rw-r--r--tools/perf/scripts/python/syscall-counts-by-pid.py69
-rw-r--r--tools/perf/scripts/python/syscall-counts.py59
53 files changed, 2264 insertions, 82 deletions
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
index af78d9a52a7..790ceba6ad3 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.c
@@ -8,7 +8,7 @@
8 8
9#line 1 "Context.xs" 9#line 1 "Context.xs"
10/* 10/*
11 * Context.xs. XS interfaces for perf trace. 11 * Context.xs. XS interfaces for perf script.
12 * 12 *
13 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com> 13 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
14 * 14 *
@@ -31,13 +31,14 @@
31#include "EXTERN.h" 31#include "EXTERN.h"
32#include "perl.h" 32#include "perl.h"
33#include "XSUB.h" 33#include "XSUB.h"
34#include "../../../util/trace-event-perl.h" 34#include "../../../perf.h"
35#include "../../../util/trace-event.h"
35 36
36#ifndef PERL_UNUSED_VAR 37#ifndef PERL_UNUSED_VAR
37# define PERL_UNUSED_VAR(var) if (0) var = var 38# define PERL_UNUSED_VAR(var) if (0) var = var
38#endif 39#endif
39 40
40#line 41 "Context.c" 41#line 42 "Context.c"
41 42
42XS(XS_Perf__Trace__Context_common_pc); /* prototype to pass -Wmissing-prototypes */ 43XS(XS_Perf__Trace__Context_common_pc); /* prototype to pass -Wmissing-prototypes */
43XS(XS_Perf__Trace__Context_common_pc) 44XS(XS_Perf__Trace__Context_common_pc)
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
index fb78006c165..c1e2ed1ed34 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Context.xs
@@ -1,5 +1,5 @@
1/* 1/*
2 * Context.xs. XS interfaces for perf trace. 2 * Context.xs. XS interfaces for perf script.
3 * 3 *
4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com> 4 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
5 * 5 *
@@ -22,7 +22,8 @@
22#include "EXTERN.h" 22#include "EXTERN.h"
23#include "perl.h" 23#include "perl.h"
24#include "XSUB.h" 24#include "XSUB.h"
25#include "../../../util/trace-event-perl.h" 25#include "../../../perf.h"
26#include "../../../util/script-event.h"
26 27
27MODULE = Perf::Trace::Context PACKAGE = Perf::Trace::Context 28MODULE = Perf::Trace::Context PACKAGE = Perf::Trace::Context
28PROTOTYPES: ENABLE 29PROTOTYPES: ENABLE
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/README b/tools/perf/scripts/perl/Perf-Trace-Util/README
index 9a970763079..2f0c7f3043e 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/README
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/README
@@ -1,7 +1,7 @@
1Perf-Trace-Util version 0.01 1Perf-Trace-Util version 0.01
2============================ 2============================
3 3
4This module contains utility functions for use with perf trace. 4This module contains utility functions for use with perf script.
5 5
6Core.pm and Util.pm are pure Perl modules; Core.pm contains routines 6Core.pm and Util.pm are pure Perl modules; Core.pm contains routines
7that the core perf support for Perl calls on and should always be 7that the core perf support for Perl calls on and should always be
@@ -33,7 +33,7 @@ After you do that:
33 33
34INSTALLATION 34INSTALLATION
35 35
36Building perf with perf trace Perl scripting should install this 36Building perf with perf script Perl scripting should install this
37module in the right place. 37module in the right place.
38 38
39You should make sure libperl and ExtUtils/Embed.pm are installed first 39You should make sure libperl and ExtUtils/Embed.pm are installed first
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
index 6c7f3659cb1..4e2f6039ac9 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Context.pm
@@ -34,7 +34,7 @@ Perf::Trace::Context - Perl extension for accessing functions in perf.
34 34
35=head1 SEE ALSO 35=head1 SEE ALSO
36 36
37Perf (trace) documentation 37Perf (script) documentation
38 38
39=head1 AUTHOR 39=head1 AUTHOR
40 40
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
index 9df376a9f62..9158458d3ee 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Core.pm
@@ -163,7 +163,7 @@ sub dump_symbolic_fields
163__END__ 163__END__
164=head1 NAME 164=head1 NAME
165 165
166Perf::Trace::Core - Perl extension for perf trace 166Perf::Trace::Core - Perl extension for perf script
167 167
168=head1 SYNOPSIS 168=head1 SYNOPSIS
169 169
@@ -171,7 +171,7 @@ Perf::Trace::Core - Perl extension for perf trace
171 171
172=head1 SEE ALSO 172=head1 SEE ALSO
173 173
174Perf (trace) documentation 174Perf (script) documentation
175 175
176=head1 AUTHOR 176=head1 AUTHOR
177 177
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
index 052f132ced2..05350011462 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/lib/Perf/Trace/Util.pm
@@ -15,6 +15,7 @@ our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
15 15
16our @EXPORT = qw( 16our @EXPORT = qw(
17avg nsecs nsecs_secs nsecs_nsecs nsecs_usecs print_nsecs 17avg nsecs nsecs_secs nsecs_nsecs nsecs_usecs print_nsecs
18clear_term
18); 19);
19 20
20our $VERSION = '0.01'; 21our $VERSION = '0.01';
@@ -44,7 +45,7 @@ sub nsecs_secs {
44sub nsecs_nsecs { 45sub nsecs_nsecs {
45 my ($nsecs) = @_; 46 my ($nsecs) = @_;
46 47
47 return $nsecs - nsecs_secs($nsecs); 48 return $nsecs % $NSECS_PER_SEC;
48} 49}
49 50
50sub nsecs_str { 51sub nsecs_str {
@@ -55,11 +56,16 @@ sub nsecs_str {
55 return $str; 56 return $str;
56} 57}
57 58
59sub clear_term
60{
61 print "\x1b[H\x1b[2J";
62}
63
581; 641;
59__END__ 65__END__
60=head1 NAME 66=head1 NAME
61 67
62Perf::Trace::Util - Perl extension for perf trace 68Perf::Trace::Util - Perl extension for perf script
63 69
64=head1 SYNOPSIS 70=head1 SYNOPSIS
65 71
@@ -67,7 +73,7 @@ Perf::Trace::Util - Perl extension for perf trace
67 73
68=head1 SEE ALSO 74=head1 SEE ALSO
69 75
70Perf (trace) documentation 76Perf (script) documentation
71 77
72=head1 AUTHOR 78=head1 AUTHOR
73 79
diff --git a/tools/perf/scripts/perl/bin/check-perf-trace-record b/tools/perf/scripts/perl/bin/check-perf-trace-record
index c7ec5de2f53..423ad6aed05 100644
--- a/tools/perf/scripts/perl/bin/check-perf-trace-record
+++ b/tools/perf/scripts/perl/bin/check-perf-trace-record
@@ -1,7 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e kmem:kmalloc -e irq:softirq_entry 2perf record -a -e kmem:kmalloc -e irq:softirq_entry -e kmem:kfree
3
4
5
6
7
diff --git a/tools/perf/scripts/perl/bin/check-perf-trace-report b/tools/perf/scripts/perl/bin/check-perf-trace-report
deleted file mode 100644
index 7fc4a033dd4..00000000000
--- a/tools/perf/scripts/perl/bin/check-perf-trace-report
+++ /dev/null
@@ -1,6 +0,0 @@
1#!/bin/bash
2# description: useless but exhaustive test script
3perf trace -s ~/libexec/perf-core/scripts/perl/check-perf-trace.pl
4
5
6
diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-record b/tools/perf/scripts/perl/bin/failed-syscalls-record
new file mode 100644
index 00000000000..8104895a7b6
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/failed-syscalls-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -e raw_syscalls:sys_exit $@
diff --git a/tools/perf/scripts/perl/bin/failed-syscalls-report b/tools/perf/scripts/perl/bin/failed-syscalls-report
new file mode 100644
index 00000000000..9f83cc1ad8b
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/failed-syscalls-report
@@ -0,0 +1,10 @@
1#!/bin/bash
2# description: system-wide failed syscalls
3# args: [comm]
4if [ $# -gt 0 ] ; then
5 if ! expr match "$1" "-" > /dev/null ; then
6 comm=$1
7 shift
8 fi
9fi
10perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/failed-syscalls.pl $comm
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-record b/tools/perf/scripts/perl/bin/rw-by-file-record
index b25056ebf96..33efc8673aa 100644
--- a/tools/perf/scripts/perl/bin/rw-by-file-record
+++ b/tools/perf/scripts/perl/bin/rw-by-file-record
@@ -1,2 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_enter_write 2perf record -e syscalls:sys_enter_read -e syscalls:sys_enter_write $@
3
diff --git a/tools/perf/scripts/perl/bin/rw-by-file-report b/tools/perf/scripts/perl/bin/rw-by-file-report
index eddb9ccce6a..77200b3f310 100644
--- a/tools/perf/scripts/perl/bin/rw-by-file-report
+++ b/tools/perf/scripts/perl/bin/rw-by-file-report
@@ -1,7 +1,10 @@
1#!/bin/bash 1#!/bin/bash
2# description: r/w activity for a program, by file 2# description: r/w activity for a program, by file
3# args: <comm> 3# args: <comm>
4perf trace -s ~/libexec/perf-core/scripts/perl/rw-by-file.pl $1 4if [ $# -lt 1 ] ; then
5 5 echo "usage: rw-by-file <comm>"
6 6 exit
7 7fi
8comm=$1
9shift
10perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-file.pl $comm
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-record b/tools/perf/scripts/perl/bin/rw-by-pid-record
index 8903979c5b6..7cb9db23044 100644
--- a/tools/perf/scripts/perl/bin/rw-by-pid-record
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write 2perf record -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
diff --git a/tools/perf/scripts/perl/bin/rw-by-pid-report b/tools/perf/scripts/perl/bin/rw-by-pid-report
index 7f44c25cc85..a27b9f311f9 100644
--- a/tools/perf/scripts/perl/bin/rw-by-pid-report
+++ b/tools/perf/scripts/perl/bin/rw-by-pid-report
@@ -1,6 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide r/w activity 2# description: system-wide r/w activity
3perf trace -s ~/libexec/perf-core/scripts/perl/rw-by-pid.pl 3perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rw-by-pid.pl
4
5
6
diff --git a/tools/perf/scripts/perl/bin/rwtop-record b/tools/perf/scripts/perl/bin/rwtop-record
new file mode 100644
index 00000000000..7cb9db23044
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/rwtop-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -e syscalls:sys_enter_read -e syscalls:sys_exit_read -e syscalls:sys_enter_write -e syscalls:sys_exit_write $@
diff --git a/tools/perf/scripts/perl/bin/rwtop-report b/tools/perf/scripts/perl/bin/rwtop-report
new file mode 100644
index 00000000000..83e11ec2e19
--- /dev/null
+++ b/tools/perf/scripts/perl/bin/rwtop-report
@@ -0,0 +1,20 @@
1#!/bin/bash
2# description: system-wide r/w top
3# args: [interval]
4n_args=0
5for i in "$@"
6do
7 if expr match "$i" "-" > /dev/null ; then
8 break
9 fi
10 n_args=$(( $n_args + 1 ))
11done
12if [ "$n_args" -gt 1 ] ; then
13 echo "usage: rwtop-report [interval]"
14 exit
15fi
16if [ "$n_args" -gt 0 ] ; then
17 interval=$1
18 shift
19fi
20perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/rwtop.pl $interval
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-record b/tools/perf/scripts/perl/bin/wakeup-latency-record
index 6abedda911a..464251a1bd7 100644
--- a/tools/perf/scripts/perl/bin/wakeup-latency-record
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-record
@@ -1,5 +1,5 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e sched:sched_switch -e sched:sched_wakeup 2perf record -e sched:sched_switch -e sched:sched_wakeup $@
3 3
4 4
5 5
diff --git a/tools/perf/scripts/perl/bin/wakeup-latency-report b/tools/perf/scripts/perl/bin/wakeup-latency-report
index fce3adcb324..889e8130cca 100644
--- a/tools/perf/scripts/perl/bin/wakeup-latency-report
+++ b/tools/perf/scripts/perl/bin/wakeup-latency-report
@@ -1,6 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2# description: system-wide min/max/avg wakeup latency 2# description: system-wide min/max/avg wakeup latency
3perf trace -s ~/libexec/perf-core/scripts/perl/wakeup-latency.pl 3perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/wakeup-latency.pl
4
5
6
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-record b/tools/perf/scripts/perl/bin/workqueue-stats-record
index fce6637b19b..8edda9078d5 100644
--- a/tools/perf/scripts/perl/bin/workqueue-stats-record
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-record
@@ -1,2 +1,2 @@
1#!/bin/bash 1#!/bin/bash
2perf record -c 1 -f -a -M -R -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion 2perf record -e workqueue:workqueue_creation -e workqueue:workqueue_destruction -e workqueue:workqueue_execution -e workqueue:workqueue_insertion $@
diff --git a/tools/perf/scripts/perl/bin/workqueue-stats-report b/tools/perf/scripts/perl/bin/workqueue-stats-report
index 71cfbd182fb..6d91411d248 100644
--- a/tools/perf/scripts/perl/bin/workqueue-stats-report
+++ b/tools/perf/scripts/perl/bin/workqueue-stats-report
@@ -1,7 +1,3 @@
1#!/bin/bash 1#!/bin/bash
2# description: workqueue stats (ins/exe/create/destroy) 2# description: workqueue stats (ins/exe/create/destroy)
3perf trace -s ~/libexec/perf-core/scripts/perl/workqueue-stats.pl 3perf script $@ -s "$PERF_EXEC_PATH"/scripts/perl/workqueue-stats.pl
4
5
6
7
diff --git a/tools/perf/scripts/perl/check-perf-trace.pl b/tools/perf/scripts/perl/check-perf-trace.pl
index 4e7dc0a407a..4e7076c2061 100644
--- a/tools/perf/scripts/perl/check-perf-trace.pl
+++ b/tools/perf/scripts/perl/check-perf-trace.pl
@@ -1,4 +1,4 @@
1# perf trace event handlers, generated by perf trace -g perl 1# perf script event handlers, generated by perf script -g perl
2# (c) 2009, Tom Zanussi <tzanussi@gmail.com> 2# (c) 2009, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2 3# Licensed under the terms of the GNU GPL License version 2
4 4
diff --git a/tools/perf/scripts/perl/failed-syscalls.pl b/tools/perf/scripts/perl/failed-syscalls.pl
new file mode 100644
index 00000000000..94bc25a347e
--- /dev/null
+++ b/tools/perf/scripts/perl/failed-syscalls.pl
@@ -0,0 +1,42 @@
1# failed system call counts
2# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4#
5# Displays system-wide failed system call totals
6# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
7
8use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
9use lib "./Perf-Trace-Util/lib";
10use Perf::Trace::Core;
11use Perf::Trace::Context;
12use Perf::Trace::Util;
13
14my $for_comm = shift;
15
16my %failed_syscalls;
17
18sub raw_syscalls::sys_exit
19{
20 my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
21 $common_pid, $common_comm,
22 $id, $ret) = @_;
23
24 if ($ret < 0) {
25 $failed_syscalls{$common_comm}++;
26 }
27}
28
29sub trace_end
30{
31 printf("\nfailed syscalls by comm:\n\n");
32
33 printf("%-20s %10s\n", "comm", "# errors");
34 printf("%-20s %6s %10s\n", "--------------------", "----------");
35
36 foreach my $comm (sort {$failed_syscalls{$b} <=> $failed_syscalls{$a}}
37 keys %failed_syscalls) {
38 next if ($for_comm && $comm ne $for_comm);
39
40 printf("%-20s %10s\n", $comm, $failed_syscalls{$comm});
41 }
42}
diff --git a/tools/perf/scripts/perl/rw-by-file.pl b/tools/perf/scripts/perl/rw-by-file.pl
index 2a39097687b..74844ee2be3 100644
--- a/tools/perf/scripts/perl/rw-by-file.pl
+++ b/tools/perf/scripts/perl/rw-by-file.pl
@@ -18,7 +18,7 @@ use lib "./Perf-Trace-Util/lib";
18use Perf::Trace::Core; 18use Perf::Trace::Core;
19use Perf::Trace::Util; 19use Perf::Trace::Util;
20 20
21my $usage = "perf trace -s rw-by-file.pl <comm>\n"; 21my $usage = "perf script -s rw-by-file.pl <comm>\n";
22 22
23my $for_comm = shift or die $usage; 23my $for_comm = shift or die $usage;
24 24
diff --git a/tools/perf/scripts/perl/rw-by-pid.pl b/tools/perf/scripts/perl/rw-by-pid.pl
index da601fae1a0..9db23c9daf5 100644
--- a/tools/perf/scripts/perl/rw-by-pid.pl
+++ b/tools/perf/scripts/perl/rw-by-pid.pl
@@ -79,12 +79,12 @@ sub trace_end
79 printf("%6s %-20s %10s %10s %10s\n", "------", "--------------------", 79 printf("%6s %-20s %10s %10s %10s\n", "------", "--------------------",
80 "-----------", "----------", "----------"); 80 "-----------", "----------", "----------");
81 81
82 foreach my $pid (sort {$reads{$b}{bytes_read} <=> 82 foreach my $pid (sort { ($reads{$b}{bytes_read} || 0) <=>
83 $reads{$a}{bytes_read}} keys %reads) { 83 ($reads{$a}{bytes_read} || 0) } keys %reads) {
84 my $comm = $reads{$pid}{comm}; 84 my $comm = $reads{$pid}{comm} || "";
85 my $total_reads = $reads{$pid}{total_reads}; 85 my $total_reads = $reads{$pid}{total_reads} || 0;
86 my $bytes_requested = $reads{$pid}{bytes_requested}; 86 my $bytes_requested = $reads{$pid}{bytes_requested} || 0;
87 my $bytes_read = $reads{$pid}{bytes_read}; 87 my $bytes_read = $reads{$pid}{bytes_read} || 0;
88 88
89 printf("%6s %-20s %10s %10s %10s\n", $pid, $comm, 89 printf("%6s %-20s %10s %10s %10s\n", $pid, $comm,
90 $total_reads, $bytes_requested, $bytes_read); 90 $total_reads, $bytes_requested, $bytes_read);
@@ -96,16 +96,23 @@ sub trace_end
96 printf("%6s %20s %6s %10s\n", "------", "--------------------", 96 printf("%6s %20s %6s %10s\n", "------", "--------------------",
97 "------", "----------"); 97 "------", "----------");
98 98
99 foreach my $pid (keys %reads) { 99 my @errcounts = ();
100 my $comm = $reads{$pid}{comm};
101 foreach my $err (sort {$reads{$b}{comm} cmp $reads{$a}{comm}}
102 keys %{$reads{$pid}{errors}}) {
103 my $errors = $reads{$pid}{errors}{$err};
104 100
105 printf("%6d %-20s %6d %10s\n", $pid, $comm, $err, $errors); 101 foreach my $pid (keys %reads) {
102 foreach my $error (keys %{$reads{$pid}{errors}}) {
103 my $comm = $reads{$pid}{comm} || "";
104 my $errcount = $reads{$pid}{errors}{$error} || 0;
105 push @errcounts, [$pid, $comm, $error, $errcount];
106 } 106 }
107 } 107 }
108 108
109 @errcounts = sort { $b->[3] <=> $a->[3] } @errcounts;
110
111 for my $i (0 .. $#errcounts) {
112 printf("%6d %-20s %6d %10s\n", $errcounts[$i][0],
113 $errcounts[$i][1], $errcounts[$i][2], $errcounts[$i][3]);
114 }
115
109 printf("\nwrite counts by pid:\n\n"); 116 printf("\nwrite counts by pid:\n\n");
110 117
111 printf("%6s %20s %10s %10s\n", "pid", "comm", 118 printf("%6s %20s %10s %10s\n", "pid", "comm",
@@ -113,11 +120,11 @@ sub trace_end
113 printf("%6s %-20s %10s %10s\n", "------", "--------------------", 120 printf("%6s %-20s %10s %10s\n", "------", "--------------------",
114 "-----------", "----------"); 121 "-----------", "----------");
115 122
116 foreach my $pid (sort {$writes{$b}{bytes_written} <=> 123 foreach my $pid (sort { ($writes{$b}{bytes_written} || 0) <=>
117 $writes{$a}{bytes_written}} keys %writes) { 124 ($writes{$a}{bytes_written} || 0)} keys %writes) {
118 my $comm = $writes{$pid}{comm}; 125 my $comm = $writes{$pid}{comm} || "";
119 my $total_writes = $writes{$pid}{total_writes}; 126 my $total_writes = $writes{$pid}{total_writes} || 0;
120 my $bytes_written = $writes{$pid}{bytes_written}; 127 my $bytes_written = $writes{$pid}{bytes_written} || 0;
121 128
122 printf("%6s %-20s %10s %10s\n", $pid, $comm, 129 printf("%6s %-20s %10s %10s\n", $pid, $comm,
123 $total_writes, $bytes_written); 130 $total_writes, $bytes_written);
@@ -129,16 +136,23 @@ sub trace_end
129 printf("%6s %20s %6s %10s\n", "------", "--------------------", 136 printf("%6s %20s %6s %10s\n", "------", "--------------------",
130 "------", "----------"); 137 "------", "----------");
131 138
132 foreach my $pid (keys %writes) { 139 @errcounts = ();
133 my $comm = $writes{$pid}{comm};
134 foreach my $err (sort {$writes{$b}{comm} cmp $writes{$a}{comm}}
135 keys %{$writes{$pid}{errors}}) {
136 my $errors = $writes{$pid}{errors}{$err};
137 140
138 printf("%6d %-20s %6d %10s\n", $pid, $comm, $err, $errors); 141 foreach my $pid (keys %writes) {
142 foreach my $error (keys %{$writes{$pid}{errors}}) {
143 my $comm = $writes{$pid}{comm} || "";
144 my $errcount = $writes{$pid}{errors}{$error} || 0;
145 push @errcounts, [$pid, $comm, $error, $errcount];
139 } 146 }
140 } 147 }
141 148
149 @errcounts = sort { $b->[3] <=> $a->[3] } @errcounts;
150
151 for my $i (0 .. $#errcounts) {
152 printf("%6d %-20s %6d %10s\n", $errcounts[$i][0],
153 $errcounts[$i][1], $errcounts[$i][2], $errcounts[$i][3]);
154 }
155
142 print_unhandled(); 156 print_unhandled();
143} 157}
144 158
diff --git a/tools/perf/scripts/perl/rwtop.pl b/tools/perf/scripts/perl/rwtop.pl
new file mode 100644
index 00000000000..4bb3ecd3347
--- /dev/null
+++ b/tools/perf/scripts/perl/rwtop.pl
@@ -0,0 +1,199 @@
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
12use 5.010000;
13use strict;
14use warnings;
15
16use lib "$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
17use lib "./Perf-Trace-Util/lib";
18use Perf::Trace::Core;
19use Perf::Trace::Util;
20
21my $default_interval = 3;
22my $nlines = 20;
23my $print_thread;
24my $print_pending = 0;
25
26my %reads;
27my %writes;
28
29my $interval = shift;
30if (!$interval) {
31 $interval = $default_interval;
32}
33
34sub 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
52sub 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
65sub 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
78sub 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
91sub trace_begin
92{
93 $SIG{ALRM} = \&set_print_pending;
94 alarm 1;
95}
96
97sub trace_end
98{
99 print_unhandled();
100 print_totals();
101}
102
103sub print_check()
104{
105 if ($print_pending == 1) {
106 $print_pending = 0;
107 print_totals();
108 }
109}
110
111sub set_print_pending()
112{
113 $print_pending = 1;
114 alarm $interval;
115}
116
117sub 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
174my %unhandled;
175
176sub 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
193sub 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}
diff --git a/tools/perf/scripts/perl/wakeup-latency.pl b/tools/perf/scripts/perl/wakeup-latency.pl
index ed58ef284e2..d9143dcec6c 100644
--- a/tools/perf/scripts/perl/wakeup-latency.pl
+++ b/tools/perf/scripts/perl/wakeup-latency.pl
@@ -22,8 +22,8 @@ my %last_wakeup;
22 22
23my $max_wakeup_latency; 23my $max_wakeup_latency;
24my $min_wakeup_latency; 24my $min_wakeup_latency;
25my $total_wakeup_latency; 25my $total_wakeup_latency = 0;
26my $total_wakeups; 26my $total_wakeups = 0;
27 27
28sub sched::sched_switch 28sub sched::sched_switch
29{ 29{
@@ -67,8 +67,12 @@ sub trace_end
67{ 67{
68 printf("wakeup_latency stats:\n\n"); 68 printf("wakeup_latency stats:\n\n");
69 print "total_wakeups: $total_wakeups\n"; 69 print "total_wakeups: $total_wakeups\n";
70 printf("avg_wakeup_latency (ns): %u\n", 70 if ($total_wakeups) {
71 avg($total_wakeup_latency, $total_wakeups)); 71 printf("avg_wakeup_latency (ns): %u\n",
72 avg($total_wakeup_latency, $total_wakeups));
73 } else {
74 printf("avg_wakeup_latency (ns): N/A\n");
75 }
72 printf("min_wakeup_latency (ns): %u\n", $min_wakeup_latency); 76 printf("min_wakeup_latency (ns): %u\n", $min_wakeup_latency);
73 printf("max_wakeup_latency (ns): %u\n", $max_wakeup_latency); 77 printf("max_wakeup_latency (ns): %u\n", $max_wakeup_latency);
74 78
diff --git a/tools/perf/scripts/perl/workqueue-stats.pl b/tools/perf/scripts/perl/workqueue-stats.pl
index 511302c8a49..a8eaff5119e 100644
--- a/tools/perf/scripts/perl/workqueue-stats.pl
+++ b/tools/perf/scripts/perl/workqueue-stats.pl
@@ -10,7 +10,7 @@
10# workqueue:workqueue_destruction -e workqueue:workqueue_execution 10# workqueue:workqueue_destruction -e workqueue:workqueue_execution
11# -e workqueue:workqueue_insertion 11# -e workqueue:workqueue_insertion
12# 12#
13# perf trace -p -s tools/perf/scripts/perl/workqueue-stats.pl 13# perf script -p -s tools/perf/scripts/perl/workqueue-stats.pl
14 14
15use 5.010000; 15use 5.010000;
16use strict; 16use strict;
@@ -71,9 +71,9 @@ sub trace_end
71 printf("%3s %6s %6s\t%-20s\n", "---", "---", "----", "----"); 71 printf("%3s %6s %6s\t%-20s\n", "---", "---", "----", "----");
72 foreach my $pidhash (@cpus) { 72 foreach my $pidhash (@cpus) {
73 while ((my $pid, my $wqhash) = each %$pidhash) { 73 while ((my $pid, my $wqhash) = each %$pidhash) {
74 my $ins = $$wqhash{'inserted'}; 74 my $ins = $$wqhash{'inserted'} || 0;
75 my $exe = $$wqhash{'executed'}; 75 my $exe = $$wqhash{'executed'} || 0;
76 my $comm = $$wqhash{'comm'}; 76 my $comm = $$wqhash{'comm'} || "";
77 if ($ins || $exe) { 77 if ($ins || $exe) {
78 printf("%3u %6u %6u\t%-20s\n", $cpu, $ins, $exe, $comm); 78 printf("%3u %6u %6u\t%-20s\n", $cpu, $ins, $exe, $comm);
79 } 79 }
@@ -87,9 +87,9 @@ sub trace_end
87 printf("%3s %6s %6s\t%-20s\n", "---", "-------", "---------", "----"); 87 printf("%3s %6s %6s\t%-20s\n", "---", "-------", "---------", "----");
88 foreach my $pidhash (@cpus) { 88 foreach my $pidhash (@cpus) {
89 while ((my $pid, my $wqhash) = each %$pidhash) { 89 while ((my $pid, my $wqhash) = each %$pidhash) {
90 my $created = $$wqhash{'created'}; 90 my $created = $$wqhash{'created'} || 0;
91 my $destroyed = $$wqhash{'destroyed'}; 91 my $destroyed = $$wqhash{'destroyed'} || 0;
92 my $comm = $$wqhash{'comm'}; 92 my $comm = $$wqhash{'comm'} || "";
93 if ($created || $destroyed) { 93 if ($created || $destroyed) {
94 printf("%3u %6u %6u\t%-20s\n", $cpu, $created, $destroyed, 94 printf("%3u %6u %6u\t%-20s\n", $cpu, $created, $destroyed,
95 $comm); 95 $comm);
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
new file mode 100644
index 00000000000..315067b8f55
--- /dev/null
+++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c
@@ -0,0 +1,88 @@
1/*
2 * Context.c. Python interfaces for perf script.
3 *
4 * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <Python.h>
23#include "../../../perf.h"
24#include "../../../util/trace-event.h"
25
26PyMODINIT_FUNC initperf_trace_context(void);
27
28static PyObject *perf_trace_context_common_pc(PyObject *self, PyObject *args)
29{
30 static struct scripting_context *scripting_context;
31 PyObject *context;
32 int retval;
33
34 if (!PyArg_ParseTuple(args, "O", &context))
35 return NULL;
36
37 scripting_context = PyCObject_AsVoidPtr(context);
38 retval = common_pc(scripting_context);
39
40 return Py_BuildValue("i", retval);
41}
42
43static PyObject *perf_trace_context_common_flags(PyObject *self,
44 PyObject *args)
45{
46 static struct scripting_context *scripting_context;
47 PyObject *context;
48 int retval;
49
50 if (!PyArg_ParseTuple(args, "O", &context))
51 return NULL;
52
53 scripting_context = PyCObject_AsVoidPtr(context);
54 retval = common_flags(scripting_context);
55
56 return Py_BuildValue("i", retval);
57}
58
59static PyObject *perf_trace_context_common_lock_depth(PyObject *self,
60 PyObject *args)
61{
62 static struct scripting_context *scripting_context;
63 PyObject *context;
64 int retval;
65
66 if (!PyArg_ParseTuple(args, "O", &context))
67 return NULL;
68
69 scripting_context = PyCObject_AsVoidPtr(context);
70 retval = common_lock_depth(scripting_context);
71
72 return Py_BuildValue("i", retval);
73}
74
75static PyMethodDef ContextMethods[] = {
76 { "common_pc", perf_trace_context_common_pc, METH_VARARGS,
77 "Get the common preempt count event field value."},
78 { "common_flags", perf_trace_context_common_flags, METH_VARARGS,
79 "Get the common flags event field value."},
80 { "common_lock_depth", perf_trace_context_common_lock_depth,
81 METH_VARARGS, "Get the common lock depth event field value."},
82 { NULL, NULL, 0, NULL}
83};
84
85PyMODINIT_FUNC initperf_trace_context(void)
86{
87 (void) Py_InitModule("perf_trace_context", ContextMethods);
88}
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
new file mode 100644
index 00000000000..de7211e4fa4
--- /dev/null
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py
@@ -0,0 +1,121 @@
1# Core.py - Python extension for perf script, core functions
2#
3# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com>
4#
5# This software may be distributed under the terms of the GNU General
6# Public License ("GPL") version 2 as published by the Free Software
7# Foundation.
8
9from collections import defaultdict
10
11def autodict():
12 return defaultdict(autodict)
13
14flag_fields = autodict()
15symbolic_fields = autodict()
16
17def define_flag_field(event_name, field_name, delim):
18 flag_fields[event_name][field_name]['delim'] = delim
19
20def define_flag_value(event_name, field_name, value, field_str):
21 flag_fields[event_name][field_name]['values'][value] = field_str
22
23def define_symbolic_field(event_name, field_name):
24 # nothing to do, really
25 pass
26
27def define_symbolic_value(event_name, field_name, value, field_str):
28 symbolic_fields[event_name][field_name]['values'][value] = field_str
29
30def flag_str(event_name, field_name, value):
31 string = ""
32
33 if flag_fields[event_name][field_name]:
34 print_delim = 0
35 keys = flag_fields[event_name][field_name]['values'].keys()
36 keys.sort()
37 for idx in keys:
38 if not value and not idx:
39 string += flag_fields[event_name][field_name]['values'][idx]
40 break
41 if idx and (value & idx) == idx:
42 if print_delim and flag_fields[event_name][field_name]['delim']:
43 string += " " + flag_fields[event_name][field_name]['delim'] + " "
44 string += flag_fields[event_name][field_name]['values'][idx]
45 print_delim = 1
46 value &= ~idx
47
48 return string
49
50def symbol_str(event_name, field_name, value):
51 string = ""
52
53 if symbolic_fields[event_name][field_name]:
54 keys = symbolic_fields[event_name][field_name]['values'].keys()
55 keys.sort()
56 for idx in keys:
57 if not value and not idx:
58 string = symbolic_fields[event_name][field_name]['values'][idx]
59 break
60 if (value == idx):
61 string = symbolic_fields[event_name][field_name]['values'][idx]
62 break
63
64 return string
65
66trace_flags = { 0x00: "NONE", \
67 0x01: "IRQS_OFF", \
68 0x02: "IRQS_NOSUPPORT", \
69 0x04: "NEED_RESCHED", \
70 0x08: "HARDIRQ", \
71 0x10: "SOFTIRQ" }
72
73def trace_flag_str(value):
74 string = ""
75 print_delim = 0
76
77 keys = trace_flags.keys()
78
79 for idx in keys:
80 if not value and not idx:
81 string += "NONE"
82 break
83
84 if idx and (value & idx) == idx:
85 if print_delim:
86 string += " | ";
87 string += trace_flags[idx]
88 print_delim = 1
89 value &= ~idx
90
91 return string
92
93
94def taskState(state):
95 states = {
96 0 : "R",
97 1 : "S",
98 2 : "D",
99 64: "DEAD"
100 }
101
102 if state not in states:
103 return "Unknown"
104
105 return states[state]
106
107
108class EventHeaders:
109 def __init__(self, common_cpu, common_secs, common_nsecs,
110 common_pid, common_comm):
111 self.cpu = common_cpu
112 self.secs = common_secs
113 self.nsecs = common_nsecs
114 self.pid = common_pid
115 self.comm = common_comm
116
117 def ts(self):
118 return (self.secs * (10 ** 9)) + self.nsecs
119
120 def ts_format(self):
121 return "%d.%d" % (self.secs, int(self.nsecs / 1000))
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
new file mode 100644
index 00000000000..fdd92f69905
--- /dev/null
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py
@@ -0,0 +1,184 @@
1# SchedGui.py - Python extension for perf script, basic GUI code for
2# traces drawing and overview.
3#
4# Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com>
5#
6# This software is distributed under the terms of the GNU General
7# Public License ("GPL") version 2 as published by the Free Software
8# Foundation.
9
10
11try:
12 import wx
13except ImportError:
14 raise ImportError, "You need to install the wxpython lib for this script"
15
16
17class RootFrame(wx.Frame):
18 Y_OFFSET = 100
19 RECT_HEIGHT = 100
20 RECT_SPACE = 50
21 EVENT_MARKING_WIDTH = 5
22
23 def __init__(self, sched_tracer, title, parent = None, id = -1):
24 wx.Frame.__init__(self, parent, id, title)
25
26 (self.screen_width, self.screen_height) = wx.GetDisplaySize()
27 self.screen_width -= 10
28 self.screen_height -= 10
29 self.zoom = 0.5
30 self.scroll_scale = 20
31 self.sched_tracer = sched_tracer
32 self.sched_tracer.set_root_win(self)
33 (self.ts_start, self.ts_end) = sched_tracer.interval()
34 self.update_width_virtual()
35 self.nr_rects = sched_tracer.nr_rectangles() + 1
36 self.height_virtual = RootFrame.Y_OFFSET + (self.nr_rects * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
37
38 # whole window panel
39 self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height))
40
41 # scrollable container
42 self.scroll = wx.ScrolledWindow(self.panel)
43 self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale)
44 self.scroll.EnableScrolling(True, True)
45 self.scroll.SetFocus()
46
47 # scrollable drawing area
48 self.scroll_panel = wx.Panel(self.scroll, size=(self.screen_width - 15, self.screen_height / 2))
49 self.scroll_panel.Bind(wx.EVT_PAINT, self.on_paint)
50 self.scroll_panel.Bind(wx.EVT_KEY_DOWN, self.on_key_press)
51 self.scroll_panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
52 self.scroll.Bind(wx.EVT_PAINT, self.on_paint)
53 self.scroll.Bind(wx.EVT_KEY_DOWN, self.on_key_press)
54 self.scroll.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down)
55
56 self.scroll.Fit()
57 self.Fit()
58
59 self.scroll_panel.SetDimensions(-1, -1, self.width_virtual, self.height_virtual, wx.SIZE_USE_EXISTING)
60
61 self.txt = None
62
63 self.Show(True)
64
65 def us_to_px(self, val):
66 return val / (10 ** 3) * self.zoom
67
68 def px_to_us(self, val):
69 return (val / self.zoom) * (10 ** 3)
70
71 def scroll_start(self):
72 (x, y) = self.scroll.GetViewStart()
73 return (x * self.scroll_scale, y * self.scroll_scale)
74
75 def scroll_start_us(self):
76 (x, y) = self.scroll_start()
77 return self.px_to_us(x)
78
79 def paint_rectangle_zone(self, nr, color, top_color, start, end):
80 offset_px = self.us_to_px(start - self.ts_start)
81 width_px = self.us_to_px(end - self.ts_start)
82
83 offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE))
84 width_py = RootFrame.RECT_HEIGHT
85
86 dc = self.dc
87
88 if top_color is not None:
89 (r, g, b) = top_color
90 top_color = wx.Colour(r, g, b)
91 brush = wx.Brush(top_color, wx.SOLID)
92 dc.SetBrush(brush)
93 dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH)
94 width_py -= RootFrame.EVENT_MARKING_WIDTH
95 offset_py += RootFrame.EVENT_MARKING_WIDTH
96
97 (r ,g, b) = color
98 color = wx.Colour(r, g, b)
99 brush = wx.Brush(color, wx.SOLID)
100 dc.SetBrush(brush)
101 dc.DrawRectangle(offset_px, offset_py, width_px, width_py)
102
103 def update_rectangles(self, dc, start, end):
104 start += self.ts_start
105 end += self.ts_start
106 self.sched_tracer.fill_zone(start, end)
107
108 def on_paint(self, event):
109 dc = wx.PaintDC(self.scroll_panel)
110 self.dc = dc
111
112 width = min(self.width_virtual, self.screen_width)
113 (x, y) = self.scroll_start()
114 start = self.px_to_us(x)
115 end = self.px_to_us(x + width)
116 self.update_rectangles(dc, start, end)
117
118 def rect_from_ypixel(self, y):
119 y -= RootFrame.Y_OFFSET
120 rect = y / (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)
121 height = y % (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)
122
123 if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT:
124 return -1
125
126 return rect
127
128 def update_summary(self, txt):
129 if self.txt:
130 self.txt.Destroy()
131 self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50))
132
133
134 def on_mouse_down(self, event):
135 (x, y) = event.GetPositionTuple()
136 rect = self.rect_from_ypixel(y)
137 if rect == -1:
138 return
139
140 t = self.px_to_us(x) + self.ts_start
141
142 self.sched_tracer.mouse_down(rect, t)
143
144
145 def update_width_virtual(self):
146 self.width_virtual = self.us_to_px(self.ts_end - self.ts_start)
147
148 def __zoom(self, x):
149 self.update_width_virtual()
150 (xpos, ypos) = self.scroll.GetViewStart()
151 xpos = self.us_to_px(x) / self.scroll_scale
152 self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale, xpos, ypos)
153 self.Refresh()
154
155 def zoom_in(self):
156 x = self.scroll_start_us()
157 self.zoom *= 2
158 self.__zoom(x)
159
160 def zoom_out(self):
161 x = self.scroll_start_us()
162 self.zoom /= 2
163 self.__zoom(x)
164
165
166 def on_key_press(self, event):
167 key = event.GetRawKeyCode()
168 if key == ord("+"):
169 self.zoom_in()
170 return
171 if key == ord("-"):
172 self.zoom_out()
173 return
174
175 key = event.GetKeyCode()
176 (x, y) = self.scroll.GetViewStart()
177 if key == wx.WXK_RIGHT:
178 self.scroll.Scroll(x + 1, y)
179 elif key == wx.WXK_LEFT:
180 self.scroll.Scroll(x - 1, y)
181 elif key == wx.WXK_DOWN:
182 self.scroll.Scroll(x, y + 1)
183 elif key == wx.WXK_UP:
184 self.scroll.Scroll(x, y - 1)
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
new file mode 100644
index 00000000000..15c8400240f
--- /dev/null
+++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
@@ -0,0 +1,86 @@
1# Util.py - Python extension for perf script, miscellaneous utility code
2#
3# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com>
4#
5# This software may be distributed under the terms of the GNU General
6# Public License ("GPL") version 2 as published by the Free Software
7# Foundation.
8
9import errno, os
10
11FUTEX_WAIT = 0
12FUTEX_WAKE = 1
13FUTEX_PRIVATE_FLAG = 128
14FUTEX_CLOCK_REALTIME = 256
15FUTEX_CMD_MASK = ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
16
17NSECS_PER_SEC = 1000000000
18
19def avg(total, n):
20 return total / n
21
22def nsecs(secs, nsecs):
23 return secs * NSECS_PER_SEC + nsecs
24
25def nsecs_secs(nsecs):
26 return nsecs / NSECS_PER_SEC
27
28def nsecs_nsecs(nsecs):
29 return nsecs % NSECS_PER_SEC
30
31def nsecs_str(nsecs):
32 str = "%5u.%09u" % (nsecs_secs(nsecs), nsecs_nsecs(nsecs)),
33 return str
34
35def add_stats(dict, key, value):
36 if not dict.has_key(key):
37 dict[key] = (value, value, value, 1)
38 else:
39 min, max, avg, count = dict[key]
40 if value < min:
41 min = value
42 if value > max:
43 max = value
44 avg = (avg + value) / 2
45 dict[key] = (min, max, avg, count + 1)
46
47def clear_term():
48 print("\x1b[H\x1b[2J")
49
50audit_package_warned = False
51
52try:
53 import audit
54 machine_to_id = {
55 'x86_64': audit.MACH_86_64,
56 'alpha' : audit.MACH_ALPHA,
57 'ia64' : audit.MACH_IA64,
58 'ppc' : audit.MACH_PPC,
59 'ppc64' : audit.MACH_PPC64,
60 's390' : audit.MACH_S390,
61 's390x' : audit.MACH_S390X,
62 'i386' : audit.MACH_X86,
63 'i586' : audit.MACH_X86,
64 'i686' : audit.MACH_X86,
65 }
66 try:
67 machine_to_id['armeb'] = audit.MACH_ARMEB
68 except:
69 pass
70 machine_id = machine_to_id[os.uname()[4]]
71except:
72 if not audit_package_warned:
73 audit_package_warned = True
74 print "Install the audit-libs-python package to get syscall names"
75
76def syscall_name(id):
77 try:
78 return audit.audit_syscall_to_name(id, machine_id)
79 except:
80 return str(id)
81
82def strerror(nr):
83 try:
84 return errno.errorcode[abs(nr)]
85 except:
86 return "Unknown %d errno" % nr
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
new file mode 100644
index 00000000000..8104895a7b6
--- /dev/null
+++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -e raw_syscalls:sys_exit $@
diff --git a/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
new file mode 100644
index 00000000000..fda5096d0cb
--- /dev/null
+++ b/tools/perf/scripts/python/bin/failed-syscalls-by-pid-report
@@ -0,0 +1,10 @@
1#!/bin/bash
2# description: system-wide failed syscalls, by pid
3# args: [comm]
4if [ $# -gt 0 ] ; then
5 if ! expr match "$1" "-" > /dev/null ; then
6 comm=$1
7 shift
8 fi
9fi
10perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/failed-syscalls-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/futex-contention-record b/tools/perf/scripts/python/bin/futex-contention-record
new file mode 100644
index 00000000000..b1495c9a9b2
--- /dev/null
+++ b/tools/perf/scripts/python/bin/futex-contention-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex $@
diff --git a/tools/perf/scripts/python/bin/futex-contention-report b/tools/perf/scripts/python/bin/futex-contention-report
new file mode 100644
index 00000000000..6c44271091a
--- /dev/null
+++ b/tools/perf/scripts/python/bin/futex-contention-report
@@ -0,0 +1,4 @@
1#!/bin/bash
2# description: futext contention measurement
3
4perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/futex-contention.py
diff --git a/tools/perf/scripts/python/bin/netdev-times-record b/tools/perf/scripts/python/bin/netdev-times-record
new file mode 100644
index 00000000000..558754b840a
--- /dev/null
+++ b/tools/perf/scripts/python/bin/netdev-times-record
@@ -0,0 +1,8 @@
1#!/bin/bash
2perf record -e net:net_dev_xmit -e net:net_dev_queue \
3 -e net:netif_receive_skb -e net:netif_rx \
4 -e skb:consume_skb -e skb:kfree_skb \
5 -e skb:skb_copy_datagram_iovec -e napi:napi_poll \
6 -e irq:irq_handler_entry -e irq:irq_handler_exit \
7 -e irq:softirq_entry -e irq:softirq_exit \
8 -e irq:softirq_raise $@
diff --git a/tools/perf/scripts/python/bin/netdev-times-report b/tools/perf/scripts/python/bin/netdev-times-report
new file mode 100644
index 00000000000..8f759291da8
--- /dev/null
+++ b/tools/perf/scripts/python/bin/netdev-times-report
@@ -0,0 +1,5 @@
1#!/bin/bash
2# description: display a process of packet and processing time
3# args: [tx] [rx] [dev=] [debug]
4
5perf script -s "$PERF_EXEC_PATH"/scripts/python/netdev-times.py $@
diff --git a/tools/perf/scripts/python/bin/sched-migration-record b/tools/perf/scripts/python/bin/sched-migration-record
new file mode 100644
index 00000000000..7493fddbe99
--- /dev/null
+++ b/tools/perf/scripts/python/bin/sched-migration-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -m 16384 -e sched:sched_wakeup -e sched:sched_wakeup_new -e sched:sched_switch -e sched:sched_migrate_task $@
diff --git a/tools/perf/scripts/python/bin/sched-migration-report b/tools/perf/scripts/python/bin/sched-migration-report
new file mode 100644
index 00000000000..68b037a1849
--- /dev/null
+++ b/tools/perf/scripts/python/bin/sched-migration-report
@@ -0,0 +1,3 @@
1#!/bin/bash
2# description: sched migration overview
3perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/sched-migration.py
diff --git a/tools/perf/scripts/python/bin/sctop-record b/tools/perf/scripts/python/bin/sctop-record
new file mode 100644
index 00000000000..4efbfaa7f6a
--- /dev/null
+++ b/tools/perf/scripts/python/bin/sctop-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/sctop-report b/tools/perf/scripts/python/bin/sctop-report
new file mode 100644
index 00000000000..c32db294124
--- /dev/null
+++ b/tools/perf/scripts/python/bin/sctop-report
@@ -0,0 +1,24 @@
1#!/bin/bash
2# description: syscall top
3# args: [comm] [interval]
4n_args=0
5for i in "$@"
6do
7 if expr match "$i" "-" > /dev/null ; then
8 break
9 fi
10 n_args=$(( $n_args + 1 ))
11done
12if [ "$n_args" -gt 2 ] ; then
13 echo "usage: sctop-report [comm] [interval]"
14 exit
15fi
16if [ "$n_args" -gt 1 ] ; then
17 comm=$1
18 interval=$2
19 shift 2
20elif [ "$n_args" -gt 0 ] ; then
21 interval=$1
22 shift
23fi
24perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/sctop.py $comm $interval
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-record b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
new file mode 100644
index 00000000000..4efbfaa7f6a
--- /dev/null
+++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/syscall-counts-by-pid-report b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
new file mode 100644
index 00000000000..16eb8d65c54
--- /dev/null
+++ b/tools/perf/scripts/python/bin/syscall-counts-by-pid-report
@@ -0,0 +1,10 @@
1#!/bin/bash
2# description: system-wide syscall counts, by pid
3# args: [comm]
4if [ $# -gt 0 ] ; then
5 if ! expr match "$1" "-" > /dev/null ; then
6 comm=$1
7 shift
8 fi
9fi
10perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts-by-pid.py $comm
diff --git a/tools/perf/scripts/python/bin/syscall-counts-record b/tools/perf/scripts/python/bin/syscall-counts-record
new file mode 100644
index 00000000000..4efbfaa7f6a
--- /dev/null
+++ b/tools/perf/scripts/python/bin/syscall-counts-record
@@ -0,0 +1,2 @@
1#!/bin/bash
2perf record -e raw_syscalls:sys_enter $@
diff --git a/tools/perf/scripts/python/bin/syscall-counts-report b/tools/perf/scripts/python/bin/syscall-counts-report
new file mode 100644
index 00000000000..0f0e9d453bb
--- /dev/null
+++ b/tools/perf/scripts/python/bin/syscall-counts-report
@@ -0,0 +1,10 @@
1#!/bin/bash
2# description: system-wide syscall counts
3# args: [comm]
4if [ $# -gt 0 ] ; then
5 if ! expr match "$1" "-" > /dev/null ; then
6 comm=$1
7 shift
8 fi
9fi
10perf script $@ -s "$PERF_EXEC_PATH"/scripts/python/syscall-counts.py $comm
diff --git a/tools/perf/scripts/python/check-perf-trace.py b/tools/perf/scripts/python/check-perf-trace.py
new file mode 100644
index 00000000000..4647a7694cf
--- /dev/null
+++ b/tools/perf/scripts/python/check-perf-trace.py
@@ -0,0 +1,82 @@
1# perf script event handlers, generated by perf script -g python
2# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4#
5# This script tests basic functionality such as flag and symbol
6# strings, common_xxx() calls back into perf, begin, end, unhandled
7# events, etc. Basically, if this script runs successfully and
8# displays expected results, Python scripting support should be ok.
9
10import os
11import sys
12
13sys.path.append(os.environ['PERF_EXEC_PATH'] + \
14 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
15
16from Core import *
17from perf_trace_context import *
18
19unhandled = autodict()
20
21def trace_begin():
22 print "trace_begin"
23 pass
24
25def trace_end():
26 print_unhandled()
27
28def irq__softirq_entry(event_name, context, common_cpu,
29 common_secs, common_nsecs, common_pid, common_comm,
30 vec):
31 print_header(event_name, common_cpu, common_secs, common_nsecs,
32 common_pid, common_comm)
33
34 print_uncommon(context)
35
36 print "vec=%s\n" % \
37 (symbol_str("irq__softirq_entry", "vec", vec)),
38
39def kmem__kmalloc(event_name, context, common_cpu,
40 common_secs, common_nsecs, common_pid, common_comm,
41 call_site, ptr, bytes_req, bytes_alloc,
42 gfp_flags):
43 print_header(event_name, common_cpu, common_secs, common_nsecs,
44 common_pid, common_comm)
45
46 print_uncommon(context)
47
48 print "call_site=%u, ptr=%u, bytes_req=%u, " \
49 "bytes_alloc=%u, gfp_flags=%s\n" % \
50 (call_site, ptr, bytes_req, bytes_alloc,
51
52 flag_str("kmem__kmalloc", "gfp_flags", gfp_flags)),
53
54def trace_unhandled(event_name, context, event_fields_dict):
55 try:
56 unhandled[event_name] += 1
57 except TypeError:
58 unhandled[event_name] = 1
59
60def print_header(event_name, cpu, secs, nsecs, pid, comm):
61 print "%-20s %5u %05u.%09u %8u %-20s " % \
62 (event_name, cpu, secs, nsecs, pid, comm),
63
64# print trace fields not included in handler args
65def print_uncommon(context):
66 print "common_preempt_count=%d, common_flags=%s, common_lock_depth=%d, " \
67 % (common_pc(context), trace_flag_str(common_flags(context)), \
68 common_lock_depth(context))
69
70def print_unhandled():
71 keys = unhandled.keys()
72 if not keys:
73 return
74
75 print "\nunhandled events:\n\n",
76
77 print "%-40s %10s\n" % ("event", "count"),
78 print "%-40s %10s\n" % ("----------------------------------------", \
79 "-----------"),
80
81 for event_name in keys:
82 print "%-40s %10d\n" % (event_name, unhandled[event_name])
diff --git a/tools/perf/scripts/python/failed-syscalls-by-pid.py b/tools/perf/scripts/python/failed-syscalls-by-pid.py
new file mode 100644
index 00000000000..85805fac411
--- /dev/null
+++ b/tools/perf/scripts/python/failed-syscalls-by-pid.py
@@ -0,0 +1,73 @@
1# failed system call counts, by pid
2# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4#
5# Displays system-wide failed system call totals, broken down by pid.
6# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
7
8import os
9import sys
10
11sys.path.append(os.environ['PERF_EXEC_PATH'] + \
12 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
13
14from perf_trace_context import *
15from Core import *
16from Util import *
17
18usage = "perf script -s syscall-counts-by-pid.py [comm|pid]\n";
19
20for_comm = None
21for_pid = None
22
23if len(sys.argv) > 2:
24 sys.exit(usage)
25
26if len(sys.argv) > 1:
27 try:
28 for_pid = int(sys.argv[1])
29 except:
30 for_comm = sys.argv[1]
31
32syscalls = autodict()
33
34def trace_begin():
35 print "Press control+C to stop and show the summary"
36
37def trace_end():
38 print_error_totals()
39
40def raw_syscalls__sys_exit(event_name, context, common_cpu,
41 common_secs, common_nsecs, common_pid, common_comm,
42 id, ret):
43 if (for_comm and common_comm != for_comm) or \
44 (for_pid and common_pid != for_pid ):
45 return
46
47 if ret < 0:
48 try:
49 syscalls[common_comm][common_pid][id][ret] += 1
50 except TypeError:
51 syscalls[common_comm][common_pid][id][ret] = 1
52
53def print_error_totals():
54 if for_comm is not None:
55 print "\nsyscall errors for %s:\n\n" % (for_comm),
56 else:
57 print "\nsyscall errors:\n\n",
58
59 print "%-30s %10s\n" % ("comm [pid]", "count"),
60 print "%-30s %10s\n" % ("------------------------------", \
61 "----------"),
62
63 comm_keys = syscalls.keys()
64 for comm in comm_keys:
65 pid_keys = syscalls[comm].keys()
66 for pid in pid_keys:
67 print "\n%s [%d]\n" % (comm, pid),
68 id_keys = syscalls[comm][pid].keys()
69 for id in id_keys:
70 print " syscall: %-16s\n" % syscall_name(id),
71 ret_keys = syscalls[comm][pid][id].keys()
72 for ret, val in sorted(syscalls[comm][pid][id].iteritems(), key = lambda(k, v): (v, k), reverse = True):
73 print " err = %-20s %10d\n" % (strerror(ret), val),
diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
new file mode 100644
index 00000000000..11e70a388d4
--- /dev/null
+++ b/tools/perf/scripts/python/futex-contention.py
@@ -0,0 +1,50 @@
1# futex contention
2# (c) 2010, Arnaldo Carvalho de Melo <acme@redhat.com>
3# Licensed under the terms of the GNU GPL License version 2
4#
5# Translation of:
6#
7# http://sourceware.org/systemtap/wiki/WSFutexContention
8#
9# to perf python scripting.
10#
11# Measures futex contention
12
13import os, sys
14sys.path.append(os.environ['PERF_EXEC_PATH'] + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
15from Util import *
16
17process_names = {}
18thread_thislock = {}
19thread_blocktime = {}
20
21lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time
22process_names = {} # long-lived pid-to-execname mapping
23
24def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
25 nr, uaddr, op, val, utime, uaddr2, val3):
26 cmd = op & FUTEX_CMD_MASK
27 if cmd != FUTEX_WAIT:
28 return # we don't care about originators of WAKE events
29
30 process_names[tid] = comm
31 thread_thislock[tid] = uaddr
32 thread_blocktime[tid] = nsecs(s, ns)
33
34def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm,
35 nr, ret):
36 if thread_blocktime.has_key(tid):
37 elapsed = nsecs(s, ns) - thread_blocktime[tid]
38 add_stats(lock_waits, (tid, thread_thislock[tid]), elapsed)
39 del thread_blocktime[tid]
40 del thread_thislock[tid]
41
42def trace_begin():
43 print "Press control+C to stop and show the summary"
44
45def trace_end():
46 for (tid, lock) in lock_waits:
47 min, max, avg, count = lock_waits[tid, lock]
48 print "%s[%d] lock %x contended %d times, %d avg ns" % \
49 (process_names[tid], tid, lock, count, avg)
50
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
new file mode 100644
index 00000000000..9aa0a32972e
--- /dev/null
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -0,0 +1,464 @@
1# Display a process of packets and processed time.
2# It helps us to investigate networking or network device.
3#
4# options
5# tx: show only tx chart
6# rx: show only rx chart
7# dev=: show only thing related to specified device
8# debug: work with debug mode. It shows buffer status.
9
10import os
11import sys
12
13sys.path.append(os.environ['PERF_EXEC_PATH'] + \
14 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
15
16from perf_trace_context import *
17from Core import *
18from Util import *
19
20all_event_list = []; # insert all tracepoint event related with this script
21irq_dic = {}; # key is cpu and value is a list which stacks irqs
22 # which raise NET_RX softirq
23net_rx_dic = {}; # key is cpu and value include time of NET_RX softirq-entry
24 # and a list which stacks receive
25receive_hunk_list = []; # a list which include a sequence of receive events
26rx_skb_list = []; # received packet list for matching
27 # skb_copy_datagram_iovec
28
29buffer_budget = 65536; # the budget of rx_skb_list, tx_queue_list and
30 # tx_xmit_list
31of_count_rx_skb_list = 0; # overflow count
32
33tx_queue_list = []; # list of packets which pass through dev_queue_xmit
34of_count_tx_queue_list = 0; # overflow count
35
36tx_xmit_list = []; # list of packets which pass through dev_hard_start_xmit
37of_count_tx_xmit_list = 0; # overflow count
38
39tx_free_list = []; # list of packets which is freed
40
41# options
42show_tx = 0;
43show_rx = 0;
44dev = 0; # store a name of device specified by option "dev="
45debug = 0;
46
47# indices of event_info tuple
48EINFO_IDX_NAME= 0
49EINFO_IDX_CONTEXT=1
50EINFO_IDX_CPU= 2
51EINFO_IDX_TIME= 3
52EINFO_IDX_PID= 4
53EINFO_IDX_COMM= 5
54
55# Calculate a time interval(msec) from src(nsec) to dst(nsec)
56def diff_msec(src, dst):
57 return (dst - src) / 1000000.0
58
59# Display a process of transmitting a packet
60def print_transmit(hunk):
61 if dev != 0 and hunk['dev'].find(dev) < 0:
62 return
63 print "%7s %5d %6d.%06dsec %12.3fmsec %12.3fmsec" % \
64 (hunk['dev'], hunk['len'],
65 nsecs_secs(hunk['queue_t']),
66 nsecs_nsecs(hunk['queue_t'])/1000,
67 diff_msec(hunk['queue_t'], hunk['xmit_t']),
68 diff_msec(hunk['xmit_t'], hunk['free_t']))
69
70# Format for displaying rx packet processing
71PF_IRQ_ENTRY= " irq_entry(+%.3fmsec irq=%d:%s)"
72PF_SOFT_ENTRY=" softirq_entry(+%.3fmsec)"
73PF_NAPI_POLL= " napi_poll_exit(+%.3fmsec %s)"
74PF_JOINT= " |"
75PF_WJOINT= " | |"
76PF_NET_RECV= " |---netif_receive_skb(+%.3fmsec skb=%x len=%d)"
77PF_NET_RX= " |---netif_rx(+%.3fmsec skb=%x)"
78PF_CPY_DGRAM= " | skb_copy_datagram_iovec(+%.3fmsec %d:%s)"
79PF_KFREE_SKB= " | kfree_skb(+%.3fmsec location=%x)"
80PF_CONS_SKB= " | consume_skb(+%.3fmsec)"
81
82# Display a process of received packets and interrputs associated with
83# a NET_RX softirq
84def print_receive(hunk):
85 show_hunk = 0
86 irq_list = hunk['irq_list']
87 cpu = irq_list[0]['cpu']
88 base_t = irq_list[0]['irq_ent_t']
89 # check if this hunk should be showed
90 if dev != 0:
91 for i in range(len(irq_list)):
92 if irq_list[i]['name'].find(dev) >= 0:
93 show_hunk = 1
94 break
95 else:
96 show_hunk = 1
97 if show_hunk == 0:
98 return
99
100 print "%d.%06dsec cpu=%d" % \
101 (nsecs_secs(base_t), nsecs_nsecs(base_t)/1000, cpu)
102 for i in range(len(irq_list)):
103 print PF_IRQ_ENTRY % \
104 (diff_msec(base_t, irq_list[i]['irq_ent_t']),
105 irq_list[i]['irq'], irq_list[i]['name'])
106 print PF_JOINT
107 irq_event_list = irq_list[i]['event_list']
108 for j in range(len(irq_event_list)):
109 irq_event = irq_event_list[j]
110 if irq_event['event'] == 'netif_rx':
111 print PF_NET_RX % \
112 (diff_msec(base_t, irq_event['time']),
113 irq_event['skbaddr'])
114 print PF_JOINT
115 print PF_SOFT_ENTRY % \
116 diff_msec(base_t, hunk['sirq_ent_t'])
117 print PF_JOINT
118 event_list = hunk['event_list']
119 for i in range(len(event_list)):
120 event = event_list[i]
121 if event['event_name'] == 'napi_poll':
122 print PF_NAPI_POLL % \
123 (diff_msec(base_t, event['event_t']), event['dev'])
124 if i == len(event_list) - 1:
125 print ""
126 else:
127 print PF_JOINT
128 else:
129 print PF_NET_RECV % \
130 (diff_msec(base_t, event['event_t']), event['skbaddr'],
131 event['len'])
132 if 'comm' in event.keys():
133 print PF_WJOINT
134 print PF_CPY_DGRAM % \
135 (diff_msec(base_t, event['comm_t']),
136 event['pid'], event['comm'])
137 elif 'handle' in event.keys():
138 print PF_WJOINT
139 if event['handle'] == "kfree_skb":
140 print PF_KFREE_SKB % \
141 (diff_msec(base_t,
142 event['comm_t']),
143 event['location'])
144 elif event['handle'] == "consume_skb":
145 print PF_CONS_SKB % \
146 diff_msec(base_t,
147 event['comm_t'])
148 print PF_JOINT
149
150def trace_begin():
151 global show_tx
152 global show_rx
153 global dev
154 global debug
155
156 for i in range(len(sys.argv)):
157 if i == 0:
158 continue
159 arg = sys.argv[i]
160 if arg == 'tx':
161 show_tx = 1
162 elif arg =='rx':
163 show_rx = 1
164 elif arg.find('dev=',0, 4) >= 0:
165 dev = arg[4:]
166 elif arg == 'debug':
167 debug = 1
168 if show_tx == 0 and show_rx == 0:
169 show_tx = 1
170 show_rx = 1
171
172def trace_end():
173 # order all events in time
174 all_event_list.sort(lambda a,b :cmp(a[EINFO_IDX_TIME],
175 b[EINFO_IDX_TIME]))
176 # process all events
177 for i in range(len(all_event_list)):
178 event_info = all_event_list[i]
179 name = event_info[EINFO_IDX_NAME]
180 if name == 'irq__softirq_exit':
181 handle_irq_softirq_exit(event_info)
182 elif name == 'irq__softirq_entry':
183 handle_irq_softirq_entry(event_info)
184 elif name == 'irq__softirq_raise':
185 handle_irq_softirq_raise(event_info)
186 elif name == 'irq__irq_handler_entry':
187 handle_irq_handler_entry(event_info)
188 elif name == 'irq__irq_handler_exit':
189 handle_irq_handler_exit(event_info)
190 elif name == 'napi__napi_poll':
191 handle_napi_poll(event_info)
192 elif name == 'net__netif_receive_skb':
193 handle_netif_receive_skb(event_info)
194 elif name == 'net__netif_rx':
195 handle_netif_rx(event_info)
196 elif name == 'skb__skb_copy_datagram_iovec':
197 handle_skb_copy_datagram_iovec(event_info)
198 elif name == 'net__net_dev_queue':
199 handle_net_dev_queue(event_info)
200 elif name == 'net__net_dev_xmit':
201 handle_net_dev_xmit(event_info)
202 elif name == 'skb__kfree_skb':
203 handle_kfree_skb(event_info)
204 elif name == 'skb__consume_skb':
205 handle_consume_skb(event_info)
206 # display receive hunks
207 if show_rx:
208 for i in range(len(receive_hunk_list)):
209 print_receive(receive_hunk_list[i])
210 # display transmit hunks
211 if show_tx:
212 print " dev len Qdisc " \
213 " netdevice free"
214 for i in range(len(tx_free_list)):
215 print_transmit(tx_free_list[i])
216 if debug:
217 print "debug buffer status"
218 print "----------------------------"
219 print "xmit Qdisc:remain:%d overflow:%d" % \
220 (len(tx_queue_list), of_count_tx_queue_list)
221 print "xmit netdevice:remain:%d overflow:%d" % \
222 (len(tx_xmit_list), of_count_tx_xmit_list)
223 print "receive:remain:%d overflow:%d" % \
224 (len(rx_skb_list), of_count_rx_skb_list)
225
226# called from perf, when it finds a correspoinding event
227def irq__softirq_entry(name, context, cpu, sec, nsec, pid, comm, vec):
228 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
229 return
230 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
231 all_event_list.append(event_info)
232
233def irq__softirq_exit(name, context, cpu, sec, nsec, pid, comm, vec):
234 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
235 return
236 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
237 all_event_list.append(event_info)
238
239def irq__softirq_raise(name, context, cpu, sec, nsec, pid, comm, vec):
240 if symbol_str("irq__softirq_entry", "vec", vec) != "NET_RX":
241 return
242 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, vec)
243 all_event_list.append(event_info)
244
245def irq__irq_handler_entry(name, context, cpu, sec, nsec, pid, comm,
246 irq, irq_name):
247 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
248 irq, irq_name)
249 all_event_list.append(event_info)
250
251def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, irq, ret):
252 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
253 all_event_list.append(event_info)
254
255def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, napi, dev_name):
256 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
257 napi, dev_name)
258 all_event_list.append(event_info)
259
260def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr,
261 skblen, dev_name):
262 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
263 skbaddr, skblen, dev_name)
264 all_event_list.append(event_info)
265
266def net__netif_rx(name, context, cpu, sec, nsec, pid, comm, skbaddr,
267 skblen, dev_name):
268 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
269 skbaddr, skblen, dev_name)
270 all_event_list.append(event_info)
271
272def net__net_dev_queue(name, context, cpu, sec, nsec, pid, comm,
273 skbaddr, skblen, dev_name):
274 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
275 skbaddr, skblen, dev_name)
276 all_event_list.append(event_info)
277
278def net__net_dev_xmit(name, context, cpu, sec, nsec, pid, comm,
279 skbaddr, skblen, rc, dev_name):
280 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
281 skbaddr, skblen, rc ,dev_name)
282 all_event_list.append(event_info)
283
284def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm,
285 skbaddr, protocol, location):
286 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
287 skbaddr, protocol, location)
288 all_event_list.append(event_info)
289
290def skb__consume_skb(name, context, cpu, sec, nsec, pid, comm, skbaddr):
291 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
292 skbaddr)
293 all_event_list.append(event_info)
294
295def skb__skb_copy_datagram_iovec(name, context, cpu, sec, nsec, pid, comm,
296 skbaddr, skblen):
297 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
298 skbaddr, skblen)
299 all_event_list.append(event_info)
300
301def handle_irq_handler_entry(event_info):
302 (name, context, cpu, time, pid, comm, irq, irq_name) = event_info
303 if cpu not in irq_dic.keys():
304 irq_dic[cpu] = []
305 irq_record = {'irq':irq, 'name':irq_name, 'cpu':cpu, 'irq_ent_t':time}
306 irq_dic[cpu].append(irq_record)
307
308def handle_irq_handler_exit(event_info):
309 (name, context, cpu, time, pid, comm, irq, ret) = event_info
310 if cpu not in irq_dic.keys():
311 return
312 irq_record = irq_dic[cpu].pop()
313 if irq != irq_record['irq']:
314 return
315 irq_record.update({'irq_ext_t':time})
316 # if an irq doesn't include NET_RX softirq, drop.
317 if 'event_list' in irq_record.keys():
318 irq_dic[cpu].append(irq_record)
319
320def handle_irq_softirq_raise(event_info):
321 (name, context, cpu, time, pid, comm, vec) = event_info
322 if cpu not in irq_dic.keys() \
323 or len(irq_dic[cpu]) == 0:
324 return
325 irq_record = irq_dic[cpu].pop()
326 if 'event_list' in irq_record.keys():
327 irq_event_list = irq_record['event_list']
328 else:
329 irq_event_list = []
330 irq_event_list.append({'time':time, 'event':'sirq_raise'})
331 irq_record.update({'event_list':irq_event_list})
332 irq_dic[cpu].append(irq_record)
333
334def handle_irq_softirq_entry(event_info):
335 (name, context, cpu, time, pid, comm, vec) = event_info
336 net_rx_dic[cpu] = {'sirq_ent_t':time, 'event_list':[]}
337
338def handle_irq_softirq_exit(event_info):
339 (name, context, cpu, time, pid, comm, vec) = event_info
340 irq_list = []
341 event_list = 0
342 if cpu in irq_dic.keys():
343 irq_list = irq_dic[cpu]
344 del irq_dic[cpu]
345 if cpu in net_rx_dic.keys():
346 sirq_ent_t = net_rx_dic[cpu]['sirq_ent_t']
347 event_list = net_rx_dic[cpu]['event_list']
348 del net_rx_dic[cpu]
349 if irq_list == [] or event_list == 0:
350 return
351 rec_data = {'sirq_ent_t':sirq_ent_t, 'sirq_ext_t':time,
352 'irq_list':irq_list, 'event_list':event_list}
353 # merge information realted to a NET_RX softirq
354 receive_hunk_list.append(rec_data)
355
356def handle_napi_poll(event_info):
357 (name, context, cpu, time, pid, comm, napi, dev_name) = event_info
358 if cpu in net_rx_dic.keys():
359 event_list = net_rx_dic[cpu]['event_list']
360 rec_data = {'event_name':'napi_poll',
361 'dev':dev_name, 'event_t':time}
362 event_list.append(rec_data)
363
364def handle_netif_rx(event_info):
365 (name, context, cpu, time, pid, comm,
366 skbaddr, skblen, dev_name) = event_info
367 if cpu not in irq_dic.keys() \
368 or len(irq_dic[cpu]) == 0:
369 return
370 irq_record = irq_dic[cpu].pop()
371 if 'event_list' in irq_record.keys():
372 irq_event_list = irq_record['event_list']
373 else:
374 irq_event_list = []
375 irq_event_list.append({'time':time, 'event':'netif_rx',
376 'skbaddr':skbaddr, 'skblen':skblen, 'dev_name':dev_name})
377 irq_record.update({'event_list':irq_event_list})
378 irq_dic[cpu].append(irq_record)
379
380def handle_netif_receive_skb(event_info):
381 global of_count_rx_skb_list
382
383 (name, context, cpu, time, pid, comm,
384 skbaddr, skblen, dev_name) = event_info
385 if cpu in net_rx_dic.keys():
386 rec_data = {'event_name':'netif_receive_skb',
387 'event_t':time, 'skbaddr':skbaddr, 'len':skblen}
388 event_list = net_rx_dic[cpu]['event_list']
389 event_list.append(rec_data)
390 rx_skb_list.insert(0, rec_data)
391 if len(rx_skb_list) > buffer_budget:
392 rx_skb_list.pop()
393 of_count_rx_skb_list += 1
394
395def handle_net_dev_queue(event_info):
396 global of_count_tx_queue_list
397
398 (name, context, cpu, time, pid, comm,
399 skbaddr, skblen, dev_name) = event_info
400 skb = {'dev':dev_name, 'skbaddr':skbaddr, 'len':skblen, 'queue_t':time}
401 tx_queue_list.insert(0, skb)
402 if len(tx_queue_list) > buffer_budget:
403 tx_queue_list.pop()
404 of_count_tx_queue_list += 1
405
406def handle_net_dev_xmit(event_info):
407 global of_count_tx_xmit_list
408
409 (name, context, cpu, time, pid, comm,
410 skbaddr, skblen, rc, dev_name) = event_info
411 if rc == 0: # NETDEV_TX_OK
412 for i in range(len(tx_queue_list)):
413 skb = tx_queue_list[i]
414 if skb['skbaddr'] == skbaddr:
415 skb['xmit_t'] = time
416 tx_xmit_list.insert(0, skb)
417 del tx_queue_list[i]
418 if len(tx_xmit_list) > buffer_budget:
419 tx_xmit_list.pop()
420 of_count_tx_xmit_list += 1
421 return
422
423def handle_kfree_skb(event_info):
424 (name, context, cpu, time, pid, comm,
425 skbaddr, protocol, location) = event_info
426 for i in range(len(tx_queue_list)):
427 skb = tx_queue_list[i]
428 if skb['skbaddr'] == skbaddr:
429 del tx_queue_list[i]
430 return
431 for i in range(len(tx_xmit_list)):
432 skb = tx_xmit_list[i]
433 if skb['skbaddr'] == skbaddr:
434 skb['free_t'] = time
435 tx_free_list.append(skb)
436 del tx_xmit_list[i]
437 return
438 for i in range(len(rx_skb_list)):
439 rec_data = rx_skb_list[i]
440 if rec_data['skbaddr'] == skbaddr:
441 rec_data.update({'handle':"kfree_skb",
442 'comm':comm, 'pid':pid, 'comm_t':time})
443 del rx_skb_list[i]
444 return
445
446def handle_consume_skb(event_info):
447 (name, context, cpu, time, pid, comm, skbaddr) = event_info
448 for i in range(len(tx_xmit_list)):
449 skb = tx_xmit_list[i]
450 if skb['skbaddr'] == skbaddr:
451 skb['free_t'] = time
452 tx_free_list.append(skb)
453 del tx_xmit_list[i]
454 return
455
456def handle_skb_copy_datagram_iovec(event_info):
457 (name, context, cpu, time, pid, comm, skbaddr, skblen) = event_info
458 for i in range(len(rx_skb_list)):
459 rec_data = rx_skb_list[i]
460 if skbaddr == rec_data['skbaddr']:
461 rec_data.update({'handle':"skb_copy_datagram_iovec",
462 'comm':comm, 'pid':pid, 'comm_t':time})
463 del rx_skb_list[i]
464 return
diff --git a/tools/perf/scripts/python/sched-migration.py b/tools/perf/scripts/python/sched-migration.py
new file mode 100644
index 00000000000..74d55ec08ae
--- /dev/null
+++ b/tools/perf/scripts/python/sched-migration.py
@@ -0,0 +1,461 @@
1#!/usr/bin/python
2#
3# Cpu task migration overview toy
4#
5# Copyright (C) 2010 Frederic Weisbecker <fweisbec@gmail.com>
6#
7# perf script event handlers have been generated by perf script -g python
8#
9# This software is distributed under the terms of the GNU General
10# Public License ("GPL") version 2 as published by the Free Software
11# Foundation.
12
13
14import os
15import sys
16
17from collections import defaultdict
18from UserList import UserList
19
20sys.path.append(os.environ['PERF_EXEC_PATH'] + \
21 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
22sys.path.append('scripts/python/Perf-Trace-Util/lib/Perf/Trace')
23
24from perf_trace_context import *
25from Core import *
26from SchedGui import *
27
28
29threads = { 0 : "idle"}
30
31def thread_name(pid):
32 return "%s:%d" % (threads[pid], pid)
33
34class RunqueueEventUnknown:
35 @staticmethod
36 def color():
37 return None
38
39 def __repr__(self):
40 return "unknown"
41
42class RunqueueEventSleep:
43 @staticmethod
44 def color():
45 return (0, 0, 0xff)
46
47 def __init__(self, sleeper):
48 self.sleeper = sleeper
49
50 def __repr__(self):
51 return "%s gone to sleep" % thread_name(self.sleeper)
52
53class RunqueueEventWakeup:
54 @staticmethod
55 def color():
56 return (0xff, 0xff, 0)
57
58 def __init__(self, wakee):
59 self.wakee = wakee
60
61 def __repr__(self):
62 return "%s woke up" % thread_name(self.wakee)
63
64class RunqueueEventFork:
65 @staticmethod
66 def color():
67 return (0, 0xff, 0)
68
69 def __init__(self, child):
70 self.child = child
71
72 def __repr__(self):
73 return "new forked task %s" % thread_name(self.child)
74
75class RunqueueMigrateIn:
76 @staticmethod
77 def color():
78 return (0, 0xf0, 0xff)
79
80 def __init__(self, new):
81 self.new = new
82
83 def __repr__(self):
84 return "task migrated in %s" % thread_name(self.new)
85
86class RunqueueMigrateOut:
87 @staticmethod
88 def color():
89 return (0xff, 0, 0xff)
90
91 def __init__(self, old):
92 self.old = old
93
94 def __repr__(self):
95 return "task migrated out %s" % thread_name(self.old)
96
97class RunqueueSnapshot:
98 def __init__(self, tasks = [0], event = RunqueueEventUnknown()):
99 self.tasks = tuple(tasks)
100 self.event = event
101
102 def sched_switch(self, prev, prev_state, next):
103 event = RunqueueEventUnknown()
104
105 if taskState(prev_state) == "R" and next in self.tasks \
106 and prev in self.tasks:
107 return self
108
109 if taskState(prev_state) != "R":
110 event = RunqueueEventSleep(prev)
111
112 next_tasks = list(self.tasks[:])
113 if prev in self.tasks:
114 if taskState(prev_state) != "R":
115 next_tasks.remove(prev)
116 elif taskState(prev_state) == "R":
117 next_tasks.append(prev)
118
119 if next not in next_tasks:
120 next_tasks.append(next)
121
122 return RunqueueSnapshot(next_tasks, event)
123
124 def migrate_out(self, old):
125 if old not in self.tasks:
126 return self
127 next_tasks = [task for task in self.tasks if task != old]
128
129 return RunqueueSnapshot(next_tasks, RunqueueMigrateOut(old))
130
131 def __migrate_in(self, new, event):
132 if new in self.tasks:
133 self.event = event
134 return self
135 next_tasks = self.tasks[:] + tuple([new])
136
137 return RunqueueSnapshot(next_tasks, event)
138
139 def migrate_in(self, new):
140 return self.__migrate_in(new, RunqueueMigrateIn(new))
141
142 def wake_up(self, new):
143 return self.__migrate_in(new, RunqueueEventWakeup(new))
144
145 def wake_up_new(self, new):
146 return self.__migrate_in(new, RunqueueEventFork(new))
147
148 def load(self):
149 """ Provide the number of tasks on the runqueue.
150 Don't count idle"""
151 return len(self.tasks) - 1
152
153 def __repr__(self):
154 ret = self.tasks.__repr__()
155 ret += self.origin_tostring()
156
157 return ret
158
159class TimeSlice:
160 def __init__(self, start, prev):
161 self.start = start
162 self.prev = prev
163 self.end = start
164 # cpus that triggered the event
165 self.event_cpus = []
166 if prev is not None:
167 self.total_load = prev.total_load
168 self.rqs = prev.rqs.copy()
169 else:
170 self.rqs = defaultdict(RunqueueSnapshot)
171 self.total_load = 0
172
173 def __update_total_load(self, old_rq, new_rq):
174 diff = new_rq.load() - old_rq.load()
175 self.total_load += diff
176
177 def sched_switch(self, ts_list, prev, prev_state, next, cpu):
178 old_rq = self.prev.rqs[cpu]
179 new_rq = old_rq.sched_switch(prev, prev_state, next)
180
181 if old_rq is new_rq:
182 return
183
184 self.rqs[cpu] = new_rq
185 self.__update_total_load(old_rq, new_rq)
186 ts_list.append(self)
187 self.event_cpus = [cpu]
188
189 def migrate(self, ts_list, new, old_cpu, new_cpu):
190 if old_cpu == new_cpu:
191 return
192 old_rq = self.prev.rqs[old_cpu]
193 out_rq = old_rq.migrate_out(new)
194 self.rqs[old_cpu] = out_rq
195 self.__update_total_load(old_rq, out_rq)
196
197 new_rq = self.prev.rqs[new_cpu]
198 in_rq = new_rq.migrate_in(new)
199 self.rqs[new_cpu] = in_rq
200 self.__update_total_load(new_rq, in_rq)
201
202 ts_list.append(self)
203
204 if old_rq is not out_rq:
205 self.event_cpus.append(old_cpu)
206 self.event_cpus.append(new_cpu)
207
208 def wake_up(self, ts_list, pid, cpu, fork):
209 old_rq = self.prev.rqs[cpu]
210 if fork:
211 new_rq = old_rq.wake_up_new(pid)
212 else:
213 new_rq = old_rq.wake_up(pid)
214
215 if new_rq is old_rq:
216 return
217 self.rqs[cpu] = new_rq
218 self.__update_total_load(old_rq, new_rq)
219 ts_list.append(self)
220 self.event_cpus = [cpu]
221
222 def next(self, t):
223 self.end = t
224 return TimeSlice(t, self)
225
226class TimeSliceList(UserList):
227 def __init__(self, arg = []):
228 self.data = arg
229
230 def get_time_slice(self, ts):
231 if len(self.data) == 0:
232 slice = TimeSlice(ts, TimeSlice(-1, None))
233 else:
234 slice = self.data[-1].next(ts)
235 return slice
236
237 def find_time_slice(self, ts):
238 start = 0
239 end = len(self.data)
240 found = -1
241 searching = True
242 while searching:
243 if start == end or start == end - 1:
244 searching = False
245
246 i = (end + start) / 2
247 if self.data[i].start <= ts and self.data[i].end >= ts:
248 found = i
249 end = i
250 continue
251
252 if self.data[i].end < ts:
253 start = i
254
255 elif self.data[i].start > ts:
256 end = i
257
258 return found
259
260 def set_root_win(self, win):
261 self.root_win = win
262
263 def mouse_down(self, cpu, t):
264 idx = self.find_time_slice(t)
265 if idx == -1:
266 return
267
268 ts = self[idx]
269 rq = ts.rqs[cpu]
270 raw = "CPU: %d\n" % cpu
271 raw += "Last event : %s\n" % rq.event.__repr__()
272 raw += "Timestamp : %d.%06d\n" % (ts.start / (10 ** 9), (ts.start % (10 ** 9)) / 1000)
273 raw += "Duration : %6d us\n" % ((ts.end - ts.start) / (10 ** 6))
274 raw += "Load = %d\n" % rq.load()
275 for t in rq.tasks:
276 raw += "%s \n" % thread_name(t)
277
278 self.root_win.update_summary(raw)
279
280 def update_rectangle_cpu(self, slice, cpu):
281 rq = slice.rqs[cpu]
282
283 if slice.total_load != 0:
284 load_rate = rq.load() / float(slice.total_load)
285 else:
286 load_rate = 0
287
288 red_power = int(0xff - (0xff * load_rate))
289 color = (0xff, red_power, red_power)
290
291 top_color = None
292
293 if cpu in slice.event_cpus:
294 top_color = rq.event.color()
295
296 self.root_win.paint_rectangle_zone(cpu, color, top_color, slice.start, slice.end)
297
298 def fill_zone(self, start, end):
299 i = self.find_time_slice(start)
300 if i == -1:
301 return
302
303 for i in xrange(i, len(self.data)):
304 timeslice = self.data[i]
305 if timeslice.start > end:
306 return
307
308 for cpu in timeslice.rqs:
309 self.update_rectangle_cpu(timeslice, cpu)
310
311 def interval(self):
312 if len(self.data) == 0:
313 return (0, 0)
314
315 return (self.data[0].start, self.data[-1].end)
316
317 def nr_rectangles(self):
318 last_ts = self.data[-1]
319 max_cpu = 0
320 for cpu in last_ts.rqs:
321 if cpu > max_cpu:
322 max_cpu = cpu
323 return max_cpu
324
325
326class SchedEventProxy:
327 def __init__(self):
328 self.current_tsk = defaultdict(lambda : -1)
329 self.timeslices = TimeSliceList()
330
331 def sched_switch(self, headers, prev_comm, prev_pid, prev_prio, prev_state,
332 next_comm, next_pid, next_prio):
333 """ Ensure the task we sched out this cpu is really the one
334 we logged. Otherwise we may have missed traces """
335
336 on_cpu_task = self.current_tsk[headers.cpu]
337
338 if on_cpu_task != -1 and on_cpu_task != prev_pid:
339 print "Sched switch event rejected ts: %s cpu: %d prev: %s(%d) next: %s(%d)" % \
340 (headers.ts_format(), headers.cpu, prev_comm, prev_pid, next_comm, next_pid)
341
342 threads[prev_pid] = prev_comm
343 threads[next_pid] = next_comm
344 self.current_tsk[headers.cpu] = next_pid
345
346 ts = self.timeslices.get_time_slice(headers.ts())
347 ts.sched_switch(self.timeslices, prev_pid, prev_state, next_pid, headers.cpu)
348
349 def migrate(self, headers, pid, prio, orig_cpu, dest_cpu):
350 ts = self.timeslices.get_time_slice(headers.ts())
351 ts.migrate(self.timeslices, pid, orig_cpu, dest_cpu)
352
353 def wake_up(self, headers, comm, pid, success, target_cpu, fork):
354 if success == 0:
355 return
356 ts = self.timeslices.get_time_slice(headers.ts())
357 ts.wake_up(self.timeslices, pid, target_cpu, fork)
358
359
360def trace_begin():
361 global parser
362 parser = SchedEventProxy()
363
364def trace_end():
365 app = wx.App(False)
366 timeslices = parser.timeslices
367 frame = RootFrame(timeslices, "Migration")
368 app.MainLoop()
369
370def sched__sched_stat_runtime(event_name, context, common_cpu,
371 common_secs, common_nsecs, common_pid, common_comm,
372 comm, pid, runtime, vruntime):
373 pass
374
375def sched__sched_stat_iowait(event_name, context, common_cpu,
376 common_secs, common_nsecs, common_pid, common_comm,
377 comm, pid, delay):
378 pass
379
380def sched__sched_stat_sleep(event_name, context, common_cpu,
381 common_secs, common_nsecs, common_pid, common_comm,
382 comm, pid, delay):
383 pass
384
385def sched__sched_stat_wait(event_name, context, common_cpu,
386 common_secs, common_nsecs, common_pid, common_comm,
387 comm, pid, delay):
388 pass
389
390def sched__sched_process_fork(event_name, context, common_cpu,
391 common_secs, common_nsecs, common_pid, common_comm,
392 parent_comm, parent_pid, child_comm, child_pid):
393 pass
394
395def sched__sched_process_wait(event_name, context, common_cpu,
396 common_secs, common_nsecs, common_pid, common_comm,
397 comm, pid, prio):
398 pass
399
400def sched__sched_process_exit(event_name, context, common_cpu,
401 common_secs, common_nsecs, common_pid, common_comm,
402 comm, pid, prio):
403 pass
404
405def sched__sched_process_free(event_name, context, common_cpu,
406 common_secs, common_nsecs, common_pid, common_comm,
407 comm, pid, prio):
408 pass
409
410def sched__sched_migrate_task(event_name, context, common_cpu,
411 common_secs, common_nsecs, common_pid, common_comm,
412 comm, pid, prio, orig_cpu,
413 dest_cpu):
414 headers = EventHeaders(common_cpu, common_secs, common_nsecs,
415 common_pid, common_comm)
416 parser.migrate(headers, pid, prio, orig_cpu, dest_cpu)
417
418def sched__sched_switch(event_name, context, common_cpu,
419 common_secs, common_nsecs, common_pid, common_comm,
420 prev_comm, prev_pid, prev_prio, prev_state,
421 next_comm, next_pid, next_prio):
422
423 headers = EventHeaders(common_cpu, common_secs, common_nsecs,
424 common_pid, common_comm)
425 parser.sched_switch(headers, prev_comm, prev_pid, prev_prio, prev_state,
426 next_comm, next_pid, next_prio)
427
428def sched__sched_wakeup_new(event_name, context, common_cpu,
429 common_secs, common_nsecs, common_pid, common_comm,
430 comm, pid, prio, success,
431 target_cpu):
432 headers = EventHeaders(common_cpu, common_secs, common_nsecs,
433 common_pid, common_comm)
434 parser.wake_up(headers, comm, pid, success, target_cpu, 1)
435
436def sched__sched_wakeup(event_name, context, common_cpu,
437 common_secs, common_nsecs, common_pid, common_comm,
438 comm, pid, prio, success,
439 target_cpu):
440 headers = EventHeaders(common_cpu, common_secs, common_nsecs,
441 common_pid, common_comm)
442 parser.wake_up(headers, comm, pid, success, target_cpu, 0)
443
444def sched__sched_wait_task(event_name, context, common_cpu,
445 common_secs, common_nsecs, common_pid, common_comm,
446 comm, pid, prio):
447 pass
448
449def sched__sched_kthread_stop_ret(event_name, context, common_cpu,
450 common_secs, common_nsecs, common_pid, common_comm,
451 ret):
452 pass
453
454def sched__sched_kthread_stop(event_name, context, common_cpu,
455 common_secs, common_nsecs, common_pid, common_comm,
456 comm, pid):
457 pass
458
459def trace_unhandled(event_name, context, common_cpu, common_secs, common_nsecs,
460 common_pid, common_comm):
461 pass
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py
new file mode 100644
index 00000000000..42c267e292f
--- /dev/null
+++ b/tools/perf/scripts/python/sctop.py
@@ -0,0 +1,75 @@
1# system call top
2# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4#
5# Periodically displays system-wide system call totals, broken down by
6# syscall. If a [comm] arg is specified, only syscalls called by
7# [comm] are displayed. If an [interval] arg is specified, the display
8# will be refreshed every [interval] seconds. The default interval is
9# 3 seconds.
10
11import os, sys, thread, time
12
13sys.path.append(os.environ['PERF_EXEC_PATH'] + \
14 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
15
16from perf_trace_context import *
17from Core import *
18from Util import *
19
20usage = "perf script -s sctop.py [comm] [interval]\n";
21
22for_comm = None
23default_interval = 3
24interval = default_interval
25
26if len(sys.argv) > 3:
27 sys.exit(usage)
28
29if len(sys.argv) > 2:
30 for_comm = sys.argv[1]
31 interval = int(sys.argv[2])
32elif len(sys.argv) > 1:
33 try:
34 interval = int(sys.argv[1])
35 except ValueError:
36 for_comm = sys.argv[1]
37 interval = default_interval
38
39syscalls = autodict()
40
41def trace_begin():
42 thread.start_new_thread(print_syscall_totals, (interval,))
43 pass
44
45def raw_syscalls__sys_enter(event_name, context, common_cpu,
46 common_secs, common_nsecs, common_pid, common_comm,
47 id, args):
48 if for_comm is not None:
49 if common_comm != for_comm:
50 return
51 try:
52 syscalls[id] += 1
53 except TypeError:
54 syscalls[id] = 1
55
56def print_syscall_totals(interval):
57 while 1:
58 clear_term()
59 if for_comm is not None:
60 print "\nsyscall events for %s:\n\n" % (for_comm),
61 else:
62 print "\nsyscall events:\n\n",
63
64 print "%-40s %10s\n" % ("event", "count"),
65 print "%-40s %10s\n" % ("----------------------------------------", \
66 "----------"),
67
68 for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \
69 reverse = True):
70 try:
71 print "%-40s %10d\n" % (syscall_name(id), val),
72 except TypeError:
73 pass
74 syscalls.clear()
75 time.sleep(interval)
diff --git a/tools/perf/scripts/python/syscall-counts-by-pid.py b/tools/perf/scripts/python/syscall-counts-by-pid.py
new file mode 100644
index 00000000000..c64d1c55d74
--- /dev/null
+++ b/tools/perf/scripts/python/syscall-counts-by-pid.py
@@ -0,0 +1,69 @@
1# system call counts, by pid
2# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4#
5# Displays system-wide system call totals, broken down by syscall.
6# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
7
8import os, sys
9
10sys.path.append(os.environ['PERF_EXEC_PATH'] + \
11 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
12
13from perf_trace_context import *
14from Core import *
15from Util import syscall_name
16
17usage = "perf script -s syscall-counts-by-pid.py [comm]\n";
18
19for_comm = None
20for_pid = None
21
22if len(sys.argv) > 2:
23 sys.exit(usage)
24
25if len(sys.argv) > 1:
26 try:
27 for_pid = int(sys.argv[1])
28 except:
29 for_comm = sys.argv[1]
30
31syscalls = autodict()
32
33def trace_begin():
34 print "Press control+C to stop and show the summary"
35
36def trace_end():
37 print_syscall_totals()
38
39def raw_syscalls__sys_enter(event_name, context, common_cpu,
40 common_secs, common_nsecs, common_pid, common_comm,
41 id, args):
42
43 if (for_comm and common_comm != for_comm) or \
44 (for_pid and common_pid != for_pid ):
45 return
46 try:
47 syscalls[common_comm][common_pid][id] += 1
48 except TypeError:
49 syscalls[common_comm][common_pid][id] = 1
50
51def print_syscall_totals():
52 if for_comm is not None:
53 print "\nsyscall events for %s:\n\n" % (for_comm),
54 else:
55 print "\nsyscall events by comm/pid:\n\n",
56
57 print "%-40s %10s\n" % ("comm [pid]/syscalls", "count"),
58 print "%-40s %10s\n" % ("----------------------------------------", \
59 "----------"),
60
61 comm_keys = syscalls.keys()
62 for comm in comm_keys:
63 pid_keys = syscalls[comm].keys()
64 for pid in pid_keys:
65 print "\n%s [%d]\n" % (comm, pid),
66 id_keys = syscalls[comm][pid].keys()
67 for id, val in sorted(syscalls[comm][pid].iteritems(), \
68 key = lambda(k, v): (v, k), reverse = True):
69 print " %-38s %10d\n" % (syscall_name(id), val),
diff --git a/tools/perf/scripts/python/syscall-counts.py b/tools/perf/scripts/python/syscall-counts.py
new file mode 100644
index 00000000000..b435d3f188e
--- /dev/null
+++ b/tools/perf/scripts/python/syscall-counts.py
@@ -0,0 +1,59 @@
1# system call counts
2# (c) 2010, Tom Zanussi <tzanussi@gmail.com>
3# Licensed under the terms of the GNU GPL License version 2
4#
5# Displays system-wide system call totals, broken down by syscall.
6# If a [comm] arg is specified, only syscalls called by [comm] are displayed.
7
8import os
9import sys
10
11sys.path.append(os.environ['PERF_EXEC_PATH'] + \
12 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
13
14from perf_trace_context import *
15from Core import *
16from Util import syscall_name
17
18usage = "perf script -s syscall-counts.py [comm]\n";
19
20for_comm = None
21
22if len(sys.argv) > 2:
23 sys.exit(usage)
24
25if len(sys.argv) > 1:
26 for_comm = sys.argv[1]
27
28syscalls = autodict()
29
30def trace_begin():
31 print "Press control+C to stop and show the summary"
32
33def trace_end():
34 print_syscall_totals()
35
36def raw_syscalls__sys_enter(event_name, context, common_cpu,
37 common_secs, common_nsecs, common_pid, common_comm,
38 id, args):
39 if for_comm is not None:
40 if common_comm != for_comm:
41 return
42 try:
43 syscalls[id] += 1
44 except TypeError:
45 syscalls[id] = 1
46
47def print_syscall_totals():
48 if for_comm is not None:
49 print "\nsyscall events for %s:\n\n" % (for_comm),
50 else:
51 print "\nsyscall events:\n\n",
52
53 print "%-40s %10s\n" % ("event", "count"),
54 print "%-40s %10s\n" % ("----------------------------------------", \
55 "-----------"),
56
57 for id, val in sorted(syscalls.iteritems(), key = lambda(k, v): (v, k), \
58 reverse = True):
59 print "%-40s %10d\n" % (syscall_name(id), val),