perf_counter tools: Add a data file header
authorPeter Zijlstra <a.p.zijlstra@chello.nl>
Thu, 18 Jun 2009 21:22:55 +0000 (23:22 +0200)
committerIngo Molnar <mingo@elte.hu>
Fri, 19 Jun 2009 11:42:36 +0000 (13:42 +0200)
Add a data file header so we can transfer data between record and report.

LKML-Reference: <new-submission>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/perf.h

index 06fdfb8b482805f2dc4e056c1075fd39b901e08f..28304677c73e7166b7168104177fd1c3ca7dd6d1 100644 (file)
@@ -51,6 +51,9 @@ static struct pollfd          event_array[MAX_NR_CPUS * MAX_COUNTERS];
 static int                     nr_poll;
 static int                     nr_cpu;
 
+static int                     file_new = 1;
+static struct perf_file_header file_header;
+
 struct mmap_event {
        struct perf_event_header        header;
        __u32                           pid;
@@ -100,6 +103,21 @@ static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
        pc->data_tail = tail;
 }
 
+static void write_output(void *buf, size_t size)
+{
+       while (size) {
+               int ret = write(output, buf, size);
+
+               if (ret < 0)
+                       die("failed to write");
+
+               size -= ret;
+               buf += ret;
+
+               bytes_written += ret;
+       }
+}
+
 static void mmap_read(struct mmap_data *md)
 {
        unsigned int head = mmap_read_head(md);
@@ -148,34 +166,14 @@ static void mmap_read(struct mmap_data *md)
                size = md->mask + 1 - (old & md->mask);
                old += size;
 
-               while (size) {
-                       int ret = write(output, buf, size);
-
-                       if (ret < 0)
-                               die("failed to write");
-
-                       size -= ret;
-                       buf += ret;
-
-                       bytes_written += ret;
-               }
+               write_output(buf, size);
        }
 
        buf = &data[old & md->mask];
        size = head - old;
        old += size;
 
-       while (size) {
-               int ret = write(output, buf, size);
-
-               if (ret < 0)
-                       die("failed to write");
-
-               size -= ret;
-               buf += ret;
-
-               bytes_written += ret;
-       }
+       write_output(buf, size);
 
        md->prev = old;
        mmap_write_tail(md, old);
@@ -204,7 +202,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
        struct comm_event comm_ev;
        char filename[PATH_MAX];
        char bf[BUFSIZ];
-       int fd, ret;
+       int fd;
        size_t size;
        char *field, *sep;
        DIR *tasks;
@@ -246,11 +244,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
        if (!full) {
                comm_ev.tid = pid;
 
-               ret = write(output, &comm_ev, comm_ev.header.size);
-               if (ret < 0) {
-                       perror("failed to write");
-                       exit(-1);
-               }
+               write_output(&comm_ev, comm_ev.header.size);
                return;
        }
 
@@ -265,11 +259,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
 
                comm_ev.tid = pid;
 
-               ret = write(output, &comm_ev, comm_ev.header.size);
-               if (ret < 0) {
-                       perror("failed to write");
-                       exit(-1);
-               }
+               write_output(&comm_ev, comm_ev.header.size);
        }
        closedir(tasks);
        return;
@@ -332,10 +322,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
                        mmap_ev.pid = pid;
                        mmap_ev.tid = pid;
 
-                       if (write(output, &mmap_ev, mmap_ev.header.size) < 0) {
-                               perror("failed to write");
-                               exit(-1);
-                       }
+                       write_output(&mmap_ev, mmap_ev.header.size);
                }
        }
 
@@ -382,6 +369,15 @@ 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;
@@ -461,6 +457,13 @@ static void open_counters(int cpu, pid_t pid)
        nr_cpu++;
 }
 
+static void atexit_header(void)
+{
+       file_header.data_size += bytes_written;
+
+       pwrite(output, &file_header, sizeof(file_header), 0);
+}
+
 static int __cmd_record(int argc, const char **argv)
 {
        int i, counter;
@@ -474,6 +477,10 @@ static int __cmd_record(int argc, const char **argv)
        assert(nr_cpus <= MAX_NR_CPUS);
        assert(nr_cpus >= 0);
 
+       atexit(sig_atexit);
+       signal(SIGCHLD, sig_handler);
+       signal(SIGINT, sig_handler);
+
        if (!stat(output_name, &st) && !force && !append_file) {
                fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
                                output_name);
@@ -482,7 +489,7 @@ static int __cmd_record(int argc, const char **argv)
 
        flags = O_CREAT|O_RDWR;
        if (append_file)
-               flags |= O_APPEND;
+               file_new = 0;
        else
                flags |= O_TRUNC;
 
@@ -492,15 +499,18 @@ static int __cmd_record(int argc, const char **argv)
                exit(-1);
        }
 
+       if (!file_new) {
+               read(output, &file_header, sizeof(file_header));
+               lseek(output, file_header.data_size, SEEK_CUR);
+       }
+
+       atexit(atexit_header);
+
        if (!system_wide) {
                open_counters(-1, target_pid != -1 ? target_pid : getpid());
        } else for (i = 0; i < nr_cpus; i++)
                open_counters(i, target_pid);
 
-       atexit(sig_atexit);
-       signal(SIGCHLD, sig_handler);
-       signal(SIGINT, sig_handler);
-
        if (target_pid == -1 && argc) {
                pid = fork();
                if (pid < 0)
index 7a6577bf9a41dcb811ea45cbb1b24cb48132279a..37b26ecb0d0b1aa931e61405361a303dcda80b94 100644 (file)
@@ -1366,11 +1366,13 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
        return 0;
 }
 
+static struct perf_file_header         file_header;
+
 static int __cmd_report(void)
 {
        int ret, rc = EXIT_FAILURE;
        unsigned long offset = 0;
-       unsigned long head = 0;
+       unsigned long head = sizeof(file_header);
        struct stat stat;
        event_t *event;
        uint32_t size;
@@ -1398,6 +1400,14 @@ static int __cmd_report(void)
                exit(0);
        }
 
+       read(input, &file_header, sizeof(file_header));
+
+       if (sort__has_parent &&
+           !(file_header.sample_type & PERF_SAMPLE_CALLCHAIN)) {
+               fprintf(stderr, "selected --sort parent, but no callchain data\n");
+               exit(-1);
+       }
+
        if (load_kernel() < 0) {
                perror("failed to load kernel symbols");
                return EXIT_FAILURE;
@@ -1469,9 +1479,13 @@ more:
 
        head += size;
 
+       if (offset + head >= sizeof(file_header) + file_header.data_size)
+               goto done;
+
        if (offset + head < stat.st_size)
                goto more;
 
+done:
        rc = EXIT_SUCCESS;
        close(input);
 
index 87a1aca4a4246e0dad3ea82276ccd5487cddacf0..55c62f4b990b9f0e10a7d435aba5058c718dc1c1 100644 (file)
@@ -65,4 +65,10 @@ sys_perf_counter_open(struct perf_counter_attr *attr,
 #define MAX_COUNTERS                   256
 #define MAX_NR_CPUS                    256
 
+struct perf_file_header {
+       __u64   version;
+       __u64   sample_type;
+       __u64   data_size;
+};
+
 #endif