|
@@ -696,6 +696,94 @@ iter_finish_normal_entry(struct hist_entry_iter *iter, struct addr_location *al)
|
|
|
return hist_entry__append_callchain(he, sample);
|
|
|
}
|
|
|
|
|
|
+static int
|
|
|
+iter_prepare_cumulative_entry(struct hist_entry_iter *iter __maybe_unused,
|
|
|
+ struct addr_location *al __maybe_unused)
|
|
|
+{
|
|
|
+ callchain_cursor_commit(&callchain_cursor);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
+ struct addr_location *al)
|
|
|
+{
|
|
|
+ struct perf_evsel *evsel = iter->evsel;
|
|
|
+ struct perf_sample *sample = iter->sample;
|
|
|
+ struct hist_entry *he;
|
|
|
+ int err = 0;
|
|
|
+
|
|
|
+ he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL,
|
|
|
+ sample->period, sample->weight,
|
|
|
+ sample->transaction, true);
|
|
|
+ if (he == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ iter->he = he;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * The iter->he will be over-written after ->add_next_entry()
|
|
|
+ * called so inc stats for the original entry now.
|
|
|
+ */
|
|
|
+ if (ui__has_annotation())
|
|
|
+ err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
|
|
+
|
|
|
+ hists__inc_nr_samples(&evsel->hists, he->filtered);
|
|
|
+
|
|
|
+ return err;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+iter_next_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
+ struct addr_location *al)
|
|
|
+{
|
|
|
+ struct callchain_cursor_node *node;
|
|
|
+
|
|
|
+ node = callchain_cursor_current(&callchain_cursor);
|
|
|
+ if (node == NULL)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ al->map = node->map;
|
|
|
+ al->sym = node->sym;
|
|
|
+ if (node->map)
|
|
|
+ al->addr = node->map->map_ip(node->map, node->ip);
|
|
|
+ else
|
|
|
+ al->addr = node->ip;
|
|
|
+
|
|
|
+ if (iter->hide_unresolved && al->sym == NULL)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ callchain_cursor_advance(&callchain_cursor);
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
+ struct addr_location *al)
|
|
|
+{
|
|
|
+ struct perf_evsel *evsel = iter->evsel;
|
|
|
+ struct perf_sample *sample = iter->sample;
|
|
|
+ struct hist_entry *he;
|
|
|
+
|
|
|
+ he = __hists__add_entry(&evsel->hists, al, iter->parent, NULL, NULL,
|
|
|
+ sample->period, sample->weight,
|
|
|
+ sample->transaction, false);
|
|
|
+ if (he == NULL)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ iter->he = he;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+iter_finish_cumulative_entry(struct hist_entry_iter *iter,
|
|
|
+ struct addr_location *al __maybe_unused)
|
|
|
+{
|
|
|
+ iter->he = NULL;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
const struct hist_iter_ops hist_iter_mem = {
|
|
|
.prepare_entry = iter_prepare_mem_entry,
|
|
|
.add_single_entry = iter_add_single_mem_entry,
|
|
@@ -720,6 +808,14 @@ const struct hist_iter_ops hist_iter_normal = {
|
|
|
.finish_entry = iter_finish_normal_entry,
|
|
|
};
|
|
|
|
|
|
+const struct hist_iter_ops hist_iter_cumulative = {
|
|
|
+ .prepare_entry = iter_prepare_cumulative_entry,
|
|
|
+ .add_single_entry = iter_add_single_cumulative_entry,
|
|
|
+ .next_entry = iter_next_cumulative_entry,
|
|
|
+ .add_next_entry = iter_add_next_cumulative_entry,
|
|
|
+ .finish_entry = iter_finish_cumulative_entry,
|
|
|
+};
|
|
|
+
|
|
|
int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
|
|
|
struct perf_evsel *evsel, struct perf_sample *sample,
|
|
|
int max_stack_depth)
|