* [PATCH 01/15] perf report: Fix usage string
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 02/15] perf tools: Fix comm for processes with named threads Arnaldo Carvalho de Melo
` (14 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Namhyung Kim, Paul Mackerras, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Namhyung Kim <namhyung@gmail.com>
perf report does not take a command from command line.
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1323703017-6060-8-git-send-email-namhyung@gmail.com
Signed-off-by: Namhyung Kim <namhyung@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-report.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index b2654c9..9051f6b 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -432,7 +432,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
{
char callchain_default_opt[] = "fractal,0.5,callee";
const char * const report_usage[] = {
- "perf report [<options>] <command>",
+ "perf report [<options>]",
NULL
};
struct perf_report report = {
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 02/15] perf tools: Fix comm for processes with named threads
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 01/15] perf report: Fix usage string Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 03/15] perf tools: Look up thread names for system wide profiling Arnaldo Carvalho de Melo
` (13 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, David Ahern, Frederic Weisbecker, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: David Ahern <dsahern@gmail.com>
perf does not properly handle monitoring of processes with named threads.
For example:
$ ps -C myapp -L
PID LWP TTY TIME CMD
25118 25118 ? 00:00:00 myapp
25118 25119 ? 00:00:00 myapp:worker
perf record -e cs -c 1 -fo /tmp/perf.data -p 25118 -- sleep 10
perf report --stdio -i /tmp/perf.data
100.00% myapp:worker [kernel.kallsyms] [k] perf_event_task_sched_out
The process name is set to the name of the last thread it finds for the
process.
The Problem:
perf-top and perf-record both create a thread_map of threads to be
monitored. That map is used in perf_event__synthesize_thread_map which
loops over the entries in thread_map and calls __event__synthesize_thread
to generate COMM and MMAP events.
__event__synthesize_thread calls perf_event__synthesize_comm which opens
/proc/pid/status, reads the name of the task and its thread group id.
That's all fine. The problem is that it then reads /proc/pid/task and
generates COMM events for each task it finds - but using the name found
in /proc/pid/status where pid is the thread of interest.
The end result (looping over thread_map + synthesizing comm events for
each thread each time) means the name of the last thread processed sets
the name for all threads in the process - which is not good for
multithreaded processes with named threads.
The Fix:
perf_event__synthesize_comm has an input argument (full) that decides
whether to process task entries for each pid it is passed. It currently
never set to 0 (perf_event__synthesize_comm has a single caller and it
always passes the value 1). Let's fix that.
Add the full input argument to __event__synthesize_thread which passes
it to perf_event__synthesize_comm. For thread/process monitoring set full
to 0 which means COMM and MMAP events are only generated for the pid
passed to it. For system wide monitoring set full to 1 so that COMM events
are generated for all threads in a process.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1324578603-12762-2-git-send-email-dsahern@gmail.com
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/event.c | 37 ++++++++++++++++++++++++++++++++-----
1 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index b7c7f39..a578726 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -261,11 +261,12 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
static int __event__synthesize_thread(union perf_event *comm_event,
union perf_event *mmap_event,
- pid_t pid, perf_event__handler_t process,
+ pid_t pid, int full,
+ perf_event__handler_t process,
struct perf_tool *tool,
struct machine *machine)
{
- pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, 1,
+ pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full,
process, machine);
if (tgid == -1)
return -1;
@@ -279,7 +280,7 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
struct machine *machine)
{
union perf_event *comm_event, *mmap_event;
- int err = -1, thread;
+ int err = -1, thread, j;
comm_event = malloc(sizeof(comm_event->comm) + machine->id_hdr_size);
if (comm_event == NULL)
@@ -292,11 +293,37 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
err = 0;
for (thread = 0; thread < threads->nr; ++thread) {
if (__event__synthesize_thread(comm_event, mmap_event,
- threads->map[thread],
+ threads->map[thread], 0,
process, tool, machine)) {
err = -1;
break;
}
+
+ /*
+ * comm.pid is set to thread group id by
+ * perf_event__synthesize_comm
+ */
+ if ((int) comm_event->comm.pid != threads->map[thread]) {
+ bool need_leader = true;
+
+ /* is thread group leader in thread_map? */
+ for (j = 0; j < threads->nr; ++j) {
+ if ((int) comm_event->comm.pid == threads->map[j]) {
+ need_leader = false;
+ break;
+ }
+ }
+
+ /* if not, generate events for it */
+ if (need_leader &&
+ __event__synthesize_thread(comm_event,
+ mmap_event,
+ comm_event->comm.pid, 0,
+ process, tool, machine)) {
+ err = -1;
+ break;
+ }
+ }
}
free(mmap_event);
out_free_comm:
@@ -333,7 +360,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
if (*end) /* only interested in proper numerical dirents */
continue;
- __event__synthesize_thread(comm_event, mmap_event, pid,
+ __event__synthesize_thread(comm_event, mmap_event, pid, 1,
process, tool, machine);
}
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 03/15] perf tools: Look up thread names for system wide profiling
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 01/15] perf report: Fix usage string Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 02/15] perf tools: Fix comm for processes with named threads Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 04/15] perf script: look up thread using tid instead of pid Arnaldo Carvalho de Melo
` (12 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, David Ahern, Frederic Weisbecker, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: David Ahern <dsahern@gmail.com>
This handles multithreaded processes with named threads when doing
system wide profiling: the comm for each thread is looked up allowing
them to be different from the thread group leader.
v2:
- fixed sizeof arg to perf_event__get_comm_tgid
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1324578603-12762-3-git-send-email-dsahern@gmail.com
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/event.c | 75 +++++++++++++++++++++++++++++++++--------------
1 files changed, 53 insertions(+), 22 deletions(-)
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index a578726..73ddaf0 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -43,37 +43,27 @@ static struct perf_sample synth_sample = {
.period = 1,
};
-static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
- union perf_event *event, pid_t pid,
- int full, perf_event__handler_t process,
- struct machine *machine)
+static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
{
char filename[PATH_MAX];
char bf[BUFSIZ];
FILE *fp;
size_t size = 0;
- DIR *tasks;
- struct dirent dirent, *next;
- pid_t tgid = 0;
+ pid_t tgid = -1;
snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
fp = fopen(filename, "r");
if (fp == NULL) {
-out_race:
- /*
- * We raced with a task exiting - just return:
- */
pr_debug("couldn't open %s\n", filename);
return 0;
}
- memset(&event->comm, 0, sizeof(event->comm));
-
- while (!event->comm.comm[0] || !event->comm.pid) {
+ while (!comm[0] || (tgid < 0)) {
if (fgets(bf, sizeof(bf), fp) == NULL) {
- pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
- goto out;
+ pr_warning("couldn't get COMM and pgid, malformed %s\n",
+ filename);
+ break;
}
if (memcmp(bf, "Name:", 5) == 0) {
@@ -81,16 +71,46 @@ out_race:
while (*name && isspace(*name))
++name;
size = strlen(name) - 1;
- memcpy(event->comm.comm, name, size++);
+ if (size >= len)
+ size = len - 1;
+ memcpy(comm, name, size);
+
} else if (memcmp(bf, "Tgid:", 5) == 0) {
char *tgids = bf + 5;
while (*tgids && isspace(*tgids))
++tgids;
- tgid = event->comm.pid = atoi(tgids);
+ tgid = atoi(tgids);
}
}
+ fclose(fp);
+
+ return tgid;
+}
+
+static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
+ union perf_event *event, pid_t pid,
+ int full,
+ perf_event__handler_t process,
+ struct machine *machine)
+{
+ char filename[PATH_MAX];
+ size_t size;
+ DIR *tasks;
+ struct dirent dirent, *next;
+ pid_t tgid;
+
+ memset(&event->comm, 0, sizeof(event->comm));
+
+ tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
+ sizeof(event->comm.comm));
+ if (tgid < 0)
+ goto out;
+
+ event->comm.pid = tgid;
event->comm.header.type = PERF_RECORD_COMM;
+
+ size = strlen(event->comm.comm) + 1;
size = ALIGN(size, sizeof(u64));
memset(event->comm.comm + size, 0, machine->id_hdr_size);
event->comm.header.size = (sizeof(event->comm) -
@@ -106,8 +126,10 @@ out_race:
snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
tasks = opendir(filename);
- if (tasks == NULL)
- goto out_race;
+ if (tasks == NULL) {
+ pr_debug("couldn't open %s\n", filename);
+ return 0;
+ }
while (!readdir_r(tasks, &dirent, &next) && next) {
char *end;
@@ -115,6 +137,17 @@ out_race:
if (*end)
continue;
+ /* already have tgid; jut want to update the comm */
+ (void) perf_event__get_comm_tgid(pid, event->comm.comm,
+ sizeof(event->comm.comm));
+
+ size = strlen(event->comm.comm) + 1;
+ size = ALIGN(size, sizeof(u64));
+ memset(event->comm.comm + size, 0, machine->id_hdr_size);
+ event->comm.header.size = (sizeof(event->comm) -
+ (sizeof(event->comm.comm) - size) +
+ machine->id_hdr_size);
+
event->comm.tid = pid;
process(tool, event, &synth_sample, machine);
@@ -122,8 +155,6 @@ out_race:
closedir(tasks);
out:
- fclose(fp);
-
return tgid;
}
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 04/15] perf script: look up thread using tid instead of pid
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (2 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 03/15] perf tools: Look up thread names for system wide profiling Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 05/15] perf tools: Fix truncated annotation Arnaldo Carvalho de Melo
` (11 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, David Ahern, Frederic Weisbecker, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: David Ahern <dsahern@gmail.com>
This allows the thread name to be dispalyed when dumping
events:
myapp 25118 [000] 450385.538815: context-switches ...
myapp:worker 25119 [000] 450385.538894: context-switches ...
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1324578603-12762-4-git-send-email-dsahern@gmail.com
Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-script.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index ea71c5e..d71b745 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -443,7 +443,7 @@ static int process_sample_event(struct perf_tool *tool __used,
struct machine *machine)
{
struct addr_location al;
- struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
+ struct thread *thread = machine__findnew_thread(machine, event->ip.tid);
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 05/15] perf tools: Fix truncated annotation
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (3 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 04/15] perf script: look up thread using tid instead of pid Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 06/15] perf: builtin-record: Provide advice if mmap'ing fails with EPERM Arnaldo Carvalho de Melo
` (10 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar; +Cc: linux-kernel, Peter Zijlstra, Arnaldo Carvalho de Melo
From: Ingo Molnar <mingo@elte.hu>
I get such truncated annotation results in 'perf top':
: Disassembly of section .text: ▒
: ▒
: ffffffff810966a8 <nr_iowait_cpu>: ▒
4.94 : ffffffff810966a8: movslq %edi,%rdi ▒
3.70 : ffffffff810966ab: mov $0x13700,%rax ▒
0.00 : ffffffff810966b2: add -0x7e32cb00(,%rdi,8),%rax ▒
8.64 : ffffffff810966ba: mov 0x7e0(%rax),%eax ▒
82.72 : ffffffff810966c0: cltq ▒
Note the missing 'retq' which is there in the original function:
ffffffff810966a8 <nr_iowait_cpu>:
ffffffff810966a8: 48 63 ff movslq %edi,%rdi
ffffffff810966ab: 48 c7 c0 00 37 01 00 mov $0x13700,%rax
ffffffff810966b2: 48 03 04 fd 00 35 cd add -0x7e32cb00(,%rdi,8),%rax
ffffffff810966b9: 81
ffffffff810966ba: 8b 80 e0 07 00 00 mov 0x7e0(%rax),%eax
ffffffff810966c0: 48 98 cltq
ffffffff810966c2: c3 retq
ffffffff810966c3 <this_cpu_load>:
I'm using a fairly recent binutils:
GNU objdump version 2.21.51.0.6-2.fc16 20110118
AFAICS the bug is simply that sym->end points to the last byte
of the symbol in question - while objdump's --stop-address
expects the last byte plus 1 to disassemble the full range.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/20111223130804.GA24305@elte.hu
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/annotate.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 376e643..011ed26 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -334,7 +334,7 @@ fallback:
disassembler_style ? "-M " : "",
disassembler_style ? disassembler_style : "",
map__rip_2objdump(map, sym->start),
- map__rip_2objdump(map, sym->end),
+ map__rip_2objdump(map, sym->end+1),
symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
symbol_conf.annotate_src ? "-S" : "",
symfs_filename, filename);
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 06/15] perf: builtin-record: Provide advice if mmap'ing fails with EPERM.
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (4 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 05/15] perf tools: Fix truncated annotation Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 07/15] perf: builtin-record: Document and check that mmap_pages must be a power of two Arnaldo Carvalho de Melo
` (9 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Nelson Elhage, Paul Mackerras, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Nelson Elhage <nelhage@nelhage.com>
This failure is most likely due to running up against the
kernel.perf_event_mlock_kb sysctl, so we can tell the user what to do to
fix the issue.
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1324301972-22740-3-git-send-email-nelhage@nelhage.com
Signed-off-by: Nelson Elhage <nelhage@nelhage.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-record.c | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index f8fd14f..56bb447 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -272,8 +272,15 @@ try_again:
exit(-1);
}
- if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0)
+ if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
+ if (errno == EPERM)
+ die("Permission error mapping pages.\n"
+ "Consider increasing "
+ "/proc/sys/kernel/perf_event_mlock_kb,\n"
+ "or try again with a smaller value of -m/--mmap_pages.\n"
+ "(current value: %d)\n", opts->mmap_pages);
die("failed to mmap with %d (%s)\n", errno, strerror(errno));
+ }
if (rec->file_new)
session->evlist = evlist;
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 07/15] perf: builtin-record: Document and check that mmap_pages must be a power of two.
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (5 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 06/15] perf: builtin-record: Provide advice if mmap'ing fails with EPERM Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 08/15] perf tools: Improve macros for struct feature_ops Arnaldo Carvalho de Melo
` (8 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Nelson Elhage, Paul Mackerras, Peter Zijlstra,
Arnaldo Carvalho de Melo
From: Nelson Elhage <nelhage@nelhage.com>
Now that we automatically point users at it, let's provide them some
guidance so that they hopefully don't just get mysterious EINVAL's
from the kernel.
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1324301972-22740-4-git-send-email-nelhage@nelhage.com
Signed-off-by: Nelson Elhage <nelhage@nelhage.com>
[ committer note: Made it work after 50a682c ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Documentation/perf-record.txt | 2 +-
tools/perf/builtin-record.c | 3 +++
tools/perf/util/evlist.c | 2 ++
tools/perf/util/util.h | 11 +++++++++++
4 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 5a520f8..2937f7e 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -89,7 +89,7 @@ OPTIONS
-m::
--mmap-pages=::
- Number of mmap data pages.
+ Number of mmap data pages. Must be a power of two.
-g::
--call-graph::
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 56bb447..e873ae2 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -279,6 +279,9 @@ try_again:
"/proc/sys/kernel/perf_event_mlock_kb,\n"
"or try again with a smaller value of -m/--mmap_pages.\n"
"(current value: %d)\n", opts->mmap_pages);
+ else if (!is_power_of_2(opts->mmap_pages))
+ die("--mmap_pages/-m value must be a power of two.");
+
die("failed to mmap with %d (%s)\n", errno, strerror(errno));
}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 963d63d..fa18370 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -563,6 +563,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
/* 512 kiB: default amount of unprivileged mlocked memory */
if (pages == UINT_MAX)
pages = (512 * 1024) / page_size;
+ else if (!is_power_of_2(pages))
+ return -EINVAL;
mask = pages * page_size - 1;
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 0128906..37be34d 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -245,4 +245,15 @@ int readn(int fd, void *buf, size_t size);
#define _STR(x) #x
#define STR(x) _STR(x)
+/*
+ * Determine whether some value is a power of two, where zero is
+ * *not* considered a power of two.
+ */
+
+static inline __attribute__((const))
+bool is_power_of_2(unsigned long n)
+{
+ return (n != 0 && ((n & (n - 1)) == 0));
+}
+
#endif
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 08/15] perf tools: Improve macros for struct feature_ops
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (6 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 07/15] perf: builtin-record: Document and check that mmap_pages must be a power of two Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 09/15] perf tools: Continue processing header on unknown features Arnaldo Carvalho de Melo
` (7 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Robert Richter, Frederic Weisbecker,
Peter Zijlstra, Stephane Eranian, Arnaldo Carvalho de Melo
From: Robert Richter <robert.richter@amd.com>
Reducing duplication and line size by extending function names for
print and write from a single name.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323248577-11268-7-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 40 ++++++++++++++++++++++------------------
1 files changed, 22 insertions(+), 18 deletions(-)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 5b01449..4c48be8 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1065,26 +1065,30 @@ struct feature_ops {
bool full_only;
};
-#define FEAT_OPA(n, w, p) \
- [n] = { .name = #n, .write = w, .print = p }
-#define FEAT_OPF(n, w, p) \
- [n] = { .name = #n, .write = w, .print = p, .full_only = true }
+#define FEAT_OPA(n, func) \
+ [n] = { .name = #n, .write = write_##func, .print = print_##func }
+#define FEAT_OPF(n, func) \
+ [n] = { .name = #n, .write = write_##func, .print = print_##func, .full_only = true }
+
+/* feature_ops not implemented: */
+#define print_trace_info NULL
+#define print_build_id NULL
static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
- FEAT_OPA(HEADER_TRACE_INFO, write_trace_info, NULL),
- FEAT_OPA(HEADER_BUILD_ID, write_build_id, NULL),
- FEAT_OPA(HEADER_HOSTNAME, write_hostname, print_hostname),
- FEAT_OPA(HEADER_OSRELEASE, write_osrelease, print_osrelease),
- FEAT_OPA(HEADER_VERSION, write_version, print_version),
- FEAT_OPA(HEADER_ARCH, write_arch, print_arch),
- FEAT_OPA(HEADER_NRCPUS, write_nrcpus, print_nrcpus),
- FEAT_OPA(HEADER_CPUDESC, write_cpudesc, print_cpudesc),
- FEAT_OPA(HEADER_CPUID, write_cpuid, print_cpuid),
- FEAT_OPA(HEADER_TOTAL_MEM, write_total_mem, print_total_mem),
- FEAT_OPA(HEADER_EVENT_DESC, write_event_desc, print_event_desc),
- FEAT_OPA(HEADER_CMDLINE, write_cmdline, print_cmdline),
- FEAT_OPF(HEADER_CPU_TOPOLOGY, write_cpu_topology, print_cpu_topology),
- FEAT_OPF(HEADER_NUMA_TOPOLOGY, write_numa_topology, print_numa_topology),
+ FEAT_OPA(HEADER_TRACE_INFO, trace_info),
+ FEAT_OPA(HEADER_BUILD_ID, build_id),
+ FEAT_OPA(HEADER_HOSTNAME, hostname),
+ FEAT_OPA(HEADER_OSRELEASE, osrelease),
+ FEAT_OPA(HEADER_VERSION, version),
+ FEAT_OPA(HEADER_ARCH, arch),
+ FEAT_OPA(HEADER_NRCPUS, nrcpus),
+ FEAT_OPA(HEADER_CPUDESC, cpudesc),
+ FEAT_OPA(HEADER_CPUID, cpuid),
+ FEAT_OPA(HEADER_TOTAL_MEM, total_mem),
+ FEAT_OPA(HEADER_EVENT_DESC, event_desc),
+ FEAT_OPA(HEADER_CMDLINE, cmdline),
+ FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology),
+ FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology),
};
struct header_print_data {
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 09/15] perf tools: Continue processing header on unknown features
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (7 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 08/15] perf tools: Improve macros for struct feature_ops Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 10/15] perf tools: Fix out-of-bound access to struct perf_session Arnaldo Carvalho de Melo
` (6 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Robert Richter, Frederic Weisbecker,
Peter Zijlstra, Stephane Eranian, Arnaldo Carvalho de Melo
From: Robert Richter <robert.richter@amd.com>
A feature may be unknown if perf.data is created and parsed on different
perf tool versions. This should not stop the header to be processed,
instead continue processing it.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323248577-11268-2-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 4c48be8..428a4a2 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1109,7 +1109,7 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section,
}
if (feat < HEADER_TRACE_INFO || feat >= HEADER_LAST_FEATURE) {
pr_warning("unknown feature %d\n", feat);
- return -1;
+ return 0;
}
if (!feat_ops[feat].print)
return 0;
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 10/15] perf tools: Fix out-of-bound access to struct perf_session
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (8 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 09/15] perf tools: Continue processing header on unknown features Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 11/15] perf tools: Moving code in some files Arnaldo Carvalho de Melo
` (5 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Robert Richter, Frederic Weisbecker,
Peter Zijlstra, Stephane Eranian, Arnaldo Carvalho de Melo
From: Robert Richter <robert.richter@amd.com>
If filename is NULL there is an out-of-bound access to struct
perf_session if it would be used with perf_session__open(). Shouldn't
actually happen in current implementation as filename is always !NULL.
Fixing this by always null-terminating filename.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323248577-11268-3-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/util/session.c | 2 +-
tools/perf/util/session.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index d9318d8..ea17dfb 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -107,7 +107,7 @@ struct perf_session *perf_session__new(const char *filename, int mode,
bool force, bool repipe,
struct perf_tool *tool)
{
- size_t len = filename ? strlen(filename) + 1 : 0;
+ size_t len = filename ? strlen(filename) : 0;
struct perf_session *self = zalloc(sizeof(*self) + len);
if (self == NULL)
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index fb69612..37bc383 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -50,7 +50,7 @@ struct perf_session {
int cwdlen;
char *cwd;
struct ordered_samples ordered_samples;
- char filename[0];
+ char filename[1];
};
struct perf_tool;
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 11/15] perf tools: Moving code in some files
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (9 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 10/15] perf tools: Fix out-of-bound access to struct perf_session Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 12/15] perf report: Accept fifos as input file Arnaldo Carvalho de Melo
` (4 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Robert Richter, Frederic Weisbecker,
Peter Zijlstra, Stephane Eranian, Arnaldo Carvalho de Melo
From: Robert Richter <robert.richter@amd.com>
Needed for later changes. No modified functionality.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323248577-11268-4-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-buildid-list.c | 36 ++--
| 495 ++++++++++++++++++-------------------
2 files changed, 264 insertions(+), 267 deletions(-)
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index cb690a6..4895668 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -39,24 +39,6 @@ static const struct option options[] = {
OPT_END()
};
-static int perf_session__list_build_ids(void)
-{
- struct perf_session *session;
-
- session = perf_session__new(input_name, O_RDONLY, force, false,
- &build_id__mark_dso_hit_ops);
- if (session == NULL)
- return -1;
-
- if (with_hits)
- perf_session__process_events(session, &build_id__mark_dso_hit_ops);
-
- perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
-
- perf_session__delete(session);
- return 0;
-}
-
static int sysfs__fprintf_build_id(FILE *fp)
{
u8 kallsyms_build_id[BUILD_ID_SIZE];
@@ -85,6 +67,24 @@ static int filename__fprintf_build_id(const char *name, FILE *fp)
return fprintf(fp, "%s\n", sbuild_id);
}
+static int perf_session__list_build_ids(void)
+{
+ struct perf_session *session;
+
+ session = perf_session__new(input_name, O_RDONLY, force, false,
+ &build_id__mark_dso_hit_ops);
+ if (session == NULL)
+ return -1;
+
+ if (with_hits)
+ perf_session__process_events(session, &build_id__mark_dso_hit_ops);
+
+ perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
+
+ perf_session__delete(session);
+ return 0;
+}
+
static int __cmd_buildid_list(void)
{
if (show_kernel)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 428a4a2..609d79b 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -28,9 +28,6 @@ static struct perf_trace_event_type *events;
static u32 header_argc;
static const char **header_argv;
-static int dsos__write_buildid_table(struct perf_header *header, int fd);
-static int perf_session__cache_build_ids(struct perf_session *session);
-
int perf_header__push_event(u64 id, const char *name)
{
if (strlen(name) > MAX_EVENT_NAME)
@@ -187,6 +184,252 @@ perf_header__set_cmdline(int argc, const char **argv)
return 0;
}
+#define dsos__for_each_with_build_id(pos, head) \
+ list_for_each_entry(pos, head, node) \
+ if (!pos->has_build_id) \
+ continue; \
+ else
+
+static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
+ u16 misc, int fd)
+{
+ struct dso *pos;
+
+ dsos__for_each_with_build_id(pos, head) {
+ int err;
+ struct build_id_event b;
+ size_t len;
+
+ if (!pos->hit)
+ continue;
+ len = pos->long_name_len + 1;
+ len = ALIGN(len, NAME_ALIGN);
+ memset(&b, 0, sizeof(b));
+ memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
+ b.pid = pid;
+ b.header.misc = misc;
+ b.header.size = sizeof(b) + len;
+ err = do_write(fd, &b, sizeof(b));
+ if (err < 0)
+ return err;
+ err = write_padded(fd, pos->long_name,
+ pos->long_name_len + 1, len);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int machine__write_buildid_table(struct machine *machine, int fd)
+{
+ int err;
+ u16 kmisc = PERF_RECORD_MISC_KERNEL,
+ umisc = PERF_RECORD_MISC_USER;
+
+ if (!machine__is_host(machine)) {
+ kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
+ umisc = PERF_RECORD_MISC_GUEST_USER;
+ }
+
+ err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
+ kmisc, fd);
+ if (err == 0)
+ err = __dsos__write_buildid_table(&machine->user_dsos,
+ machine->pid, umisc, fd);
+ return err;
+}
+
+static int dsos__write_buildid_table(struct perf_header *header, int fd)
+{
+ struct perf_session *session = container_of(header,
+ struct perf_session, header);
+ struct rb_node *nd;
+ int err = machine__write_buildid_table(&session->host_machine, fd);
+
+ if (err)
+ return err;
+
+ for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
+ struct machine *pos = rb_entry(nd, struct machine, rb_node);
+ err = machine__write_buildid_table(pos, fd);
+ if (err)
+ break;
+ }
+ return err;
+}
+
+int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
+ const char *name, bool is_kallsyms)
+{
+ const size_t size = PATH_MAX;
+ char *realname, *filename = zalloc(size),
+ *linkname = zalloc(size), *targetname;
+ int len, err = -1;
+
+ if (is_kallsyms) {
+ if (symbol_conf.kptr_restrict) {
+ pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
+ return 0;
+ }
+ realname = (char *)name;
+ } else
+ realname = realpath(name, NULL);
+
+ if (realname == NULL || filename == NULL || linkname == NULL)
+ goto out_free;
+
+ len = snprintf(filename, size, "%s%s%s",
+ debugdir, is_kallsyms ? "/" : "", realname);
+ if (mkdir_p(filename, 0755))
+ goto out_free;
+
+ snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id);
+
+ if (access(filename, F_OK)) {
+ if (is_kallsyms) {
+ if (copyfile("/proc/kallsyms", filename))
+ goto out_free;
+ } else if (link(realname, filename) && copyfile(name, filename))
+ goto out_free;
+ }
+
+ len = snprintf(linkname, size, "%s/.build-id/%.2s",
+ debugdir, sbuild_id);
+
+ if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
+ goto out_free;
+
+ snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
+ targetname = filename + strlen(debugdir) - 5;
+ memcpy(targetname, "../..", 5);
+
+ if (symlink(targetname, linkname) == 0)
+ err = 0;
+out_free:
+ if (!is_kallsyms)
+ free(realname);
+ free(filename);
+ free(linkname);
+ return err;
+}
+
+static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
+ const char *name, const char *debugdir,
+ bool is_kallsyms)
+{
+ char sbuild_id[BUILD_ID_SIZE * 2 + 1];
+
+ build_id__sprintf(build_id, build_id_size, sbuild_id);
+
+ return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
+}
+
+int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
+{
+ const size_t size = PATH_MAX;
+ char *filename = zalloc(size),
+ *linkname = zalloc(size);
+ int err = -1;
+
+ if (filename == NULL || linkname == NULL)
+ goto out_free;
+
+ snprintf(linkname, size, "%s/.build-id/%.2s/%s",
+ debugdir, sbuild_id, sbuild_id + 2);
+
+ if (access(linkname, F_OK))
+ goto out_free;
+
+ if (readlink(linkname, filename, size - 1) < 0)
+ goto out_free;
+
+ if (unlink(linkname))
+ goto out_free;
+
+ /*
+ * Since the link is relative, we must make it absolute:
+ */
+ snprintf(linkname, size, "%s/.build-id/%.2s/%s",
+ debugdir, sbuild_id, filename);
+
+ if (unlink(linkname))
+ goto out_free;
+
+ err = 0;
+out_free:
+ free(filename);
+ free(linkname);
+ return err;
+}
+
+static int dso__cache_build_id(struct dso *dso, const char *debugdir)
+{
+ bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
+
+ return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
+ dso->long_name, debugdir, is_kallsyms);
+}
+
+static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
+{
+ struct dso *pos;
+ int err = 0;
+
+ dsos__for_each_with_build_id(pos, head)
+ if (dso__cache_build_id(pos, debugdir))
+ err = -1;
+
+ return err;
+}
+
+static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
+{
+ int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
+ ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
+ return ret;
+}
+
+static int perf_session__cache_build_ids(struct perf_session *session)
+{
+ struct rb_node *nd;
+ int ret;
+ char debugdir[PATH_MAX];
+
+ snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
+
+ if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
+ return -1;
+
+ ret = machine__cache_build_ids(&session->host_machine, debugdir);
+
+ for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
+ struct machine *pos = rb_entry(nd, struct machine, rb_node);
+ ret |= machine__cache_build_ids(pos, debugdir);
+ }
+ return ret ? -1 : 0;
+}
+
+static bool machine__read_build_ids(struct machine *machine, bool with_hits)
+{
+ bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits);
+ ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits);
+ return ret;
+}
+
+static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
+{
+ struct rb_node *nd;
+ bool ret = machine__read_build_ids(&session->host_machine, with_hits);
+
+ for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
+ struct machine *pos = rb_entry(nd, struct machine, rb_node);
+ ret |= machine__read_build_ids(pos, with_hits);
+ }
+
+ return ret;
+}
+
static int write_trace_info(int fd, struct perf_header *h __used,
struct perf_evlist *evlist)
{
@@ -1136,252 +1379,6 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full)
return 0;
}
-#define dsos__for_each_with_build_id(pos, head) \
- list_for_each_entry(pos, head, node) \
- if (!pos->has_build_id) \
- continue; \
- else
-
-static int __dsos__write_buildid_table(struct list_head *head, pid_t pid,
- u16 misc, int fd)
-{
- struct dso *pos;
-
- dsos__for_each_with_build_id(pos, head) {
- int err;
- struct build_id_event b;
- size_t len;
-
- if (!pos->hit)
- continue;
- len = pos->long_name_len + 1;
- len = ALIGN(len, NAME_ALIGN);
- memset(&b, 0, sizeof(b));
- memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id));
- b.pid = pid;
- b.header.misc = misc;
- b.header.size = sizeof(b) + len;
- err = do_write(fd, &b, sizeof(b));
- if (err < 0)
- return err;
- err = write_padded(fd, pos->long_name,
- pos->long_name_len + 1, len);
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-static int machine__write_buildid_table(struct machine *machine, int fd)
-{
- int err;
- u16 kmisc = PERF_RECORD_MISC_KERNEL,
- umisc = PERF_RECORD_MISC_USER;
-
- if (!machine__is_host(machine)) {
- kmisc = PERF_RECORD_MISC_GUEST_KERNEL;
- umisc = PERF_RECORD_MISC_GUEST_USER;
- }
-
- err = __dsos__write_buildid_table(&machine->kernel_dsos, machine->pid,
- kmisc, fd);
- if (err == 0)
- err = __dsos__write_buildid_table(&machine->user_dsos,
- machine->pid, umisc, fd);
- return err;
-}
-
-static int dsos__write_buildid_table(struct perf_header *header, int fd)
-{
- struct perf_session *session = container_of(header,
- struct perf_session, header);
- struct rb_node *nd;
- int err = machine__write_buildid_table(&session->host_machine, fd);
-
- if (err)
- return err;
-
- for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
- struct machine *pos = rb_entry(nd, struct machine, rb_node);
- err = machine__write_buildid_table(pos, fd);
- if (err)
- break;
- }
- return err;
-}
-
-int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
- const char *name, bool is_kallsyms)
-{
- const size_t size = PATH_MAX;
- char *realname, *filename = zalloc(size),
- *linkname = zalloc(size), *targetname;
- int len, err = -1;
-
- if (is_kallsyms) {
- if (symbol_conf.kptr_restrict) {
- pr_debug("Not caching a kptr_restrict'ed /proc/kallsyms\n");
- return 0;
- }
- realname = (char *)name;
- } else
- realname = realpath(name, NULL);
-
- if (realname == NULL || filename == NULL || linkname == NULL)
- goto out_free;
-
- len = snprintf(filename, size, "%s%s%s",
- debugdir, is_kallsyms ? "/" : "", realname);
- if (mkdir_p(filename, 0755))
- goto out_free;
-
- snprintf(filename + len, sizeof(filename) - len, "/%s", sbuild_id);
-
- if (access(filename, F_OK)) {
- if (is_kallsyms) {
- if (copyfile("/proc/kallsyms", filename))
- goto out_free;
- } else if (link(realname, filename) && copyfile(name, filename))
- goto out_free;
- }
-
- len = snprintf(linkname, size, "%s/.build-id/%.2s",
- debugdir, sbuild_id);
-
- if (access(linkname, X_OK) && mkdir_p(linkname, 0755))
- goto out_free;
-
- snprintf(linkname + len, size - len, "/%s", sbuild_id + 2);
- targetname = filename + strlen(debugdir) - 5;
- memcpy(targetname, "../..", 5);
-
- if (symlink(targetname, linkname) == 0)
- err = 0;
-out_free:
- if (!is_kallsyms)
- free(realname);
- free(filename);
- free(linkname);
- return err;
-}
-
-static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
- const char *name, const char *debugdir,
- bool is_kallsyms)
-{
- char sbuild_id[BUILD_ID_SIZE * 2 + 1];
-
- build_id__sprintf(build_id, build_id_size, sbuild_id);
-
- return build_id_cache__add_s(sbuild_id, debugdir, name, is_kallsyms);
-}
-
-int build_id_cache__remove_s(const char *sbuild_id, const char *debugdir)
-{
- const size_t size = PATH_MAX;
- char *filename = zalloc(size),
- *linkname = zalloc(size);
- int err = -1;
-
- if (filename == NULL || linkname == NULL)
- goto out_free;
-
- snprintf(linkname, size, "%s/.build-id/%.2s/%s",
- debugdir, sbuild_id, sbuild_id + 2);
-
- if (access(linkname, F_OK))
- goto out_free;
-
- if (readlink(linkname, filename, size - 1) < 0)
- goto out_free;
-
- if (unlink(linkname))
- goto out_free;
-
- /*
- * Since the link is relative, we must make it absolute:
- */
- snprintf(linkname, size, "%s/.build-id/%.2s/%s",
- debugdir, sbuild_id, filename);
-
- if (unlink(linkname))
- goto out_free;
-
- err = 0;
-out_free:
- free(filename);
- free(linkname);
- return err;
-}
-
-static int dso__cache_build_id(struct dso *dso, const char *debugdir)
-{
- bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
-
- return build_id_cache__add_b(dso->build_id, sizeof(dso->build_id),
- dso->long_name, debugdir, is_kallsyms);
-}
-
-static int __dsos__cache_build_ids(struct list_head *head, const char *debugdir)
-{
- struct dso *pos;
- int err = 0;
-
- dsos__for_each_with_build_id(pos, head)
- if (dso__cache_build_id(pos, debugdir))
- err = -1;
-
- return err;
-}
-
-static int machine__cache_build_ids(struct machine *machine, const char *debugdir)
-{
- int ret = __dsos__cache_build_ids(&machine->kernel_dsos, debugdir);
- ret |= __dsos__cache_build_ids(&machine->user_dsos, debugdir);
- return ret;
-}
-
-static int perf_session__cache_build_ids(struct perf_session *session)
-{
- struct rb_node *nd;
- int ret;
- char debugdir[PATH_MAX];
-
- snprintf(debugdir, sizeof(debugdir), "%s", buildid_dir);
-
- if (mkdir(debugdir, 0755) != 0 && errno != EEXIST)
- return -1;
-
- ret = machine__cache_build_ids(&session->host_machine, debugdir);
-
- for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
- struct machine *pos = rb_entry(nd, struct machine, rb_node);
- ret |= machine__cache_build_ids(pos, debugdir);
- }
- return ret ? -1 : 0;
-}
-
-static bool machine__read_build_ids(struct machine *machine, bool with_hits)
-{
- bool ret = __dsos__read_build_ids(&machine->kernel_dsos, with_hits);
- ret |= __dsos__read_build_ids(&machine->user_dsos, with_hits);
- return ret;
-}
-
-static bool perf_session__read_build_ids(struct perf_session *session, bool with_hits)
-{
- struct rb_node *nd;
- bool ret = machine__read_build_ids(&session->host_machine, with_hits);
-
- for (nd = rb_first(&session->machines); nd; nd = rb_next(nd)) {
- struct machine *pos = rb_entry(nd, struct machine, rb_node);
- ret |= machine__read_build_ids(pos, with_hits);
- }
-
- return ret;
-}
-
static int do_write_feat(int fd, struct perf_header *h, int type,
struct perf_file_section **p,
struct perf_evlist *evlist)
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 12/15] perf report: Accept fifos as input file
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (10 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 11/15] perf tools: Moving code in some files Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 13/15] perf tools: Unify handling of features when writing feature section Arnaldo Carvalho de Melo
` (3 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Robert Richter, Frederic Weisbecker,
Peter Zijlstra, Stephane Eranian, Arnaldo Carvalho de Melo
From: Robert Richter <robert.richter@amd.com>
The default input file for perf report is not handled the same way as
perf record does it for its output file. This leads to unexpected
behavior of perf report, etc. E.g.:
# perf record -a -e cpu-cycles sleep 2 | perf report | cat
failed to open perf.data: No such file or directory (try 'perf record' first)
While perf record writes to a fifo, perf report expects perf.data to be
read. This patch changes this to accept fifos as input file.
Applies to the following commands:
perf annotate
perf buildid-list
perf evlist
perf kmem
perf lock
perf report
perf sched
perf script
perf timechart
Also fixes char const* -> const char* type declaration for filename
strings.
v2:
* Prevent potential null pointer access to input_name in
builtin-report.c. Needed due to removal of patch "perf report: Setup
browser if stdout is a pipe"
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323248577-11268-5-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/Documentation/perf-annotate.txt | 2 +-
tools/perf/Documentation/perf-buildid-list.txt | 2 +-
tools/perf/Documentation/perf-evlist.txt | 2 +-
tools/perf/Documentation/perf-kmem.txt | 2 +-
tools/perf/Documentation/perf-lock.txt | 2 +-
tools/perf/Documentation/perf-report.txt | 2 +-
tools/perf/Documentation/perf-sched.txt | 2 +-
tools/perf/Documentation/perf-script.txt | 2 +-
tools/perf/Documentation/perf-timechart.txt | 2 +-
tools/perf/builtin-annotate.c | 3 +--
tools/perf/builtin-buildid-list.c | 19 ++++++++++---------
tools/perf/builtin-evlist.c | 2 +-
tools/perf/builtin-kmem.c | 2 +-
tools/perf/builtin-lock.c | 2 +-
tools/perf/builtin-report.c | 13 ++++++++++---
tools/perf/builtin-sched.c | 2 +-
tools/perf/builtin-script.c | 4 ++--
tools/perf/builtin-timechart.c | 4 ++--
tools/perf/util/session.c | 15 +++++++++++++--
19 files changed, 51 insertions(+), 33 deletions(-)
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index 476029d..c89f9e1 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -22,7 +22,7 @@ OPTIONS
-------
-i::
--input=::
- Input file name. (default: perf.data)
+ Input file name. (default: perf.data unless stdin is a fifo)
-d::
--dsos=<dso[,dso...]>::
diff --git a/tools/perf/Documentation/perf-buildid-list.txt b/tools/perf/Documentation/perf-buildid-list.txt
index cc22325..25c52ef 100644
--- a/tools/perf/Documentation/perf-buildid-list.txt
+++ b/tools/perf/Documentation/perf-buildid-list.txt
@@ -26,7 +26,7 @@ OPTIONS
Show only DSOs with hits.
-i::
--input=::
- Input file name. (default: perf.data)
+ Input file name. (default: perf.data unless stdin is a fifo)
-f::
--force::
Don't do ownership validation.
diff --git a/tools/perf/Documentation/perf-evlist.txt b/tools/perf/Documentation/perf-evlist.txt
index 0cada9e..0507ec7 100644
--- a/tools/perf/Documentation/perf-evlist.txt
+++ b/tools/perf/Documentation/perf-evlist.txt
@@ -18,7 +18,7 @@ OPTIONS
-------
-i::
--input=::
- Input file name. (default: perf.data)
+ Input file name. (default: perf.data unless stdin is a fifo)
SEE ALSO
--------
diff --git a/tools/perf/Documentation/perf-kmem.txt b/tools/perf/Documentation/perf-kmem.txt
index a52fcde..7c8fbbf 100644
--- a/tools/perf/Documentation/perf-kmem.txt
+++ b/tools/perf/Documentation/perf-kmem.txt
@@ -23,7 +23,7 @@ OPTIONS
-------
-i <file>::
--input=<file>::
- Select the input file (default: perf.data)
+ Select the input file (default: perf.data unless stdin is a fifo)
--caller::
Show per-callsite statistics
diff --git a/tools/perf/Documentation/perf-lock.txt b/tools/perf/Documentation/perf-lock.txt
index 4a26a2f..d6b2a4f 100644
--- a/tools/perf/Documentation/perf-lock.txt
+++ b/tools/perf/Documentation/perf-lock.txt
@@ -29,7 +29,7 @@ COMMON OPTIONS
-i::
--input=<file>::
- Input file name.
+ Input file name. (default: perf.data unless stdin is a fifo)
-v::
--verbose::
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 35af0dc..9b430e9 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -19,7 +19,7 @@ OPTIONS
-------
-i::
--input=::
- Input file name. (default: perf.data)
+ Input file name. (default: perf.data unless stdin is a fifo)
-v::
--verbose::
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 5b212b5..8ff4df9 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -40,7 +40,7 @@ OPTIONS
-------
-i::
--input=<file>::
- Input file name. (default: perf.data)
+ Input file name. (default: perf.data unless stdin is a fifo)
-v::
--verbose::
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 7f61eaa..2f6cef4 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -106,7 +106,7 @@ OPTIONS
-i::
--input=::
- Input file name.
+ Input file name. (default: perf.data unless stdin is a fifo)
-d::
--debug-mode::
diff --git a/tools/perf/Documentation/perf-timechart.txt b/tools/perf/Documentation/perf-timechart.txt
index d7b79e2..1632b0e 100644
--- a/tools/perf/Documentation/perf-timechart.txt
+++ b/tools/perf/Documentation/perf-timechart.txt
@@ -27,7 +27,7 @@ OPTIONS
Select the output file (default: output.svg)
-i::
--input=::
- Select the input file (default: perf.data)
+ Select the input file (default: perf.data unless stdin is a fifo)
-w::
--width=::
Select the width of the SVG file (default: 1000)
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index d449645..214ba7f 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -215,7 +215,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
}
if (total_nr_samples == 0) {
- ui__warning("The %s file has no samples!\n", ann->input_name);
+ ui__warning("The %s file has no samples!\n", session->filename);
goto out_delete;
}
out_delete:
@@ -250,7 +250,6 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
.ordered_samples = true,
.ordering_requires_timestamps = true,
},
- .input_name = "perf.data",
};
const struct option options[] = {
OPT_STRING('i', "input", &annotate.input_name, "file",
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
index 4895668..5248046 100644
--- a/tools/perf/builtin-buildid-list.c
+++ b/tools/perf/builtin-buildid-list.c
@@ -18,7 +18,7 @@
#include <libelf.h>
-static char const *input_name = "perf.data";
+static const char *input_name;
static bool force;
static bool show_kernel;
static bool with_hits;
@@ -71,16 +71,24 @@ static int perf_session__list_build_ids(void)
{
struct perf_session *session;
+ elf_version(EV_CURRENT);
+
session = perf_session__new(input_name, O_RDONLY, force, false,
&build_id__mark_dso_hit_ops);
if (session == NULL)
return -1;
+ /*
+ * See if this is an ELF file first:
+ */
+ if (filename__fprintf_build_id(session->filename, stdout))
+ goto out;
+
if (with_hits)
perf_session__process_events(session, &build_id__mark_dso_hit_ops);
perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
-
+out:
perf_session__delete(session);
return 0;
}
@@ -90,13 +98,6 @@ static int __cmd_buildid_list(void)
if (show_kernel)
return sysfs__fprintf_build_id(stdout);
- elf_version(EV_CURRENT);
- /*
- * See if this is an ELF file first:
- */
- if (filename__fprintf_build_id(input_name, stdout))
- return 0;
-
return perf_session__list_build_ids();
}
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 4c5e9e0..2676032 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -15,7 +15,7 @@
#include "util/parse-options.h"
#include "util/session.h"
-static char const *input_name = "perf.data";
+static const char *input_name;
static int __cmd_evlist(void)
{
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 886174e..fe1ad8f 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -19,7 +19,7 @@
struct alloc_stat;
typedef int (*sort_fn_t)(struct alloc_stat *, struct alloc_stat *);
-static char const *input_name = "perf.data";
+static const char *input_name;
static int alloc_flag;
static int caller_flag;
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c
index 4db5e52..2296c39 100644
--- a/tools/perf/builtin-lock.c
+++ b/tools/perf/builtin-lock.c
@@ -326,7 +326,7 @@ alloc_failed:
die("memory allocation failed\n");
}
-static char const *input_name = "perf.data";
+static const char *input_name;
struct raw_event_sample {
u32 size;
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 9051f6b..25d34d4 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -321,8 +321,7 @@ static int __cmd_report(struct perf_report *rep)
}
if (nr_samples == 0) {
- ui__warning("The %s file has no samples!\n",
- rep->input_name);
+ ui__warning("The %s file has no samples!\n", session->filename);
goto out_delete;
}
@@ -430,6 +429,7 @@ setup:
int cmd_report(int argc, const char **argv, const char *prefix __used)
{
+ struct stat st;
char callchain_default_opt[] = "fractal,0.5,callee";
const char * const report_usage[] = {
"perf report [<options>]",
@@ -451,7 +451,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
.ordered_samples = true,
.ordering_requires_timestamps = true,
},
- .input_name = "perf.data",
.pretty_printing_style = "normal",
};
const struct option options[] = {
@@ -531,10 +530,18 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
if (report.inverted_callchain)
callchain_param.order = ORDER_CALLER;
+ if (!report.input_name || !strlen(report.input_name)) {
+ if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
+ report.input_name = "-";
+ else
+ report.input_name = "perf.data";
+ }
+
if (strcmp(report.input_name, "-") != 0)
setup_browser(true);
else
use_browser = 0;
+
/*
* Only in the newt browser we are doing integrated annotation,
* so don't allocate extra space that won't be used in the stdio
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 6284ed2..fb8b5f8 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -22,7 +22,7 @@
#include <pthread.h>
#include <math.h>
-static char const *input_name = "perf.data";
+static const char *input_name;
static char default_sort_order[] = "avg, max, switch, runtime";
static const char *sort_order = default_sort_order;
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index d71b745..3d4c0c7 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -434,7 +434,7 @@ static int cleanup_scripting(void)
return scripting_ops->stop_script();
}
-static char const *input_name = "perf.data";
+static const char *input_name;
static int process_sample_event(struct perf_tool *tool __used,
union perf_event *event,
@@ -1316,7 +1316,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
return -1;
}
- input = open(input_name, O_RDONLY);
+ input = open(session->filename, O_RDONLY); /* input_name */
if (input < 0) {
perror("failed to open file");
exit(-1);
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 135376a..3b75b2e 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -38,8 +38,8 @@
#define PWR_EVENT_EXIT -1
-static char const *input_name = "perf.data";
-static char const *output_name = "output.svg";
+static const char *input_name;
+static const char *output_name = "output.svg";
static unsigned int numcpus;
static u64 min_freq; /* Lowest CPU frequency seen */
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index ea17dfb..cc5e6be 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -107,8 +107,19 @@ struct perf_session *perf_session__new(const char *filename, int mode,
bool force, bool repipe,
struct perf_tool *tool)
{
- size_t len = filename ? strlen(filename) : 0;
- struct perf_session *self = zalloc(sizeof(*self) + len);
+ struct perf_session *self;
+ struct stat st;
+ size_t len;
+
+ if (!filename || !strlen(filename)) {
+ if (!fstat(STDIN_FILENO, &st) && S_ISFIFO(st.st_mode))
+ filename = "-";
+ else
+ filename = "perf.data";
+ }
+
+ len = strlen(filename);
+ self = zalloc(sizeof(*self) + len);
if (self == NULL)
goto out;
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 13/15] perf tools: Unify handling of features when writing feature section
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (11 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 12/15] perf report: Accept fifos as input file Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 14/15] perf tools: Use for_each_set_bit() to iterate over feature flags Arnaldo Carvalho de Melo
` (2 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Robert Richter, Frederic Weisbecker,
Peter Zijlstra, Stephane Eranian, Arnaldo Carvalho de Melo
From: Robert Richter <robert.richter@amd.com>
The features HEADER_TRACE_INFO and HEADER_BUILD_ID are handled
different when writing the feature section. All other features are
simply disabled on failure and writing the section goes on without
returning an error. There is no reason for these special cases. This
patch unifies handling of the features.
This should be ok since all features can be parsed independently.
Offset and size of a feature's block is stored in struct perf_file_
section right after the data block of perf.data (see perf_session__
write_header()). Thus, if a feature does not exist then other features
can be processed anyway.
Also moving special code for HEADER_BUILD_ID out to write_build_id().
v2:
* perf record throws an error now if buildids may not be generated,
which can be disabled with the --no-buildid option.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323248577-11268-6-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
tools/perf/builtin-record.c | 7 +++++++
| 14 +++++---------
2 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e873ae2..0abfb18 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -503,6 +503,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
return err;
}
+ if (!!rec->no_buildid
+ && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
+ pr_err("Couldn't generating buildids. "
+ "Use --no-buildid to profile anyway.\n");
+ return -1;
+ }
+
rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
machine = perf_session__find_host_machine(session);
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 609d79b..7132683 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -445,6 +445,9 @@ static int write_build_id(int fd, struct perf_header *h,
session = container_of(h, struct perf_session, header);
+ if (!perf_session__read_build_ids(session, true))
+ return -1;
+
err = dsos__write_buildid_table(h, fd);
if (err < 0) {
pr_debug("failed to write buildid table\n");
@@ -1417,10 +1420,6 @@ static int perf_header__adds_write(struct perf_header *header,
session = container_of(header, struct perf_session, header);
- if (perf_header__has_feat(header, HEADER_BUILD_ID &&
- !perf_session__read_build_ids(session, true)))
- perf_header__clear_feat(header, HEADER_BUILD_ID);
-
nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
if (!nr_sections)
return 0;
@@ -1436,13 +1435,11 @@ static int perf_header__adds_write(struct perf_header *header,
err = do_write_feat(fd, header, HEADER_TRACE_INFO, &p, evlist);
if (err)
- goto out_free;
+ perf_header__clear_feat(header, HEADER_TRACE_INFO);
err = do_write_feat(fd, header, HEADER_BUILD_ID, &p, evlist);
- if (err) {
+ if (err)
perf_header__clear_feat(header, HEADER_BUILD_ID);
- goto out_free;
- }
err = do_write_feat(fd, header, HEADER_HOSTNAME, &p, evlist);
if (err)
@@ -1500,7 +1497,6 @@ static int perf_header__adds_write(struct perf_header *header,
err = do_write(fd, feat_sec, sec_size);
if (err < 0)
pr_debug("failed to write feature section\n");
-out_free:
free(feat_sec);
return err;
}
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 14/15] perf tools: Use for_each_set_bit() to iterate over feature flags
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (12 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 13/15] perf tools: Unify handling of features when writing feature section Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-23 21:53 ` [PATCH 15/15] perf script: Add generic perl handler to process events Arnaldo Carvalho de Melo
2011-12-29 20:28 ` [GIT PULL 00/15] perf/core improvements and fixes Ingo Molnar
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Robert Richter, Frederic Weisbecker,
Peter Zijlstra, Stephane Eranian, Arnaldo Carvalho de Melo
From: Robert Richter <robert.richter@amd.com>
This patch introduces the for_each_set_bit() macro and modifies feature
implementation to use it.
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323248577-11268-8-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
| 118 ++++++++------------------------
| 6 +-
tools/perf/util/include/linux/bitops.h | 118 ++++++++++++++++++++++++++++++++
3 files changed, 149 insertions(+), 93 deletions(-)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 7132683..e509a9d 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -8,6 +8,7 @@
#include <stdlib.h>
#include <linux/list.h>
#include <linux/kernel.h>
+#include <linux/bitops.h>
#include <sys/utsname.h>
#include "evlist.h"
@@ -1353,7 +1354,7 @@ static int perf_file_section__fprintf_info(struct perf_file_section *section,
"%d, continuing...\n", section->offset, feat);
return 0;
}
- if (feat < HEADER_TRACE_INFO || feat >= HEADER_LAST_FEATURE) {
+ if (feat >= HEADER_LAST_FEATURE) {
pr_warning("unknown feature %d\n", feat);
return 0;
}
@@ -1390,6 +1391,8 @@ static int do_write_feat(int fd, struct perf_header *h, int type,
int ret = 0;
if (perf_header__has_feat(h, type)) {
+ if (!feat_ops[type].write)
+ return -1;
(*p)->offset = lseek(fd, 0, SEEK_CUR);
@@ -1416,6 +1419,7 @@ static int perf_header__adds_write(struct perf_header *header,
struct perf_file_section *feat_sec, *p;
int sec_size;
u64 sec_start;
+ int feat;
int err;
session = container_of(header, struct perf_session, header);
@@ -1433,61 +1437,10 @@ static int perf_header__adds_write(struct perf_header *header,
sec_start = header->data_offset + header->data_size;
lseek(fd, sec_start + sec_size, SEEK_SET);
- err = do_write_feat(fd, header, HEADER_TRACE_INFO, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_TRACE_INFO);
-
- err = do_write_feat(fd, header, HEADER_BUILD_ID, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_BUILD_ID);
-
- err = do_write_feat(fd, header, HEADER_HOSTNAME, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_HOSTNAME);
-
- err = do_write_feat(fd, header, HEADER_OSRELEASE, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_OSRELEASE);
-
- err = do_write_feat(fd, header, HEADER_VERSION, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_VERSION);
-
- err = do_write_feat(fd, header, HEADER_ARCH, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_ARCH);
-
- err = do_write_feat(fd, header, HEADER_NRCPUS, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_NRCPUS);
-
- err = do_write_feat(fd, header, HEADER_CPUDESC, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_CPUDESC);
-
- err = do_write_feat(fd, header, HEADER_CPUID, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_CPUID);
-
- err = do_write_feat(fd, header, HEADER_TOTAL_MEM, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_TOTAL_MEM);
-
- err = do_write_feat(fd, header, HEADER_CMDLINE, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_CMDLINE);
-
- err = do_write_feat(fd, header, HEADER_EVENT_DESC, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_EVENT_DESC);
-
- err = do_write_feat(fd, header, HEADER_CPU_TOPOLOGY, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_CPU_TOPOLOGY);
-
- err = do_write_feat(fd, header, HEADER_NUMA_TOPOLOGY, &p, evlist);
- if (err)
- perf_header__clear_feat(header, HEADER_NUMA_TOPOLOGY);
+ for_each_set_bit(feat, header->adds_features, HEADER_FEAT_BITS) {
+ if (do_write_feat(fd, header, feat, &p, evlist))
+ perf_header__clear_feat(header, feat);
+ }
lseek(fd, sec_start, SEEK_SET);
/*
@@ -1634,20 +1587,20 @@ static int perf_header__getbuffer64(struct perf_header *header,
int perf_header__process_sections(struct perf_header *header, int fd,
void *data,
int (*process)(struct perf_file_section *section,
- struct perf_header *ph,
- int feat, int fd, void *data))
+ struct perf_header *ph,
+ int feat, int fd, void *data))
{
- struct perf_file_section *feat_sec;
+ struct perf_file_section *feat_sec, *sec;
int nr_sections;
int sec_size;
- int idx = 0;
- int err = -1, feat = 1;
+ int feat;
+ int err;
nr_sections = bitmap_weight(header->adds_features, HEADER_FEAT_BITS);
if (!nr_sections)
return 0;
- feat_sec = calloc(sizeof(*feat_sec), nr_sections);
+ feat_sec = sec = calloc(sizeof(*feat_sec), nr_sections);
if (!feat_sec)
return -1;
@@ -1655,20 +1608,16 @@ int perf_header__process_sections(struct perf_header *header, int fd,
lseek(fd, header->data_offset + header->data_size, SEEK_SET);
- if (perf_header__getbuffer64(header, fd, feat_sec, sec_size))
+ err = perf_header__getbuffer64(header, fd, feat_sec, sec_size);
+ if (err < 0)
goto out_free;
- err = 0;
- while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
- if (perf_header__has_feat(header, feat)) {
- struct perf_file_section *sec = &feat_sec[idx++];
-
- err = process(sec, header, feat, fd, data);
- if (err < 0)
- break;
- }
- ++feat;
+ for_each_set_bit(feat, header->adds_features, HEADER_LAST_FEATURE) {
+ err = process(sec++, header, feat, fd, data);
+ if (err < 0)
+ goto out_free;
}
+ err = 0;
out_free:
free(feat_sec);
return err;
@@ -1903,32 +1852,21 @@ static int perf_file_section__process(struct perf_file_section *section,
return 0;
}
+ if (feat >= HEADER_LAST_FEATURE) {
+ pr_debug("unknown feature %d, continuing...\n", feat);
+ return 0;
+ }
+
switch (feat) {
case HEADER_TRACE_INFO:
trace_report(fd, false);
break;
-
case HEADER_BUILD_ID:
if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
pr_debug("Failed to read buildids, continuing...\n");
break;
-
- case HEADER_HOSTNAME:
- case HEADER_OSRELEASE:
- case HEADER_VERSION:
- case HEADER_ARCH:
- case HEADER_NRCPUS:
- case HEADER_CPUDESC:
- case HEADER_CPUID:
- case HEADER_TOTAL_MEM:
- case HEADER_CMDLINE:
- case HEADER_EVENT_DESC:
- case HEADER_CPU_TOPOLOGY:
- case HEADER_NUMA_TOPOLOGY:
- break;
-
default:
- pr_debug("unknown feature %d, continuing...\n", feat);
+ break;
}
return 0;
--git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 09365b3..ac4ec95 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -10,7 +10,8 @@
#include <linux/bitmap.h>
enum {
- HEADER_TRACE_INFO = 1,
+ HEADER_RESERVED = 0, /* always cleared */
+ HEADER_TRACE_INFO = 1,
HEADER_BUILD_ID,
HEADER_HOSTNAME,
@@ -27,10 +28,9 @@ enum {
HEADER_NUMA_TOPOLOGY,
HEADER_LAST_FEATURE,
+ HEADER_FEAT_BITS = 256,
};
-#define HEADER_FEAT_BITS 256
-
struct perf_file_section {
u64 offset;
u64 size;
diff --git a/tools/perf/util/include/linux/bitops.h b/tools/perf/util/include/linux/bitops.h
index 305c848..62cdee7 100644
--- a/tools/perf/util/include/linux/bitops.h
+++ b/tools/perf/util/include/linux/bitops.h
@@ -9,6 +9,17 @@
#define BITS_PER_BYTE 8
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+#define for_each_set_bit(bit, addr, size) \
+ for ((bit) = find_first_bit((addr), (size)); \
+ (bit) < (size); \
+ (bit) = find_next_bit((addr), (size), (bit) + 1))
+
+/* same as for_each_set_bit() but use bit as value to start with */
+#define for_each_set_bit_cont(bit, addr, size) \
+ for ((bit) = find_next_bit((addr), (size), (bit)); \
+ (bit) < (size); \
+ (bit) = find_next_bit((addr), (size), (bit) + 1))
+
static inline void set_bit(int nr, unsigned long *addr)
{
addr[nr / BITS_PER_LONG] |= 1UL << (nr % BITS_PER_LONG);
@@ -30,4 +41,111 @@ static inline unsigned long hweight_long(unsigned long w)
return sizeof(w) == 4 ? hweight32(w) : hweight64(w);
}
+#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
+
+/**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ */
+static __always_inline unsigned long __ffs(unsigned long word)
+{
+ int num = 0;
+
+#if BITS_PER_LONG == 64
+ if ((word & 0xffffffff) == 0) {
+ num += 32;
+ word >>= 32;
+ }
+#endif
+ if ((word & 0xffff) == 0) {
+ num += 16;
+ word >>= 16;
+ }
+ if ((word & 0xff) == 0) {
+ num += 8;
+ word >>= 8;
+ }
+ if ((word & 0xf) == 0) {
+ num += 4;
+ word >>= 4;
+ }
+ if ((word & 0x3) == 0) {
+ num += 2;
+ word >>= 2;
+ }
+ if ((word & 0x1) == 0)
+ num += 1;
+ return num;
+}
+
+/*
+ * Find the first set bit in a memory region.
+ */
+static inline unsigned long
+find_first_bit(const unsigned long *addr, unsigned long size)
+{
+ const unsigned long *p = addr;
+ unsigned long result = 0;
+ unsigned long tmp;
+
+ while (size & ~(BITS_PER_LONG-1)) {
+ if ((tmp = *(p++)))
+ goto found;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
+ }
+ if (!size)
+ return result;
+
+ tmp = (*p) & (~0UL >> (BITS_PER_LONG - size));
+ if (tmp == 0UL) /* Are any bits set? */
+ return result + size; /* Nope. */
+found:
+ return result + __ffs(tmp);
+}
+
+/*
+ * Find the next set bit in a memory region.
+ */
+static inline unsigned long
+find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset)
+{
+ const unsigned long *p = addr + BITOP_WORD(offset);
+ unsigned long result = offset & ~(BITS_PER_LONG-1);
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset %= BITS_PER_LONG;
+ if (offset) {
+ tmp = *(p++);
+ tmp &= (~0UL << offset);
+ if (size < BITS_PER_LONG)
+ goto found_first;
+ if (tmp)
+ goto found_middle;
+ size -= BITS_PER_LONG;
+ result += BITS_PER_LONG;
+ }
+ while (size & ~(BITS_PER_LONG-1)) {
+ if ((tmp = *(p++)))
+ goto found_middle;
+ result += BITS_PER_LONG;
+ size -= BITS_PER_LONG;
+ }
+ if (!size)
+ return result;
+ tmp = *p;
+
+found_first:
+ tmp &= (~0UL >> (BITS_PER_LONG - size));
+ if (tmp == 0UL) /* Are any bits set? */
+ return result + size; /* Nope. */
+found_middle:
+ return result + __ffs(tmp);
+}
+
#endif
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* [PATCH 15/15] perf script: Add generic perl handler to process events
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (13 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 14/15] perf tools: Use for_each_set_bit() to iterate over feature flags Arnaldo Carvalho de Melo
@ 2011-12-23 21:53 ` Arnaldo Carvalho de Melo
2011-12-29 20:28 ` [GIT PULL 00/15] perf/core improvements and fixes Ingo Molnar
15 siblings, 0 replies; 17+ messages in thread
From: Arnaldo Carvalho de Melo @ 2011-12-23 21:53 UTC (permalink / raw)
To: Ingo Molnar
Cc: linux-kernel, Robert Richter, Peter Zijlstra, Stephane Eranian,
Arnaldo Carvalho de Melo
From: Robert Richter <robert.richter@amd.com>
The current perf scripting facility only supports tracepoints. This
patch implements a generic perl handler to support other events than
tracepoints too.
This patch introduces a function process_event() that is called by perf
for each sample. The function is called with byte streams as arguments
containing information about the event, its attributes, the sample and
raw data. Perl's unpack() function can easily be used for byte decoding.
The following is the default implementation for process_event() that can
also be generated with perf script:
# Packed byte string args of process_event():
#
# $event: union perf_event util/event.h
# $attr: struct perf_event_attr linux/perf_event.h
# $sample: struct perf_sample util/event.h
# $raw_data: perf_sample->raw_data util/event.h
sub process_event
{
my ($event, $attr, $sample, $raw_data) = @_;
my @event = unpack("LSS", $event);
my @attr = unpack("LLQQQQQLLQQ", $attr);
my @sample = unpack("QLLQQQQQLL", $sample);
my @raw_data = unpack("C*", $raw_data);
use Data::Dumper;
print Dumper \@event, \@attr, \@sample, \@raw_data;
}
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/r/1323969824-9711-4-git-send-email-robert.richter@amd.com
Signed-off-by: Robert Richter <robert.richter@amd.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
.../perf/util/scripting-engines/trace-event-perl.c | 73 ++++++++++++++++++--
1 files changed, 67 insertions(+), 6 deletions(-)
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index a82ce43..e30749e 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -30,6 +30,7 @@
#include "../thread.h"
#include "../event.h"
#include "../trace-event.h"
+#include "../evsel.h"
#include <EXTERN.h>
#include <perl.h>
@@ -247,11 +248,11 @@ static inline struct event *find_cache_event(int type)
return event;
}
-static void perl_process_event(union perf_event *pevent __unused,
- struct perf_sample *sample,
- struct perf_evsel *evsel,
- struct machine *machine __unused,
- struct thread *thread)
+static void perl_process_tracepoint(union perf_event *pevent __unused,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct machine *machine __unused,
+ struct thread *thread)
{
struct format_field *field;
static char handler[256];
@@ -267,6 +268,9 @@ static void perl_process_event(union perf_event *pevent __unused,
dSP;
+ if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
+ return;
+
type = trace_parse_common_type(data);
event = find_cache_event(type);
@@ -334,6 +338,42 @@ static void perl_process_event(union perf_event *pevent __unused,
LEAVE;
}
+static void perl_process_event_generic(union perf_event *pevent __unused,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel __unused,
+ struct machine *machine __unused,
+ struct thread *thread __unused)
+{
+ dSP;
+
+ if (!get_cv("process_event", 0))
+ return;
+
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
+ XPUSHs(sv_2mortal(newSVpvn((const char *)pevent, pevent->header.size)));
+ XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->attr, sizeof(evsel->attr))));
+ XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample))));
+ XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size)));
+ PUTBACK;
+ call_pv("process_event", G_SCALAR);
+ SPAGAIN;
+ PUTBACK;
+ FREETMPS;
+ LEAVE;
+}
+
+static void perl_process_event(union perf_event *pevent,
+ struct perf_sample *sample,
+ struct perf_evsel *evsel,
+ struct machine *machine,
+ struct thread *thread)
+{
+ perl_process_tracepoint(pevent, sample, evsel, machine, thread);
+ perl_process_event_generic(pevent, sample, evsel, machine, thread);
+}
+
static void run_start_sub(void)
{
dSP; /* access to Perl stack */
@@ -555,7 +595,28 @@ static int perl_generate_script(const char *outfile)
fprintf(ofp, "sub print_header\n{\n"
"\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"
"\tprintf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \",\n\t "
- "$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}");
+ "$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}\n");
+
+ fprintf(ofp,
+ "\n# Packed byte string args of process_event():\n"
+ "#\n"
+ "# $event:\tunion perf_event\tutil/event.h\n"
+ "# $attr:\tstruct perf_event_attr\tlinux/perf_event.h\n"
+ "# $sample:\tstruct perf_sample\tutil/event.h\n"
+ "# $raw_data:\tperf_sample->raw_data\tutil/event.h\n"
+ "\n"
+ "sub process_event\n"
+ "{\n"
+ "\tmy ($event, $attr, $sample, $raw_data) = @_;\n"
+ "\n"
+ "\tmy @event\t= unpack(\"LSS\", $event);\n"
+ "\tmy @attr\t= unpack(\"LLQQQQQLLQQ\", $attr);\n"
+ "\tmy @sample\t= unpack(\"QLLQQQQQLL\", $sample);\n"
+ "\tmy @raw_data\t= unpack(\"C*\", $raw_data);\n"
+ "\n"
+ "\tuse Data::Dumper;\n"
+ "\tprint Dumper \\@event, \\@attr, \\@sample, \\@raw_data;\n"
+ "}\n");
fclose(ofp);
--
1.7.8.rc0.35.gee6df
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: [GIT PULL 00/15] perf/core improvements and fixes
2011-12-23 21:53 [GIT PULL 00/15] perf/core improvements and fixes Arnaldo Carvalho de Melo
` (14 preceding siblings ...)
2011-12-23 21:53 ` [PATCH 15/15] perf script: Add generic perl handler to process events Arnaldo Carvalho de Melo
@ 2011-12-29 20:28 ` Ingo Molnar
15 siblings, 0 replies; 17+ messages in thread
From: Ingo Molnar @ 2011-12-29 20:28 UTC (permalink / raw)
To: Arnaldo Carvalho de Melo
Cc: linux-kernel, David Ahern, Frederic Weisbecker, Namhyung Kim,
Nelson Elhage, Paul Mackerras, Peter Zijlstra, Robert Richter,
Stephane Eranian, arnaldo.melo
* Arnaldo Carvalho de Melo <acme@infradead.org> wrote:
> Hi Ingo,
>
> Please consider pulling from:
>
> git://github.com/acmel/linux.git perf/core
>
> Regards,
>
> - Arnaldo
>
> David Ahern (3):
> perf tools: Fix comm for processes with named threads
> perf tools: Look up thread names for system wide profiling
> perf script: look up thread using tid instead of pid
>
> Ingo Molnar (1):
> perf tools: Fix truncated annotation
>
> Namhyung Kim (1):
> perf report: Fix usage string
>
> Nelson Elhage (2):
> perf: builtin-record: Provide advice if mmap'ing fails with EPERM.
> perf: builtin-record: Document and check that mmap_pages must be a power of two.
>
> Robert Richter (8):
> perf tools: Improve macros for struct feature_ops
> perf tools: Continue processing header on unknown features
> perf tools: Fix out-of-bound access to struct perf_session
> perf tools: Moving code in some files
> perf report: Accept fifos as input file
> perf tools: Unify handling of features when writing feature section
> perf tools: Use for_each_set_bit() to iterate over feature flags
> perf script: Add generic perl handler to process events
>
> tools/perf/Documentation/perf-annotate.txt | 2 +-
> tools/perf/Documentation/perf-buildid-list.txt | 2 +-
> tools/perf/Documentation/perf-evlist.txt | 2 +-
> tools/perf/Documentation/perf-kmem.txt | 2 +-
> tools/perf/Documentation/perf-lock.txt | 2 +-
> tools/perf/Documentation/perf-record.txt | 2 +-
> tools/perf/Documentation/perf-report.txt | 2 +-
> tools/perf/Documentation/perf-sched.txt | 2 +-
> tools/perf/Documentation/perf-script.txt | 2 +-
> tools/perf/Documentation/perf-timechart.txt | 2 +-
> tools/perf/builtin-annotate.c | 3 +-
> tools/perf/builtin-buildid-list.c | 53 +-
> tools/perf/builtin-evlist.c | 2 +-
> tools/perf/builtin-kmem.c | 2 +-
> tools/perf/builtin-lock.c | 2 +-
> tools/perf/builtin-record.c | 19 +-
> tools/perf/builtin-report.c | 15 +-
> tools/perf/builtin-sched.c | 2 +-
> tools/perf/builtin-script.c | 6 +-
> tools/perf/builtin-timechart.c | 4 +-
> tools/perf/util/annotate.c | 2 +-
> tools/perf/util/event.c | 112 +++-
> tools/perf/util/evlist.c | 2 +
> tools/perf/util/header.c | 663 +++++++++-----------
> tools/perf/util/header.h | 6 +-
> tools/perf/util/include/linux/bitops.h | 118 ++++
> .../perf/util/scripting-engines/trace-event-perl.c | 73 ++-
> tools/perf/util/session.c | 15 +-
> tools/perf/util/session.h | 2 +-
> tools/perf/util/util.h | 11 +
> 30 files changed, 676 insertions(+), 456 deletions(-)
Pulled, thanks a lot Arnaldo!
FYI, i fixed a trivial build failure, in:
f2328062726d: perf tools: Fix feature-bits rework fallout, remove unused variable
Thanks,
Ingo
^ permalink raw reply [flat|nested] 17+ messages in thread