Patches contributed by Eötvös Lorand University
commit 2d65537ee7cd4a0818ea80a97ab7932368fff5cd
Author: Ingo Molnar <mingo@elte.hu>
Date: Wed May 27 21:36:22 2009 +0200
pref_counter: tools: report: Add header printout & prettify
Old default output:
3.12% perf-report [.] ./perf-report: dsos__find
2.44% perf-report [k] kernel: kallsyms_expand_symbol
2.28% :4483 [.] <unknown>: <unknown>
2.05% :4174 [k] kernel: _spin_lock_irqsave
2.01% perf-report [k] kernel: vsnprintf
1.92% perf-report [k] kernel: format_decode
1.92% :4438 [k] kernel: _spin_lock
New default output:
#
# Overhead Command File: Symbol
# ........ ....... ............
#
6.54% perf [k] kernel: kallsyms_expand_symbol
6.26% perf [.] /home/mingo/tip/Documentation/perf_counter/perf: dso__insert_symbol
4.76% perf [.] /home/mingo/tip/Documentation/perf_counter/perf: hex2long
4.55% perf [k] kernel: number
4.48% perf [k] kernel: format_decode
4.09% perf [k] kernel: vsnprintf
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20090527182101.229504802@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 30e12c7f7108..6df95c2698c6 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -708,6 +708,7 @@ struct sort_entry {
struct list_head list;
int64_t (*cmp)(struct hist_entry *, struct hist_entry *);
+ size_t (*print_header)(FILE *fp);
size_t (*print)(FILE *fp, struct hist_entry *);
};
@@ -722,7 +723,7 @@ sort__thread_print(FILE *fp, struct hist_entry *self)
{
char bf[32];
- return fprintf(fp, "%14s ",
+ return fprintf(fp, " %16s",
thread__name(self->thread, bf, sizeof(bf)));
}
@@ -752,7 +753,7 @@ sort__comm_cmp(struct hist_entry *left, struct hist_entry *right)
static size_t
sort__comm_print(FILE *fp, struct hist_entry *self)
{
- return fprintf(fp, "%20s ", self->thread->comm ?: "<unknown>");
+ return fprintf(fp, " %16s", self->thread->comm ?: "<unknown>");
}
static struct sort_entry sort_comm = {
@@ -781,7 +782,7 @@ sort__dso_cmp(struct hist_entry *left, struct hist_entry *right)
static size_t
sort__dso_print(FILE *fp, struct hist_entry *self)
{
- return fprintf(fp, "%64s ", self->dso ? self->dso->name : "<unknown>");
+ return fprintf(fp, " %64s", self->dso ? self->dso->name : "<unknown>");
}
static struct sort_entry sort_dso = {
@@ -803,21 +804,33 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
return (int64_t)(ip_r - ip_l);
}
+static size_t sort__sym_print_header(FILE *fp)
+{
+ size_t ret = 0;
+
+ ret += fprintf(fp, "#\n");
+ ret += fprintf(fp, "# Overhead Command File: Symbol\n");
+ ret += fprintf(fp, "# ........ ....... ............\n");
+ ret += fprintf(fp, "#\n");
+
+ return ret;
+}
+
static size_t
sort__sym_print(FILE *fp, struct hist_entry *self)
{
size_t ret = 0;
- ret += fprintf(fp, "[%c] ", self->level);
+ ret += fprintf(fp, " [%c] ", self->level);
if (verbose)
- ret += fprintf(fp, "%#018llx ", (unsigned long long)self->ip);
+ ret += fprintf(fp, " %#018llx", (unsigned long long)self->ip);
if (self->level != '.')
- ret += fprintf(fp, "%s ",
+ ret += fprintf(fp, " kernel: %s",
self->sym ? self->sym->name : "<unknown>");
else
- ret += fprintf(fp, "%s: %s ",
+ ret += fprintf(fp, " %s: %s",
self->dso ? self->dso->name : "<unknown>",
self->sym ? self->sym->name : "<unknown>");
@@ -825,8 +838,9 @@ sort__sym_print(FILE *fp, struct hist_entry *self)
}
static struct sort_entry sort_sym = {
- .cmp = sort__sym_cmp,
- .print = sort__sym_print,
+ .cmp = sort__sym_cmp,
+ .print_header = sort__sym_print_header,
+ .print = sort__sym_print,
};
struct sort_dimension {
@@ -898,7 +912,7 @@ hist_entry__fprintf(FILE *fp, struct hist_entry *self, uint64_t total_samples)
size_t ret;
if (total_samples) {
- ret = fprintf(fp, "%5.2f%% ",
+ ret = fprintf(fp, " %5.2f%%",
(self->count * 100.0) / total_samples);
} else
ret = fprintf(fp, "%12d ", self->count);
@@ -1003,9 +1017,15 @@ static void output__resort(void)
static size_t output__fprintf(FILE *fp, uint64_t total_samples)
{
struct hist_entry *pos;
+ struct sort_entry *se;
struct rb_node *nd;
size_t ret = 0;
+ list_for_each_entry(se, &hist_entry__sort_list, list) {
+ if (se->print_header)
+ ret += se->print_header(fp);
+ }
+
for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
pos = rb_entry(nd, struct hist_entry, rb_node);
ret += hist_entry__fprintf(fp, pos, total_samples);
commit d716fba49c7445ec87c3f045c59624fac03ee3f2
Author: Ingo Molnar <mingo@elte.hu>
Date: Wed May 27 13:19:59 2009 +0200
perf report: Remove <ctype.h> include
Pekka reported build failure in builtin-report.c:
CC builtin-report.o
In file included from builtin-report.c:7:
/usr/include/ctype.h:102: error: expected expression before token
And observed:
| Removing #include <ctype.h> from builtin-report.c makes the problem
| go away. I am running Ubuntu 9.04 that has gcc 4.3.3 and libc 2.9.
Reported-by: Pekka J Enberg <penberg@cs.helsinki.fi>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 9aef7c54483e..6265bedcd937 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -4,7 +4,6 @@
#include <libelf.h>
#include <gelf.h>
#include <elf.h>
-#include <ctype.h>
#include "util/list.h"
#include "util/cache.h"
commit a930d2c0d0a685ab955472b08baad041cc5edb4a
Author: Ingo Molnar <mingo@elte.hu>
Date: Wed May 27 09:50:13 2009 +0200
perf_counter tools: Add built-in pager support
Add Git's pager.c (and sigchain) code. A command only
has to call setup_pager() to get paged interactive
output.
Non-interactive (redirected, command-piped, etc.) uses
are not affected.
Update perf-report to make use of this.
[ Impact: new feature ]
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/Makefile b/Documentation/perf_counter/Makefile
index efb05892db69..51b13f989833 100644
--- a/Documentation/perf_counter/Makefile
+++ b/Documentation/perf_counter/Makefile
@@ -297,11 +297,13 @@ LIB_H += util/util.h
LIB_H += util/help.h
LIB_H += util/strbuf.h
LIB_H += util/run-command.h
+LIB_H += util/sigchain.h
LIB_OBJS += util/abspath.o
LIB_OBJS += util/alias.o
LIB_OBJS += util/config.o
LIB_OBJS += util/ctype.o
+LIB_OBJS += util/environment.o
LIB_OBJS += util/exec_cmd.o
LIB_OBJS += util/help.o
LIB_OBJS += util/levenshtein.o
@@ -314,6 +316,8 @@ LIB_OBJS += util/quote.o
LIB_OBJS += util/strbuf.o
LIB_OBJS += util/usage.o
LIB_OBJS += util/wrapper.o
+LIB_OBJS += util/sigchain.o
+LIB_OBJS += util/pager.o
BUILTIN_OBJS += builtin-help.o
BUILTIN_OBJS += builtin-record.o
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index e2712cd06310..9aef7c54483e 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -7,6 +7,7 @@
#include <ctype.h>
#include "util/list.h"
+#include "util/cache.h"
#include "util/rbtree.h"
#include "perf.h"
@@ -992,5 +993,7 @@ int cmd_report(int argc, const char **argv, const char *prefix)
parse_options(argc, argv, options, report_usage, 0);
+ setup_pager();
+
return __cmd_report();
}
diff --git a/Documentation/perf_counter/util/environment.c b/Documentation/perf_counter/util/environment.c
new file mode 100644
index 000000000000..9b1c8199e729
--- /dev/null
+++ b/Documentation/perf_counter/util/environment.c
@@ -0,0 +1,8 @@
+/*
+ * We put all the perf config variables in this same object
+ * file, so that programs can link against the config parser
+ * without having to link against all the rest of perf.
+ */
+#include "cache.h"
+
+const char *pager_program;
diff --git a/Documentation/perf_counter/util/pager.c b/Documentation/perf_counter/util/pager.c
new file mode 100644
index 000000000000..a28bccae5458
--- /dev/null
+++ b/Documentation/perf_counter/util/pager.c
@@ -0,0 +1,99 @@
+#include "cache.h"
+#include "run-command.h"
+#include "sigchain.h"
+
+/*
+ * This is split up from the rest of git so that we can do
+ * something different on Windows.
+ */
+
+static int spawned_pager;
+
+#ifndef __MINGW32__
+static void pager_preexec(void)
+{
+ /*
+ * Work around bug in "less" by not starting it until we
+ * have real input
+ */
+ fd_set in;
+
+ FD_ZERO(&in);
+ FD_SET(0, &in);
+ select(1, &in, NULL, &in, NULL);
+
+ setenv("LESS", "FRSX", 0);
+}
+#endif
+
+static const char *pager_argv[] = { "sh", "-c", NULL, NULL };
+static struct child_process pager_process;
+
+static void wait_for_pager(void)
+{
+ fflush(stdout);
+ fflush(stderr);
+ /* signal EOF to pager */
+ close(1);
+ close(2);
+ finish_command(&pager_process);
+}
+
+static void wait_for_pager_signal(int signo)
+{
+ wait_for_pager();
+ sigchain_pop(signo);
+ raise(signo);
+}
+
+void setup_pager(void)
+{
+ const char *pager = getenv("PERF_PAGER");
+
+ if (!isatty(1))
+ return;
+ if (!pager) {
+ if (!pager_program)
+ perf_config(perf_default_config, NULL);
+ pager = pager_program;
+ }
+ if (!pager)
+ pager = getenv("PAGER");
+ if (!pager)
+ pager = "less";
+ else if (!*pager || !strcmp(pager, "cat"))
+ return;
+
+ spawned_pager = 1; /* means we are emitting to terminal */
+
+ /* spawn the pager */
+ pager_argv[2] = pager;
+ pager_process.argv = pager_argv;
+ pager_process.in = -1;
+#ifndef __MINGW32__
+ pager_process.preexec_cb = pager_preexec;
+#endif
+ if (start_command(&pager_process))
+ return;
+
+ /* original process continues, but writes to the pipe */
+ dup2(pager_process.in, 1);
+ if (isatty(2))
+ dup2(pager_process.in, 2);
+ close(pager_process.in);
+
+ /* this makes sure that the parent terminates after the pager */
+ sigchain_push_common(wait_for_pager_signal);
+ atexit(wait_for_pager);
+}
+
+int pager_in_use(void)
+{
+ const char *env;
+
+ if (spawned_pager)
+ return 1;
+
+ env = getenv("PERF_PAGER_IN_USE");
+ return env ? perf_config_bool("PERF_PAGER_IN_USE", env) : 0;
+}
diff --git a/Documentation/perf_counter/util/sigchain.c b/Documentation/perf_counter/util/sigchain.c
new file mode 100644
index 000000000000..1118b99e57d3
--- /dev/null
+++ b/Documentation/perf_counter/util/sigchain.c
@@ -0,0 +1,52 @@
+#include "sigchain.h"
+#include "cache.h"
+
+#define SIGCHAIN_MAX_SIGNALS 32
+
+struct sigchain_signal {
+ sigchain_fun *old;
+ int n;
+ int alloc;
+};
+static struct sigchain_signal signals[SIGCHAIN_MAX_SIGNALS];
+
+static void check_signum(int sig)
+{
+ if (sig < 1 || sig >= SIGCHAIN_MAX_SIGNALS)
+ die("BUG: signal out of range: %d", sig);
+}
+
+int sigchain_push(int sig, sigchain_fun f)
+{
+ struct sigchain_signal *s = signals + sig;
+ check_signum(sig);
+
+ ALLOC_GROW(s->old, s->n + 1, s->alloc);
+ s->old[s->n] = signal(sig, f);
+ if (s->old[s->n] == SIG_ERR)
+ return -1;
+ s->n++;
+ return 0;
+}
+
+int sigchain_pop(int sig)
+{
+ struct sigchain_signal *s = signals + sig;
+ check_signum(sig);
+ if (s->n < 1)
+ return 0;
+
+ if (signal(sig, s->old[s->n - 1]) == SIG_ERR)
+ return -1;
+ s->n--;
+ return 0;
+}
+
+void sigchain_push_common(sigchain_fun f)
+{
+ sigchain_push(SIGINT, f);
+ sigchain_push(SIGHUP, f);
+ sigchain_push(SIGTERM, f);
+ sigchain_push(SIGQUIT, f);
+ sigchain_push(SIGPIPE, f);
+}
diff --git a/Documentation/perf_counter/util/sigchain.h b/Documentation/perf_counter/util/sigchain.h
new file mode 100644
index 000000000000..618083bce0c6
--- /dev/null
+++ b/Documentation/perf_counter/util/sigchain.h
@@ -0,0 +1,11 @@
+#ifndef SIGCHAIN_H
+#define SIGCHAIN_H
+
+typedef void (*sigchain_fun)(int);
+
+int sigchain_push(int sig, sigchain_fun f);
+int sigchain_pop(int sig);
+
+void sigchain_push_common(sigchain_fun f);
+
+#endif /* SIGCHAIN_H */
commit 23ac9cbed82b00ca3520bb81dbe9ea3b7a936a1b
Author: Ingo Molnar <mingo@elte.hu>
Date: Wed May 27 09:33:18 2009 +0200
perf_counter tools: Rename output.perf to perf.data
output.perf is only output to perf-record - it's input to
perf-report. So change it to a more direction-neutral name.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/Documentation/perf-record.txt b/Documentation/perf_counter/Documentation/perf-record.txt
index d07700e35eb2..353db1bb98ab 100644
--- a/Documentation/perf_counter/Documentation/perf-record.txt
+++ b/Documentation/perf_counter/Documentation/perf-record.txt
@@ -3,7 +3,7 @@ perf-record(1)
NAME
----
-perf-record - Run a command and record its profile into output.perf
+perf-record - Run a command and record its profile into perf.data
SYNOPSIS
--------
@@ -13,7 +13,7 @@ SYNOPSIS
DESCRIPTION
-----------
This command runs a command and gathers a performance counter profile
-from it, into output.perf - without displaying anything.
+from it, into perf.data - without displaying anything.
This file can then be inspected later on, using 'perf report'.
diff --git a/Documentation/perf_counter/Documentation/perf-report.txt b/Documentation/perf_counter/Documentation/perf-report.txt
index 64696a218105..49efe16c9588 100644
--- a/Documentation/perf_counter/Documentation/perf-report.txt
+++ b/Documentation/perf_counter/Documentation/perf-report.txt
@@ -3,7 +3,7 @@ perf-report(1)
NAME
----
-perf-report - Read output.perf (created by perf record) and display the profile
+perf-report - Read perf.data (created by perf record) and display the profile
SYNOPSIS
--------
@@ -19,7 +19,7 @@ OPTIONS
-------
-i::
--input=::
- Input file name. (default: output.perf)
+ Input file name. (default: perf.data)
Configuration
-------------
diff --git a/Documentation/perf_counter/builtin-record.c b/Documentation/perf_counter/builtin-record.c
index 68abfdf71d39..431077a6fb77 100644
--- a/Documentation/perf_counter/builtin-record.c
+++ b/Documentation/perf_counter/builtin-record.c
@@ -19,7 +19,7 @@ static int nr_cpus = 0;
static unsigned int page_size;
static unsigned int mmap_pages = 16;
static int output;
-static const char *output_name = "output.perf";
+static const char *output_name = "perf.data";
static int group = 0;
static unsigned int realtime_prio = 0;
static int system_wide = 0;
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 7f1255dcd222..e2712cd06310 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -18,7 +18,7 @@
#define SHOW_USER 2
#define SHOW_HV 4
-static char const *input_name = "output.perf";
+static char const *input_name = "perf.data";
static int input;
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
commit 16f762a2ac5ecf8a11f6f0332e46cc3459220da5
Author: Ingo Molnar <mingo@elte.hu>
Date: Wed May 27 09:10:38 2009 +0200
perf_counter tools: Introduce stricter C code checking
Tighten up our C code requirements:
- disallow warnings
- disallow declarations-mixed-with-statements
- require proper prototypes
- require C99 (with gcc extensions)
Fix up a ton of problems these measures unearth:
- unused functions
- needlessly global functions
- missing prototypes
- code mixed with declarations
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
LKML-Reference: <20090526222155.GJ4424@ghostprotocols.net>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/Makefile b/Documentation/perf_counter/Makefile
index 10c13a6f2bc9..efb05892db69 100644
--- a/Documentation/perf_counter/Makefile
+++ b/Documentation/perf_counter/Makefile
@@ -159,7 +159,7 @@ uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
# CFLAGS and LDFLAGS are for the users to override from the command line.
-CFLAGS = -ggdb3 -Wall
+CFLAGS = -ggdb3 -Wall -Werror -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -std=gnu99 -Wdeclaration-after-statement
LDFLAGS = -lpthread -lrt -lelf
ALL_CFLAGS = $(CFLAGS)
ALL_LDFLAGS = $(LDFLAGS)
diff --git a/Documentation/perf_counter/builtin-help.c b/Documentation/perf_counter/builtin-help.c
index 6616de0ef053..d2bd3177b98c 100644
--- a/Documentation/perf_counter/builtin-help.c
+++ b/Documentation/perf_counter/builtin-help.c
@@ -399,7 +399,7 @@ static void get_html_page_path(struct strbuf *page_path, const char *page)
* HTML.
*/
#ifndef open_html
-void open_html(const char *path)
+static void open_html(const char *path)
{
execl_perf_cmd("web--browse", "-c", "help.browser", path, NULL);
}
diff --git a/Documentation/perf_counter/builtin-record.c b/Documentation/perf_counter/builtin-record.c
index ec2b787b23bd..68abfdf71d39 100644
--- a/Documentation/perf_counter/builtin-record.c
+++ b/Documentation/perf_counter/builtin-record.c
@@ -1,6 +1,7 @@
#include "perf.h"
+#include "builtin.h"
#include "util/util.h"
#include "util/parse-options.h"
#include "util/parse-events.h"
@@ -144,26 +145,32 @@ static int nr_poll;
static int nr_cpu;
struct mmap_event {
- struct perf_event_header header;
- __u32 pid, tid;
- __u64 start;
- __u64 len;
- __u64 pgoff;
- char filename[PATH_MAX];
+ struct perf_event_header header;
+ __u32 pid;
+ __u32 tid;
+ __u64 start;
+ __u64 len;
+ __u64 pgoff;
+ char filename[PATH_MAX];
};
+
struct comm_event {
- struct perf_event_header header;
- __u32 pid,tid;
- char comm[16];
+ struct perf_event_header header;
+ __u32 pid;
+ __u32 tid;
+ char comm[16];
};
static pid_t pid_synthesize_comm_event(pid_t pid)
{
+ struct comm_event comm_ev;
char filename[PATH_MAX];
+ pid_t spid, ppid;
char bf[BUFSIZ];
- struct comm_event comm_ev;
+ int fd, nr, ret;
+ char comm[18];
size_t size;
- int fd;
+ char state;
snprintf(filename, sizeof(filename), "/proc/%d/stat", pid);
@@ -178,12 +185,8 @@ static pid_t pid_synthesize_comm_event(pid_t pid)
}
close(fd);
- pid_t spid, ppid;
- char state;
- char comm[18];
-
memset(&comm_ev, 0, sizeof(comm_ev));
- int nr = sscanf(bf, "%d %s %c %d %d ",
+ nr = sscanf(bf, "%d %s %c %d %d ",
&spid, comm, &state, &ppid, &comm_ev.pid);
if (nr != 5) {
fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
@@ -198,7 +201,8 @@ static pid_t pid_synthesize_comm_event(pid_t pid)
memcpy(comm_ev.comm, comm + 1, size);
size = ALIGN(size, sizeof(uint64_t));
comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
- int ret = write(output, &comm_ev, comm_ev.header.size);
+
+ ret = write(output, &comm_ev, comm_ev.header.size);
if (ret < 0) {
perror("failed to write");
exit(-1);
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 2d65d9c12aad..7f1255dcd222 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -1,4 +1,5 @@
#include "util/util.h"
+#include "builtin.h"
#include <libelf.h>
#include <gelf.h>
@@ -22,7 +23,7 @@ static int input;
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
static int dump_trace = 0;
-static int verbose;
+static int verbose;
static unsigned long page_size;
static unsigned long mmap_window = 32;
@@ -60,10 +61,10 @@ typedef union event_union {
} event_t;
struct symbol {
- struct rb_node rb_node;
- uint64_t start;
- uint64_t end;
- char name[0];
+ struct rb_node rb_node;
+ __u64 start;
+ __u64 end;
+ char name[0];
};
static struct symbol *symbol__new(uint64_t start, uint64_t len, const char *name)
@@ -86,7 +87,7 @@ static void symbol__delete(struct symbol *self)
static size_t symbol__fprintf(struct symbol *self, FILE *fp)
{
- return fprintf(fp, " %lx-%lx %s\n",
+ return fprintf(fp, " %llx-%llx %s\n",
self->start, self->end, self->name);
}
@@ -147,10 +148,12 @@ static void dso__insert_symbol(struct dso *self, struct symbol *sym)
static struct symbol *dso__find_symbol(struct dso *self, uint64_t ip)
{
+ struct rb_node *n;
+
if (self == NULL)
return NULL;
- struct rb_node *n = self->syms.rb_node;
+ n = self->syms.rb_node;
while (n) {
struct symbol *s = rb_entry(n, struct symbol, rb_node);
@@ -221,33 +224,42 @@ static Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
static int dso__load(struct dso *self)
{
- int fd = open(self->name, O_RDONLY), err = -1;
+ Elf_Data *symstrs;
+ uint32_t nr_syms;
+ int fd, err = -1;
+ uint32_t index;
+ GElf_Ehdr ehdr;
+ GElf_Shdr shdr;
+ Elf_Data *syms;
+ GElf_Sym sym;
+ Elf_Scn *sec;
+ Elf *elf;
+
+ fd = open(self->name, O_RDONLY);
if (fd == -1)
return -1;
- Elf *elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
+ elf = elf_begin(fd, ELF_C_READ_MMAP, NULL);
if (elf == NULL) {
fprintf(stderr, "%s: cannot read %s ELF file.\n",
__func__, self->name);
goto out_close;
}
- GElf_Ehdr ehdr;
if (gelf_getehdr(elf, &ehdr) == NULL) {
fprintf(stderr, "%s: cannot get elf header.\n", __func__);
goto out_elf_end;
}
- GElf_Shdr shdr;
- Elf_Scn *sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
+ sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL);
if (sec == NULL)
sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL);
if (sec == NULL)
goto out_elf_end;
- Elf_Data *syms = elf_getdata(sec, NULL);
+ syms = elf_getdata(sec, NULL);
if (syms == NULL)
goto out_elf_end;
@@ -255,14 +267,12 @@ static int dso__load(struct dso *self)
if (sec == NULL)
goto out_elf_end;
- Elf_Data *symstrs = elf_getdata(sec, NULL);
+ symstrs = elf_getdata(sec, NULL);
if (symstrs == NULL)
goto out_elf_end;
- const uint32_t nr_syms = shdr.sh_size / shdr.sh_entsize;
+ nr_syms = shdr.sh_size / shdr.sh_entsize;
- GElf_Sym sym;
- uint32_t index;
elf_symtab__for_each_symbol(syms, nr_syms, index, sym) {
struct symbol *f;
@@ -342,7 +352,7 @@ static struct dso *dsos__findnew(const char *name)
return NULL;
}
-void dsos__fprintf(FILE *fp)
+static void dsos__fprintf(FILE *fp)
{
struct dso *pos;
@@ -365,7 +375,7 @@ static int hex(char ch)
* While we find nice hex chars, build a long_val.
* Return number of chars processed.
*/
-int hex2long(char *ptr, unsigned long *long_val)
+static int hex2long(char *ptr, unsigned long *long_val)
{
const char *p = ptr;
*long_val = 0;
@@ -493,12 +503,6 @@ static struct map *map__new(struct mmap_event *event)
return NULL;
}
-static size_t map__fprintf(struct map *self, FILE *fp)
-{
- return fprintf(fp, " %lx-%lx %lx %s\n",
- self->start, self->end, self->pgoff, self->dso->name);
-}
-
struct thread;
static const char *thread__name(struct thread *self, char *bf, size_t size);
@@ -531,11 +535,6 @@ static struct symhist *symhist__new(struct symbol *sym, uint64_t ip,
return self;
}
-void symhist__delete(struct symhist *self)
-{
- free(self);
-}
-
static void symhist__inc(struct symhist *self)
{
++self->count;
@@ -608,6 +607,8 @@ static int thread__symbol_incnew(struct thread *self, struct symbol *sym,
struct symhist *sh;
while (*p != NULL) {
+ uint64_t start;
+
parent = *p;
sh = rb_entry(parent, struct symhist, rb_node);
@@ -617,7 +618,7 @@ static int thread__symbol_incnew(struct thread *self, struct symbol *sym,
}
/* Handle unresolved symbols too */
- const uint64_t start = !sh->sym ? sh->ip : sh->sym->start;
+ start = !sh->sym ? sh->ip : sh->sym->start;
if (ip < start)
p = &(*p)->rb_left;
@@ -639,17 +640,6 @@ static int thread__set_comm(struct thread *self, const char *comm)
return self->comm ? 0 : -ENOMEM;
}
-size_t thread__maps_fprintf(struct thread *self, FILE *fp)
-{
- struct map *pos;
- size_t ret = 0;
-
- list_for_each_entry(pos, &self->maps, node)
- ret += map__fprintf(pos, fp);
-
- return ret;
-}
-
static size_t thread__fprintf(struct thread *self, FILE *fp)
{
int ret = fprintf(fp, "thread: %d %s\n", self->pid, self->comm);
@@ -657,13 +647,14 @@ static size_t thread__fprintf(struct thread *self, FILE *fp)
for (nd = rb_first(&self->symhists); nd; nd = rb_next(nd)) {
struct symhist *pos = rb_entry(nd, struct symhist, rb_node);
+
ret += symhist__fprintf(pos, 0, fp);
}
return ret;
}
-static struct rb_root threads = RB_ROOT;
+static struct rb_root threads;
static struct thread *threads__findnew(pid_t pid)
{
@@ -699,11 +690,11 @@ static void thread__insert_map(struct thread *self, struct map *map)
static struct map *thread__find_map(struct thread *self, uint64_t ip)
{
+ struct map *pos;
+
if (self == NULL)
return NULL;
- struct map *pos;
-
list_for_each_entry(pos, &self->maps, node)
if (ip >= pos->start && ip <= pos->end)
return pos;
@@ -711,7 +702,7 @@ static struct map *thread__find_map(struct thread *self, uint64_t ip)
return NULL;
}
-void threads__fprintf(FILE *fp)
+static void threads__fprintf(FILE *fp)
{
struct rb_node *nd;
for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
@@ -720,7 +711,7 @@ void threads__fprintf(FILE *fp)
}
}
-static struct rb_root global_symhists = RB_ROOT;
+static struct rb_root global_symhists;
static void threads__insert_symhist(struct symhist *sh)
{
@@ -852,7 +843,7 @@ static int __cmd_report(void)
(void *)(long)(event->header.size),
event->header.misc,
event->ip.pid,
- (void *)event->ip.ip);
+ (void *)(long)ip);
}
if (thread == NULL) {
@@ -866,9 +857,12 @@ static int __cmd_report(void)
level = 'k';
dso = kernel_dso;
} else if (event->header.misc & PERF_EVENT_MISC_USER) {
+ struct map *map;
+
show = SHOW_USER;
level = '.';
- struct map *map = thread__find_map(thread, ip);
+
+ map = thread__find_map(thread, ip);
if (map != NULL) {
dso = map->dso;
ip -= map->start + map->pgoff;
@@ -896,9 +890,9 @@ static int __cmd_report(void)
fprintf(stderr, "%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
- (void *)event->mmap.start,
- (void *)event->mmap.len,
- (void *)event->mmap.pgoff,
+ (void *)(long)event->mmap.start,
+ (void *)(long)event->mmap.len,
+ (void *)(long)event->mmap.pgoff,
event->mmap.filename);
}
if (thread == NULL || map == NULL) {
@@ -964,6 +958,11 @@ static int __cmd_report(void)
return 0;
}
+ if (verbose >= 2) {
+ dsos__fprintf(stdout);
+ threads__fprintf(stdout);
+ }
+
threads__sort_symhists();
threads__symhists_fprintf(total, stdout);
diff --git a/Documentation/perf_counter/builtin-stat.c b/Documentation/perf_counter/builtin-stat.c
index e7cb9412212b..ce661e2fa8dd 100644
--- a/Documentation/perf_counter/builtin-stat.c
+++ b/Documentation/perf_counter/builtin-stat.c
@@ -30,6 +30,7 @@
*/
#include "perf.h"
+#include "builtin.h"
#include "util/util.h"
#include "util/parse-options.h"
#include "util/parse-events.h"
@@ -108,7 +109,7 @@ static void create_perfstat_counter(int counter)
}
}
-int do_perfstat(int argc, const char **argv)
+static int do_perfstat(int argc, const char **argv)
{
unsigned long long t0, t1;
int counter;
diff --git a/Documentation/perf_counter/builtin-top.c b/Documentation/perf_counter/builtin-top.c
index 6b1c66f99e4d..a890872638c1 100644
--- a/Documentation/perf_counter/builtin-top.c
+++ b/Documentation/perf_counter/builtin-top.c
@@ -42,8 +42,8 @@
* Released under the GPL v2. (and only v2, not any later version)
*/
-
#include "perf.h"
+#include "builtin.h"
#include "util/util.h"
#include "util/util.h"
#include "util/parse-options.h"
diff --git a/Documentation/perf_counter/util/abspath.c b/Documentation/perf_counter/util/abspath.c
index 649f34f83365..61d33b81fc97 100644
--- a/Documentation/perf_counter/util/abspath.c
+++ b/Documentation/perf_counter/util/abspath.c
@@ -5,7 +5,7 @@
* symlink to a directory, we do not want to say it is a directory when
* dealing with tracked content in the working tree.
*/
-int is_directory(const char *path)
+static int is_directory(const char *path)
{
struct stat st;
return (!stat(path, &st) && S_ISDIR(st.st_mode));
diff --git a/Documentation/perf_counter/util/cache.h b/Documentation/perf_counter/util/cache.h
index 71080512fa86..393d6146d13b 100644
--- a/Documentation/perf_counter/util/cache.h
+++ b/Documentation/perf_counter/util/cache.h
@@ -104,6 +104,8 @@ char *strip_path_suffix(const char *path, const char *suffix);
extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
extern char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+/* perf_mkstemp() - create tmp file honoring TMPDIR variable */
+extern int perf_mkstemp(char *path, size_t len, const char *template);
extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
__attribute__((format (printf, 3, 4)));
diff --git a/Documentation/perf_counter/util/util.h b/Documentation/perf_counter/util/util.h
index 36e40c38e093..76590a16c271 100644
--- a/Documentation/perf_counter/util/util.h
+++ b/Documentation/perf_counter/util/util.h
@@ -309,6 +309,8 @@ extern ssize_t xread(int fd, void *buf, size_t len);
extern ssize_t xwrite(int fd, const void *buf, size_t len);
extern int xdup(int fd);
extern FILE *xfdopen(int fd, const char *mode);
+extern int xmkstemp(char *template);
+
static inline size_t xsize_t(off_t len)
{
return (size_t)len;
commit af83632f98aefd1ae4d8ca3c7c285ccf6a7d3956
Author: Ingo Molnar <mingo@elte.hu>
Date: Wed May 27 08:38:48 2009 +0200
perf report: Only load text symbols from kallsyms, fix
- allow 'W' symbols too
- Convert initializations to C99 style
- whitespace cleanups
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
LKML-Reference: <20090526222155.GJ4424@ghostprotocols.net>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index a55f15d7651d..ed3da9d61985 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -384,21 +384,26 @@ int hex2long(char *ptr, unsigned long *long_val)
static int load_kallsyms(void)
{
+ struct rb_node *nd, *prevnd;
+ char *line = NULL;
+ FILE *file;
+ size_t n;
+
kernel_dso = dso__new("[kernel]");
if (kernel_dso == NULL)
return -1;
- FILE *file = fopen("/proc/kallsyms", "r");
-
+ file = fopen("/proc/kallsyms", "r");
if (file == NULL)
goto out_delete_dso;
- char *line = NULL;
- size_t n;
-
while (!feof(file)) {
unsigned long start;
- int line_len = getline(&line, &n, file);
+ struct symbol *sym;
+ int line_len, len;
+ char symbol_type;
+
+ line_len = getline(&line, &n, file);
if (line_len < 0)
break;
@@ -407,22 +412,22 @@ static int load_kallsyms(void)
line[--line_len] = '\0'; /* \n */
- int len = hex2long(line, &start);
-
+ len = hex2long(line, &start);
+
len++;
if (len + 2 >= line_len)
continue;
- char symbol_type = line[len];
+ symbol_type = toupper(line[len]);
/*
* We're interested only in code ('T'ext)
*/
- if (toupper(symbol_type) != 'T')
+ if (symbol_type != 'T' && symbol_type != 'W')
continue;
/*
* Well fix up the end later, when we have all sorted.
*/
- struct symbol *sym = symbol__new(start, 0xdead, line + len + 2);
+ sym = symbol__new(start, 0xdead, line + len + 2);
if (sym == NULL)
goto out_delete_dso;
@@ -434,7 +439,7 @@ static int load_kallsyms(void)
* Now that we have all sorted out, just set the ->end of all
* symbols
*/
- struct rb_node *nd, *prevnd = rb_first(&kernel_dso->syms);
+ prevnd = rb_first(&kernel_dso->syms);
if (prevnd == NULL)
goto out_delete_line;
@@ -450,6 +455,7 @@ static int load_kallsyms(void)
dsos__add(kernel_dso);
free(line);
fclose(file);
+
return 0;
out_delete_line:
commit f49515b157e2d3ca3633eb0664fc46c42f6cb37e
Author: Ingo Molnar <mingo@elte.hu>
Date: Tue May 26 19:03:36 2009 +0200
perf report: add more debugging
Add the offset of the file we are analyzing, and the size of the record.
In case of problems it's easier to see where the parser lost track.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Kacur <jkacur@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 4b5ccc5bd0e6..2d4e4cc655a3 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -645,7 +645,7 @@ static int __cmd_report(void)
char *buf;
event_t *event;
int ret, rc = EXIT_FAILURE;
- unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown;
+ unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0;
input = open(input_name, O_RDONLY);
if (input < 0) {
@@ -699,8 +699,6 @@ static int __cmd_report(void)
goto done;
}
- head += event->header.size;
-
if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
char level;
int show = 0;
@@ -709,7 +707,9 @@ static int __cmd_report(void)
uint64_t ip = event->ip.ip;
if (dump_trace) {
- fprintf(stderr, "PERF_EVENT (IP, %d): %d: %p\n",
+ fprintf(stderr, "%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
+ (void *)(offset + head),
+ (void *)(long)(event->header.size),
event->header.misc,
event->ip.pid,
(void *)event->ip.ip);
@@ -753,7 +753,9 @@ static int __cmd_report(void)
struct map *map = map__new(&event->mmap);
if (dump_trace) {
- fprintf(stderr, "PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
+ fprintf(stderr, "%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
+ (void *)(offset + head),
+ (void *)(long)(event->header.size),
(void *)event->mmap.start,
(void *)event->mmap.len,
(void *)event->mmap.pgoff,
@@ -771,7 +773,9 @@ static int __cmd_report(void)
struct thread *thread = threads__findnew(event->comm.pid);
if (dump_trace) {
- fprintf(stderr, "PERF_EVENT_COMM: %s:%d\n",
+ fprintf(stderr, "%p [%p]: PERF_EVENT_COMM: %s:%d\n",
+ (void *)(offset + head),
+ (void *)(long)(event->header.size),
event->comm.comm, event->comm.pid);
}
if (thread == NULL ||
@@ -783,12 +787,16 @@ static int __cmd_report(void)
break;
}
default: {
- fprintf(stderr, "skipping unknown header type: %d\n",
+ fprintf(stderr, "%p [%p]: skipping unknown header type: %d\n",
+ (void *)(offset + head),
+ (void *)(long)(event->header.size),
event->header.type);
total_unknown++;
}
}
+ head += event->header.size;
+
if (offset + head < stat.st_size)
goto more;
commit 3e70611460fe74ad32534fa9791774f6bbdd4159
Author: Ingo Molnar <mingo@elte.hu>
Date: Tue May 26 18:53:17 2009 +0200
perf report: add counter for unknown events
Add a counter for unknown event records.
[ Impact: improve debugging ]
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index 8ea8aaa05af5..4b5ccc5bd0e6 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -645,7 +645,7 @@ static int __cmd_report(void)
char *buf;
event_t *event;
int ret, rc = EXIT_FAILURE;
- unsigned long total = 0, total_mmap = 0, total_comm = 0;
+ unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown;
input = open(input_name, O_RDONLY);
if (input < 0) {
@@ -785,6 +785,7 @@ static int __cmd_report(void)
default: {
fprintf(stderr, "skipping unknown header type: %d\n",
event->header.type);
+ total_unknown++;
}
}
@@ -796,9 +797,10 @@ static int __cmd_report(void)
close(input);
if (dump_trace) {
- fprintf(stderr, " IP events: %10ld\n", total);
- fprintf(stderr, " mmap events: %10ld\n", total_mmap);
- fprintf(stderr, " comm events: %10ld\n", total_comm);
+ fprintf(stderr, " IP events: %10ld\n", total);
+ fprintf(stderr, " mmap events: %10ld\n", total_mmap);
+ fprintf(stderr, " comm events: %10ld\n", total_comm);
+ fprintf(stderr, " unknown events: %10ld\n", total_unknown);
return 0;
}
commit 97b07b699b11d4bd1218a841e5dfed16bd53de06
Author: Ingo Molnar <mingo@elte.hu>
Date: Tue May 26 18:48:58 2009 +0200
perf report: add --dump-raw-trace option
To help the inspection of various data files, implement an ASCII dump
method that just dumps the records as they are read in - then we exit.
[ Impact: new feature ]
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c
index e17819001dd5..8ea8aaa05af5 100644
--- a/Documentation/perf_counter/builtin-report.c
+++ b/Documentation/perf_counter/builtin-report.c
@@ -20,6 +20,8 @@ static char const *input_name = "output.perf";
static int input;
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
+static int dump_trace = 0;
+
static unsigned long page_size;
static unsigned long mmap_window = 32;
@@ -643,7 +645,7 @@ static int __cmd_report(void)
char *buf;
event_t *event;
int ret, rc = EXIT_FAILURE;
- unsigned long total = 0;
+ unsigned long total = 0, total_mmap = 0, total_comm = 0;
input = open(input_name, O_RDONLY);
if (input < 0) {
@@ -706,6 +708,13 @@ static int __cmd_report(void)
struct thread *thread = threads__findnew(event->ip.pid);
uint64_t ip = event->ip.ip;
+ if (dump_trace) {
+ fprintf(stderr, "PERF_EVENT (IP, %d): %d: %p\n",
+ event->header.misc,
+ event->ip.pid,
+ (void *)event->ip.ip);
+ }
+
if (thread == NULL) {
fprintf(stderr, "problem processing %d event, bailing out\n",
event->header.type);
@@ -743,23 +752,40 @@ static int __cmd_report(void)
struct thread *thread = threads__findnew(event->mmap.pid);
struct map *map = map__new(&event->mmap);
+ if (dump_trace) {
+ fprintf(stderr, "PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
+ (void *)event->mmap.start,
+ (void *)event->mmap.len,
+ (void *)event->mmap.pgoff,
+ event->mmap.filename);
+ }
if (thread == NULL || map == NULL) {
fprintf(stderr, "problem processing PERF_EVENT_MMAP, bailing out\n");
goto done;
}
thread__insert_map(thread, map);
+ total_mmap++;
break;
}
case PERF_EVENT_COMM: {
struct thread *thread = threads__findnew(event->comm.pid);
+ if (dump_trace) {
+ fprintf(stderr, "PERF_EVENT_COMM: %s:%d\n",
+ event->comm.comm, event->comm.pid);
+ }
if (thread == NULL ||
thread__set_comm(thread, event->comm.comm)) {
fprintf(stderr, "problem processing PERF_EVENT_COMM, bailing out\n");
goto done;
}
+ total_comm++;
break;
}
+ default: {
+ fprintf(stderr, "skipping unknown header type: %d\n",
+ event->header.type);
+ }
}
if (offset + head < stat.st_size)
@@ -768,6 +794,15 @@ static int __cmd_report(void)
rc = EXIT_SUCCESS;
done:
close(input);
+
+ if (dump_trace) {
+ fprintf(stderr, " IP events: %10ld\n", total);
+ fprintf(stderr, " mmap events: %10ld\n", total_mmap);
+ fprintf(stderr, " comm events: %10ld\n", total_comm);
+
+ return 0;
+ }
+
//dsos__fprintf(stdout);
threads__fprintf(stdout);
#if 0
@@ -796,6 +831,8 @@ static const char * const report_usage[] = {
static const struct option options[] = {
OPT_STRING('i', "input", &input_name, "file",
"input file name"),
+ OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
+ "dump raw trace in ASCII"),
OPT_END()
};
commit 0bec253c813fbb067db4dfd9f5b6cec1bd2ef026
Author: Ingo Molnar <mingo@elte.hu>
Date: Tue May 26 09:17:18 2009 +0200
perf report: Add help/manpage
Add a (minimal) manpage for perf report.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/Documentation/perf-report.txt b/Documentation/perf_counter/Documentation/perf-report.txt
new file mode 100644
index 000000000000..64696a218105
--- /dev/null
+++ b/Documentation/perf_counter/Documentation/perf-report.txt
@@ -0,0 +1,32 @@
+perf-report(1)
+==========
+
+NAME
+----
+perf-report - Read output.perf (created by perf record) and display the profile
+
+SYNOPSIS
+--------
+[verse]
+'perf report' [-i <file> | --input=file]
+
+DESCRIPTION
+-----------
+This command displays the performance counter profile information recorded
+via perf report.
+
+OPTIONS
+-------
+-i::
+--input=::
+ Input file name. (default: output.perf)
+
+Configuration
+-------------
+
+EXAMPLES
+--------
+
+SEE ALSO
+--------
+linkperf:perf-stat[1]