While collecting samples using "perf record", function "__cmd_record" checks if monitoring is done. Once recording is done, event list will be disabled using "evlist__disable". After this, event fd won't be read and event will be removed.
Before removing the event, if any additional data needs to be captured/written to perf.data, currently its not possible. Introduce arch_record__collect_final_data to collect additional data before closing the event Signed-off-by: Athira Rajeev <[email protected]> --- tools/perf/builtin-record.c | 29 +++++++++++++++++++++++++++++ tools/perf/util/record.h | 4 ++++ 2 files changed, 33 insertions(+) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index ebd3ed0c9b3e..1312f7223455 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -2426,6 +2426,34 @@ static unsigned long record__waking(struct record *rec) return waking; } +/* + * Weak symbol - architecture can override to indicate if more + * data needs to be collected before finishing output. + * + * Returns: 1 if more data exists, 0 if collection is complete + */ +__weak int arch_perf_record__need_read(struct evlist *evlist __maybe_unused) +{ + return 0; /* Default: no arch-specific data to collect */ +} + +static void record__final_data(struct record *rec) +{ + /* + * Collect any remaining architecture-specific data. + * The arch code checks if more data exists, and we do the actual + * reading here since we have access to record__mmap_read_all(). + */ + while (arch_perf_record__need_read(rec->evlist)) { + if (record__mmap_read_all(rec, false) < 0) + break; + /* Re-enable events for next batch */ + evlist__enable(rec->evlist); + } + + return; +} + static int __cmd_record(struct record *rec, int argc, const char **argv) { int err; @@ -2853,6 +2881,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) */ if (done && !disabled && !target__none(&opts->target)) { trigger_off(&auxtrace_snapshot_trigger); + record__final_data(rec); evlist__disable(rec->evlist); disabled = true; } diff --git a/tools/perf/util/record.h b/tools/perf/util/record.h index 93627c9a7338..21f51efd36fc 100644 --- a/tools/perf/util/record.h +++ b/tools/perf/util/record.h @@ -8,6 +8,8 @@ #include <linux/stddef.h> #include <linux/perf_event.h> #include "util/target.h" +#include "util/evlist.h" +#include "util/util.h" struct option; @@ -95,4 +97,6 @@ static inline bool record_opts__no_switch_events(const struct record_opts *opts) return opts->record_switch_events_set && !opts->record_switch_events; } +int arch_perf_record__need_read(struct evlist *evlist); + #endif // _PERF_RECORD_H -- 2.52.0
