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

« back to all changes in this revision

Viewing changes to tools/perf/builtin-lock.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:
15
15
#include "util/debug.h"
16
16
#include "util/session.h"
17
17
#include "util/tool.h"
 
18
#include "util/data.h"
18
19
 
19
20
#include <sys/types.h>
20
21
#include <sys/prctl.h>
56
57
 
57
58
        unsigned int            nr_readlock;
58
59
        unsigned int            nr_trylock;
 
60
 
59
61
        /* these times are in nano sec. */
 
62
        u64                     avg_wait_time;
60
63
        u64                     wait_time_total;
61
64
        u64                     wait_time_min;
62
65
        u64                     wait_time_max;
208
211
 
209
212
SINGLE_KEY(nr_acquired)
210
213
SINGLE_KEY(nr_contended)
 
214
SINGLE_KEY(avg_wait_time)
211
215
SINGLE_KEY(wait_time_total)
212
216
SINGLE_KEY(wait_time_max)
213
217
 
244
248
struct lock_key keys[] = {
245
249
        DEF_KEY_LOCK(acquired, nr_acquired),
246
250
        DEF_KEY_LOCK(contended, nr_contended),
 
251
        DEF_KEY_LOCK(avg_wait, avg_wait_time),
247
252
        DEF_KEY_LOCK(wait_total, wait_time_total),
248
253
        DEF_KEY_LOCK(wait_min, wait_time_min),
249
254
        DEF_KEY_LOCK(wait_max, wait_time_max),
321
326
 
322
327
        new->addr = addr;
323
328
        new->name = zalloc(sizeof(char) * strlen(name) + 1);
324
 
        if (!new->name)
 
329
        if (!new->name) {
 
330
                free(new);
325
331
                goto alloc_failed;
 
332
        }
 
333
 
326
334
        strcpy(new->name, name);
327
 
 
328
335
        new->wait_time_min = ULLONG_MAX;
329
336
 
330
337
        list_add(&new->hash_entry, entry);
400
407
 
401
408
        ls = lock_stat_findnew(addr, name);
402
409
        if (!ls)
403
 
                return -1;
 
410
                return -ENOMEM;
404
411
        if (ls->discard)
405
412
                return 0;
406
413
 
407
414
        ts = thread_stat_findnew(sample->tid);
408
415
        if (!ts)
409
 
                return -1;
 
416
                return -ENOMEM;
410
417
 
411
418
        seq = get_seq(ts, addr);
412
419
        if (!seq)
413
 
                return -1;
 
420
                return -ENOMEM;
414
421
 
415
422
        switch (seq->state) {
416
423
        case SEQ_STATE_UNINITIALIZED:
446
453
                list_del(&seq->list);
447
454
                free(seq);
448
455
                goto end;
449
 
                break;
450
456
        default:
451
457
                BUG_ON("Unknown state of lock sequence found!\n");
452
458
                break;
473
479
 
474
480
        ls = lock_stat_findnew(addr, name);
475
481
        if (!ls)
476
 
                return -1;
 
482
                return -ENOMEM;
477
483
        if (ls->discard)
478
484
                return 0;
479
485
 
480
486
        ts = thread_stat_findnew(sample->tid);
481
487
        if (!ts)
482
 
                return -1;
 
488
                return -ENOMEM;
483
489
 
484
490
        seq = get_seq(ts, addr);
485
491
        if (!seq)
486
 
                return -1;
 
492
                return -ENOMEM;
487
493
 
488
494
        switch (seq->state) {
489
495
        case SEQ_STATE_UNINITIALIZED:
508
514
                list_del(&seq->list);
509
515
                free(seq);
510
516
                goto end;
511
 
                break;
512
 
 
513
517
        default:
514
518
                BUG_ON("Unknown state of lock sequence found!\n");
515
519
                break;
517
521
 
518
522
        seq->state = SEQ_STATE_ACQUIRED;
519
523
        ls->nr_acquired++;
 
524
        ls->avg_wait_time = ls->nr_contended ? ls->wait_time_total/ls->nr_contended : 0;
520
525
        seq->prev_event_time = sample->time;
521
526
end:
522
527
        return 0;
536
541
 
537
542
        ls = lock_stat_findnew(addr, name);
538
543
        if (!ls)
539
 
                return -1;
 
544
                return -ENOMEM;
540
545
        if (ls->discard)
541
546
                return 0;
542
547
 
543
548
        ts = thread_stat_findnew(sample->tid);
544
549
        if (!ts)
545
 
                return -1;
 
550
                return -ENOMEM;
546
551
 
547
552
        seq = get_seq(ts, addr);
548
553
        if (!seq)
549
 
                return -1;
 
554
                return -ENOMEM;
550
555
 
551
556
        switch (seq->state) {
552
557
        case SEQ_STATE_UNINITIALIZED:
564
569
                list_del(&seq->list);
565
570
                free(seq);
566
571
                goto end;
567
 
                break;
568
572
        default:
569
573
                BUG_ON("Unknown state of lock sequence found!\n");
570
574
                break;
572
576
 
573
577
        seq->state = SEQ_STATE_CONTENDED;
574
578
        ls->nr_contended++;
 
579
        ls->avg_wait_time = ls->wait_time_total/ls->nr_contended;
575
580
        seq->prev_event_time = sample->time;
576
581
end:
577
582
        return 0;
591
596
 
592
597
        ls = lock_stat_findnew(addr, name);
593
598
        if (!ls)
594
 
                return -1;
 
599
                return -ENOMEM;
595
600
        if (ls->discard)
596
601
                return 0;
597
602
 
598
603
        ts = thread_stat_findnew(sample->tid);
599
604
        if (!ts)
600
 
                return -1;
 
605
                return -ENOMEM;
601
606
 
602
607
        seq = get_seq(ts, addr);
603
608
        if (!seq)
604
 
                return -1;
 
609
                return -ENOMEM;
605
610
 
606
611
        switch (seq->state) {
607
612
        case SEQ_STATE_UNINITIALIZED:
608
613
                goto end;
609
 
                break;
610
614
        case SEQ_STATE_ACQUIRED:
611
615
                break;
612
616
        case SEQ_STATE_READ_ACQUIRED:
624
628
                ls->discard = 1;
625
629
                bad_hist[BROKEN_RELEASE]++;
626
630
                goto free_seq;
627
 
                break;
628
631
        default:
629
632
                BUG_ON("Unknown state of lock sequence found!\n");
630
633
                break;
690
693
 
691
694
        pr_info("\n=== output for debug===\n\n");
692
695
        pr_info("bad: %d, total: %d\n", bad, total);
693
 
        pr_info("bad rate: %f %%\n", (double)bad / (double)total * 100);
 
696
        pr_info("bad rate: %.2f %%\n", (double)bad / (double)total * 100);
694
697
        pr_info("histogram of events caused bad sequence\n");
695
698
        for (i = 0; i < BROKEN_MAX; i++)
696
699
                pr_info(" %10s: %d\n", name[i], bad_hist[i]);
707
710
        pr_info("%10s ", "acquired");
708
711
        pr_info("%10s ", "contended");
709
712
 
 
713
        pr_info("%15s ", "avg wait (ns)");
710
714
        pr_info("%15s ", "total wait (ns)");
711
715
        pr_info("%15s ", "max wait (ns)");
712
716
        pr_info("%15s ", "min wait (ns)");
738
742
                pr_info("%10u ", st->nr_acquired);
739
743
                pr_info("%10u ", st->nr_contended);
740
744
 
 
745
                pr_info("%15" PRIu64 " ", st->avg_wait_time);
741
746
                pr_info("%15" PRIu64 " ", st->wait_time_total);
742
747
                pr_info("%15" PRIu64 " ", st->wait_time_max);
743
748
                pr_info("%15" PRIu64 " ", st->wait_time_min == ULLONG_MAX ?
762
767
        while (node) {
763
768
                st = container_of(node, struct thread_stat, rb);
764
769
                t = perf_session__findnew(session, st->tid);
765
 
                pr_info("%10d: %s\n", st->tid, t->comm);
 
770
                pr_info("%10d: %s\n", st->tid, thread__comm_str(t));
766
771
                node = rb_next(node);
767
772
        };
768
773
}
814
819
                return -1;
815
820
        }
816
821
 
817
 
        if (evsel->handler.func != NULL) {
818
 
                tracepoint_handler f = evsel->handler.func;
 
822
        if (evsel->handler != NULL) {
 
823
                tracepoint_handler f = evsel->handler;
819
824
                return f(evsel, sample);
820
825
        }
821
826
 
822
827
        return 0;
823
828
}
824
829
 
 
830
static void sort_result(void)
 
831
{
 
832
        unsigned int i;
 
833
        struct lock_stat *st;
 
834
 
 
835
        for (i = 0; i < LOCKHASH_SIZE; i++) {
 
836
                list_for_each_entry(st, &lockhash_table[i], hash_entry) {
 
837
                        insert_to_result(st, compare);
 
838
                }
 
839
        }
 
840
}
 
841
 
825
842
static const struct perf_evsel_str_handler lock_tracepoints[] = {
826
843
        { "lock:lock_acquire",   perf_evsel__process_lock_acquire,   }, /* CONFIG_LOCKDEP */
827
844
        { "lock:lock_acquired",  perf_evsel__process_lock_acquired,  }, /* CONFIG_LOCKDEP, CONFIG_LOCK_STAT */
829
846
        { "lock:lock_release",   perf_evsel__process_lock_release,   }, /* CONFIG_LOCKDEP */
830
847
};
831
848
 
832
 
static int read_events(void)
 
849
static int __cmd_report(bool display_info)
833
850
{
 
851
        int err = -EINVAL;
834
852
        struct perf_tool eops = {
835
853
                .sample          = process_sample_event,
836
854
                .comm            = perf_event__process_comm,
837
855
                .ordered_samples = true,
838
856
        };
839
 
        session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
 
857
        struct perf_data_file file = {
 
858
                .path = input_name,
 
859
                .mode = PERF_DATA_MODE_READ,
 
860
        };
 
861
 
 
862
        session = perf_session__new(&file, false, &eops);
840
863
        if (!session) {
841
864
                pr_err("Initializing perf session failed\n");
842
 
                return -1;
 
865
                return -ENOMEM;
843
866
        }
844
867
 
 
868
        if (!perf_session__has_traces(session, "lock record"))
 
869
                goto out_delete;
 
870
 
845
871
        if (perf_session__set_tracepoints_handlers(session, lock_tracepoints)) {
846
872
                pr_err("Initializing perf session tracepoint handlers failed\n");
847
 
                return -1;
848
 
        }
849
 
 
850
 
        return perf_session__process_events(session, &eops);
851
 
}
852
 
 
853
 
static void sort_result(void)
854
 
{
855
 
        unsigned int i;
856
 
        struct lock_stat *st;
857
 
 
858
 
        for (i = 0; i < LOCKHASH_SIZE; i++) {
859
 
                list_for_each_entry(st, &lockhash_table[i], hash_entry) {
860
 
                        insert_to_result(st, compare);
861
 
                }
862
 
        }
863
 
}
864
 
 
865
 
static int __cmd_report(void)
866
 
{
 
873
                goto out_delete;
 
874
        }
 
875
 
 
876
        if (select_key())
 
877
                goto out_delete;
 
878
 
 
879
        err = perf_session__process_events(session, &eops);
 
880
        if (err)
 
881
                goto out_delete;
 
882
 
867
883
        setup_pager();
868
 
 
869
 
        if ((select_key() != 0) ||
870
 
            (read_events() != 0))
871
 
                return -1;
872
 
 
873
 
        sort_result();
874
 
        print_result();
875
 
 
876
 
        return 0;
 
884
        if (display_info) /* used for info subcommand */
 
885
                err = dump_info();
 
886
        else {
 
887
                sort_result();
 
888
                print_result();
 
889
        }
 
890
 
 
891
out_delete:
 
892
        perf_session__delete(session);
 
893
        return err;
877
894
}
878
895
 
879
896
static int __cmd_record(int argc, const char **argv)
881
898
        const char *record_args[] = {
882
899
                "record", "-R", "-m", "1024", "-c", "1",
883
900
        };
884
 
        unsigned int rec_argc, i, j;
 
901
        unsigned int rec_argc, i, j, ret;
885
902
        const char **rec_argv;
886
903
 
887
904
        for (i = 0; i < ARRAY_SIZE(lock_tracepoints); i++) {
898
915
        rec_argc += 2 * ARRAY_SIZE(lock_tracepoints);
899
916
 
900
917
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
901
 
        if (rec_argv == NULL)
 
918
        if (!rec_argv)
902
919
                return -ENOMEM;
903
920
 
904
921
        for (i = 0; i < ARRAY_SIZE(record_args); i++)
914
931
 
915
932
        BUG_ON(i != rec_argc);
916
933
 
917
 
        return cmd_record(i, rec_argv, NULL);
 
934
        ret = cmd_record(i, rec_argv, NULL);
 
935
        free(rec_argv);
 
936
        return ret;
918
937
}
919
938
 
920
939
int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
934
953
        };
935
954
        const struct option report_options[] = {
936
955
        OPT_STRING('k', "key", &sort_key, "acquired",
937
 
                    "key for sorting (acquired / contended / wait_total / wait_max / wait_min)"),
 
956
                    "key for sorting (acquired / contended / avg_wait / wait_total / wait_max / wait_min)"),
938
957
        /* TODO: type */
939
958
        OPT_END()
940
959
        };
972
991
                        if (argc)
973
992
                                usage_with_options(report_usage, report_options);
974
993
                }
975
 
                __cmd_report();
 
994
                rc = __cmd_report(false);
976
995
        } else if (!strcmp(argv[0], "script")) {
977
996
                /* Aliased to 'perf script' */
978
997
                return cmd_script(argc, argv, prefix);
985
1004
                }
986
1005
                /* recycling report_lock_ops */
987
1006
                trace_handler = &report_lock_ops;
988
 
                setup_pager();
989
 
                if (read_events() != 0)
990
 
                        rc = -1;
991
 
                else
992
 
                        rc = dump_info();
 
1007
                rc = __cmd_report(true);
993
1008
        } else {
994
1009
                usage_with_options(lock_usage, lock_options);
995
1010
        }