[PATCH V2 1/2] perf,tools: store cpu socket_id and core_id in perf.date

From: Kan Liang
Date: Fri Aug 28 2015 - 16:59:46 EST


From: Kan Liang <kan.liang@xxxxxxxxx>

This patch stores cpu socket_id and core_id in perf.date, and read them
to perf_env in header process.

Signed-off-by: Kan Liang <kan.liang@xxxxxxxxx>
---

Changes since V1:
- Store core_id and socket_id in perf.date

tools/perf/util/header.c | 97 +++++++++++++++++++++++++++++++++++++++++++++--
tools/perf/util/header.h | 6 +++
tools/perf/util/session.c | 1 +
3 files changed, 100 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 4181454..482749f 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -439,14 +439,42 @@ static int write_cmdline(int fd, struct perf_header *h __maybe_unused,
"/sys/devices/system/cpu/cpu%d/topology/core_siblings_list"
#define THRD_SIB_FMT \
"/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list"
+#define CORE_ID_FMT \
+ "/sys/devices/system/cpu/cpu%d/topology/core_id"
+#define PHY_PKG_ID_FMT \
+ "/sys/devices/system/cpu/cpu%d/topology/physical_package_id"

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 read_id(const char *path, int cpu)
+{
+ FILE *fp;
+ char filename[MAXPATHLEN];
+ char *buf = NULL;
+ size_t len = 0;
+ int ret = -1;
+
+ sprintf(filename, path, cpu);
+ fp = fopen(filename, "r");
+ if (fp == NULL)
+ return ret;
+
+ if (getline(&buf, &len, fp) > 0)
+ ret = atoi(buf);
+
+ fclose(fp);
+ free(buf);
+ return ret;
+}
+
static int build_cpu_topo(struct cpu_topo *tp, int cpu)
{
FILE *fp;
@@ -507,6 +535,9 @@ try_threads:
}
ret = 0;
done:
+ tp->core_id[cpu] = read_id(CORE_ID_FMT, cpu);
+ tp->phy_pkg_id[cpu] = read_id(PHY_PKG_ID_FMT, cpu);
+
if(fp)
fclose(fp);
free(buf);
@@ -534,7 +565,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 +576,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 +634,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 +983,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 +1000,10 @@ static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused,
fprintf(fp, "# sibling threads : %s\n", str);
str += strlen(str) + 1;
}
+
+ 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);
}

static void free_event_desc(struct perf_evsel *events)
@@ -1590,10 +1640,15 @@ 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;
+
+ 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);
@@ -1631,10 +1686,44 @@ static int process_cpu_topology(struct perf_file_section *section __maybe_unused
free(str);
}
ph->env.sibling_threads = strbuf_detach(&sb, NULL);
+
+ 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:
+ free(ph->env.cpu);
return -1;
}

diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 396e496..975d803 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 8a4537e..61669be 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)
--
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/