Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 323727
b: refs/heads/master
c: 50a9667
h: refs/heads/master
i:
  323725: 7cc1e0f
  323723: 0251451
  323719: 8b11c09
  323711: 2fe4743
v: v3
  • Loading branch information
Robert Richter authored and Arnaldo Carvalho de Melo committed Aug 22, 2012
1 parent 6fef706 commit a36d1ef
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7c2f7afd36cc111dd08eb8eb8ef74fb6564fd131
refs/heads/master: 50a9667c9383982d7ec4e6bbc707f67be0e163d2
78 changes: 78 additions & 0 deletions trunk/tools/perf/util/header.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "symbol.h"
#include "debug.h"
#include "cpumap.h"
#include "pmu.h"

static bool no_buildid_cache = false;

Expand Down Expand Up @@ -1003,6 +1004,45 @@ static int write_numa_topology(int fd, struct perf_header *h __used,
return ret;
}

/*
* File format:
*
* struct pmu_mappings {
* u32 pmu_num;
* struct pmu_map {
* u32 type;
* char name[];
* }[pmu_num];
* };
*/

static int write_pmu_mappings(int fd, struct perf_header *h __used,
struct perf_evlist *evlist __used)
{
struct perf_pmu *pmu = NULL;
off_t offset = lseek(fd, 0, SEEK_CUR);
__u32 pmu_num = 0;

/* write real pmu_num later */
do_write(fd, &pmu_num, sizeof(pmu_num));

while ((pmu = perf_pmu__scan(pmu))) {
if (!pmu->name)
continue;
pmu_num++;
do_write(fd, &pmu->type, sizeof(pmu->type));
do_write_string(fd, pmu->name);
}

if (pwrite(fd, &pmu_num, sizeof(pmu_num), offset) != sizeof(pmu_num)) {
/* discard all */
lseek(fd, offset, SEEK_SET);
return -1;
}

return 0;
}

/*
* default get_cpuid(): nothing gets recorded
* actual implementation must be in arch/$(ARCH)/util/header.c
Expand Down Expand Up @@ -1389,6 +1429,43 @@ static void print_branch_stack(struct perf_header *ph __used, int fd __used,
fprintf(fp, "# contains samples with branch stack\n");
}

static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp)
{
const char *delimiter = "# pmu mappings: ";
char *name;
int ret;
u32 pmu_num;
u32 type;

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

if (!pmu_num) {
fprintf(fp, "# pmu mappings: not available\n");
return;
}

while (pmu_num) {
if (read(fd, &type, sizeof(type)) != sizeof(type))
break;
name = do_read_string(fd, ph);
if (!name)
break;
pmu_num--;
fprintf(fp, "%s%s = %" PRIu32, delimiter, name, type);
free(name);
delimiter = ", ";
}

fprintf(fp, "\n");

if (!pmu_num)
return;
error:
fprintf(fp, "# pmu mappings: unable to read\n");
}

static int __event_process_build_id(struct build_id_event *bev,
char *filename,
struct perf_session *session)
Expand Down Expand Up @@ -1644,6 +1721,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = {
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),
};

struct header_print_data {
Expand Down
1 change: 1 addition & 0 deletions trunk/tools/perf/util/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ enum {
HEADER_CPU_TOPOLOGY,
HEADER_NUMA_TOPOLOGY,
HEADER_BRANCH_STACK,
HEADER_PMU_MAPPINGS,
HEADER_LAST_FEATURE,
HEADER_FEAT_BITS = 256,
};
Expand Down
50 changes: 48 additions & 2 deletions trunk/tools/perf/util/pmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "pmu.h"
#include "parse-events.h"

#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"

int perf_pmu_parse(struct list_head *list, char *name);
extern FILE *perf_pmu_in;

Expand Down Expand Up @@ -69,7 +71,7 @@ static int pmu_format(char *name, struct list_head *format)
return -1;

snprintf(path, PATH_MAX,
"%s/bus/event_source/devices/%s/format", sysfs, name);
"%s" EVENT_SOURCE_DEVICE_PATH "%s/format", sysfs, name);

if (stat(path, &st) < 0)
return 0; /* no error if format does not exist */
Expand Down Expand Up @@ -206,7 +208,7 @@ static int pmu_type(char *name, __u32 *type)
return -1;

snprintf(path, PATH_MAX,
"%s/bus/event_source/devices/%s/type", sysfs, name);
"%s" EVENT_SOURCE_DEVICE_PATH "%s/type", sysfs, name);

if (stat(path, &st) < 0)
return -1;
Expand All @@ -222,6 +224,35 @@ static int pmu_type(char *name, __u32 *type)
return ret;
}

/* Add all pmus in sysfs to pmu list: */
static void pmu_read_sysfs(void)
{
char path[PATH_MAX];
const char *sysfs;
DIR *dir;
struct dirent *dent;

sysfs = sysfs_find_mountpoint();
if (!sysfs)
return;

snprintf(path, PATH_MAX,
"%s" EVENT_SOURCE_DEVICE_PATH, sysfs);

dir = opendir(path);
if (!dir)
return;

while ((dent = readdir(dir))) {
if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
continue;
/* add to static LIST_HEAD(pmus): */
perf_pmu__find(dent->d_name);
}

closedir(dir);
}

static struct perf_pmu *pmu_lookup(char *name)
{
struct perf_pmu *pmu;
Expand Down Expand Up @@ -267,6 +298,21 @@ static struct perf_pmu *pmu_find(char *name)
return NULL;
}

struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu)
{
/*
* pmu iterator: If pmu is NULL, we start at the begin,
* otherwise return the next pmu. Returns NULL on end.
*/
if (!pmu) {
pmu_read_sysfs();
pmu = list_prepare_entry(pmu, &pmus, list);
}
list_for_each_entry_continue(pmu, &pmus, list)
return pmu;
return NULL;
}

struct perf_pmu *perf_pmu__find(char *name)
{
struct perf_pmu *pmu;
Expand Down
2 changes: 2 additions & 0 deletions trunk/tools/perf/util/pmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,7 @@ int perf_pmu__new_format(struct list_head *list, char *name,
int config, unsigned long *bits);
void perf_pmu__set_format(unsigned long *bits, long from, long to);

struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);

int perf_pmu__test(void);
#endif /* __PMU_H */

0 comments on commit a36d1ef

Please sign in to comment.