diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-11-10 22:51:07 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-11-11 01:30:19 -0500 |
commit | 9e827dd00a94136b944a538bede67c944d0b740a (patch) | |
tree | 216a995921b8741461667bfdce8acc595a99685f /tools/perf | |
parent | 3e13ab2d83b6867a20663c73c184f29c2fde1558 (diff) |
perf tools: Bring linear set of section headers for features
Build a set of section headers for features right after the
datas. Each implemented feature will have one of such section
header that provides the offset and the size of the data
manipulated by the feature.
The trace informations have moved after the data and are
recorded on exit time.
The new layout is as follows:
-----------------------
___
[ magic ] |
[ header size ] |
[ attr size ] |
[ attr content offset ] |
[ attr content size ] |
[ data offset ] File Headers
[ data size ] |
[ event_types offset ] |
[ event_types size ] |
[ feature bitmap ] v
[ attr section ]
[ events section ]
___
[ X ] |
[ X ] |
[ X ] Datas
[ X ] |
[ X ] v
___
[ Feature 1 offset ] |
[ Feature 1 size ] Features headers
[ Feature 2 offset ] |
[ Feature 2 size ] v
[ Feature 1 content ]
[ Feature 2 content ]
-----------------------
We have as many feature's section headers as we have features in
use for the current file.
Say Feat 1 and Feat 3 are used by the file, but not Feat 2. Then
the feature headers will be like follows:
[ Feature 1 offset ] |
[ Feature 1 size ] Features headers
[ Feature 3 offset ] |
[ Feature 3 size ] v
There is no hole to cover Feature 2 that is not in use here. We
only need to cover the needed headers in order, from the lowest
feature bit to the highest.
Currently we have two features: HEADER_TRACE_INFO and
HEADER_BUILD_ID. Both have their contents that follow the
feature headers. Putting the contents right after the feature
headers is not mandatory though. While we keep the feature
headers right after the data and in order, their offsets can
point everywhere. We have just put the two above feature
contents in the end of the file for convenience.
The purpose of this layout change is to have a file format that
scales while keeping it simple: having such linear feature
headers is less error prone wrt forward/backward compatibility
as the content of a feature can be put anywhere, its location
can even change by the time, it's fine because its headers will
tell where it is. And we know how to find these headers,
following the above rules.
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: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
LKML-Reference: <1257911467-28276-6-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/util/data_map.c | 11 | ||||
-rw-r--r-- | tools/perf/util/data_map.h | 3 | ||||
-rw-r--r-- | tools/perf/util/header.c | 110 | ||||
-rw-r--r-- | tools/perf/util/include/linux/bitmap.h | 1 | ||||
-rw-r--r-- | tools/perf/util/include/linux/ctype.h | 2 | ||||
-rw-r--r-- | tools/perf/util/util.h | 3 |
6 files changed, 85 insertions, 45 deletions
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c index 66e58aaecce3..aacb814a4eff 100644 --- a/tools/perf/util/data_map.c +++ b/tools/perf/util/data_map.c | |||
@@ -70,18 +70,15 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
70 | } | 70 | } |
71 | } | 71 | } |
72 | 72 | ||
73 | int perf_header__read_build_ids(const struct perf_header *self, | 73 | int perf_header__read_build_ids(int input, off_t size) |
74 | int input, off_t file_size) | ||
75 | { | 74 | { |
76 | off_t offset = self->data_offset + self->data_size; | ||
77 | struct build_id_event bev; | 75 | struct build_id_event bev; |
78 | char filename[PATH_MAX]; | 76 | char filename[PATH_MAX]; |
77 | off_t offset = lseek(input, 0, SEEK_CUR); | ||
78 | off_t limit = offset + size; | ||
79 | int err = -1; | 79 | int err = -1; |
80 | 80 | ||
81 | if (lseek(input, offset, SEEK_SET) < 0) | 81 | while (offset < limit) { |
82 | return -1; | ||
83 | |||
84 | while (offset < file_size) { | ||
85 | struct dso *dso; | 82 | struct dso *dso; |
86 | ssize_t len; | 83 | ssize_t len; |
87 | 84 | ||
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h index c4122810e489..20b4037a8236 100644 --- a/tools/perf/util/data_map.h +++ b/tools/perf/util/data_map.h | |||
@@ -27,7 +27,6 @@ int mmap_dispatch_perf_file(struct perf_header **pheader, | |||
27 | int full_paths, | 27 | int full_paths, |
28 | int *cwdlen, | 28 | int *cwdlen, |
29 | char **cwd); | 29 | char **cwd); |
30 | int perf_header__read_build_ids(const struct perf_header *self, | 30 | int perf_header__read_build_ids(int input, off_t file_size); |
31 | int input, off_t file_size); | ||
32 | 31 | ||
33 | #endif | 32 | #endif |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 9709d38113b1..ebed4f44ed36 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -186,41 +186,58 @@ static void write_buildid_table(int fd, struct list_head *id_head) | |||
186 | } | 186 | } |
187 | 187 | ||
188 | static void | 188 | static void |
189 | perf_header__adds_write(struct perf_header *self, int fd, bool at_exit) | 189 | perf_header__adds_write(struct perf_header *self, int fd) |
190 | { | 190 | { |
191 | struct perf_file_section trace_sec; | 191 | LIST_HEAD(id_list); |
192 | u64 cur_offset = lseek(fd, 0, SEEK_CUR); | 192 | int nr_sections; |
193 | struct perf_file_section *feat_sec; | ||
194 | int sec_size; | ||
195 | u64 sec_start; | ||
196 | int idx = 0; | ||
197 | |||
198 | if (fetch_build_id_table(&id_list)) | ||
199 | perf_header__set_feat(self, HEADER_BUILD_ID); | ||
200 | |||
201 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | ||
202 | if (!nr_sections) | ||
203 | return; | ||
204 | |||
205 | feat_sec = calloc(sizeof(*feat_sec), nr_sections); | ||
206 | if (!feat_sec) | ||
207 | die("No memory"); | ||
208 | |||
209 | sec_size = sizeof(*feat_sec) * nr_sections; | ||
210 | |||
211 | sec_start = self->data_offset + self->data_size; | ||
212 | lseek(fd, sec_start + sec_size, SEEK_SET); | ||
193 | 213 | ||
194 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { | 214 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { |
215 | struct perf_file_section *trace_sec; | ||
216 | |||
217 | trace_sec = &feat_sec[idx++]; | ||
218 | |||
195 | /* Write trace info */ | 219 | /* Write trace info */ |
196 | trace_sec.offset = lseek(fd, sizeof(trace_sec), SEEK_CUR); | 220 | trace_sec->offset = lseek(fd, 0, SEEK_CUR); |
197 | read_tracing_data(fd, attrs, nr_counters); | 221 | read_tracing_data(fd, attrs, nr_counters); |
198 | trace_sec.size = lseek(fd, 0, SEEK_CUR) - trace_sec.offset; | 222 | trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset; |
199 | |||
200 | /* Write trace info headers */ | ||
201 | lseek(fd, cur_offset, SEEK_SET); | ||
202 | do_write(fd, &trace_sec, sizeof(trace_sec)); | ||
203 | |||
204 | /* | ||
205 | * Update cur_offset. So that other (future) | ||
206 | * features can set their own infos in this place. But if we are | ||
207 | * the only feature, at least that seeks to the place the data | ||
208 | * should begin. | ||
209 | */ | ||
210 | cur_offset = lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET); | ||
211 | } | 223 | } |
212 | 224 | ||
213 | if (at_exit) { | ||
214 | LIST_HEAD(id_list); | ||
215 | 225 | ||
216 | if (fetch_build_id_table(&id_list)) { | 226 | if (perf_header__has_feat(self, HEADER_BUILD_ID)) { |
217 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | 227 | struct perf_file_section *buildid_sec; |
218 | perf_header__set_feat(self, HEADER_BUILD_ID); | 228 | |
219 | write_buildid_table(fd, &id_list); | 229 | buildid_sec = &feat_sec[idx++]; |
220 | lseek(fd, cur_offset, SEEK_SET); | 230 | |
221 | } | 231 | /* Write build-ids */ |
232 | buildid_sec->offset = lseek(fd, 0, SEEK_CUR); | ||
233 | write_buildid_table(fd, &id_list); | ||
234 | buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset; | ||
222 | } | 235 | } |
223 | }; | 236 | |
237 | lseek(fd, sec_start, SEEK_SET); | ||
238 | do_write(fd, feat_sec, sec_size); | ||
239 | free(feat_sec); | ||
240 | } | ||
224 | 241 | ||
225 | void perf_header__write(struct perf_header *self, int fd, bool at_exit) | 242 | void perf_header__write(struct perf_header *self, int fd, bool at_exit) |
226 | { | 243 | { |
@@ -260,10 +277,11 @@ void perf_header__write(struct perf_header *self, int fd, bool at_exit) | |||
260 | if (events) | 277 | if (events) |
261 | do_write(fd, events, self->event_size); | 278 | do_write(fd, events, self->event_size); |
262 | 279 | ||
263 | perf_header__adds_write(self, fd, at_exit); | ||
264 | |||
265 | self->data_offset = lseek(fd, 0, SEEK_CUR); | 280 | self->data_offset = lseek(fd, 0, SEEK_CUR); |
266 | 281 | ||
282 | if (at_exit) | ||
283 | perf_header__adds_write(self, fd); | ||
284 | |||
267 | f_header = (struct perf_file_header){ | 285 | f_header = (struct perf_file_header){ |
268 | .magic = PERF_MAGIC, | 286 | .magic = PERF_MAGIC, |
269 | .size = sizeof(f_header), | 287 | .size = sizeof(f_header), |
@@ -308,22 +326,44 @@ static void do_read(int fd, void *buf, size_t size) | |||
308 | 326 | ||
309 | static void perf_header__adds_read(struct perf_header *self, int fd) | 327 | static void perf_header__adds_read(struct perf_header *self, int fd) |
310 | { | 328 | { |
329 | struct perf_file_section *feat_sec; | ||
330 | int nr_sections; | ||
331 | int sec_size; | ||
332 | int idx = 0; | ||
333 | |||
334 | |||
335 | nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS); | ||
336 | if (!nr_sections) | ||
337 | return; | ||
338 | |||
339 | feat_sec = calloc(sizeof(*feat_sec), nr_sections); | ||
340 | if (!feat_sec) | ||
341 | die("No memory"); | ||
342 | |||
343 | sec_size = sizeof(*feat_sec) * nr_sections; | ||
344 | |||
345 | lseek(fd, self->data_offset + self->data_size, SEEK_SET); | ||
346 | |||
347 | do_read(fd, feat_sec, sec_size); | ||
348 | |||
311 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { | 349 | if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { |
312 | struct perf_file_section trace_sec; | 350 | struct perf_file_section *trace_sec; |
313 | 351 | ||
314 | do_read(fd, &trace_sec, sizeof(trace_sec)); | 352 | trace_sec = &feat_sec[idx++]; |
315 | lseek(fd, trace_sec.offset, SEEK_SET); | 353 | lseek(fd, trace_sec->offset, SEEK_SET); |
316 | trace_report(fd); | 354 | trace_report(fd); |
317 | lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET); | ||
318 | } | 355 | } |
319 | 356 | ||
320 | if (perf_header__has_feat(self, HEADER_BUILD_ID)) { | 357 | if (perf_header__has_feat(self, HEADER_BUILD_ID)) { |
321 | struct stat input_stat; | 358 | struct perf_file_section *buildid_sec; |
322 | 359 | ||
323 | fstat(fd, &input_stat); | 360 | buildid_sec = &feat_sec[idx++]; |
324 | if (perf_header__read_build_ids(self, fd, input_stat.st_size)) | 361 | lseek(fd, buildid_sec->offset, SEEK_SET); |
362 | if (perf_header__read_build_ids(fd, buildid_sec->size)) | ||
325 | pr_debug("failed to read buildids, continuing...\n"); | 363 | pr_debug("failed to read buildids, continuing...\n"); |
326 | } | 364 | } |
365 | |||
366 | free(feat_sec); | ||
327 | }; | 367 | }; |
328 | 368 | ||
329 | struct perf_header *perf_header__read(int fd) | 369 | struct perf_header *perf_header__read(int fd) |
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h index 821c1033bccf..94507639a8c4 100644 --- a/tools/perf/util/include/linux/bitmap.h +++ b/tools/perf/util/include/linux/bitmap.h | |||
@@ -1,2 +1,3 @@ | |||
1 | #include "../../../../include/linux/bitmap.h" | 1 | #include "../../../../include/linux/bitmap.h" |
2 | #include "../../../../include/asm-generic/bitops/find.h" | 2 | #include "../../../../include/asm-generic/bitops/find.h" |
3 | #include <linux/errno.h> | ||
diff --git a/tools/perf/util/include/linux/ctype.h b/tools/perf/util/include/linux/ctype.h index bae5783282ef..a53d4ee1e0b7 100644 --- a/tools/perf/util/include/linux/ctype.h +++ b/tools/perf/util/include/linux/ctype.h | |||
@@ -1 +1 @@ | |||
#include "../../../../include/linux/ctype.h" | #include "../util.h" | ||
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index 9de2329dd44d..7bd5bdaeb235 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -306,6 +306,7 @@ static inline int has_extension(const char *filename, const char *ext) | |||
306 | #undef isascii | 306 | #undef isascii |
307 | #undef isspace | 307 | #undef isspace |
308 | #undef isdigit | 308 | #undef isdigit |
309 | #undef isxdigit | ||
309 | #undef isalpha | 310 | #undef isalpha |
310 | #undef isprint | 311 | #undef isprint |
311 | #undef isalnum | 312 | #undef isalnum |
@@ -323,6 +324,8 @@ extern unsigned char sane_ctype[256]; | |||
323 | #define isascii(x) (((x) & ~0x7f) == 0) | 324 | #define isascii(x) (((x) & ~0x7f) == 0) |
324 | #define isspace(x) sane_istest(x,GIT_SPACE) | 325 | #define isspace(x) sane_istest(x,GIT_SPACE) |
325 | #define isdigit(x) sane_istest(x,GIT_DIGIT) | 326 | #define isdigit(x) sane_istest(x,GIT_DIGIT) |
327 | #define isxdigit(x) \ | ||
328 | (sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G') | ||
326 | #define isalpha(x) sane_istest(x,GIT_ALPHA) | 329 | #define isalpha(x) sane_istest(x,GIT_ALPHA) |
327 | #define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) | 330 | #define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) |
328 | #define isprint(x) sane_istest(x,GIT_PRINT) | 331 | #define isprint(x) sane_istest(x,GIT_PRINT) |