diff options
| author | Ingo Molnar <mingo@elte.hu> | 2011-05-07 04:51:38 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2011-05-07 04:51:48 -0400 |
| commit | 4cb1f43ce8c72ee453c00fcb9f6ee9c4ebd03f98 (patch) | |
| tree | 15e64f192b54ea01fd640d69eed0cabed2baaaa9 /tools | |
| parent | 9de4966a4d218f29c68e96e8e7b4d2840dedec79 (diff) | |
| parent | 0ee5623f9a6e52df90a78bd21179f8ab370e102e (diff) | |
Merge commit 'v2.6.39-rc6' into x86/cleanups
Merge reason: move to a (much) newer upstream base.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools')
39 files changed, 384 insertions, 198 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 158c30e8210c..207dee5c5b16 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
| @@ -165,8 +165,12 @@ grep-libs = $(filter -l%,$(1)) | |||
| 165 | strip-libs = $(filter-out -l%,$(1)) | 165 | strip-libs = $(filter-out -l%,$(1)) |
| 166 | 166 | ||
| 167 | $(OUTPUT)python/perf.so: $(PYRF_OBJS) | 167 | $(OUTPUT)python/perf.so: $(PYRF_OBJS) |
| 168 | $(QUIET_GEN)python util/setup.py --quiet build_ext --build-lib='$(OUTPUT)python' \ | 168 | $(QUIET_GEN)( \ |
| 169 | --build-temp='$(OUTPUT)python/temp' | 169 | export CFLAGS="$(BASIC_CFLAGS)"; \ |
| 170 | python util/setup.py --quiet build_ext --build-lib='$(OUTPUT)python' \ | ||
| 171 | --build-temp='$(OUTPUT)python/temp' \ | ||
| 172 | ) | ||
| 173 | |||
| 170 | # | 174 | # |
| 171 | # No Perl scripts right now: | 175 | # No Perl scripts right now: |
| 172 | # | 176 | # |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 695de4b5ae63..e18eb7ed30ae 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
| @@ -42,9 +42,9 @@ static const char *sym_hist_filter; | |||
| 42 | 42 | ||
| 43 | static int perf_evlist__add_sample(struct perf_evlist *evlist, | 43 | static int perf_evlist__add_sample(struct perf_evlist *evlist, |
| 44 | struct perf_sample *sample, | 44 | struct perf_sample *sample, |
| 45 | struct perf_evsel *evsel, | ||
| 45 | struct addr_location *al) | 46 | struct addr_location *al) |
| 46 | { | 47 | { |
| 47 | struct perf_evsel *evsel; | ||
| 48 | struct hist_entry *he; | 48 | struct hist_entry *he; |
| 49 | int ret; | 49 | int ret; |
| 50 | 50 | ||
| @@ -59,18 +59,6 @@ static int perf_evlist__add_sample(struct perf_evlist *evlist, | |||
| 59 | return 0; | 59 | return 0; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | evsel = perf_evlist__id2evsel(evlist, sample->id); | ||
| 63 | if (evsel == NULL) { | ||
| 64 | /* | ||
| 65 | * FIXME: Propagate this back, but at least we're in a builtin, | ||
| 66 | * where exit() is allowed. ;-) | ||
| 67 | */ | ||
| 68 | ui__warning("Invalid %s file, contains samples with id not in " | ||
| 69 | "its header!\n", input_name); | ||
| 70 | exit_browser(0); | ||
| 71 | exit(1); | ||
| 72 | } | ||
| 73 | |||
| 74 | he = __hists__add_entry(&evsel->hists, al, NULL, 1); | 62 | he = __hists__add_entry(&evsel->hists, al, NULL, 1); |
| 75 | if (he == NULL) | 63 | if (he == NULL) |
| 76 | return -ENOMEM; | 64 | return -ENOMEM; |
| @@ -92,6 +80,7 @@ static int perf_evlist__add_sample(struct perf_evlist *evlist, | |||
| 92 | 80 | ||
| 93 | static int process_sample_event(union perf_event *event, | 81 | static int process_sample_event(union perf_event *event, |
| 94 | struct perf_sample *sample, | 82 | struct perf_sample *sample, |
| 83 | struct perf_evsel *evsel, | ||
| 95 | struct perf_session *session) | 84 | struct perf_session *session) |
| 96 | { | 85 | { |
| 97 | struct addr_location al; | 86 | struct addr_location al; |
| @@ -103,7 +92,8 @@ static int process_sample_event(union perf_event *event, | |||
| 103 | return -1; | 92 | return -1; |
| 104 | } | 93 | } |
| 105 | 94 | ||
| 106 | if (!al.filtered && perf_evlist__add_sample(session->evlist, sample, &al)) { | 95 | if (!al.filtered && |
| 96 | perf_evlist__add_sample(session->evlist, sample, evsel, &al)) { | ||
| 107 | pr_warning("problem incrementing symbol count, " | 97 | pr_warning("problem incrementing symbol count, " |
| 108 | "skipping event\n"); | 98 | "skipping event\n"); |
| 109 | return -1; | 99 | return -1; |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 6b7d91160ecb..e8219990f8b8 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
| @@ -32,6 +32,7 @@ static int hists__add_entry(struct hists *self, | |||
| 32 | 32 | ||
| 33 | static int diff__process_sample_event(union perf_event *event, | 33 | static int diff__process_sample_event(union perf_event *event, |
| 34 | struct perf_sample *sample, | 34 | struct perf_sample *sample, |
| 35 | struct perf_evsel *evsel __used, | ||
| 35 | struct perf_session *session) | 36 | struct perf_session *session) |
| 36 | { | 37 | { |
| 37 | struct addr_location al; | 38 | struct addr_location al; |
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index e29f04ed3396..8dfc12bb119b 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
| @@ -43,6 +43,14 @@ static int perf_event__repipe(union perf_event *event, | |||
| 43 | return perf_event__repipe_synth(event, session); | 43 | return perf_event__repipe_synth(event, session); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | static int perf_event__repipe_sample(union perf_event *event, | ||
| 47 | struct perf_sample *sample __used, | ||
| 48 | struct perf_evsel *evsel __used, | ||
| 49 | struct perf_session *session) | ||
| 50 | { | ||
| 51 | return perf_event__repipe_synth(event, session); | ||
| 52 | } | ||
| 53 | |||
| 46 | static int perf_event__repipe_mmap(union perf_event *event, | 54 | static int perf_event__repipe_mmap(union perf_event *event, |
| 47 | struct perf_sample *sample, | 55 | struct perf_sample *sample, |
| 48 | struct perf_session *session) | 56 | struct perf_session *session) |
| @@ -124,6 +132,7 @@ static int dso__inject_build_id(struct dso *self, struct perf_session *session) | |||
| 124 | 132 | ||
| 125 | static int perf_event__inject_buildid(union perf_event *event, | 133 | static int perf_event__inject_buildid(union perf_event *event, |
| 126 | struct perf_sample *sample, | 134 | struct perf_sample *sample, |
| 135 | struct perf_evsel *evsel __used, | ||
| 127 | struct perf_session *session) | 136 | struct perf_session *session) |
| 128 | { | 137 | { |
| 129 | struct addr_location al; | 138 | struct addr_location al; |
| @@ -164,7 +173,7 @@ repipe: | |||
| 164 | } | 173 | } |
| 165 | 174 | ||
| 166 | struct perf_event_ops inject_ops = { | 175 | struct perf_event_ops inject_ops = { |
| 167 | .sample = perf_event__repipe, | 176 | .sample = perf_event__repipe_sample, |
| 168 | .mmap = perf_event__repipe, | 177 | .mmap = perf_event__repipe, |
| 169 | .comm = perf_event__repipe, | 178 | .comm = perf_event__repipe, |
| 170 | .fork = perf_event__repipe, | 179 | .fork = perf_event__repipe, |
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 7f618f4e7b79..225e963df105 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
| @@ -305,6 +305,7 @@ static void process_raw_event(union perf_event *raw_event __used, void *data, | |||
| 305 | 305 | ||
| 306 | static int process_sample_event(union perf_event *event, | 306 | static int process_sample_event(union perf_event *event, |
| 307 | struct perf_sample *sample, | 307 | struct perf_sample *sample, |
| 308 | struct perf_evsel *evsel __used, | ||
| 308 | struct perf_session *session) | 309 | struct perf_session *session) |
| 309 | { | 310 | { |
| 310 | struct thread *thread = perf_session__findnew(session, event->ip.pid); | 311 | struct thread *thread = perf_session__findnew(session, event->ip.pid); |
diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c index 7a2a79d2cf2c..9ac05aafd9b2 100644 --- a/tools/perf/builtin-lock.c +++ b/tools/perf/builtin-lock.c | |||
| @@ -845,7 +845,9 @@ static void dump_info(void) | |||
| 845 | die("Unknown type of information\n"); | 845 | die("Unknown type of information\n"); |
| 846 | } | 846 | } |
| 847 | 847 | ||
| 848 | static int process_sample_event(union perf_event *event, struct perf_sample *sample, | 848 | static int process_sample_event(union perf_event *event, |
| 849 | struct perf_sample *sample, | ||
| 850 | struct perf_evsel *evsel __used, | ||
| 849 | struct perf_session *s) | 851 | struct perf_session *s) |
| 850 | { | 852 | { |
| 851 | struct thread *thread = perf_session__findnew(s, sample->tid); | 853 | struct thread *thread = perf_session__findnew(s, sample->tid); |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 6febcc168a8c..416538248a4b 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -41,7 +41,7 @@ static u64 user_interval = ULLONG_MAX; | |||
| 41 | static u64 default_interval = 0; | 41 | static u64 default_interval = 0; |
| 42 | 42 | ||
| 43 | static unsigned int page_size; | 43 | static unsigned int page_size; |
| 44 | static unsigned int mmap_pages = 128; | 44 | static unsigned int mmap_pages = UINT_MAX; |
| 45 | static unsigned int user_freq = UINT_MAX; | 45 | static unsigned int user_freq = UINT_MAX; |
| 46 | static int freq = 1000; | 46 | static int freq = 1000; |
| 47 | static int output; | 47 | static int output; |
| @@ -163,6 +163,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist) | |||
| 163 | struct perf_event_attr *attr = &evsel->attr; | 163 | struct perf_event_attr *attr = &evsel->attr; |
| 164 | int track = !evsel->idx; /* only the first counter needs these */ | 164 | int track = !evsel->idx; /* only the first counter needs these */ |
| 165 | 165 | ||
| 166 | attr->inherit = !no_inherit; | ||
| 166 | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | | 167 | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | |
| 167 | PERF_FORMAT_TOTAL_TIME_RUNNING | | 168 | PERF_FORMAT_TOTAL_TIME_RUNNING | |
| 168 | PERF_FORMAT_ID; | 169 | PERF_FORMAT_ID; |
| @@ -251,6 +252,9 @@ static void open_counters(struct perf_evlist *evlist) | |||
| 251 | { | 252 | { |
| 252 | struct perf_evsel *pos; | 253 | struct perf_evsel *pos; |
| 253 | 254 | ||
| 255 | if (evlist->cpus->map[0] < 0) | ||
| 256 | no_inherit = true; | ||
| 257 | |||
| 254 | list_for_each_entry(pos, &evlist->entries, node) { | 258 | list_for_each_entry(pos, &evlist->entries, node) { |
| 255 | struct perf_event_attr *attr = &pos->attr; | 259 | struct perf_event_attr *attr = &pos->attr; |
| 256 | /* | 260 | /* |
| @@ -271,15 +275,13 @@ static void open_counters(struct perf_evlist *evlist) | |||
| 271 | retry_sample_id: | 275 | retry_sample_id: |
| 272 | attr->sample_id_all = sample_id_all_avail ? 1 : 0; | 276 | attr->sample_id_all = sample_id_all_avail ? 1 : 0; |
| 273 | try_again: | 277 | try_again: |
| 274 | if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group, | 278 | if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) { |
| 275 | !no_inherit) < 0) { | ||
| 276 | int err = errno; | 279 | int err = errno; |
| 277 | 280 | ||
| 278 | if (err == EPERM || err == EACCES) | 281 | if (err == EPERM || err == EACCES) { |
| 279 | die("Permission error - are you root?\n" | 282 | ui__warning_paranoid(); |
| 280 | "\t Consider tweaking" | 283 | exit(EXIT_FAILURE); |
| 281 | " /proc/sys/kernel/perf_event_paranoid.\n"); | 284 | } else if (err == ENODEV && cpu_list) { |
| 282 | else if (err == ENODEV && cpu_list) { | ||
| 283 | die("No such device - did you specify" | 285 | die("No such device - did you specify" |
| 284 | " an out-of-range profile CPU?\n"); | 286 | " an out-of-range profile CPU?\n"); |
| 285 | } else if (err == EINVAL && sample_id_all_avail) { | 287 | } else if (err == EINVAL && sample_id_all_avail) { |
| @@ -302,11 +304,19 @@ try_again: | |||
| 302 | && attr->config == PERF_COUNT_HW_CPU_CYCLES) { | 304 | && attr->config == PERF_COUNT_HW_CPU_CYCLES) { |
| 303 | 305 | ||
| 304 | if (verbose) | 306 | if (verbose) |
| 305 | warning(" ... trying to fall back to cpu-clock-ticks\n"); | 307 | ui__warning("The cycles event is not supported, " |
| 308 | "trying to fall back to cpu-clock-ticks\n"); | ||
| 306 | attr->type = PERF_TYPE_SOFTWARE; | 309 | attr->type = PERF_TYPE_SOFTWARE; |
| 307 | attr->config = PERF_COUNT_SW_CPU_CLOCK; | 310 | attr->config = PERF_COUNT_SW_CPU_CLOCK; |
| 308 | goto try_again; | 311 | goto try_again; |
| 309 | } | 312 | } |
| 313 | |||
| 314 | if (err == ENOENT) { | ||
| 315 | ui__warning("The %s event is not supported.\n", | ||
| 316 | event_name(pos)); | ||
| 317 | exit(EXIT_FAILURE); | ||
| 318 | } | ||
| 319 | |||
| 310 | printf("\n"); | 320 | printf("\n"); |
| 311 | error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", | 321 | error("sys_perf_event_open() syscall returned with %d (%s). /bin/dmesg may provide additional information.\n", |
| 312 | err, strerror(err)); | 322 | err, strerror(err)); |
| @@ -506,6 +516,10 @@ static int __cmd_record(int argc, const char **argv) | |||
| 506 | if (have_tracepoints(&evsel_list->entries)) | 516 | if (have_tracepoints(&evsel_list->entries)) |
| 507 | perf_header__set_feat(&session->header, HEADER_TRACE_INFO); | 517 | perf_header__set_feat(&session->header, HEADER_TRACE_INFO); |
| 508 | 518 | ||
| 519 | /* 512 kiB: default amount of unprivileged mlocked memory */ | ||
| 520 | if (mmap_pages == UINT_MAX) | ||
| 521 | mmap_pages = (512 * 1024) / page_size; | ||
| 522 | |||
| 509 | if (forks) { | 523 | if (forks) { |
| 510 | child_pid = fork(); | 524 | child_pid = fork(); |
| 511 | if (child_pid < 0) { | 525 | if (child_pid < 0) { |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index b1b82009ab9b..498c6f70a747 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
| @@ -50,12 +50,12 @@ static symbol_filter_t annotate_init; | |||
| 50 | 50 | ||
| 51 | static int perf_session__add_hist_entry(struct perf_session *session, | 51 | static int perf_session__add_hist_entry(struct perf_session *session, |
| 52 | struct addr_location *al, | 52 | struct addr_location *al, |
| 53 | struct perf_sample *sample) | 53 | struct perf_sample *sample, |
| 54 | struct perf_evsel *evsel) | ||
| 54 | { | 55 | { |
| 55 | struct symbol *parent = NULL; | 56 | struct symbol *parent = NULL; |
| 56 | int err = 0; | 57 | int err = 0; |
| 57 | struct hist_entry *he; | 58 | struct hist_entry *he; |
| 58 | struct perf_evsel *evsel; | ||
| 59 | 59 | ||
| 60 | if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { | 60 | if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) { |
| 61 | err = perf_session__resolve_callchain(session, al->thread, | 61 | err = perf_session__resolve_callchain(session, al->thread, |
| @@ -64,18 +64,6 @@ static int perf_session__add_hist_entry(struct perf_session *session, | |||
| 64 | return err; | 64 | return err; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | evsel = perf_evlist__id2evsel(session->evlist, sample->id); | ||
| 68 | if (evsel == NULL) { | ||
| 69 | /* | ||
| 70 | * FIXME: Propagate this back, but at least we're in a builtin, | ||
| 71 | * where exit() is allowed. ;-) | ||
| 72 | */ | ||
| 73 | ui__warning("Invalid %s file, contains samples with id %" PRIu64 " not in " | ||
| 74 | "its header!\n", input_name, sample->id); | ||
| 75 | exit_browser(0); | ||
| 76 | exit(1); | ||
| 77 | } | ||
| 78 | |||
| 79 | he = __hists__add_entry(&evsel->hists, al, parent, sample->period); | 67 | he = __hists__add_entry(&evsel->hists, al, parent, sample->period); |
| 80 | if (he == NULL) | 68 | if (he == NULL) |
| 81 | return -ENOMEM; | 69 | return -ENOMEM; |
| @@ -113,6 +101,7 @@ out: | |||
| 113 | 101 | ||
| 114 | static int process_sample_event(union perf_event *event, | 102 | static int process_sample_event(union perf_event *event, |
| 115 | struct perf_sample *sample, | 103 | struct perf_sample *sample, |
| 104 | struct perf_evsel *evsel, | ||
| 116 | struct perf_session *session) | 105 | struct perf_session *session) |
| 117 | { | 106 | { |
| 118 | struct addr_location al; | 107 | struct addr_location al; |
| @@ -127,7 +116,7 @@ static int process_sample_event(union perf_event *event, | |||
| 127 | if (al.filtered || (hide_unresolved && al.sym == NULL)) | 116 | if (al.filtered || (hide_unresolved && al.sym == NULL)) |
| 128 | return 0; | 117 | return 0; |
| 129 | 118 | ||
| 130 | if (perf_session__add_hist_entry(session, &al, sample)) { | 119 | if (perf_session__add_hist_entry(session, &al, sample, evsel)) { |
| 131 | pr_debug("problem incrementing symbol period, skipping event\n"); | 120 | pr_debug("problem incrementing symbol period, skipping event\n"); |
| 132 | return -1; | 121 | return -1; |
| 133 | } | 122 | } |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index a32f411faeac..dcfe8873c9a1 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
| @@ -1603,6 +1603,7 @@ static void process_raw_event(union perf_event *raw_event __used, | |||
| 1603 | 1603 | ||
| 1604 | static int process_sample_event(union perf_event *event, | 1604 | static int process_sample_event(union perf_event *event, |
| 1605 | struct perf_sample *sample, | 1605 | struct perf_sample *sample, |
| 1606 | struct perf_evsel *evsel __used, | ||
| 1606 | struct perf_session *session) | 1607 | struct perf_session *session) |
| 1607 | { | 1608 | { |
| 1608 | struct thread *thread; | 1609 | struct thread *thread; |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 9f5fc5492141..ac574ea23917 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
| @@ -162,19 +162,11 @@ static void print_sample_start(struct perf_sample *sample, | |||
| 162 | 162 | ||
| 163 | static void process_event(union perf_event *event __unused, | 163 | static void process_event(union perf_event *event __unused, |
| 164 | struct perf_sample *sample, | 164 | struct perf_sample *sample, |
| 165 | struct perf_evsel *evsel, | ||
| 165 | struct perf_session *session, | 166 | struct perf_session *session, |
| 166 | struct thread *thread) | 167 | struct thread *thread) |
| 167 | { | 168 | { |
| 168 | struct perf_event_attr *attr; | 169 | struct perf_event_attr *attr = &evsel->attr; |
| 169 | struct perf_evsel *evsel; | ||
| 170 | |||
| 171 | evsel = perf_evlist__id2evsel(session->evlist, sample->id); | ||
| 172 | if (evsel == NULL) { | ||
| 173 | pr_err("Invalid data. Contains samples with id not in " | ||
| 174 | "its header!\n"); | ||
| 175 | return; | ||
| 176 | } | ||
| 177 | attr = &evsel->attr; | ||
| 178 | 170 | ||
| 179 | if (output_fields[attr->type] == 0) | 171 | if (output_fields[attr->type] == 0) |
| 180 | return; | 172 | return; |
| @@ -244,6 +236,7 @@ static char const *input_name = "perf.data"; | |||
| 244 | 236 | ||
| 245 | static int process_sample_event(union perf_event *event, | 237 | static int process_sample_event(union perf_event *event, |
| 246 | struct perf_sample *sample, | 238 | struct perf_sample *sample, |
| 239 | struct perf_evsel *evsel, | ||
| 247 | struct perf_session *session) | 240 | struct perf_session *session) |
| 248 | { | 241 | { |
| 249 | struct thread *thread = perf_session__findnew(session, event->ip.pid); | 242 | struct thread *thread = perf_session__findnew(session, event->ip.pid); |
| @@ -264,7 +257,7 @@ static int process_sample_event(union perf_event *event, | |||
| 264 | last_timestamp = sample->time; | 257 | last_timestamp = sample->time; |
| 265 | return 0; | 258 | return 0; |
| 266 | } | 259 | } |
| 267 | scripting_ops->process_event(event, sample, session, thread); | 260 | scripting_ops->process_event(event, sample, evsel, session, thread); |
| 268 | 261 | ||
| 269 | session->hists.stats.total_period += sample->period; | 262 | session->hists.stats.total_period += sample->period; |
| 270 | return 0; | 263 | return 0; |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index e2109f9b43eb..03f0e45f1479 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
| @@ -167,16 +167,17 @@ static int create_perf_stat_counter(struct perf_evsel *evsel) | |||
| 167 | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | | 167 | attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | |
| 168 | PERF_FORMAT_TOTAL_TIME_RUNNING; | 168 | PERF_FORMAT_TOTAL_TIME_RUNNING; |
| 169 | 169 | ||
| 170 | attr->inherit = !no_inherit; | ||
| 171 | |||
| 170 | if (system_wide) | 172 | if (system_wide) |
| 171 | return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false); | 173 | return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false); |
| 172 | 174 | ||
| 173 | attr->inherit = !no_inherit; | ||
| 174 | if (target_pid == -1 && target_tid == -1) { | 175 | if (target_pid == -1 && target_tid == -1) { |
| 175 | attr->disabled = 1; | 176 | attr->disabled = 1; |
| 176 | attr->enable_on_exec = 1; | 177 | attr->enable_on_exec = 1; |
| 177 | } | 178 | } |
| 178 | 179 | ||
| 179 | return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false); | 180 | return perf_evsel__open_per_thread(evsel, evsel_list->threads, false); |
| 180 | } | 181 | } |
| 181 | 182 | ||
| 182 | /* | 183 | /* |
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 1b2106c58f66..11e3c8458362 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c | |||
| @@ -290,7 +290,7 @@ static int test__open_syscall_event(void) | |||
| 290 | goto out_thread_map_delete; | 290 | goto out_thread_map_delete; |
| 291 | } | 291 | } |
| 292 | 292 | ||
| 293 | if (perf_evsel__open_per_thread(evsel, threads, false, false) < 0) { | 293 | if (perf_evsel__open_per_thread(evsel, threads, false) < 0) { |
| 294 | pr_debug("failed to open counter: %s, " | 294 | pr_debug("failed to open counter: %s, " |
| 295 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", | 295 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", |
| 296 | strerror(errno)); | 296 | strerror(errno)); |
| @@ -303,7 +303,7 @@ static int test__open_syscall_event(void) | |||
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) { | 305 | if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) { |
| 306 | pr_debug("perf_evsel__open_read_on_cpu\n"); | 306 | pr_debug("perf_evsel__read_on_cpu\n"); |
| 307 | goto out_close_fd; | 307 | goto out_close_fd; |
| 308 | } | 308 | } |
| 309 | 309 | ||
| @@ -365,7 +365,7 @@ static int test__open_syscall_event_on_all_cpus(void) | |||
| 365 | goto out_thread_map_delete; | 365 | goto out_thread_map_delete; |
| 366 | } | 366 | } |
| 367 | 367 | ||
| 368 | if (perf_evsel__open(evsel, cpus, threads, false, false) < 0) { | 368 | if (perf_evsel__open(evsel, cpus, threads, false) < 0) { |
| 369 | pr_debug("failed to open counter: %s, " | 369 | pr_debug("failed to open counter: %s, " |
| 370 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", | 370 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", |
| 371 | strerror(errno)); | 371 | strerror(errno)); |
| @@ -418,7 +418,7 @@ static int test__open_syscall_event_on_all_cpus(void) | |||
| 418 | continue; | 418 | continue; |
| 419 | 419 | ||
| 420 | if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) { | 420 | if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) { |
| 421 | pr_debug("perf_evsel__open_read_on_cpu\n"); | 421 | pr_debug("perf_evsel__read_on_cpu\n"); |
| 422 | err = -1; | 422 | err = -1; |
| 423 | break; | 423 | break; |
| 424 | } | 424 | } |
| @@ -529,7 +529,7 @@ static int test__basic_mmap(void) | |||
| 529 | 529 | ||
| 530 | perf_evlist__add(evlist, evsels[i]); | 530 | perf_evlist__add(evlist, evsels[i]); |
| 531 | 531 | ||
| 532 | if (perf_evsel__open(evsels[i], cpus, threads, false, false) < 0) { | 532 | if (perf_evsel__open(evsels[i], cpus, threads, false) < 0) { |
| 533 | pr_debug("failed to open counter: %s, " | 533 | pr_debug("failed to open counter: %s, " |
| 534 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", | 534 | "tweak /proc/sys/kernel/perf_event_paranoid?\n", |
| 535 | strerror(errno)); | 535 | strerror(errno)); |
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 67c0459dc325..aa26f4d66d10 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
| @@ -488,6 +488,7 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) | |||
| 488 | 488 | ||
| 489 | static int process_sample_event(union perf_event *event __used, | 489 | static int process_sample_event(union perf_event *event __used, |
| 490 | struct perf_sample *sample, | 490 | struct perf_sample *sample, |
| 491 | struct perf_evsel *evsel __used, | ||
| 491 | struct perf_session *session) | 492 | struct perf_session *session) |
| 492 | { | 493 | { |
| 493 | struct trace_entry *te; | 494 | struct trace_entry *te; |
| @@ -506,6 +507,16 @@ static int process_sample_event(union perf_event *event __used, | |||
| 506 | struct power_entry_old *peo; | 507 | struct power_entry_old *peo; |
| 507 | peo = (void *)te; | 508 | peo = (void *)te; |
| 508 | #endif | 509 | #endif |
| 510 | /* | ||
| 511 | * FIXME: use evsel, its already mapped from id to perf_evsel, | ||
| 512 | * remove perf_header__find_event infrastructure bits. | ||
| 513 | * Mapping all these "power:cpu_idle" strings to the tracepoint | ||
| 514 | * ID and then just comparing against evsel->attr.config. | ||
| 515 | * | ||
| 516 | * e.g.: | ||
| 517 | * | ||
| 518 | * if (evsel->attr.config == power_cpu_idle_id) | ||
| 519 | */ | ||
| 509 | event_str = perf_header__find_event(te->type); | 520 | event_str = perf_header__find_event(te->type); |
| 510 | 521 | ||
| 511 | if (!event_str) | 522 | if (!event_str) |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 70f1075cc5b0..7e3d6e310bf8 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
| @@ -515,7 +515,9 @@ static void handle_keypress(struct perf_session *session, int c) | |||
| 515 | break; | 515 | break; |
| 516 | case 'E': | 516 | case 'E': |
| 517 | if (top.evlist->nr_entries > 1) { | 517 | if (top.evlist->nr_entries > 1) { |
| 518 | int counter; | 518 | /* Select 0 as the default event: */ |
| 519 | int counter = 0; | ||
| 520 | |||
| 519 | fprintf(stderr, "\nAvailable events:"); | 521 | fprintf(stderr, "\nAvailable events:"); |
| 520 | 522 | ||
| 521 | list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) | 523 | list_for_each_entry(top.sym_evsel, &top.evlist->entries, node) |
| @@ -843,15 +845,16 @@ static void start_counters(struct perf_evlist *evlist) | |||
| 843 | } | 845 | } |
| 844 | 846 | ||
| 845 | attr->mmap = 1; | 847 | attr->mmap = 1; |
| 848 | attr->inherit = inherit; | ||
| 846 | try_again: | 849 | try_again: |
| 847 | if (perf_evsel__open(counter, top.evlist->cpus, | 850 | if (perf_evsel__open(counter, top.evlist->cpus, |
| 848 | top.evlist->threads, group, inherit) < 0) { | 851 | top.evlist->threads, group) < 0) { |
| 849 | int err = errno; | 852 | int err = errno; |
| 850 | 853 | ||
| 851 | if (err == EPERM || err == EACCES) | 854 | if (err == EPERM || err == EACCES) { |
| 852 | die("Permission error - are you root?\n" | 855 | ui__warning_paranoid(); |
| 853 | "\t Consider tweaking" | 856 | goto out_err; |
| 854 | " /proc/sys/kernel/perf_event_paranoid.\n"); | 857 | } |
| 855 | /* | 858 | /* |
| 856 | * If it's cycles then fall back to hrtimer | 859 | * If it's cycles then fall back to hrtimer |
| 857 | * based cpu-clock-tick sw counter, which | 860 | * based cpu-clock-tick sw counter, which |
| @@ -859,25 +862,41 @@ try_again: | |||
| 859 | */ | 862 | */ |
| 860 | if (attr->type == PERF_TYPE_HARDWARE && | 863 | if (attr->type == PERF_TYPE_HARDWARE && |
| 861 | attr->config == PERF_COUNT_HW_CPU_CYCLES) { | 864 | attr->config == PERF_COUNT_HW_CPU_CYCLES) { |
| 862 | |||
| 863 | if (verbose) | 865 | if (verbose) |
| 864 | warning(" ... trying to fall back to cpu-clock-ticks\n"); | 866 | ui__warning("Cycles event not supported,\n" |
| 867 | "trying to fall back to cpu-clock-ticks\n"); | ||
| 865 | 868 | ||
| 866 | attr->type = PERF_TYPE_SOFTWARE; | 869 | attr->type = PERF_TYPE_SOFTWARE; |
| 867 | attr->config = PERF_COUNT_SW_CPU_CLOCK; | 870 | attr->config = PERF_COUNT_SW_CPU_CLOCK; |
| 868 | goto try_again; | 871 | goto try_again; |
| 869 | } | 872 | } |
| 870 | printf("\n"); | 873 | |
| 871 | error("sys_perf_event_open() syscall returned with %d " | 874 | if (err == ENOENT) { |
| 872 | "(%s). /bin/dmesg may provide additional information.\n", | 875 | ui__warning("The %s event is not supported.\n", |
| 873 | err, strerror(err)); | 876 | event_name(counter)); |
| 874 | die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); | 877 | goto out_err; |
| 875 | exit(-1); | 878 | } |
| 879 | |||
| 880 | ui__warning("The sys_perf_event_open() syscall " | ||
| 881 | "returned with %d (%s). /bin/dmesg " | ||
| 882 | "may provide additional information.\n" | ||
| 883 | "No CONFIG_PERF_EVENTS=y kernel support " | ||
| 884 | "configured?\n", err, strerror(err)); | ||
| 885 | goto out_err; | ||
| 876 | } | 886 | } |
| 877 | } | 887 | } |
| 878 | 888 | ||
| 879 | if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) | 889 | if (perf_evlist__mmap(evlist, mmap_pages, false) < 0) { |
| 880 | die("failed to mmap with %d (%s)\n", errno, strerror(errno)); | 890 | ui__warning("Failed to mmap with %d (%s)\n", |
| 891 | errno, strerror(errno)); | ||
| 892 | goto out_err; | ||
| 893 | } | ||
| 894 | |||
| 895 | return; | ||
| 896 | |||
| 897 | out_err: | ||
| 898 | exit_browser(0); | ||
| 899 | exit(0); | ||
| 881 | } | 900 | } |
| 882 | 901 | ||
| 883 | static int __cmd_top(void) | 902 | static int __cmd_top(void) |
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 31f934af9861..a91cd99f26ea 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | static int build_id__mark_dso_hit(union perf_event *event, | 17 | static int build_id__mark_dso_hit(union perf_event *event, |
| 18 | struct perf_sample *sample __used, | 18 | struct perf_sample *sample __used, |
| 19 | struct perf_evsel *evsel __used, | ||
| 19 | struct perf_session *session) | 20 | struct perf_session *session) |
| 20 | { | 21 | { |
| 21 | struct addr_location al; | 22 | struct addr_location al; |
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c index 9fea75535221..96bee5c46008 100644 --- a/tools/perf/util/cgroup.c +++ b/tools/perf/util/cgroup.c | |||
| @@ -13,7 +13,7 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen) | |||
| 13 | { | 13 | { |
| 14 | FILE *fp; | 14 | FILE *fp; |
| 15 | char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1]; | 15 | char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1]; |
| 16 | char *token, *saved_ptr; | 16 | char *token, *saved_ptr = NULL; |
| 17 | int found = 0; | 17 | int found = 0; |
| 18 | 18 | ||
| 19 | fp = fopen("/proc/mounts", "r"); | 19 | fp = fopen("/proc/mounts", "r"); |
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index d4536a9e0d8c..155749d74350 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c | |||
| @@ -57,6 +57,16 @@ void ui__warning(const char *format, ...) | |||
| 57 | } | 57 | } |
| 58 | #endif | 58 | #endif |
| 59 | 59 | ||
| 60 | void ui__warning_paranoid(void) | ||
| 61 | { | ||
| 62 | ui__warning("Permission error - are you root?\n" | ||
| 63 | "Consider tweaking /proc/sys/kernel/perf_event_paranoid:\n" | ||
| 64 | " -1 - Not paranoid at all\n" | ||
| 65 | " 0 - Disallow raw tracepoint access for unpriv\n" | ||
| 66 | " 1 - Disallow cpu events for unpriv\n" | ||
| 67 | " 2 - Disallow kernel profiling for unpriv\n"); | ||
| 68 | } | ||
| 69 | |||
| 60 | void trace_event(union perf_event *event) | 70 | void trace_event(union perf_event *event) |
| 61 | { | 71 | { |
| 62 | unsigned char *raw_event = (void *)event; | 72 | unsigned char *raw_event = (void *)event; |
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 93516cf4682c..fd53db47e3de 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h | |||
| @@ -36,5 +36,6 @@ int ui_helpline__show_help(const char *format, va_list ap); | |||
| 36 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); | 38 | void ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2))); |
| 39 | void ui__warning_paranoid(void); | ||
| 39 | 40 | ||
| 40 | #endif /* __PERF_DEBUG_H */ | 41 | #endif /* __PERF_DEBUG_H */ |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 2b15c362ef56..1023f67633a4 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
| @@ -710,7 +710,7 @@ try_again: | |||
| 710 | * in the whole kernel symbol list. | 710 | * in the whole kernel symbol list. |
| 711 | */ | 711 | */ |
| 712 | if ((long long)al->addr < 0 && | 712 | if ((long long)al->addr < 0 && |
| 713 | cpumode == PERF_RECORD_MISC_KERNEL && | 713 | cpumode == PERF_RECORD_MISC_USER && |
| 714 | machine && mg != &machine->kmaps) { | 714 | machine && mg != &machine->kmaps) { |
| 715 | mg = &machine->kmaps; | 715 | mg = &machine->kmaps; |
| 716 | goto try_again; | 716 | goto try_again; |
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index d852cefa20de..45da8d186b49 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "evlist.h" | 12 | #include "evlist.h" |
| 13 | #include "evsel.h" | 13 | #include "evsel.h" |
| 14 | #include "util.h" | 14 | #include "util.h" |
| 15 | #include "debug.h" | ||
| 15 | 16 | ||
| 16 | #include <sys/mman.h> | 17 | #include <sys/mman.h> |
| 17 | 18 | ||
| @@ -250,15 +251,19 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist) | |||
| 250 | return evlist->mmap != NULL ? 0 : -ENOMEM; | 251 | return evlist->mmap != NULL ? 0 : -ENOMEM; |
| 251 | } | 252 | } |
| 252 | 253 | ||
| 253 | static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot, | 254 | static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel, |
| 254 | int mask, int fd) | 255 | int cpu, int prot, int mask, int fd) |
| 255 | { | 256 | { |
| 256 | evlist->mmap[cpu].prev = 0; | 257 | evlist->mmap[cpu].prev = 0; |
| 257 | evlist->mmap[cpu].mask = mask; | 258 | evlist->mmap[cpu].mask = mask; |
| 258 | evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot, | 259 | evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot, |
| 259 | MAP_SHARED, fd, 0); | 260 | MAP_SHARED, fd, 0); |
| 260 | if (evlist->mmap[cpu].base == MAP_FAILED) | 261 | if (evlist->mmap[cpu].base == MAP_FAILED) { |
| 262 | if (evlist->cpus->map[cpu] == -1 && evsel->attr.inherit) | ||
| 263 | ui__warning("Inherit is not allowed on per-task " | ||
| 264 | "events using mmap.\n"); | ||
| 261 | return -1; | 265 | return -1; |
| 266 | } | ||
| 262 | 267 | ||
| 263 | perf_evlist__add_pollfd(evlist, fd); | 268 | perf_evlist__add_pollfd(evlist, fd); |
| 264 | return 0; | 269 | return 0; |
| @@ -312,7 +317,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite) | |||
| 312 | if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, | 317 | if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, |
| 313 | FD(first_evsel, cpu, 0)) != 0) | 318 | FD(first_evsel, cpu, 0)) != 0) |
| 314 | goto out_unmap; | 319 | goto out_unmap; |
| 315 | } else if (__perf_evlist__mmap(evlist, cpu, prot, mask, fd) < 0) | 320 | } else if (__perf_evlist__mmap(evlist, evsel, cpu, |
| 321 | prot, mask, fd) < 0) | ||
| 316 | goto out_unmap; | 322 | goto out_unmap; |
| 317 | 323 | ||
| 318 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && | 324 | if ((evsel->attr.read_format & PERF_FORMAT_ID) && |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 662596afd7f1..d6fd59beb860 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
| @@ -175,7 +175,7 @@ int __perf_evsel__read(struct perf_evsel *evsel, | |||
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | 177 | static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, |
| 178 | struct thread_map *threads, bool group, bool inherit) | 178 | struct thread_map *threads, bool group) |
| 179 | { | 179 | { |
| 180 | int cpu, thread; | 180 | int cpu, thread; |
| 181 | unsigned long flags = 0; | 181 | unsigned long flags = 0; |
| @@ -192,19 +192,6 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
| 192 | 192 | ||
| 193 | for (cpu = 0; cpu < cpus->nr; cpu++) { | 193 | for (cpu = 0; cpu < cpus->nr; cpu++) { |
| 194 | int group_fd = -1; | 194 | int group_fd = -1; |
| 195 | /* | ||
| 196 | * Don't allow mmap() of inherited per-task counters. This | ||
| 197 | * would create a performance issue due to all children writing | ||
| 198 | * to the same buffer. | ||
| 199 | * | ||
| 200 | * FIXME: | ||
| 201 | * Proper fix is not to pass 'inherit' to perf_evsel__open*, | ||
| 202 | * but a 'flags' parameter, with 'group' folded there as well, | ||
| 203 | * then introduce a PERF_O_{MMAP,GROUP,INHERIT} enum, and if | ||
| 204 | * O_MMAP is set, emit a warning if cpu < 0 and O_INHERIT is | ||
| 205 | * set. Lets go for the minimal fix first tho. | ||
| 206 | */ | ||
| 207 | evsel->attr.inherit = (cpus->map[cpu] >= 0) && inherit; | ||
| 208 | 195 | ||
| 209 | for (thread = 0; thread < threads->nr; thread++) { | 196 | for (thread = 0; thread < threads->nr; thread++) { |
| 210 | 197 | ||
| @@ -253,7 +240,7 @@ static struct { | |||
| 253 | }; | 240 | }; |
| 254 | 241 | ||
| 255 | int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | 242 | int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, |
| 256 | struct thread_map *threads, bool group, bool inherit) | 243 | struct thread_map *threads, bool group) |
| 257 | { | 244 | { |
| 258 | if (cpus == NULL) { | 245 | if (cpus == NULL) { |
| 259 | /* Work around old compiler warnings about strict aliasing */ | 246 | /* Work around old compiler warnings about strict aliasing */ |
| @@ -263,19 +250,19 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
| 263 | if (threads == NULL) | 250 | if (threads == NULL) |
| 264 | threads = &empty_thread_map.map; | 251 | threads = &empty_thread_map.map; |
| 265 | 252 | ||
| 266 | return __perf_evsel__open(evsel, cpus, threads, group, inherit); | 253 | return __perf_evsel__open(evsel, cpus, threads, group); |
| 267 | } | 254 | } |
| 268 | 255 | ||
| 269 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, | 256 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, |
| 270 | struct cpu_map *cpus, bool group, bool inherit) | 257 | struct cpu_map *cpus, bool group) |
| 271 | { | 258 | { |
| 272 | return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, inherit); | 259 | return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group); |
| 273 | } | 260 | } |
| 274 | 261 | ||
| 275 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, | 262 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, |
| 276 | struct thread_map *threads, bool group, bool inherit) | 263 | struct thread_map *threads, bool group) |
| 277 | { | 264 | { |
| 278 | return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit); | 265 | return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group); |
| 279 | } | 266 | } |
| 280 | 267 | ||
| 281 | static int perf_event__parse_id_sample(const union perf_event *event, u64 type, | 268 | static int perf_event__parse_id_sample(const union perf_event *event, u64 type, |
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 6710ab538342..f79bb2c09a6c 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h | |||
| @@ -81,11 +81,11 @@ void perf_evsel__free_id(struct perf_evsel *evsel); | |||
| 81 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); | 81 | void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); |
| 82 | 82 | ||
| 83 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, | 83 | int perf_evsel__open_per_cpu(struct perf_evsel *evsel, |
| 84 | struct cpu_map *cpus, bool group, bool inherit); | 84 | struct cpu_map *cpus, bool group); |
| 85 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, | 85 | int perf_evsel__open_per_thread(struct perf_evsel *evsel, |
| 86 | struct thread_map *threads, bool group, bool inherit); | 86 | struct thread_map *threads, bool group); |
| 87 | int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | 87 | int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, |
| 88 | struct thread_map *threads, bool group, bool inherit); | 88 | struct thread_map *threads, bool group); |
| 89 | 89 | ||
| 90 | #define perf_evsel__match(evsel, t, c) \ | 90 | #define perf_evsel__match(evsel, t, c) \ |
| 91 | (evsel->attr.type == PERF_TYPE_##t && \ | 91 | (evsel->attr.type == PERF_TYPE_##t && \ |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index e5230c0ef95b..93862a8027ea 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
| @@ -695,13 +695,50 @@ out: | |||
| 695 | return err; | 695 | return err; |
| 696 | } | 696 | } |
| 697 | 697 | ||
| 698 | static int perf_header__read_build_ids_abi_quirk(struct perf_header *header, | ||
| 699 | int input, u64 offset, u64 size) | ||
| 700 | { | ||
| 701 | struct perf_session *session = container_of(header, struct perf_session, header); | ||
| 702 | struct { | ||
| 703 | struct perf_event_header header; | ||
| 704 | u8 build_id[ALIGN(BUILD_ID_SIZE, sizeof(u64))]; | ||
| 705 | char filename[0]; | ||
| 706 | } old_bev; | ||
| 707 | struct build_id_event bev; | ||
| 708 | char filename[PATH_MAX]; | ||
| 709 | u64 limit = offset + size; | ||
| 710 | |||
| 711 | while (offset < limit) { | ||
| 712 | ssize_t len; | ||
| 713 | |||
| 714 | if (read(input, &old_bev, sizeof(old_bev)) != sizeof(old_bev)) | ||
| 715 | return -1; | ||
| 716 | |||
| 717 | if (header->needs_swap) | ||
| 718 | perf_event_header__bswap(&old_bev.header); | ||
| 719 | |||
| 720 | len = old_bev.header.size - sizeof(old_bev); | ||
| 721 | if (read(input, filename, len) != len) | ||
| 722 | return -1; | ||
| 723 | |||
| 724 | bev.header = old_bev.header; | ||
| 725 | bev.pid = 0; | ||
| 726 | memcpy(bev.build_id, old_bev.build_id, sizeof(bev.build_id)); | ||
| 727 | __event_process_build_id(&bev, filename, session); | ||
| 728 | |||
| 729 | offset += bev.header.size; | ||
| 730 | } | ||
| 731 | |||
| 732 | return 0; | ||
| 733 | } | ||
| 734 | |||
| 698 | static int perf_header__read_build_ids(struct perf_header *header, | 735 | static int perf_header__read_build_ids(struct perf_header *header, |
| 699 | int input, u64 offset, u64 size) | 736 | int input, u64 offset, u64 size) |
| 700 | { | 737 | { |
| 701 | struct perf_session *session = container_of(header, struct perf_session, header); | 738 | struct perf_session *session = container_of(header, struct perf_session, header); |
| 702 | struct build_id_event bev; | 739 | struct build_id_event bev; |
| 703 | char filename[PATH_MAX]; | 740 | char filename[PATH_MAX]; |
| 704 | u64 limit = offset + size; | 741 | u64 limit = offset + size, orig_offset = offset; |
| 705 | int err = -1; | 742 | int err = -1; |
| 706 | 743 | ||
| 707 | while (offset < limit) { | 744 | while (offset < limit) { |
| @@ -716,6 +753,24 @@ static int perf_header__read_build_ids(struct perf_header *header, | |||
| 716 | len = bev.header.size - sizeof(bev); | 753 | len = bev.header.size - sizeof(bev); |
| 717 | if (read(input, filename, len) != len) | 754 | if (read(input, filename, len) != len) |
| 718 | goto out; | 755 | goto out; |
| 756 | /* | ||
| 757 | * The a1645ce1 changeset: | ||
| 758 | * | ||
| 759 | * "perf: 'perf kvm' tool for monitoring guest performance from host" | ||
| 760 | * | ||
| 761 | * Added a field to struct build_id_event that broke the file | ||
| 762 | * format. | ||
| 763 | * | ||
| 764 | * Since the kernel build-id is the first entry, process the | ||
| 765 | * table using the old format if the well known | ||
| 766 | * '[kernel.kallsyms]' string for the kernel build-id has the | ||
| 767 | * first 4 characters chopped off (where the pid_t sits). | ||
| 768 | */ | ||
| 769 | if (memcmp(filename, "nel.kallsyms]", 13) == 0) { | ||
| 770 | if (lseek(input, orig_offset, SEEK_SET) == (off_t)-1) | ||
| 771 | return -1; | ||
| 772 | return perf_header__read_build_ids_abi_quirk(header, input, offset, size); | ||
| 773 | } | ||
| 719 | 774 | ||
| 720 | __event_process_build_id(&bev, filename, session); | 775 | __event_process_build_id(&bev, filename, session); |
| 721 | 776 | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index cb6858a2f9a3..3beb97c4d822 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
| @@ -29,6 +29,7 @@ struct events_stats { | |||
| 29 | u32 nr_events[PERF_RECORD_HEADER_MAX]; | 29 | u32 nr_events[PERF_RECORD_HEADER_MAX]; |
| 30 | u32 nr_unknown_events; | 30 | u32 nr_unknown_events; |
| 31 | u32 nr_invalid_chains; | 31 | u32 nr_invalid_chains; |
| 32 | u32 nr_unknown_id; | ||
| 32 | }; | 33 | }; |
| 33 | 34 | ||
| 34 | enum hist_column { | 35 | enum hist_column { |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 5ddee66020a7..f0223166e761 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
| @@ -234,7 +234,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
| 234 | 234 | ||
| 235 | /* Searching trace events corresponding to probe event */ | 235 | /* Searching trace events corresponding to probe event */ |
| 236 | ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); | 236 | ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); |
| 237 | close(fd); | ||
| 238 | 237 | ||
| 239 | if (ntevs > 0) { /* Succeeded to find trace events */ | 238 | if (ntevs > 0) { /* Succeeded to find trace events */ |
| 240 | pr_debug("find %d probe_trace_events.\n", ntevs); | 239 | pr_debug("find %d probe_trace_events.\n", ntevs); |
| @@ -388,7 +387,6 @@ int show_line_range(struct line_range *lr, const char *module) | |||
| 388 | } | 387 | } |
| 389 | 388 | ||
| 390 | ret = find_line_range(fd, lr); | 389 | ret = find_line_range(fd, lr); |
| 391 | close(fd); | ||
| 392 | if (ret == 0) { | 390 | if (ret == 0) { |
| 393 | pr_warning("Specified source line is not found.\n"); | 391 | pr_warning("Specified source line is not found.\n"); |
| 394 | return -ENOENT; | 392 | return -ENOENT; |
| @@ -512,19 +510,18 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, | |||
| 512 | if (ret < 0) | 510 | if (ret < 0) |
| 513 | return ret; | 511 | return ret; |
| 514 | 512 | ||
| 515 | fd = open_vmlinux(module); | ||
| 516 | if (fd < 0) { | ||
| 517 | pr_warning("Failed to open debug information file.\n"); | ||
| 518 | return fd; | ||
| 519 | } | ||
| 520 | |||
| 521 | setup_pager(); | 513 | setup_pager(); |
| 522 | 514 | ||
| 523 | for (i = 0; i < npevs && ret >= 0; i++) | 515 | for (i = 0; i < npevs && ret >= 0; i++) { |
| 516 | fd = open_vmlinux(module); | ||
| 517 | if (fd < 0) { | ||
| 518 | pr_warning("Failed to open debug information file.\n"); | ||
| 519 | ret = fd; | ||
| 520 | break; | ||
| 521 | } | ||
| 524 | ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter, | 522 | ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter, |
| 525 | externs); | 523 | externs); |
| 526 | 524 | } | |
| 527 | close(fd); | ||
| 528 | return ret; | 525 | return ret; |
| 529 | } | 526 | } |
| 530 | 527 | ||
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 194f9e2a3285..b7c85ce466a1 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
| @@ -273,6 +273,25 @@ static const char *cu_get_comp_dir(Dwarf_Die *cu_die) | |||
| 273 | return dwarf_formstring(&attr); | 273 | return dwarf_formstring(&attr); |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | /* Get a line number and file name for given address */ | ||
| 277 | static int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr, | ||
| 278 | const char **fname, int *lineno) | ||
| 279 | { | ||
| 280 | Dwarf_Line *line; | ||
| 281 | Dwarf_Addr laddr; | ||
| 282 | |||
| 283 | line = dwarf_getsrc_die(cudie, (Dwarf_Addr)addr); | ||
| 284 | if (line && dwarf_lineaddr(line, &laddr) == 0 && | ||
| 285 | addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) { | ||
| 286 | *fname = dwarf_linesrc(line, NULL, NULL); | ||
| 287 | if (!*fname) | ||
| 288 | /* line number is useless without filename */ | ||
| 289 | *lineno = 0; | ||
| 290 | } | ||
| 291 | |||
| 292 | return *lineno ?: -ENOENT; | ||
| 293 | } | ||
| 294 | |||
| 276 | /* Compare diename and tname */ | 295 | /* Compare diename and tname */ |
| 277 | static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) | 296 | static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) |
| 278 | { | 297 | { |
| @@ -497,7 +516,20 @@ static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data) | |||
| 497 | static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, | 516 | static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, |
| 498 | Dwarf_Die *die_mem) | 517 | Dwarf_Die *die_mem) |
| 499 | { | 518 | { |
| 500 | return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem); | 519 | Dwarf_Die tmp_die; |
| 520 | |||
| 521 | sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die); | ||
| 522 | if (!sp_die) | ||
| 523 | return NULL; | ||
| 524 | |||
| 525 | /* Inlined function could be recursive. Trace it until fail */ | ||
| 526 | while (sp_die) { | ||
| 527 | memcpy(die_mem, sp_die, sizeof(Dwarf_Die)); | ||
| 528 | sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, | ||
| 529 | &tmp_die); | ||
| 530 | } | ||
| 531 | |||
| 532 | return die_mem; | ||
| 501 | } | 533 | } |
| 502 | 534 | ||
| 503 | /* Walker on lines (Note: line number will not be sorted) */ | 535 | /* Walker on lines (Note: line number will not be sorted) */ |
| @@ -1395,6 +1427,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) | |||
| 1395 | !die_compare_name(sp_die, pp->function)) | 1427 | !die_compare_name(sp_die, pp->function)) |
| 1396 | return DWARF_CB_OK; | 1428 | return DWARF_CB_OK; |
| 1397 | 1429 | ||
| 1430 | /* Check declared file */ | ||
| 1431 | if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die))) | ||
| 1432 | return DWARF_CB_OK; | ||
| 1433 | |||
| 1398 | pf->fname = dwarf_decl_file(sp_die); | 1434 | pf->fname = dwarf_decl_file(sp_die); |
| 1399 | if (pp->line) { /* Function relative line */ | 1435 | if (pp->line) { /* Function relative line */ |
| 1400 | dwarf_decl_line(sp_die, &pf->lno); | 1436 | dwarf_decl_line(sp_die, &pf->lno); |
| @@ -1451,6 +1487,7 @@ static int find_probes(int fd, struct probe_finder *pf) | |||
| 1451 | if (!dbg) { | 1487 | if (!dbg) { |
| 1452 | pr_warning("No debug information found in the vmlinux - " | 1488 | pr_warning("No debug information found in the vmlinux - " |
| 1453 | "please rebuild with CONFIG_DEBUG_INFO=y.\n"); | 1489 | "please rebuild with CONFIG_DEBUG_INFO=y.\n"); |
| 1490 | close(fd); /* Without dwfl_end(), fd isn't closed. */ | ||
| 1454 | return -EBADF; | 1491 | return -EBADF; |
| 1455 | } | 1492 | } |
| 1456 | 1493 | ||
| @@ -1686,11 +1723,9 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) | |||
| 1686 | Dwarf_Die cudie, spdie, indie; | 1723 | Dwarf_Die cudie, spdie, indie; |
| 1687 | Dwarf *dbg = NULL; | 1724 | Dwarf *dbg = NULL; |
| 1688 | Dwfl *dwfl = NULL; | 1725 | Dwfl *dwfl = NULL; |
| 1689 | Dwarf_Line *line; | 1726 | Dwarf_Addr _addr, baseaddr, bias = 0; |
| 1690 | Dwarf_Addr laddr, eaddr, bias = 0; | 1727 | const char *fname = NULL, *func = NULL, *tmp; |
| 1691 | const char *tmp; | 1728 | int baseline = 0, lineno = 0, ret = 0; |
| 1692 | int lineno, ret = 0; | ||
| 1693 | bool found = false; | ||
| 1694 | 1729 | ||
| 1695 | /* Open the live linux kernel */ | 1730 | /* Open the live linux kernel */ |
| 1696 | dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); | 1731 | dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); |
| @@ -1711,68 +1746,79 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt) | |||
| 1711 | goto end; | 1746 | goto end; |
| 1712 | } | 1747 | } |
| 1713 | 1748 | ||
| 1714 | /* Find a corresponding line */ | 1749 | /* Find a corresponding line (filename and lineno) */ |
| 1715 | line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr); | 1750 | cu_find_lineinfo(&cudie, addr, &fname, &lineno); |
| 1716 | if (line) { | 1751 | /* Don't care whether it failed or not */ |
| 1717 | if (dwarf_lineaddr(line, &laddr) == 0 && | ||
| 1718 | (Dwarf_Addr)addr == laddr && | ||
| 1719 | dwarf_lineno(line, &lineno) == 0) { | ||
| 1720 | tmp = dwarf_linesrc(line, NULL, NULL); | ||
| 1721 | if (tmp) { | ||
| 1722 | ppt->line = lineno; | ||
| 1723 | ppt->file = strdup(tmp); | ||
| 1724 | if (ppt->file == NULL) { | ||
| 1725 | ret = -ENOMEM; | ||
| 1726 | goto end; | ||
| 1727 | } | ||
| 1728 | found = true; | ||
| 1729 | } | ||
| 1730 | } | ||
| 1731 | } | ||
| 1732 | 1752 | ||
| 1733 | /* Find a corresponding function */ | 1753 | /* Find a corresponding function (name, baseline and baseaddr) */ |
| 1734 | if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { | 1754 | if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { |
| 1755 | /* Get function entry information */ | ||
| 1735 | tmp = dwarf_diename(&spdie); | 1756 | tmp = dwarf_diename(&spdie); |
| 1736 | if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0) | 1757 | if (!tmp || |
| 1737 | goto end; | 1758 | dwarf_entrypc(&spdie, &baseaddr) != 0 || |
| 1738 | 1759 | dwarf_decl_line(&spdie, &baseline) != 0) | |
| 1739 | if (ppt->line) { | 1760 | goto post; |
| 1740 | if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, | 1761 | func = tmp; |
| 1741 | &indie)) { | 1762 | |
| 1742 | /* addr in an inline function */ | 1763 | if (addr == (unsigned long)baseaddr) |
| 1764 | /* Function entry - Relative line number is 0 */ | ||
| 1765 | lineno = baseline; | ||
| 1766 | else if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, | ||
| 1767 | &indie)) { | ||
| 1768 | if (dwarf_entrypc(&indie, &_addr) == 0 && | ||
| 1769 | _addr == addr) | ||
| 1770 | /* | ||
| 1771 | * addr is at an inline function entry. | ||
| 1772 | * In this case, lineno should be the call-site | ||
| 1773 | * line number. | ||
| 1774 | */ | ||
| 1775 | lineno = die_get_call_lineno(&indie); | ||
| 1776 | else { | ||
| 1777 | /* | ||
| 1778 | * addr is in an inline function body. | ||
| 1779 | * Since lineno points one of the lines | ||
| 1780 | * of the inline function, baseline should | ||
| 1781 | * be the entry line of the inline function. | ||
| 1782 | */ | ||
| 1743 | tmp = dwarf_diename(&indie); | 1783 | tmp = dwarf_diename(&indie); |
| 1744 | if (!tmp) | 1784 | if (tmp && |
| 1745 | goto end; | 1785 | dwarf_decl_line(&spdie, &baseline) == 0) |
| 1746 | ret = dwarf_decl_line(&indie, &lineno); | 1786 | func = tmp; |
| 1747 | } else { | ||
| 1748 | if (eaddr == addr) { /* Function entry */ | ||
| 1749 | lineno = ppt->line; | ||
| 1750 | ret = 0; | ||
| 1751 | } else | ||
| 1752 | ret = dwarf_decl_line(&spdie, &lineno); | ||
| 1753 | } | ||
| 1754 | if (ret == 0) { | ||
| 1755 | /* Make a relative line number */ | ||
| 1756 | ppt->line -= lineno; | ||
| 1757 | goto found; | ||
| 1758 | } | 1787 | } |
| 1759 | } | 1788 | } |
| 1760 | /* We don't have a line number, let's use offset */ | 1789 | } |
| 1761 | ppt->offset = addr - (unsigned long)eaddr; | 1790 | |
| 1762 | found: | 1791 | post: |
| 1763 | ppt->function = strdup(tmp); | 1792 | /* Make a relative line number or an offset */ |
| 1793 | if (lineno) | ||
| 1794 | ppt->line = lineno - baseline; | ||
| 1795 | else if (func) | ||
| 1796 | ppt->offset = addr - (unsigned long)baseaddr; | ||
| 1797 | |||
| 1798 | /* Duplicate strings */ | ||
| 1799 | if (func) { | ||
| 1800 | ppt->function = strdup(func); | ||
| 1764 | if (ppt->function == NULL) { | 1801 | if (ppt->function == NULL) { |
| 1765 | ret = -ENOMEM; | 1802 | ret = -ENOMEM; |
| 1766 | goto end; | 1803 | goto end; |
| 1767 | } | 1804 | } |
| 1768 | found = true; | ||
| 1769 | } | 1805 | } |
| 1770 | 1806 | if (fname) { | |
| 1807 | ppt->file = strdup(fname); | ||
| 1808 | if (ppt->file == NULL) { | ||
| 1809 | if (ppt->function) { | ||
| 1810 | free(ppt->function); | ||
| 1811 | ppt->function = NULL; | ||
| 1812 | } | ||
| 1813 | ret = -ENOMEM; | ||
| 1814 | goto end; | ||
| 1815 | } | ||
| 1816 | } | ||
| 1771 | end: | 1817 | end: |
| 1772 | if (dwfl) | 1818 | if (dwfl) |
| 1773 | dwfl_end(dwfl); | 1819 | dwfl_end(dwfl); |
| 1774 | if (ret >= 0) | 1820 | if (ret == 0 && (fname || func)) |
| 1775 | ret = found ? 1 : 0; | 1821 | ret = 1; /* Found a point */ |
| 1776 | return ret; | 1822 | return ret; |
| 1777 | } | 1823 | } |
| 1778 | 1824 | ||
| @@ -1840,6 +1886,10 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data) | |||
| 1840 | struct line_finder *lf = param->data; | 1886 | struct line_finder *lf = param->data; |
| 1841 | struct line_range *lr = lf->lr; | 1887 | struct line_range *lr = lf->lr; |
| 1842 | 1888 | ||
| 1889 | /* Check declared file */ | ||
| 1890 | if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die))) | ||
| 1891 | return DWARF_CB_OK; | ||
| 1892 | |||
| 1843 | if (dwarf_tag(sp_die) == DW_TAG_subprogram && | 1893 | if (dwarf_tag(sp_die) == DW_TAG_subprogram && |
| 1844 | die_compare_name(sp_die, lr->function)) { | 1894 | die_compare_name(sp_die, lr->function)) { |
| 1845 | lf->fname = dwarf_decl_file(sp_die); | 1895 | lf->fname = dwarf_decl_file(sp_die); |
| @@ -1892,6 +1942,7 @@ int find_line_range(int fd, struct line_range *lr) | |||
| 1892 | if (!dbg) { | 1942 | if (!dbg) { |
| 1893 | pr_warning("No debug information found in the vmlinux - " | 1943 | pr_warning("No debug information found in the vmlinux - " |
| 1894 | "please rebuild with CONFIG_DEBUG_INFO=y.\n"); | 1944 | "please rebuild with CONFIG_DEBUG_INFO=y.\n"); |
| 1945 | close(fd); /* Without dwfl_end(), fd isn't closed. */ | ||
| 1895 | return -EBADF; | 1946 | return -EBADF; |
| 1896 | } | 1947 | } |
| 1897 | 1948 | ||
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c index a9f2d7e1204d..f5e38451fdc5 100644 --- a/tools/perf/util/python.c +++ b/tools/perf/util/python.c | |||
| @@ -498,11 +498,11 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, | |||
| 498 | struct cpu_map *cpus = NULL; | 498 | struct cpu_map *cpus = NULL; |
| 499 | struct thread_map *threads = NULL; | 499 | struct thread_map *threads = NULL; |
| 500 | PyObject *pcpus = NULL, *pthreads = NULL; | 500 | PyObject *pcpus = NULL, *pthreads = NULL; |
| 501 | int group = 0, overwrite = 0; | 501 | int group = 0, inherit = 0; |
| 502 | static char *kwlist[] = {"cpus", "threads", "group", "overwrite", NULL, NULL}; | 502 | static char *kwlist[] = {"cpus", "threads", "group", "inherit", NULL, NULL}; |
| 503 | 503 | ||
| 504 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, | 504 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, |
| 505 | &pcpus, &pthreads, &group, &overwrite)) | 505 | &pcpus, &pthreads, &group, &inherit)) |
| 506 | return NULL; | 506 | return NULL; |
| 507 | 507 | ||
| 508 | if (pthreads != NULL) | 508 | if (pthreads != NULL) |
| @@ -511,7 +511,8 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel, | |||
| 511 | if (pcpus != NULL) | 511 | if (pcpus != NULL) |
| 512 | cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; | 512 | cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; |
| 513 | 513 | ||
| 514 | if (perf_evsel__open(evsel, cpus, threads, group, overwrite) < 0) { | 514 | evsel->attr.inherit = inherit; |
| 515 | if (perf_evsel__open(evsel, cpus, threads, group) < 0) { | ||
| 515 | PyErr_SetFromErrno(PyExc_OSError); | 516 | PyErr_SetFromErrno(PyExc_OSError); |
| 516 | return NULL; | 517 | return NULL; |
| 517 | } | 518 | } |
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c index 621427212e86..74350ffb57fe 100644 --- a/tools/perf/util/scripting-engines/trace-event-perl.c +++ b/tools/perf/util/scripting-engines/trace-event-perl.c | |||
| @@ -247,6 +247,7 @@ static inline struct event *find_cache_event(int type) | |||
| 247 | 247 | ||
| 248 | static void perl_process_event(union perf_event *pevent __unused, | 248 | static void perl_process_event(union perf_event *pevent __unused, |
| 249 | struct perf_sample *sample, | 249 | struct perf_sample *sample, |
| 250 | struct perf_evsel *evsel, | ||
| 250 | struct perf_session *session __unused, | 251 | struct perf_session *session __unused, |
| 251 | struct thread *thread) | 252 | struct thread *thread) |
| 252 | { | 253 | { |
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 1b85d6055159..6ccf70e8d8f2 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
| @@ -206,6 +206,7 @@ static inline struct event *find_cache_event(int type) | |||
| 206 | 206 | ||
| 207 | static void python_process_event(union perf_event *pevent __unused, | 207 | static void python_process_event(union perf_event *pevent __unused, |
| 208 | struct perf_sample *sample, | 208 | struct perf_sample *sample, |
| 209 | struct perf_evsel *evsel __unused, | ||
| 209 | struct perf_session *session __unused, | 210 | struct perf_session *session __unused, |
| 210 | struct thread *thread) | 211 | struct thread *thread) |
| 211 | { | 212 | { |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index c68cf40764f9..caa224522fea 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
| @@ -280,6 +280,15 @@ static int process_event_synth_stub(union perf_event *event __used, | |||
| 280 | return 0; | 280 | return 0; |
| 281 | } | 281 | } |
| 282 | 282 | ||
| 283 | static int process_event_sample_stub(union perf_event *event __used, | ||
| 284 | struct perf_sample *sample __used, | ||
| 285 | struct perf_evsel *evsel __used, | ||
| 286 | struct perf_session *session __used) | ||
| 287 | { | ||
| 288 | dump_printf(": unhandled!\n"); | ||
| 289 | return 0; | ||
| 290 | } | ||
| 291 | |||
| 283 | static int process_event_stub(union perf_event *event __used, | 292 | static int process_event_stub(union perf_event *event __used, |
| 284 | struct perf_sample *sample __used, | 293 | struct perf_sample *sample __used, |
| 285 | struct perf_session *session __used) | 294 | struct perf_session *session __used) |
| @@ -303,7 +312,7 @@ static int process_finished_round(union perf_event *event, | |||
| 303 | static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) | 312 | static void perf_event_ops__fill_defaults(struct perf_event_ops *handler) |
| 304 | { | 313 | { |
| 305 | if (handler->sample == NULL) | 314 | if (handler->sample == NULL) |
| 306 | handler->sample = process_event_stub; | 315 | handler->sample = process_event_sample_stub; |
| 307 | if (handler->mmap == NULL) | 316 | if (handler->mmap == NULL) |
| 308 | handler->mmap = process_event_stub; | 317 | handler->mmap = process_event_stub; |
| 309 | if (handler->comm == NULL) | 318 | if (handler->comm == NULL) |
| @@ -698,12 +707,19 @@ static int perf_session_deliver_event(struct perf_session *session, | |||
| 698 | struct perf_event_ops *ops, | 707 | struct perf_event_ops *ops, |
| 699 | u64 file_offset) | 708 | u64 file_offset) |
| 700 | { | 709 | { |
| 710 | struct perf_evsel *evsel; | ||
| 711 | |||
| 701 | dump_event(session, event, file_offset, sample); | 712 | dump_event(session, event, file_offset, sample); |
| 702 | 713 | ||
| 703 | switch (event->header.type) { | 714 | switch (event->header.type) { |
| 704 | case PERF_RECORD_SAMPLE: | 715 | case PERF_RECORD_SAMPLE: |
| 705 | dump_sample(session, event, sample); | 716 | dump_sample(session, event, sample); |
| 706 | return ops->sample(event, sample, session); | 717 | evsel = perf_evlist__id2evsel(session->evlist, sample->id); |
| 718 | if (evsel == NULL) { | ||
| 719 | ++session->hists.stats.nr_unknown_id; | ||
| 720 | return -1; | ||
| 721 | } | ||
| 722 | return ops->sample(event, sample, evsel, session); | ||
| 707 | case PERF_RECORD_MMAP: | 723 | case PERF_RECORD_MMAP: |
| 708 | return ops->mmap(event, sample, session); | 724 | return ops->mmap(event, sample, session); |
| 709 | case PERF_RECORD_COMM: | 725 | case PERF_RECORD_COMM: |
| @@ -845,6 +861,11 @@ static void perf_session__warn_about_errors(const struct perf_session *session, | |||
| 845 | session->hists.stats.nr_unknown_events); | 861 | session->hists.stats.nr_unknown_events); |
| 846 | } | 862 | } |
| 847 | 863 | ||
| 864 | if (session->hists.stats.nr_unknown_id != 0) { | ||
| 865 | ui__warning("%u samples with id not present in the header\n", | ||
| 866 | session->hists.stats.nr_unknown_id); | ||
| 867 | } | ||
| 868 | |||
| 848 | if (session->hists.stats.nr_invalid_chains != 0) { | 869 | if (session->hists.stats.nr_invalid_chains != 0) { |
| 849 | ui__warning("Found invalid callchains!\n\n" | 870 | ui__warning("Found invalid callchains!\n\n" |
| 850 | "%u out of %u events were discarded for this reason.\n\n" | 871 | "%u out of %u events were discarded for this reason.\n\n" |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 0b3c9afecaa9..1ac481fc1100 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
| @@ -55,8 +55,11 @@ struct perf_session { | |||
| 55 | char filename[0]; | 55 | char filename[0]; |
| 56 | }; | 56 | }; |
| 57 | 57 | ||
| 58 | struct perf_evsel; | ||
| 58 | struct perf_event_ops; | 59 | struct perf_event_ops; |
| 59 | 60 | ||
| 61 | typedef int (*event_sample)(union perf_event *event, struct perf_sample *sample, | ||
| 62 | struct perf_evsel *evsel, struct perf_session *session); | ||
| 60 | typedef int (*event_op)(union perf_event *self, struct perf_sample *sample, | 63 | typedef int (*event_op)(union perf_event *self, struct perf_sample *sample, |
| 61 | struct perf_session *session); | 64 | struct perf_session *session); |
| 62 | typedef int (*event_synth_op)(union perf_event *self, | 65 | typedef int (*event_synth_op)(union perf_event *self, |
| @@ -65,8 +68,8 @@ typedef int (*event_op2)(union perf_event *self, struct perf_session *session, | |||
| 65 | struct perf_event_ops *ops); | 68 | struct perf_event_ops *ops); |
| 66 | 69 | ||
| 67 | struct perf_event_ops { | 70 | struct perf_event_ops { |
| 68 | event_op sample, | 71 | event_sample sample; |
| 69 | mmap, | 72 | event_op mmap, |
| 70 | comm, | 73 | comm, |
| 71 | fork, | 74 | fork, |
| 72 | exit, | 75 | exit, |
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py index e24ffadb20b2..bbc982f5dd8b 100644 --- a/tools/perf/util/setup.py +++ b/tools/perf/util/setup.py | |||
| @@ -1,13 +1,18 @@ | |||
| 1 | #!/usr/bin/python2 | 1 | #!/usr/bin/python2 |
| 2 | 2 | ||
| 3 | from distutils.core import setup, Extension | 3 | from distutils.core import setup, Extension |
| 4 | from os import getenv | ||
| 5 | |||
| 6 | cflags = ['-fno-strict-aliasing', '-Wno-write-strings'] | ||
| 7 | cflags += getenv('CFLAGS', '').split() | ||
| 4 | 8 | ||
| 5 | perf = Extension('perf', | 9 | perf = Extension('perf', |
| 6 | sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', | 10 | sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', |
| 7 | 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c', | 11 | 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c', |
| 8 | 'util/util.c', 'util/xyarray.c', 'util/cgroup.c'], | 12 | 'util/util.c', 'util/xyarray.c', 'util/cgroup.c'], |
| 9 | include_dirs = ['util/include'], | 13 | include_dirs = ['util/include'], |
| 10 | extra_compile_args = ['-fno-strict-aliasing', '-Wno-write-strings']) | 14 | extra_compile_args = cflags, |
| 15 | ) | ||
| 11 | 16 | ||
| 12 | setup(name='perf', | 17 | setup(name='perf', |
| 13 | version='0.1', | 18 | version='0.1', |
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c index 8fc0bd3a3a4a..b9a985dadd08 100644 --- a/tools/perf/util/string.c +++ b/tools/perf/util/string.c | |||
| @@ -85,7 +85,7 @@ out: | |||
| 85 | 85 | ||
| 86 | /* | 86 | /* |
| 87 | * Helper function for splitting a string into an argv-like array. | 87 | * Helper function for splitting a string into an argv-like array. |
| 88 | * originaly copied from lib/argv_split.c | 88 | * originally copied from lib/argv_split.c |
| 89 | */ | 89 | */ |
| 90 | static const char *skip_sep(const char *cp) | 90 | static const char *skip_sep(const char *cp) |
| 91 | { | 91 | { |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 651dbfe7f4f3..f06c10f092ba 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -1196,6 +1196,8 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
| 1196 | if (curr_dso == NULL) | 1196 | if (curr_dso == NULL) |
| 1197 | goto out_elf_end; | 1197 | goto out_elf_end; |
| 1198 | curr_dso->kernel = self->kernel; | 1198 | curr_dso->kernel = self->kernel; |
| 1199 | curr_dso->long_name = self->long_name; | ||
| 1200 | curr_dso->long_name_len = self->long_name_len; | ||
| 1199 | curr_map = map__new2(start, curr_dso, | 1201 | curr_map = map__new2(start, curr_dso, |
| 1200 | map->type); | 1202 | map->type); |
| 1201 | if (curr_map == NULL) { | 1203 | if (curr_map == NULL) { |
| @@ -1486,7 +1488,9 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
| 1486 | * On the first pass, only load images if they have a full symtab. | 1488 | * On the first pass, only load images if they have a full symtab. |
| 1487 | * Failing that, do a second pass where we accept .dynsym also | 1489 | * Failing that, do a second pass where we accept .dynsym also |
| 1488 | */ | 1490 | */ |
| 1489 | for (self->symtab_type = SYMTAB__BUILD_ID_CACHE, want_symtab = 1; | 1491 | want_symtab = 1; |
| 1492 | restart: | ||
| 1493 | for (self->symtab_type = SYMTAB__BUILD_ID_CACHE; | ||
| 1490 | self->symtab_type != SYMTAB__NOT_FOUND; | 1494 | self->symtab_type != SYMTAB__NOT_FOUND; |
| 1491 | self->symtab_type++) { | 1495 | self->symtab_type++) { |
| 1492 | switch (self->symtab_type) { | 1496 | switch (self->symtab_type) { |
| @@ -1536,17 +1540,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
| 1536 | snprintf(name, size, "%s%s", symbol_conf.symfs, | 1540 | snprintf(name, size, "%s%s", symbol_conf.symfs, |
| 1537 | self->long_name); | 1541 | self->long_name); |
| 1538 | break; | 1542 | break; |
| 1539 | 1543 | default:; | |
| 1540 | default: | ||
| 1541 | /* | ||
| 1542 | * If we wanted a full symtab but no image had one, | ||
| 1543 | * relax our requirements and repeat the search. | ||
| 1544 | */ | ||
| 1545 | if (want_symtab) { | ||
| 1546 | want_symtab = 0; | ||
| 1547 | self->symtab_type = SYMTAB__BUILD_ID_CACHE; | ||
| 1548 | } else | ||
| 1549 | continue; | ||
| 1550 | } | 1544 | } |
| 1551 | 1545 | ||
| 1552 | /* Name is now the name of the next image to try */ | 1546 | /* Name is now the name of the next image to try */ |
| @@ -1573,6 +1567,15 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
| 1573 | } | 1567 | } |
| 1574 | } | 1568 | } |
| 1575 | 1569 | ||
| 1570 | /* | ||
| 1571 | * If we wanted a full symtab but no image had one, | ||
| 1572 | * relax our requirements and repeat the search. | ||
| 1573 | */ | ||
| 1574 | if (ret <= 0 && want_symtab) { | ||
| 1575 | want_symtab = 0; | ||
| 1576 | goto restart; | ||
| 1577 | } | ||
| 1578 | |||
| 1576 | free(name); | 1579 | free(name); |
| 1577 | if (ret < 0 && strstr(self->name, " (deleted)") != NULL) | 1580 | if (ret < 0 && strstr(self->name, " (deleted)") != NULL) |
| 1578 | return 0; | 1581 | return 0; |
| @@ -1841,6 +1844,7 @@ int dso__load_vmlinux(struct dso *self, struct map *map, | |||
| 1841 | if (fd < 0) | 1844 | if (fd < 0) |
| 1842 | return -1; | 1845 | return -1; |
| 1843 | 1846 | ||
| 1847 | dso__set_long_name(self, (char *)vmlinux); | ||
| 1844 | dso__set_loaded(self, map->type); | 1848 | dso__set_loaded(self, map->type); |
| 1845 | err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0); | 1849 | err = dso__load_sym(self, map, symfs_vmlinux, fd, filter, 0, 0); |
| 1846 | close(fd); | 1850 | close(fd); |
| @@ -2402,6 +2406,8 @@ int symbol__init(void) | |||
| 2402 | if (symbol_conf.initialized) | 2406 | if (symbol_conf.initialized) |
| 2403 | return 0; | 2407 | return 0; |
| 2404 | 2408 | ||
| 2409 | symbol_conf.priv_size = ALIGN(symbol_conf.priv_size, sizeof(u64)); | ||
| 2410 | |||
| 2405 | elf_version(EV_CURRENT); | 2411 | elf_version(EV_CURRENT); |
| 2406 | if (symbol_conf.sort_by_name) | 2412 | if (symbol_conf.sort_by_name) |
| 2407 | symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - | 2413 | symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - |
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c index 66f4b78737ab..c9dcbec7d800 100644 --- a/tools/perf/util/trace-event-scripting.c +++ b/tools/perf/util/trace-event-scripting.c | |||
| @@ -38,6 +38,7 @@ static int stop_script_unsupported(void) | |||
| 38 | 38 | ||
| 39 | static void process_event_unsupported(union perf_event *event __unused, | 39 | static void process_event_unsupported(union perf_event *event __unused, |
| 40 | struct perf_sample *sample __unused, | 40 | struct perf_sample *sample __unused, |
| 41 | struct perf_evsel *evsel __unused, | ||
| 41 | struct perf_session *session __unused, | 42 | struct perf_session *session __unused, |
| 42 | struct thread *thread __unused) | 43 | struct thread *thread __unused) |
| 43 | { | 44 | { |
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h index b04da5722437..f674dda3363b 100644 --- a/tools/perf/util/trace-event.h +++ b/tools/perf/util/trace-event.h | |||
| @@ -280,6 +280,7 @@ struct scripting_ops { | |||
| 280 | int (*stop_script) (void); | 280 | int (*stop_script) (void); |
| 281 | void (*process_event) (union perf_event *event, | 281 | void (*process_event) (union perf_event *event, |
| 282 | struct perf_sample *sample, | 282 | struct perf_sample *sample, |
| 283 | struct perf_evsel *evsel, | ||
| 283 | struct perf_session *session, | 284 | struct perf_session *session, |
| 284 | struct thread *thread); | 285 | struct thread *thread); |
| 285 | int (*generate_script) (const char *outfile); | 286 | int (*generate_script) (const char *outfile); |
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index 8c17a8730e4a..15633d608133 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c | |||
| @@ -256,10 +256,9 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, | |||
| 256 | int refresh) | 256 | int refresh) |
| 257 | { | 257 | { |
| 258 | struct objdump_line *pos, *n; | 258 | struct objdump_line *pos, *n; |
| 259 | struct annotation *notes = symbol__annotation(sym); | 259 | struct annotation *notes; |
| 260 | struct annotate_browser browser = { | 260 | struct annotate_browser browser = { |
| 261 | .b = { | 261 | .b = { |
| 262 | .entries = ¬es->src->source, | ||
| 263 | .refresh = ui_browser__list_head_refresh, | 262 | .refresh = ui_browser__list_head_refresh, |
| 264 | .seek = ui_browser__list_head_seek, | 263 | .seek = ui_browser__list_head_seek, |
| 265 | .write = annotate_browser__write, | 264 | .write = annotate_browser__write, |
| @@ -281,6 +280,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, | |||
| 281 | 280 | ||
| 282 | ui_helpline__push("Press <- or ESC to exit"); | 281 | ui_helpline__push("Press <- or ESC to exit"); |
| 283 | 282 | ||
| 283 | notes = symbol__annotation(sym); | ||
| 284 | |||
| 284 | list_for_each_entry(pos, ¬es->src->source, node) { | 285 | list_for_each_entry(pos, ¬es->src->source, node) { |
| 285 | struct objdump_line_rb_node *rbpos; | 286 | struct objdump_line_rb_node *rbpos; |
| 286 | size_t line_len = strlen(pos->line); | 287 | size_t line_len = strlen(pos->line); |
| @@ -291,6 +292,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, | |||
| 291 | rbpos->idx = browser.b.nr_entries++; | 292 | rbpos->idx = browser.b.nr_entries++; |
| 292 | } | 293 | } |
| 293 | 294 | ||
| 295 | browser.b.entries = ¬es->src->source, | ||
| 294 | browser.b.width += 18; /* Percentage */ | 296 | browser.b.width += 18; /* Percentage */ |
| 295 | ret = annotate_browser__run(&browser, evidx, refresh); | 297 | ret = annotate_browser__run(&browser, evidx, refresh); |
| 296 | list_for_each_entry_safe(pos, n, ¬es->src->source, node) { | 298 | list_for_each_entry_safe(pos, n, ¬es->src->source, node) { |
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c index 798efdca3ead..5d767c622dfc 100644 --- a/tools/perf/util/ui/browsers/hists.c +++ b/tools/perf/util/ui/browsers/hists.c | |||
| @@ -851,7 +851,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, | |||
| 851 | goto out_free_stack; | 851 | goto out_free_stack; |
| 852 | case 'a': | 852 | case 'a': |
| 853 | if (browser->selection == NULL || | 853 | if (browser->selection == NULL || |
| 854 | browser->selection->map == NULL || | 854 | browser->selection->sym == NULL || |
| 855 | browser->selection->map->dso->annotate_warned) | 855 | browser->selection->map->dso->annotate_warned) |
| 856 | continue; | 856 | continue; |
| 857 | goto do_annotate; | 857 | goto do_annotate; |
diff --git a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c index d9678a34dd70..2618ef2ba31f 100644 --- a/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c +++ b/tools/power/x86/x86_energy_perf_policy/x86_energy_perf_policy.c | |||
| @@ -46,7 +46,7 @@ int cpu = -1; | |||
| 46 | * | 46 | * |
| 47 | * performance | 47 | * performance |
| 48 | * Performance is paramount. | 48 | * Performance is paramount. |
| 49 | * Unwilling to sacrafice any performance | 49 | * Unwilling to sacrifice any performance |
| 50 | * for the sake of energy saving. (hardware default) | 50 | * for the sake of energy saving. (hardware default) |
| 51 | * | 51 | * |
| 52 | * normal | 52 | * normal |
