diff options
| -rw-r--r-- | trace-local.h | 2 | ||||
| -rw-r--r-- | trace-read.c | 353 |
2 files changed, 259 insertions, 96 deletions
diff --git a/trace-local.h b/trace-local.h index 73c38d2..72f6450 100644 --- a/trace-local.h +++ b/trace-local.h | |||
| @@ -33,7 +33,7 @@ void usage(char **argv); | |||
| 33 | extern int silence_warnings; | 33 | extern int silence_warnings; |
| 34 | extern int show_status; | 34 | extern int show_status; |
| 35 | 35 | ||
| 36 | struct tracecmd_input *read_trace_header(void); | 36 | struct tracecmd_input *read_trace_header(const char *file); |
| 37 | int read_trace_files(void); | 37 | int read_trace_files(void); |
| 38 | 38 | ||
| 39 | void trace_report(int argc, char **argv); | 39 | void trace_report(int argc, char **argv); |
diff --git a/trace-read.c b/trace-read.c index 326054e..0e9ced8 100644 --- a/trace-read.c +++ b/trace-read.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | 39 | ||
| 40 | #include "trace-local.h" | 40 | #include "trace-local.h" |
| 41 | #include "trace-hash-local.h" | 41 | #include "trace-hash-local.h" |
| 42 | #include "list.h" | ||
| 42 | 43 | ||
| 43 | static struct filter { | 44 | static struct filter { |
| 44 | struct filter *next; | 45 | struct filter *next; |
| @@ -47,13 +48,30 @@ static struct filter { | |||
| 47 | } *filter_strings; | 48 | } *filter_strings; |
| 48 | static struct filter **filter_next = &filter_strings; | 49 | static struct filter **filter_next = &filter_strings; |
| 49 | 50 | ||
| 50 | static struct event_filter *event_filters; | 51 | struct handle_list { |
| 51 | static struct event_filter *event_filter_out; | 52 | struct list_head list; |
| 53 | struct tracecmd_input *handle; | ||
| 54 | const char *file; | ||
| 55 | int cpus; | ||
| 56 | int done; | ||
| 57 | struct record *record; | ||
| 58 | struct event_filter *event_filters; | ||
| 59 | struct event_filter *event_filter_out; | ||
| 60 | }; | ||
| 61 | static struct list_head handle_list; | ||
| 62 | |||
| 63 | struct input_files { | ||
| 64 | struct list_head list; | ||
| 65 | const char *file; | ||
| 66 | }; | ||
| 67 | static struct list_head input_files; | ||
| 52 | 68 | ||
| 53 | static unsigned int page_size; | 69 | static unsigned int page_size; |
| 54 | static int input_fd; | 70 | static int input_fd; |
| 55 | const char *default_input_file = "trace.dat"; | 71 | static const char *default_input_file = "trace.dat"; |
| 56 | const char *input_file; | 72 | static const char *input_file; |
| 73 | static int multi_inputs; | ||
| 74 | static int max_file_size; | ||
| 57 | 75 | ||
| 58 | static int filter_cpu = -1; | 76 | static int filter_cpu = -1; |
| 59 | static int *filter_cpus; | 77 | static int *filter_cpus; |
| @@ -231,6 +249,55 @@ static void test_save(struct record *record, int cpu) | |||
| 231 | } | 249 | } |
| 232 | #endif | 250 | #endif |
| 233 | 251 | ||
| 252 | static void add_input(const char *file) | ||
| 253 | { | ||
| 254 | struct input_files *item; | ||
| 255 | |||
| 256 | item = malloc_or_die(sizeof(*item)); | ||
| 257 | item->file = file; | ||
| 258 | list_add_tail(&item->list, &input_files); | ||
| 259 | } | ||
| 260 | |||
| 261 | static void add_handle(struct tracecmd_input *handle, const char *file) | ||
| 262 | { | ||
| 263 | struct handle_list *item; | ||
| 264 | |||
| 265 | item = malloc_or_die(sizeof(*item)); | ||
| 266 | memset(item, 0, sizeof(*item)); | ||
| 267 | item->handle = handle; | ||
| 268 | item->file = file + strlen(file); | ||
| 269 | /* we want just the base name */ | ||
| 270 | while (*item->file != '/' && item->file >= file) | ||
| 271 | item->file--; | ||
| 272 | item->file++; | ||
| 273 | if (strlen(item->file) > max_file_size) | ||
| 274 | max_file_size = strlen(item->file); | ||
| 275 | |||
| 276 | list_add_tail(&item->list, &handle_list); | ||
| 277 | } | ||
| 278 | |||
| 279 | static void free_inputs(void) | ||
| 280 | { | ||
| 281 | struct input_files *item; | ||
| 282 | |||
| 283 | while (!list_empty(&input_files)) { | ||
| 284 | item = container_of(input_files.next, struct input_files, list); | ||
| 285 | list_del(&item->list); | ||
| 286 | free(item); | ||
| 287 | } | ||
| 288 | } | ||
| 289 | |||
| 290 | static void free_handles(void) | ||
| 291 | { | ||
| 292 | struct handle_list *item; | ||
| 293 | |||
| 294 | while (!list_empty(&handle_list)) { | ||
| 295 | item = container_of(handle_list.next, struct handle_list, list); | ||
| 296 | list_del(&item->list); | ||
| 297 | free(item); | ||
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 234 | static void add_filter(const char *filter, int neg) | 301 | static void add_filter(const char *filter, int neg) |
| 235 | { | 302 | { |
| 236 | struct filter *ftr; | 303 | struct filter *ftr; |
| @@ -245,7 +312,7 @@ static void add_filter(const char *filter, int neg) | |||
| 245 | filter_next = &ftr->next; | 312 | filter_next = &ftr->next; |
| 246 | } | 313 | } |
| 247 | 314 | ||
| 248 | static void process_filters(struct tracecmd_input *handle) | 315 | static void process_filters(struct handle_list *handles) |
| 249 | { | 316 | { |
| 250 | struct event_filter *event_filter; | 317 | struct event_filter *event_filter; |
| 251 | struct pevent *pevent; | 318 | struct pevent *pevent; |
| @@ -253,17 +320,17 @@ static void process_filters(struct tracecmd_input *handle) | |||
| 253 | char *errstr; | 320 | char *errstr; |
| 254 | int ret; | 321 | int ret; |
| 255 | 322 | ||
| 256 | pevent = tracecmd_get_pevent(handle); | 323 | pevent = tracecmd_get_pevent(handles->handle); |
| 257 | event_filters = pevent_filter_alloc(pevent); | 324 | handles->event_filters = pevent_filter_alloc(pevent); |
| 258 | event_filter_out = pevent_filter_alloc(pevent); | 325 | handles->event_filter_out = pevent_filter_alloc(pevent); |
| 259 | 326 | ||
| 260 | while (filter_strings) { | 327 | while (filter_strings) { |
| 261 | filter = filter_strings; | 328 | filter = filter_strings; |
| 262 | filter_strings = filter->next; | 329 | filter_strings = filter->next; |
| 263 | if (filter->neg) | 330 | if (filter->neg) |
| 264 | event_filter = event_filter_out; | 331 | event_filter = handles->event_filter_out; |
| 265 | else | 332 | else |
| 266 | event_filter = event_filters; | 333 | event_filter = handles->event_filters; |
| 267 | 334 | ||
| 268 | ret = pevent_filter_add_filter_str(event_filter, | 335 | ret = pevent_filter_add_filter_str(event_filter, |
| 269 | filter->filter, | 336 | filter->filter, |
| @@ -515,30 +582,21 @@ static void read_rest(void) | |||
| 515 | } while (r > 0); | 582 | } while (r > 0); |
| 516 | } | 583 | } |
| 517 | 584 | ||
| 518 | static void read_data_info(struct tracecmd_input *handle) | 585 | static struct record * |
| 586 | get_next_record(struct handle_list *handles, int *next_cpu) | ||
| 519 | { | 587 | { |
| 520 | unsigned long long ts; | 588 | unsigned long long ts; |
| 521 | struct record *record; | 589 | struct record *record; |
| 522 | int cpus; | 590 | int found = 0; |
| 523 | int next; | 591 | int next; |
| 524 | int cpu; | 592 | int cpu; |
| 525 | int ret; | 593 | int ret; |
| 526 | 594 | ||
| 527 | ret = tracecmd_init_data(handle); | 595 | if (handles->record) |
| 528 | if (ret < 0) | 596 | return handles->record; |
| 529 | die("failed to init data"); | ||
| 530 | |||
| 531 | cpus = tracecmd_cpus(handle); | ||
| 532 | printf("cpus=%d\n", cpus); | ||
| 533 | |||
| 534 | /* Latency trace is just all ASCII */ | ||
| 535 | if (ret > 0) { | ||
| 536 | read_rest(); | ||
| 537 | return; | ||
| 538 | } | ||
| 539 | 597 | ||
| 540 | init_wakeup(handle); | 598 | if (handles->done) |
| 541 | process_filters(handle); | 599 | return NULL; |
| 542 | 600 | ||
| 543 | do { | 601 | do { |
| 544 | next = -1; | 602 | next = -1; |
| @@ -550,7 +608,7 @@ static void read_data_info(struct tracecmd_input *handle) | |||
| 550 | int i; | 608 | int i; |
| 551 | 609 | ||
| 552 | for (i = 0; (cpu = filter_cpus[i]) >= 0; i++) { | 610 | for (i = 0; (cpu = filter_cpus[i]) >= 0; i++) { |
| 553 | precord = tracecmd_peek_data(handle, cpu); | 611 | precord = tracecmd_peek_data(handles->handle, cpu); |
| 554 | if (precord && | 612 | if (precord && |
| 555 | (!last_stamp || precord->ts < last_stamp)) { | 613 | (!last_stamp || precord->ts < last_stamp)) { |
| 556 | next_cpu = cpu; | 614 | next_cpu = cpu; |
| @@ -558,41 +616,123 @@ static void read_data_info(struct tracecmd_input *handle) | |||
| 558 | } | 616 | } |
| 559 | } | 617 | } |
| 560 | if (last_stamp) | 618 | if (last_stamp) |
| 561 | record = tracecmd_read_data(handle, next_cpu); | 619 | record = tracecmd_read_data(handles->handle, next_cpu); |
| 562 | else | 620 | else |
| 563 | record = NULL; | 621 | record = NULL; |
| 564 | 622 | ||
| 565 | } else if (filter_cpu >= 0) { | 623 | } else if (filter_cpu >= 0) { |
| 566 | cpu = filter_cpu; | 624 | cpu = filter_cpu; |
| 567 | record = tracecmd_read_data(handle, cpu); | 625 | record = tracecmd_read_data(handles->handle, cpu); |
| 568 | } else | 626 | } else |
| 569 | record = tracecmd_read_next_data(handle, &cpu); | 627 | record = tracecmd_read_next_data(handles->handle, &cpu); |
| 570 | 628 | ||
| 571 | if (record) { | 629 | if (record) { |
| 572 | ret = pevent_filter_match(event_filters, record); | 630 | ret = pevent_filter_match( |
