From: Namhyung Kim <namhyung@kernel.org>
To: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: Ingo Molnar <mingo@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
LKML <linux-kernel@vger.kernel.org>,
Stephane Eranian <eranian@google.com>
Subject: [PATCH 2/5] perf header: add ->process callbacks to most of features
Date: Sun, 22 Jul 2012 01:45:32 +0900 [thread overview]
Message-ID: <1342889135-14825-2-git-send-email-namhyung@kernel.org> (raw)
In-Reply-To: <1342889135-14825-1-git-send-email-namhyung@kernel.org>
>From now for each feature information is processed and saved in perf
header so that it can be used wherever needed. The EVENT_DESC and
BRANCH_STACK features are exceptions since they need nothing to be done.
Cc: Stephane Eranian <eranian@google.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
| 360 ++++++++++++++++++++++++++++++++++++++++++++--
| 13 ++
2 files changed, 363 insertions(+), 10 deletions(-)
--git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 193aa089f9a6..1a30f2831616 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1377,6 +1377,346 @@ static int process_build_id(struct perf_file_section *section,
return 0;
}
+static int process_hostname(struct perf_file_section *section __used,
+ struct perf_header *ph, int feat __used, int fd,
+ void *data __used)
+{
+ ph->hostname = do_read_string(fd, ph);
+ return ph->hostname ? 0 : -ENOMEM;
+}
+
+static int process_osrelease(struct perf_file_section *section __used,
+ struct perf_header *ph, int feat __used, int fd,
+ void *data __used)
+{
+
+ ph->os_release = do_read_string(fd, ph);
+ return ph->os_release ? 0 : -ENOMEM;
+}
+
+static int process_arch(struct perf_file_section *section __used,
+ struct perf_header *ph, int feat __used, int fd,
+ void *data __used)
+{
+ ph->arch = do_read_string(fd, ph);
+ return ph->arch ? 0 : -ENOMEM;
+}
+
+static int process_cpudesc(struct perf_file_section *section __used,
+ struct perf_header *ph, int feat __used, int fd,
+ void *data __used)
+{
+ ph->cpu_desc = do_read_string(fd, ph);
+ return ph->cpu_desc ? 0 : -ENOMEM;
+}
+
+static int process_nrcpus(struct perf_file_section *section __used,
+ struct perf_header *ph, int feat __used, int fd,
+ void *data __used)
+{
+ ssize_t ret;
+ u32 nr;
+
+ ret = read(fd, &nr, sizeof(nr));
+ if (ret != (ssize_t)sizeof(nr))
+ nr = -1; /* interpreted as error */
+
+ if (ph->needs_swap)
+ nr = bswap_32(nr);
+
+ ph->nr_cpus_online = nr;
+
+ ret = read(fd, &nr, sizeof(nr));
+ if (ret != (ssize_t)sizeof(nr))
+ nr = -1; /* interpreted as error */
+
+ if (ph->needs_swap)
+ nr = bswap_32(nr);
+
+ ph->nr_cpus_avail = nr;
+
+ return 0;
+}
+
+static int process_version(struct perf_file_section *section __used,
+ struct perf_header *ph, int feat __used, int fd,
+ void *data __used)
+{
+ ph->version = do_read_string(fd, ph);
+ return ph->version ? 0 : -ENOMEM;
+}
+
+/* Each argv would be separated by a NULL character */
+static int process_cmdline(struct perf_file_section *section __used,
+ struct perf_header *ph, int feat __used, int fd,
+ void *data __used)
+{
+ ssize_t ret;
+ char *str, *tmp;
+ u32 nr, i;
+ char *cmdline = NULL;
+ size_t len = 0;
+
+ ret = read(fd, &nr, sizeof(nr));
+ if (ret != (ssize_t)sizeof(nr))
+ return -1;
+
+ if (ph->needs_swap)
+ nr = bswap_32(nr);
+
+ ph->cmdline_argc = nr;
+
+ for (i = 0; i < nr; i++) {
+ str = do_read_string(fd, ph);
+ if (!str)
+ goto error;
+
+ tmp = realloc(cmdline, len + strlen(str) + 1);
+ if (!tmp)
+ goto error;
+ cmdline = tmp;
+
+ /* include null character at the end */
+ strcpy(cmdline + len, str);
+
+ len += strlen(str) + 1;
+ free(str);
+ }
+ ph->cmdline = cmdline;
+ return 0;
+
+error:
+ free(cmdline);
+ free(str);
+ return -1;
+}
+
+#define TOPO_STR_LEN ((size_t) 256)
+#define TOPO_STR_DELIM ':'
+
+#define check_topo_len(topo, allocated, used, len) \
+({ \
+ if (len > allocated - used) { \
+ char *tmp = realloc(topo, allocated + TOPO_STR_LEN); \
+ if (!tmp) \
+ goto error; \
+ topo = tmp; \
+ allocated += TOPO_STR_LEN; \
+ } \
+})
+
+/*
+ * The topology string looks like below (':' is used for delimiter):
+ *
+ * "NR_CORE_SIBLINGS(N):SIBLING[0]:SIBLING[1]:...:SIBLING[N-1]\n"
+ * "NR_THREAD_SIBLINGS(M):SIBLING[0]:SIBLING[1]:...:SIBLING[M-1]\n"
+ */
+static int process_cpu_topology(struct perf_file_section *section __used,
+ struct perf_header *ph, int feat __used,
+ int fd, void *data __used)
+{
+ ssize_t ret;
+ u32 nr, i;
+ char *str;
+ char buf[128];
+ char *topo = NULL;
+ size_t allocated = 0, used, len;
+
+ ret = read(fd, &nr, sizeof(nr));
+ if (ret != (ssize_t)sizeof(nr))
+ return -1;
+
+ if (ph->needs_swap)
+ nr = bswap_32(nr);
+
+ allocated = TOPO_STR_LEN;
+ topo = malloc(TOPO_STR_LEN);
+ if (!topo)
+ return -ENOMEM;
+
+ /* core siblings */
+ used = scnprintf(topo, allocated, "%u", nr);
+
+ for (i = 0; i < nr; i++) {
+ str = do_read_string(fd, ph);
+ if (!str)
+ goto error;
+
+ len = strlen(str) + 1;
+ check_topo_len(topo, allocated, used, len);
+
+ scnprintf(topo + used, allocated - used, "%c%s",
+ TOPO_STR_DELIM, str);
+ used += len;
+ free(str);
+ }
+ check_topo_len(topo, allocated, used, 1);
+ scnprintf(topo + used, allocated - used, "\n");
+ used++;
+
+ /* thread siblings */
+ ret = read(fd, &nr, sizeof(nr));
+ if (ret != (ssize_t)sizeof(nr))
+ goto error;
+
+ if (ph->needs_swap)
+ nr = bswap_32(nr);
+
+ len = scnprintf(buf, sizeof(buf), "%u", nr);
+ check_topo_len(topo, allocated, used, len);
+
+ strcat(topo, buf);
+ used += len;
+
+ for (i = 0; i < nr; i++) {
+ str = do_read_string(fd, ph);
+ if (!str)
+ goto error;
+
+ len = strlen(str) + 1;
+ check_topo_len(topo, allocated, used, len);
+
+ scnprintf(topo + used, allocated - used, "%c%s",
+ TOPO_STR_DELIM, str);
+ used += len;
+ free(str);
+ }
+ check_topo_len(topo, allocated, used, 1);
+ scnprintf(topo + used, allocated - used, "\n");
+
+ ph->cpu_topology = topo;
+ return 0;
+
+error:
+ free(topo);
+ return -1;
+}
+
+/*
+ * The topology string looks like below (':' is used for delimiter):
+ *
+ * "NR_NODES(N)\n
+ * "NODE_NUM(0):MEM_TOTAL:MEM_FREE:CPULIST\n"
+ * "NODE_NUM(1):MEM_TOTAL:MEM_FREE:CPULIST\n"
+ * ...
+ * "NODE_NUM(N-1):MEM_TOTAL:MEM_FREE:CPULIST\n"
+ */
+static int process_numa_topology(struct perf_file_section *section __used,
+ struct perf_header *ph, int feat __used,
+ int fd, void *data __used)
+{
+ ssize_t ret;
+ u32 nr, node, i;
+ char *str;
+ uint64_t mem_total, mem_free;
+ char *topo = NULL;
+ size_t allocated = 0, used, len;
+
+ /* nr nodes */
+ ret = read(fd, &nr, sizeof(nr));
+ if (ret != (ssize_t)sizeof(nr))
+ goto error;
+
+ if (ph->needs_swap)
+ nr = bswap_32(nr);
+
+ allocated = TOPO_STR_LEN;
+ topo = malloc(TOPO_STR_LEN);
+ if (!topo)
+ return -ENOMEM;
+
+ used = scnprintf(topo, allocated, "%u\n", nr);
+
+ for (i = 0; i < nr; i++) {
+ char buf[128];
+
+ /* node number */
+ ret = read(fd, &node, sizeof(node));
+ if (ret != (ssize_t)sizeof(node))
+ goto error;
+
+ if (ph->needs_swap)
+ node = bswap_32(node);
+
+ len = scnprintf(buf, sizeof(buf), "%u%c", node, TOPO_STR_DELIM);
+ check_topo_len(topo, allocated, used, len);
+
+ scnprintf(topo + used, allocated - used, "%s", buf);
+ used += len;
+
+ ret = read(fd, &mem_total, sizeof(u64));
+ if (ret != sizeof(u64))
+ goto error;
+
+ if (ph->needs_swap)
+ mem_total = bswap_64(mem_total);
+
+ len = scnprintf(buf, sizeof(buf), "%"PRIu64"%c",
+ mem_total, TOPO_STR_DELIM);
+ check_topo_len(topo, allocated, used, len);
+
+ scnprintf(topo + used, allocated - used, "%s", buf);
+ used += len;
+
+ ret = read(fd, &mem_free, sizeof(u64));
+ if (ret != sizeof(u64))
+ goto error;
+
+ if (ph->needs_swap)
+ mem_free = bswap_64(mem_free);
+
+ len = scnprintf(buf, sizeof(buf), "%"PRIu64"%c",
+ mem_total, TOPO_STR_DELIM);
+ check_topo_len(topo, allocated, used, len);
+
+ scnprintf(topo + used, allocated - used, "%s", buf);
+ used += len;
+
+ str = do_read_string(fd, ph);
+ if (!str)
+ goto error;
+
+ len = strlen(str) + 1;
+ check_topo_len(topo, allocated, used, len);
+
+ scnprintf(topo + used, allocated - used, "%s\n", str);
+ used += len;
+ free(str);
+ }
+
+ ph->numa_topology = topo;
+ return 0;
+error:
+ free(topo);
+ return -1;
+}
+
+static int process_cpuid(struct perf_file_section *section __used,
+ struct perf_header *ph, int feat __used, int fd,
+ void *data __used)
+{
+ ph->cpuid = do_read_string(fd, ph);
+ return ph->cpuid ? 0 : -ENOMEM;
+}
+
+static int process_total_mem(struct perf_file_section *section __used,
+ struct perf_header *ph, int feat __used, int fd,
+ void *data __used)
+{
+ uint64_t mem;
+ ssize_t ret;
+
+ ret = read(fd, &mem, sizeof(mem));
+ if (ret != sizeof(mem))
+ return -1;
+
+ if (ph->needs_swap)
+ mem = bswap_64(mem);
+
+ ph->total_mem = mem;
+ return 0;
+}
+
struct feature_ops {
int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
void (*print)(struct perf_header *h, int fd, FILE *fp);
@@ -1393,7 +1733,7 @@ struct feature_ops {
.process = process_##func }
#define FEAT_OPF(n, func) \
[n] = { .name = #n, .write = write_##func, .print = print_##func, \
- .full_only = true }
+ .process = process_##func, .full_only = true }
/* feature_ops not implemented: */
#define print_tracing_data NULL
@@ -1402,16 +1742,16 @@ struct feature_ops {
static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
FEAT_OPP(HEADER_TRACING_DATA, tracing_data),
FEAT_OPP(HEADER_BUILD_ID, build_id),
- FEAT_OPA(HEADER_HOSTNAME, hostname),
- FEAT_OPA(HEADER_OSRELEASE, osrelease),
- FEAT_OPA(HEADER_VERSION, version),
- FEAT_OPA(HEADER_ARCH, arch),
- FEAT_OPA(HEADER_NRCPUS, nrcpus),
- FEAT_OPA(HEADER_CPUDESC, cpudesc),
- FEAT_OPA(HEADER_CPUID, cpuid),
- FEAT_OPA(HEADER_TOTAL_MEM, total_mem),
+ FEAT_OPP(HEADER_HOSTNAME, hostname),
+ FEAT_OPP(HEADER_OSRELEASE, osrelease),
+ FEAT_OPP(HEADER_VERSION, version),
+ FEAT_OPP(HEADER_ARCH, arch),
+ FEAT_OPP(HEADER_NRCPUS, nrcpus),
+ FEAT_OPP(HEADER_CPUDESC, cpudesc),
+ FEAT_OPP(HEADER_CPUID, cpuid),
+ FEAT_OPP(HEADER_TOTAL_MEM, total_mem),
FEAT_OPA(HEADER_EVENT_DESC, event_desc),
- FEAT_OPA(HEADER_CMDLINE, cmdline),
+ FEAT_OPP(HEADER_CMDLINE, cmdline),
FEAT_OPF(HEADER_CPU_TOPOLOGY, cpu_topology),
FEAT_OPF(HEADER_NUMA_TOPOLOGY, numa_topology),
FEAT_OPA(HEADER_BRANCH_STACK, branch_stack),
--git a/tools/perf/util/header.h b/tools/perf/util/header.h
index 2d42b3e1826f..6e4f14eb3c95 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -66,6 +66,19 @@ struct perf_header {
u64 event_offset;
u64 event_size;
DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
+ char *hostname;
+ char *os_release;
+ char *version;
+ char *arch;
+ u32 nr_cpus_online;
+ u32 nr_cpus_avail;
+ char *cpu_desc;
+ char *cpuid;
+ u64 total_mem;
+ int cmdline_argc;
+ char *cmdline;
+ char *cpu_topology;
+ char *numa_topology;
};
struct perf_evlist;
--
1.7.9.2
next prev parent reply other threads:[~2012-07-21 16:46 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-07-21 16:45 [PATCH 1/5] perf header: Do not write event_desc feature Namhyung Kim
2012-07-21 16:45 ` Namhyung Kim [this message]
2012-07-21 16:45 ` [PATCH 3/5] perf header: Make feat_ops->print use processed result Namhyung Kim
2012-07-21 16:45 ` [PATCH 4/5] perf header: Remove unused @fd arg from ->print callback Namhyung Kim
2012-07-21 16:45 ` [PATCH 5/5] perf header: Remove unused @feat arg from ->process callback Namhyung Kim
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=1342889135-14825-2-git-send-email-namhyung@kernel.org \
--to=namhyung@kernel.org \
--cc=acme@ghostprotocols.net \
--cc=eranian@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
/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;
as well as URLs for NNTP newsgroup(s).