|
@@ -51,6 +51,9 @@ static struct pollfd event_array[MAX_NR_CPUS * MAX_COUNTERS];
|
|
static int nr_poll;
|
|
static int nr_poll;
|
|
static int nr_cpu;
|
|
static int nr_cpu;
|
|
|
|
|
|
|
|
+static int file_new = 1;
|
|
|
|
+static struct perf_file_header file_header;
|
|
|
|
+
|
|
struct mmap_event {
|
|
struct mmap_event {
|
|
struct perf_event_header header;
|
|
struct perf_event_header header;
|
|
__u32 pid;
|
|
__u32 pid;
|
|
@@ -100,6 +103,21 @@ static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
|
|
pc->data_tail = 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)
|
|
static void mmap_read(struct mmap_data *md)
|
|
{
|
|
{
|
|
unsigned int head = mmap_read_head(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);
|
|
size = md->mask + 1 - (old & md->mask);
|
|
old += size;
|
|
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];
|
|
buf = &data[old & md->mask];
|
|
size = head - old;
|
|
size = head - old;
|
|
old += size;
|
|
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;
|
|
md->prev = old;
|
|
mmap_write_tail(md, 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;
|
|
struct comm_event comm_ev;
|
|
char filename[PATH_MAX];
|
|
char filename[PATH_MAX];
|
|
char bf[BUFSIZ];
|
|
char bf[BUFSIZ];
|
|
- int fd, ret;
|
|
|
|
|
|
+ int fd;
|
|
size_t size;
|
|
size_t size;
|
|
char *field, *sep;
|
|
char *field, *sep;
|
|
DIR *tasks;
|
|
DIR *tasks;
|
|
@@ -246,11 +244,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
|
|
if (!full) {
|
|
if (!full) {
|
|
comm_ev.tid = pid;
|
|
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;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -265,11 +259,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
|
|
|
|
|
|
comm_ev.tid = pid;
|
|
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);
|
|
closedir(tasks);
|
|
return;
|
|
return;
|
|
@@ -332,10 +322,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
|
|
mmap_ev.pid = pid;
|
|
mmap_ev.pid = pid;
|
|
mmap_ev.tid = 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)
|
|
if (call_graph)
|
|
attr->sample_type |= PERF_SAMPLE_CALLCHAIN;
|
|
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->mmap = track;
|
|
attr->comm = track;
|
|
attr->comm = track;
|
|
attr->inherit = (cpu < 0) && inherit;
|
|
attr->inherit = (cpu < 0) && inherit;
|
|
@@ -461,6 +457,13 @@ static void open_counters(int cpu, pid_t pid)
|
|
nr_cpu++;
|
|
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)
|
|
static int __cmd_record(int argc, const char **argv)
|
|
{
|
|
{
|
|
int i, counter;
|
|
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 <= MAX_NR_CPUS);
|
|
assert(nr_cpus >= 0);
|
|
assert(nr_cpus >= 0);
|
|
|
|
|
|
|
|
+ atexit(sig_atexit);
|
|
|
|
+ signal(SIGCHLD, sig_handler);
|
|
|
|
+ signal(SIGINT, sig_handler);
|
|
|
|
+
|
|
if (!stat(output_name, &st) && !force && !append_file) {
|
|
if (!stat(output_name, &st) && !force && !append_file) {
|
|
fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
|
|
fprintf(stderr, "Error, output file %s exists, use -A to append or -f to overwrite.\n",
|
|
output_name);
|
|
output_name);
|
|
@@ -482,7 +489,7 @@ static int __cmd_record(int argc, const char **argv)
|
|
|
|
|
|
flags = O_CREAT|O_RDWR;
|
|
flags = O_CREAT|O_RDWR;
|
|
if (append_file)
|
|
if (append_file)
|
|
- flags |= O_APPEND;
|
|
|
|
|
|
+ file_new = 0;
|
|
else
|
|
else
|
|
flags |= O_TRUNC;
|
|
flags |= O_TRUNC;
|
|
|
|
|
|
@@ -492,15 +499,18 @@ static int __cmd_record(int argc, const char **argv)
|
|
exit(-1);
|
|
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) {
|
|
if (!system_wide) {
|
|
open_counters(-1, target_pid != -1 ? target_pid : getpid());
|
|
open_counters(-1, target_pid != -1 ? target_pid : getpid());
|
|
} else for (i = 0; i < nr_cpus; i++)
|
|
} else for (i = 0; i < nr_cpus; i++)
|
|
open_counters(i, target_pid);
|
|
open_counters(i, target_pid);
|
|
|
|
|
|
- atexit(sig_atexit);
|
|
|
|
- signal(SIGCHLD, sig_handler);
|
|
|
|
- signal(SIGINT, sig_handler);
|
|
|
|
-
|
|
|
|
if (target_pid == -1 && argc) {
|
|
if (target_pid == -1 && argc) {
|
|
pid = fork();
|
|
pid = fork();
|
|
if (pid < 0)
|
|
if (pid < 0)
|