]> git.karo-electronics.de Git - mv-sheeva.git/blob - tools/perf/util/data_map.c
Merge branch 'for-2.6.33' of git://git.kernel.dk/linux-2.6-block
[mv-sheeva.git] / tools / perf / util / data_map.c
1 #include "data_map.h"
2 #include "symbol.h"
3 #include "util.h"
4 #include "debug.h"
5
6
7 static struct perf_file_handler *curr_handler;
8 static unsigned long    mmap_window = 32;
9 static char             __cwd[PATH_MAX];
10
11 static int process_event_stub(event_t *event __used)
12 {
13         dump_printf(": unhandled!\n");
14         return 0;
15 }
16
17 void register_perf_file_handler(struct perf_file_handler *handler)
18 {
19         if (!handler->process_sample_event)
20                 handler->process_sample_event = process_event_stub;
21         if (!handler->process_mmap_event)
22                 handler->process_mmap_event = process_event_stub;
23         if (!handler->process_comm_event)
24                 handler->process_comm_event = process_event_stub;
25         if (!handler->process_fork_event)
26                 handler->process_fork_event = process_event_stub;
27         if (!handler->process_exit_event)
28                 handler->process_exit_event = process_event_stub;
29         if (!handler->process_lost_event)
30                 handler->process_lost_event = process_event_stub;
31         if (!handler->process_read_event)
32                 handler->process_read_event = process_event_stub;
33         if (!handler->process_throttle_event)
34                 handler->process_throttle_event = process_event_stub;
35         if (!handler->process_unthrottle_event)
36                 handler->process_unthrottle_event = process_event_stub;
37
38         curr_handler = handler;
39 }
40
41 static const char *event__name[] = {
42         [0]                      = "TOTAL",
43         [PERF_RECORD_MMAP]       = "MMAP",
44         [PERF_RECORD_LOST]       = "LOST",
45         [PERF_RECORD_COMM]       = "COMM",
46         [PERF_RECORD_EXIT]       = "EXIT",
47         [PERF_RECORD_THROTTLE]   = "THROTTLE",
48         [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE",
49         [PERF_RECORD_FORK]       = "FORK",
50         [PERF_RECORD_READ]       = "READ",
51         [PERF_RECORD_SAMPLE]     = "SAMPLE",
52 };
53
54 unsigned long event__total[PERF_RECORD_MAX];
55
56 void event__print_totals(void)
57 {
58         int i;
59         for (i = 0; i < PERF_RECORD_MAX; ++i)
60                 pr_info("%10s events: %10ld\n",
61                         event__name[i], event__total[i]);
62 }
63
64 static int
65 process_event(event_t *event, unsigned long offset, unsigned long head)
66 {
67         trace_event(event);
68
69         if (event->header.type < PERF_RECORD_MAX) {
70                 dump_printf("%p [%p]: PERF_RECORD_%s",
71                             (void *)(offset + head),
72                             (void *)(long)(event->header.size),
73                             event__name[event->header.type]);
74                 ++event__total[0];
75                 ++event__total[event->header.type];
76         }
77
78         switch (event->header.type) {
79         case PERF_RECORD_SAMPLE:
80                 return curr_handler->process_sample_event(event);
81         case PERF_RECORD_MMAP:
82                 return curr_handler->process_mmap_event(event);
83         case PERF_RECORD_COMM:
84                 return curr_handler->process_comm_event(event);
85         case PERF_RECORD_FORK:
86                 return curr_handler->process_fork_event(event);
87         case PERF_RECORD_EXIT:
88                 return curr_handler->process_exit_event(event);
89         case PERF_RECORD_LOST:
90                 return curr_handler->process_lost_event(event);
91         case PERF_RECORD_READ:
92                 return curr_handler->process_read_event(event);
93         case PERF_RECORD_THROTTLE:
94                 return curr_handler->process_throttle_event(event);
95         case PERF_RECORD_UNTHROTTLE:
96                 return curr_handler->process_unthrottle_event(event);
97         default:
98                 curr_handler->total_unknown++;
99                 return -1;
100         }
101 }
102
103 int perf_header__read_build_ids(int input, u64 offset, u64 size)
104 {
105         struct build_id_event bev;
106         char filename[PATH_MAX];
107         u64 limit = offset + size;
108         int err = -1;
109
110         while (offset < limit) {
111                 struct dso *dso;
112                 ssize_t len;
113
114                 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
115                         goto out;
116
117                 len = bev.header.size - sizeof(bev);
118                 if (read(input, filename, len) != len)
119                         goto out;
120
121                 dso = dsos__findnew(filename);
122                 if (dso != NULL)
123                         dso__set_build_id(dso, &bev.build_id);
124
125                 offset += bev.header.size;
126         }
127         err = 0;
128 out:
129         return err;
130 }
131
132 int perf_session__process_events(struct perf_session *self,
133                                  int full_paths, int *cwdlen, char **cwd)
134 {
135         int err;
136         unsigned long head, shift;
137         unsigned long offset = 0;
138         size_t  page_size;
139         u64 sample_type;
140         event_t *event;
141         uint32_t size;
142         char *buf;
143
144         if (curr_handler == NULL) {
145                 pr_debug("Forgot to register perf file handler\n");
146                 return -EINVAL;
147         }
148
149         page_size = getpagesize();
150
151         head = self->header.data_offset;
152         sample_type = perf_header__sample_type(&self->header);
153
154         err = -EINVAL;
155         if (curr_handler->sample_type_check &&
156             curr_handler->sample_type_check(sample_type) < 0)
157                 goto out_err;
158
159         if (!full_paths) {
160                 if (getcwd(__cwd, sizeof(__cwd)) == NULL) {
161                         pr_err("failed to get the current directory\n");
162                         err = -errno;
163                         goto out_err;
164                 }
165                 *cwd = __cwd;
166                 *cwdlen = strlen(*cwd);
167         } else {
168                 *cwd = NULL;
169                 *cwdlen = 0;
170         }
171
172         shift = page_size * (head / page_size);
173         offset += shift;
174         head -= shift;
175
176 remap:
177         buf = mmap(NULL, page_size * mmap_window, PROT_READ,
178                    MAP_SHARED, self->fd, offset);
179         if (buf == MAP_FAILED) {
180                 pr_err("failed to mmap file\n");
181                 err = -errno;
182                 goto out_err;
183         }
184
185 more:
186         event = (event_t *)(buf + head);
187
188         size = event->header.size;
189         if (!size)
190                 size = 8;
191
192         if (head + event->header.size >= page_size * mmap_window) {
193                 int munmap_ret;
194
195                 shift = page_size * (head / page_size);
196
197                 munmap_ret = munmap(buf, page_size * mmap_window);
198                 assert(munmap_ret == 0);
199
200                 offset += shift;
201                 head -= shift;
202                 goto remap;
203         }
204
205         size = event->header.size;
206
207         dump_printf("\n%p [%p]: event: %d\n",
208                         (void *)(offset + head),
209                         (void *)(long)event->header.size,
210                         event->header.type);
211
212         if (!size || process_event(event, offset, head) < 0) {
213
214                 dump_printf("%p [%p]: skipping unknown header type: %d\n",
215                         (void *)(offset + head),
216                         (void *)(long)(event->header.size),
217                         event->header.type);
218
219                 /*
220                  * assume we lost track of the stream, check alignment, and
221                  * increment a single u64 in the hope to catch on again 'soon'.
222                  */
223
224                 if (unlikely(head & 7))
225                         head &= ~7ULL;
226
227                 size = 8;
228         }
229
230         head += size;
231
232         if (offset + head >= self->header.data_offset + self->header.data_size)
233                 goto done;
234
235         if (offset + head < self->size)
236                 goto more;
237
238 done:
239         err = 0;
240 out_err:
241         return err;
242 }