diff options
Diffstat (limited to 'tools/perf/util')
| -rw-r--r-- | tools/perf/util/hist.c | 72 | ||||
| -rw-r--r-- | tools/perf/util/hist.h | 14 | ||||
| -rw-r--r-- | tools/perf/util/jitdump.c | 29 | ||||
| -rw-r--r-- | tools/perf/util/parse-events.y | 2 | ||||
| -rw-r--r-- | tools/perf/util/session.c | 40 | ||||
| -rw-r--r-- | tools/perf/util/sort.c | 146 | ||||
| -rw-r--r-- | tools/perf/util/sort.h | 1 | ||||
| -rw-r--r-- | tools/perf/util/tsc.c | 2 |
8 files changed, 202 insertions, 104 deletions
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 4b8b67bc0cd8..29da9e0d8db9 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -1091,18 +1091,25 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he); static struct hist_entry *hierarchy_insert_entry(struct hists *hists, struct rb_root *root, struct hist_entry *he, - struct perf_hpp_fmt *fmt) + struct perf_hpp_list *hpp_list) { struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct hist_entry *iter, *new; + struct perf_hpp_fmt *fmt; int64_t cmp; while (*p != NULL) { parent = *p; iter = rb_entry(parent, struct hist_entry, rb_node_in); - cmp = fmt->collapse(fmt, iter, he); + cmp = 0; + perf_hpp_list__for_each_sort_list(hpp_list, fmt) { + cmp = fmt->collapse(fmt, iter, he); + if (cmp) + break; + } + if (!cmp) { he_stat__add_stat(&iter->stat, &he->stat); return iter; @@ -1121,24 +1128,26 @@ static struct hist_entry *hierarchy_insert_entry(struct hists *hists, hists__apply_filters(hists, new); hists->nr_entries++; - /* save related format for output */ - new->fmt = fmt; + /* save related format list for output */ + new->hpp_list = hpp_list; /* some fields are now passed to 'new' */ - if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt)) - he->trace_output = NULL; - else - new->trace_output = NULL; + perf_hpp_list__for_each_sort_list(hpp_list, fmt) { + if (perf_hpp__is_trace_entry(fmt) || perf_hpp__is_dynamic_entry(fmt)) + he->trace_output = NULL; + else + new->trace_output = NULL; - if (perf_hpp__is_srcline_entry(fmt)) - he->srcline = NULL; - else - new->srcline = NULL; + if (perf_hpp__is_srcline_entry(fmt)) + he->srcline = NULL; + else + new->srcline = NULL; - if (perf_hpp__is_srcfile_entry(fmt)) - he->srcfile = NULL; - else - new->srcfile = NULL; + if (perf_hpp__is_srcfile_entry(fmt)) + he->srcfile = NULL; + else + new->srcfile = NULL; + } rb_link_node(&new->rb_node_in, parent, p); rb_insert_color(&new->rb_node_in, root); @@ -1149,21 +1158,19 @@ static int hists__hierarchy_insert_entry(struct hists *hists, struct rb_root *root, struct hist_entry *he) { - struct perf_hpp_fmt *fmt; + struct perf_hpp_list_node *node; struct hist_entry *new_he = NULL; struct hist_entry *parent = NULL; int depth = 0; int ret = 0; - hists__for_each_sort_list(hists, fmt) { - if (!perf_hpp__is_sort_entry(fmt) && - !perf_hpp__is_dynamic_entry(fmt)) - continue; - if (perf_hpp__should_skip(fmt, hists)) + list_for_each_entry(node, &hists->hpp_formats, list) { + /* skip period (overhead) and elided columns */ + if (node->level == 0 || node->skip) continue; /* insert copy of 'he' for each fmt into the hierarchy */ - new_he = hierarchy_insert_entry(hists, root, he, fmt); + new_he = hierarchy_insert_entry(hists, root, he, &node->hpp); if (new_he == NULL) { ret = -1; break; @@ -1358,6 +1365,7 @@ static void hierarchy_insert_output_entry(struct rb_root *root, struct rb_node **p = &root->rb_node; struct rb_node *parent = NULL; struct hist_entry *iter; + struct perf_hpp_fmt *fmt; while (*p != NULL) { parent = *p; @@ -1373,8 +1381,10 @@ static void hierarchy_insert_output_entry(struct rb_root *root, rb_insert_color(&he->rb_node, root); /* update column width of dynamic entry */ - if (perf_hpp__is_dynamic_entry(he->fmt)) - he->fmt->sort(he->fmt, he, NULL); + perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) { + if (perf_hpp__is_dynamic_entry(fmt)) + fmt->sort(fmt, he, NULL); + } } static void hists__hierarchy_output_resort(struct hists *hists, @@ -2105,6 +2115,7 @@ int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list) pthread_mutex_init(&hists->lock, NULL); hists->socket_filter = -1; hists->hpp_list = hpp_list; + INIT_LIST_HEAD(&hists->hpp_formats); return 0; } @@ -2133,8 +2144,19 @@ static void hists__delete_all_entries(struct hists *hists) static void hists_evsel__exit(struct perf_evsel *evsel) { struct hists *hists = evsel__hists(evsel); + struct perf_hpp_fmt *fmt, *pos; + struct perf_hpp_list_node *node, *tmp; hists__delete_all_entries(hists); + + list_for_each_entry_safe(node, tmp, &hists->hpp_formats, list) { + perf_hpp_list__for_each_format_safe(&node->hpp, fmt, pos) { + list_del(&fmt->list); + free(fmt); + } + list_del(&node->list); + free(node); + } } static int hists_evsel__init(struct perf_evsel *evsel) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index da5e50586bfd..2cb017f28f9e 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -78,7 +78,9 @@ struct hists { u16 col_len[HISTC_NR_COLS]; int socket_filter; struct perf_hpp_list *hpp_list; + struct list_head hpp_formats; int nr_sort_keys; + int nr_hpp_node; }; struct hist_entry_iter; @@ -233,6 +235,7 @@ struct perf_hpp_fmt { int len; int user_len; int idx; + int level; }; struct perf_hpp_list { @@ -243,6 +246,13 @@ struct perf_hpp_list { extern struct perf_hpp_list perf_hpp_list; +struct perf_hpp_list_node { + struct list_head list; + struct perf_hpp_list hpp; + int level; + bool skip; +}; + void perf_hpp_list__column_register(struct perf_hpp_list *list, struct perf_hpp_fmt *format); void perf_hpp_list__register_sort_field(struct perf_hpp_list *list, @@ -298,6 +308,8 @@ void perf_hpp__cancel_cumulate(void); void perf_hpp__setup_output_field(struct perf_hpp_list *list); void perf_hpp__reset_output_field(struct perf_hpp_list *list); void perf_hpp__append_sort_keys(struct perf_hpp_list *list); +int perf_hpp__setup_hists_formats(struct perf_hpp_list *list, + struct perf_evlist *evlist); bool perf_hpp__is_sort_entry(struct perf_hpp_fmt *format); @@ -307,6 +319,8 @@ bool perf_hpp__is_trace_entry(struct perf_hpp_fmt *fmt); bool perf_hpp__is_srcline_entry(struct perf_hpp_fmt *fmt); bool perf_hpp__is_srcfile_entry(struct perf_hpp_fmt *fmt); +struct perf_hpp_fmt *perf_hpp_fmt__dup(struct perf_hpp_fmt *fmt); + int hist_entry__filter(struct hist_entry *he, int type, const void *arg); static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format, diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c index 99fa5eee9fe0..cd272cc21e05 100644 --- a/tools/perf/util/jitdump.c +++ b/tools/perf/util/jitdump.c @@ -99,6 +99,21 @@ jit_close(struct jit_buf_desc *jd) } static int +jit_validate_events(struct perf_session *session) +{ + struct perf_evsel *evsel; + + /* + * check that all events use CLOCK_MONOTONIC + */ + evlist__for_each(session->evlist, evsel) { + if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC) + return -1; + } + return 0; +} + +static int jit_open(struct jit_buf_desc *jd, const char *name) { struct jitheader header; @@ -157,6 +172,14 @@ jit_open(struct jit_buf_desc *jd, const char *name) goto error; } + /* + * validate event is using the correct clockid + */ + if (jit_validate_events(jd->session)) { + pr_err("error, jitted code must be sampled with perf record -k 1\n"); + goto error; + } + bs = header.total_size - sizeof(header); if (bs > bsz) { @@ -647,7 +670,7 @@ jit_process(struct perf_session *session, * first, detect marker mmap (i.e., the jitdump mmap) */ if (jit_detect(filename, pid)) - return -1; + return 0; memset(&jd, 0, sizeof(jd)); @@ -665,8 +688,10 @@ jit_process(struct perf_session *session, *nbytes = 0; ret = jit_inject(&jd, filename); - if (!ret) + if (!ret) { *nbytes = jd.bytes_written; + ret = 1; + } return ret; } diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 85c44ba79cad..5be4a5f216d6 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -28,7 +28,7 @@ do { \ INIT_LIST_HEAD(list); \ } while (0) -static inc_group_count(struct list_head *list, +static void inc_group_count(struct list_head *list, struct parse_events_evlist *data) { /* Count groups only have more than 1 members */ diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 40b7a0d0905b..60b3593d210d 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -240,14 +240,6 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused, return 0; } -static int process_build_id_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *session __maybe_unused) -{ - dump_printf(": unhandled!\n"); - return 0; -} - static int process_finished_round_stub(struct perf_tool *tool __maybe_unused, union perf_event *event __maybe_unused, struct ordered_events *oe __maybe_unused) @@ -260,23 +252,6 @@ static int process_finished_round(struct perf_tool *tool, union perf_event *event, struct ordered_events *oe); -static int process_id_index_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *perf_session - __maybe_unused) -{ - dump_printf(": unhandled!\n"); - return 0; -} - -static int process_event_auxtrace_info_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *session __maybe_unused) -{ - dump_printf(": unhandled!\n"); - return 0; -} - static int skipn(int fd, off_t n) { char buf[4096]; @@ -303,10 +278,9 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused, return event->auxtrace.size; } -static -int process_event_auxtrace_error_stub(struct perf_tool *tool __maybe_unused, - union perf_event *event __maybe_unused, - struct perf_session *session __maybe_unused) +static int process_event_op2_stub(struct perf_tool *tool __maybe_unused, + union perf_event *event __maybe_unused, + struct perf_session *session __maybe_unused) { dump_printf(": unhandled!\n"); return 0; @@ -410,7 +384,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool) if (tool->tracing_data == NULL) tool->tracing_data = process_event_synth_tracing_data_stub; if (tool->build_id == NULL) - tool->build_id = process_build_id_stub; + tool->build_id = process_event_op2_stub; if (tool->finished_round == NULL) { if (tool->ordered_events) tool->finished_round = process_finished_round; @@ -418,13 +392,13 @@ void perf_tool__fill_defaults(struct perf_tool *tool) tool->finished_round = process_finished_round_stub; } if (tool->id_index == NULL) - tool->id_index = process_id_index_stub; + tool->id_index = process_event_op2_stub; if (tool->auxtrace_info == NULL) - tool->auxtrace_info = process_event_auxtrace_info_stub; + tool->auxtrace_info = process_event_op2_stub; if (tool->auxtrace == NULL) tool->auxtrace = process_event_auxtrace_stub; if (tool->auxtrace_error == NULL) - tool->auxtrace_error = process_event_auxtrace_error_stub; + tool->auxtrace_error = process_event_op2_stub; if (tool->thread_map == NULL) tool->thread_map = process_event_thread_map_stub; if (tool->cpu_map == NULL) diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index 4380a2858802..041f236379e0 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c @@ -1544,7 +1544,7 @@ static void hse_free(struct perf_hpp_fmt *fmt) } static struct hpp_sort_entry * -__sort_dimension__alloc_hpp(struct sort_dimension *sd) +__sort_dimension__alloc_hpp(struct sort_dimension *sd, int level) { struct hpp_sort_entry *hse; @@ -1572,6 +1572,7 @@ __sort_dimension__alloc_hpp(struct sort_dimension *sd) hse->hpp.elide = false; hse->hpp.len = 0; hse->hpp.user_len = 0; + hse->hpp.level = level; return hse; } @@ -1581,7 +1582,8 @@ static void hpp_free(struct perf_hpp_fmt *fmt) free(fmt); } -static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd) +static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd, + int level) { struct perf_hpp_fmt *fmt; @@ -1590,6 +1592,7 @@ static struct perf_hpp_fmt *__hpp_dimension__alloc_hpp(struct hpp_dimension *hd) INIT_LIST_HEAD(&fmt->list); INIT_LIST_HEAD(&fmt->sort_list); fmt->free = hpp_free; + fmt->level = level; } return fmt; @@ -1611,9 +1614,9 @@ int hist_entry__filter(struct hist_entry *he, int type, const void *arg) return hse->se->se_filter(he, type, arg); } -static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd) +static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd, int level) { - struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd); + struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd, level); if (hse == NULL) return -1; @@ -1625,7 +1628,7 @@ static int __sort_dimension__add_hpp_sort(struct sort_dimension *sd) static int __sort_dimension__add_hpp_output(struct perf_hpp_list *list, struct sort_dimension *sd) { - struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd); + struct hpp_sort_entry *hse = __sort_dimension__alloc_hpp(sd, 0); if (hse == NULL) return -1; @@ -1868,7 +1871,8 @@ static void hde_free(struct perf_hpp_fmt *fmt) } static struct hpp_dynamic_entry * -__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field) +__alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field, + int level) { struct hpp_dynamic_entry *hde; @@ -1899,10 +1903,39 @@ __alloc_dynamic_entry(struct perf_evsel *evsel, struct format_field *field) hde->hpp.elide = false; hde->hpp.len = 0; hde->hpp.user_len = 0; + hde->hpp.level = level; return hde; } +struct perf_hpp_fmt *perf_hpp_fmt__dup(struct perf_hpp_fmt *fmt) +{ + struct perf_hpp_fmt *new_fmt = NULL; + + if (perf_hpp__is_sort_entry(fmt)) { + struct hpp_sort_entry *hse, *new_hse; + + hse = container_of(fmt, struct hpp_sort_entry, hpp); + new_hse = memdup(hse, sizeof(*hse)); + if (new_hse) + new_fmt = &new_hse->hpp; + } else if (perf_hpp__is_dynamic_entry(fmt)) { + struct hpp_dynamic_entry *hde, *new_hde; + + hde = container_of(fmt, struct hpp_dynamic_entry, hpp); + new_hde = memdup(hde, sizeof(*hde)); + if (new_hde) + new_fmt = &new_hde->hpp; + } else { + new_fmt = memdup(fmt, sizeof(*fmt)); + } + + INIT_LIST_HEAD(&new_fmt->list); + INIT_LIST_HEAD(&new_fmt->sort_list); + + return new_fmt; +} + static int parse_field_name(char *str, char **event, char **field, char **opt) { char *event_name, *field_name, *opt_name; @@ -1974,11 +2007,11 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam static int __dynamic_dimension__add(struct perf_evsel *evsel, struct format_field *field, - bool raw_trace) + bool raw_trace, int level) { struct hpp_dynamic_entry *hde; - hde = __alloc_dynamic_entry(evsel, field); + hde = __alloc_dynamic_entry(evsel, field, level); if (hde == NULL) return -ENOMEM; @@ -1988,14 +2021,14 @@ static int __dynamic_dimension__add(struct perf_evsel *evsel, return 0; } -static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace) +static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace, int level) { int ret; struct format_field *field; field = evsel->tp_format->format.fields; while (field) { - ret = __dynamic_dimension__add(evsel, field, raw_trace); + ret = __dynamic_dimension__add(evsel, field, raw_trace, level); if (ret < 0) return ret; @@ -2004,7 +2037,8 @@ static int add_evsel_fields(struct perf_evsel *evsel, bool raw_trace) return 0; } -static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace) +static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace, + int level) { int ret; struct perf_evsel *evsel; @@ -2013,7 +2047,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace) if (evsel->attr.type != PERF_TYPE_TRACEPOINT) continue; - ret = add_evsel_fields(evsel, raw_trace); + ret = add_evsel_fields(evsel, raw_trace, level); if (ret < 0) return ret; } @@ -2021,7 +2055,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace) } static int add_all_matching_fields(struct perf_evlist *evlist, - char *field_name, bool raw_trace) + char *field_name, bool raw_trace, int level) { int ret = -ESRCH; struct perf_evsel *evsel; @@ -2035,14 +2069,15 @@ static int add_all_matching_fields(struct perf_evlist *evlist, if (field == NULL) continue; - ret = __dynamic_dimension__add(evsel, field, raw_trace); + ret = __dynamic_dimension__add(evsel, field, raw_trace, level); if (ret < 0) break; } return ret; } -static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok) +static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok, + int level) { char *str, *event_name, *field_name, *opt_name; struct perf_evsel *evsel; @@ -2072,12 +2107,12 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok) } if (!strcmp(field_name, "trace_fields")) { - ret = add_all_dynamic_fields(evlist, raw_trace); + ret = add_all_dynamic_fields(evlist, raw_trace, level); goto out; } if (event_name == NULL) { - ret = add_all_matching_fields(evlist, field_name, raw_trace); + ret = add_all_matching_fields(evlist, field_name, raw_trace, level); goto out; } @@ -2095,7 +2130,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok) } if (!strcmp(field_name, "*")) { - ret = add_evsel_fields(evsel, raw_trace); + ret = add_evsel_fields(evsel, raw_trace, level); } else { field = pevent_find_any_field(evsel->tp_format, field_name); if (field == NULL) { @@ -2104,7 +2139,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok) return -ENOENT; } - ret = __dynamic_dimension__add(evsel, field, raw_trace); + ret = __dynamic_dimension__add(evsel, field, raw_trace, level); } out: @@ -2112,12 +2147,12 @@ out: return ret; } -static int __sort_dimension__add(struct sort_dimension *sd) +static int __sort_dimension__add(struct sort_dimension *sd, int level) { if (sd->taken) return 0; - if (__sort_dimension__add_hpp_sort(sd) < 0) + if (__sort_dimension__add_hpp_sort(sd, level) < 0) return -1; if (sd->entry->se_collapse) @@ -2128,14 +2163,14 @@ static int __sort_dimension__add(struct sort_dimension *sd) return 0; } -static int __hpp_dimension__add(struct hpp_dimension *hd) +static int __hpp_dimension__add(struct hpp_dimension *hd, int level) { struct perf_hpp_fmt *fmt; if (hd->taken) return 0; - fmt = __hpp_dimension__alloc_hpp(hd); + fmt = __hpp_dimension__alloc_hpp(hd, level); if (!fmt) return -1; @@ -2165,7 +2200,7 @@ static int __hpp_dimension__add_output(struct perf_hpp_list *list, if (hd->taken) return 0; - fmt = __hpp_dimension__alloc_hpp(hd); + fmt = __hpp_dimension__alloc_hpp(hd, 0); if (!fmt) return -1; @@ -2180,8 +2215,8 @@ int hpp_dimension__add_output(unsigned col) return __hpp_dimension__add_output(&perf_hpp_list, &hpp_sort_dimensions[col]); } -static int sort_dimension__add(const char *tok, - struct perf_evlist *evlist __maybe_unused) +static int sort_dimension__add(const char *tok, struct perf_evlist *evlist, + int level) { unsigned int i; @@ -2220,7 +2255,7 @@ static int sort_dimension__add(const char *tok, sort__has_thread = 1; } - return __sort_dimension__add(sd); + return __sort_dimension__add(sd, level); } for (i = 0; i < ARRAY_SIZE(hpp_sort_dimensions); i++) { @@ -2229,7 +2264,7 @@ static int sort_dimension__add(const char *tok, if (strncasecmp(tok, hd->name, strlen(tok))) continue; - return __hpp_dimension__add(hd); + return __hpp_dimension__add(hd, level); } for (i = 0; i < ARRAY_SIZE(bstack_sort_dimensions); i++) { @@ -2244,7 +2279,7 @@ static int sort_dimension__add(const char *tok, if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to) sort__has_sym = 1; - __sort_dimension__add(sd); + __sort_dimension__add(sd, level); return 0; } @@ -2260,11 +2295,11 @@ static int sort_dimension__add(const char *tok, if (sd->entry == &sort_mem_daddr_sym) sort__has_sym = 1; - __sort_dimension__add(sd); + __sort_dimension__add(sd, level); return 0; } - if (!add_dynamic_entry(evlist, tok)) + if (!add_dynamic_entry(evlist, tok, level)) return 0; return -ESRCH; @@ -2274,18 +2309,41 @@ static int setup_sort_list(char *str, struct perf_evlist *evlist) { char *tmp, *tok; int ret = 0; + int level = 0; + int next_level = 1; + bool in_group = false; + + do { + tok = str; + tmp = strpbrk(str, "{}, "); + if (tmp) { + if (in_group) + next_level = level; + else + next_level = level + 1; + + if (*tmp == '{') + in_group = true; + else if (*tmp == '}') + in_group = false; + + *tmp = '\0'; + str = tmp + 1; + } - for (tok = strtok_r(str, ", ", &tmp); - tok; tok = strtok_r(NULL, ", ", &tmp)) { - ret = sort_dimension__add(tok, evlist); - if (ret == -EINVAL) { - error("Invalid --sort key: `%s'", tok); - break; - } else if (ret == -ESRCH) { - error("Unknown --sort key: `%s'", tok); - break; + if (*tok) { + ret = sort_dimension__add(tok, evlist, level); + if (ret == -EINVAL) { + error("Invalid --sort key: `%s'", tok); + break; + } else if (ret == -ESRCH) { + error("Unknown --sort key: `%s'", tok); + break; + } } - } + + level = next_level; + } while (tmp); return ret; } @@ -2667,7 +2725,7 @@ int setup_sorting(struct perf_evlist *evlist) return err; if (parent_pattern != default_parent_pattern) { - err = sort_dimension__add("parent", evlist); + err = sort_dimension__add("parent", evlist, -1); if (err < 0) return err; } @@ -2692,6 +2750,10 @@ int setup_sorting(struct perf_evlist *evlist) /* and then copy output fields to sort keys */ perf_hpp__append_sort_keys(&perf_hpp_list); + /* setup hists-specific output fields */ + if (perf_hpp__setup_hists_formats(&perf_hpp_list, evlist) < 0) + return -1; + return 0; } diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 25a5529a94e4..ea1f722cffea 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -130,6 +130,7 @@ struct hist_entry { u32 raw_size; void *trace_output; struct perf_hpp_fmt *fmt; + struct perf_hpp_list *hpp_list; struct hist_entry *parent_he; union { /* this is for hierarchical entry structure */ diff --git a/tools/perf/util/tsc.c b/tools/perf/util/tsc.c index 4d4210d4e13d..1b741646eed0 100644 --- a/tools/perf/util/tsc.c +++ b/tools/perf/util/tsc.c @@ -19,7 +19,7 @@ u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc) u64 quot, rem; quot = cyc >> tc->time_shift; - rem = cyc & ((1 << tc->time_shift) - 1); + rem = cyc & (((u64)1 << tc->time_shift) - 1); return tc->time_zero + quot * tc->time_mult + ((rem * tc->time_mult) >> tc->time_shift); } |
