From: "Steven Rostedt (Google)" <rostedt@xxxxxxxxxxx> Add a helper function that takes an array of tracecmd_input handles and calls the callback for each event in order of the record's timestamp for each handle. Signed-off-by: Steven Rostedt (Google) <rostedt@xxxxxxxxxxx> --- include/trace-cmd/trace-cmd.h | 6 +++ lib/trace-cmd/trace-input.c | 91 +++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h index b91235751d64..86a3486972cc 100644 --- a/include/trace-cmd/trace-cmd.h +++ b/include/trace-cmd/trace-cmd.h @@ -54,6 +54,12 @@ int tracecmd_iterate_events(struct tracecmd_input *handle, struct tep_record *, int, void *), void *callback_data); +int tracecmd_iterate_events_multi(struct tracecmd_input **handles, + int nr_handles, + int (*callback)(struct tracecmd_input *handle, + struct tep_record *, + int, void *), + void *callback_data); void tracecmd_set_loglevel(enum tep_loglevel level); diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c index e990600ad6b1..5df10716013d 100644 --- a/lib/trace-cmd/trace-input.c +++ b/lib/trace-cmd/trace-input.c @@ -170,6 +170,7 @@ struct tracecmd_input { int page_map_size; int max_cpu; int cpus; + int start_cpu; int ref; int nr_buffers; /* buffer instances */ bool use_trace_clock; @@ -2581,6 +2582,96 @@ int tracecmd_iterate_events(struct tracecmd_input *handle, return ret; } +struct record_handle { + struct tep_record *record; + struct tracecmd_input *handle; +}; + +/** + * tracecmd_iterate_events_multi - iterate events over multiple handles + * @handles: An array of handles to iterate over + * @nr_handles: The number of handles in the @handles array. + * @callback: The callback function for each event + * @callback_data: The data to pass to the @callback. + * + * Will loop over all CPUs for each handle in @handles and call the + * @callback in the order of the timestamp for each event's record + * for each handle. + * + * Returns the -1 on error, or the value of the callbacks. + */ +int tracecmd_iterate_events_multi(struct tracecmd_input **handles, + int nr_handles, + int (*callback)(struct tracecmd_input *handle, + struct tep_record *, + int, void *), + void *callback_data) +{ + struct tracecmd_input *handle; + struct record_handle *records; + struct tep_record *record; + unsigned long long last_timestamp = 0; + int next_cpu; + int cpus = 0; + int all_cpus = 0; + int cpu; + int i; + int ret = 0; + + for (i = 0; i < nr_handles; i++) { + handle = handles[i]; + cpus += handle->max_cpu; + } + + records = calloc(cpus, sizeof(*records)); + if (!records) + return -1; + + for (i = 0; i < nr_handles; i++) { + handle = handles[i]; + handle->start_cpu = all_cpus; + for (cpu = 0; cpu < handle->max_cpu; cpu++) { + records[all_cpus + cpu].record = tracecmd_peek_data(handle, cpu); + records[all_cpus + cpu].handle = handle; + } + all_cpus += cpu; + } + + do { + next_cpu = -1; + for (cpu = 0; cpu < all_cpus; cpu++) { + record = records[cpu].record; + if (!record) + continue; + + if (next_cpu < 0 || record->ts < last_timestamp) { + next_cpu = cpu; + last_timestamp = record->ts; + } + } + if (next_cpu >= 0) { + record = records[next_cpu].record; + handle = records[next_cpu].handle; + cpu = next_cpu - handle->start_cpu; + /* Need to call read_data to increment to the next record */ + record = tracecmd_read_data(handle, cpu); + records[next_cpu].record = tracecmd_peek_data(handle, cpu); + + ret = callback(handle, record, cpu, callback_data); + tracecmd_free_record(record); + } + + } while (next_cpu >= 0 && ret >= 0); + + /* + * The records array contains only records that were taken via + * tracecmd_peek_data(), and do not need to be freed. + */ + free(records); + + return ret; +} + /** * tracecmd_peek_next_data - return the next record * @handle: input handle to the trace.dat file -- 2.35.1