diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-02-08 11:43:59 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-02-08 14:49:51 -0500 |
commit | 0147df4b777ade75785c4667ef4b6e5642ca6590 (patch) | |
tree | ffcde3cb5e75231c2e01d1a2e07206f4b1065885 | |
parent | 38e4c3fb1424da4b4a6eebe808108907fc31a43b (diff) |
trace-cmd: Add new tracecmd_set_cursor() function
The tracecmd_set_cursor() takes an offset that will cause the next
tracecmd_peek_data() or tracecmd_read_data() to return a record at
that offset (given that the CPU matches). This is useful when
iterating with tracecmd_read_data() and then needing to read a
record out of sequence. One can do:
while ((record = tracecmd_read_data(h, cpu))) {
/* ... */
free_record(record);
record = tracecmd_peek_data(h, cpu);
save_offset = record->offset;
free_record(record);
record = tracecmd_read_at(h, o, NULL);
/* ... */
tracecmd_set_cursor(h, cpu, save_offset);
}
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | trace-cmd.h | 3 | ||||
-rw-r--r-- | trace-input.c | 94 |
2 files changed, 85 insertions, 12 deletions
diff --git a/trace-cmd.h b/trace-cmd.h index eda7181..b7cd5cc 100644 --- a/trace-cmd.h +++ b/trace-cmd.h | |||
@@ -82,6 +82,9 @@ int tracecmd_refresh_record(struct tracecmd_input *handle, | |||
82 | int tracecmd_set_cpu_to_timestamp(struct tracecmd_input *handle, | 82 | int tracecmd_set_cpu_to_timestamp(struct tracecmd_input *handle, |
83 | int cpu, unsigned long long ts); | 83 | int cpu, unsigned long long ts); |
84 | 84 | ||
85 | int tracecmd_set_cursor(struct tracecmd_input *handle, | ||
86 | int cpu, unsigned long long offset); | ||
87 | |||
85 | int tracecmd_ftrace_overrides(struct tracecmd_input *handle); | 88 | int tracecmd_ftrace_overrides(struct tracecmd_input *handle); |
86 | struct pevent *tracecmd_get_pevent(struct tracecmd_input *handle); | 89 | struct pevent *tracecmd_get_pevent(struct tracecmd_input *handle); |
87 | 90 | ||
diff --git a/trace-input.c b/trace-input.c index 884dd2f..3191510 100644 --- a/trace-input.c +++ b/trace-input.c | |||
@@ -816,13 +816,13 @@ read_old_format(struct tracecmd_input *handle, void **ptr, int cpu) | |||
816 | } | 816 | } |
817 | 817 | ||
818 | static struct record * | 818 | static struct record * |
819 | read_event(struct tracecmd_input *handle, unsigned long long offset, | 819 | peek_event(struct tracecmd_input *handle, unsigned long long offset, |
820 | int cpu) | 820 | int cpu) |
821 | { | 821 | { |
822 | struct record *record = NULL; | 822 | struct record *record = NULL; |
823 | 823 | ||
824 | /* | 824 | /* |
825 | * Since the timestamp is calculated from the beginnnig | 825 | * Since the timestamp is calculated from the beginning |
826 | * of the page and through each event, we reset the | 826 | * of the page and through each event, we reset the |
827 | * page to the beginning. This is just used by | 827 | * page to the beginning. This is just used by |
828 | * tracecmd_read_at. | 828 | * tracecmd_read_at. |
@@ -834,21 +834,30 @@ read_event(struct tracecmd_input *handle, unsigned long long offset, | |||
834 | } | 834 | } |
835 | 835 | ||
836 | do { | 836 | do { |
837 | if (record) | 837 | free_record(record); |
838 | free_record(record); | 838 | record = tracecmd_peek_data(handle, cpu); |
839 | /* Make sure peek returns new data */ | 839 | if (record && (record->offset + record->record_size) > offset) |
840 | if (handle->cpu_data[cpu].next) { | 840 | break; |
841 | free_record(handle->cpu_data[cpu].next); | ||
842 | handle->cpu_data[cpu].next = NULL; | ||
843 | } | ||
844 | record = tracecmd_read_data(handle, cpu); | 841 | record = tracecmd_read_data(handle, cpu); |
845 | } while (record && (record->offset + record->record_size) <= offset); | 842 | } while (record); |
846 | 843 | ||
847 | return record; | 844 | return record; |
848 | } | 845 | } |
849 | 846 | ||
850 | static struct record * | 847 | static struct record * |
851 | find_and_read_event(struct tracecmd_input *handle, unsigned long long offset, | 848 | read_event(struct tracecmd_input *handle, unsigned long long offset, |
849 | int cpu) | ||
850 | { | ||
851 | struct record *record; | ||
852 | |||
853 | record = peek_event(handle, offset, cpu); | ||
854 | if (record) | ||
855 | record = tracecmd_read_data(handle, cpu); | ||
856 | return record; | ||
857 | } | ||
858 | |||
859 | static struct record * | ||
860 | find_and_peek_event(struct tracecmd_input *handle, unsigned long long offset, | ||
852 | int *pcpu) | 861 | int *pcpu) |
853 | { | 862 | { |
854 | unsigned long long page_offset; | 863 | unsigned long long page_offset; |
@@ -875,7 +884,24 @@ find_and_read_event(struct tracecmd_input *handle, unsigned long long offset, | |||
875 | if (pcpu) | 884 | if (pcpu) |
876 | *pcpu = cpu; | 885 | *pcpu = cpu; |
877 | 886 | ||
878 | return read_event(handle, offset, cpu); | 887 | return peek_event(handle, offset, cpu); |
888 | } | ||
889 | |||
890 | |||
891 | static struct record * | ||
892 | find_and_read_event(struct tracecmd_input *handle, unsigned long long offset, | ||
893 | int *pcpu) | ||
894 | { | ||
895 | struct record *record; | ||
896 | int cpu; | ||
897 | |||
898 | record = find_and_peek_event(handle, offset, &cpu); | ||
899 | if (record) { | ||
900 | record = tracecmd_read_data(handle, cpu); | ||
901 | if (pcpu) | ||
902 | *pcpu = cpu; | ||
903 | } | ||
904 | return record; | ||
879 | } | 905 | } |
880 | 906 | ||
881 | /** | 907 | /** |
@@ -1147,6 +1173,50 @@ tracecmd_set_cpu_to_timestamp(struct tracecmd_input *handle, int cpu, | |||
1147 | return 0; | 1173 | return 0; |
1148 | } | 1174 | } |
1149 | 1175 | ||
1176 | /** | ||
1177 | * tracecmd_set_cursor - set the offset for the next tracecmd_read_data | ||
1178 | * @handle: input handle for the trace.dat file | ||
1179 | * @cpu: the CPU pointer to set | ||
1180 | * @offset: the offset to place the cursor | ||
1181 | * | ||
1182 | * Set the pointer to the next read or peek. This is useful when | ||
1183 | * needing to read sequentially and then look at another record | ||
1184 | * out of sequence without breaking the iteration. This is done with: | ||
1185 | * | ||
1186 | * record = tracecmd_peek_data() | ||
1187 | * offset = record->offset; | ||
1188 | * record = tracecmd_read_at(); | ||
1189 | * - do what ever with record - | ||
1190 | * tracecmd_set_cursor(handle, cpu, offset); | ||
1191 | * | ||
1192 | * Now the next tracecmd_peek_data or tracecmd_read_data will return | ||
1193 | * the original record. | ||
1194 | */ | ||
1195 | int tracecmd_set_cursor(struct tracecmd_input *handle, | ||
1196 | int cpu, unsigned long long offset) | ||
1197 | { | ||
1198 | struct cpu_data *cpu_data = &handle->cpu_data[cpu]; | ||
1199 | unsigned long long page_offset; | ||
1200 | |||
1201 | if (cpu < 0 || cpu >= handle->cpus) | ||
1202 | return -1; | ||
1203 | |||
1204 | if (offset < cpu_data->file_offset || | ||
1205 | offset > cpu_data->file_offset + cpu_data->file_size) | ||
1206 | return -1; /* cpu does not have this offset. */ | ||
1207 | |||
1208 | /* Move this cpu index to point to this offest */ | ||
1209 | page_offset = offset & ~(handle->page_size - 1); | ||
1210 | |||
1211 | if (get_page(handle, cpu, page_offset) < 0) | ||
1212 | return -1; | ||
1213 | |||
1214 | peek_event(handle, offset, cpu); | ||
1215 | |||
1216 | return 0; | ||
1217 | } | ||
1218 | |||
1219 | |||
1150 | static unsigned int | 1220 | static unsigned int |
1151 | translate_data(struct tracecmd_input *handle, | 1221 | translate_data(struct tracecmd_input *handle, |
1152 | void **ptr, unsigned long long *delta, int *length) | 1222 | void **ptr, unsigned long long *delta, int *length) |