Skip to content

Commit

Permalink
perf header: Add ->process callbacks to most of features
Browse files Browse the repository at this point in the history
From now on each feature information is processed and saved in perf
header so that it can be used wherever needed.  The BRANCH_STACK feature
is an exception since it needs nothing to be done.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Robert Richter <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
  • Loading branch information
namhyung authored and acmel committed Sep 24, 2012
1 parent e93699b commit a1ae565
Showing 1 changed file with 308 additions and 11 deletions.
319 changes: 308 additions & 11 deletions tools/perf/util/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "cpumap.h"
#include "pmu.h"
#include "vdso.h"
#include "strbuf.h"

static bool no_buildid_cache = false;

Expand Down Expand Up @@ -1673,6 +1674,99 @@ static int process_build_id(struct perf_file_section *section,
return 0;
}

static int process_hostname(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
ph->env.hostname = do_read_string(fd, ph);
return ph->env.hostname ? 0 : -ENOMEM;
}

static int process_osrelease(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
ph->env.os_release = do_read_string(fd, ph);
return ph->env.os_release ? 0 : -ENOMEM;
}

static int process_version(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
ph->env.version = do_read_string(fd, ph);
return ph->env.version ? 0 : -ENOMEM;
}

static int process_arch(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
ph->env.arch = do_read_string(fd, ph);
return ph->env.arch ? 0 : -ENOMEM;
}

static int process_nrcpus(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
size_t ret;
u32 nr;

ret = read(fd, &nr, sizeof(nr));
if (ret != sizeof(nr))
return -1;

if (ph->needs_swap)
nr = bswap_32(nr);

ph->env.nr_cpus_online = nr;

ret = read(fd, &nr, sizeof(nr));
if (ret != sizeof(nr))
return -1;

if (ph->needs_swap)
nr = bswap_32(nr);

ph->env.nr_cpus_avail = nr;
return 0;
}

static int process_cpudesc(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
ph->env.cpu_desc = do_read_string(fd, ph);
return ph->env.cpu_desc ? 0 : -ENOMEM;
}

static int process_cpuid(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
ph->env.cpuid = do_read_string(fd, ph);
return ph->env.cpuid ? 0 : -ENOMEM;
}

static int process_total_mem(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
uint64_t mem;
size_t ret;

ret = read(fd, &mem, sizeof(mem));
if (ret != sizeof(mem))
return -1;

if (ph->needs_swap)
mem = bswap_64(mem);

ph->env.total_mem = mem;
return 0;
}

static char *read_cpuid(struct perf_header *ph, int fd)
{
return do_read_string(fd, ph);
Expand Down Expand Up @@ -1728,6 +1822,208 @@ process_event_desc(struct perf_file_section *section __maybe_unused,
return 0;
}

static int process_cmdline(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
size_t ret;
char *str;
u32 nr, i;
struct strbuf sb;

ret = read(fd, &nr, sizeof(nr));
if (ret != sizeof(nr))
return -1;

if (ph->needs_swap)
nr = bswap_32(nr);

ph->env.nr_cmdline = nr;
strbuf_init(&sb, 128);

for (i = 0; i < nr; i++) {
str = do_read_string(fd, ph);
if (!str)
goto error;

/* include a NULL character at the end */
strbuf_add(&sb, str, strlen(str) + 1);
free(str);
}
ph->env.cmdline = strbuf_detach(&sb, NULL);
return 0;

error:
strbuf_release(&sb);
return -1;
}

static int process_cpu_topology(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
size_t ret;
u32 nr, i;
char *str;
struct strbuf sb;

ret = read(fd, &nr, sizeof(nr));
if (ret != sizeof(nr))
return -1;

if (ph->needs_swap)
nr = bswap_32(nr);

ph->env.nr_sibling_cores = nr;
strbuf_init(&sb, 128);

for (i = 0; i < nr; i++) {
str = do_read_string(fd, ph);
if (!str)
goto error;

/* include a NULL character at the end */
strbuf_add(&sb, str, strlen(str) + 1);
free(str);
}
ph->env.sibling_cores = strbuf_detach(&sb, NULL);

ret = read(fd, &nr, sizeof(nr));
if (ret != sizeof(nr))
return -1;

if (ph->needs_swap)
nr = bswap_32(nr);

ph->env.nr_sibling_threads = nr;

for (i = 0; i < nr; i++) {
str = do_read_string(fd, ph);
if (!str)
goto error;

/* include a NULL character at the end */
strbuf_add(&sb, str, strlen(str) + 1);
free(str);
}
ph->env.sibling_threads = strbuf_detach(&sb, NULL);
return 0;

error:
strbuf_release(&sb);
return -1;
}

static int process_numa_topology(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
size_t ret;
u32 nr, node, i;
char *str;
uint64_t mem_total, mem_free;
struct strbuf sb;

/* nr nodes */
ret = read(fd, &nr, sizeof(nr));
if (ret != sizeof(nr))
goto error;

if (ph->needs_swap)
nr = bswap_32(nr);

ph->env.nr_numa_nodes = nr;
strbuf_init(&sb, 256);

for (i = 0; i < nr; i++) {
/* node number */
ret = read(fd, &node, sizeof(node));
if (ret != sizeof(node))
goto error;

ret = read(fd, &mem_total, sizeof(u64));
if (ret != sizeof(u64))
goto error;

ret = read(fd, &mem_free, sizeof(u64));
if (ret != sizeof(u64))
goto error;

if (ph->needs_swap) {
node = bswap_32(node);
mem_total = bswap_64(mem_total);
mem_free = bswap_64(mem_free);
}

strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":",
node, mem_total, mem_free);

str = do_read_string(fd, ph);
if (!str)
goto error;

/* include a NULL character at the end */
strbuf_add(&sb, str, strlen(str) + 1);
free(str);
}
ph->env.numa_nodes = strbuf_detach(&sb, NULL);
return 0;

error:
strbuf_release(&sb);
return -1;
}

static int process_pmu_mappings(struct perf_file_section *section __maybe_unused,
struct perf_header *ph, int feat __maybe_unused,
int fd, void *data __maybe_unused)
{
size_t ret;
char *name;
u32 pmu_num;
u32 type;
struct strbuf sb;

ret = read(fd, &pmu_num, sizeof(pmu_num));
if (ret != sizeof(pmu_num))
return -1;

if (ph->needs_swap)
pmu_num = bswap_32(pmu_num);

if (!pmu_num) {
pr_debug("pmu mappings not available\n");
return 0;
}

ph->env.nr_pmu_mappings = pmu_num;
strbuf_init(&sb, 128);

while (pmu_num) {
if (read(fd, &type, sizeof(type)) != sizeof(type))
goto error;
if (ph->needs_swap)
type = bswap_32(type);

name = do_read_string(fd, ph);
if (!name)
goto error;

strbuf_addf(&sb, "%u:%s", type, name);
/* include a NULL character at the end */
strbuf_add(&sb, "", 1);

free(name);
pmu_num--;
}
ph->env.pmu_mappings = strbuf_detach(&sb, NULL);
return 0;

error:
strbuf_release(&sb);
return -1;
}

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);
Expand All @@ -1745,10 +2041,11 @@ 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 }
#define FEAT_OPA_R(n, func) \
[n] = { .name = #n, .write = write_##func, .print = print_##func, \
.read = read_##func }
.read = read_##func, .process = process_##func, \
.full_only = true }

/* feature_ops not implemented: */
#define print_tracing_data NULL
Expand All @@ -1757,20 +2054,20 @@ 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_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_OPA_R(HEADER_CPUID, cpuid),
FEAT_OPA(HEADER_TOTAL_MEM, total_mem),
FEAT_OPP(HEADER_TOTAL_MEM, total_mem),
FEAT_OPP(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),
FEAT_OPA(HEADER_PMU_MAPPINGS, pmu_mappings),
FEAT_OPP(HEADER_PMU_MAPPINGS, pmu_mappings),
};

struct header_print_data {
Expand Down

0 comments on commit a1ae565

Please sign in to comment.