perf_counter tools: Rework the file format

Create a structured file format that includes the full
perf_counter_attr and all its relevant counter IDs so that
the reporting program has full information.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Peter Zijlstra
2009-06-25 17:05:54 +02:00
committed by Ingo Molnar
parent e5c5954779
commit 7c6a1c65bb
9 changed files with 377 additions and 54 deletions

View File

@@ -14,6 +14,8 @@
#include "util/parse-events.h"
#include "util/string.h"
#include "util/header.h"
#include <unistd.h>
#include <sched.h>
@@ -52,7 +54,8 @@ static int nr_poll;
static int nr_cpu;
static int file_new = 1;
static struct perf_file_header file_header;
struct perf_header *header;
struct mmap_event {
struct perf_event_header header;
@@ -328,7 +331,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
fclose(fp);
}
static void synthesize_samples(void)
static void synthesize_all(void)
{
DIR *proc;
struct dirent dirent, *next;
@@ -352,10 +355,35 @@ static void synthesize_samples(void)
static int group_fd;
static struct perf_header_attr *get_header_attr(struct perf_counter_attr *a, int nr)
{
struct perf_header_attr *h_attr;
if (nr < header->attrs) {
h_attr = header->attr[nr];
} else {
h_attr = perf_header_attr__new(a);
perf_header__add_attr(header, h_attr);
}
return h_attr;
}
static void create_counter(int counter, int cpu, pid_t pid)
{
struct perf_counter_attr *attr = attrs + counter;
int track = 1;
struct perf_header_attr *h_attr;
int track = !counter; /* only the first counter needs these */
struct {
u64 count;
u64 time_enabled;
u64 time_running;
u64 id;
} read_data;
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING |
PERF_FORMAT_ID;
attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
@@ -368,22 +396,11 @@ static void create_counter(int counter, int cpu, pid_t pid)
if (call_graph)
attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
if (file_new) {
file_header.sample_type = attr->sample_type;
} else {
if (file_header.sample_type != attr->sample_type) {
fprintf(stderr, "incompatible append\n");
exit(-1);
}
}
attr->mmap = track;
attr->comm = track;
attr->inherit = (cpu < 0) && inherit;
attr->disabled = 1;
track = 0; /* only the first counter needs these */
try_again:
fd[nr_cpu][counter] = sys_perf_counter_open(attr, pid, cpu, group_fd, 0);
@@ -414,6 +431,19 @@ try_again:
exit(-1);
}
h_attr = get_header_attr(attr, counter);
if (!file_new) {
if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
fprintf(stderr, "incompatible append\n");
exit(-1);
}
}
read(fd[nr_cpu][counter], &read_data, sizeof(read_data));
perf_header_attr__add_id(h_attr, read_data.id);
assert(fd[nr_cpu][counter] >= 0);
fcntl(fd[nr_cpu][counter], F_SETFL, O_NONBLOCK);
@@ -444,11 +474,6 @@ static void open_counters(int cpu, pid_t pid)
{
int counter;
if (pid > 0) {
pid_synthesize_comm_event(pid, 0);
pid_synthesize_mmap_samples(pid);
}
group_fd = -1;
for (counter = 0; counter < nr_counters; counter++)
create_counter(counter, cpu, pid);
@@ -458,17 +483,16 @@ static void open_counters(int cpu, pid_t pid)
static void atexit_header(void)
{
file_header.data_size += bytes_written;
header->data_size += bytes_written;
if (pwrite(output, &file_header, sizeof(file_header), 0) == -1)
perror("failed to write on file headers");
perf_header__write(header, output);
}
static int __cmd_record(int argc, const char **argv)
{
int i, counter;
struct stat st;
pid_t pid;
pid_t pid = 0;
int flags;
int ret;
@@ -499,22 +523,31 @@ static int __cmd_record(int argc, const char **argv)
exit(-1);
}
if (!file_new) {
if (read(output, &file_header, sizeof(file_header)) == -1) {
perror("failed to read file headers");
exit(-1);
}
lseek(output, file_header.data_size, SEEK_CUR);
}
if (!file_new)
header = perf_header__read(output);
else
header = perf_header__new();
atexit(atexit_header);
if (!system_wide) {
open_counters(-1, target_pid != -1 ? target_pid : getpid());
pid = target_pid;
if (pid == -1)
pid = getpid();
open_counters(-1, pid);
} else for (i = 0; i < nr_cpus; i++)
open_counters(i, target_pid);
if (file_new)
perf_header__write(header, output);
if (!system_wide) {
pid_synthesize_comm_event(pid, 0);
pid_synthesize_mmap_samples(pid);
} else
synthesize_all();
if (target_pid == -1 && argc) {
pid = fork();
if (pid < 0)
@@ -538,9 +571,6 @@ static int __cmd_record(int argc, const char **argv)
}
}
if (system_wide)
synthesize_samples();
while (!done) {
int hits = samples;