diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2009-12-29 14:16:35 -0500 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2009-12-29 14:16:35 -0500 |
| commit | c40b62e42e901e46c1722104dbeaa17ac0b591a5 (patch) | |
| tree | 08dde432c7c974c5dc50829157994e5635135712 | |
| parent | ff8ebb0ecd19766c9a8d72cd17e622156f7ca723 (diff) | |
| parent | 2b0090a023316912f7d242a861aec50145919fae (diff) | |
Merge branch 'trace-cmd' into trace-view
| -rw-r--r-- | .gitignore | 4 | ||||
| -rw-r--r-- | ctracecmd.i | 20 | ||||
| -rw-r--r-- | list.h | 47 | ||||
| -rw-r--r-- | parse-events.h | 13 | ||||
| -rw-r--r-- | trace-cmd.h | 5 | ||||
| -rw-r--r-- | trace-input.c | 284 | ||||
| -rw-r--r-- | trace-util.c | 11 | ||||
| -rw-r--r-- | tracecmd.py | 15 |
8 files changed, 254 insertions, 145 deletions
| @@ -4,3 +4,7 @@ trace-cmd | |||
| 4 | *.a | 4 | *.a |
| 5 | trace.dat | 5 | trace.dat |
| 6 | *~ | 6 | *~ |
| 7 | kernelshark | ||
| 8 | trace-graph | ||
| 9 | trace-view | ||
| 10 | |||
diff --git a/ctracecmd.i b/ctracecmd.i index 20a681c..a9d3ca5 100644 --- a/ctracecmd.i +++ b/ctracecmd.i | |||
| @@ -6,19 +6,21 @@ | |||
| 6 | #include "trace-cmd.h" | 6 | #include "trace-cmd.h" |
| 7 | %} | 7 | %} |
| 8 | 8 | ||
| 9 | /* typemaps must come before the implementation of wrapped functions */ | 9 | %typemap(out) unsigned long long { |
| 10 | extern int pevent_read_number_field_32(struct format_field *f, void *data, | 10 | $result = PyLong_FromUnsignedLongLong((unsigned long long) $1); |
| 11 | unsigned long *OUTPUT, unsigned long *OUTPUT); | 11 | } |
| 12 | 12 | ||
| 13 | %inline %{ | 13 | %inline %{ |
| 14 | int pevent_read_number_field_32(struct format_field *f, void *data, unsigned long *hi, unsigned long *lo) | 14 | PyObject *pevent_read_number_field_py(struct format_field *f, void *data) |
| 15 | { | 15 | { |
| 16 | unsigned long long val64; | 16 | unsigned long long val; |
| 17 | int ret; | 17 | int ret; |
| 18 | ret = pevent_read_number_field(f, data, &val64); | 18 | |
| 19 | *hi = (unsigned long)(val64>>32); | 19 | ret = pevent_read_number_field(f, data, &val); |
| 20 | *lo = (unsigned long)((val64<<32)>>32); | 20 | if (ret) |
| 21 | return ret; | 21 | Py_RETURN_NONE; |
| 22 | else | ||
| 23 | return PyLong_FromUnsignedLongLong(val); | ||
| 22 | } | 24 | } |
| 23 | %} | 25 | %} |
| 24 | 26 | ||
| @@ -0,0 +1,47 @@ | |||
| 1 | #ifndef __LIST_H | ||
| 2 | #define __LIST_H | ||
| 3 | |||
| 4 | #define offset_of(type, field) (long)(&((type *)0)->field) | ||
| 5 | #define container_of(p, type, field) (type *)((long)p - offset_of(type, field)) | ||
| 6 | |||
| 7 | struct list_head { | ||
| 8 | struct list_head *next; | ||
| 9 | struct list_head *prev; | ||
| 10 | }; | ||
| 11 | |||
| 12 | static inline void list_head_init(struct list_head *list) | ||
| 13 | { | ||
| 14 | list->next = list; | ||
| 15 | list->prev = list; | ||
| 16 | } | ||
| 17 | |||
| 18 | static inline void list_add(struct list_head *p, struct list_head *head) | ||
| 19 | { | ||
| 20 | struct list_head *next = head->next; | ||
| 21 | |||
| 22 | p->prev = head; | ||
| 23 | p->next = next; | ||
| 24 | next->prev = p; | ||
| 25 | head->next = p; | ||
| 26 | } | ||
| 27 | |||
| 28 | static inline void list_del(struct list_head *p) | ||
| 29 | { | ||
| 30 | struct list_head *next = p->next; | ||
| 31 | struct list_head *prev = p->prev; | ||
| 32 | |||
| 33 | next->prev = prev; | ||
| 34 | prev->next = next; | ||
| 35 | } | ||
| 36 | |||
| 37 | static inline int list_empty(struct list_head *list) | ||
| 38 | { | ||
| 39 | return list->next == list; | ||
| 40 | } | ||
| 41 | |||
| 42 | #define list_for_each_entry(p, list, type, field) \ | ||
| 43 | for (p = container_of((list)->next, type, field); \ | ||
| 44 | &(p)->field != list; \ | ||
| 45 | p = container_of((p)->field.next, type, field)) | ||
| 46 | |||
| 47 | #endif /* __LIST_H */ | ||
diff --git a/parse-events.h b/parse-events.h index 92f174e..bfbba5c 100644 --- a/parse-events.h +++ b/parse-events.h | |||
| @@ -15,12 +15,13 @@ | |||
| 15 | #endif | 15 | #endif |
| 16 | 16 | ||
| 17 | struct record { | 17 | struct record { |
| 18 | unsigned long long ts; | 18 | unsigned long long ts; |
| 19 | unsigned long long offset; | 19 | unsigned long long offset; |
| 20 | int record_size; /* size of binary record */ | 20 | int record_size; /* size of binary record */ |
| 21 | int size; /* size of data */ | 21 | int size; /* size of data */ |
| 22 | void *data; | 22 | void *data; |
| 23 | int cpu; | 23 | int cpu; |
| 24 | void *private; | ||
| 24 | }; | 25 | }; |
| 25 | 26 | ||
| 26 | /* | 27 | /* |
diff --git a/trace-cmd.h b/trace-cmd.h index f6141f4..d0b5c92 100644 --- a/trace-cmd.h +++ b/trace-cmd.h | |||
| @@ -22,10 +22,7 @@ enum { | |||
| 22 | #define TS_SHIFT 27 | 22 | #define TS_SHIFT 27 |
| 23 | #endif | 23 | #endif |
| 24 | 24 | ||
| 25 | static inline void free_record(struct record *record) | 25 | void free_record(struct record *record); |
| 26 | { | ||
| 27 | free(record); | ||
| 28 | } | ||
| 29 | 26 | ||
| 30 | struct tracecmd_input; | 27 | struct tracecmd_input; |
| 31 | struct tracecmd_output; | 28 | struct tracecmd_output; |
diff --git a/trace-input.c b/trace-input.c index 0bb750c..431c580 100644 --- a/trace-input.c +++ b/trace-input.c | |||
| @@ -17,10 +17,19 @@ | |||
| 17 | #include <errno.h> | 17 | #include <errno.h> |
| 18 | 18 | ||
| 19 | #include "trace-cmd.h" | 19 | #include "trace-cmd.h" |
| 20 | #include "list.h" | ||
| 20 | 21 | ||
| 21 | /* for debugging read instead of mmap */ | 22 | /* for debugging read instead of mmap */ |
| 22 | static int force_read = 0; | 23 | static int force_read = 0; |
| 23 | 24 | ||
| 25 | struct page { | ||
| 26 | struct list_head list; | ||
| 27 | off64_t offset; | ||
| 28 | struct tracecmd_input *handle; | ||
| 29 | void *map; | ||
| 30 | int ref_count; | ||
| 31 | }; | ||
| 32 | |||
| 24 | struct cpu_data { | 33 | struct cpu_data { |
| 25 | /* the first two never change */ | 34 | /* the first two never change */ |
| 26 | unsigned long long file_offset; | 35 | unsigned long long file_offset; |
| @@ -28,28 +37,27 @@ struct cpu_data { | |||
| 28 | unsigned long long offset; | 37 | unsigned long long offset; |
| 29 | unsigned long long size; | 38 | unsigned long long size; |
| 30 | unsigned long long timestamp; | 39 | unsigned long long timestamp; |
| 40 | struct list_head pages; | ||
| 31 | struct record *next; | 41 | struct record *next; |
| 32 | char *page; | 42 | struct page *page; |
| 33 | void *read_page; | ||
| 34 | int cpu; | 43 | int cpu; |
| 35 | int index; | 44 | int index; |
| 36 | int page_size; | 45 | int page_size; |
| 37 | }; | 46 | }; |
| 38 | 47 | ||
| 39 | struct tracecmd_input { | 48 | struct tracecmd_input { |
| 40 | struct pevent *pevent; | 49 | struct pevent *pevent; |
| 41 | int fd; | 50 | int fd; |
| 42 | int long_size; | 51 | int long_size; |
| 43 | int page_size; | 52 | int page_size; |
| 44 | int read_page; | 53 | int read_page; |
| 45 | int cpus; | 54 | int cpus; |
| 46 | struct cpu_data *cpu_data; | 55 | struct cpu_data *cpu_data; |
| 47 | 56 | ||
| 48 | /* file information */ | 57 | /* file information */ |
| 49 | size_t header_files_start; | 58 | size_t header_files_start; |
| 50 | size_t ftrace_files_start; | 59 | size_t ftrace_files_start; |
| 51 | size_t event_files_start; | 60 | size_t event_files_start; |
| 52 | |||
| 53 | }; | 61 | }; |
| 54 | 62 | ||
| 55 | __thread struct tracecmd_input *tracecmd_curr_thread_handle; | 63 | __thread struct tracecmd_input *tracecmd_curr_thread_handle; |
| @@ -109,7 +117,7 @@ static char *read_string(struct tracecmd_input *handle) | |||
| 109 | } | 117 | } |
| 110 | if (i < r) | 118 | if (i < r) |
| 111 | break; | 119 | break; |
| 112 | 120 | ||
| 113 | if (str) { | 121 | if (str) { |
| 114 | size += BUFSIZ; | 122 | size += BUFSIZ; |
| 115 | str = realloc(str, size); | 123 | str = realloc(str, size); |
| @@ -121,7 +129,7 @@ static char *read_string(struct tracecmd_input *handle) | |||
| 121 | str = malloc(size); | 129 | str = malloc(size); |
| 122 | if (!str) | 130 | if (!str) |
| 123 | return NULL; | 131 | return NULL; |
| 124 | memcpy(str, buf, size); | 132 | memcpy(str, buf, size); |
| 125 | } | 133 | } |
| 126 | } | 134 | } |
| 127 | 135 | ||
| @@ -504,7 +512,97 @@ static unsigned int read_type_len_ts(struct tracecmd_input *handle, void *ptr) | |||
| 504 | static int calc_index(struct tracecmd_input *handle, | 512 | static int calc_index(struct tracecmd_input *handle, |
| 505 | void *ptr, int cpu) | 513 | void *ptr, int cpu) |
| 506 | { | 514 | { |
| 507 | return (unsigned long)ptr - (unsigned long)handle->cpu_data[cpu].page; | 515 | return (unsigned long)ptr - (unsigned long)handle->cpu_data[cpu].page->map; |
| 516 | } | ||
| 517 | |||
| 518 | |||
| 519 | static int read_page(struct tracecmd_input *handle, off64_t offset, | ||
| 520 | void *map) | ||
| 521 | { | ||
| 522 | off64_t save_seek; | ||
| 523 | off64_t ret; | ||
| 524 | |||
| 525 | /* other parts of the code may expect the pointer to not move */ | ||
| 526 | save_seek = lseek64(handle->fd, 0, SEEK_CUR); | ||
| 527 | |||
| 528 | ret = lseek64(handle->fd, offset, SEEK_SET); | ||
| 529 | if (ret < 0) | ||
| 530 | return -1; | ||
| 531 | ret = read(handle->fd, map, handle->page_size); | ||
| 532 | if (ret < 0) | ||
| 533 | return -1; | ||
| 534 | |||
| 535 | /* reset the file pointer back */ | ||
| 536 | lseek64(handle->fd, save_seek, SEEK_SET); | ||
| 537 | |||
| 538 | return 0; | ||
| 539 | } | ||
| 540 | |||
| 541 | static struct page *allocate_page(struct tracecmd_input *handle, | ||
| 542 | int cpu, off64_t offset) | ||
| 543 | { | ||
| 544 | struct cpu_data *cpu_data = &handle->cpu_data[cpu]; | ||
| 545 | struct page *page; | ||
| 546 | int ret; | ||
| 547 | |||
| 548 | list_for_each_entry(page, &cpu_data->pages, struct page, list) { | ||
| 549 | if (page->offset == offset) { | ||
| 550 | page->ref_count++; | ||
| 551 | return page; | ||
| 552 | } | ||
| 553 | } | ||
| 554 | |||
| 555 | page = malloc(sizeof(*page)); | ||
| 556 | if (!page) | ||
| 557 | return NULL; | ||
| 558 | |||
| 559 | memset(page, 0, sizeof(*page)); | ||
| 560 | page->offset = offset; | ||
| 561 | page->handle = handle; | ||
| 562 | |||
| 563 | if (handle->read_page) { | ||
| 564 | page->map = malloc(handle->page_size); | ||
| 565 | if (page->map) { | ||
| 566 | ret = read_page(handle, offset, page->map); | ||
| 567 | if (ret < 0) { | ||
| 568 | free(page->map); | ||
| 569 | page->map = NULL; | ||
| 570 | } | ||
| 571 | } | ||
| 572 | } else { | ||
| 573 | page->map = mmap(NULL, handle->page_size, PROT_READ, MAP_PRIVATE, | ||
| 574 | handle->fd, offset); | ||
| 575 | if (page->map == MAP_FAILED) | ||
| 576 | page->map = NULL; | ||
| 577 | } | ||
| 578 | |||
| 579 | if (!page->map) { | ||
| 580 | free(page); | ||
| 581 | return NULL; | ||
| 582 | } | ||
| 583 | |||
| 584 | list_add(&page->list, &cpu_data->pages); | ||
| 585 | page->ref_count = 1; | ||
| 586 | |||
| 587 | return page; | ||
| 588 | } | ||
| 589 | |||
| 590 | static void __free_page(struct tracecmd_input *handle, struct page *page) | ||
| 591 | { | ||
| 592 | if (!page->ref_count) | ||
| 593 | die("Page ref count is zero!\n"); | ||
| 594 | |||
| 595 | page->ref_count--; | ||
| 596 | if (page->ref_count) | ||
| 597 | return; | ||
| 598 | |||
| 599 | if (handle->read_page) | ||
| 600 | free(page->map); | ||
| 601 | else | ||
| 602 | munmap(page->map, handle->page_size); | ||
| 603 | |||
| 604 | list_del(&page->list); | ||
| 605 | free(page); | ||
| 508 | } | 606 | } |
| 509 | 607 | ||
| 510 | static void free_page(struct tracecmd_input *handle, int cpu) | 608 | static void free_page(struct tracecmd_input *handle, int cpu) |
| @@ -512,17 +610,22 @@ static void free_page(struct tracecmd_input *handle, int cpu) | |||
| 512 | if (!handle->cpu_data[cpu].page) | 610 | if (!handle->cpu_data[cpu].page) |
| 513 | return; | 611 | return; |
| 514 | 612 | ||
| 515 | if (!handle->read_page) | 613 | __free_page(handle, handle->cpu_data[cpu].page); |
| 516 | munmap(handle->cpu_data[cpu].page, handle->page_size); | ||
| 517 | 614 | ||
| 518 | handle->cpu_data[cpu].page = NULL; | 615 | handle->cpu_data[cpu].page = NULL; |
| 519 | } | 616 | } |
| 520 | 617 | ||
| 521 | static void free_read_page(struct tracecmd_input *handle, int cpu) | 618 | void free_record(struct record *record) |
| 522 | { | 619 | { |
| 523 | free_page(handle, cpu); | 620 | if (!record) |
| 524 | if (handle->read_page) | 621 | return; |
| 525 | free(handle->cpu_data[cpu].read_page); | 622 | |
| 623 | if (record->private) { | ||
| 624 | struct page *page = record->private; | ||
| 625 | __free_page(page->handle, page); | ||
| 626 | } | ||
| 627 | |||
| 628 | free(record); | ||
| 526 | } | 629 | } |
| 527 | 630 | ||
| 528 | /* | 631 | /* |
| @@ -531,7 +634,7 @@ static void free_read_page(struct tracecmd_input *handle, int cpu) | |||
| 531 | static int update_page_info(struct tracecmd_input *handle, int cpu) | 634 | static int update_page_info(struct tracecmd_input *handle, int cpu) |
| 532 | { | 635 | { |
| 533 | struct pevent *pevent = handle->pevent; | 636 | struct pevent *pevent = handle->pevent; |
| 534 | void *ptr = handle->cpu_data[cpu].page; | 637 | void *ptr = handle->cpu_data[cpu].page->map; |
| 535 | 638 | ||
| 536 | /* FIXME: handle header page */ | 639 | /* FIXME: handle header page */ |
| 537 | if (pevent->header_page_ts_size != 8) { | 640 | if (pevent->header_page_ts_size != 8) { |
| @@ -558,35 +661,6 @@ static int update_page_info(struct tracecmd_input *handle, int cpu) | |||
| 558 | return 0; | 661 | return 0; |
| 559 | } | 662 | } |
| 560 | 663 | ||
| 561 | static int get_read_page(struct tracecmd_input *handle, int cpu, | ||
| 562 | off64_t offset) | ||
| 563 | { | ||
| 564 | off64_t save_seek; | ||
| 565 | off64_t ret; | ||
| 566 | |||
| 567 | free_page(handle, cpu); | ||
| 568 | |||
| 569 | handle->cpu_data[cpu].page = handle->cpu_data[cpu].read_page; | ||
| 570 | |||
| 571 | /* other parts of the code may expect the pointer to not move */ | ||
| 572 | save_seek = lseek64(handle->fd, 0, SEEK_CUR); | ||
| 573 | |||
| 574 | ret = lseek64(handle->fd, offset, SEEK_SET); | ||
| 575 | if (ret < 0) | ||
| 576 | return -1; | ||
| 577 | ret = read(handle->fd, handle->cpu_data[cpu].page, handle->page_size); | ||
| 578 | if (ret < 0) | ||
| 579 | return -1; | ||
| 580 | |||
| 581 | /* reset the file pointer back */ | ||
| 582 | lseek64(handle->fd, save_seek, SEEK_SET); | ||
| 583 | |||
| 584 | if (update_page_info(handle, cpu)) | ||
| 585 | return -1; | ||
| 586 | |||
| 587 | return 0; | ||
| 588 | } | ||
| 589 | |||
| 590 | /* | 664 | /* |
| 591 | * get_page maps a page for a given cpu. | 665 | * get_page maps a page for a given cpu. |
| 592 | * | 666 | * |
| @@ -623,15 +697,10 @@ static int get_page(struct tracecmd_input *handle, int cpu, | |||
| 623 | handle->cpu_data[cpu].file_size) - | 697 | handle->cpu_data[cpu].file_size) - |
| 624 | offset; | 698 | offset; |
| 625 | 699 | ||
| 626 | if (handle->read_page) | 700 | free_page(handle, cpu); |
| 627 | return get_read_page(handle, cpu, offset); | ||
| 628 | |||
| 629 | if (handle->cpu_data[cpu].page) | ||
| 630 | free_page(handle, cpu); | ||
| 631 | 701 | ||
| 632 | handle->cpu_data[cpu].page = mmap(NULL, handle->page_size, PROT_READ, MAP_PRIVATE, | 702 | handle->cpu_data[cpu].page = allocate_page(handle, cpu, offset); |
| 633 | handle->fd, offset); | 703 | if (!handle->cpu_data[cpu].page) |
| 634 | if (handle->cpu_data[cpu].page == MAP_FAILED) | ||
| 635 | return -1; | 704 | return -1; |
| 636 | 705 | ||
| 637 | if (update_page_info(handle, cpu)) | 706 | if (update_page_info(handle, cpu)) |
| @@ -876,7 +945,7 @@ int tracecmd_refresh_record(struct tracecmd_input *handle, | |||
| 876 | if (ret) | 945 | if (ret) |
| 877 | return 1; | 946 | return 1; |
| 878 | 947 | ||
| 879 | record->data = cpu_data->page + index; | 948 | record->data = cpu_data->page->map + index; |
| 880 | 949 | ||
| 881 | type_len_ts = read_type_len_ts(handle, record->data); | 950 | type_len_ts = read_type_len_ts(handle, record->data); |
| 882 | len = len4host(handle, type_len_ts); | 951 | len = len4host(handle, type_len_ts); |
| @@ -1140,9 +1209,9 @@ tracecmd_peek_data(struct tracecmd_input *handle, int cpu) | |||
| 1140 | { | 1209 | { |
| 1141 | struct pevent *pevent = handle->pevent; | 1210 | struct pevent *pevent = handle->pevent; |
| 1142 | struct record *record; | 1211 | struct record *record; |
| 1143 | void *page = handle->cpu_data[cpu].page; | 1212 | struct page *page = handle->cpu_data[cpu].page; |
| 1144 | int index = handle->cpu_data[cpu].index; | 1213 | int index = handle->cpu_data[cpu].index; |
| 1145 | void *ptr = page + index; | 1214 | void *ptr; |
| 1146 | unsigned long long extend; | 1215 | unsigned long long extend; |
| 1147 | unsigned int type_len; | 1216 | unsigned int type_len; |
| 1148 | int length; | 1217 | int length; |
| @@ -1176,8 +1245,10 @@ tracecmd_peek_data(struct tracecmd_input *handle, int cpu) | |||
| 1176 | if (!page) | 1245 | if (!page) |
| 1177 | return NULL; | 1246 | return NULL; |
| 1178 | 1247 | ||
| 1248 | ptr = page->map + index; | ||
| 1249 | |||
| 1179 | if (!index) | 1250 | if (!index) |
| 1180 | ptr = handle->cpu_data[cpu].page + pevent->header_page_data_offset; | 1251 | ptr = handle->cpu_data[cpu].page->map + pevent->header_page_data_offset; |
| 1181 | 1252 | ||
| 1182 | read_again: | 1253 | read_again: |
| 1183 | index = calc_index(handle, ptr, cpu); | 1254 | index = calc_index(handle, ptr, cpu); |
| @@ -1236,6 +1307,8 @@ read_again: | |||
| 1236 | handle->cpu_data[cpu].next = record; | 1307 | handle->cpu_data[cpu].next = record; |
| 1237 | 1308 | ||
| 1238 | record->record_size = handle->cpu_data[cpu].index - index; | 1309 | record->record_size = handle->cpu_data[cpu].index - index; |
| 1310 | record->private = page; | ||
| 1311 | page->ref_count++; | ||
| 1239 | 1312 | ||
| 1240 | return record; | 1313 | return record; |
| 1241 | } | 1314 | } |
| @@ -1261,63 +1334,37 @@ tracecmd_read_data(struct tracecmd_input *handle, int cpu) | |||
| 1261 | return record; | 1334 | return record; |
| 1262 | } | 1335 | } |
| 1263 | 1336 | ||
| 1264 | static int init_read(struct tracecmd_input *handle, int cpu) | ||
| 1265 | { | ||
| 1266 | off64_t ret; | ||
| 1267 | off64_t save_seek; | ||
| 1268 | |||
| 1269 | handle->cpu_data[cpu].read_page = malloc(handle->page_size); | ||
| 1270 | if (!handle->cpu_data[cpu].read_page) | ||
| 1271 | return -1; | ||
| 1272 | |||
| 1273 | handle->cpu_data[cpu].page = handle->cpu_data[cpu].read_page; | ||
| 1274 | |||
| 1275 | /* other parts of the code may expect the pointer to not move */ | ||
| 1276 | save_seek = lseek64(handle->fd, 0, SEEK_CUR); | ||
| 1277 | |||
| 1278 | ret = lseek64(handle->fd, (off64_t)handle->cpu_data[cpu].offset, SEEK_SET); | ||
| 1279 | if (ret < 0) | ||
| 1280 | return -1; | ||
| 1281 | ret = read(handle->fd, handle->cpu_data[cpu].page, handle->page_size); | ||
| 1282 | if (ret < 0) | ||
| 1283 | return -1; | ||
| 1284 | |||
| 1285 | /* reset the file pointer back */ | ||
| 1286 | lseek64(handle->fd, save_seek, SEEK_SET); | ||
| 1287 | |||
| 1288 | handle->cpu_data[cpu].timestamp = | ||
| 1289 | data2host8(handle->pevent, handle->cpu_data[cpu].page); | ||
| 1290 | |||
| 1291 | return 0; | ||
| 1292 | } | ||
| 1293 | |||
| 1294 | static int init_cpu(struct tracecmd_input *handle, int cpu) | 1337 | static int init_cpu(struct tracecmd_input *handle, int cpu) |
| 1295 | { | 1338 | { |
| 1296 | handle->cpu_data[cpu].offset = handle->cpu_data[cpu].file_offset; | 1339 | struct cpu_data *cpu_data = &handle->cpu_data[cpu]; |
| 1297 | handle->cpu_data[cpu].size = handle->cpu_data[cpu].file_size; | 1340 | |
| 1298 | handle->cpu_data[cpu].timestamp = 0; | 1341 | cpu_data->offset = cpu_data->file_offset; |
| 1342 | cpu_data->size = cpu_data->file_size; | ||
| 1343 | cpu_data->timestamp = 0; | ||
| 1299 | 1344 | ||
| 1300 | if (!handle->cpu_data[cpu].size) { | 1345 | if (!cpu_data->size) { |
| 1301 | printf("CPU %d is empty\n", cpu); | 1346 | printf("CPU %d is empty\n", cpu); |
| 1302 | return 0; | 1347 | return 0; |
| 1303 | } | 1348 | } |
| 1304 | 1349 | ||
| 1305 | if (handle->read_page) | 1350 | list_head_init(&cpu_data->pages); |
| 1306 | return init_read(handle, cpu); | ||
| 1307 | 1351 | ||
| 1308 | if (!force_read) { | 1352 | cpu_data->page = allocate_page(handle, cpu, cpu_data->offset); |
| 1309 | handle->cpu_data[cpu].page = mmap(NULL, handle->page_size, PROT_READ, | 1353 | if (!cpu_data->page && !handle->read_page) { |
| 1310 | MAP_PRIVATE, handle->fd, handle->cpu_data[cpu].offset); | ||
| 1311 | } | ||
| 1312 | if (force_read || handle->cpu_data[cpu].page == MAP_FAILED) { | ||
| 1313 | /* fall back to just reading pages */ | ||
| 1314 | perror("mmap"); | 1354 | perror("mmap"); |
| 1315 | fprintf(stderr, "Can not mmap file, will read instead\n"); | 1355 | fprintf(stderr, "Can not mmap file, will read instead\n"); |
| 1316 | handle->read_page = 1; | ||
| 1317 | 1356 | ||
| 1318 | return init_read(handle, cpu); | 1357 | if (cpu) |
| 1319 | } | 1358 | /* Other CPUs worked! bail */ |
| 1359 | return -1; | ||
| 1320 | 1360 | ||
| 1361 | /* try again without mmapping, just read it directly */ | ||
| 1362 | handle->read_page = 1; | ||
| 1363 | cpu_data->page = allocate_page(handle, cpu, cpu_data->offset); | ||
| 1364 | if (!cpu_data->page) | ||
| 1365 | /* Still no luck, bail! */ | ||
| 1366 | return -1; | ||
| 1367 | } | ||
| 1321 | 1368 | ||
| 1322 | if (update_page_info(handle, cpu)) | 1369 | if (update_page_info(handle, cpu)) |
| 1323 | return -1; | 1370 | return -1; |
| @@ -1374,6 +1421,9 @@ int tracecmd_init_data(struct tracecmd_input *handle) | |||
| 1374 | return -1; | 1421 | return -1; |
| 1375 | memset(handle->cpu_data, 0, sizeof(*handle->cpu_data) * handle->cpus); | 1422 | memset(handle->cpu_data, 0, sizeof(*handle->cpu_data) * handle->cpus); |
| 1376 | 1423 | ||
| 1424 | if (force_read) | ||
| 1425 | handle->read_page = 1; | ||
| 1426 | |||
| 1377 | for (cpu = 0; cpu < handle->cpus; cpu++) { | 1427 | for (cpu = 0; cpu < handle->cpus; cpu++) { |
| 1378 | unsigned long long offset; | 1428 | unsigned long long offset; |
| 1379 | 1429 | ||
| @@ -1498,8 +1548,20 @@ void tracecmd_close(struct tracecmd_input *handle) | |||
| 1498 | if (!handle) | 1548 | if (!handle) |
| 1499 | return; | 1549 | return; |
| 1500 | 1550 | ||
| 1501 | for (cpu = 0; cpu < handle->cpus; cpu++) | 1551 | for (cpu = 0; cpu < handle->cpus; cpu++) { |
| 1502 | free_read_page(handle, cpu); | 1552 | struct record *rec; |
| 1553 | /* | ||
| 1554 | * The tracecmd_peek_data may have cached a record | ||
| 1555 | * Do a read to flush it out. | ||
| 1556 | */ | ||
| 1557 | rec = tracecmd_read_data(handle, cpu); | ||
| 1558 | if (rec) | ||
| 1559 | free_record(rec); | ||
| 1560 | free_page(handle, cpu); | ||
| 1561 | if (!list_empty(&handle->cpu_data[cpu].pages)) | ||
| 1562 | warning("pages still allocated on cpu %d", cpu); | ||
| 1563 | } | ||
| 1564 | |||
| 1503 | free(handle->cpu_data); | 1565 | free(handle->cpu_data); |
| 1504 | 1566 | ||
| 1505 | close(handle->fd); | 1567 | close(handle->fd); |
diff --git a/trace-util.c b/trace-util.c index d5be6ed..520f800 100644 --- a/trace-util.c +++ b/trace-util.c | |||
| @@ -154,7 +154,7 @@ static int load_plugin(struct pevent *pevent, | |||
| 154 | char *plugin; | 154 | char *plugin; |
| 155 | void *handle; | 155 | void *handle; |
| 156 | pevent_plugin_load_func func; | 156 | pevent_plugin_load_func func; |
| 157 | int ret; | 157 | int ret = -1; |
| 158 | 158 | ||
| 159 | plugin = malloc_or_die(strlen(path) + strlen(file) + 2); | 159 | plugin = malloc_or_die(strlen(path) + strlen(file) + 2); |
| 160 | 160 | ||
| @@ -166,19 +166,22 @@ static int load_plugin(struct pevent *pevent, | |||
| 166 | if (!handle) { | 166 | if (!handle) { |
| 167 | warning("cound not load plugin '%s'\n%s\n", | 167 | warning("cound not load plugin '%s'\n%s\n", |
| 168 | plugin, dlerror()); | 168 | plugin, dlerror()); |
| 169 | return -1; | 169 | goto out; |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME); | 172 | func = dlsym(handle, PEVENT_PLUGIN_LOADER_NAME); |
| 173 | if (!func) { | 173 | if (!func) { |
| 174 | warning("cound not find func '%s' in plugin '%s'\n%s\n", | 174 | warning("cound not find func '%s' in plugin '%s'\n%s\n", |
| 175 | PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror()); | 175 | PEVENT_PLUGIN_LOADER_NAME, plugin, dlerror()); |
| 176 | return -1; | 176 | goto out; |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | printf("registering plugin: %s\n", plugin); | 179 | printf("registering plugin: %s\n", plugin); |
| 180 | ret = func(pevent); | 180 | ret = func(pevent); |
| 181 | 181 | ||
| 182 | out: | ||
| 183 | free(plugin); | ||
| 184 | |||
| 182 | /* dlclose ?? */ | 185 | /* dlclose ?? */ |
| 183 | return ret; | 186 | return ret; |
| 184 | } | 187 | } |
| @@ -262,5 +265,7 @@ int trace_load_plugins(struct pevent *pevent) | |||
| 262 | 265 | ||
| 263 | fail: | 266 | fail: |
| 264 | free(path); | 267 | free(path); |
| 268 | closedir(dir); | ||
| 269 | |||
| 265 | return -1; | 270 | return -1; |
| 266 | } | 271 | } |
diff --git a/tracecmd.py b/tracecmd.py index 6520a48..f9a2708 100644 --- a/tracecmd.py +++ b/tracecmd.py | |||
| @@ -31,13 +31,6 @@ and it is recommended applications not use it directly. | |||
| 31 | TODO: consider a complete class hierarchy of ftrace events... | 31 | TODO: consider a complete class hierarchy of ftrace events... |
| 32 | """ | 32 | """ |
| 33 | 33 | ||
| 34 | def _pevent_read_number_field(field, data): | ||
| 35 | ret,hi,lo = pevent_read_number_field_32(field, data) | ||
| 36 | if ret == 0: | ||
| 37 | return ret,long(long(hi).__lshift__(32)+lo) | ||
| 38 | return ret,None | ||
| 39 | |||
| 40 | |||
| 41 | class Event(object): | 34 | class Event(object): |
| 42 | def __init__(self, trace, record): | 35 | def __init__(self, trace, record): |
| 43 | self.trace = trace | 36 | self.trace = trace |
| @@ -46,8 +39,8 @@ class Event(object): | |||
| 46 | self.ec = pevent_data_event_from_type(trace.pe, type) | 39 | self.ec = pevent_data_event_from_type(trace.pe, type) |
| 47 | 40 | ||
| 48 | def __str__(self): | 41 | def __str__(self): |
| 49 | return "%f %s: pid=%d comm=%s type=%d" % \ | 42 | return "%d.%d %s: pid=%d comm=%s type=%d" % \ |
| 50 | (self.ts, self.name, self.num_field("common_pid"), self.comm, self.type) | 43 | (self.ts/1000000000, self.ts%1000000000, self.name, self.num_field("common_pid"), self.comm, self.type) |
| 51 | 44 | ||
| 52 | 45 | ||
| 53 | # TODO: consider caching the results of the properties | 46 | # TODO: consider caching the results of the properties |
| @@ -65,7 +58,6 @@ class Event(object): | |||
| 65 | 58 | ||
| 66 | @property | 59 | @property |
| 67 | def ts(self): | 60 | def ts(self): |
| 68 | # FIXME: this currently returns a float instead of a 64bit nsec value | ||
| 69 | return record_ts_get(self.rec) | 61 | return record_ts_get(self.rec) |
| 70 | 62 | ||
| 71 | @property | 63 | @property |
| @@ -73,9 +65,8 @@ class Event(object): | |||
| 73 | return pevent_data_type(self.trace.pe, self.rec) | 65 | return pevent_data_type(self.trace.pe, self.rec) |
| 74 | 66 | ||
| 75 | def num_field(self, name): | 67 | def num_field(self, name): |
| 76 | # FIXME: need to find an elegant way to handle 64bit fields | ||
| 77 | f = pevent_find_any_field(self.ec, name) | 68 | f = pevent_find_any_field(self.ec, name) |
| 78 | ret,val = _pevent_read_number_field(f, record_data_get(self.rec)) | 69 | val = pevent_read_number_field_py(f, record_data_get(self.rec)) |
| 79 | return val | 70 | return val |
| 80 | 71 | ||
| 81 | 72 | ||
