diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2009-06-04 10:53:49 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-06-04 11:51:39 -0400 |
commit | 62fc44536c14b5787531bac7417580fca54c88b4 (patch) | |
tree | 6b43ae4d32a1087f5e1bfa04d323fae8067a8ce4 /Documentation/perf_counter | |
parent | d99e9446200c1ffab28cb0e39b76c34a2bfafd06 (diff) |
perf_counter tools: Use fork and remove munmap events
Use fork events to clone comm and map data and remove everything
munmap related
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'Documentation/perf_counter')
-rw-r--r-- | Documentation/perf_counter/builtin-report.c | 103 | ||||
-rw-r--r-- | Documentation/perf_counter/builtin-top.c | 21 |
2 files changed, 93 insertions, 31 deletions
diff --git a/Documentation/perf_counter/builtin-report.c b/Documentation/perf_counter/builtin-report.c index 389ae2569f49..5d191216c80a 100644 --- a/Documentation/perf_counter/builtin-report.c +++ b/Documentation/perf_counter/builtin-report.c | |||
@@ -43,12 +43,6 @@ static int full_paths; | |||
43 | static unsigned long page_size; | 43 | static unsigned long page_size; |
44 | static unsigned long mmap_window = 32; | 44 | static unsigned long mmap_window = 32; |
45 | 45 | ||
46 | const char *perf_event_names[] = { | ||
47 | [PERF_EVENT_MMAP] = " PERF_EVENT_MMAP", | ||
48 | [PERF_EVENT_MUNMAP] = " PERF_EVENT_MUNMAP", | ||
49 | [PERF_EVENT_COMM] = " PERF_EVENT_COMM", | ||
50 | }; | ||
51 | |||
52 | struct ip_event { | 46 | struct ip_event { |
53 | struct perf_event_header header; | 47 | struct perf_event_header header; |
54 | __u64 ip; | 48 | __u64 ip; |
@@ -70,11 +64,17 @@ struct comm_event { | |||
70 | char comm[16]; | 64 | char comm[16]; |
71 | }; | 65 | }; |
72 | 66 | ||
67 | struct fork_event { | ||
68 | struct perf_event_header header; | ||
69 | __u32 pid, ppid; | ||
70 | }; | ||
71 | |||
73 | typedef union event_union { | 72 | typedef union event_union { |
74 | struct perf_event_header header; | 73 | struct perf_event_header header; |
75 | struct ip_event ip; | 74 | struct ip_event ip; |
76 | struct mmap_event mmap; | 75 | struct mmap_event mmap; |
77 | struct comm_event comm; | 76 | struct comm_event comm; |
77 | struct fork_event fork; | ||
78 | } event_t; | 78 | } event_t; |
79 | 79 | ||
80 | static LIST_HEAD(dsos); | 80 | static LIST_HEAD(dsos); |
@@ -208,7 +208,31 @@ out_delete: | |||
208 | return NULL; | 208 | return NULL; |
209 | } | 209 | } |
210 | 210 | ||
211 | struct thread; | 211 | static struct map *map__clone(struct map *self) |
212 | { | ||
213 | struct map *map = malloc(sizeof(*self)); | ||
214 | |||
215 | if (!map) | ||
216 | return NULL; | ||
217 | |||
218 | memcpy(map, self, sizeof(*self)); | ||
219 | |||
220 | return map; | ||
221 | } | ||
222 | |||
223 | static int map__overlap(struct map *l, struct map *r) | ||
224 | { | ||
225 | if (l->start > r->start) { | ||
226 | struct map *t = l; | ||
227 | l = r; | ||
228 | r = t; | ||
229 | } | ||
230 | |||
231 | if (l->end > r->start) | ||
232 | return 1; | ||
233 | |||
234 | return 0; | ||
235 | } | ||
212 | 236 | ||
213 | struct thread { | 237 | struct thread { |
214 | struct rb_node rb_node; | 238 | struct rb_node rb_node; |
@@ -284,9 +308,39 @@ static struct thread *threads__findnew(pid_t pid) | |||
284 | 308 | ||
285 | static void thread__insert_map(struct thread *self, struct map *map) | 309 | static void thread__insert_map(struct thread *self, struct map *map) |
286 | { | 310 | { |
311 | struct map *pos, *tmp; | ||
312 | |||
313 | list_for_each_entry_safe(pos, tmp, &self->maps, node) { | ||
314 | if (map__overlap(pos, map)) { | ||
315 | list_del_init(&pos->node); | ||
316 | /* XXX leaks dsos */ | ||
317 | free(pos); | ||
318 | } | ||
319 | } | ||
320 | |||
287 | list_add_tail(&map->node, &self->maps); | 321 | list_add_tail(&map->node, &self->maps); |
288 | } | 322 | } |
289 | 323 | ||
324 | static int thread__fork(struct thread *self, struct thread *parent) | ||
325 | { | ||
326 | struct map *map; | ||
327 | |||
328 | if (self->comm) | ||
329 | free(self->comm); | ||
330 | self->comm = strdup(parent->comm); | ||
331 | if (!self->comm) | ||
332 | return -ENOMEM; | ||
333 | |||
334 | list_for_each_entry(map, &parent->maps, node) { | ||
335 | struct map *new = map__clone(map); | ||
336 | if (!new) | ||
337 | return -ENOMEM; | ||
338 | thread__insert_map(self, new); | ||
339 | } | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
290 | static struct map *thread__find_map(struct thread *self, uint64_t ip) | 344 | static struct map *thread__find_map(struct thread *self, uint64_t ip) |
291 | { | 345 | { |
292 | struct map *pos; | 346 | struct map *pos; |
@@ -784,7 +838,11 @@ static void register_idle_thread(void) | |||
784 | } | 838 | } |
785 | } | 839 | } |
786 | 840 | ||
787 | static unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0; | 841 | static unsigned long total = 0, |
842 | total_mmap = 0, | ||
843 | total_comm = 0, | ||
844 | total_fork = 0, | ||
845 | total_unknown = 0; | ||
788 | 846 | ||
789 | static int | 847 | static int |
790 | process_overflow_event(event_t *event, unsigned long offset, unsigned long head) | 848 | process_overflow_event(event_t *event, unsigned long offset, unsigned long head) |
@@ -866,9 +924,10 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head) | |||
866 | struct thread *thread = threads__findnew(event->mmap.pid); | 924 | struct thread *thread = threads__findnew(event->mmap.pid); |
867 | struct map *map = map__new(&event->mmap); | 925 | struct map *map = map__new(&event->mmap); |
868 | 926 | ||
869 | dprintf("%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n", | 927 | dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", |
870 | (void *)(offset + head), | 928 | (void *)(offset + head), |
871 | (void *)(long)(event->header.size), | 929 | (void *)(long)(event->header.size), |
930 | event->mmap.pid, | ||
872 | (void *)(long)event->mmap.start, | 931 | (void *)(long)event->mmap.start, |
873 | (void *)(long)event->mmap.len, | 932 | (void *)(long)event->mmap.len, |
874 | (void *)(long)event->mmap.pgoff, | 933 | (void *)(long)event->mmap.pgoff, |
@@ -906,6 +965,26 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head) | |||
906 | } | 965 | } |
907 | 966 | ||
908 | static int | 967 | static int |
968 | process_fork_event(event_t *event, unsigned long offset, unsigned long head) | ||
969 | { | ||
970 | struct thread *thread = threads__findnew(event->fork.pid); | ||
971 | struct thread *parent = threads__findnew(event->fork.ppid); | ||
972 | |||
973 | dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", | ||
974 | (void *)(offset + head), | ||
975 | (void *)(long)(event->header.size), | ||
976 | event->fork.pid, event->fork.ppid); | ||
977 | |||
978 | if (!thread || !parent || thread__fork(thread, parent)) { | ||
979 | dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); | ||
980 | return -1; | ||
981 | } | ||
982 | total_fork++; | ||
983 | |||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | static int | ||
909 | process_event(event_t *event, unsigned long offset, unsigned long head) | 988 | process_event(event_t *event, unsigned long offset, unsigned long head) |
910 | { | 989 | { |
911 | if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) | 990 | if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) |
@@ -918,10 +997,13 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
918 | case PERF_EVENT_COMM: | 997 | case PERF_EVENT_COMM: |
919 | return process_comm_event(event, offset, head); | 998 | return process_comm_event(event, offset, head); |
920 | 999 | ||
1000 | case PERF_EVENT_FORK: | ||
1001 | return process_fork_event(event, offset, head); | ||
1002 | |||
921 | /* | 1003 | /* |
922 | * We dont process them right now but they are fine: | 1004 | * We dont process them right now but they are fine: |
923 | */ | 1005 | */ |
924 | case PERF_EVENT_MUNMAP: | 1006 | |
925 | case PERF_EVENT_PERIOD: | 1007 | case PERF_EVENT_PERIOD: |
926 | case PERF_EVENT_THROTTLE: | 1008 | case PERF_EVENT_THROTTLE: |
927 | case PERF_EVENT_UNTHROTTLE: | 1009 | case PERF_EVENT_UNTHROTTLE: |
@@ -1038,6 +1120,7 @@ more: | |||
1038 | dprintf(" IP events: %10ld\n", total); | 1120 | dprintf(" IP events: %10ld\n", total); |
1039 | dprintf(" mmap events: %10ld\n", total_mmap); | 1121 | dprintf(" mmap events: %10ld\n", total_mmap); |
1040 | dprintf(" comm events: %10ld\n", total_comm); | 1122 | dprintf(" comm events: %10ld\n", total_comm); |
1123 | dprintf(" fork events: %10ld\n", total_fork); | ||
1041 | dprintf(" unknown events: %10ld\n", total_unknown); | 1124 | dprintf(" unknown events: %10ld\n", total_unknown); |
1042 | 1125 | ||
1043 | if (dump_trace) | 1126 | if (dump_trace) |
diff --git a/Documentation/perf_counter/builtin-top.c b/Documentation/perf_counter/builtin-top.c index 20e5b1200959..31c00ba99b14 100644 --- a/Documentation/perf_counter/builtin-top.c +++ b/Documentation/perf_counter/builtin-top.c | |||
@@ -75,8 +75,6 @@ static unsigned int realtime_prio = 0; | |||
75 | static int group = 0; | 75 | static int group = 0; |
76 | static unsigned int page_size; | 76 | static unsigned int page_size; |
77 | static unsigned int mmap_pages = 16; | 77 | static unsigned int mmap_pages = 16; |
78 | static int use_mmap = 0; | ||
79 | static int use_munmap = 0; | ||
80 | static int freq = 0; | 78 | static int freq = 0; |
81 | 79 | ||
82 | static char *sym_filter; | 80 | static char *sym_filter; |
@@ -527,19 +525,6 @@ static void mmap_read(struct mmap_data *md) | |||
527 | if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) { | 525 | if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) { |
528 | if (event->header.type & PERF_SAMPLE_IP) | 526 | if (event->header.type & PERF_SAMPLE_IP) |
529 | process_event(event->ip.ip, md->counter); | 527 | process_event(event->ip.ip, md->counter); |
530 | } else { | ||
531 | switch (event->header.type) { | ||
532 | case PERF_EVENT_MMAP: | ||
533 | case PERF_EVENT_MUNMAP: | ||
534 | printf("%s: %Lu %Lu %Lu %s\n", | ||
535 | event->header.type == PERF_EVENT_MMAP | ||
536 | ? "mmap" : "munmap", | ||
537 | event->mmap.start, | ||
538 | event->mmap.len, | ||
539 | event->mmap.pgoff, | ||
540 | event->mmap.filename); | ||
541 | break; | ||
542 | } | ||
543 | } | 528 | } |
544 | } | 529 | } |
545 | 530 | ||
@@ -569,8 +554,6 @@ static int __cmd_top(void) | |||
569 | attr.config = event_id[counter]; | 554 | attr.config = event_id[counter]; |
570 | attr.sample_period = event_count[counter]; | 555 | attr.sample_period = event_count[counter]; |
571 | attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; | 556 | attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; |
572 | attr.mmap = use_mmap; | ||
573 | attr.munmap = use_munmap; | ||
574 | attr.freq = freq; | 557 | attr.freq = freq; |
575 | 558 | ||
576 | fd[i][counter] = sys_perf_counter_open(&attr, target_pid, cpu, group_fd, 0); | 559 | fd[i][counter] = sys_perf_counter_open(&attr, target_pid, cpu, group_fd, 0); |
@@ -670,10 +653,6 @@ static const struct option options[] = { | |||
670 | "only display symbols matchig this pattern"), | 653 | "only display symbols matchig this pattern"), |
671 | OPT_BOOLEAN('z', "zero", &group, | 654 | OPT_BOOLEAN('z', "zero", &group, |
672 | "zero history across updates"), | 655 | "zero history across updates"), |
673 | OPT_BOOLEAN('M', "use-mmap", &use_mmap, | ||
674 | "track mmap events"), | ||
675 | OPT_BOOLEAN('U', "use-munmap", &use_munmap, | ||
676 | "track munmap events"), | ||
677 | OPT_INTEGER('F', "freq", &freq, | 656 | OPT_INTEGER('F', "freq", &freq, |
678 | "profile at this frequency"), | 657 | "profile at this frequency"), |
679 | OPT_INTEGER('E', "entries", &print_entries, | 658 | OPT_INTEGER('E', "entries", &print_entries, |