aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-annotate.c
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-08-14 06:21:53 -0400
committerIngo Molnar <mingo@elte.hu>2009-08-15 10:10:19 -0400
commit6baa0a5ae0954fb2486c480a20556a9f1aee0965 (patch)
treeb85e485562b34b222153d41414dec655724e26b8 /tools/perf/builtin-annotate.c
parentbe750231ce1599b86fbba213e3da8344ece262e2 (diff)
perf tools: Factorize the thread code in a dedicated file
Factorize the thread management code used by perf-annotate and perf-report in dedicated source and header files. v2: pass last_match by address so that it can actually be modified. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Mike Galbraith <efault@gmx.de> LKML-Reference: <1250245313-6995-1-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r--tools/perf/builtin-annotate.c173
1 files changed, 18 insertions, 155 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 543c4524f8c2..3bedaa5d21d2 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -20,6 +20,7 @@
20 20
21#include "util/parse-options.h" 21#include "util/parse-options.h"
22#include "util/parse-events.h" 22#include "util/parse-events.h"
23#include "util/thread.h"
23 24
24#define SHOW_KERNEL 1 25#define SHOW_KERNEL 1
25#define SHOW_USER 2 26#define SHOW_USER 2
@@ -44,6 +45,9 @@ static int print_line;
44static unsigned long page_size; 45static unsigned long page_size;
45static unsigned long mmap_window = 32; 46static unsigned long mmap_window = 32;
46 47
48static struct rb_root threads;
49static struct thread *last_match;
50
47 51
48struct sym_ext { 52struct sym_ext {
49 struct rb_node node; 53 struct rb_node node;
@@ -51,154 +55,6 @@ struct sym_ext {
51 char *path; 55 char *path;
52}; 56};
53 57
54
55struct thread {
56 struct rb_node rb_node;
57 struct list_head maps;
58 pid_t pid;
59 char *comm;
60};
61
62static struct thread *thread__new(pid_t pid)
63{
64 struct thread *self = malloc(sizeof(*self));
65
66 if (self != NULL) {
67 self->pid = pid;
68 self->comm = malloc(32);
69 if (self->comm)
70 snprintf(self->comm, 32, ":%d", self->pid);
71 INIT_LIST_HEAD(&self->maps);
72 }
73
74 return self;
75}
76
77static int thread__set_comm(struct thread *self, const char *comm)
78{
79 if (self->comm)
80 free(self->comm);
81 self->comm = strdup(comm);
82 return self->comm ? 0 : -ENOMEM;
83}
84
85static size_t thread__fprintf(struct thread *self, FILE *fp)
86{
87 struct map *pos;
88 size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm);
89
90 list_for_each_entry(pos, &self->maps, node)
91 ret += map__fprintf(pos, fp);
92
93 return ret;
94}
95
96
97static struct rb_root threads;
98static struct thread *last_match;
99
100static struct thread *threads__findnew(pid_t pid)
101{
102 struct rb_node **p = &threads.rb_node;
103 struct rb_node *parent = NULL;
104 struct thread *th;
105
106 /*
107 * Font-end cache - PID lookups come in blocks,
108 * so most of the time we dont have to look up
109 * the full rbtree:
110 */
111 if (last_match && last_match->pid == pid)
112 return last_match;
113
114 while (*p != NULL) {
115 parent = *p;
116 th = rb_entry(parent, struct thread, rb_node);
117
118 if (th->pid == pid) {
119 last_match = th;
120 return th;
121 }
122
123 if (pid < th->pid)
124 p = &(*p)->rb_left;
125 else
126 p = &(*p)->rb_right;
127 }
128
129 th = thread__new(pid);
130 if (th != NULL) {
131 rb_link_node(&th->rb_node, parent, p);
132 rb_insert_color(&th->rb_node, &threads);
133 last_match = th;
134 }
135
136 return th;
137}
138
139static void thread__insert_map(struct thread *self, struct map *map)
140{
141 struct map *pos, *tmp;
142
143 list_for_each_entry_safe(pos, tmp, &self->maps, node) {
144 if (map__overlap(pos, map)) {
145 list_del_init(&pos->node);
146 /* XXX leaks dsos */
147 free(pos);
148 }
149 }
150
151 list_add_tail(&map->node, &self->maps);
152}
153
154static int thread__fork(struct thread *self, struct thread *parent)
155{
156 struct map *map;
157
158 if (self->comm)
159 free(self->comm);
160 self->comm = strdup(parent->comm);
161 if (!self->comm)
162 return -ENOMEM;
163
164 list_for_each_entry(map, &parent->maps, node) {
165 struct map *new = map__clone(map);
166 if (!new)
167 return -ENOMEM;
168 thread__insert_map(self, new);
169 }
170
171 return 0;
172}
173
174static struct map *thread__find_map(struct thread *self, u64 ip)
175{
176 struct map *pos;
177
178 if (self == NULL)
179 return NULL;
180
181 list_for_each_entry(pos, &self->maps, node)
182 if (ip >= pos->start && ip <= pos->end)
183 return pos;
184
185 return NULL;
186}
187
188static size_t threads__fprintf(FILE *fp)
189{
190 size_t ret = 0;
191 struct rb_node *nd;
192
193 for (nd = rb_first(&threads); nd; nd = rb_next(nd)) {
194 struct thread *pos = rb_entry(nd, struct thread, rb_node);
195
196 ret += thread__fprintf(pos, fp);
197 }
198
199 return ret;
200}
201
202/* 58/*
203 * histogram, sorted on item, collects counts 59 * histogram, sorted on item, collects counts
204 */ 60 */
@@ -624,7 +480,7 @@ static void output__resort(void)
624 480
625static void register_idle_thread(void) 481static void register_idle_thread(void)
626{ 482{
627 struct thread *thread = threads__findnew(0); 483 struct thread *thread = threads__findnew(0, &threads, &last_match);
628 484
629 if (thread == NULL || 485 if (thread == NULL ||
630 thread__set_comm(thread, "[idle]")) { 486 thread__set_comm(thread, "[idle]")) {
@@ -645,10 +501,12 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
645 char level; 501 char level;
646 int show = 0; 502 int show = 0;
647 struct dso *dso = NULL; 503 struct dso *dso = NULL;
648 struct thread *thread = threads__findnew(event->ip.pid); 504 struct thread *thread;
649 u64 ip = event->ip.ip; 505 u64 ip = event->ip.ip;
650 struct map *map = NULL; 506 struct map *map = NULL;
651 507
508 thread = threads__findnew(event->ip.pid, &threads, &last_match);
509
652 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n", 510 dprintf("%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
653 (void *)(offset + head), 511 (void *)(offset + head),
654 (void *)(long)(event->header.size), 512 (void *)(long)(event->header.size),
@@ -719,9 +577,11 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
719static int 577static int
720process_mmap_event(event_t *event, unsigned long offset, unsigned long head) 578process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
721{ 579{
722 struct thread *thread = threads__findnew(event->mmap.pid); 580 struct thread *thread;
723 struct map *map = map__new(&event->mmap, NULL, 0); 581 struct map *map = map__new(&event->mmap, NULL, 0);
724 582
583 thread = threads__findnew(event->mmap.pid, &threads, &last_match);
584
725 dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", 585 dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n",
726 (void *)(offset + head), 586 (void *)(offset + head),
727 (void *)(long)(event->header.size), 587 (void *)(long)(event->header.size),
@@ -745,8 +605,9 @@ process_mmap_event(event_t *event, unsigned long offset, unsigned long head)
745static int 605static int
746process_comm_event(event_t *event, unsigned long offset, unsigned long head) 606process_comm_event(event_t *event, unsigned long offset, unsigned long head)
747{ 607{
748 struct thread *thread = threads__findnew(event->comm.pid); 608 struct thread *thread;
749 609
610 thread = threads__findnew(event->comm.pid, &threads, &last_match);
750 dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n", 611 dprintf("%p [%p]: PERF_EVENT_COMM: %s:%d\n",
751 (void *)(offset + head), 612 (void *)(offset + head),
752 (void *)(long)(event->header.size), 613 (void *)(long)(event->header.size),
@@ -765,9 +626,11 @@ process_comm_event(event_t *event, unsigned long offset, unsigned long head)
765static int 626static int
766process_fork_event(event_t *event, unsigned long offset, unsigned long head) 627process_fork_event(event_t *event, unsigned long offset, unsigned long head)
767{ 628{
768 struct thread *thread = threads__findnew(event->fork.pid); 629 struct thread *thread;
769 struct thread *parent = threads__findnew(event->fork.ppid); 630 struct thread *parent;
770 631
632 thread = threads__findnew(event->fork.pid, &threads, &last_match);
633 parent = threads__findnew(event->fork.ppid, &threads, &last_match);
771 dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n", 634 dprintf("%p [%p]: PERF_EVENT_FORK: %d:%d\n",
772 (void *)(offset + head), 635 (void *)(offset + head),
773 (void *)(long)(event->header.size), 636 (void *)(long)(event->header.size),
@@ -1202,7 +1065,7 @@ more:
1202 return 0; 1065 return 0;
1203 1066
1204 if (verbose >= 3) 1067 if (verbose >= 3)
1205 threads__fprintf(stdout); 1068 threads__fprintf(stdout, &threads);
1206 1069
1207 if (verbose >= 2) 1070 if (verbose >= 2)
1208 dsos__fprintf(stdout); 1071 dsos__fprintf(stdout);