From: Leo Yan <leo.yan@arm.com>
To: Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>, Jiri Olsa <jolsa@kernel.org>,
Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
James Clark <james.clark@linaro.org>,
Suyash Mahar <smahar@meta.com>, Amir Ayupov <aaupov@fb.com>
Cc: linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
Leo Yan <leo.yan@arm.com>
Subject: [PATCH 1/4] perf synthetic-events: Split oversized thread maps into records
Date: Sun, 15 Nov 2026 13:34:19 +0000 [thread overview]
Message-ID: <20261115-perf_fix_large_threads-v1-1-69c9b86b9ae5@arm.com> (raw)
In-Reply-To: <20261115-perf_fix_large_threads-v1-0-69c9b86b9ae5@arm.com>
PERF_RECORD_THREAD_MAP has a 16-bit header.size field. With 16 bytes of
fixed fields and 24 bytes per entry, a record can hold at most 2,729
threads within the 65,535-byte size limit.
For larger maps, header.size overflows and no longer describes the
entries counted by nr, so readers reject the record.
Split larger maps into records that fit the size field. Set
PERF_RECORD_MISC_THREAD_MAP_MORE in header.misc when another record
follows, and clear it in the final record. Preserve entry order and the
existing encoding for maps that fit in one record, including empty maps.
Stop synthesis if allocation or the event callback fails.
Signed-off-by: Leo Yan <leo.yan@arm.com>
---
tools/lib/perf/include/perf/event.h | 8 +++++++
tools/perf/util/synthetic-events.c | 46 +++++++++++++++++++++++++++++--------
2 files changed, 44 insertions(+), 10 deletions(-)
diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h
index fdced574c889e503bda3cf2f8457a14026140025..1785fea2873e4c4dca369b9257626302cece11c0 100644
--- a/tools/lib/perf/include/perf/event.h
+++ b/tools/lib/perf/include/perf/event.h
@@ -406,6 +406,14 @@ struct perf_record_thread_map_entry {
char comm[16];
};
+/*
+ * PERF_RECORD_MISC_THREAD_MAP_MORE means another THREAD_MAP record follows
+ * for the same map. A clear bit marks the final record.
+ * Each nr counts only that record's entries; concatenate records in order.
+ * A map fitting in one record has the bit clear.
+ */
+#define PERF_RECORD_MISC_THREAD_MAP_MORE (1U << 0)
+
struct perf_record_thread_map {
struct perf_event_header header;
__u64 nr;
diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic-events.c
index 3c8d29f27fd91a2cb5ddcf3a20664024edf697c7..938fb63473c479bda167acfe432e7a2d623c6ef0 100644
--- a/tools/perf/util/synthetic-events.c
+++ b/tools/perf/util/synthetic-events.c
@@ -1332,16 +1332,18 @@ int perf_event__synthesize_kernel_mmap(const struct perf_tool *tool,
return perf_event__synthesize_extra_kmaps(tool, process, machine);
}
-int perf_event__synthesize_thread_map2(const struct perf_tool *tool,
- struct perf_thread_map *threads,
- perf_event__handler_t process,
- struct machine *machine)
+static int __perf_event__synthesize_thread_map2(const struct perf_tool *tool,
+ struct perf_thread_map *threads,
+ perf_event__handler_t process,
+ struct machine *machine,
+ int offset, int nr)
{
union perf_event *event;
- int i, err, size;
+ int i, err;
+ size_t size;
size = sizeof(event->thread_map);
- size += threads->nr * sizeof(event->thread_map.entries[0]);
+ size += nr * sizeof(event->thread_map.entries[0]);
event = zalloc(size);
if (!event)
@@ -1349,16 +1351,18 @@ int perf_event__synthesize_thread_map2(const struct perf_tool *tool,
event->header.type = PERF_RECORD_THREAD_MAP;
event->header.size = size;
- event->thread_map.nr = threads->nr;
+ event->header.misc = offset + nr < threads->nr ?
+ PERF_RECORD_MISC_THREAD_MAP_MORE : 0;
+ event->thread_map.nr = nr;
- for (i = 0; i < threads->nr; i++) {
+ for (i = 0; i < nr; i++) {
struct perf_record_thread_map_entry *entry = &event->thread_map.entries[i];
- char *comm = perf_thread_map__comm(threads, i);
+ char *comm = perf_thread_map__comm(threads, offset + i);
if (!comm)
comm = (char *) "";
- entry->pid = perf_thread_map__pid(threads, i);
+ entry->pid = perf_thread_map__pid(threads, offset + i);
strncpy((char *) &entry->comm, comm, sizeof(entry->comm));
}
@@ -1368,6 +1372,28 @@ int perf_event__synthesize_thread_map2(const struct perf_tool *tool,
return err;
}
+int perf_event__synthesize_thread_map2(const struct perf_tool *tool,
+ struct perf_thread_map *threads,
+ perf_event__handler_t process,
+ struct machine *machine)
+{
+ const int max_nr = (UINT16_MAX - sizeof(struct perf_record_thread_map)) /
+ sizeof(struct perf_record_thread_map_entry);
+ int offset = 0;
+ int nr, err;
+
+ do {
+ nr = min(threads->nr - offset, max_nr);
+ err = __perf_event__synthesize_thread_map2(tool, threads, process, machine,
+ offset, nr);
+ if (err)
+ return err;
+ offset += nr;
+ } while (offset < threads->nr);
+
+ return 0;
+}
+
struct synthesize_cpu_map_data {
const struct perf_cpu_map *map;
int nr;
--
2.34.1
next prev parent reply other threads:[~2026-11-15 13:34 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-15 13:34 [PATCH 0/4] perf: Support thread maps larger than one record Leo Yan
2026-11-15 13:34 ` Leo Yan [this message]
2026-11-15 13:34 ` [PATCH 2/4] perf: Assemble split thread maps in script and stat report Leo Yan
2026-11-15 13:34 ` [PATCH 3/4] perf test: Cover multi-record thread map synthesis Leo Yan
2026-11-15 13:34 ` [PATCH 4/4] perf docs: Describe multi-record thread maps Leo Yan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261115-perf_fix_large_threads-v1-1-69c9b86b9ae5@arm.com \
--to=leo.yan@arm.com \
--cc=aaupov@fb.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=irogers@google.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=namhyung@kernel.org \
--cc=smahar@meta.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®