~ubuntu-branches/debian/experimental/linux-tools/experimental

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): Ben Hutchings
  • Date: 2014-02-02 16:57:49 UTC
  • mfrom: (1.1.10) (0.1.21 sid)
  • Revision ID: package-import@ubuntu.com-20140202165749-tw94o9t1t0a8txk6
Tags: 3.13-1~exp2
Merge changes from sid up to 3.12.6-3

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
#include "util/symbol.h"
25
25
#include "util/cpumap.h"
26
26
#include "util/thread_map.h"
 
27
#include "util/data.h"
27
28
 
28
29
#include <unistd.h>
29
30
#include <sched.h>
30
31
#include <sys/mman.h>
31
32
 
32
 
#ifndef HAVE_ON_EXIT
 
33
#ifndef HAVE_ON_EXIT_SUPPORT
33
34
#ifndef ATEXIT_MAX
34
35
#define ATEXIT_MAX 32
35
36
#endif
65
66
        struct perf_tool        tool;
66
67
        struct perf_record_opts opts;
67
68
        u64                     bytes_written;
68
 
        const char              *output_name;
 
69
        struct perf_data_file   file;
69
70
        struct perf_evlist      *evlist;
70
71
        struct perf_session     *session;
71
72
        const char              *progname;
72
 
        int                     output;
73
 
        unsigned int            page_size;
74
73
        int                     realtime_prio;
75
74
        bool                    no_buildid;
76
75
        bool                    no_buildid_cache;
77
76
        long                    samples;
78
 
        off_t                   post_processing_offset;
79
77
};
80
78
 
81
 
static void advance_output(struct perf_record *rec, size_t size)
 
79
static int do_write_output(struct perf_record *rec, void *buf, size_t size)
82
80
{
83
 
        rec->bytes_written += size;
84
 
}
 
81
        struct perf_data_file *file = &rec->file;
85
82
 
86
 
static int write_output(struct perf_record *rec, void *buf, size_t size)
87
 
{
88
83
        while (size) {
89
 
                int ret = write(rec->output, buf, size);
 
84
                ssize_t ret = write(file->fd, buf, size);
90
85
 
91
86
                if (ret < 0) {
92
 
                        pr_err("failed to write\n");
 
87
                        pr_err("failed to write perf data, error: %m\n");
93
88
                        return -1;
94
89
                }
95
90
 
102
97
        return 0;
103
98
}
104
99
 
 
100
static int write_output(struct perf_record *rec, void *buf, size_t size)
 
101
{
 
102
        return do_write_output(rec, buf, size);
 
103
}
 
104
 
105
105
static int process_synthesized_event(struct perf_tool *tool,
106
106
                                     union perf_event *event,
107
107
                                     struct perf_sample *sample __maybe_unused,
119
119
{
120
120
        unsigned int head = perf_mmap__read_head(md);
121
121
        unsigned int old = md->prev;
122
 
        unsigned char *data = md->base + rec->page_size;
 
122
        unsigned char *data = md->base + page_size;
123
123
        unsigned long size;
124
124
        void *buf;
125
125
        int rc = 0;
234
234
                               "or try again with a smaller value of -m/--mmap_pages.\n"
235
235
                               "(current value: %d)\n", opts->mmap_pages);
236
236
                        rc = -errno;
237
 
                } else if (!is_power_of_2(opts->mmap_pages) &&
238
 
                           (opts->mmap_pages != UINT_MAX)) {
239
 
                        pr_err("--mmap_pages/-m value must be a power of two.");
240
 
                        rc = -EINVAL;
241
237
                } else {
242
238
                        pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
243
239
                        rc = -errno;
253
249
 
254
250
static int process_buildids(struct perf_record *rec)
255
251
{
256
 
        u64 size = lseek(rec->output, 0, SEEK_CUR);
 
252
        struct perf_data_file *file  = &rec->file;
 
253
        struct perf_session *session = rec->session;
 
254
        u64 start = session->header.data_offset;
257
255
 
 
256
        u64 size = lseek(file->fd, 0, SEEK_CUR);
258
257
        if (size == 0)
259
258
                return 0;
260
259
 
261
 
        rec->session->fd = rec->output;
262
 
        return __perf_session__process_events(rec->session, rec->post_processing_offset,
263
 
                                              size - rec->post_processing_offset,
 
260
        return __perf_session__process_events(session, start,
 
261
                                              size - start,
264
262
                                              size, &build_id__mark_dso_hit_ops);
265
263
}
266
264
 
267
265
static void perf_record__exit(int status, void *arg)
268
266
{
269
267
        struct perf_record *rec = arg;
 
268
        struct perf_data_file *file = &rec->file;
270
269
 
271
270
        if (status != 0)
272
271
                return;
273
272
 
274
 
        if (!rec->opts.pipe_output) {
 
273
        if (!file->is_pipe) {
275
274
                rec->session->header.data_size += rec->bytes_written;
276
275
 
277
276
                if (!rec->no_buildid)
278
277
                        process_buildids(rec);
279
278
                perf_session__write_header(rec->session, rec->evlist,
280
 
                                           rec->output, true);
 
279
                                           file->fd, true);
281
280
                perf_session__delete(rec->session);
282
281
                perf_evlist__delete(rec->evlist);
283
282
                symbol__exit();
343
342
        return rc;
344
343
}
345
344
 
 
345
static void perf_record__init_features(struct perf_record *rec)
 
346
{
 
347
        struct perf_evlist *evsel_list = rec->evlist;
 
348
        struct perf_session *session = rec->session;
 
349
        int feat;
 
350
 
 
351
        for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
 
352
                perf_header__set_feat(&session->header, feat);
 
353
 
 
354
        if (rec->no_buildid)
 
355
                perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
 
356
 
 
357
        if (!have_tracepoints(&evsel_list->entries))
 
358
                perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
 
359
 
 
360
        if (!rec->opts.branch_stack)
 
361
                perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
 
362
}
 
363
 
346
364
static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
347
365
{
348
 
        struct stat st;
349
 
        int flags;
350
 
        int err, output, feat;
 
366
        int err;
351
367
        unsigned long waking = 0;
352
368
        const bool forks = argc > 0;
353
369
        struct machine *machine;
354
370
        struct perf_tool *tool = &rec->tool;
355
371
        struct perf_record_opts *opts = &rec->opts;
356
372
        struct perf_evlist *evsel_list = rec->evlist;
357
 
        const char *output_name = rec->output_name;
 
373
        struct perf_data_file *file = &rec->file;
358
374
        struct perf_session *session;
359
375
        bool disabled = false;
360
376
 
361
377
        rec->progname = argv[0];
362
378
 
363
 
        rec->page_size = sysconf(_SC_PAGE_SIZE);
364
 
 
365
379
        on_exit(perf_record__sig_exit, rec);
366
380
        signal(SIGCHLD, sig_handler);
367
381
        signal(SIGINT, sig_handler);
368
382
        signal(SIGUSR1, sig_handler);
369
383
        signal(SIGTERM, sig_handler);
370
384
 
371
 
        if (!output_name) {
372
 
                if (!fstat(STDOUT_FILENO, &st) && S_ISFIFO(st.st_mode))
373
 
                        opts->pipe_output = true;
374
 
                else
375
 
                        rec->output_name = output_name = "perf.data";
376
 
        }
377
 
        if (output_name) {
378
 
                if (!strcmp(output_name, "-"))
379
 
                        opts->pipe_output = true;
380
 
                else if (!stat(output_name, &st) && st.st_size) {
381
 
                        char oldname[PATH_MAX];
382
 
                        snprintf(oldname, sizeof(oldname), "%s.old",
383
 
                                 output_name);
384
 
                        unlink(oldname);
385
 
                        rename(output_name, oldname);
386
 
                }
387
 
        }
388
 
 
389
 
        flags = O_CREAT|O_RDWR|O_TRUNC;
390
 
 
391
 
        if (opts->pipe_output)
392
 
                output = STDOUT_FILENO;
393
 
        else
394
 
                output = open(output_name, flags, S_IRUSR | S_IWUSR);
395
 
        if (output < 0) {
396
 
                perror("failed to create output file");
397
 
                return -1;
398
 
        }
399
 
 
400
 
        rec->output = output;
401
 
 
402
 
        session = perf_session__new(output_name, O_WRONLY,
403
 
                                    true, false, NULL);
 
385
        session = perf_session__new(file, false, NULL);
404
386
        if (session == NULL) {
405
387
                pr_err("Not enough memory for reading perf file header\n");
406
388
                return -1;
408
390
 
409
391
        rec->session = session;
410
392
 
411
 
        for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
412
 
                perf_header__set_feat(&session->header, feat);
413
 
 
414
 
        if (rec->no_buildid)
415
 
                perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
416
 
 
417
 
        if (!have_tracepoints(&evsel_list->entries))
418
 
                perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
419
 
 
420
 
        if (!rec->opts.branch_stack)
421
 
                perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
 
393
        perf_record__init_features(rec);
422
394
 
423
395
        if (forks) {
424
396
                err = perf_evlist__prepare_workload(evsel_list, &opts->target,
425
 
                                                    argv, opts->pipe_output,
 
397
                                                    argv, file->is_pipe,
426
398
                                                    true);
427
399
                if (err < 0) {
428
400
                        pr_err("Couldn't run the workload!\n");
443
415
         */
444
416
        on_exit(perf_record__exit, rec);
445
417
 
446
 
        if (opts->pipe_output) {
447
 
                err = perf_header__write_pipe(output);
 
418
        if (file->is_pipe) {
 
419
                err = perf_header__write_pipe(file->fd);
448
420
                if (err < 0)
449
421
                        goto out_delete_session;
450
422
        } else {
451
423
                err = perf_session__write_header(session, evsel_list,
452
 
                                                 output, false);
 
424
                                                 file->fd, false);
453
425
                if (err < 0)
454
426
                        goto out_delete_session;
455
427
        }
462
434
                goto out_delete_session;
463
435
        }
464
436
 
465
 
        rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
466
 
 
467
437
        machine = &session->machines.host;
468
438
 
469
 
        if (opts->pipe_output) {
 
439
        if (file->is_pipe) {
470
440
                err = perf_event__synthesize_attrs(tool, session,
471
441
                                                   process_synthesized_event);
472
442
                if (err < 0) {
483
453
                         * return this more properly and also
484
454
                         * propagate errors that now are calling die()
485
455
                         */
486
 
                        err = perf_event__synthesize_tracing_data(tool, output, evsel_list,
 
456
                        err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list,
487
457
                                                                  process_synthesized_event);
488
458
                        if (err <= 0) {
489
459
                                pr_err("Couldn't record tracing data.\n");
490
460
                                goto out_delete_session;
491
461
                        }
492
 
                        advance_output(rec, err);
 
462
                        rec->bytes_written += err;
493
463
                }
494
464
        }
495
465
 
515
485
                                         perf_event__synthesize_guest_os, tool);
516
486
        }
517
487
 
518
 
        if (perf_target__has_task(&opts->target))
519
 
                err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
520
 
                                                  process_synthesized_event,
521
 
                                                  machine);
522
 
        else if (perf_target__has_cpu(&opts->target))
523
 
                err = perf_event__synthesize_threads(tool, process_synthesized_event,
524
 
                                               machine);
525
 
        else /* command specified */
526
 
                err = 0;
527
 
 
 
488
        err = __machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads,
 
489
                                            process_synthesized_event, opts->sample_address);
528
490
        if (err != 0)
529
491
                goto out_delete_session;
530
492
 
544
506
         * (apart from group members) have enable_on_exec=1 set,
545
507
         * so don't spoil it by prematurely enabling them.
546
508
         */
547
 
        if (!perf_target__none(&opts->target))
 
509
        if (!target__none(&opts->target))
548
510
                perf_evlist__enable(evsel_list);
549
511
 
550
512
        /*
573
535
                 * die with the process and we wait for that. Thus no need to
574
536
                 * disable events in this case.
575
537
                 */
576
 
                if (done && !disabled && !perf_target__none(&opts->target)) {
 
538
                if (done && !disabled && !target__none(&opts->target)) {
577
539
                        perf_evlist__disable(evsel_list);
578
540
                        disabled = true;
579
541
                }
590
552
        fprintf(stderr,
591
553
                "[ perf record: Captured and wrote %.3f MB %s (~%" PRIu64 " samples) ]\n",
592
554
                (double)rec->bytes_written / 1024.0 / 1024.0,
593
 
                output_name,
 
555
                file->path,
594
556
                rec->bytes_written / 24);
595
557
 
596
558
        return 0;
618
580
        BRANCH_OPT("any_call", PERF_SAMPLE_BRANCH_ANY_CALL),
619
581
        BRANCH_OPT("any_ret", PERF_SAMPLE_BRANCH_ANY_RETURN),
620
582
        BRANCH_OPT("ind_call", PERF_SAMPLE_BRANCH_IND_CALL),
 
583
        BRANCH_OPT("abort_tx", PERF_SAMPLE_BRANCH_ABORT_TX),
 
584
        BRANCH_OPT("in_tx", PERF_SAMPLE_BRANCH_IN_TX),
 
585
        BRANCH_OPT("no_tx", PERF_SAMPLE_BRANCH_NO_TX),
621
586
        BRANCH_END
622
587
};
623
588
 
684
649
        return ret;
685
650
}
686
651
 
687
 
#ifdef LIBUNWIND_SUPPORT
 
652
#ifdef HAVE_LIBUNWIND_SUPPORT
688
653
static int get_stack_size(char *str, unsigned long *_size)
689
654
{
690
655
        char *endptr;
710
675
               max_size, str);
711
676
        return -1;
712
677
}
713
 
#endif /* LIBUNWIND_SUPPORT */
 
678
#endif /* HAVE_LIBUNWIND_SUPPORT */
714
679
 
715
680
int record_parse_callchain(const char *arg, struct perf_record_opts *opts)
716
681
{
739
704
                                       "needed for -g fp\n");
740
705
                        break;
741
706
 
742
 
#ifdef LIBUNWIND_SUPPORT
 
707
#ifdef HAVE_LIBUNWIND_SUPPORT
743
708
                /* Dwarf style */
744
709
                } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
745
710
                        const unsigned long default_stack_dump_size = 8192;
755
720
                                ret = get_stack_size(tok, &size);
756
721
                                opts->stack_dump_size = size;
757
722
                        }
758
 
#endif /* LIBUNWIND_SUPPORT */
 
723
#endif /* HAVE_LIBUNWIND_SUPPORT */
759
724
                } else {
760
725
                        pr_err("callchain: Unknown --call-graph option "
761
726
                               "value: %s\n", arg);
841
806
 
842
807
#define CALLCHAIN_HELP "setup and enables call-graph (stack chain/backtrace) recording: "
843
808
 
844
 
#ifdef LIBUNWIND_SUPPORT
 
809
#ifdef HAVE_LIBUNWIND_SUPPORT
845
810
const char record_callchain_help[] = CALLCHAIN_HELP "fp dwarf";
846
811
#else
847
812
const char record_callchain_help[] = CALLCHAIN_HELP "fp";
875
840
        OPT_STRING('C', "cpu", &record.opts.target.cpu_list, "cpu",
876
841
                    "list of cpus to monitor"),
877
842
        OPT_U64('c', "count", &record.opts.user_interval, "event period to sample"),
878
 
        OPT_STRING('o', "output", &record.output_name, "file",
 
843
        OPT_STRING('o', "output", &record.file.path, "file",
879
844
                    "output file name"),
880
845
        OPT_BOOLEAN('i', "no-inherit", &record.opts.no_inherit,
881
846
                    "child tasks do not inherit counters"),
882
847
        OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
883
 
        OPT_UINTEGER('m', "mmap-pages", &record.opts.mmap_pages,
884
 
                     "number of mmap data pages"),
 
848
        OPT_CALLBACK('m', "mmap-pages", &record.opts.mmap_pages, "pages",
 
849
                     "number of mmap data pages",
 
850
                     perf_evlist__parse_mmap_pages),
885
851
        OPT_BOOLEAN(0, "group", &record.opts.group,
886
852
                    "put the counters into a counter group"),
887
853
        OPT_CALLBACK_NOOPT('g', NULL, &record.opts,
920
886
                     parse_branch_stack),
921
887
        OPT_BOOLEAN('W', "weight", &record.opts.sample_weight,
922
888
                    "sample by weight (on special events only)"),
 
889
        OPT_BOOLEAN(0, "transaction", &record.opts.sample_transaction,
 
890
                    "sample transaction flags (special events only)"),
 
891
        OPT_BOOLEAN(0, "force-per-cpu", &record.opts.target.force_per_cpu,
 
892
                    "force the use of per-cpu mmaps"),
923
893
        OPT_END()
924
894
};
925
895
 
938
908
 
939
909
        argc = parse_options(argc, argv, record_options, record_usage,
940
910
                            PARSE_OPT_STOP_AT_NON_OPTION);
941
 
        if (!argc && perf_target__none(&rec->opts.target))
 
911
        if (!argc && target__none(&rec->opts.target))
942
912
                usage_with_options(record_usage, record_options);
943
913
 
944
914
        if (nr_cgroups && !rec->opts.target.system_wide) {
968
938
                goto out_symbol_exit;
969
939
        }
970
940
 
971
 
        err = perf_target__validate(&rec->opts.target);
 
941
        err = target__validate(&rec->opts.target);
972
942
        if (err) {
973
 
                perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
 
943
                target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
974
944
                ui__warning("%s", errbuf);
975
945
        }
976
946
 
977
 
        err = perf_target__parse_uid(&rec->opts.target);
 
947
        err = target__parse_uid(&rec->opts.target);
978
948
        if (err) {
979
949
                int saved_errno = errno;
980
950
 
981
 
                perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
 
951
                target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
982
952
                ui__error("%s", errbuf);
983
953
 
984
954
                err = -saved_errno;
989
959
        if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
990
960
                usage_with_options(record_usage, record_options);
991
961
 
992
 
        if (rec->opts.user_interval != ULLONG_MAX)
993
 
                rec->opts.default_interval = rec->opts.user_interval;
994
 
        if (rec->opts.user_freq != UINT_MAX)
995
 
                rec->opts.freq = rec->opts.user_freq;
996
 
 
997
 
        /*
998
 
         * User specified count overrides default frequency.
999
 
         */
1000
 
        if (rec->opts.default_interval)
1001
 
                rec->opts.freq = 0;
1002
 
        else if (rec->opts.freq) {
1003
 
                rec->opts.default_interval = rec->opts.freq;
1004
 
        } else {
1005
 
                ui__error("frequency and count are zero, aborting\n");
 
962
        if (perf_record_opts__config(&rec->opts)) {
1006
963
                err = -EINVAL;
1007
964
                goto out_free_fd;
1008
965
        }