| 1 | #include <linux/perf_event.h> |
| 2 | #include <perf/evlist.h> |
| 3 | #include <perf/evsel.h> |
| 4 | #include <perf/cpumap.h> |
| 5 | #include <perf/threadmap.h> |
| 6 | #include <perf/mmap.h> |
| 7 | #include <perf/core.h> |
| 8 | #include <perf/event.h> |
| 9 | #include <stdio.h> |
| 10 | #include <unistd.h> |
| 11 | |
| 12 | static int libperf_print(enum libperf_print_level level, |
| 13 | const char *fmt, va_list ap) |
| 14 | { |
| 15 | return vfprintf(stderr, format: fmt, arg: ap); |
| 16 | } |
| 17 | |
| 18 | union u64_swap { |
| 19 | __u64 val64; |
| 20 | __u32 val32[2]; |
| 21 | }; |
| 22 | |
| 23 | int main(int argc, char **argv) |
| 24 | { |
| 25 | struct perf_evlist *evlist; |
| 26 | struct perf_evsel *evsel; |
| 27 | struct perf_mmap *map; |
| 28 | struct perf_cpu_map *cpus; |
| 29 | struct perf_event_attr attr = { |
| 30 | .type = PERF_TYPE_HARDWARE, |
| 31 | .config = PERF_COUNT_HW_CPU_CYCLES, |
| 32 | .disabled = 1, |
| 33 | .freq = 1, |
| 34 | .sample_freq = 10, |
| 35 | .sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_CPU|PERF_SAMPLE_PERIOD, |
| 36 | }; |
| 37 | int err = -1; |
| 38 | union perf_event *event; |
| 39 | |
| 40 | libperf_init(libperf_print); |
| 41 | |
| 42 | cpus = perf_cpu_map__new_online_cpus(); |
| 43 | if (!cpus) { |
| 44 | fprintf(stderr, format: "failed to create cpus\n" ); |
| 45 | return -1; |
| 46 | } |
| 47 | |
| 48 | evlist = perf_evlist__new(); |
| 49 | if (!evlist) { |
| 50 | fprintf(stderr, format: "failed to create evlist\n" ); |
| 51 | goto out_cpus; |
| 52 | } |
| 53 | |
| 54 | evsel = perf_evsel__new(&attr); |
| 55 | if (!evsel) { |
| 56 | fprintf(stderr, format: "failed to create cycles\n" ); |
| 57 | goto out_cpus; |
| 58 | } |
| 59 | |
| 60 | perf_evlist__add(evlist, evsel); |
| 61 | |
| 62 | perf_evlist__set_maps(evlist, cpus, NULL); |
| 63 | |
| 64 | err = perf_evlist__open(evlist); |
| 65 | if (err) { |
| 66 | fprintf(stderr, format: "failed to open evlist\n" ); |
| 67 | goto out_evlist; |
| 68 | } |
| 69 | |
| 70 | err = perf_evlist__mmap(evlist, 4); |
| 71 | if (err) { |
| 72 | fprintf(stderr, format: "failed to mmap evlist\n" ); |
| 73 | goto out_evlist; |
| 74 | } |
| 75 | |
| 76 | perf_evlist__enable(evlist); |
| 77 | sleep(seconds: 3); |
| 78 | perf_evlist__disable(evlist); |
| 79 | |
| 80 | perf_evlist__for_each_mmap(evlist, map, false) { |
| 81 | if (perf_mmap__read_init(map) < 0) |
| 82 | continue; |
| 83 | |
| 84 | while ((event = perf_mmap__read_event(map)) != NULL) { |
| 85 | int cpu, pid, tid; |
| 86 | __u64 ip, period, *array; |
| 87 | union u64_swap u; |
| 88 | |
| 89 | array = event->sample.array; |
| 90 | |
| 91 | ip = *array; |
| 92 | array++; |
| 93 | |
| 94 | u.val64 = *array; |
| 95 | pid = u.val32[0]; |
| 96 | tid = u.val32[1]; |
| 97 | array++; |
| 98 | |
| 99 | u.val64 = *array; |
| 100 | cpu = u.val32[0]; |
| 101 | array++; |
| 102 | |
| 103 | period = *array; |
| 104 | |
| 105 | fprintf(stdout, format: "cpu %3d, pid %6d, tid %6d, ip %20llx, period %20llu\n" , |
| 106 | cpu, pid, tid, ip, period); |
| 107 | |
| 108 | perf_mmap__consume(map); |
| 109 | } |
| 110 | |
| 111 | perf_mmap__read_done(map); |
| 112 | } |
| 113 | |
| 114 | out_evlist: |
| 115 | perf_evlist__delete(evlist); |
| 116 | out_cpus: |
| 117 | perf_cpu_map__put(cpus); |
| 118 | return err; |
| 119 | } |
| 120 | |