aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2009-12-12 22:53:12 -0500
committerSteven Rostedt <rostedt@goodmis.org>2009-12-12 22:53:12 -0500
commit8f2de2b4080a3d871810b77dff983f0d89b551ad (patch)
tree0df4d024b99fb26511ad9944c4daab21a90a7dce
parent61d90eef4b5849d00ca064512fe178345f4bcfd1 (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.h3
-rw-r--r--trace-input.c78
-rw-r--r--trace-read.c68
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 *
59tracecmd_translate_data(struct tracecmd_input *handle, 59tracecmd_translate_data(struct tracecmd_input *handle,
60 void *ptr, int size); 60 void *ptr, int size);
61 61
62int tracecmd_set_cpu_to_timestamp(struct tracecmd_input *handle,
63 int cpu, unsigned long long ts);
64
62int tracecmd_ftrace_overrides(struct tracecmd_input *handle); 65int tracecmd_ftrace_overrides(struct tracecmd_input *handle);
63struct pevent *tracecmd_get_pevent(struct tracecmd_input *handle); 66struct 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
544static int get_page(struct tracecmd_input *handle, int cpu, 546static 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}
573static int get_next_page(struct tracecmd_input *handle, int cpu) 578static 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
766int
767tracecmd_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
761static unsigned int 832static unsigned int
762translate_data(struct tracecmd_input *handle, 833translate_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
50static off64_t test_read_at_offset; 51static off64_t test_read_at_offset;
51static int test_read_at_copy = 100; 52static int test_read_at_copy = 100;
52static int test_read_at_index; 53static int test_read_at_index;
53static void test_read_at(struct tracecmd_input *handle) 54static 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
77static void test_read_at_save(struct record *record) 78static 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 */
85static 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
91static unsigned long long test_at_timestamp_ts;
92static int test_at_timestamp_copy = 100;
93static int test_at_timestamp_cpu = -1;
94static int test_at_timestamp_index;
95static 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
124static 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}
88static void test_read_at_save(struct record *record) 134#endif /* TEST_AT_TIMESTAMP */
135
136#ifndef DO_TEST
137static void show_test(struct tracecmd_input *handle)
89{ 138{
90} 139}
91#endif /* TEST_READ_AT */ 140static void test_save(struct record *record, int cpu)
141{
142}
143#endif
92 144
93static void show_data(struct tracecmd_input *handle, int cpu) 145static 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
174struct tracecmd_input *read_trace_header(void) 226struct tracecmd_input *read_trace_header(void)