Implement the arch_perf_record__need_read() architecture-specific hook for powerpc in arch/powerpc/util/evsel.c.
The HTM kernel driver sets event->count to 1 while data is staged in its internal buffers and to 0 once the stream is exhausted. This hook reads that count for every open htm evsel via perf_evsel__read() and accumulates the values. A non-zero total means at least one HTM target still has data pending; the recording loop added in the previous patch will perform another mmap-read pass. The implementation scans the evlist for htm events, iterates the fd/ sample-id xyarray, and skips any evsel whose fd and sample-id arrays are mismatched to avoid reading stale state. When the accumulated count reaches zero the hook returns 0 and the recording loop proceeds to disable and close the events. Signed-off-by: Athira Rajeev <[email protected]> --- Changes in V2: - Implements the renamed arch_perf_record__need_read() hook (V1 implemented arch_record__collect_final_data()). - Skips evsels whose fd and sample-id xyarrays are mismatched, avoiding stale-state reads. V1 had no such guard. - evlist__enable cycling is removed; that responsibility now belongs to the drain loop in builtin-record.c added in patch 3. - File location changed to arch/powerpc/util/evsel.c (V1 used arch/powerpc/util/powerpc-htm.c). - Patch is now 4/6 instead of 4/9. tools/perf/arch/powerpc/util/evsel.c | 69 ++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/tools/perf/arch/powerpc/util/evsel.c b/tools/perf/arch/powerpc/util/evsel.c index 2f733cdc8dbb..8f2805a68026 100644 --- a/tools/perf/arch/powerpc/util/evsel.c +++ b/tools/perf/arch/powerpc/util/evsel.c @@ -1,8 +1,77 @@ // SPDX-License-Identifier: GPL-2.0 #include <stdio.h> +#include <linux/string.h> #include "util/evsel.h" +#include "util/record.h" +#include "util/evlist.h" +#include "util/debug.h" +#include <internal/xyarray.h> void arch_evsel__set_sample_weight(struct evsel *evsel) { evsel__set_sample_bit(evsel, WEIGHT_STRUCT); } + +/* + * Check if HTM events have more data to collect. + * + * This function reads the HTM event counts. When the kernel driver + * has more data available, it returns a non-zero count. When all + * data has been collected, it returns zero. + * + * Returns: 1 if more data exists, 0 if collection is complete + */ +int arch_perf_record__need_read(struct evlist *evlist) +{ + struct evsel *evsel; + bool found_htm = false; + u64 total_pending_bytes = 0; + int x, y; + + /* there was an error during record__open */ + if (!evlist) + return 0; + + /* First, check if any HTM events exist */ + evlist__for_each_entry(evlist, evsel) { + if (evsel->name && strstarts(evsel->name, "htm")) { + found_htm = true; + break; + } + } + + if (!found_htm) + return 0; + + /* Read HTM event counts to check if more data is available */ + evlist__for_each_entry(evlist, evsel) { + struct xyarray *xy = evsel->core.sample_id; + + if (!evsel->name || !strstarts(evsel->name, "htm")) + continue; + + if (!strcmp(evsel->name, "dummy:u")) + continue; + + if (xy == NULL || evsel->core.fd == NULL) + continue; + + if (xyarray__max_x(evsel->core.fd) != xyarray__max_x(xy) || + xyarray__max_y(evsel->core.fd) != xyarray__max_y(xy)) { + pr_debug("Unmatched FD vs sample ID array for HTM event\n"); + continue; + } + + for (x = 0; x < xyarray__max_x(xy); x++) { + for (y = 0; y < xyarray__max_y(xy); y++) { + struct perf_counts_values count = { .val = 0 }; + + if (perf_evsel__read(&evsel->core, x, y, &count) == 0) + total_pending_bytes += count.val; + } + } + } + + /* Collection is complete only when ALL hardware queues match 0 */ + return (total_pending_bytes > 0) ? 1 : 0; +} -- 2.43.0
