aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2012-10-06 15:26:02 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-10-06 15:34:13 -0400
commitb0a7d1a0cd2e228dc06d099db2e1bb02f1b7d591 (patch)
treee943d42d36229261829b7c51978ecd1ee649a59a
parent0439539f72ea222fbfe511b47318b9c1815a7108 (diff)
perf machine: Carve up event processing specific from perf_tool
The perf_tool vtable expects methods that receive perf_tool and perf_sample entries, but for tools not interested in doing any special processing on non PERF_RECORD_SAMPLE events, like 'perf top', and for those not using perf_session, like 'perf trace', they were using perf_event__process passing tool and sample paramenters that were just not used. Provide 'machine' methods for this purpose and make the perf_event ones use them. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-ot9cc6mt025o8kbngzckcrx9@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/builtin-top.c3
-rw-r--r--tools/perf/util/event.c211
-rw-r--r--tools/perf/util/machine.c220
-rw-r--r--tools/perf/util/machine.h8
4 files changed, 242 insertions, 200 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index ff6db8086805..fb9da71eba1f 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -26,6 +26,7 @@
26#include "util/color.h" 26#include "util/color.h"
27#include "util/evlist.h" 27#include "util/evlist.h"
28#include "util/evsel.h" 28#include "util/evsel.h"
29#include "util/machine.h"
29#include "util/session.h" 30#include "util/session.h"
30#include "util/symbol.h" 31#include "util/symbol.h"
31#include "util/thread.h" 32#include "util/thread.h"
@@ -871,7 +872,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
871 &sample, machine); 872 &sample, machine);
872 } else if (event->header.type < PERF_RECORD_MAX) { 873 } else if (event->header.type < PERF_RECORD_MAX) {
873 hists__inc_nr_events(&evsel->hists, event->header.type); 874 hists__inc_nr_events(&evsel->hists, event->header.type);
874 perf_event__process(&top->tool, event, &sample, machine); 875 machine__process_event(machine, event);
875 } else 876 } else
876 ++session->hists.stats.nr_unknown_events; 877 ++session->hists.stats.nr_unknown_events;
877 } 878 }
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index eaaee22628ea..0ae444ef1429 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -520,134 +520,15 @@ int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
520 struct perf_sample *sample __maybe_unused, 520 struct perf_sample *sample __maybe_unused,
521 struct machine *machine) 521 struct machine *machine)
522{ 522{
523 struct thread *thread = machine__findnew_thread(machine, event->comm.tid); 523 return machine__process_comm_event(machine, event);
524
525 if (dump_trace)
526 perf_event__fprintf_comm(event, stdout);
527
528 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
529 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
530 return -1;
531 }
532
533 return 0;
534} 524}
535 525
536int perf_event__process_lost(struct perf_tool *tool __maybe_unused, 526int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
537 union perf_event *event, 527 union perf_event *event,
538 struct perf_sample *sample __maybe_unused, 528 struct perf_sample *sample __maybe_unused,
539 struct machine *machine __maybe_unused) 529 struct machine *machine)
540{
541 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
542 event->lost.id, event->lost.lost);
543 return 0;
544}
545
546static void perf_event__set_kernel_mmap_len(union perf_event *event,
547 struct map **maps)
548{
549 maps[MAP__FUNCTION]->start = event->mmap.start;
550 maps[MAP__FUNCTION]->end = event->mmap.start + event->mmap.len;
551 /*
552 * Be a bit paranoid here, some perf.data file came with
553 * a zero sized synthesized MMAP event for the kernel.
554 */
555 if (maps[MAP__FUNCTION]->end == 0)
556 maps[MAP__FUNCTION]->end = ~0ULL;
557}
558
559static int perf_event__process_kernel_mmap(struct perf_tool *tool
560 __maybe_unused,
561 union perf_event *event,
562 struct machine *machine)
563{ 530{
564 struct map *map; 531 return machine__process_lost_event(machine, event);
565 char kmmap_prefix[PATH_MAX];
566 enum dso_kernel_type kernel_type;
567 bool is_kernel_mmap;
568
569 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
570 if (machine__is_host(machine))
571 kernel_type = DSO_TYPE_KERNEL;
572 else
573 kernel_type = DSO_TYPE_GUEST_KERNEL;
574
575 is_kernel_mmap = memcmp(event->mmap.filename,
576 kmmap_prefix,
577 strlen(kmmap_prefix) - 1) == 0;
578 if (event->mmap.filename[0] == '/' ||
579 (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
580
581 char short_module_name[1024];
582 char *name, *dot;
583
584 if (event->mmap.filename[0] == '/') {
585 name = strrchr(event->mmap.filename, '/');
586 if (name == NULL)
587 goto out_problem;
588
589 ++name; /* skip / */
590 dot = strrchr(name, '.');
591 if (dot == NULL)
592 goto out_problem;
593 snprintf(short_module_name, sizeof(short_module_name),
594 "[%.*s]", (int)(dot - name), name);
595 strxfrchar(short_module_name, '-', '_');
596 } else
597 strcpy(short_module_name, event->mmap.filename);
598
599 map = machine__new_module(machine, event->mmap.start,
600 event->mmap.filename);
601 if (map == NULL)
602 goto out_problem;
603
604 name = strdup(short_module_name);
605 if (name == NULL)
606 goto out_problem;
607
608 map->dso->short_name = name;
609 map->dso->sname_alloc = 1;
610 map->end = map->start + event->mmap.len;
611 } else if (is_kernel_mmap) {
612 const char *symbol_name = (event->mmap.filename +
613 strlen(kmmap_prefix));
614 /*
615 * Should be there already, from the build-id table in
616 * the header.
617 */
618 struct dso *kernel = __dsos__findnew(&machine->kernel_dsos,
619 kmmap_prefix);
620 if (kernel == NULL)
621 goto out_problem;
622
623 kernel->kernel = kernel_type;
624 if (__machine__create_kernel_maps(machine, kernel) < 0)
625 goto out_problem;
626
627 perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps);
628
629 /*
630 * Avoid using a zero address (kptr_restrict) for the ref reloc
631 * symbol. Effectively having zero here means that at record
632 * time /proc/sys/kernel/kptr_restrict was non zero.
633 */
634 if (event->mmap.pgoff != 0) {
635 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
636 symbol_name,
637 event->mmap.pgoff);
638 }
639
640 if (machine__is_default_guest(machine)) {
641 /*
642 * preload dso of guest kernel and modules
643 */
644 dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION],
645 NULL);
646 }
647 }
648 return 0;
649out_problem:
650 return -1;
651} 532}
652 533
653size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) 534size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
@@ -657,43 +538,12 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
657 event->mmap.len, event->mmap.pgoff, event->mmap.filename); 538 event->mmap.len, event->mmap.pgoff, event->mmap.filename);
658} 539}
659 540
660int perf_event__process_mmap(struct perf_tool *tool, 541int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
661 union perf_event *event, 542 union perf_event *event,
662 struct perf_sample *sample __maybe_unused, 543 struct perf_sample *sample __maybe_unused,
663 struct machine *machine) 544 struct machine *machine)
664{ 545{
665 struct thread *thread; 546 return machine__process_mmap_event(machine, event);
666 struct map *map;
667 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
668 int ret = 0;
669
670 if (dump_trace)
671 perf_event__fprintf_mmap(event, stdout);
672
673 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
674 cpumode == PERF_RECORD_MISC_KERNEL) {
675 ret = perf_event__process_kernel_mmap(tool, event, machine);
676 if (ret < 0)
677 goto out_problem;
678 return 0;
679 }
680
681 thread = machine__findnew_thread(machine, event->mmap.pid);
682 if (thread == NULL)
683 goto out_problem;
684 map = map__new(&machine->user_dsos, event->mmap.start,
685 event->mmap.len, event->mmap.pgoff,
686 event->mmap.pid, event->mmap.filename,
687 MAP__FUNCTION);
688 if (map == NULL)
689 goto out_problem;
690
691 thread__insert_map(thread, map);
692 return 0;
693
694out_problem:
695 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
696 return 0;
697} 547}
698 548
699size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) 549size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
@@ -708,19 +558,7 @@ int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
708 struct perf_sample *sample __maybe_unused, 558 struct perf_sample *sample __maybe_unused,
709 struct machine *machine) 559 struct machine *machine)
710{ 560{
711 struct thread *thread = machine__findnew_thread(machine, event->fork.tid); 561 return machine__process_fork_event(machine, event);
712 struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
713
714 if (dump_trace)
715 perf_event__fprintf_task(event, stdout);
716
717 if (thread == NULL || parent == NULL ||
718 thread__fork(thread, parent) < 0) {
719 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
720 return -1;
721 }
722
723 return 0;
724} 562}
725 563
726int perf_event__process_exit(struct perf_tool *tool __maybe_unused, 564int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
@@ -728,15 +566,7 @@ int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
728 struct perf_sample *sample __maybe_unused, 566 struct perf_sample *sample __maybe_unused,
729 struct machine *machine) 567 struct machine *machine)
730{ 568{
731 struct thread *thread = machine__find_thread(machine, event->fork.tid); 569 return machine__process_exit_event(machine, event);
732
733 if (dump_trace)
734 perf_event__fprintf_task(event, stdout);
735
736 if (thread != NULL)
737 machine__remove_thread(machine, thread);
738
739 return 0;
740} 570}
741 571
742size_t perf_event__fprintf(union perf_event *event, FILE *fp) 572size_t perf_event__fprintf(union perf_event *event, FILE *fp)
@@ -762,29 +592,12 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
762 return ret; 592 return ret;
763} 593}
764 594
765int perf_event__process(struct perf_tool *tool, union perf_event *event, 595int perf_event__process(struct perf_tool *tool __maybe_unused,
766 struct perf_sample *sample, struct machine *machine) 596 union perf_event *event,
597 struct perf_sample *sample __maybe_unused,
598 struct machine *machine)
767{ 599{
768 switch (event->header.type) { 600 return machine__process_event(machine, event);
769 case PERF_RECORD_COMM:
770 perf_event__process_comm(tool, event, sample, machine);
771 break;
772 case PERF_RECORD_MMAP:
773 perf_event__process_mmap(tool, event, sample, machine);
774 break;
775 case PERF_RECORD_FORK:
776 perf_event__process_fork(tool, event, sample, machine);
777 break;
778 case PERF_RECORD_EXIT:
779 perf_event__process_exit(tool, event, sample, machine);
780 break;
781 case PERF_RECORD_LOST:
782 perf_event__process_lost(tool, event, sample, machine);
783 default:
784 break;
785 }
786
787 return 0;
788} 601}
789 602
790void thread__find_addr_map(struct thread *self, 603void thread__find_addr_map(struct thread *self,
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 9d36d7eeda92..502eec0d4773 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1,3 +1,5 @@
1#include "debug.h"
2#include "event.h"
1#include "machine.h" 3#include "machine.h"
2#include "map.h" 4#include "map.h"
3#include "thread.h" 5#include "thread.h"
@@ -55,3 +57,221 @@ struct thread *machine__find_thread(struct machine *machine, pid_t pid)
55{ 57{
56 return __machine__findnew_thread(machine, pid, false); 58 return __machine__findnew_thread(machine, pid, false);
57} 59}
60
61int machine__process_comm_event(struct machine *machine, union perf_event *event)
62{
63 struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
64
65 if (dump_trace)
66 perf_event__fprintf_comm(event, stdout);
67
68 if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
69 dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
70 return -1;
71 }
72
73 return 0;
74}
75
76int machine__process_lost_event(struct machine *machine __maybe_unused,
77 union perf_event *event)
78{
79 dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
80 event->lost.id, event->lost.lost);
81 return 0;
82}
83
84static void machine__set_kernel_mmap_len(struct machine *machine,
85 union perf_event *event)
86{
87 machine->vmlinux_maps[MAP__FUNCTION]->start = event->mmap.start;
88 machine->vmlinux_maps[MAP__FUNCTION]->end = (event->mmap.start +
89 event->mmap.len);
90 /*
91 * Be a bit paranoid here, some perf.data file came with
92 * a zero sized synthesized MMAP event for the kernel.
93 */
94 if (machine->vmlinux_maps[MAP__FUNCTION]->end == 0)
95 machine->vmlinux_maps[MAP__FUNCTION]->end = ~0ULL;
96}
97
98static int machine__process_kernel_mmap_event(struct machine *machine,
99 union perf_event *event)
100{
101 struct map *map;
102 char kmmap_prefix[PATH_MAX];
103 enum dso_kernel_type kernel_type;
104 bool is_kernel_mmap;
105
106 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
107 if (machine__is_host(machine))
108 kernel_type = DSO_TYPE_KERNEL;
109 else
110 kernel_type = DSO_TYPE_GUEST_KERNEL;
111
112 is_kernel_mmap = memcmp(event->mmap.filename,
113 kmmap_prefix,
114 strlen(kmmap_prefix) - 1) == 0;
115 if (event->mmap.filename[0] == '/' ||
116 (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
117
118 char short_module_name[1024];
119 char *name, *dot;
120
121 if (event->mmap.filename[0] == '/') {
122 name = strrchr(event->mmap.filename, '/');
123 if (name == NULL)
124 goto out_problem;
125
126 ++name; /* skip / */
127 dot = strrchr(name, '.');
128 if (dot == NULL)
129 goto out_problem;
130 snprintf(short_module_name, sizeof(short_module_name),
131 "[%.*s]", (int)(dot - name), name);
132 strxfrchar(short_module_name, '-', '_');
133 } else
134 strcpy(short_module_name, event->mmap.filename);
135
136 map = machine__new_module(machine, event->mmap.start,
137 event->mmap.filename);
138 if (map == NULL)
139 goto out_problem;
140
141 name = strdup(short_module_name);
142 if (name == NULL)
143 goto out_problem;
144
145 map->dso->short_name = name;
146 map->dso->sname_alloc = 1;
147 map->end = map->start + event->mmap.len;
148 } else if (is_kernel_mmap) {
149 const char *symbol_name = (event->mmap.filename +
150 strlen(kmmap_prefix));
151 /*
152 * Should be there already, from the build-id table in
153 * the header.
154 */
155 struct dso *kernel = __dsos__findnew(&machine->kernel_dsos,
156 kmmap_prefix);
157 if (kernel == NULL)
158 goto out_problem;
159
160 kernel->kernel = kernel_type;
161 if (__machine__create_kernel_maps(machine, kernel) < 0)
162 goto out_problem;
163
164 machine__set_kernel_mmap_len(machine, event);
165
166 /*
167 * Avoid using a zero address (kptr_restrict) for the ref reloc
168 * symbol. Effectively having zero here means that at record
169 * time /proc/sys/kernel/kptr_restrict was non zero.
170 */
171 if (event->mmap.pgoff != 0) {
172 maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
173 symbol_name,
174 event->mmap.pgoff);
175 }
176
177 if (machine__is_default_guest(machine)) {
178 /*
179 * preload dso of guest kernel and modules
180 */
181 dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION],
182 NULL);
183 }
184 }
185 return 0;
186out_problem:
187 return -1;
188}
189
190int machine__process_mmap_event(struct machine *machine, union perf_event *event)
191{
192 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
193 struct thread *thread;
194 struct map *map;
195 int ret = 0;
196
197 if (dump_trace)
198 perf_event__fprintf_mmap(event, stdout);
199
200 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
201 cpumode == PERF_RECORD_MISC_KERNEL) {
202 ret = machine__process_kernel_mmap_event(machine, event);
203 if (ret < 0)
204 goto out_problem;
205 return 0;
206 }
207
208 thread = machine__findnew_thread(machine, event->mmap.pid);
209 if (thread == NULL)
210 goto out_problem;
211 map = map__new(&machine->user_dsos, event->mmap.start,
212 event->mmap.len, event->mmap.pgoff,
213 event->mmap.pid, event->mmap.filename,
214 MAP__FUNCTION);
215 if (map == NULL)
216 goto out_problem;
217
218 thread__insert_map(thread, map);
219 return 0;
220
221out_problem:
222 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
223 return 0;
224}
225
226int machine__process_fork_event(struct machine *machine, union perf_event *event)
227{
228 struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
229 struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
230
231 if (dump_trace)
232 perf_event__fprintf_task(event, stdout);
233
234 if (thread == NULL || parent == NULL ||
235 thread__fork(thread, parent) < 0) {
236 dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
237 return -1;
238 }
239
240 return 0;
241}
242
243int machine__process_exit_event(struct machine *machine, union perf_event *event)
244{
245 struct thread *thread = machine__find_thread(machine, event->fork.tid);
246
247 if (dump_trace)
248 perf_event__fprintf_task(event, stdout);
249
250 if (thread != NULL)
251 machine__remove_thread(machine, thread);
252
253 return 0;
254}
255
256int machine__process_event(struct machine *machine, union perf_event *event)
257{
258 int ret;
259
260 switch (event->header.type) {
261 case PERF_RECORD_COMM:
262 ret = machine__process_comm_event(machine, event); break;
263 case PERF_RECORD_MMAP:
264 ret = machine__process_mmap_event(machine, event); break;
265 case PERF_RECORD_FORK:
266 ret = machine__process_fork_event(machine, event); break;
267 case PERF_RECORD_EXIT:
268 ret = machine__process_exit_event(machine, event); break;
269 case PERF_RECORD_LOST:
270 ret = machine__process_lost_event(machine, event); break;
271 default:
272 ret = -1;
273 break;
274 }
275
276 return ret;
277}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 54df0cdd3000..df152f1768be 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -5,7 +5,15 @@
5 5
6struct thread; 6struct thread;
7struct machine; 7struct machine;
8union perf_event;
8 9
9struct thread *machine__find_thread(struct machine *machine, pid_t pid); 10struct thread *machine__find_thread(struct machine *machine, pid_t pid);
10 11
12int machine__process_comm_event(struct machine *machine, union perf_event *event);
13int machine__process_exit_event(struct machine *machine, union perf_event *event);
14int machine__process_fork_event(struct machine *machine, union perf_event *event);
15int machine__process_lost_event(struct machine *machine, union perf_event *event);
16int machine__process_mmap_event(struct machine *machine, union perf_event *event);
17int machine__process_event(struct machine *machine, union perf_event *event);
18
11#endif /* __PERF_MACHINE_H */ 19#endif /* __PERF_MACHINE_H */