diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-12-12 22:53:12 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2009-12-12 22:53:12 -0500 |
commit | 8f2de2b4080a3d871810b77dff983f0d89b551ad (patch) | |
tree | 0df4d024b99fb26511ad9944c4daab21a90a7dce | |
parent | 61d90eef4b5849d00ca064512fe178345f4bcfd1 (diff) |
Add tracecmd_set_cpu_to_timestamp()
This adds an API to set the CPU data field to the location
specified by a timestamp. It looks for the page that contains or
is before the timestamp to allow for walking forward to find
the specified event.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | trace-cmd.h | 3 | ||||
-rw-r--r-- | trace-input.c | 78 | ||||
-rw-r--r-- | trace-read.c | 68 |
3 files changed, 140 insertions, 9 deletions
diff --git a/trace-cmd.h b/trace-cmd.h index 39dff16..cc63627 100644 --- a/trace-cmd.h +++ b/trace-cmd.h | |||
@@ -59,6 +59,9 @@ struct record * | |||
59 | tracecmd_translate_data(struct tracecmd_input *handle, | 59 | tracecmd_translate_data(struct tracecmd_input *handle, |
60 | void *ptr, int size); | 60 | void *ptr, int size); |
61 | 61 | ||
62 | int tracecmd_set_cpu_to_timestamp(struct tracecmd_input *handle, | ||
63 | int cpu, unsigned long long ts); | ||
64 | |||
62 | int tracecmd_ftrace_overrides(struct tracecmd_input *handle); | 65 | int tracecmd_ftrace_overrides(struct tracecmd_input *handle); |
63 | struct pevent *tracecmd_get_pevent(struct tracecmd_input *handle); | 66 | struct pevent *tracecmd_get_pevent(struct tracecmd_input *handle); |
64 | 67 | ||
diff --git a/trace-input.c b/trace-input.c index 0a8ebb1..0d50bf0 100644 --- a/trace-input.c +++ b/trace-input.c | |||
@@ -537,8 +537,10 @@ static int get_read_page(struct tracecmd_input *handle, int cpu, | |||
537 | /* reset the file pointer back */ | 537 | /* reset the file pointer back */ |
538 | lseek64(handle->fd, save_seek, SEEK_SET); | 538 | lseek64(handle->fd, save_seek, SEEK_SET); |
539 | 539 | ||
540 | return 0; | 540 | handle->cpu_data[cpu].timestamp = |
541 | data2host8(handle->pevent, handle->cpu_data[cpu].page); | ||
541 | 542 | ||
543 | return 0; | ||
542 | } | 544 | } |
543 | 545 | ||
544 | static int get_page(struct tracecmd_input *handle, int cpu, | 546 | static int get_page(struct tracecmd_input *handle, int cpu, |
@@ -568,6 +570,9 @@ static int get_page(struct tracecmd_input *handle, int cpu, | |||
568 | if (handle->cpu_data[cpu].page == MAP_FAILED) | 570 | if (handle->cpu_data[cpu].page == MAP_FAILED) |
569 | return -1; | 571 | return -1; |
570 | 572 | ||
573 | handle->cpu_data[cpu].timestamp = | ||
574 | data2host8(handle->pevent, handle->cpu_data[cpu].page); | ||
575 | |||
571 | return 0; | 576 | return 0; |
572 | } | 577 | } |
573 | static int get_next_page(struct tracecmd_input *handle, int cpu) | 578 | static int get_next_page(struct tracecmd_input *handle, int cpu) |
@@ -758,6 +763,72 @@ tracecmd_read_at(struct tracecmd_input *handle, unsigned long long offset, | |||
758 | return find_and_read_event(handle, offset, pcpu); | 763 | return find_and_read_event(handle, offset, pcpu); |
759 | } | 764 | } |
760 | 765 | ||
766 | int | ||
767 | tracecmd_set_cpu_to_timestamp(struct tracecmd_input *handle, int cpu, | ||
768 | unsigned long long ts) | ||
769 | { | ||
770 | struct cpu_data *cpu_data = &handle->cpu_data[cpu]; | ||
771 | off64_t start, end, next; | ||
772 | |||
773 | if (cpu < 0 || cpu >= handle->cpus) { | ||
774 | errno = -EINVAL; | ||
775 | return -1; | ||
776 | } | ||
777 | |||
778 | if (!cpu_data->page) { | ||
779 | if (init_cpu(handle, cpu)) | ||
780 | return -1; | ||
781 | } | ||
782 | |||
783 | if (cpu_data->timestamp == ts) | ||
784 | return 0; | ||
785 | |||
786 | if (cpu_data->timestamp < ts) { | ||
787 | start = cpu_data->offset; | ||
788 | end = cpu_data->file_offset + cpu_data->file_size; | ||
789 | if (end & (handle->page_size - 1)) | ||
790 | end &= ~(handle->page_size - 1); | ||
791 | else | ||
792 | end -= handle->page_size; | ||
793 | next = end; | ||
794 | } else { | ||
795 | end = cpu_data->offset; | ||
796 | start = cpu_data->file_offset; | ||
797 | next = start; | ||
798 | } | ||
799 | |||
800 | while (start < end) { | ||
801 | if (get_page(handle, cpu, next)) | ||
802 | return -1; | ||
803 | |||
804 | if (cpu_data->timestamp == ts) | ||
805 | break; | ||
806 | |||
807 | if (cpu_data->timestamp < ts) | ||
808 | start = next; | ||
809 | else | ||
810 | end = next; | ||
811 | |||
812 | next = start + (end - start) / 2; | ||
813 | next &= ~(handle->page_size - 1); | ||
814 | } | ||
815 | |||
816 | /* | ||
817 | * We need to end up on a page before the time stamp. | ||
818 | * We go back even if the timestamp is the same. This is because | ||
819 | * we want the event with the timestamp, not the page. The page | ||
820 | * can start with the timestamp we are looking for, but the event | ||
821 | * may be on the previous page. | ||
822 | */ | ||
823 | if (cpu_data->timestamp >= ts && | ||
824 | cpu_data->offset > cpu_data->file_offset) | ||
825 | get_page(handle, cpu, cpu_data->offset - handle->page_size); | ||
826 | |||
827 | cpu_data->index = 0; | ||
828 | |||
829 | return 0; | ||
830 | } | ||
831 | |||
761 | static unsigned int | 832 | static unsigned int |
762 | translate_data(struct tracecmd_input *handle, | 833 | translate_data(struct tracecmd_input *handle, |
763 | void **ptr, unsigned long long *delta, int *length) | 834 | void **ptr, unsigned long long *delta, int *length) |
@@ -976,6 +1047,9 @@ static int init_read(struct tracecmd_input *handle, int cpu) | |||
976 | /* reset the file pointer back */ | 1047 | /* reset the file pointer back */ |
977 | lseek64(handle->fd, save_seek, SEEK_SET); | 1048 | lseek64(handle->fd, save_seek, SEEK_SET); |
978 | 1049 | ||
1050 | handle->cpu_data[cpu].timestamp = | ||
1051 | data2host8(handle->pevent, handle->cpu_data[cpu].page); | ||
1052 | |||
979 | return 0; | 1053 | return 0; |
980 | } | 1054 | } |
981 | 1055 | ||
@@ -1004,6 +1078,8 @@ static int init_cpu(struct tracecmd_input *handle, int cpu) | |||
1004 | 1078 | ||
1005 | return init_read(handle, cpu); | 1079 | return init_read(handle, cpu); |
1006 | } | 1080 | } |
1081 | handle->cpu_data[cpu].timestamp = | ||
1082 | data2host8(handle->pevent, handle->cpu_data[cpu].page); | ||
1007 | return 0; | 1083 | return 0; |
1008 | } | 1084 | } |
1009 | 1085 | ||
diff --git a/trace-read.c b/trace-read.c index bf01c55..48c9510 100644 --- a/trace-read.c +++ b/trace-read.c | |||
@@ -47,10 +47,11 @@ static int filter_cpu = -1; | |||
47 | /* Debug variables for testing tracecmd_read_at */ | 47 | /* Debug variables for testing tracecmd_read_at */ |
48 | #define TEST_READ_AT 0 | 48 | #define TEST_READ_AT 0 |
49 | #if TEST_READ_AT | 49 | #if TEST_READ_AT |
50 | #define DO_TEST | ||
50 | static off64_t test_read_at_offset; | 51 | static off64_t test_read_at_offset; |
51 | static int test_read_at_copy = 100; | 52 | static int test_read_at_copy = 100; |
52 | static int test_read_at_index; | 53 | static int test_read_at_index; |
53 | static void test_read_at(struct tracecmd_input *handle) | 54 | static void show_test(struct tracecmd_input *handle) |
54 | { | 55 | { |
55 | struct pevent *pevent; | 56 | struct pevent *pevent; |
56 | struct record *record; | 57 | struct record *record; |
@@ -74,21 +75,72 @@ static void test_read_at(struct tracecmd_input *handle) | |||
74 | free(record); | 75 | free(record); |
75 | } | 76 | } |
76 | 77 | ||
77 | static void test_read_at_save(struct record *record) | 78 | static void test_save(struct record *record, int cpu) |
78 | { | 79 | { |
79 | if (test_read_at_index++ == test_read_at_copy) { | 80 | if (test_read_at_index++ == test_read_at_copy) { |
80 | test_read_at_offset = record->offset; | 81 | test_read_at_offset = record->offset; |
81 | printf("\nUSING THIS RECORD\n"); | 82 | printf("\nUSING THIS RECORD\n"); |
82 | } | 83 | } |
83 | } | 84 | } |
84 | #else | 85 | #endif /* TEST_READ_AT */ |
85 | static void test_read_at(struct tracecmd_input *handle) | 86 | |
87 | /* Debug variables for testing tracecmd_set_cpu_at_timestamp */ | ||
88 | #define TEST_AT_TIMESTAMP 0 | ||
89 | #if TEST_AT_TIMESTAMP | ||
90 | #define DO_TEST | ||
91 | static unsigned long long test_at_timestamp_ts; | ||
92 | static int test_at_timestamp_copy = 100; | ||
93 | static int test_at_timestamp_cpu = -1; | ||
94 | static int test_at_timestamp_index; | ||
95 | static void show_test(struct tracecmd_input *handle) | ||
86 | { | 96 | { |
97 | struct pevent *pevent; | ||
98 | struct record *record; | ||
99 | struct trace_seq s; | ||
100 | int cpu = test_at_timestamp_cpu; | ||
101 | |||
102 | if (!test_at_timestamp_ts) { | ||
103 | printf("\nNO RECORD COPIED\n"); | ||
104 | return; | ||
105 | } | ||
106 | |||
107 | pevent = tracecmd_get_pevent(handle); | ||
108 | |||
109 | if (tracecmd_set_cpu_to_timestamp(handle, cpu, test_at_timestamp_ts)) | ||
110 | return; | ||
111 | |||
112 | record = tracecmd_read_data(handle, cpu); | ||
113 | printf("\nHERE'S THE COPY RECORD with page %p offset=%p\n", | ||
114 | (void *)(record->offset & ~(page_size - 1)), | ||
115 | (void *)record->offset); | ||
116 | trace_seq_init(&s); | ||
117 | pevent_print_event(pevent, &s, cpu, record->data, record->size, record->ts); | ||
118 | trace_seq_do_printf(&s); | ||
119 | printf("\n"); | ||
120 | |||
121 | free(record); | ||
122 | } | ||
123 | |||
124 | static void test_save(struct record *record, int cpu) | ||
125 | { | ||
126 | if (test_at_timestamp_index++ == test_at_timestamp_copy) { | ||
127 | test_at_timestamp_ts = record->ts; | ||
128 | test_at_timestamp_cpu = cpu; | ||
129 | printf("\nUSING THIS RECORD page=%p offset=%p\n", | ||
130 | (void *)(record->offset & ~(page_size - 1)), | ||
131 | (void *)record->offset); | ||
132 | } | ||
87 | } | 133 | } |
88 | static void test_read_at_save(struct record *record) | 134 | #endif /* TEST_AT_TIMESTAMP */ |
135 | |||
136 | #ifndef DO_TEST | ||
137 | static void show_test(struct tracecmd_input *handle) | ||
89 | { | 138 | { |
90 | } | 139 | } |
91 | #endif /* TEST_READ_AT */ | 140 | static void test_save(struct record *record, int cpu) |
141 | { | ||
142 | } | ||
143 | #endif | ||
92 | 144 | ||
93 | static void show_data(struct tracecmd_input *handle, int cpu) | 145 | static void show_data(struct tracecmd_input *handle, int cpu) |
94 | { | 146 | { |
@@ -100,7 +152,7 @@ static void show_data(struct tracecmd_input *handle, int cpu) | |||
100 | 152 | ||
101 | record = tracecmd_read_data(handle, cpu); | 153 | record = tracecmd_read_data(handle, cpu); |
102 | 154 | ||
103 | test_read_at_save(record); | 155 | test_save(record, cpu); |
104 | 156 | ||
105 | trace_seq_init(&s); | 157 | trace_seq_init(&s); |
106 | pevent_print_event(pevent, &s, cpu, record->data, record->size, record->ts); | 158 | pevent_print_event(pevent, &s, cpu, record->data, record->size, record->ts); |
@@ -168,7 +220,7 @@ static void read_data_info(struct tracecmd_input *handle) | |||
168 | 220 | ||
169 | } while (next >= 0); | 221 | } while (next >= 0); |
170 | 222 | ||
171 | test_read_at(handle); | 223 | show_test(handle); |
172 | } | 224 | } |
173 | 225 | ||
174 | struct tracecmd_input *read_trace_header(void) | 226 | struct tracecmd_input *read_trace_header(void) |