diff options
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/util/header.c | 94 | ||||
-rw-r--r-- | tools/perf/util/header.h | 6 | ||||
-rw-r--r-- | tools/perf/util/session.c | 1 |
3 files changed, 96 insertions, 5 deletions
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 41814547da15..8fd7b7de1acd 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -88,6 +88,9 @@ int write_padded(int fd, const void *bf, size_t count, size_t count_aligned) return err; } +#define string_size(str) \ + (PERF_ALIGN((strlen(str) + 1), NAME_ALIGN) + sizeof(u32)) + static int do_write_string(int fd, const char *str) { u32 len, olen; @@ -441,10 +444,13 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused, "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list" struct cpu_topo { + u32 cpu_nr; u32 core_sib; u32 thread_sib; char **core_siblings; char **thread_siblings; + int *core_id; + int *phy_pkg_id; }; static int build_cpu_topo(struct cpu_topo *tp, int cpu) @@ -507,6 +513,9 @@ try_threads: } ret = 0; done: + tp->core_id[cpu] = cpu_map__get_core_id(cpu); + tp->phy_pkg_id[cpu] = cpu_map__get_socket_id(cpu); + if(fp) fclose(fp); free(buf); @@ -534,7 +543,7 @@ static struct cpu_topo *build_cpu_topology(void) struct cpu_topo *tp; void *addr; u32 nr, i; - size_t sz; + size_t sz, sz_id; long ncpus; int ret = -1; @@ -545,17 +554,22 @@ static struct cpu_topo *build_cpu_topology(void) nr = (u32)(ncpus & UINT_MAX); sz = nr * sizeof(char *); + sz_id = nr * sizeof(int); - addr = calloc(1, sizeof(*tp) + 2 * sz); + addr = calloc(1, sizeof(*tp) + 2 * sz + 2 * sz_id); if (!addr) return NULL; tp = addr; - + tp->cpu_nr = nr; addr += sizeof(*tp); tp->core_siblings = addr; addr += sz; tp->thread_siblings = addr; + addr += sz; + tp->core_id = addr; + addr += sz_id; + tp->phy_pkg_id = addr; for (i = 0; i < nr; i++) { ret = build_cpu_topo(tp, i); @@ -598,6 +612,15 @@ static int write_cpu_topology(int fd, struct perf_header *h __maybe_unused, if (ret < 0) break; } + + for (i = 0; i < tp->cpu_nr; i++) { + ret = do_write(fd, &tp->core_id[i], sizeof(int)); + if (ret < 0) + return ret; + ret = do_write(fd, &tp->phy_pkg_id[i], sizeof(int)); + if (ret < 0) + return ret; + } done: free_cpu_topo(tp); return ret; @@ -938,6 +961,7 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused, { int nr, i; char *str; + int cpu_nr = ph->env.nr_cpus_online; nr = ph->env.nr_sibling_cores; str = ph->env.sibling_cores; @@ -954,6 +978,13 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused, fprintf(fp, "# sibling threads : %s\n", str); str += strlen(str) + 1; } + + if (ph->env.cpu != NULL) { + for (i = 0; i < cpu_nr; i++) + fprintf(fp, "# CPU %d: Core ID %d, Socket ID %d\n", i, + ph->env.cpu[i].core_id, ph->env.cpu[i].socket_id); + } else + fprintf(fp, "# Core ID and Socket ID information is not available\n"); } static void free_event_desc(struct perf_evsel *events) @@ -1582,7 +1613,7 @@ error: return -1; } -static int process_cpu_topology(struct perf_file_section *section __maybe_unused, +static int process_cpu_topology(struct perf_file_section *section, struct perf_header *ph, int fd, void *data __maybe_unused) { @@ -1590,15 +1621,22 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused u32 nr, i; char *str; struct strbuf sb; + int cpu_nr = ph->env.nr_cpus_online; + u64 size = 0; + + ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu)); + if (!ph->env.cpu) + return -1; ret = readn(fd, &nr, sizeof(nr)); if (ret != sizeof(nr)) - return -1; + goto free_cpu; if (ph->needs_swap) nr = bswap_32(nr); ph->env.nr_sibling_cores = nr; + size += sizeof(u32); strbuf_init(&sb, 128); for (i = 0; i < nr; i++) { @@ -1608,6 +1646,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused /* include a NULL character at the end */ strbuf_add(&sb, str, strlen(str) + 1); + size += string_size(str); free(str); } ph->env.sibling_cores = strbuf_detach(&sb, NULL); @@ -1620,6 +1659,7 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused nr = bswap_32(nr); ph->env.nr_sibling_threads = nr; + size += sizeof(u32); for (i = 0; i < nr; i++) { str = do_read_string(fd, ph); @@ -1628,13 +1668,57 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused /* include a NULL character at the end */ strbuf_add(&sb, str, strlen(str) + 1); + size += string_size(str); free(str); } ph->env.sibling_threads = strbuf_detach(&sb, NULL); + + /* + * The header may be from old perf, + * which doesn't include core id and socket id information. + */ + if (section->size <= size) { + zfree(&ph->env.cpu); + return 0; + } + + for (i = 0; i < (u32)cpu_nr; i++) { + ret = readn(fd, &nr, sizeof(nr)); + if (ret != sizeof(nr)) + goto free_cpu; + + if (ph->needs_swap) + nr = bswap_32(nr); + + if (nr > (u32)cpu_nr) { + pr_debug("core_id number is too big." + "You may need to upgrade the perf tool.\n"); + goto free_cpu; + } + ph->env.cpu[i].core_id = nr; + + ret = readn(fd, &nr, sizeof(nr)); + if (ret != sizeof(nr)) + goto free_cpu; + + if (ph->needs_swap) + nr = bswap_32(nr); + + if (nr > (u32)cpu_nr) { + pr_debug("socket_id number is too big." + "You may need to upgrade the perf tool.\n"); + goto free_cpu; + } + + ph->env.cpu[i].socket_id = nr; + } + return 0; error: strbuf_release(&sb); +free_cpu: + zfree(&ph->env.cpu); return -1; } diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 396e4965f0c9..975d803f46c8 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -66,6 +66,11 @@ struct perf_header; int perf_file_header__read(struct perf_file_header *header, struct perf_header *ph, int fd); +struct cpu_topology_map { + int socket_id; + int core_id; +}; + struct perf_env { char *hostname; char *os_release; @@ -89,6 +94,7 @@ struct perf_env { char *sibling_threads; char *numa_nodes; char *pmu_mappings; + struct cpu_topology_map *cpu; }; struct perf_header { diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 8a4537ee9bc3..61669be15056 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -185,6 +185,7 @@ static void perf_session_env__exit(struct perf_env *env) zfree(&env->sibling_threads); zfree(&env->numa_nodes); zfree(&env->pmu_mappings); + zfree(&env->cpu); } void perf_session__delete(struct perf_session *session) |