|
@@ -196,6 +196,12 @@ static void perf_top__record_precise_ip(struct perf_top *top,
|
|
|
|
|
|
pthread_mutex_unlock(¬es->lock);
|
|
pthread_mutex_unlock(¬es->lock);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * This function is now called with he->hists->lock held.
|
|
|
|
+ * Release it before going to sleep.
|
|
|
|
+ */
|
|
|
|
+ pthread_mutex_unlock(&he->hists->lock);
|
|
|
|
+
|
|
if (err == -ERANGE && !he->ms.map->erange_warned)
|
|
if (err == -ERANGE && !he->ms.map->erange_warned)
|
|
ui__warn_map_erange(he->ms.map, sym, ip);
|
|
ui__warn_map_erange(he->ms.map, sym, ip);
|
|
else if (err == -ENOMEM) {
|
|
else if (err == -ENOMEM) {
|
|
@@ -203,6 +209,8 @@ static void perf_top__record_precise_ip(struct perf_top *top,
|
|
sym->name);
|
|
sym->name);
|
|
sleep(1);
|
|
sleep(1);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ pthread_mutex_lock(&he->hists->lock);
|
|
}
|
|
}
|
|
|
|
|
|
static void perf_top__show_details(struct perf_top *top)
|
|
static void perf_top__show_details(struct perf_top *top)
|
|
@@ -238,24 +246,6 @@ out_unlock:
|
|
pthread_mutex_unlock(¬es->lock);
|
|
pthread_mutex_unlock(¬es->lock);
|
|
}
|
|
}
|
|
|
|
|
|
-static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
|
|
|
|
- struct addr_location *al,
|
|
|
|
- struct perf_sample *sample)
|
|
|
|
-{
|
|
|
|
- struct hist_entry *he;
|
|
|
|
-
|
|
|
|
- pthread_mutex_lock(&evsel->hists.lock);
|
|
|
|
- he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL,
|
|
|
|
- sample->period, sample->weight,
|
|
|
|
- sample->transaction, true);
|
|
|
|
- pthread_mutex_unlock(&evsel->hists.lock);
|
|
|
|
- if (he == NULL)
|
|
|
|
- return NULL;
|
|
|
|
-
|
|
|
|
- hists__inc_nr_samples(&evsel->hists, he->filtered);
|
|
|
|
- return he;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static void perf_top__print_sym_table(struct perf_top *top)
|
|
static void perf_top__print_sym_table(struct perf_top *top)
|
|
{
|
|
{
|
|
char bf[160];
|
|
char bf[160];
|
|
@@ -659,6 +649,26 @@ static int symbol_filter(struct map *map __maybe_unused, struct symbol *sym)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int hist_iter__top_callback(struct hist_entry_iter *iter,
|
|
|
|
+ struct addr_location *al, bool single,
|
|
|
|
+ void *arg)
|
|
|
|
+{
|
|
|
|
+ struct perf_top *top = arg;
|
|
|
|
+ struct hist_entry *he = iter->he;
|
|
|
|
+ struct perf_evsel *evsel = iter->evsel;
|
|
|
|
+
|
|
|
|
+ if (sort__has_sym && single) {
|
|
|
|
+ u64 ip = al->addr;
|
|
|
|
+
|
|
|
|
+ if (al->map)
|
|
|
|
+ ip = al->map->unmap_ip(al->map, ip);
|
|
|
|
+
|
|
|
|
+ perf_top__record_precise_ip(top, he, evsel->idx, ip);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static void perf_event__process_sample(struct perf_tool *tool,
|
|
static void perf_event__process_sample(struct perf_tool *tool,
|
|
const union perf_event *event,
|
|
const union perf_event *event,
|
|
struct perf_evsel *evsel,
|
|
struct perf_evsel *evsel,
|
|
@@ -666,8 +676,6 @@ static void perf_event__process_sample(struct perf_tool *tool,
|
|
struct machine *machine)
|
|
struct machine *machine)
|
|
{
|
|
{
|
|
struct perf_top *top = container_of(tool, struct perf_top, tool);
|
|
struct perf_top *top = container_of(tool, struct perf_top, tool);
|
|
- struct symbol *parent = NULL;
|
|
|
|
- u64 ip = sample->ip;
|
|
|
|
struct addr_location al;
|
|
struct addr_location al;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
@@ -742,25 +750,23 @@ static void perf_event__process_sample(struct perf_tool *tool,
|
|
}
|
|
}
|
|
|
|
|
|
if (al.sym == NULL || !al.sym->ignore) {
|
|
if (al.sym == NULL || !al.sym->ignore) {
|
|
- struct hist_entry *he;
|
|
|
|
|
|
+ struct hist_entry_iter iter = {
|
|
|
|
+ .add_entry_cb = hist_iter__top_callback,
|
|
|
|
+ };
|
|
|
|
|
|
- err = sample__resolve_callchain(sample, &parent, evsel, &al,
|
|
|
|
- top->max_stack);
|
|
|
|
- if (err)
|
|
|
|
- return;
|
|
|
|
|
|
+ if (symbol_conf.cumulate_callchain)
|
|
|
|
+ iter.ops = &hist_iter_cumulative;
|
|
|
|
+ else
|
|
|
|
+ iter.ops = &hist_iter_normal;
|
|
|
|
|
|
- he = perf_evsel__add_hist_entry(evsel, &al, sample);
|
|
|
|
- if (he == NULL) {
|
|
|
|
- pr_err("Problem incrementing symbol period, skipping event\n");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ pthread_mutex_lock(&evsel->hists.lock);
|
|
|
|
|
|
- err = hist_entry__append_callchain(he, sample);
|
|
|
|
- if (err)
|
|
|
|
- return;
|
|
|
|
|
|
+ err = hist_entry_iter__add(&iter, &al, evsel, sample,
|
|
|
|
+ top->max_stack, top);
|
|
|
|
+ if (err < 0)
|
|
|
|
+ pr_err("Problem incrementing symbol period, skipping event\n");
|
|
|
|
|
|
- if (sort__has_sym)
|
|
|
|
- perf_top__record_precise_ip(top, he, evsel->idx, ip);
|
|
|
|
|
|
+ pthread_mutex_unlock(&evsel->hists.lock);
|
|
}
|
|
}
|
|
|
|
|
|
return;
|
|
return;
|