aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt (Google) <rostedt@goodmis.org>2022-08-05 11:40:33 -0400
committerSteven Rostedt (Google) <rostedt@goodmis.org>2022-08-05 11:45:10 -0400
commit2cb6cc2f4e556a9c7a011a5932720b2832324ee7 (patch)
tree76950be40388acd4308aafd3a7a5045a4ff50bfc
parent762839a848e3725e20300c66a467259ad79e616b (diff)
downloadtrace-cmd-2cb6cc2f4e556a9c7a011a5932720b2832324ee7.tar.gz
tracecmd library: Add tracecmd_iterate_events()
Add a helper function that will iterate over a list of events for a given handle. Requires the handle to be opened and ready for reading. Link: https://lore.kernel.org/linux-trace-devel/20220805154040.2014381-3-rostedt@goodmis.org Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
-rw-r--r--include/trace-cmd/trace-cmd.h7
-rw-r--r--lib/trace-cmd/trace-input.c70
2 files changed, 77 insertions, 0 deletions
diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h
index 5d71e8ba..b9123575 100644
--- a/include/trace-cmd/trace-cmd.h
+++ b/include/trace-cmd/trace-cmd.h
@@ -48,6 +48,13 @@ int tracecmd_buffer_instances(struct tracecmd_input *handle);
const char *tracecmd_buffer_instance_name(struct tracecmd_input *handle, int indx);
struct tracecmd_input *tracecmd_buffer_instance_handle(struct tracecmd_input *handle, int indx);
+int tracecmd_iterate_events(struct tracecmd_input *handle,
+ cpu_set_t *cpus, int cpu_size,
+ int (*callback)(struct tracecmd_input *handle,
+ struct tep_record *,
+ int, void *),
+ void *callback_data);
+
void tracecmd_set_loglevel(enum tep_loglevel level);
#endif /* _TRACE_CMD_H */
diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c
index 0fef2ca7..e990600a 100644
--- a/lib/trace-cmd/trace-input.c
+++ b/lib/trace-cmd/trace-input.c
@@ -2512,6 +2512,76 @@ tracecmd_read_next_data(struct tracecmd_input *handle, int *rec_cpu)
}
/**
+ * tracecmd_iterate_events - iterate events over a given handle
+ * @handle: The handle to iterate over
+ * @cpus: The CPU set to filter on (NULL for all CPUs)
+ * @cpu_size: The size of @cpus (ignored if @cpus is NULL)
+ * @callback: The callback function for each event
+ * @callback_data: The data to pass to the @callback.
+ *
+ * Will loop over all events in @handle (filtered by the given @cpus),
+ * and will call @callback for each event in order of the event's records
+ * timestamp.
+ *
+ * Returns the -1 on error, or the value of the callbacks.
+ */
+int tracecmd_iterate_events(struct tracecmd_input *handle,
+ cpu_set_t *cpus, int cpu_size,
+ int (*callback)(struct tracecmd_input *handle,
+ struct tep_record *,
+ int, void *),
+ void *callback_data)
+{
+ struct tep_record **records;
+ struct tep_record *record;
+ unsigned long long last_timestamp = 0;
+ int next_cpu;
+ int cpu;
+ int ret = 0;
+
+ records = calloc(handle->max_cpu, sizeof(*records));
+ if (!records)
+ return -1;
+
+ for (cpu = 0; cpu < handle->max_cpu; cpu++) {
+ if (cpus && !CPU_ISSET_S(cpu, cpu_size, cpus))
+ continue;
+
+ records[cpu] = tracecmd_peek_data(handle, cpu);
+ }
+
+ do {
+ next_cpu = -1;
+ for (cpu = 0; cpu < handle->max_cpu; cpu++) {
+ record = records[cpu];
+ if (!record)
+ continue;
+
+ if (next_cpu < 0 || record->ts < last_timestamp) {
+ next_cpu = cpu;
+ last_timestamp = record->ts;
+ }
+ }
+ if (next_cpu >= 0) {
+ /* Need to call read_data to increment to the next record */
+ record = tracecmd_read_data(handle, next_cpu);
+ records[next_cpu] = tracecmd_peek_data(handle, next_cpu);
+
+ ret = callback(handle, record, next_cpu, callback_data);
+ tracecmd_free_record(record);
+ }
+
+ } while (next_cpu >= 0 && ret >= 0);
+
+ for (cpu = 0; cpu < handle->max_cpu; cpu++)
+ tracecmd_free_record(records[cpu]);
+
+ free(records);
+
+ return ret;
+}
+
+/**
* tracecmd_peek_next_data - return the next record
* @handle: input handle to the trace.dat file
* @rec_cpu: return pointer to the CPU that the record belongs to