~ubuntu-branches/ubuntu/saucy/linux-n900/saucy

« back to all changes in this revision

Viewing changes to tools/perf/builtin-record.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Poirier
  • Date: 2011-02-18 09:43:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110218094331-eyubsja4f9k0yhmq
Tags: 2.6.35-1.1
Initial release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * builtin-record.c
 
3
 *
 
4
 * Builtin record command: Record the profile of a workload
 
5
 * (or a CPU, or a PID) into the perf.data output file - for
 
6
 * later analysis via perf report.
 
7
 */
 
8
#define _FILE_OFFSET_BITS 64
 
9
 
 
10
#include "builtin.h"
 
11
 
 
12
#include "perf.h"
 
13
 
 
14
#include "util/build-id.h"
 
15
#include "util/util.h"
 
16
#include "util/parse-options.h"
 
17
#include "util/parse-events.h"
 
18
 
 
19
#include "util/header.h"
 
20
#include "util/event.h"
 
21
#include "util/debug.h"
 
22
#include "util/session.h"
 
23
#include "util/symbol.h"
 
24
#include "util/cpumap.h"
 
25
 
 
26
#include <unistd.h>
 
27
#include <sched.h>
 
28
#include <sys/mman.h>
 
29
 
 
30
enum write_mode_t {
 
31
        WRITE_FORCE,
 
32
        WRITE_APPEND
 
33
};
 
34
 
 
35
static int                      *fd[MAX_NR_CPUS][MAX_COUNTERS];
 
36
 
 
37
static u64                      user_interval                   = ULLONG_MAX;
 
38
static u64                      default_interval                =      0;
 
39
 
 
40
static int                      nr_cpus                         =      0;
 
41
static unsigned int             page_size;
 
42
static unsigned int             mmap_pages                      =    128;
 
43
static unsigned int             user_freq                       = UINT_MAX;
 
44
static int                      freq                            =   1000;
 
45
static int                      output;
 
46
static int                      pipe_output                     =      0;
 
47
static const char               *output_name                    = "perf.data";
 
48
static int                      group                           =      0;
 
49
static int                      realtime_prio                   =      0;
 
50
static bool                     raw_samples                     =  false;
 
51
static bool                     system_wide                     =  false;
 
52
static int                      profile_cpu                     =     -1;
 
53
static pid_t                    target_pid                      =     -1;
 
54
static pid_t                    target_tid                      =     -1;
 
55
static pid_t                    *all_tids                       =      NULL;
 
56
static int                      thread_num                      =      0;
 
57
static pid_t                    child_pid                       =     -1;
 
58
static bool                     no_inherit                      =  false;
 
59
static enum write_mode_t        write_mode                      = WRITE_FORCE;
 
60
static bool                     call_graph                      =  false;
 
61
static bool                     inherit_stat                    =  false;
 
62
static bool                     no_samples                      =  false;
 
63
static bool                     sample_address                  =  false;
 
64
 
 
65
static long                     samples                         =      0;
 
66
static u64                      bytes_written                   =      0;
 
67
 
 
68
static struct pollfd            *event_array;
 
69
 
 
70
static int                      nr_poll                         =      0;
 
71
static int                      nr_cpu                          =      0;
 
72
 
 
73
static int                      file_new                        =      1;
 
74
static off_t                    post_processing_offset;
 
75
 
 
76
static struct perf_session      *session;
 
77
 
 
78
struct mmap_data {
 
79
        int                     counter;
 
80
        void                    *base;
 
81
        unsigned int            mask;
 
82
        unsigned int            prev;
 
83
};
 
84
 
 
85
static struct mmap_data         mmap_array[MAX_NR_CPUS];
 
86
 
 
87
static unsigned long mmap_read_head(struct mmap_data *md)
 
88
{
 
89
        struct perf_event_mmap_page *pc = md->base;
 
90
        long head;
 
91
 
 
92
        head = pc->data_head;
 
93
        rmb();
 
94
 
 
95
        return head;
 
96
}
 
97
 
 
98
static void mmap_write_tail(struct mmap_data *md, unsigned long tail)
 
99
{
 
100
        struct perf_event_mmap_page *pc = md->base;
 
101
 
 
102
        /*
 
103
         * ensure all reads are done before we write the tail out.
 
104
         */
 
105
        /* mb(); */
 
106
        pc->data_tail = tail;
 
107
}
 
108
 
 
109
static void advance_output(size_t size)
 
110
{
 
111
        bytes_written += size;
 
112
}
 
113
 
 
114
static void write_output(void *buf, size_t size)
 
115
{
 
116
        while (size) {
 
117
                int ret = write(output, buf, size);
 
118
 
 
119
                if (ret < 0)
 
120
                        die("failed to write");
 
121
 
 
122
                size -= ret;
 
123
                buf += ret;
 
124
 
 
125
                bytes_written += ret;
 
126
        }
 
127
}
 
128
 
 
129
static int process_synthesized_event(event_t *event,
 
130
                                     struct perf_session *self __used)
 
131
{
 
132
        write_output(event, event->header.size);
 
133
        return 0;
 
134
}
 
135
 
 
136
static void mmap_read(struct mmap_data *md)
 
137
{
 
138
        unsigned int head = mmap_read_head(md);
 
139
        unsigned int old = md->prev;
 
140
        unsigned char *data = md->base + page_size;
 
141
        unsigned long size;
 
142
        void *buf;
 
143
        int diff;
 
144
 
 
145
        /*
 
146
         * If we're further behind than half the buffer, there's a chance
 
147
         * the writer will bite our tail and mess up the samples under us.
 
148
         *
 
149
         * If we somehow ended up ahead of the head, we got messed up.
 
150
         *
 
151
         * In either case, truncate and restart at head.
 
152
         */
 
153
        diff = head - old;
 
154
        if (diff < 0) {
 
155
                fprintf(stderr, "WARNING: failed to keep up with mmap data\n");
 
156
                /*
 
157
                 * head points to a known good entry, start there.
 
158
                 */
 
159
                old = head;
 
160
        }
 
161
 
 
162
        if (old != head)
 
163
                samples++;
 
164
 
 
165
        size = head - old;
 
166
 
 
167
        if ((old & md->mask) + size != (head & md->mask)) {
 
168
                buf = &data[old & md->mask];
 
169
                size = md->mask + 1 - (old & md->mask);
 
170
                old += size;
 
171
 
 
172
                write_output(buf, size);
 
173
        }
 
174
 
 
175
        buf = &data[old & md->mask];
 
176
        size = head - old;
 
177
        old += size;
 
178
 
 
179
        write_output(buf, size);
 
180
 
 
181
        md->prev = old;
 
182
        mmap_write_tail(md, old);
 
183
}
 
184
 
 
185
static volatile int done = 0;
 
186
static volatile int signr = -1;
 
187
 
 
188
static void sig_handler(int sig)
 
189
{
 
190
        done = 1;
 
191
        signr = sig;
 
192
}
 
193
 
 
194
static void sig_atexit(void)
 
195
{
 
196
        if (child_pid > 0)
 
197
                kill(child_pid, SIGTERM);
 
198
 
 
199
        if (signr == -1)
 
200
                return;
 
201
 
 
202
        signal(signr, SIG_DFL);
 
203
        kill(getpid(), signr);
 
204
}
 
205
 
 
206
static int group_fd;
 
207
 
 
208
static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int nr)
 
209
{
 
210
        struct perf_header_attr *h_attr;
 
211
 
 
212
        if (nr < session->header.attrs) {
 
213
                h_attr = session->header.attr[nr];
 
214
        } else {
 
215
                h_attr = perf_header_attr__new(a);
 
216
                if (h_attr != NULL)
 
217
                        if (perf_header__add_attr(&session->header, h_attr) < 0) {
 
218
                                perf_header_attr__delete(h_attr);
 
219
                                h_attr = NULL;
 
220
                        }
 
221
        }
 
222
 
 
223
        return h_attr;
 
224
}
 
225
 
 
226
static void create_counter(int counter, int cpu)
 
227
{
 
228
        char *filter = filters[counter];
 
229
        struct perf_event_attr *attr = attrs + counter;
 
230
        struct perf_header_attr *h_attr;
 
231
        int track = !counter; /* only the first counter needs these */
 
232
        int thread_index;
 
233
        int ret;
 
234
        struct {
 
235
                u64 count;
 
236
                u64 time_enabled;
 
237
                u64 time_running;
 
238
                u64 id;
 
239
        } read_data;
 
240
 
 
241
        attr->read_format       = PERF_FORMAT_TOTAL_TIME_ENABLED |
 
242
                                  PERF_FORMAT_TOTAL_TIME_RUNNING |
 
243
                                  PERF_FORMAT_ID;
 
244
 
 
245
        attr->sample_type       |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
 
246
 
 
247
        if (nr_counters > 1)
 
248
                attr->sample_type |= PERF_SAMPLE_ID;
 
249
 
 
250
        /*
 
251
         * We default some events to a 1 default interval. But keep
 
252
         * it a weak assumption overridable by the user.
 
253
         */
 
254
        if (!attr->sample_period || (user_freq != UINT_MAX &&
 
255
                                     user_interval != ULLONG_MAX)) {
 
256
                if (freq) {
 
257
                        attr->sample_type       |= PERF_SAMPLE_PERIOD;
 
258
                        attr->freq              = 1;
 
259
                        attr->sample_freq       = freq;
 
260
                } else {
 
261
                        attr->sample_period = default_interval;
 
262
                }
 
263
        }
 
264
 
 
265
        if (no_samples)
 
266
                attr->sample_freq = 0;
 
267
 
 
268
        if (inherit_stat)
 
269
                attr->inherit_stat = 1;
 
270
 
 
271
        if (sample_address)
 
272
                attr->sample_type       |= PERF_SAMPLE_ADDR;
 
273
 
 
274
        if (call_graph)
 
275
                attr->sample_type       |= PERF_SAMPLE_CALLCHAIN;
 
276
 
 
277
        if (raw_samples) {
 
278
                attr->sample_type       |= PERF_SAMPLE_TIME;
 
279
                attr->sample_type       |= PERF_SAMPLE_RAW;
 
280
                attr->sample_type       |= PERF_SAMPLE_CPU;
 
281
        }
 
282
 
 
283
        attr->mmap              = track;
 
284
        attr->comm              = track;
 
285
        attr->inherit           = !no_inherit;
 
286
        if (target_pid == -1 && target_tid == -1 && !system_wide) {
 
287
                attr->disabled = 1;
 
288
                attr->enable_on_exec = 1;
 
289
        }
 
290
 
 
291
        for (thread_index = 0; thread_index < thread_num; thread_index++) {
 
292
try_again:
 
293
                fd[nr_cpu][counter][thread_index] = sys_perf_event_open(attr,
 
294
                                all_tids[thread_index], cpu, group_fd, 0);
 
295
 
 
296
                if (fd[nr_cpu][counter][thread_index] < 0) {
 
297
                        int err = errno;
 
298
 
 
299
                        if (err == EPERM || err == EACCES)
 
300
                                die("Permission error - are you root?\n"
 
301
                                        "\t Consider tweaking"
 
302
                                        " /proc/sys/kernel/perf_event_paranoid.\n");
 
303
                        else if (err ==  ENODEV && profile_cpu != -1) {
 
304
                                die("No such device - did you specify"
 
305
                                        " an out-of-range profile CPU?\n");
 
306
                        }
 
307
 
 
308
                        /*
 
309
                         * If it's cycles then fall back to hrtimer
 
310
                         * based cpu-clock-tick sw counter, which
 
311
                         * is always available even if no PMU support:
 
312
                         */
 
313
                        if (attr->type == PERF_TYPE_HARDWARE
 
314
                                        && attr->config == PERF_COUNT_HW_CPU_CYCLES) {
 
315
 
 
316
                                if (verbose)
 
317
                                        warning(" ... trying to fall back to cpu-clock-ticks\n");
 
318
                                attr->type = PERF_TYPE_SOFTWARE;
 
319
                                attr->config = PERF_COUNT_SW_CPU_CLOCK;
 
320
                                goto try_again;
 
321
                        }
 
322
                        printf("\n");
 
323
                        error("perfcounter syscall returned with %d (%s)\n",
 
324
                                        fd[nr_cpu][counter][thread_index], strerror(err));
 
325
 
 
326
#if defined(__i386__) || defined(__x86_64__)
 
327
                        if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP)
 
328
                                die("No hardware sampling interrupt available."
 
329
                                    " No APIC? If so then you can boot the kernel"
 
330
                                    " with the \"lapic\" boot parameter to"
 
331
                                    " force-enable it.\n");
 
332
#endif
 
333
 
 
334
                        die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
 
335
                        exit(-1);
 
336
                }
 
337
 
 
338
                h_attr = get_header_attr(attr, counter);
 
339
                if (h_attr == NULL)
 
340
                        die("nomem\n");
 
341
 
 
342
                if (!file_new) {
 
343
                        if (memcmp(&h_attr->attr, attr, sizeof(*attr))) {
 
344
                                fprintf(stderr, "incompatible append\n");
 
345
                                exit(-1);
 
346
                        }
 
347
                }
 
348
 
 
349
                if (read(fd[nr_cpu][counter][thread_index], &read_data, sizeof(read_data)) == -1) {
 
350
                        perror("Unable to read perf file descriptor\n");
 
351
                        exit(-1);
 
352
                }
 
353
 
 
354
                if (perf_header_attr__add_id(h_attr, read_data.id) < 0) {
 
355
                        pr_warning("Not enough memory to add id\n");
 
356
                        exit(-1);
 
357
                }
 
358
 
 
359
                assert(fd[nr_cpu][counter][thread_index] >= 0);
 
360
                fcntl(fd[nr_cpu][counter][thread_index], F_SETFL, O_NONBLOCK);
 
361
 
 
362
                /*
 
363
                 * First counter acts as the group leader:
 
364
                 */
 
365
                if (group && group_fd == -1)
 
366
                        group_fd = fd[nr_cpu][counter][thread_index];
 
367
 
 
368
                if (counter || thread_index) {
 
369
                        ret = ioctl(fd[nr_cpu][counter][thread_index],
 
370
                                        PERF_EVENT_IOC_SET_OUTPUT,
 
371
                                        fd[nr_cpu][0][0]);
 
372
                        if (ret) {
 
373
                                error("failed to set output: %d (%s)\n", errno,
 
374
                                                strerror(errno));
 
375
                                exit(-1);
 
376
                        }
 
377
                } else {
 
378
                        mmap_array[nr_cpu].counter = counter;
 
379
                        mmap_array[nr_cpu].prev = 0;
 
380
                        mmap_array[nr_cpu].mask = mmap_pages*page_size - 1;
 
381
                        mmap_array[nr_cpu].base = mmap(NULL, (mmap_pages+1)*page_size,
 
382
                                PROT_READ|PROT_WRITE, MAP_SHARED, fd[nr_cpu][counter][thread_index], 0);
 
383
                        if (mmap_array[nr_cpu].base == MAP_FAILED) {
 
384
                                error("failed to mmap with %d (%s)\n", errno, strerror(errno));
 
385
                                exit(-1);
 
386
                        }
 
387
 
 
388
                        event_array[nr_poll].fd = fd[nr_cpu][counter][thread_index];
 
389
                        event_array[nr_poll].events = POLLIN;
 
390
                        nr_poll++;
 
391
                }
 
392
 
 
393
                if (filter != NULL) {
 
394
                        ret = ioctl(fd[nr_cpu][counter][thread_index],
 
395
                                        PERF_EVENT_IOC_SET_FILTER, filter);
 
396
                        if (ret) {
 
397
                                error("failed to set filter with %d (%s)\n", errno,
 
398
                                                strerror(errno));
 
399
                                exit(-1);
 
400
                        }
 
401
                }
 
402
        }
 
403
}
 
404
 
 
405
static void open_counters(int cpu)
 
406
{
 
407
        int counter;
 
408
 
 
409
        group_fd = -1;
 
410
        for (counter = 0; counter < nr_counters; counter++)
 
411
                create_counter(counter, cpu);
 
412
 
 
413
        nr_cpu++;
 
414
}
 
415
 
 
416
static int process_buildids(void)
 
417
{
 
418
        u64 size = lseek(output, 0, SEEK_CUR);
 
419
 
 
420
        if (size == 0)
 
421
                return 0;
 
422
 
 
423
        session->fd = output;
 
424
        return __perf_session__process_events(session, post_processing_offset,
 
425
                                              size - post_processing_offset,
 
426
                                              size, &build_id__mark_dso_hit_ops);
 
427
}
 
428
 
 
429
static void atexit_header(void)
 
430
{
 
431
        if (!pipe_output) {
 
432
                session->header.data_size += bytes_written;
 
433
 
 
434
                process_buildids();
 
435
                perf_header__write(&session->header, output, true);
 
436
        }
 
437
}
 
438
 
 
439
static void event__synthesize_guest_os(struct machine *machine, void *data)
 
440
{
 
441
        int err;
 
442
        char *guest_kallsyms;
 
443
        char path[PATH_MAX];
 
444
        struct perf_session *psession = data;
 
445
 
 
446
        if (machine__is_host(machine))
 
447
                return;
 
448
 
 
449
        /*
 
450
         *As for guest kernel when processing subcommand record&report,
 
451
         *we arrange module mmap prior to guest kernel mmap and trigger
 
452
         *a preload dso because default guest module symbols are loaded
 
453
         *from guest kallsyms instead of /lib/modules/XXX/XXX. This
 
454
         *method is used to avoid symbol missing when the first addr is
 
455
         *in module instead of in guest kernel.
 
456
         */
 
457
        err = event__synthesize_modules(process_synthesized_event,
 
458
                                        psession, machine);
 
459
        if (err < 0)
 
460
                pr_err("Couldn't record guest kernel [%d]'s reference"
 
461
                       " relocation symbol.\n", machine->pid);
 
462
 
 
463
        if (machine__is_default_guest(machine))
 
464
                guest_kallsyms = (char *) symbol_conf.default_guest_kallsyms;
 
465
        else {
 
466
                sprintf(path, "%s/proc/kallsyms", machine->root_dir);
 
467
                guest_kallsyms = path;
 
468
        }
 
469
 
 
470
        /*
 
471
         * We use _stext for guest kernel because guest kernel's /proc/kallsyms
 
472
         * have no _text sometimes.
 
473
         */
 
474
        err = event__synthesize_kernel_mmap(process_synthesized_event,
 
475
                                            psession, machine, "_text");
 
476
        if (err < 0)
 
477
                err = event__synthesize_kernel_mmap(process_synthesized_event,
 
478
                                                    psession, machine, "_stext");
 
479
        if (err < 0)
 
480
                pr_err("Couldn't record guest kernel [%d]'s reference"
 
481
                       " relocation symbol.\n", machine->pid);
 
482
}
 
483
 
 
484
static struct perf_event_header finished_round_event = {
 
485
        .size = sizeof(struct perf_event_header),
 
486
        .type = PERF_RECORD_FINISHED_ROUND,
 
487
};
 
488
 
 
489
static void mmap_read_all(void)
 
490
{
 
491
        int i;
 
492
 
 
493
        for (i = 0; i < nr_cpu; i++) {
 
494
                if (mmap_array[i].base)
 
495
                        mmap_read(&mmap_array[i]);
 
496
        }
 
497
 
 
498
        if (perf_header__has_feat(&session->header, HEADER_TRACE_INFO))
 
499
                write_output(&finished_round_event, sizeof(finished_round_event));
 
500
}
 
501
 
 
502
static int __cmd_record(int argc, const char **argv)
 
503
{
 
504
        int i, counter;
 
505
        struct stat st;
 
506
        int flags;
 
507
        int err;
 
508
        unsigned long waking = 0;
 
509
        int child_ready_pipe[2], go_pipe[2];
 
510
        const bool forks = argc > 0;
 
511
        char buf;
 
512
        struct machine *machine;
 
513
 
 
514
        page_size = sysconf(_SC_PAGE_SIZE);
 
515
 
 
516
        atexit(sig_atexit);
 
517
        signal(SIGCHLD, sig_handler);
 
518
        signal(SIGINT, sig_handler);
 
519
 
 
520
        if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
 
521
                perror("failed to create pipes");
 
522
                exit(-1);
 
523
        }
 
524
 
 
525
        if (!strcmp(output_name, "-"))
 
526
                pipe_output = 1;
 
527
        else if (!stat(output_name, &st) && st.st_size) {
 
528
                if (write_mode == WRITE_FORCE) {
 
529
                        char oldname[PATH_MAX];
 
530
                        snprintf(oldname, sizeof(oldname), "%s.old",
 
531
                                 output_name);
 
532
                        unlink(oldname);
 
533
                        rename(output_name, oldname);
 
534
                }
 
535
        } else if (write_mode == WRITE_APPEND) {
 
536
                write_mode = WRITE_FORCE;
 
537
        }
 
538
 
 
539
        flags = O_CREAT|O_RDWR;
 
540
        if (write_mode == WRITE_APPEND)
 
541
                file_new = 0;
 
542
        else
 
543
                flags |= O_TRUNC;
 
544
 
 
545
        if (pipe_output)
 
546
                output = STDOUT_FILENO;
 
547
        else
 
548
                output = open(output_name, flags, S_IRUSR | S_IWUSR);
 
549
        if (output < 0) {
 
550
                perror("failed to create output file");
 
551
                exit(-1);
 
552
        }
 
553
 
 
554
        session = perf_session__new(output_name, O_WRONLY,
 
555
                                    write_mode == WRITE_FORCE, false);
 
556
        if (session == NULL) {
 
557
                pr_err("Not enough memory for reading perf file header\n");
 
558
                return -1;
 
559
        }
 
560
 
 
561
        if (!file_new) {
 
562
                err = perf_header__read(session, output);
 
563
                if (err < 0)
 
564
                        return err;
 
565
        }
 
566
 
 
567
        if (have_tracepoints(attrs, nr_counters))
 
568
                perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
 
569
 
 
570
        atexit(atexit_header);
 
571
 
 
572
        if (forks) {
 
573
                child_pid = fork();
 
574
                if (child_pid < 0) {
 
575
                        perror("failed to fork");
 
576
                        exit(-1);
 
577
                }
 
578
 
 
579
                if (!child_pid) {
 
580
                        if (pipe_output)
 
581
                                dup2(2, 1);
 
582
                        close(child_ready_pipe[0]);
 
583
                        close(go_pipe[1]);
 
584
                        fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
 
585
 
 
586
                        /*
 
587
                         * Do a dummy execvp to get the PLT entry resolved,
 
588
                         * so we avoid the resolver overhead on the real
 
589
                         * execvp call.
 
590
                         */
 
591
                        execvp("", (char **)argv);
 
592
 
 
593
                        /*
 
594
                         * Tell the parent we're ready to go
 
595
                         */
 
596
                        close(child_ready_pipe[1]);
 
597
 
 
598
                        /*
 
599
                         * Wait until the parent tells us to go.
 
600
                         */
 
601
                        if (read(go_pipe[0], &buf, 1) == -1)
 
602
                                perror("unable to read pipe");
 
603
 
 
604
                        execvp(argv[0], (char **)argv);
 
605
 
 
606
                        perror(argv[0]);
 
607
                        exit(-1);
 
608
                }
 
609
 
 
610
                if (!system_wide && target_tid == -1 && target_pid == -1)
 
611
                        all_tids[0] = child_pid;
 
612
 
 
613
                close(child_ready_pipe[1]);
 
614
                close(go_pipe[0]);
 
615
                /*
 
616
                 * wait for child to settle
 
617
                 */
 
618
                if (read(child_ready_pipe[0], &buf, 1) == -1) {
 
619
                        perror("unable to read pipe");
 
620
                        exit(-1);
 
621
                }
 
622
                close(child_ready_pipe[0]);
 
623
        }
 
624
 
 
625
        if ((!system_wide && no_inherit) || profile_cpu != -1) {
 
626
                open_counters(profile_cpu);
 
627
        } else {
 
628
                nr_cpus = read_cpu_map();
 
629
                for (i = 0; i < nr_cpus; i++)
 
630
                        open_counters(cpumap[i]);
 
631
        }
 
632
 
 
633
        if (pipe_output) {
 
634
                err = perf_header__write_pipe(output);
 
635
                if (err < 0)
 
636
                        return err;
 
637
        } else if (file_new) {
 
638
                err = perf_header__write(&session->header, output, false);
 
639
                if (err < 0)
 
640
                        return err;
 
641
        }
 
642
 
 
643
        post_processing_offset = lseek(output, 0, SEEK_CUR);
 
644
 
 
645
        if (pipe_output) {
 
646
                err = event__synthesize_attrs(&session->header,
 
647
                                              process_synthesized_event,
 
648
                                              session);
 
649
                if (err < 0) {
 
650
                        pr_err("Couldn't synthesize attrs.\n");
 
651
                        return err;
 
652
                }
 
653
 
 
654
                err = event__synthesize_event_types(process_synthesized_event,
 
655
                                                    session);
 
656
                if (err < 0) {
 
657
                        pr_err("Couldn't synthesize event_types.\n");
 
658
                        return err;
 
659
                }
 
660
 
 
661
                if (have_tracepoints(attrs, nr_counters)) {
 
662
                        /*
 
663
                         * FIXME err <= 0 here actually means that
 
664
                         * there were no tracepoints so its not really
 
665
                         * an error, just that we don't need to
 
666
                         * synthesize anything.  We really have to
 
667
                         * return this more properly and also
 
668
                         * propagate errors that now are calling die()
 
669
                         */
 
670
                        err = event__synthesize_tracing_data(output, attrs,
 
671
                                                             nr_counters,
 
672
                                                             process_synthesized_event,
 
673
                                                             session);
 
674
                        if (err <= 0) {
 
675
                                pr_err("Couldn't record tracing data.\n");
 
676
                                return err;
 
677
                        }
 
678
                        advance_output(err);
 
679
                }
 
680
        }
 
681
 
 
682
        machine = perf_session__find_host_machine(session);
 
683
        if (!machine) {
 
684
                pr_err("Couldn't find native kernel information.\n");
 
685
                return -1;
 
686
        }
 
687
 
 
688
        err = event__synthesize_kernel_mmap(process_synthesized_event,
 
689
                                            session, machine, "_text");
 
690
        if (err < 0)
 
691
                err = event__synthesize_kernel_mmap(process_synthesized_event,
 
692
                                                    session, machine, "_stext");
 
693
        if (err < 0) {
 
694
                pr_err("Couldn't record kernel reference relocation symbol.\n");
 
695
                return err;
 
696
        }
 
697
 
 
698
        err = event__synthesize_modules(process_synthesized_event,
 
699
                                        session, machine);
 
700
        if (err < 0) {
 
701
                pr_err("Couldn't record kernel reference relocation symbol.\n");
 
702
                return err;
 
703
        }
 
704
        if (perf_guest)
 
705
                perf_session__process_machines(session, event__synthesize_guest_os);
 
706
 
 
707
        if (!system_wide && profile_cpu == -1)
 
708
                event__synthesize_thread(target_tid, process_synthesized_event,
 
709
                                         session);
 
710
        else
 
711
                event__synthesize_threads(process_synthesized_event, session);
 
712
 
 
713
        if (realtime_prio) {
 
714
                struct sched_param param;
 
715
 
 
716
                param.sched_priority = realtime_prio;
 
717
                if (sched_setscheduler(0, SCHED_FIFO, &param)) {
 
718
                        pr_err("Could not set realtime priority.\n");
 
719
                        exit(-1);
 
720
                }
 
721
        }
 
722
 
 
723
        /*
 
724
         * Let the child rip
 
725
         */
 
726
        if (forks)
 
727
                close(go_pipe[1]);
 
728
 
 
729
        for (;;) {
 
730
                int hits = samples;
 
731
                int thread;
 
732
 
 
733
                mmap_read_all();
 
734
 
 
735
                if (hits == samples) {
 
736
                        if (done)
 
737
                                break;
 
738
                        err = poll(event_array, nr_poll, -1);
 
739
                        waking++;
 
740
                }
 
741
 
 
742
                if (done) {
 
743
                        for (i = 0; i < nr_cpu; i++) {
 
744
                                for (counter = 0;
 
745
                                        counter < nr_counters;
 
746
                                        counter++) {
 
747
                                        for (thread = 0;
 
748
                                                thread < thread_num;
 
749
                                                thread++)
 
750
                                                ioctl(fd[i][counter][thread],
 
751
                                                        PERF_EVENT_IOC_DISABLE);
 
752
                                }
 
753
                        }
 
754
                }
 
755
        }
 
756
 
 
757
        fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
 
758
 
 
759
        /*
 
760
         * Approximate RIP event size: 24 bytes.
 
761
         */
 
762
        fprintf(stderr,
 
763
                "[ perf record: Captured and wrote %.3f MB %s (~%lld samples) ]\n",
 
764
                (double)bytes_written / 1024.0 / 1024.0,
 
765
                output_name,
 
766
                bytes_written / 24);
 
767
 
 
768
        return 0;
 
769
}
 
770
 
 
771
static const char * const record_usage[] = {
 
772
        "perf record [<options>] [<command>]",
 
773
        "perf record [<options>] -- <command> [<options>]",
 
774
        NULL
 
775
};
 
776
 
 
777
static bool force, append_file;
 
778
 
 
779
static const struct option options[] = {
 
780
        OPT_CALLBACK('e', "event", NULL, "event",
 
781
                     "event selector. use 'perf list' to list available events",
 
782
                     parse_events),
 
783
        OPT_CALLBACK(0, "filter", NULL, "filter",
 
784
                     "event filter", parse_filter),
 
785
        OPT_INTEGER('p', "pid", &target_pid,
 
786
                    "record events on existing process id"),
 
787
        OPT_INTEGER('t', "tid", &target_tid,
 
788
                    "record events on existing thread id"),
 
789
        OPT_INTEGER('r', "realtime", &realtime_prio,
 
790
                    "collect data with this RT SCHED_FIFO priority"),
 
791
        OPT_BOOLEAN('R', "raw-samples", &raw_samples,
 
792
                    "collect raw sample records from all opened counters"),
 
793
        OPT_BOOLEAN('a', "all-cpus", &system_wide,
 
794
                            "system-wide collection from all CPUs"),
 
795
        OPT_BOOLEAN('A', "append", &append_file,
 
796
                            "append to the output file to do incremental profiling"),
 
797
        OPT_INTEGER('C', "profile_cpu", &profile_cpu,
 
798
                            "CPU to profile on"),
 
799
        OPT_BOOLEAN('f', "force", &force,
 
800
                        "overwrite existing data file (deprecated)"),
 
801
        OPT_U64('c', "count", &user_interval, "event period to sample"),
 
802
        OPT_STRING('o', "output", &output_name, "file",
 
803
                    "output file name"),
 
804
        OPT_BOOLEAN('i', "no-inherit", &no_inherit,
 
805
                    "child tasks do not inherit counters"),
 
806
        OPT_UINTEGER('F', "freq", &user_freq, "profile at this frequency"),
 
807
        OPT_UINTEGER('m', "mmap-pages", &mmap_pages, "number of mmap data pages"),
 
808
        OPT_BOOLEAN('g', "call-graph", &call_graph,
 
809
                    "do call-graph (stack chain/backtrace) recording"),
 
810
        OPT_INCR('v', "verbose", &verbose,
 
811
                    "be more verbose (show counter open errors, etc)"),
 
812
        OPT_BOOLEAN('s', "stat", &inherit_stat,
 
813
                    "per thread counts"),
 
814
        OPT_BOOLEAN('d', "data", &sample_address,
 
815
                    "Sample addresses"),
 
816
        OPT_BOOLEAN('n', "no-samples", &no_samples,
 
817
                    "don't sample"),
 
818
        OPT_END()
 
819
};
 
820
 
 
821
int cmd_record(int argc, const char **argv, const char *prefix __used)
 
822
{
 
823
        int i,j;
 
824
 
 
825
        argc = parse_options(argc, argv, options, record_usage,
 
826
                            PARSE_OPT_STOP_AT_NON_OPTION);
 
827
        if (!argc && target_pid == -1 && target_tid == -1 &&
 
828
                !system_wide && profile_cpu == -1)
 
829
                usage_with_options(record_usage, options);
 
830
 
 
831
        if (force && append_file) {
 
832
                fprintf(stderr, "Can't overwrite and append at the same time."
 
833
                                " You need to choose between -f and -A");
 
834
                usage_with_options(record_usage, options);
 
835
        } else if (append_file) {
 
836
                write_mode = WRITE_APPEND;
 
837
        } else {
 
838
                write_mode = WRITE_FORCE;
 
839
        }
 
840
 
 
841
        symbol__init();
 
842
 
 
843
        if (!nr_counters) {
 
844
                nr_counters     = 1;
 
845
                attrs[0].type   = PERF_TYPE_HARDWARE;
 
846
                attrs[0].config = PERF_COUNT_HW_CPU_CYCLES;
 
847
        }
 
848
 
 
849
        if (target_pid != -1) {
 
850
                target_tid = target_pid;
 
851
                thread_num = find_all_tid(target_pid, &all_tids);
 
852
                if (thread_num <= 0) {
 
853
                        fprintf(stderr, "Can't find all threads of pid %d\n",
 
854
                                        target_pid);
 
855
                        usage_with_options(record_usage, options);
 
856
                }
 
857
        } else {
 
858
                all_tids=malloc(sizeof(pid_t));
 
859
                if (!all_tids)
 
860
                        return -ENOMEM;
 
861
 
 
862
                all_tids[0] = target_tid;
 
863
                thread_num = 1;
 
864
        }
 
865
 
 
866
        for (i = 0; i < MAX_NR_CPUS; i++) {
 
867
                for (j = 0; j < MAX_COUNTERS; j++) {
 
868
                        fd[i][j] = malloc(sizeof(int)*thread_num);
 
869
                        if (!fd[i][j])
 
870
                                return -ENOMEM;
 
871
                }
 
872
        }
 
873
        event_array = malloc(
 
874
                sizeof(struct pollfd)*MAX_NR_CPUS*MAX_COUNTERS*thread_num);
 
875
        if (!event_array)
 
876
                return -ENOMEM;
 
877
 
 
878
        if (user_interval != ULLONG_MAX)
 
879
                default_interval = user_interval;
 
880
        if (user_freq != UINT_MAX)
 
881
                freq = user_freq;
 
882
 
 
883
        /*
 
884
         * User specified count overrides default frequency.
 
885
         */
 
886
        if (default_interval)
 
887
                freq = 0;
 
888
        else if (freq) {
 
889
                default_interval = freq;
 
890
        } else {
 
891
                fprintf(stderr, "frequency and count are zero, aborting\n");
 
892
                exit(EXIT_FAILURE);
 
893
        }
 
894
 
 
895
        return __cmd_record(argc, argv);
 
896
}