aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-10-17 11:12:34 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-19 03:26:35 -0400
commit2ba0825075e76236d22a20decd8e2346a99faabe (patch)
treee8f407d50ad0027d59369f295b04ba736b6e7b87 /tools/perf
parent5a116dd2797677cad48fee2f42267e3cb69f5502 (diff)
perf tools: Introduce bitmask'ed additional headers
This provides a new set of bitmasked headers. A new field is added in the perf headers that implements a bitmap storing optional features present in the perf.data file. The layout can be pictured like this: (Usual perf headers)(Features bitmap)[Feature 0][Feature n][Feature 255] If the bit n is set, then the feature n is used in this file. They are all set in order. This brings a backward and forward compatibility. The trace_info section has moved into such optional features, this is the first and only one for now. This is backward compatible with the .32 file version although it doesn't support the previous separate trace.info file. And finally it doesn't support the current interim development version. Signed-off-by: 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> Cc: Paul Mackerras <paulus@samba.org> Cc: Steven Rostedt <rostedt@goodmis.org> LKML-Reference: <1255792354-11304-2-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-record.c4
-rw-r--r--tools/perf/util/header.c100
-rw-r--r--tools/perf/util/header.h30
3 files changed, 78 insertions, 56 deletions
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index fc3709cba136..f0467ff0d8ad 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -574,11 +574,11 @@ static int __cmd_record(int argc, const char **argv)
574 header = perf_header__new(); 574 header = perf_header__new();
575 575
576 if (raw_samples) { 576 if (raw_samples) {
577 perf_header__set_trace_info(); 577 perf_header__feat_trace_info(header);
578 } else { 578 } else {
579 for (i = 0; i < nr_counters; i++) { 579 for (i = 0; i < nr_counters; i++) {
580 if (attrs[i].sample_type & PERF_SAMPLE_RAW) { 580 if (attrs[i].sample_type & PERF_SAMPLE_RAW) {
581 perf_header__set_trace_info(); 581 perf_header__feat_trace_info(header);
582 break; 582 break;
583 } 583 }
584 } 584 }
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 9aae360c0f28..171d51b6f359 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -8,6 +8,8 @@
8#include "../perf.h" 8#include "../perf.h"
9#include "trace-event.h" 9#include "trace-event.h"
10 10
11#include <linux/bitmap.h>
12
11/* 13/*
12 * Create new perf.data header attribute: 14 * Create new perf.data header attribute:
13 */ 15 */
@@ -48,25 +50,17 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id)
48 */ 50 */
49struct perf_header *perf_header__new(void) 51struct perf_header *perf_header__new(void)
50{ 52{
51 struct perf_header *self = malloc(sizeof(*self)); 53 struct perf_header *self = calloc(sizeof(*self), 1);
52 54
53 if (!self) 55 if (!self)
54 die("nomem"); 56 die("nomem");
55 57
56 self->frozen = 0;
57
58 self->attrs = 0;
59 self->size = 1; 58 self->size = 1;
60 self->attr = malloc(sizeof(void *)); 59 self->attr = malloc(sizeof(void *));
61 60
62 if (!self->attr) 61 if (!self->attr)
63 die("nomem"); 62 die("nomem");
64 63
65 self->data_offset = 0;
66 self->data_size = 0;
67 self->trace_info_offset = 0;
68 self->trace_info_size = 0;
69
70 return self; 64 return self;
71} 65}
72 66
@@ -149,14 +143,12 @@ struct perf_file_header {
149 struct perf_file_section attrs; 143 struct perf_file_section attrs;
150 struct perf_file_section data; 144 struct perf_file_section data;
151 struct perf_file_section event_types; 145 struct perf_file_section event_types;
152 struct perf_file_section trace_info; 146 feat_mask_t adds_features;
153}; 147};
154 148
155static int trace_info; 149void perf_header__feat_trace_info(struct perf_header *header)
156
157void perf_header__set_trace_info(void)
158{ 150{
159 trace_info = 1; 151 set_bit(HEADER_TRACE_INFO, perf_header__adds_mask(header));
160} 152}
161 153
162static void do_write(int fd, void *buf, size_t size) 154static void do_write(int fd, void *buf, size_t size)
@@ -172,6 +164,32 @@ static void do_write(int fd, void *buf, size_t size)
172 } 164 }
173} 165}
174 166
167static void perf_header__adds_write(struct perf_header *self, int fd)
168{
169 struct perf_file_section trace_sec;
170 u64 cur_offset = lseek(fd, 0, SEEK_CUR);
171 unsigned long *feat_mask = perf_header__adds_mask(self);
172
173 if (test_bit(HEADER_TRACE_INFO, feat_mask)) {
174 /* Write trace info */
175 trace_sec.offset = lseek(fd, sizeof(trace_sec), SEEK_CUR);
176 read_tracing_data(fd, attrs, nr_counters);
177 trace_sec.size = lseek(fd, 0, SEEK_CUR) - trace_sec.offset;
178
179 /* Write trace info headers */
180 lseek(fd, cur_offset, SEEK_SET);
181 do_write(fd, &trace_sec, sizeof(trace_sec));
182
183 /*
184 * Update cur_offset. So that other (future)
185 * features can set their own infos in this place. But if we are
186 * the only feature, at least that seeks to the place the data
187 * should begin.
188 */
189 cur_offset = lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET);
190 }
191};
192
175void perf_header__write(struct perf_header *self, int fd) 193void perf_header__write(struct perf_header *self, int fd)
176{ 194{
177 struct perf_file_header f_header; 195 struct perf_file_header f_header;
@@ -210,23 +228,7 @@ void perf_header__write(struct perf_header *self, int fd)
210 if (events) 228 if (events)
211 do_write(fd, events, self->event_size); 229 do_write(fd, events, self->event_size);
212 230
213 if (trace_info) { 231 perf_header__adds_write(self, fd);
214 static int trace_info_written;
215
216 /*
217 * Write it only once
218 */
219 if (!trace_info_written) {
220 self->trace_info_offset = lseek(fd, 0, SEEK_CUR);
221 read_tracing_data(fd, attrs, nr_counters);
222 self->trace_info_size = lseek(fd, 0, SEEK_CUR) -
223 self->trace_info_offset;
224 trace_info_written = 1;
225 } else {
226 lseek(fd, self->trace_info_offset +
227 self->trace_info_size, SEEK_SET);
228 }
229 }
230 232
231 self->data_offset = lseek(fd, 0, SEEK_CUR); 233 self->data_offset = lseek(fd, 0, SEEK_CUR);
232 234
@@ -246,12 +248,10 @@ void perf_header__write(struct perf_header *self, int fd)
246 .offset = self->event_offset, 248 .offset = self->event_offset,
247 .size = self->event_size, 249 .size = self->event_size,
248 }, 250 },
249 .trace_info = {
250 .offset = self->trace_info_offset,
251 .size = self->trace_info_size,
252 },
253 }; 251 };
254 252
253 memcpy(&f_header.adds_features, &self->adds_features, sizeof(feat_mask_t));
254
255 lseek(fd, 0, SEEK_SET); 255 lseek(fd, 0, SEEK_SET);
256 do_write(fd, &f_header, sizeof(f_header)); 256 do_write(fd, &f_header, sizeof(f_header));
257 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 257 lseek(fd, self->data_offset + self->data_size, SEEK_SET);
@@ -274,6 +274,20 @@ static void do_read(int fd, void *buf, size_t size)
274 } 274 }
275} 275}
276 276
277static void perf_header__adds_read(struct perf_header *self, int fd)
278{
279 const unsigned long *feat_mask = perf_header__adds_mask(self);
280
281 if (test_bit(HEADER_TRACE_INFO, feat_mask)) {
282 struct perf_file_section trace_sec;
283
284 do_read(fd, &trace_sec, sizeof(trace_sec));
285 lseek(fd, trace_sec.offset, SEEK_SET);
286 trace_report(fd);
287 lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET);
288 }
289};
290
277struct perf_header *perf_header__read(int fd) 291struct perf_header *perf_header__read(int fd)
278{ 292{
279 struct perf_header *self = perf_header__new(); 293 struct perf_header *self = perf_header__new();
@@ -292,9 +306,11 @@ struct perf_header *perf_header__read(int fd)
292 306
293 if (f_header.size != sizeof(f_header)) { 307 if (f_header.size != sizeof(f_header)) {
294 /* Support the previous format */ 308 /* Support the previous format */
295 if (f_header.size == offsetof(typeof(f_header), trace_info)) 309 if (f_header.size == offsetof(typeof(f_header), adds_features)) {
296 f_header.trace_info.size = 0; 310 unsigned long *mask = (unsigned long *)(void *)
297 else 311 &f_header.adds_features;
312 bitmap_zero(mask, HEADER_FEAT_BITS);
313 } else
298 die("incompatible file format"); 314 die("incompatible file format");
299 } 315 }
300 nr_attrs = f_header.attrs.size / sizeof(f_attr); 316 nr_attrs = f_header.attrs.size / sizeof(f_attr);
@@ -330,13 +346,9 @@ struct perf_header *perf_header__read(int fd)
330 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type); 346 event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
331 } 347 }
332 348
333 self->trace_info_offset = f_header.trace_info.offset; 349 memcpy(&self->adds_features, &f_header.adds_features, sizeof(feat_mask_t));
334 self->trace_info_size = f_header.trace_info.size;
335 350
336 if (self->trace_info_size) { 351 perf_header__adds_read(self, fd);
337 lseek(fd, self->trace_info_offset, SEEK_SET);
338 trace_report(fd);
339 }
340 352
341 self->event_offset = f_header.event_types.offset; 353 self->event_offset = f_header.event_types.offset;
342 self->event_size = f_header.event_types.size; 354 self->event_size = f_header.event_types.size;
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 30aee5160dc0..0eb4a9126b7c 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -12,19 +12,29 @@ struct perf_header_attr {
12 off_t id_offset; 12 off_t id_offset;
13}; 13};
14 14
15#define HEADER_TRACE_INFO 1
16
17#define HEADER_FEAT_BITS 256
18
19typedef typeof(u64[HEADER_FEAT_BITS / 8]) feat_mask_t;
20
15struct perf_header { 21struct perf_header {
16 int frozen; 22 int frozen;
17 int attrs, size; 23 int attrs, size;
18 struct perf_header_attr **attr; 24 struct perf_header_attr **attr;
19 s64 attr_offset; 25 s64 attr_offset;
20 u64 data_offset; 26 u64 data_offset;
21 u64 data_size; 27 u64 data_size;
22 u64 event_offset; 28 u64 event_offset;
23 u64 event_size; 29 u64 event_size;
24 u64 trace_info_offset; 30 feat_mask_t adds_features;
25 u64 trace_info_size;
26}; 31};
27 32
33static inline unsigned long *perf_header__adds_mask(struct perf_header *self)
34{
35 return (unsigned long *)(void *)&self->adds_features;
36}
37
28struct perf_header *perf_header__read(int fd); 38struct perf_header *perf_header__read(int fd);
29void perf_header__write(struct perf_header *self, int fd); 39void perf_header__write(struct perf_header *self, int fd);
30 40
@@ -42,7 +52,7 @@ void perf_header_attr__add_id(struct perf_header_attr *self, u64 id);
42u64 perf_header__sample_type(struct perf_header *header); 52u64 perf_header__sample_type(struct perf_header *header);
43struct perf_event_attr * 53struct perf_event_attr *
44perf_header__find_attr(u64 id, struct perf_header *header); 54perf_header__find_attr(u64 id, struct perf_header *header);
45void perf_header__set_trace_info(void); 55void perf_header__feat_trace_info(struct perf_header *header);
46 56
47struct perf_header *perf_header__new(void); 57struct perf_header *perf_header__new(void);
48 58