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 | ||