1 #include "evlist.h" 2 #include "evsel.h" 3 #include "cpumap.h" 4 #include "parse-events.h" 5 6 typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel); 7 8 static int perf_do_probe_api(setup_probe_fn_t fn, int cpu, const char *str) 9 { 10 struct perf_evlist *evlist; 11 struct perf_evsel *evsel; 12 int err = -EAGAIN, fd; 13 14 evlist = perf_evlist__new(); 15 if (!evlist) 16 return -ENOMEM; 17 18 if (parse_events(evlist, str)) 19 goto out_delete; 20 21 evsel = perf_evlist__first(evlist); 22 23 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0); 24 if (fd < 0) 25 goto out_delete; 26 close(fd); 27 28 fn(evsel); 29 30 fd = sys_perf_event_open(&evsel->attr, -1, cpu, -1, 0); 31 if (fd < 0) { 32 if (errno == EINVAL) 33 err = -EINVAL; 34 goto out_delete; 35 } 36 close(fd); 37 err = 0; 38 39 out_delete: 40 perf_evlist__delete(evlist); 41 return err; 42 } 43 44 static bool perf_probe_api(setup_probe_fn_t fn) 45 { 46 const char *try[] = {"cycles:u", "instructions:u", "cpu-clock", NULL}; 47 struct cpu_map *cpus; 48 int cpu, ret, i = 0; 49 50 cpus = cpu_map__new(NULL); 51 if (!cpus) 52 return false; 53 cpu = cpus->map[0]; 54 cpu_map__delete(cpus); 55 56 do { 57 ret = perf_do_probe_api(fn, cpu, try[i++]); 58 if (!ret) 59 return true; 60 } while (ret == -EAGAIN && try[i]); 61 62 return false; 63 } 64 65 static void perf_probe_sample_identifier(struct perf_evsel *evsel) 66 { 67 evsel->attr.sample_type |= PERF_SAMPLE_IDENTIFIER; 68 } 69 70 bool perf_can_sample_identifier(void) 71 { 72 return perf_probe_api(perf_probe_sample_identifier); 73 } 74 75 void perf_evlist__config(struct perf_evlist *evlist, 76 struct perf_record_opts *opts) 77 { 78 struct perf_evsel *evsel; 79 bool use_sample_identifier = false; 80 81 /* 82 * Set the evsel leader links before we configure attributes, 83 * since some might depend on this info. 84 */ 85 if (opts->group) 86 perf_evlist__set_leader(evlist); 87 88 if (evlist->cpus->map[0] < 0) 89 opts->no_inherit = true; 90 91 list_for_each_entry(evsel, &evlist->entries, node) 92 perf_evsel__config(evsel, opts); 93 94 if (evlist->nr_entries > 1) { 95 struct perf_evsel *first = perf_evlist__first(evlist); 96 97 list_for_each_entry(evsel, &evlist->entries, node) { 98 if (evsel->attr.sample_type == first->attr.sample_type) 99 continue; 100 use_sample_identifier = perf_can_sample_identifier(); 101 break; 102 } 103 list_for_each_entry(evsel, &evlist->entries, node) 104 perf_evsel__set_sample_id(evsel, use_sample_identifier); 105 } 106 107 perf_evlist__set_id_pos(evlist); 108 } 109