.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * builtin-timechart.c - make an svg timechart of system activity |
---|
3 | 4 | * |
---|
.. | .. |
---|
5 | 6 | * |
---|
6 | 7 | * Authors: |
---|
7 | 8 | * Arjan van de Ven <arjan@linux.intel.com> |
---|
8 | | - * |
---|
9 | | - * This program is free software; you can redistribute it and/or |
---|
10 | | - * modify it under the terms of the GNU General Public License |
---|
11 | | - * as published by the Free Software Foundation; version 2 |
---|
12 | | - * of the License. |
---|
13 | 9 | */ |
---|
14 | 10 | |
---|
15 | 11 | #include <errno.h> |
---|
16 | 12 | #include <inttypes.h> |
---|
17 | | -#include <traceevent/event-parse.h> |
---|
18 | 13 | |
---|
19 | 14 | #include "builtin.h" |
---|
20 | | - |
---|
21 | | -#include "util/util.h" |
---|
22 | | - |
---|
23 | 15 | #include "util/color.h" |
---|
24 | 16 | #include <linux/list.h> |
---|
25 | | -#include "util/cache.h" |
---|
26 | | -#include "util/evlist.h" |
---|
| 17 | +#include "util/evlist.h" // for struct evsel_str_handler |
---|
27 | 18 | #include "util/evsel.h" |
---|
28 | 19 | #include <linux/kernel.h> |
---|
29 | 20 | #include <linux/rbtree.h> |
---|
30 | 21 | #include <linux/time64.h> |
---|
| 22 | +#include <linux/zalloc.h> |
---|
31 | 23 | #include "util/symbol.h" |
---|
32 | 24 | #include "util/thread.h" |
---|
33 | 25 | #include "util/callchain.h" |
---|
34 | 26 | |
---|
35 | 27 | #include "perf.h" |
---|
36 | 28 | #include "util/header.h" |
---|
| 29 | +#include <subcmd/pager.h> |
---|
37 | 30 | #include <subcmd/parse-options.h> |
---|
38 | 31 | #include "util/parse-events.h" |
---|
39 | 32 | #include "util/event.h" |
---|
.. | .. |
---|
42 | 35 | #include "util/tool.h" |
---|
43 | 36 | #include "util/data.h" |
---|
44 | 37 | #include "util/debug.h" |
---|
| 38 | +#include <linux/err.h> |
---|
45 | 39 | |
---|
46 | 40 | #ifdef LACKS_OPEN_MEMSTREAM_PROTOTYPE |
---|
47 | 41 | FILE *open_memstream(char **ptr, size_t *sizeloc); |
---|
.. | .. |
---|
134 | 128 | struct sample_wrapper *next; |
---|
135 | 129 | |
---|
136 | 130 | u64 timestamp; |
---|
137 | | - unsigned char data[0]; |
---|
| 131 | + unsigned char data[]; |
---|
138 | 132 | }; |
---|
139 | 133 | |
---|
140 | 134 | #define TYPE_NONE 0 |
---|
.. | .. |
---|
551 | 545 | } |
---|
552 | 546 | |
---|
553 | 547 | typedef int (*tracepoint_handler)(struct timechart *tchart, |
---|
554 | | - struct perf_evsel *evsel, |
---|
| 548 | + struct evsel *evsel, |
---|
555 | 549 | struct perf_sample *sample, |
---|
556 | 550 | const char *backtrace); |
---|
557 | 551 | |
---|
558 | 552 | static int process_sample_event(struct perf_tool *tool, |
---|
559 | 553 | union perf_event *event, |
---|
560 | 554 | struct perf_sample *sample, |
---|
561 | | - struct perf_evsel *evsel, |
---|
| 555 | + struct evsel *evsel, |
---|
562 | 556 | struct machine *machine) |
---|
563 | 557 | { |
---|
564 | 558 | struct timechart *tchart = container_of(tool, struct timechart, tool); |
---|
565 | 559 | |
---|
566 | | - if (evsel->attr.sample_type & PERF_SAMPLE_TIME) { |
---|
| 560 | + if (evsel->core.attr.sample_type & PERF_SAMPLE_TIME) { |
---|
567 | 561 | if (!tchart->first_time || tchart->first_time > sample->time) |
---|
568 | 562 | tchart->first_time = sample->time; |
---|
569 | 563 | if (tchart->last_time < sample->time) |
---|
.. | .. |
---|
581 | 575 | |
---|
582 | 576 | static int |
---|
583 | 577 | process_sample_cpu_idle(struct timechart *tchart __maybe_unused, |
---|
584 | | - struct perf_evsel *evsel, |
---|
| 578 | + struct evsel *evsel, |
---|
585 | 579 | struct perf_sample *sample, |
---|
586 | 580 | const char *backtrace __maybe_unused) |
---|
587 | 581 | { |
---|
588 | | - u32 state = perf_evsel__intval(evsel, sample, "state"); |
---|
589 | | - u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id"); |
---|
| 582 | + u32 state = evsel__intval(evsel, sample, "state"); |
---|
| 583 | + u32 cpu_id = evsel__intval(evsel, sample, "cpu_id"); |
---|
590 | 584 | |
---|
591 | 585 | if (state == (u32)PWR_EVENT_EXIT) |
---|
592 | 586 | c_state_end(tchart, cpu_id, sample->time); |
---|
.. | .. |
---|
597 | 591 | |
---|
598 | 592 | static int |
---|
599 | 593 | process_sample_cpu_frequency(struct timechart *tchart, |
---|
600 | | - struct perf_evsel *evsel, |
---|
| 594 | + struct evsel *evsel, |
---|
601 | 595 | struct perf_sample *sample, |
---|
602 | 596 | const char *backtrace __maybe_unused) |
---|
603 | 597 | { |
---|
604 | | - u32 state = perf_evsel__intval(evsel, sample, "state"); |
---|
605 | | - u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id"); |
---|
| 598 | + u32 state = evsel__intval(evsel, sample, "state"); |
---|
| 599 | + u32 cpu_id = evsel__intval(evsel, sample, "cpu_id"); |
---|
606 | 600 | |
---|
607 | 601 | p_state_change(tchart, cpu_id, sample->time, state); |
---|
608 | 602 | return 0; |
---|
.. | .. |
---|
610 | 604 | |
---|
611 | 605 | static int |
---|
612 | 606 | process_sample_sched_wakeup(struct timechart *tchart, |
---|
613 | | - struct perf_evsel *evsel, |
---|
| 607 | + struct evsel *evsel, |
---|
614 | 608 | struct perf_sample *sample, |
---|
615 | 609 | const char *backtrace) |
---|
616 | 610 | { |
---|
617 | | - u8 flags = perf_evsel__intval(evsel, sample, "common_flags"); |
---|
618 | | - int waker = perf_evsel__intval(evsel, sample, "common_pid"); |
---|
619 | | - int wakee = perf_evsel__intval(evsel, sample, "pid"); |
---|
| 611 | + u8 flags = evsel__intval(evsel, sample, "common_flags"); |
---|
| 612 | + int waker = evsel__intval(evsel, sample, "common_pid"); |
---|
| 613 | + int wakee = evsel__intval(evsel, sample, "pid"); |
---|
620 | 614 | |
---|
621 | 615 | sched_wakeup(tchart, sample->cpu, sample->time, waker, wakee, flags, backtrace); |
---|
622 | 616 | return 0; |
---|
.. | .. |
---|
624 | 618 | |
---|
625 | 619 | static int |
---|
626 | 620 | process_sample_sched_switch(struct timechart *tchart, |
---|
627 | | - struct perf_evsel *evsel, |
---|
| 621 | + struct evsel *evsel, |
---|
628 | 622 | struct perf_sample *sample, |
---|
629 | 623 | const char *backtrace) |
---|
630 | 624 | { |
---|
631 | | - int prev_pid = perf_evsel__intval(evsel, sample, "prev_pid"); |
---|
632 | | - int next_pid = perf_evsel__intval(evsel, sample, "next_pid"); |
---|
633 | | - u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state"); |
---|
| 625 | + int prev_pid = evsel__intval(evsel, sample, "prev_pid"); |
---|
| 626 | + int next_pid = evsel__intval(evsel, sample, "next_pid"); |
---|
| 627 | + u64 prev_state = evsel__intval(evsel, sample, "prev_state"); |
---|
634 | 628 | |
---|
635 | 629 | sched_switch(tchart, sample->cpu, sample->time, prev_pid, next_pid, |
---|
636 | 630 | prev_state, backtrace); |
---|
.. | .. |
---|
640 | 634 | #ifdef SUPPORT_OLD_POWER_EVENTS |
---|
641 | 635 | static int |
---|
642 | 636 | process_sample_power_start(struct timechart *tchart __maybe_unused, |
---|
643 | | - struct perf_evsel *evsel, |
---|
| 637 | + struct evsel *evsel, |
---|
644 | 638 | struct perf_sample *sample, |
---|
645 | 639 | const char *backtrace __maybe_unused) |
---|
646 | 640 | { |
---|
647 | | - u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id"); |
---|
648 | | - u64 value = perf_evsel__intval(evsel, sample, "value"); |
---|
| 641 | + u64 cpu_id = evsel__intval(evsel, sample, "cpu_id"); |
---|
| 642 | + u64 value = evsel__intval(evsel, sample, "value"); |
---|
649 | 643 | |
---|
650 | 644 | c_state_start(cpu_id, sample->time, value); |
---|
651 | 645 | return 0; |
---|
.. | .. |
---|
653 | 647 | |
---|
654 | 648 | static int |
---|
655 | 649 | process_sample_power_end(struct timechart *tchart, |
---|
656 | | - struct perf_evsel *evsel __maybe_unused, |
---|
| 650 | + struct evsel *evsel __maybe_unused, |
---|
657 | 651 | struct perf_sample *sample, |
---|
658 | 652 | const char *backtrace __maybe_unused) |
---|
659 | 653 | { |
---|
.. | .. |
---|
663 | 657 | |
---|
664 | 658 | static int |
---|
665 | 659 | process_sample_power_frequency(struct timechart *tchart, |
---|
666 | | - struct perf_evsel *evsel, |
---|
| 660 | + struct evsel *evsel, |
---|
667 | 661 | struct perf_sample *sample, |
---|
668 | 662 | const char *backtrace __maybe_unused) |
---|
669 | 663 | { |
---|
670 | | - u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id"); |
---|
671 | | - u64 value = perf_evsel__intval(evsel, sample, "value"); |
---|
| 664 | + u64 cpu_id = evsel__intval(evsel, sample, "cpu_id"); |
---|
| 665 | + u64 value = evsel__intval(evsel, sample, "value"); |
---|
672 | 666 | |
---|
673 | 667 | p_state_change(tchart, cpu_id, sample->time, value); |
---|
674 | 668 | return 0; |
---|
.. | .. |
---|
846 | 840 | |
---|
847 | 841 | static int |
---|
848 | 842 | process_enter_read(struct timechart *tchart, |
---|
849 | | - struct perf_evsel *evsel, |
---|
| 843 | + struct evsel *evsel, |
---|
850 | 844 | struct perf_sample *sample) |
---|
851 | 845 | { |
---|
852 | | - long fd = perf_evsel__intval(evsel, sample, "fd"); |
---|
| 846 | + long fd = evsel__intval(evsel, sample, "fd"); |
---|
853 | 847 | return pid_begin_io_sample(tchart, sample->tid, IOTYPE_READ, |
---|
854 | 848 | sample->time, fd); |
---|
855 | 849 | } |
---|
856 | 850 | |
---|
857 | 851 | static int |
---|
858 | 852 | process_exit_read(struct timechart *tchart, |
---|
859 | | - struct perf_evsel *evsel, |
---|
| 853 | + struct evsel *evsel, |
---|
860 | 854 | struct perf_sample *sample) |
---|
861 | 855 | { |
---|
862 | | - long ret = perf_evsel__intval(evsel, sample, "ret"); |
---|
| 856 | + long ret = evsel__intval(evsel, sample, "ret"); |
---|
863 | 857 | return pid_end_io_sample(tchart, sample->tid, IOTYPE_READ, |
---|
864 | 858 | sample->time, ret); |
---|
865 | 859 | } |
---|
866 | 860 | |
---|
867 | 861 | static int |
---|
868 | 862 | process_enter_write(struct timechart *tchart, |
---|
869 | | - struct perf_evsel *evsel, |
---|
| 863 | + struct evsel *evsel, |
---|
870 | 864 | struct perf_sample *sample) |
---|
871 | 865 | { |
---|
872 | | - long fd = perf_evsel__intval(evsel, sample, "fd"); |
---|
| 866 | + long fd = evsel__intval(evsel, sample, "fd"); |
---|
873 | 867 | return pid_begin_io_sample(tchart, sample->tid, IOTYPE_WRITE, |
---|
874 | 868 | sample->time, fd); |
---|
875 | 869 | } |
---|
876 | 870 | |
---|
877 | 871 | static int |
---|
878 | 872 | process_exit_write(struct timechart *tchart, |
---|
879 | | - struct perf_evsel *evsel, |
---|
| 873 | + struct evsel *evsel, |
---|
880 | 874 | struct perf_sample *sample) |
---|
881 | 875 | { |
---|
882 | | - long ret = perf_evsel__intval(evsel, sample, "ret"); |
---|
| 876 | + long ret = evsel__intval(evsel, sample, "ret"); |
---|
883 | 877 | return pid_end_io_sample(tchart, sample->tid, IOTYPE_WRITE, |
---|
884 | 878 | sample->time, ret); |
---|
885 | 879 | } |
---|
886 | 880 | |
---|
887 | 881 | static int |
---|
888 | 882 | process_enter_sync(struct timechart *tchart, |
---|
889 | | - struct perf_evsel *evsel, |
---|
| 883 | + struct evsel *evsel, |
---|
890 | 884 | struct perf_sample *sample) |
---|
891 | 885 | { |
---|
892 | | - long fd = perf_evsel__intval(evsel, sample, "fd"); |
---|
| 886 | + long fd = evsel__intval(evsel, sample, "fd"); |
---|
893 | 887 | return pid_begin_io_sample(tchart, sample->tid, IOTYPE_SYNC, |
---|
894 | 888 | sample->time, fd); |
---|
895 | 889 | } |
---|
896 | 890 | |
---|
897 | 891 | static int |
---|
898 | 892 | process_exit_sync(struct timechart *tchart, |
---|
899 | | - struct perf_evsel *evsel, |
---|
| 893 | + struct evsel *evsel, |
---|
900 | 894 | struct perf_sample *sample) |
---|
901 | 895 | { |
---|
902 | | - long ret = perf_evsel__intval(evsel, sample, "ret"); |
---|
| 896 | + long ret = evsel__intval(evsel, sample, "ret"); |
---|
903 | 897 | return pid_end_io_sample(tchart, sample->tid, IOTYPE_SYNC, |
---|
904 | 898 | sample->time, ret); |
---|
905 | 899 | } |
---|
906 | 900 | |
---|
907 | 901 | static int |
---|
908 | 902 | process_enter_tx(struct timechart *tchart, |
---|
909 | | - struct perf_evsel *evsel, |
---|
| 903 | + struct evsel *evsel, |
---|
910 | 904 | struct perf_sample *sample) |
---|
911 | 905 | { |
---|
912 | | - long fd = perf_evsel__intval(evsel, sample, "fd"); |
---|
| 906 | + long fd = evsel__intval(evsel, sample, "fd"); |
---|
913 | 907 | return pid_begin_io_sample(tchart, sample->tid, IOTYPE_TX, |
---|
914 | 908 | sample->time, fd); |
---|
915 | 909 | } |
---|
916 | 910 | |
---|
917 | 911 | static int |
---|
918 | 912 | process_exit_tx(struct timechart *tchart, |
---|
919 | | - struct perf_evsel *evsel, |
---|
| 913 | + struct evsel *evsel, |
---|
920 | 914 | struct perf_sample *sample) |
---|
921 | 915 | { |
---|
922 | | - long ret = perf_evsel__intval(evsel, sample, "ret"); |
---|
| 916 | + long ret = evsel__intval(evsel, sample, "ret"); |
---|
923 | 917 | return pid_end_io_sample(tchart, sample->tid, IOTYPE_TX, |
---|
924 | 918 | sample->time, ret); |
---|
925 | 919 | } |
---|
926 | 920 | |
---|
927 | 921 | static int |
---|
928 | 922 | process_enter_rx(struct timechart *tchart, |
---|
929 | | - struct perf_evsel *evsel, |
---|
| 923 | + struct evsel *evsel, |
---|
930 | 924 | struct perf_sample *sample) |
---|
931 | 925 | { |
---|
932 | | - long fd = perf_evsel__intval(evsel, sample, "fd"); |
---|
| 926 | + long fd = evsel__intval(evsel, sample, "fd"); |
---|
933 | 927 | return pid_begin_io_sample(tchart, sample->tid, IOTYPE_RX, |
---|
934 | 928 | sample->time, fd); |
---|
935 | 929 | } |
---|
936 | 930 | |
---|
937 | 931 | static int |
---|
938 | 932 | process_exit_rx(struct timechart *tchart, |
---|
939 | | - struct perf_evsel *evsel, |
---|
| 933 | + struct evsel *evsel, |
---|
940 | 934 | struct perf_sample *sample) |
---|
941 | 935 | { |
---|
942 | | - long ret = perf_evsel__intval(evsel, sample, "ret"); |
---|
| 936 | + long ret = evsel__intval(evsel, sample, "ret"); |
---|
943 | 937 | return pid_end_io_sample(tchart, sample->tid, IOTYPE_RX, |
---|
944 | 938 | sample->time, ret); |
---|
945 | 939 | } |
---|
946 | 940 | |
---|
947 | 941 | static int |
---|
948 | 942 | process_enter_poll(struct timechart *tchart, |
---|
949 | | - struct perf_evsel *evsel, |
---|
| 943 | + struct evsel *evsel, |
---|
950 | 944 | struct perf_sample *sample) |
---|
951 | 945 | { |
---|
952 | | - long fd = perf_evsel__intval(evsel, sample, "fd"); |
---|
| 946 | + long fd = evsel__intval(evsel, sample, "fd"); |
---|
953 | 947 | return pid_begin_io_sample(tchart, sample->tid, IOTYPE_POLL, |
---|
954 | 948 | sample->time, fd); |
---|
955 | 949 | } |
---|
956 | 950 | |
---|
957 | 951 | static int |
---|
958 | 952 | process_exit_poll(struct timechart *tchart, |
---|
959 | | - struct perf_evsel *evsel, |
---|
| 953 | + struct evsel *evsel, |
---|
960 | 954 | struct perf_sample *sample) |
---|
961 | 955 | { |
---|
962 | | - long ret = perf_evsel__intval(evsel, sample, "ret"); |
---|
| 956 | + long ret = evsel__intval(evsel, sample, "ret"); |
---|
963 | 957 | return pid_end_io_sample(tchart, sample->tid, IOTYPE_POLL, |
---|
964 | 958 | sample->time, ret); |
---|
965 | 959 | } |
---|
.. | .. |
---|
1524 | 1518 | if (!tchart->topology) |
---|
1525 | 1519 | break; |
---|
1526 | 1520 | |
---|
1527 | | - if (svg_build_topology_map(ph->env.sibling_cores, |
---|
1528 | | - ph->env.nr_sibling_cores, |
---|
1529 | | - ph->env.sibling_threads, |
---|
1530 | | - ph->env.nr_sibling_threads)) |
---|
| 1521 | + if (svg_build_topology_map(&ph->env)) |
---|
1531 | 1522 | fprintf(stderr, "problem building topology\n"); |
---|
1532 | 1523 | break; |
---|
1533 | 1524 | |
---|
.. | .. |
---|
1540 | 1531 | |
---|
1541 | 1532 | static int __cmd_timechart(struct timechart *tchart, const char *output_name) |
---|
1542 | 1533 | { |
---|
1543 | | - const struct perf_evsel_str_handler power_tracepoints[] = { |
---|
| 1534 | + const struct evsel_str_handler power_tracepoints[] = { |
---|
1544 | 1535 | { "power:cpu_idle", process_sample_cpu_idle }, |
---|
1545 | 1536 | { "power:cpu_frequency", process_sample_cpu_frequency }, |
---|
1546 | 1537 | { "sched:sched_wakeup", process_sample_sched_wakeup }, |
---|
.. | .. |
---|
1602 | 1593 | { "syscalls:sys_exit_select", process_exit_poll }, |
---|
1603 | 1594 | }; |
---|
1604 | 1595 | struct perf_data data = { |
---|
1605 | | - .file = { |
---|
1606 | | - .path = input_name, |
---|
1607 | | - }, |
---|
1608 | | - .mode = PERF_DATA_MODE_READ, |
---|
1609 | | - .force = tchart->force, |
---|
| 1596 | + .path = input_name, |
---|
| 1597 | + .mode = PERF_DATA_MODE_READ, |
---|
| 1598 | + .force = tchart->force, |
---|
1610 | 1599 | }; |
---|
1611 | 1600 | |
---|
1612 | 1601 | struct perf_session *session = perf_session__new(&data, false, |
---|
1613 | 1602 | &tchart->tool); |
---|
1614 | 1603 | int ret = -EINVAL; |
---|
1615 | 1604 | |
---|
1616 | | - if (session == NULL) |
---|
1617 | | - return -1; |
---|
| 1605 | + if (IS_ERR(session)) |
---|
| 1606 | + return PTR_ERR(session); |
---|
1618 | 1607 | |
---|
1619 | 1608 | symbol__init(&session->header.env); |
---|
1620 | 1609 | |
---|