18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * builtin-top.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Builtin top command: Display a continuously updated profile of
68c2ecf20Sopenharmony_ci * any workload, CPU or specific PID.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright (C) 2008, Red Hat Inc, Ingo Molnar <mingo@redhat.com>
98c2ecf20Sopenharmony_ci *		 2011, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * Improvements and fixes by:
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci *   Arjan van de Ven <arjan@linux.intel.com>
148c2ecf20Sopenharmony_ci *   Yanmin Zhang <yanmin.zhang@intel.com>
158c2ecf20Sopenharmony_ci *   Wu Fengguang <fengguang.wu@intel.com>
168c2ecf20Sopenharmony_ci *   Mike Galbraith <efault@gmx.de>
178c2ecf20Sopenharmony_ci *   Paul Mackerras <paulus@samba.org>
188c2ecf20Sopenharmony_ci */
198c2ecf20Sopenharmony_ci#include "builtin.h"
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include "perf.h"
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include "util/annotate.h"
248c2ecf20Sopenharmony_ci#include "util/bpf-event.h"
258c2ecf20Sopenharmony_ci#include "util/config.h"
268c2ecf20Sopenharmony_ci#include "util/color.h"
278c2ecf20Sopenharmony_ci#include "util/dso.h"
288c2ecf20Sopenharmony_ci#include "util/evlist.h"
298c2ecf20Sopenharmony_ci#include "util/evsel.h"
308c2ecf20Sopenharmony_ci#include "util/evsel_config.h"
318c2ecf20Sopenharmony_ci#include "util/event.h"
328c2ecf20Sopenharmony_ci#include "util/machine.h"
338c2ecf20Sopenharmony_ci#include "util/map.h"
348c2ecf20Sopenharmony_ci#include "util/mmap.h"
358c2ecf20Sopenharmony_ci#include "util/session.h"
368c2ecf20Sopenharmony_ci#include "util/thread.h"
378c2ecf20Sopenharmony_ci#include "util/symbol.h"
388c2ecf20Sopenharmony_ci#include "util/synthetic-events.h"
398c2ecf20Sopenharmony_ci#include "util/top.h"
408c2ecf20Sopenharmony_ci#include "util/util.h"
418c2ecf20Sopenharmony_ci#include <linux/rbtree.h>
428c2ecf20Sopenharmony_ci#include <subcmd/parse-options.h>
438c2ecf20Sopenharmony_ci#include "util/parse-events.h"
448c2ecf20Sopenharmony_ci#include "util/callchain.h"
458c2ecf20Sopenharmony_ci#include "util/cpumap.h"
468c2ecf20Sopenharmony_ci#include "util/sort.h"
478c2ecf20Sopenharmony_ci#include "util/string2.h"
488c2ecf20Sopenharmony_ci#include "util/term.h"
498c2ecf20Sopenharmony_ci#include "util/intlist.h"
508c2ecf20Sopenharmony_ci#include "util/parse-branch-options.h"
518c2ecf20Sopenharmony_ci#include "arch/common.h"
528c2ecf20Sopenharmony_ci#include "ui/ui.h"
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#include "util/debug.h"
558c2ecf20Sopenharmony_ci#include "util/ordered-events.h"
568c2ecf20Sopenharmony_ci#include "util/pfm.h"
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci#include <assert.h>
598c2ecf20Sopenharmony_ci#include <elf.h>
608c2ecf20Sopenharmony_ci#include <fcntl.h>
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#include <stdio.h>
638c2ecf20Sopenharmony_ci#include <termios.h>
648c2ecf20Sopenharmony_ci#include <unistd.h>
658c2ecf20Sopenharmony_ci#include <inttypes.h>
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#include <errno.h>
688c2ecf20Sopenharmony_ci#include <time.h>
698c2ecf20Sopenharmony_ci#include <sched.h>
708c2ecf20Sopenharmony_ci#include <signal.h>
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#include <sys/syscall.h>
738c2ecf20Sopenharmony_ci#include <sys/ioctl.h>
748c2ecf20Sopenharmony_ci#include <poll.h>
758c2ecf20Sopenharmony_ci#include <sys/prctl.h>
768c2ecf20Sopenharmony_ci#include <sys/wait.h>
778c2ecf20Sopenharmony_ci#include <sys/uio.h>
788c2ecf20Sopenharmony_ci#include <sys/utsname.h>
798c2ecf20Sopenharmony_ci#include <sys/mman.h>
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci#include <linux/stringify.h>
828c2ecf20Sopenharmony_ci#include <linux/time64.h>
838c2ecf20Sopenharmony_ci#include <linux/types.h>
848c2ecf20Sopenharmony_ci#include <linux/err.h>
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci#include <linux/ctype.h>
878c2ecf20Sopenharmony_ci#include <perf/mmap.h>
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistatic volatile int done;
908c2ecf20Sopenharmony_cistatic volatile int resize;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci#define HEADER_LINE_NR  5
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic void perf_top__update_print_entries(struct perf_top *top)
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	top->print_entries = top->winsize.ws_row - HEADER_LINE_NR;
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic void winch_sig(int sig __maybe_unused)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	resize = 1;
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic void perf_top__resize(struct perf_top *top)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	get_term_dimensions(&top->winsize);
1078c2ecf20Sopenharmony_ci	perf_top__update_print_entries(top);
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	struct evsel *evsel;
1138c2ecf20Sopenharmony_ci	struct symbol *sym;
1148c2ecf20Sopenharmony_ci	struct annotation *notes;
1158c2ecf20Sopenharmony_ci	struct map *map;
1168c2ecf20Sopenharmony_ci	int err = -1;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	if (!he || !he->ms.sym)
1198c2ecf20Sopenharmony_ci		return -1;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	evsel = hists_to_evsel(he->hists);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	sym = he->ms.sym;
1248c2ecf20Sopenharmony_ci	map = he->ms.map;
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	/*
1278c2ecf20Sopenharmony_ci	 * We can't annotate with just /proc/kallsyms
1288c2ecf20Sopenharmony_ci	 */
1298c2ecf20Sopenharmony_ci	if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1308c2ecf20Sopenharmony_ci	    !dso__is_kcore(map->dso)) {
1318c2ecf20Sopenharmony_ci		pr_err("Can't annotate %s: No vmlinux file was found in the "
1328c2ecf20Sopenharmony_ci		       "path\n", sym->name);
1338c2ecf20Sopenharmony_ci		sleep(1);
1348c2ecf20Sopenharmony_ci		return -1;
1358c2ecf20Sopenharmony_ci	}
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci	notes = symbol__annotation(sym);
1388c2ecf20Sopenharmony_ci	pthread_mutex_lock(&notes->lock);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	if (!symbol__hists(sym, top->evlist->core.nr_entries)) {
1418c2ecf20Sopenharmony_ci		pthread_mutex_unlock(&notes->lock);
1428c2ecf20Sopenharmony_ci		pr_err("Not enough memory for annotating '%s' symbol!\n",
1438c2ecf20Sopenharmony_ci		       sym->name);
1448c2ecf20Sopenharmony_ci		sleep(1);
1458c2ecf20Sopenharmony_ci		return err;
1468c2ecf20Sopenharmony_ci	}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	err = symbol__annotate(&he->ms, evsel, &top->annotation_opts, NULL);
1498c2ecf20Sopenharmony_ci	if (err == 0) {
1508c2ecf20Sopenharmony_ci		top->sym_filter_entry = he;
1518c2ecf20Sopenharmony_ci	} else {
1528c2ecf20Sopenharmony_ci		char msg[BUFSIZ];
1538c2ecf20Sopenharmony_ci		symbol__strerror_disassemble(&he->ms, err, msg, sizeof(msg));
1548c2ecf20Sopenharmony_ci		pr_err("Couldn't annotate %s: %s\n", sym->name, msg);
1558c2ecf20Sopenharmony_ci	}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	pthread_mutex_unlock(&notes->lock);
1588c2ecf20Sopenharmony_ci	return err;
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_cistatic void __zero_source_counters(struct hist_entry *he)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	struct symbol *sym = he->ms.sym;
1648c2ecf20Sopenharmony_ci	symbol__annotate_zero_histograms(sym);
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cistatic void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
1688c2ecf20Sopenharmony_ci{
1698c2ecf20Sopenharmony_ci	struct utsname uts;
1708c2ecf20Sopenharmony_ci	int err = uname(&uts);
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	ui__warning("Out of bounds address found:\n\n"
1738c2ecf20Sopenharmony_ci		    "Addr:   %" PRIx64 "\n"
1748c2ecf20Sopenharmony_ci		    "DSO:    %s %c\n"
1758c2ecf20Sopenharmony_ci		    "Map:    %" PRIx64 "-%" PRIx64 "\n"
1768c2ecf20Sopenharmony_ci		    "Symbol: %" PRIx64 "-%" PRIx64 " %c %s\n"
1778c2ecf20Sopenharmony_ci		    "Arch:   %s\n"
1788c2ecf20Sopenharmony_ci		    "Kernel: %s\n"
1798c2ecf20Sopenharmony_ci		    "Tools:  %s\n\n"
1808c2ecf20Sopenharmony_ci		    "Not all samples will be on the annotation output.\n\n"
1818c2ecf20Sopenharmony_ci		    "Please report to linux-kernel@vger.kernel.org\n",
1828c2ecf20Sopenharmony_ci		    ip, map->dso->long_name, dso__symtab_origin(map->dso),
1838c2ecf20Sopenharmony_ci		    map->start, map->end, sym->start, sym->end,
1848c2ecf20Sopenharmony_ci		    sym->binding == STB_GLOBAL ? 'g' :
1858c2ecf20Sopenharmony_ci		    sym->binding == STB_LOCAL  ? 'l' : 'w', sym->name,
1868c2ecf20Sopenharmony_ci		    err ? "[unknown]" : uts.machine,
1878c2ecf20Sopenharmony_ci		    err ? "[unknown]" : uts.release, perf_version_string);
1888c2ecf20Sopenharmony_ci	if (use_browser <= 0)
1898c2ecf20Sopenharmony_ci		sleep(5);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	map->erange_warned = true;
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cistatic void perf_top__record_precise_ip(struct perf_top *top,
1958c2ecf20Sopenharmony_ci					struct hist_entry *he,
1968c2ecf20Sopenharmony_ci					struct perf_sample *sample,
1978c2ecf20Sopenharmony_ci					struct evsel *evsel, u64 ip)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	struct annotation *notes;
2008c2ecf20Sopenharmony_ci	struct symbol *sym = he->ms.sym;
2018c2ecf20Sopenharmony_ci	int err = 0;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	if (sym == NULL || (use_browser == 0 &&
2048c2ecf20Sopenharmony_ci			    (top->sym_filter_entry == NULL ||
2058c2ecf20Sopenharmony_ci			     top->sym_filter_entry->ms.sym != sym)))
2068c2ecf20Sopenharmony_ci		return;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	notes = symbol__annotation(sym);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	if (pthread_mutex_trylock(&notes->lock))
2118c2ecf20Sopenharmony_ci		return;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	err = hist_entry__inc_addr_samples(he, sample, evsel, ip);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	pthread_mutex_unlock(&notes->lock);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	if (unlikely(err)) {
2188c2ecf20Sopenharmony_ci		/*
2198c2ecf20Sopenharmony_ci		 * This function is now called with he->hists->lock held.
2208c2ecf20Sopenharmony_ci		 * Release it before going to sleep.
2218c2ecf20Sopenharmony_ci		 */
2228c2ecf20Sopenharmony_ci		pthread_mutex_unlock(&he->hists->lock);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci		if (err == -ERANGE && !he->ms.map->erange_warned)
2258c2ecf20Sopenharmony_ci			ui__warn_map_erange(he->ms.map, sym, ip);
2268c2ecf20Sopenharmony_ci		else if (err == -ENOMEM) {
2278c2ecf20Sopenharmony_ci			pr_err("Not enough memory for annotating '%s' symbol!\n",
2288c2ecf20Sopenharmony_ci			       sym->name);
2298c2ecf20Sopenharmony_ci			sleep(1);
2308c2ecf20Sopenharmony_ci		}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci		pthread_mutex_lock(&he->hists->lock);
2338c2ecf20Sopenharmony_ci	}
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic void perf_top__show_details(struct perf_top *top)
2378c2ecf20Sopenharmony_ci{
2388c2ecf20Sopenharmony_ci	struct hist_entry *he = top->sym_filter_entry;
2398c2ecf20Sopenharmony_ci	struct evsel *evsel;
2408c2ecf20Sopenharmony_ci	struct annotation *notes;
2418c2ecf20Sopenharmony_ci	struct symbol *symbol;
2428c2ecf20Sopenharmony_ci	int more;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	if (!he)
2458c2ecf20Sopenharmony_ci		return;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	evsel = hists_to_evsel(he->hists);
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	symbol = he->ms.sym;
2508c2ecf20Sopenharmony_ci	notes = symbol__annotation(symbol);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	pthread_mutex_lock(&notes->lock);
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	symbol__calc_percent(symbol, evsel);
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	if (notes->src == NULL)
2578c2ecf20Sopenharmony_ci		goto out_unlock;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	printf("Showing %s for %s\n", evsel__name(top->sym_evsel), symbol->name);
2608c2ecf20Sopenharmony_ci	printf("  Events  Pcnt (>=%d%%)\n", top->annotation_opts.min_pcnt);
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	more = symbol__annotate_printf(&he->ms, top->sym_evsel, &top->annotation_opts);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci	if (top->evlist->enabled) {
2658c2ecf20Sopenharmony_ci		if (top->zero)
2668c2ecf20Sopenharmony_ci			symbol__annotate_zero_histogram(symbol, top->sym_evsel->idx);
2678c2ecf20Sopenharmony_ci		else
2688c2ecf20Sopenharmony_ci			symbol__annotate_decay_histogram(symbol, top->sym_evsel->idx);
2698c2ecf20Sopenharmony_ci	}
2708c2ecf20Sopenharmony_ci	if (more != 0)
2718c2ecf20Sopenharmony_ci		printf("%d lines not displayed, maybe increase display entries [e]\n", more);
2728c2ecf20Sopenharmony_ciout_unlock:
2738c2ecf20Sopenharmony_ci	pthread_mutex_unlock(&notes->lock);
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_cistatic void perf_top__resort_hists(struct perf_top *t)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	struct evlist *evlist = t->evlist;
2798c2ecf20Sopenharmony_ci	struct evsel *pos;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, pos) {
2828c2ecf20Sopenharmony_ci		struct hists *hists = evsel__hists(pos);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci		/*
2858c2ecf20Sopenharmony_ci		 * unlink existing entries so that they can be linked
2868c2ecf20Sopenharmony_ci		 * in a correct order in hists__match() below.
2878c2ecf20Sopenharmony_ci		 */
2888c2ecf20Sopenharmony_ci		hists__unlink(hists);
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci		if (evlist->enabled) {
2918c2ecf20Sopenharmony_ci			if (t->zero) {
2928c2ecf20Sopenharmony_ci				hists__delete_entries(hists);
2938c2ecf20Sopenharmony_ci			} else {
2948c2ecf20Sopenharmony_ci				hists__decay_entries(hists, t->hide_user_symbols,
2958c2ecf20Sopenharmony_ci						     t->hide_kernel_symbols);
2968c2ecf20Sopenharmony_ci			}
2978c2ecf20Sopenharmony_ci		}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci		hists__collapse_resort(hists, NULL);
3008c2ecf20Sopenharmony_ci
3018c2ecf20Sopenharmony_ci		/* Non-group events are considered as leader */
3028c2ecf20Sopenharmony_ci		if (symbol_conf.event_group && !evsel__is_group_leader(pos)) {
3038c2ecf20Sopenharmony_ci			struct hists *leader_hists = evsel__hists(pos->leader);
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci			hists__match(leader_hists, hists);
3068c2ecf20Sopenharmony_ci			hists__link(leader_hists, hists);
3078c2ecf20Sopenharmony_ci		}
3088c2ecf20Sopenharmony_ci	}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, pos) {
3118c2ecf20Sopenharmony_ci		evsel__output_resort(pos, NULL);
3128c2ecf20Sopenharmony_ci	}
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic void perf_top__print_sym_table(struct perf_top *top)
3168c2ecf20Sopenharmony_ci{
3178c2ecf20Sopenharmony_ci	char bf[160];
3188c2ecf20Sopenharmony_ci	int printed = 0;
3198c2ecf20Sopenharmony_ci	const int win_width = top->winsize.ws_col - 1;
3208c2ecf20Sopenharmony_ci	struct evsel *evsel = top->sym_evsel;
3218c2ecf20Sopenharmony_ci	struct hists *hists = evsel__hists(evsel);
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_ci	puts(CONSOLE_CLEAR);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	perf_top__header_snprintf(top, bf, sizeof(bf));
3268c2ecf20Sopenharmony_ci	printf("%s\n", bf);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci	printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	if (!top->record_opts.overwrite &&
3318c2ecf20Sopenharmony_ci	    (hists->stats.nr_lost_warned !=
3328c2ecf20Sopenharmony_ci	    hists->stats.nr_events[PERF_RECORD_LOST])) {
3338c2ecf20Sopenharmony_ci		hists->stats.nr_lost_warned =
3348c2ecf20Sopenharmony_ci			      hists->stats.nr_events[PERF_RECORD_LOST];
3358c2ecf20Sopenharmony_ci		color_fprintf(stdout, PERF_COLOR_RED,
3368c2ecf20Sopenharmony_ci			      "WARNING: LOST %d chunks, Check IO/CPU overload",
3378c2ecf20Sopenharmony_ci			      hists->stats.nr_lost_warned);
3388c2ecf20Sopenharmony_ci		++printed;
3398c2ecf20Sopenharmony_ci	}
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	if (top->sym_filter_entry) {
3428c2ecf20Sopenharmony_ci		perf_top__show_details(top);
3438c2ecf20Sopenharmony_ci		return;
3448c2ecf20Sopenharmony_ci	}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	perf_top__resort_hists(top);
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	hists__output_recalc_col_len(hists, top->print_entries - printed);
3498c2ecf20Sopenharmony_ci	putchar('\n');
3508c2ecf20Sopenharmony_ci	hists__fprintf(hists, false, top->print_entries - printed, win_width,
3518c2ecf20Sopenharmony_ci		       top->min_percent, stdout, !symbol_conf.use_callchain);
3528c2ecf20Sopenharmony_ci}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_cistatic void prompt_integer(int *target, const char *msg)
3558c2ecf20Sopenharmony_ci{
3568c2ecf20Sopenharmony_ci	char *buf = malloc(0), *p;
3578c2ecf20Sopenharmony_ci	size_t dummy = 0;
3588c2ecf20Sopenharmony_ci	int tmp;
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	fprintf(stdout, "\n%s: ", msg);
3618c2ecf20Sopenharmony_ci	if (getline(&buf, &dummy, stdin) < 0)
3628c2ecf20Sopenharmony_ci		return;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	p = strchr(buf, '\n');
3658c2ecf20Sopenharmony_ci	if (p)
3668c2ecf20Sopenharmony_ci		*p = 0;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	p = buf;
3698c2ecf20Sopenharmony_ci	while(*p) {
3708c2ecf20Sopenharmony_ci		if (!isdigit(*p))
3718c2ecf20Sopenharmony_ci			goto out_free;
3728c2ecf20Sopenharmony_ci		p++;
3738c2ecf20Sopenharmony_ci	}
3748c2ecf20Sopenharmony_ci	tmp = strtoul(buf, NULL, 10);
3758c2ecf20Sopenharmony_ci	*target = tmp;
3768c2ecf20Sopenharmony_ciout_free:
3778c2ecf20Sopenharmony_ci	free(buf);
3788c2ecf20Sopenharmony_ci}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_cistatic void prompt_percent(int *target, const char *msg)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	int tmp = 0;
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	prompt_integer(&tmp, msg);
3858c2ecf20Sopenharmony_ci	if (tmp >= 0 && tmp <= 100)
3868c2ecf20Sopenharmony_ci		*target = tmp;
3878c2ecf20Sopenharmony_ci}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_cistatic void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
3908c2ecf20Sopenharmony_ci{
3918c2ecf20Sopenharmony_ci	char *buf = malloc(0), *p;
3928c2ecf20Sopenharmony_ci	struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL;
3938c2ecf20Sopenharmony_ci	struct hists *hists = evsel__hists(top->sym_evsel);
3948c2ecf20Sopenharmony_ci	struct rb_node *next;
3958c2ecf20Sopenharmony_ci	size_t dummy = 0;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	/* zero counters of active symbol */
3988c2ecf20Sopenharmony_ci	if (syme) {
3998c2ecf20Sopenharmony_ci		__zero_source_counters(syme);
4008c2ecf20Sopenharmony_ci		top->sym_filter_entry = NULL;
4018c2ecf20Sopenharmony_ci	}
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	fprintf(stdout, "\n%s: ", msg);
4048c2ecf20Sopenharmony_ci	if (getline(&buf, &dummy, stdin) < 0)
4058c2ecf20Sopenharmony_ci		goto out_free;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	p = strchr(buf, '\n');
4088c2ecf20Sopenharmony_ci	if (p)
4098c2ecf20Sopenharmony_ci		*p = 0;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	next = rb_first_cached(&hists->entries);
4128c2ecf20Sopenharmony_ci	while (next) {
4138c2ecf20Sopenharmony_ci		n = rb_entry(next, struct hist_entry, rb_node);
4148c2ecf20Sopenharmony_ci		if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) {
4158c2ecf20Sopenharmony_ci			found = n;
4168c2ecf20Sopenharmony_ci			break;
4178c2ecf20Sopenharmony_ci		}
4188c2ecf20Sopenharmony_ci		next = rb_next(&n->rb_node);
4198c2ecf20Sopenharmony_ci	}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	if (!found) {
4228c2ecf20Sopenharmony_ci		fprintf(stderr, "Sorry, %s is not active.\n", buf);
4238c2ecf20Sopenharmony_ci		sleep(1);
4248c2ecf20Sopenharmony_ci	} else
4258c2ecf20Sopenharmony_ci		perf_top__parse_source(top, found);
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ciout_free:
4288c2ecf20Sopenharmony_ci	free(buf);
4298c2ecf20Sopenharmony_ci}
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_cistatic void perf_top__print_mapped_keys(struct perf_top *top)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	char *name = NULL;
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	if (top->sym_filter_entry) {
4368c2ecf20Sopenharmony_ci		struct symbol *sym = top->sym_filter_entry->ms.sym;
4378c2ecf20Sopenharmony_ci		name = sym->name;
4388c2ecf20Sopenharmony_ci	}
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	fprintf(stdout, "\nMapped keys:\n");
4418c2ecf20Sopenharmony_ci	fprintf(stdout, "\t[d]     display refresh delay.             \t(%d)\n", top->delay_secs);
4428c2ecf20Sopenharmony_ci	fprintf(stdout, "\t[e]     display entries (lines).           \t(%d)\n", top->print_entries);
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	if (top->evlist->core.nr_entries > 1)
4458c2ecf20Sopenharmony_ci		fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", evsel__name(top->sym_evsel));
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	fprintf(stdout, "\t[f]     profile display filter (count).    \t(%d)\n", top->count_filter);
4488c2ecf20Sopenharmony_ci
4498c2ecf20Sopenharmony_ci	fprintf(stdout, "\t[F]     annotate display filter (percent). \t(%d%%)\n", top->annotation_opts.min_pcnt);
4508c2ecf20Sopenharmony_ci	fprintf(stdout, "\t[s]     annotate symbol.                   \t(%s)\n", name?: "NULL");
4518c2ecf20Sopenharmony_ci	fprintf(stdout, "\t[S]     stop annotation.\n");
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	fprintf(stdout,
4548c2ecf20Sopenharmony_ci		"\t[K]     hide kernel symbols.             \t(%s)\n",
4558c2ecf20Sopenharmony_ci		top->hide_kernel_symbols ? "yes" : "no");
4568c2ecf20Sopenharmony_ci	fprintf(stdout,
4578c2ecf20Sopenharmony_ci		"\t[U]     hide user symbols.               \t(%s)\n",
4588c2ecf20Sopenharmony_ci		top->hide_user_symbols ? "yes" : "no");
4598c2ecf20Sopenharmony_ci	fprintf(stdout, "\t[z]     toggle sample zeroing.             \t(%d)\n", top->zero ? 1 : 0);
4608c2ecf20Sopenharmony_ci	fprintf(stdout, "\t[qQ]    quit.\n");
4618c2ecf20Sopenharmony_ci}
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_cistatic int perf_top__key_mapped(struct perf_top *top, int c)
4648c2ecf20Sopenharmony_ci{
4658c2ecf20Sopenharmony_ci	switch (c) {
4668c2ecf20Sopenharmony_ci		case 'd':
4678c2ecf20Sopenharmony_ci		case 'e':
4688c2ecf20Sopenharmony_ci		case 'f':
4698c2ecf20Sopenharmony_ci		case 'z':
4708c2ecf20Sopenharmony_ci		case 'q':
4718c2ecf20Sopenharmony_ci		case 'Q':
4728c2ecf20Sopenharmony_ci		case 'K':
4738c2ecf20Sopenharmony_ci		case 'U':
4748c2ecf20Sopenharmony_ci		case 'F':
4758c2ecf20Sopenharmony_ci		case 's':
4768c2ecf20Sopenharmony_ci		case 'S':
4778c2ecf20Sopenharmony_ci			return 1;
4788c2ecf20Sopenharmony_ci		case 'E':
4798c2ecf20Sopenharmony_ci			return top->evlist->core.nr_entries > 1 ? 1 : 0;
4808c2ecf20Sopenharmony_ci		default:
4818c2ecf20Sopenharmony_ci			break;
4828c2ecf20Sopenharmony_ci	}
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	return 0;
4858c2ecf20Sopenharmony_ci}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_cistatic bool perf_top__handle_keypress(struct perf_top *top, int c)
4888c2ecf20Sopenharmony_ci{
4898c2ecf20Sopenharmony_ci	bool ret = true;
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	if (!perf_top__key_mapped(top, c)) {
4928c2ecf20Sopenharmony_ci		struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
4938c2ecf20Sopenharmony_ci		struct termios save;
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci		perf_top__print_mapped_keys(top);
4968c2ecf20Sopenharmony_ci		fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
4978c2ecf20Sopenharmony_ci		fflush(stdout);
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_ci		set_term_quiet_input(&save);
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci		poll(&stdin_poll, 1, -1);
5028c2ecf20Sopenharmony_ci		c = getc(stdin);
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci		tcsetattr(0, TCSAFLUSH, &save);
5058c2ecf20Sopenharmony_ci		if (!perf_top__key_mapped(top, c))
5068c2ecf20Sopenharmony_ci			return ret;
5078c2ecf20Sopenharmony_ci	}
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci	switch (c) {
5108c2ecf20Sopenharmony_ci		case 'd':
5118c2ecf20Sopenharmony_ci			prompt_integer(&top->delay_secs, "Enter display delay");
5128c2ecf20Sopenharmony_ci			if (top->delay_secs < 1)
5138c2ecf20Sopenharmony_ci				top->delay_secs = 1;
5148c2ecf20Sopenharmony_ci			break;
5158c2ecf20Sopenharmony_ci		case 'e':
5168c2ecf20Sopenharmony_ci			prompt_integer(&top->print_entries, "Enter display entries (lines)");
5178c2ecf20Sopenharmony_ci			if (top->print_entries == 0) {
5188c2ecf20Sopenharmony_ci				perf_top__resize(top);
5198c2ecf20Sopenharmony_ci				signal(SIGWINCH, winch_sig);
5208c2ecf20Sopenharmony_ci			} else {
5218c2ecf20Sopenharmony_ci				signal(SIGWINCH, SIG_DFL);
5228c2ecf20Sopenharmony_ci			}
5238c2ecf20Sopenharmony_ci			break;
5248c2ecf20Sopenharmony_ci		case 'E':
5258c2ecf20Sopenharmony_ci			if (top->evlist->core.nr_entries > 1) {
5268c2ecf20Sopenharmony_ci				/* Select 0 as the default event: */
5278c2ecf20Sopenharmony_ci				int counter = 0;
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_ci				fprintf(stderr, "\nAvailable events:");
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci				evlist__for_each_entry(top->evlist, top->sym_evsel)
5328c2ecf20Sopenharmony_ci					fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, evsel__name(top->sym_evsel));
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci				prompt_integer(&counter, "Enter details event counter");
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci				if (counter >= top->evlist->core.nr_entries) {
5378c2ecf20Sopenharmony_ci					top->sym_evsel = evlist__first(top->evlist);
5388c2ecf20Sopenharmony_ci					fprintf(stderr, "Sorry, no such event, using %s.\n", evsel__name(top->sym_evsel));
5398c2ecf20Sopenharmony_ci					sleep(1);
5408c2ecf20Sopenharmony_ci					break;
5418c2ecf20Sopenharmony_ci				}
5428c2ecf20Sopenharmony_ci				evlist__for_each_entry(top->evlist, top->sym_evsel)
5438c2ecf20Sopenharmony_ci					if (top->sym_evsel->idx == counter)
5448c2ecf20Sopenharmony_ci						break;
5458c2ecf20Sopenharmony_ci			} else
5468c2ecf20Sopenharmony_ci				top->sym_evsel = evlist__first(top->evlist);
5478c2ecf20Sopenharmony_ci			break;
5488c2ecf20Sopenharmony_ci		case 'f':
5498c2ecf20Sopenharmony_ci			prompt_integer(&top->count_filter, "Enter display event count filter");
5508c2ecf20Sopenharmony_ci			break;
5518c2ecf20Sopenharmony_ci		case 'F':
5528c2ecf20Sopenharmony_ci			prompt_percent(&top->annotation_opts.min_pcnt,
5538c2ecf20Sopenharmony_ci				       "Enter details display event filter (percent)");
5548c2ecf20Sopenharmony_ci			break;
5558c2ecf20Sopenharmony_ci		case 'K':
5568c2ecf20Sopenharmony_ci			top->hide_kernel_symbols = !top->hide_kernel_symbols;
5578c2ecf20Sopenharmony_ci			break;
5588c2ecf20Sopenharmony_ci		case 'q':
5598c2ecf20Sopenharmony_ci		case 'Q':
5608c2ecf20Sopenharmony_ci			printf("exiting.\n");
5618c2ecf20Sopenharmony_ci			if (top->dump_symtab)
5628c2ecf20Sopenharmony_ci				perf_session__fprintf_dsos(top->session, stderr);
5638c2ecf20Sopenharmony_ci			ret = false;
5648c2ecf20Sopenharmony_ci			break;
5658c2ecf20Sopenharmony_ci		case 's':
5668c2ecf20Sopenharmony_ci			perf_top__prompt_symbol(top, "Enter details symbol");
5678c2ecf20Sopenharmony_ci			break;
5688c2ecf20Sopenharmony_ci		case 'S':
5698c2ecf20Sopenharmony_ci			if (!top->sym_filter_entry)
5708c2ecf20Sopenharmony_ci				break;
5718c2ecf20Sopenharmony_ci			else {
5728c2ecf20Sopenharmony_ci				struct hist_entry *syme = top->sym_filter_entry;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci				top->sym_filter_entry = NULL;
5758c2ecf20Sopenharmony_ci				__zero_source_counters(syme);
5768c2ecf20Sopenharmony_ci			}
5778c2ecf20Sopenharmony_ci			break;
5788c2ecf20Sopenharmony_ci		case 'U':
5798c2ecf20Sopenharmony_ci			top->hide_user_symbols = !top->hide_user_symbols;
5808c2ecf20Sopenharmony_ci			break;
5818c2ecf20Sopenharmony_ci		case 'z':
5828c2ecf20Sopenharmony_ci			top->zero = !top->zero;
5838c2ecf20Sopenharmony_ci			break;
5848c2ecf20Sopenharmony_ci		default:
5858c2ecf20Sopenharmony_ci			break;
5868c2ecf20Sopenharmony_ci	}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	return ret;
5898c2ecf20Sopenharmony_ci}
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_cistatic void perf_top__sort_new_samples(void *arg)
5928c2ecf20Sopenharmony_ci{
5938c2ecf20Sopenharmony_ci	struct perf_top *t = arg;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	if (t->evlist->selected != NULL)
5968c2ecf20Sopenharmony_ci		t->sym_evsel = t->evlist->selected;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	perf_top__resort_hists(t);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	if (t->lost || t->drop)
6018c2ecf20Sopenharmony_ci		pr_warning("Too slow to read ring buffer (change period (-c/-F) or limit CPUs (-C)\n");
6028c2ecf20Sopenharmony_ci}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_cistatic void stop_top(void)
6058c2ecf20Sopenharmony_ci{
6068c2ecf20Sopenharmony_ci	session_done = 1;
6078c2ecf20Sopenharmony_ci	done = 1;
6088c2ecf20Sopenharmony_ci}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_cistatic void *display_thread_tui(void *arg)
6118c2ecf20Sopenharmony_ci{
6128c2ecf20Sopenharmony_ci	struct evsel *pos;
6138c2ecf20Sopenharmony_ci	struct perf_top *top = arg;
6148c2ecf20Sopenharmony_ci	const char *help = "For a higher level overview, try: perf top --sort comm,dso";
6158c2ecf20Sopenharmony_ci	struct hist_browser_timer hbt = {
6168c2ecf20Sopenharmony_ci		.timer		= perf_top__sort_new_samples,
6178c2ecf20Sopenharmony_ci		.arg		= top,
6188c2ecf20Sopenharmony_ci		.refresh	= top->delay_secs,
6198c2ecf20Sopenharmony_ci	};
6208c2ecf20Sopenharmony_ci	int ret;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	/* In order to read symbols from other namespaces perf to  needs to call
6238c2ecf20Sopenharmony_ci	 * setns(2).  This isn't permitted if the struct_fs has multiple users.
6248c2ecf20Sopenharmony_ci	 * unshare(2) the fs so that we may continue to setns into namespaces
6258c2ecf20Sopenharmony_ci	 * that we're observing.
6268c2ecf20Sopenharmony_ci	 */
6278c2ecf20Sopenharmony_ci	unshare(CLONE_FS);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	prctl(PR_SET_NAME, "perf-top-UI", 0, 0, 0);
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_cirepeat:
6328c2ecf20Sopenharmony_ci	perf_top__sort_new_samples(top);
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	/*
6358c2ecf20Sopenharmony_ci	 * Initialize the uid_filter_str, in the future the TUI will allow
6368c2ecf20Sopenharmony_ci	 * Zooming in/out UIDs. For now just use whatever the user passed
6378c2ecf20Sopenharmony_ci	 * via --uid.
6388c2ecf20Sopenharmony_ci	 */
6398c2ecf20Sopenharmony_ci	evlist__for_each_entry(top->evlist, pos) {
6408c2ecf20Sopenharmony_ci		struct hists *hists = evsel__hists(pos);
6418c2ecf20Sopenharmony_ci		hists->uid_filter_str = top->record_opts.target.uid_str;
6428c2ecf20Sopenharmony_ci	}
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	ret = perf_evlist__tui_browse_hists(top->evlist, help, &hbt,
6458c2ecf20Sopenharmony_ci				      top->min_percent,
6468c2ecf20Sopenharmony_ci				      &top->session->header.env,
6478c2ecf20Sopenharmony_ci				      !top->record_opts.overwrite,
6488c2ecf20Sopenharmony_ci				      &top->annotation_opts);
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	if (ret == K_RELOAD) {
6518c2ecf20Sopenharmony_ci		top->zero = true;
6528c2ecf20Sopenharmony_ci		goto repeat;
6538c2ecf20Sopenharmony_ci	} else
6548c2ecf20Sopenharmony_ci		stop_top();
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	return NULL;
6578c2ecf20Sopenharmony_ci}
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_cistatic void display_sig(int sig __maybe_unused)
6608c2ecf20Sopenharmony_ci{
6618c2ecf20Sopenharmony_ci	stop_top();
6628c2ecf20Sopenharmony_ci}
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_cistatic void display_setup_sig(void)
6658c2ecf20Sopenharmony_ci{
6668c2ecf20Sopenharmony_ci	signal(SIGSEGV, sighandler_dump_stack);
6678c2ecf20Sopenharmony_ci	signal(SIGFPE, sighandler_dump_stack);
6688c2ecf20Sopenharmony_ci	signal(SIGINT,  display_sig);
6698c2ecf20Sopenharmony_ci	signal(SIGQUIT, display_sig);
6708c2ecf20Sopenharmony_ci	signal(SIGTERM, display_sig);
6718c2ecf20Sopenharmony_ci}
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_cistatic void *display_thread(void *arg)
6748c2ecf20Sopenharmony_ci{
6758c2ecf20Sopenharmony_ci	struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
6768c2ecf20Sopenharmony_ci	struct termios save;
6778c2ecf20Sopenharmony_ci	struct perf_top *top = arg;
6788c2ecf20Sopenharmony_ci	int delay_msecs, c;
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	/* In order to read symbols from other namespaces perf to  needs to call
6818c2ecf20Sopenharmony_ci	 * setns(2).  This isn't permitted if the struct_fs has multiple users.
6828c2ecf20Sopenharmony_ci	 * unshare(2) the fs so that we may continue to setns into namespaces
6838c2ecf20Sopenharmony_ci	 * that we're observing.
6848c2ecf20Sopenharmony_ci	 */
6858c2ecf20Sopenharmony_ci	unshare(CLONE_FS);
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	prctl(PR_SET_NAME, "perf-top-UI", 0, 0, 0);
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	display_setup_sig();
6908c2ecf20Sopenharmony_ci	pthread__unblock_sigwinch();
6918c2ecf20Sopenharmony_cirepeat:
6928c2ecf20Sopenharmony_ci	delay_msecs = top->delay_secs * MSEC_PER_SEC;
6938c2ecf20Sopenharmony_ci	set_term_quiet_input(&save);
6948c2ecf20Sopenharmony_ci	/* trash return*/
6958c2ecf20Sopenharmony_ci	clearerr(stdin);
6968c2ecf20Sopenharmony_ci	if (poll(&stdin_poll, 1, 0) > 0)
6978c2ecf20Sopenharmony_ci		getc(stdin);
6988c2ecf20Sopenharmony_ci
6998c2ecf20Sopenharmony_ci	while (!done) {
7008c2ecf20Sopenharmony_ci		perf_top__print_sym_table(top);
7018c2ecf20Sopenharmony_ci		/*
7028c2ecf20Sopenharmony_ci		 * Either timeout expired or we got an EINTR due to SIGWINCH,
7038c2ecf20Sopenharmony_ci		 * refresh screen in both cases.
7048c2ecf20Sopenharmony_ci		 */
7058c2ecf20Sopenharmony_ci		switch (poll(&stdin_poll, 1, delay_msecs)) {
7068c2ecf20Sopenharmony_ci		case 0:
7078c2ecf20Sopenharmony_ci			continue;
7088c2ecf20Sopenharmony_ci		case -1:
7098c2ecf20Sopenharmony_ci			if (errno == EINTR)
7108c2ecf20Sopenharmony_ci				continue;
7118c2ecf20Sopenharmony_ci			__fallthrough;
7128c2ecf20Sopenharmony_ci		default:
7138c2ecf20Sopenharmony_ci			c = getc(stdin);
7148c2ecf20Sopenharmony_ci			tcsetattr(0, TCSAFLUSH, &save);
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci			if (perf_top__handle_keypress(top, c))
7178c2ecf20Sopenharmony_ci				goto repeat;
7188c2ecf20Sopenharmony_ci			stop_top();
7198c2ecf20Sopenharmony_ci		}
7208c2ecf20Sopenharmony_ci	}
7218c2ecf20Sopenharmony_ci
7228c2ecf20Sopenharmony_ci	tcsetattr(0, TCSAFLUSH, &save);
7238c2ecf20Sopenharmony_ci	return NULL;
7248c2ecf20Sopenharmony_ci}
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_cistatic int hist_iter__top_callback(struct hist_entry_iter *iter,
7278c2ecf20Sopenharmony_ci				   struct addr_location *al, bool single,
7288c2ecf20Sopenharmony_ci				   void *arg)
7298c2ecf20Sopenharmony_ci{
7308c2ecf20Sopenharmony_ci	struct perf_top *top = arg;
7318c2ecf20Sopenharmony_ci	struct hist_entry *he = iter->he;
7328c2ecf20Sopenharmony_ci	struct evsel *evsel = iter->evsel;
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_ci	if (perf_hpp_list.sym && single)
7358c2ecf20Sopenharmony_ci		perf_top__record_precise_ip(top, he, iter->sample, evsel, al->addr);
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_ci	hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
7388c2ecf20Sopenharmony_ci		     !(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY),
7398c2ecf20Sopenharmony_ci		     NULL);
7408c2ecf20Sopenharmony_ci	return 0;
7418c2ecf20Sopenharmony_ci}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_cistatic void perf_event__process_sample(struct perf_tool *tool,
7448c2ecf20Sopenharmony_ci				       const union perf_event *event,
7458c2ecf20Sopenharmony_ci				       struct evsel *evsel,
7468c2ecf20Sopenharmony_ci				       struct perf_sample *sample,
7478c2ecf20Sopenharmony_ci				       struct machine *machine)
7488c2ecf20Sopenharmony_ci{
7498c2ecf20Sopenharmony_ci	struct perf_top *top = container_of(tool, struct perf_top, tool);
7508c2ecf20Sopenharmony_ci	struct addr_location al;
7518c2ecf20Sopenharmony_ci	int err;
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	if (!machine && perf_guest) {
7548c2ecf20Sopenharmony_ci		static struct intlist *seen;
7558c2ecf20Sopenharmony_ci
7568c2ecf20Sopenharmony_ci		if (!seen)
7578c2ecf20Sopenharmony_ci			seen = intlist__new(NULL);
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_ci		if (!intlist__has_entry(seen, sample->pid)) {
7608c2ecf20Sopenharmony_ci			pr_err("Can't find guest [%d]'s kernel information\n",
7618c2ecf20Sopenharmony_ci				sample->pid);
7628c2ecf20Sopenharmony_ci			intlist__add(seen, sample->pid);
7638c2ecf20Sopenharmony_ci		}
7648c2ecf20Sopenharmony_ci		return;
7658c2ecf20Sopenharmony_ci	}
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	if (!machine) {
7688c2ecf20Sopenharmony_ci		pr_err("%u unprocessable samples recorded.\r",
7698c2ecf20Sopenharmony_ci		       top->session->evlist->stats.nr_unprocessable_samples++);
7708c2ecf20Sopenharmony_ci		return;
7718c2ecf20Sopenharmony_ci	}
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_ci	if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
7748c2ecf20Sopenharmony_ci		top->exact_samples++;
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	if (machine__resolve(machine, &al, sample) < 0)
7778c2ecf20Sopenharmony_ci		return;
7788c2ecf20Sopenharmony_ci
7798c2ecf20Sopenharmony_ci	if (top->stitch_lbr)
7808c2ecf20Sopenharmony_ci		al.thread->lbr_stitch_enable = true;
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	if (!machine->kptr_restrict_warned &&
7838c2ecf20Sopenharmony_ci	    symbol_conf.kptr_restrict &&
7848c2ecf20Sopenharmony_ci	    al.cpumode == PERF_RECORD_MISC_KERNEL) {
7858c2ecf20Sopenharmony_ci		if (!perf_evlist__exclude_kernel(top->session->evlist)) {
7868c2ecf20Sopenharmony_ci			ui__warning(
7878c2ecf20Sopenharmony_ci"Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
7888c2ecf20Sopenharmony_ci"Check /proc/sys/kernel/kptr_restrict and /proc/sys/kernel/perf_event_paranoid.\n\n"
7898c2ecf20Sopenharmony_ci"Kernel%s samples will not be resolved.\n",
7908c2ecf20Sopenharmony_ci			  al.map && map__has_symbols(al.map) ?
7918c2ecf20Sopenharmony_ci			  " modules" : "");
7928c2ecf20Sopenharmony_ci			if (use_browser <= 0)
7938c2ecf20Sopenharmony_ci				sleep(5);
7948c2ecf20Sopenharmony_ci		}
7958c2ecf20Sopenharmony_ci		machine->kptr_restrict_warned = true;
7968c2ecf20Sopenharmony_ci	}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	if (al.sym == NULL && al.map != NULL) {
7998c2ecf20Sopenharmony_ci		const char *msg = "Kernel samples will not be resolved.\n";
8008c2ecf20Sopenharmony_ci		/*
8018c2ecf20Sopenharmony_ci		 * As we do lazy loading of symtabs we only will know if the
8028c2ecf20Sopenharmony_ci		 * specified vmlinux file is invalid when we actually have a
8038c2ecf20Sopenharmony_ci		 * hit in kernel space and then try to load it. So if we get
8048c2ecf20Sopenharmony_ci		 * here and there are _no_ symbols in the DSO backing the
8058c2ecf20Sopenharmony_ci		 * kernel map, bail out.
8068c2ecf20Sopenharmony_ci		 *
8078c2ecf20Sopenharmony_ci		 * We may never get here, for instance, if we use -K/
8088c2ecf20Sopenharmony_ci		 * --hide-kernel-symbols, even if the user specifies an
8098c2ecf20Sopenharmony_ci		 * invalid --vmlinux ;-)
8108c2ecf20Sopenharmony_ci		 */
8118c2ecf20Sopenharmony_ci		if (!machine->kptr_restrict_warned && !top->vmlinux_warned &&
8128c2ecf20Sopenharmony_ci		    __map__is_kernel(al.map) && map__has_symbols(al.map)) {
8138c2ecf20Sopenharmony_ci			if (symbol_conf.vmlinux_name) {
8148c2ecf20Sopenharmony_ci				char serr[256];
8158c2ecf20Sopenharmony_ci				dso__strerror_load(al.map->dso, serr, sizeof(serr));
8168c2ecf20Sopenharmony_ci				ui__warning("The %s file can't be used: %s\n%s",
8178c2ecf20Sopenharmony_ci					    symbol_conf.vmlinux_name, serr, msg);
8188c2ecf20Sopenharmony_ci			} else {
8198c2ecf20Sopenharmony_ci				ui__warning("A vmlinux file was not found.\n%s",
8208c2ecf20Sopenharmony_ci					    msg);
8218c2ecf20Sopenharmony_ci			}
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci			if (use_browser <= 0)
8248c2ecf20Sopenharmony_ci				sleep(5);
8258c2ecf20Sopenharmony_ci			top->vmlinux_warned = true;
8268c2ecf20Sopenharmony_ci		}
8278c2ecf20Sopenharmony_ci	}
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	if (al.sym == NULL || !al.sym->idle) {
8308c2ecf20Sopenharmony_ci		struct hists *hists = evsel__hists(evsel);
8318c2ecf20Sopenharmony_ci		struct hist_entry_iter iter = {
8328c2ecf20Sopenharmony_ci			.evsel		= evsel,
8338c2ecf20Sopenharmony_ci			.sample 	= sample,
8348c2ecf20Sopenharmony_ci			.add_entry_cb 	= hist_iter__top_callback,
8358c2ecf20Sopenharmony_ci		};
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci		if (symbol_conf.cumulate_callchain)
8388c2ecf20Sopenharmony_ci			iter.ops = &hist_iter_cumulative;
8398c2ecf20Sopenharmony_ci		else
8408c2ecf20Sopenharmony_ci			iter.ops = &hist_iter_normal;
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci		pthread_mutex_lock(&hists->lock);
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci		err = hist_entry_iter__add(&iter, &al, top->max_stack, top);
8458c2ecf20Sopenharmony_ci		if (err < 0)
8468c2ecf20Sopenharmony_ci			pr_err("Problem incrementing symbol period, skipping event\n");
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci		pthread_mutex_unlock(&hists->lock);
8498c2ecf20Sopenharmony_ci	}
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	addr_location__put(&al);
8528c2ecf20Sopenharmony_ci}
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_cistatic void
8558c2ecf20Sopenharmony_ciperf_top__process_lost(struct perf_top *top, union perf_event *event,
8568c2ecf20Sopenharmony_ci		       struct evsel *evsel)
8578c2ecf20Sopenharmony_ci{
8588c2ecf20Sopenharmony_ci	struct hists *hists = evsel__hists(evsel);
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	top->lost += event->lost.lost;
8618c2ecf20Sopenharmony_ci	top->lost_total += event->lost.lost;
8628c2ecf20Sopenharmony_ci	hists->stats.total_lost += event->lost.lost;
8638c2ecf20Sopenharmony_ci}
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_cistatic void
8668c2ecf20Sopenharmony_ciperf_top__process_lost_samples(struct perf_top *top,
8678c2ecf20Sopenharmony_ci			       union perf_event *event,
8688c2ecf20Sopenharmony_ci			       struct evsel *evsel)
8698c2ecf20Sopenharmony_ci{
8708c2ecf20Sopenharmony_ci	struct hists *hists = evsel__hists(evsel);
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	top->lost += event->lost_samples.lost;
8738c2ecf20Sopenharmony_ci	top->lost_total += event->lost_samples.lost;
8748c2ecf20Sopenharmony_ci	hists->stats.total_lost_samples += event->lost_samples.lost;
8758c2ecf20Sopenharmony_ci}
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_cistatic u64 last_timestamp;
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_cistatic void perf_top__mmap_read_idx(struct perf_top *top, int idx)
8808c2ecf20Sopenharmony_ci{
8818c2ecf20Sopenharmony_ci	struct record_opts *opts = &top->record_opts;
8828c2ecf20Sopenharmony_ci	struct evlist *evlist = top->evlist;
8838c2ecf20Sopenharmony_ci	struct mmap *md;
8848c2ecf20Sopenharmony_ci	union perf_event *event;
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci	md = opts->overwrite ? &evlist->overwrite_mmap[idx] : &evlist->mmap[idx];
8878c2ecf20Sopenharmony_ci	if (perf_mmap__read_init(&md->core) < 0)
8888c2ecf20Sopenharmony_ci		return;
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	while ((event = perf_mmap__read_event(&md->core)) != NULL) {
8918c2ecf20Sopenharmony_ci		int ret;
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci		ret = perf_evlist__parse_sample_timestamp(evlist, event, &last_timestamp);
8948c2ecf20Sopenharmony_ci		if (ret && ret != -1)
8958c2ecf20Sopenharmony_ci			break;
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_ci		ret = ordered_events__queue(top->qe.in, event, last_timestamp, 0);
8988c2ecf20Sopenharmony_ci		if (ret)
8998c2ecf20Sopenharmony_ci			break;
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci		perf_mmap__consume(&md->core);
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_ci		if (top->qe.rotate) {
9048c2ecf20Sopenharmony_ci			pthread_mutex_lock(&top->qe.mutex);
9058c2ecf20Sopenharmony_ci			top->qe.rotate = false;
9068c2ecf20Sopenharmony_ci			pthread_cond_signal(&top->qe.cond);
9078c2ecf20Sopenharmony_ci			pthread_mutex_unlock(&top->qe.mutex);
9088c2ecf20Sopenharmony_ci		}
9098c2ecf20Sopenharmony_ci	}
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci	perf_mmap__read_done(&md->core);
9128c2ecf20Sopenharmony_ci}
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_cistatic void perf_top__mmap_read(struct perf_top *top)
9158c2ecf20Sopenharmony_ci{
9168c2ecf20Sopenharmony_ci	bool overwrite = top->record_opts.overwrite;
9178c2ecf20Sopenharmony_ci	struct evlist *evlist = top->evlist;
9188c2ecf20Sopenharmony_ci	int i;
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	if (overwrite)
9218c2ecf20Sopenharmony_ci		perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_DATA_PENDING);
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	for (i = 0; i < top->evlist->core.nr_mmaps; i++)
9248c2ecf20Sopenharmony_ci		perf_top__mmap_read_idx(top, i);
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci	if (overwrite) {
9278c2ecf20Sopenharmony_ci		perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
9288c2ecf20Sopenharmony_ci		perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
9298c2ecf20Sopenharmony_ci	}
9308c2ecf20Sopenharmony_ci}
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci/*
9338c2ecf20Sopenharmony_ci * Check per-event overwrite term.
9348c2ecf20Sopenharmony_ci * perf top should support consistent term for all events.
9358c2ecf20Sopenharmony_ci * - All events don't have per-event term
9368c2ecf20Sopenharmony_ci *   E.g. "cpu/cpu-cycles/,cpu/instructions/"
9378c2ecf20Sopenharmony_ci *   Nothing change, return 0.
9388c2ecf20Sopenharmony_ci * - All events have same per-event term
9398c2ecf20Sopenharmony_ci *   E.g. "cpu/cpu-cycles,no-overwrite/,cpu/instructions,no-overwrite/
9408c2ecf20Sopenharmony_ci *   Using the per-event setting to replace the opts->overwrite if
9418c2ecf20Sopenharmony_ci *   they are different, then return 0.
9428c2ecf20Sopenharmony_ci * - Events have different per-event term
9438c2ecf20Sopenharmony_ci *   E.g. "cpu/cpu-cycles,overwrite/,cpu/instructions,no-overwrite/"
9448c2ecf20Sopenharmony_ci *   Return -1
9458c2ecf20Sopenharmony_ci * - Some of the event set per-event term, but some not.
9468c2ecf20Sopenharmony_ci *   E.g. "cpu/cpu-cycles/,cpu/instructions,no-overwrite/"
9478c2ecf20Sopenharmony_ci *   Return -1
9488c2ecf20Sopenharmony_ci */
9498c2ecf20Sopenharmony_cistatic int perf_top__overwrite_check(struct perf_top *top)
9508c2ecf20Sopenharmony_ci{
9518c2ecf20Sopenharmony_ci	struct record_opts *opts = &top->record_opts;
9528c2ecf20Sopenharmony_ci	struct evlist *evlist = top->evlist;
9538c2ecf20Sopenharmony_ci	struct evsel_config_term *term;
9548c2ecf20Sopenharmony_ci	struct list_head *config_terms;
9558c2ecf20Sopenharmony_ci	struct evsel *evsel;
9568c2ecf20Sopenharmony_ci	int set, overwrite = -1;
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, evsel) {
9598c2ecf20Sopenharmony_ci		set = -1;
9608c2ecf20Sopenharmony_ci		config_terms = &evsel->config_terms;
9618c2ecf20Sopenharmony_ci		list_for_each_entry(term, config_terms, list) {
9628c2ecf20Sopenharmony_ci			if (term->type == EVSEL__CONFIG_TERM_OVERWRITE)
9638c2ecf20Sopenharmony_ci				set = term->val.overwrite ? 1 : 0;
9648c2ecf20Sopenharmony_ci		}
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci		/* no term for current and previous event (likely) */
9678c2ecf20Sopenharmony_ci		if ((overwrite < 0) && (set < 0))
9688c2ecf20Sopenharmony_ci			continue;
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci		/* has term for both current and previous event, compare */
9718c2ecf20Sopenharmony_ci		if ((overwrite >= 0) && (set >= 0) && (overwrite != set))
9728c2ecf20Sopenharmony_ci			return -1;
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci		/* no term for current event but has term for previous one */
9758c2ecf20Sopenharmony_ci		if ((overwrite >= 0) && (set < 0))
9768c2ecf20Sopenharmony_ci			return -1;
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci		/* has term for current event */
9798c2ecf20Sopenharmony_ci		if ((overwrite < 0) && (set >= 0)) {
9808c2ecf20Sopenharmony_ci			/* if it's first event, set overwrite */
9818c2ecf20Sopenharmony_ci			if (evsel == evlist__first(evlist))
9828c2ecf20Sopenharmony_ci				overwrite = set;
9838c2ecf20Sopenharmony_ci			else
9848c2ecf20Sopenharmony_ci				return -1;
9858c2ecf20Sopenharmony_ci		}
9868c2ecf20Sopenharmony_ci	}
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci	if ((overwrite >= 0) && (opts->overwrite != overwrite))
9898c2ecf20Sopenharmony_ci		opts->overwrite = overwrite;
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ci	return 0;
9928c2ecf20Sopenharmony_ci}
9938c2ecf20Sopenharmony_ci
9948c2ecf20Sopenharmony_cistatic int perf_top_overwrite_fallback(struct perf_top *top,
9958c2ecf20Sopenharmony_ci				       struct evsel *evsel)
9968c2ecf20Sopenharmony_ci{
9978c2ecf20Sopenharmony_ci	struct record_opts *opts = &top->record_opts;
9988c2ecf20Sopenharmony_ci	struct evlist *evlist = top->evlist;
9998c2ecf20Sopenharmony_ci	struct evsel *counter;
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	if (!opts->overwrite)
10028c2ecf20Sopenharmony_ci		return 0;
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	/* only fall back when first event fails */
10058c2ecf20Sopenharmony_ci	if (evsel != evlist__first(evlist))
10068c2ecf20Sopenharmony_ci		return 0;
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, counter)
10098c2ecf20Sopenharmony_ci		counter->core.attr.write_backward = false;
10108c2ecf20Sopenharmony_ci	opts->overwrite = false;
10118c2ecf20Sopenharmony_ci	pr_debug2("fall back to non-overwrite mode\n");
10128c2ecf20Sopenharmony_ci	return 1;
10138c2ecf20Sopenharmony_ci}
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_cistatic int perf_top__start_counters(struct perf_top *top)
10168c2ecf20Sopenharmony_ci{
10178c2ecf20Sopenharmony_ci	char msg[BUFSIZ];
10188c2ecf20Sopenharmony_ci	struct evsel *counter;
10198c2ecf20Sopenharmony_ci	struct evlist *evlist = top->evlist;
10208c2ecf20Sopenharmony_ci	struct record_opts *opts = &top->record_opts;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	if (perf_top__overwrite_check(top)) {
10238c2ecf20Sopenharmony_ci		ui__error("perf top only support consistent per-event "
10248c2ecf20Sopenharmony_ci			  "overwrite setting for all events\n");
10258c2ecf20Sopenharmony_ci		goto out_err;
10268c2ecf20Sopenharmony_ci	}
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	perf_evlist__config(evlist, opts, &callchain_param);
10298c2ecf20Sopenharmony_ci
10308c2ecf20Sopenharmony_ci	evlist__for_each_entry(evlist, counter) {
10318c2ecf20Sopenharmony_citry_again:
10328c2ecf20Sopenharmony_ci		if (evsel__open(counter, top->evlist->core.cpus,
10338c2ecf20Sopenharmony_ci				     top->evlist->core.threads) < 0) {
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci			/*
10368c2ecf20Sopenharmony_ci			 * Specially handle overwrite fall back.
10378c2ecf20Sopenharmony_ci			 * Because perf top is the only tool which has
10388c2ecf20Sopenharmony_ci			 * overwrite mode by default, support
10398c2ecf20Sopenharmony_ci			 * both overwrite and non-overwrite mode, and
10408c2ecf20Sopenharmony_ci			 * require consistent mode for all events.
10418c2ecf20Sopenharmony_ci			 *
10428c2ecf20Sopenharmony_ci			 * May move it to generic code with more tools
10438c2ecf20Sopenharmony_ci			 * have similar attribute.
10448c2ecf20Sopenharmony_ci			 */
10458c2ecf20Sopenharmony_ci			if (perf_missing_features.write_backward &&
10468c2ecf20Sopenharmony_ci			    perf_top_overwrite_fallback(top, counter))
10478c2ecf20Sopenharmony_ci				goto try_again;
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci			if (evsel__fallback(counter, errno, msg, sizeof(msg))) {
10508c2ecf20Sopenharmony_ci				if (verbose > 0)
10518c2ecf20Sopenharmony_ci					ui__warning("%s\n", msg);
10528c2ecf20Sopenharmony_ci				goto try_again;
10538c2ecf20Sopenharmony_ci			}
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci			evsel__open_strerror(counter, &opts->target, errno, msg, sizeof(msg));
10568c2ecf20Sopenharmony_ci			ui__error("%s\n", msg);
10578c2ecf20Sopenharmony_ci			goto out_err;
10588c2ecf20Sopenharmony_ci		}
10598c2ecf20Sopenharmony_ci	}
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	if (evlist__mmap(evlist, opts->mmap_pages) < 0) {
10628c2ecf20Sopenharmony_ci		ui__error("Failed to mmap with %d (%s)\n",
10638c2ecf20Sopenharmony_ci			    errno, str_error_r(errno, msg, sizeof(msg)));
10648c2ecf20Sopenharmony_ci		goto out_err;
10658c2ecf20Sopenharmony_ci	}
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	return 0;
10688c2ecf20Sopenharmony_ci
10698c2ecf20Sopenharmony_ciout_err:
10708c2ecf20Sopenharmony_ci	return -1;
10718c2ecf20Sopenharmony_ci}
10728c2ecf20Sopenharmony_ci
10738c2ecf20Sopenharmony_cistatic int callchain_param__setup_sample_type(struct callchain_param *callchain)
10748c2ecf20Sopenharmony_ci{
10758c2ecf20Sopenharmony_ci	if (callchain->mode != CHAIN_NONE) {
10768c2ecf20Sopenharmony_ci		if (callchain_register_param(callchain) < 0) {
10778c2ecf20Sopenharmony_ci			ui__error("Can't register callchain params.\n");
10788c2ecf20Sopenharmony_ci			return -EINVAL;
10798c2ecf20Sopenharmony_ci		}
10808c2ecf20Sopenharmony_ci	}
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	return 0;
10838c2ecf20Sopenharmony_ci}
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_cistatic struct ordered_events *rotate_queues(struct perf_top *top)
10868c2ecf20Sopenharmony_ci{
10878c2ecf20Sopenharmony_ci	struct ordered_events *in = top->qe.in;
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	if (top->qe.in == &top->qe.data[1])
10908c2ecf20Sopenharmony_ci		top->qe.in = &top->qe.data[0];
10918c2ecf20Sopenharmony_ci	else
10928c2ecf20Sopenharmony_ci		top->qe.in = &top->qe.data[1];
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci	return in;
10958c2ecf20Sopenharmony_ci}
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_cistatic void *process_thread(void *arg)
10988c2ecf20Sopenharmony_ci{
10998c2ecf20Sopenharmony_ci	struct perf_top *top = arg;
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	while (!done) {
11028c2ecf20Sopenharmony_ci		struct ordered_events *out, *in = top->qe.in;
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci		if (!in->nr_events) {
11058c2ecf20Sopenharmony_ci			usleep(100);
11068c2ecf20Sopenharmony_ci			continue;
11078c2ecf20Sopenharmony_ci		}
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci		out = rotate_queues(top);
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci		pthread_mutex_lock(&top->qe.mutex);
11128c2ecf20Sopenharmony_ci		top->qe.rotate = true;
11138c2ecf20Sopenharmony_ci		pthread_cond_wait(&top->qe.cond, &top->qe.mutex);
11148c2ecf20Sopenharmony_ci		pthread_mutex_unlock(&top->qe.mutex);
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci		if (ordered_events__flush(out, OE_FLUSH__TOP))
11178c2ecf20Sopenharmony_ci			pr_err("failed to process events\n");
11188c2ecf20Sopenharmony_ci	}
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	return NULL;
11218c2ecf20Sopenharmony_ci}
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci/*
11248c2ecf20Sopenharmony_ci * Allow only 'top->delay_secs' seconds behind samples.
11258c2ecf20Sopenharmony_ci */
11268c2ecf20Sopenharmony_cistatic int should_drop(struct ordered_event *qevent, struct perf_top *top)
11278c2ecf20Sopenharmony_ci{
11288c2ecf20Sopenharmony_ci	union perf_event *event = qevent->event;
11298c2ecf20Sopenharmony_ci	u64 delay_timestamp;
11308c2ecf20Sopenharmony_ci
11318c2ecf20Sopenharmony_ci	if (event->header.type != PERF_RECORD_SAMPLE)
11328c2ecf20Sopenharmony_ci		return false;
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	delay_timestamp = qevent->timestamp + top->delay_secs * NSEC_PER_SEC;
11358c2ecf20Sopenharmony_ci	return delay_timestamp < last_timestamp;
11368c2ecf20Sopenharmony_ci}
11378c2ecf20Sopenharmony_ci
11388c2ecf20Sopenharmony_cistatic int deliver_event(struct ordered_events *qe,
11398c2ecf20Sopenharmony_ci			 struct ordered_event *qevent)
11408c2ecf20Sopenharmony_ci{
11418c2ecf20Sopenharmony_ci	struct perf_top *top = qe->data;
11428c2ecf20Sopenharmony_ci	struct evlist *evlist = top->evlist;
11438c2ecf20Sopenharmony_ci	struct perf_session *session = top->session;
11448c2ecf20Sopenharmony_ci	union perf_event *event = qevent->event;
11458c2ecf20Sopenharmony_ci	struct perf_sample sample;
11468c2ecf20Sopenharmony_ci	struct evsel *evsel;
11478c2ecf20Sopenharmony_ci	struct machine *machine;
11488c2ecf20Sopenharmony_ci	int ret = -1;
11498c2ecf20Sopenharmony_ci
11508c2ecf20Sopenharmony_ci	if (should_drop(qevent, top)) {
11518c2ecf20Sopenharmony_ci		top->drop++;
11528c2ecf20Sopenharmony_ci		top->drop_total++;
11538c2ecf20Sopenharmony_ci		return 0;
11548c2ecf20Sopenharmony_ci	}
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	ret = perf_evlist__parse_sample(evlist, event, &sample);
11578c2ecf20Sopenharmony_ci	if (ret) {
11588c2ecf20Sopenharmony_ci		pr_err("Can't parse sample, err = %d\n", ret);
11598c2ecf20Sopenharmony_ci		goto next_event;
11608c2ecf20Sopenharmony_ci	}
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci	evsel = perf_evlist__id2evsel(session->evlist, sample.id);
11638c2ecf20Sopenharmony_ci	assert(evsel != NULL);
11648c2ecf20Sopenharmony_ci
11658c2ecf20Sopenharmony_ci	if (event->header.type == PERF_RECORD_SAMPLE) {
11668c2ecf20Sopenharmony_ci		if (evswitch__discard(&top->evswitch, evsel))
11678c2ecf20Sopenharmony_ci			return 0;
11688c2ecf20Sopenharmony_ci		++top->samples;
11698c2ecf20Sopenharmony_ci	}
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci	switch (sample.cpumode) {
11728c2ecf20Sopenharmony_ci	case PERF_RECORD_MISC_USER:
11738c2ecf20Sopenharmony_ci		++top->us_samples;
11748c2ecf20Sopenharmony_ci		if (top->hide_user_symbols)
11758c2ecf20Sopenharmony_ci			goto next_event;
11768c2ecf20Sopenharmony_ci		machine = &session->machines.host;
11778c2ecf20Sopenharmony_ci		break;
11788c2ecf20Sopenharmony_ci	case PERF_RECORD_MISC_KERNEL:
11798c2ecf20Sopenharmony_ci		++top->kernel_samples;
11808c2ecf20Sopenharmony_ci		if (top->hide_kernel_symbols)
11818c2ecf20Sopenharmony_ci			goto next_event;
11828c2ecf20Sopenharmony_ci		machine = &session->machines.host;
11838c2ecf20Sopenharmony_ci		break;
11848c2ecf20Sopenharmony_ci	case PERF_RECORD_MISC_GUEST_KERNEL:
11858c2ecf20Sopenharmony_ci		++top->guest_kernel_samples;
11868c2ecf20Sopenharmony_ci		machine = perf_session__find_machine(session,
11878c2ecf20Sopenharmony_ci						     sample.pid);
11888c2ecf20Sopenharmony_ci		break;
11898c2ecf20Sopenharmony_ci	case PERF_RECORD_MISC_GUEST_USER:
11908c2ecf20Sopenharmony_ci		++top->guest_us_samples;
11918c2ecf20Sopenharmony_ci		/*
11928c2ecf20Sopenharmony_ci		 * TODO: we don't process guest user from host side
11938c2ecf20Sopenharmony_ci		 * except simple counting.
11948c2ecf20Sopenharmony_ci		 */
11958c2ecf20Sopenharmony_ci		goto next_event;
11968c2ecf20Sopenharmony_ci	default:
11978c2ecf20Sopenharmony_ci		if (event->header.type == PERF_RECORD_SAMPLE)
11988c2ecf20Sopenharmony_ci			goto next_event;
11998c2ecf20Sopenharmony_ci		machine = &session->machines.host;
12008c2ecf20Sopenharmony_ci		break;
12018c2ecf20Sopenharmony_ci	}
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	if (event->header.type == PERF_RECORD_SAMPLE) {
12048c2ecf20Sopenharmony_ci		perf_event__process_sample(&top->tool, event, evsel,
12058c2ecf20Sopenharmony_ci					   &sample, machine);
12068c2ecf20Sopenharmony_ci	} else if (event->header.type == PERF_RECORD_LOST) {
12078c2ecf20Sopenharmony_ci		perf_top__process_lost(top, event, evsel);
12088c2ecf20Sopenharmony_ci	} else if (event->header.type == PERF_RECORD_LOST_SAMPLES) {
12098c2ecf20Sopenharmony_ci		perf_top__process_lost_samples(top, event, evsel);
12108c2ecf20Sopenharmony_ci	} else if (event->header.type < PERF_RECORD_MAX) {
12118c2ecf20Sopenharmony_ci		hists__inc_nr_events(evsel__hists(evsel), event->header.type);
12128c2ecf20Sopenharmony_ci		machine__process_event(machine, event, &sample);
12138c2ecf20Sopenharmony_ci	} else
12148c2ecf20Sopenharmony_ci		++session->evlist->stats.nr_unknown_events;
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	ret = 0;
12178c2ecf20Sopenharmony_cinext_event:
12188c2ecf20Sopenharmony_ci	return ret;
12198c2ecf20Sopenharmony_ci}
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_cistatic void init_process_thread(struct perf_top *top)
12228c2ecf20Sopenharmony_ci{
12238c2ecf20Sopenharmony_ci	ordered_events__init(&top->qe.data[0], deliver_event, top);
12248c2ecf20Sopenharmony_ci	ordered_events__init(&top->qe.data[1], deliver_event, top);
12258c2ecf20Sopenharmony_ci	ordered_events__set_copy_on_queue(&top->qe.data[0], true);
12268c2ecf20Sopenharmony_ci	ordered_events__set_copy_on_queue(&top->qe.data[1], true);
12278c2ecf20Sopenharmony_ci	top->qe.in = &top->qe.data[0];
12288c2ecf20Sopenharmony_ci	pthread_mutex_init(&top->qe.mutex, NULL);
12298c2ecf20Sopenharmony_ci	pthread_cond_init(&top->qe.cond, NULL);
12308c2ecf20Sopenharmony_ci}
12318c2ecf20Sopenharmony_ci
12328c2ecf20Sopenharmony_cistatic int __cmd_top(struct perf_top *top)
12338c2ecf20Sopenharmony_ci{
12348c2ecf20Sopenharmony_ci	struct record_opts *opts = &top->record_opts;
12358c2ecf20Sopenharmony_ci	pthread_t thread, thread_process;
12368c2ecf20Sopenharmony_ci	int ret;
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci	if (!top->annotation_opts.objdump_path) {
12398c2ecf20Sopenharmony_ci		ret = perf_env__lookup_objdump(&top->session->header.env,
12408c2ecf20Sopenharmony_ci					       &top->annotation_opts.objdump_path);
12418c2ecf20Sopenharmony_ci		if (ret)
12428c2ecf20Sopenharmony_ci			return ret;
12438c2ecf20Sopenharmony_ci	}
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	ret = callchain_param__setup_sample_type(&callchain_param);
12468c2ecf20Sopenharmony_ci	if (ret)
12478c2ecf20Sopenharmony_ci		return ret;
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci	if (perf_session__register_idle_thread(top->session) < 0)
12508c2ecf20Sopenharmony_ci		return ret;
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_ci	if (top->nr_threads_synthesize > 1)
12538c2ecf20Sopenharmony_ci		perf_set_multithreaded();
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	init_process_thread(top);
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	if (opts->record_namespaces)
12588c2ecf20Sopenharmony_ci		top->tool.namespace_events = true;
12598c2ecf20Sopenharmony_ci	if (opts->record_cgroup) {
12608c2ecf20Sopenharmony_ci#ifdef HAVE_FILE_HANDLE
12618c2ecf20Sopenharmony_ci		top->tool.cgroup_events = true;
12628c2ecf20Sopenharmony_ci#else
12638c2ecf20Sopenharmony_ci		pr_err("cgroup tracking is not supported.\n");
12648c2ecf20Sopenharmony_ci		return -1;
12658c2ecf20Sopenharmony_ci#endif
12668c2ecf20Sopenharmony_ci	}
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	ret = perf_event__synthesize_bpf_events(top->session, perf_event__process,
12698c2ecf20Sopenharmony_ci						&top->session->machines.host,
12708c2ecf20Sopenharmony_ci						&top->record_opts);
12718c2ecf20Sopenharmony_ci	if (ret < 0)
12728c2ecf20Sopenharmony_ci		pr_debug("Couldn't synthesize BPF events: Pre-existing BPF programs won't have symbols resolved.\n");
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	ret = perf_event__synthesize_cgroups(&top->tool, perf_event__process,
12758c2ecf20Sopenharmony_ci					     &top->session->machines.host);
12768c2ecf20Sopenharmony_ci	if (ret < 0)
12778c2ecf20Sopenharmony_ci		pr_debug("Couldn't synthesize cgroup events.\n");
12788c2ecf20Sopenharmony_ci
12798c2ecf20Sopenharmony_ci	machine__synthesize_threads(&top->session->machines.host, &opts->target,
12808c2ecf20Sopenharmony_ci				    top->evlist->core.threads, false,
12818c2ecf20Sopenharmony_ci				    top->nr_threads_synthesize);
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	if (top->nr_threads_synthesize > 1)
12848c2ecf20Sopenharmony_ci		perf_set_singlethreaded();
12858c2ecf20Sopenharmony_ci
12868c2ecf20Sopenharmony_ci	if (perf_hpp_list.socket) {
12878c2ecf20Sopenharmony_ci		ret = perf_env__read_cpu_topology_map(&perf_env);
12888c2ecf20Sopenharmony_ci		if (ret < 0) {
12898c2ecf20Sopenharmony_ci			char errbuf[BUFSIZ];
12908c2ecf20Sopenharmony_ci			const char *err = str_error_r(-ret, errbuf, sizeof(errbuf));
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci			ui__error("Could not read the CPU topology map: %s\n", err);
12938c2ecf20Sopenharmony_ci			return ret;
12948c2ecf20Sopenharmony_ci		}
12958c2ecf20Sopenharmony_ci	}
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	ret = perf_top__start_counters(top);
12988c2ecf20Sopenharmony_ci	if (ret)
12998c2ecf20Sopenharmony_ci		return ret;
13008c2ecf20Sopenharmony_ci
13018c2ecf20Sopenharmony_ci	top->session->evlist = top->evlist;
13028c2ecf20Sopenharmony_ci	perf_session__set_id_hdr_size(top->session);
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	/*
13058c2ecf20Sopenharmony_ci	 * When perf is starting the traced process, all the events (apart from
13068c2ecf20Sopenharmony_ci	 * group members) have enable_on_exec=1 set, so don't spoil it by
13078c2ecf20Sopenharmony_ci	 * prematurely enabling them.
13088c2ecf20Sopenharmony_ci	 *
13098c2ecf20Sopenharmony_ci	 * XXX 'top' still doesn't start workloads like record, trace, but should,
13108c2ecf20Sopenharmony_ci	 * so leave the check here.
13118c2ecf20Sopenharmony_ci	 */
13128c2ecf20Sopenharmony_ci        if (!target__none(&opts->target))
13138c2ecf20Sopenharmony_ci		evlist__enable(top->evlist);
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci	ret = -1;
13168c2ecf20Sopenharmony_ci	if (pthread_create(&thread_process, NULL, process_thread, top)) {
13178c2ecf20Sopenharmony_ci		ui__error("Could not create process thread.\n");
13188c2ecf20Sopenharmony_ci		return ret;
13198c2ecf20Sopenharmony_ci	}
13208c2ecf20Sopenharmony_ci
13218c2ecf20Sopenharmony_ci	if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
13228c2ecf20Sopenharmony_ci							    display_thread), top)) {
13238c2ecf20Sopenharmony_ci		ui__error("Could not create display thread.\n");
13248c2ecf20Sopenharmony_ci		goto out_join_thread;
13258c2ecf20Sopenharmony_ci	}
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci	if (top->realtime_prio) {
13288c2ecf20Sopenharmony_ci		struct sched_param param;
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci		param.sched_priority = top->realtime_prio;
13318c2ecf20Sopenharmony_ci		if (sched_setscheduler(0, SCHED_FIFO, &param)) {
13328c2ecf20Sopenharmony_ci			ui__error("Could not set realtime priority.\n");
13338c2ecf20Sopenharmony_ci			goto out_join;
13348c2ecf20Sopenharmony_ci		}
13358c2ecf20Sopenharmony_ci	}
13368c2ecf20Sopenharmony_ci
13378c2ecf20Sopenharmony_ci	/* Wait for a minimal set of events before starting the snapshot */
13388c2ecf20Sopenharmony_ci	evlist__poll(top->evlist, 100);
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	perf_top__mmap_read(top);
13418c2ecf20Sopenharmony_ci
13428c2ecf20Sopenharmony_ci	while (!done) {
13438c2ecf20Sopenharmony_ci		u64 hits = top->samples;
13448c2ecf20Sopenharmony_ci
13458c2ecf20Sopenharmony_ci		perf_top__mmap_read(top);
13468c2ecf20Sopenharmony_ci
13478c2ecf20Sopenharmony_ci		if (opts->overwrite || (hits == top->samples))
13488c2ecf20Sopenharmony_ci			ret = evlist__poll(top->evlist, 100);
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci		if (resize) {
13518c2ecf20Sopenharmony_ci			perf_top__resize(top);
13528c2ecf20Sopenharmony_ci			resize = 0;
13538c2ecf20Sopenharmony_ci		}
13548c2ecf20Sopenharmony_ci	}
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	ret = 0;
13578c2ecf20Sopenharmony_ciout_join:
13588c2ecf20Sopenharmony_ci	pthread_join(thread, NULL);
13598c2ecf20Sopenharmony_ciout_join_thread:
13608c2ecf20Sopenharmony_ci	pthread_cond_signal(&top->qe.cond);
13618c2ecf20Sopenharmony_ci	pthread_join(thread_process, NULL);
13628c2ecf20Sopenharmony_ci	return ret;
13638c2ecf20Sopenharmony_ci}
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_cistatic int
13668c2ecf20Sopenharmony_cicallchain_opt(const struct option *opt, const char *arg, int unset)
13678c2ecf20Sopenharmony_ci{
13688c2ecf20Sopenharmony_ci	symbol_conf.use_callchain = true;
13698c2ecf20Sopenharmony_ci	return record_callchain_opt(opt, arg, unset);
13708c2ecf20Sopenharmony_ci}
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_cistatic int
13738c2ecf20Sopenharmony_ciparse_callchain_opt(const struct option *opt, const char *arg, int unset)
13748c2ecf20Sopenharmony_ci{
13758c2ecf20Sopenharmony_ci	struct callchain_param *callchain = opt->value;
13768c2ecf20Sopenharmony_ci
13778c2ecf20Sopenharmony_ci	callchain->enabled = !unset;
13788c2ecf20Sopenharmony_ci	callchain->record_mode = CALLCHAIN_FP;
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_ci	/*
13818c2ecf20Sopenharmony_ci	 * --no-call-graph
13828c2ecf20Sopenharmony_ci	 */
13838c2ecf20Sopenharmony_ci	if (unset) {
13848c2ecf20Sopenharmony_ci		symbol_conf.use_callchain = false;
13858c2ecf20Sopenharmony_ci		callchain->record_mode = CALLCHAIN_NONE;
13868c2ecf20Sopenharmony_ci		return 0;
13878c2ecf20Sopenharmony_ci	}
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	return parse_callchain_top_opt(arg);
13908c2ecf20Sopenharmony_ci}
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_cistatic int perf_top_config(const char *var, const char *value, void *cb __maybe_unused)
13938c2ecf20Sopenharmony_ci{
13948c2ecf20Sopenharmony_ci	if (!strcmp(var, "top.call-graph")) {
13958c2ecf20Sopenharmony_ci		var = "call-graph.record-mode";
13968c2ecf20Sopenharmony_ci		return perf_default_config(var, value, cb);
13978c2ecf20Sopenharmony_ci	}
13988c2ecf20Sopenharmony_ci	if (!strcmp(var, "top.children")) {
13998c2ecf20Sopenharmony_ci		symbol_conf.cumulate_callchain = perf_config_bool(var, value);
14008c2ecf20Sopenharmony_ci		return 0;
14018c2ecf20Sopenharmony_ci	}
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci	return 0;
14048c2ecf20Sopenharmony_ci}
14058c2ecf20Sopenharmony_ci
14068c2ecf20Sopenharmony_cistatic int
14078c2ecf20Sopenharmony_ciparse_percent_limit(const struct option *opt, const char *arg,
14088c2ecf20Sopenharmony_ci		    int unset __maybe_unused)
14098c2ecf20Sopenharmony_ci{
14108c2ecf20Sopenharmony_ci	struct perf_top *top = opt->value;
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_ci	top->min_percent = strtof(arg, NULL);
14138c2ecf20Sopenharmony_ci	return 0;
14148c2ecf20Sopenharmony_ci}
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ciconst char top_callchain_help[] = CALLCHAIN_RECORD_HELP CALLCHAIN_REPORT_HELP
14178c2ecf20Sopenharmony_ci	"\n\t\t\t\tDefault: fp,graph,0.5,caller,function";
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ciint cmd_top(int argc, const char **argv)
14208c2ecf20Sopenharmony_ci{
14218c2ecf20Sopenharmony_ci	char errbuf[BUFSIZ];
14228c2ecf20Sopenharmony_ci	struct perf_top top = {
14238c2ecf20Sopenharmony_ci		.count_filter	     = 5,
14248c2ecf20Sopenharmony_ci		.delay_secs	     = 2,
14258c2ecf20Sopenharmony_ci		.record_opts = {
14268c2ecf20Sopenharmony_ci			.mmap_pages	= UINT_MAX,
14278c2ecf20Sopenharmony_ci			.user_freq	= UINT_MAX,
14288c2ecf20Sopenharmony_ci			.user_interval	= ULLONG_MAX,
14298c2ecf20Sopenharmony_ci			.freq		= 4000, /* 4 KHz */
14308c2ecf20Sopenharmony_ci			.target		= {
14318c2ecf20Sopenharmony_ci				.uses_mmap   = true,
14328c2ecf20Sopenharmony_ci			},
14338c2ecf20Sopenharmony_ci			/*
14348c2ecf20Sopenharmony_ci			 * FIXME: This will lose PERF_RECORD_MMAP and other metadata
14358c2ecf20Sopenharmony_ci			 * when we pause, fix that and reenable. Probably using a
14368c2ecf20Sopenharmony_ci			 * separate evlist with a dummy event, i.e. a non-overwrite
14378c2ecf20Sopenharmony_ci			 * ring buffer just for metadata events, while PERF_RECORD_SAMPLE
14388c2ecf20Sopenharmony_ci			 * stays in overwrite mode. -acme
14398c2ecf20Sopenharmony_ci			 * */
14408c2ecf20Sopenharmony_ci			.overwrite	= 0,
14418c2ecf20Sopenharmony_ci			.sample_time	= true,
14428c2ecf20Sopenharmony_ci			.sample_time_set = true,
14438c2ecf20Sopenharmony_ci		},
14448c2ecf20Sopenharmony_ci		.max_stack	     = sysctl__max_stack(),
14458c2ecf20Sopenharmony_ci		.annotation_opts     = annotation__default_options,
14468c2ecf20Sopenharmony_ci		.nr_threads_synthesize = UINT_MAX,
14478c2ecf20Sopenharmony_ci	};
14488c2ecf20Sopenharmony_ci	struct record_opts *opts = &top.record_opts;
14498c2ecf20Sopenharmony_ci	struct target *target = &opts->target;
14508c2ecf20Sopenharmony_ci	const struct option options[] = {
14518c2ecf20Sopenharmony_ci	OPT_CALLBACK('e', "event", &top.evlist, "event",
14528c2ecf20Sopenharmony_ci		     "event selector. use 'perf list' to list available events",
14538c2ecf20Sopenharmony_ci		     parse_events_option),
14548c2ecf20Sopenharmony_ci	OPT_U64('c', "count", &opts->user_interval, "event period to sample"),
14558c2ecf20Sopenharmony_ci	OPT_STRING('p', "pid", &target->pid, "pid",
14568c2ecf20Sopenharmony_ci		    "profile events on existing process id"),
14578c2ecf20Sopenharmony_ci	OPT_STRING('t', "tid", &target->tid, "tid",
14588c2ecf20Sopenharmony_ci		    "profile events on existing thread id"),
14598c2ecf20Sopenharmony_ci	OPT_BOOLEAN('a', "all-cpus", &target->system_wide,
14608c2ecf20Sopenharmony_ci			    "system-wide collection from all CPUs"),
14618c2ecf20Sopenharmony_ci	OPT_STRING('C', "cpu", &target->cpu_list, "cpu",
14628c2ecf20Sopenharmony_ci		    "list of cpus to monitor"),
14638c2ecf20Sopenharmony_ci	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
14648c2ecf20Sopenharmony_ci		   "file", "vmlinux pathname"),
14658c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
14668c2ecf20Sopenharmony_ci		    "don't load vmlinux even if found"),
14678c2ecf20Sopenharmony_ci	OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
14688c2ecf20Sopenharmony_ci		   "file", "kallsyms pathname"),
14698c2ecf20Sopenharmony_ci	OPT_BOOLEAN('K', "hide_kernel_symbols", &top.hide_kernel_symbols,
14708c2ecf20Sopenharmony_ci		    "hide kernel symbols"),
14718c2ecf20Sopenharmony_ci	OPT_CALLBACK('m', "mmap-pages", &opts->mmap_pages, "pages",
14728c2ecf20Sopenharmony_ci		     "number of mmap data pages",
14738c2ecf20Sopenharmony_ci		     perf_evlist__parse_mmap_pages),
14748c2ecf20Sopenharmony_ci	OPT_INTEGER('r', "realtime", &top.realtime_prio,
14758c2ecf20Sopenharmony_ci		    "collect data with this RT SCHED_FIFO priority"),
14768c2ecf20Sopenharmony_ci	OPT_INTEGER('d', "delay", &top.delay_secs,
14778c2ecf20Sopenharmony_ci		    "number of seconds to delay between refreshes"),
14788c2ecf20Sopenharmony_ci	OPT_BOOLEAN('D', "dump-symtab", &top.dump_symtab,
14798c2ecf20Sopenharmony_ci			    "dump the symbol table used for profiling"),
14808c2ecf20Sopenharmony_ci	OPT_INTEGER('f', "count-filter", &top.count_filter,
14818c2ecf20Sopenharmony_ci		    "only display functions with more events than this"),
14828c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "group", &opts->group,
14838c2ecf20Sopenharmony_ci			    "put the counters into a counter group"),
14848c2ecf20Sopenharmony_ci	OPT_BOOLEAN('i', "no-inherit", &opts->no_inherit,
14858c2ecf20Sopenharmony_ci		    "child tasks do not inherit counters"),
14868c2ecf20Sopenharmony_ci	OPT_STRING(0, "sym-annotate", &top.sym_filter, "symbol name",
14878c2ecf20Sopenharmony_ci		    "symbol to annotate"),
14888c2ecf20Sopenharmony_ci	OPT_BOOLEAN('z', "zero", &top.zero, "zero history across updates"),
14898c2ecf20Sopenharmony_ci	OPT_CALLBACK('F', "freq", &top.record_opts, "freq or 'max'",
14908c2ecf20Sopenharmony_ci		     "profile at this frequency",
14918c2ecf20Sopenharmony_ci		      record__parse_freq),
14928c2ecf20Sopenharmony_ci	OPT_INTEGER('E', "entries", &top.print_entries,
14938c2ecf20Sopenharmony_ci		    "display this many functions"),
14948c2ecf20Sopenharmony_ci	OPT_BOOLEAN('U', "hide_user_symbols", &top.hide_user_symbols,
14958c2ecf20Sopenharmony_ci		    "hide user symbols"),
14968c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "tui", &top.use_tui, "Use the TUI interface"),
14978c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "stdio", &top.use_stdio, "Use the stdio interface"),
14988c2ecf20Sopenharmony_ci	OPT_INCR('v', "verbose", &verbose,
14998c2ecf20Sopenharmony_ci		    "be more verbose (show counter open errors, etc)"),
15008c2ecf20Sopenharmony_ci	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
15018c2ecf20Sopenharmony_ci		   "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline, ..."
15028c2ecf20Sopenharmony_ci		   " Please refer the man page for the complete list."),
15038c2ecf20Sopenharmony_ci	OPT_STRING(0, "fields", &field_order, "key[,keys...]",
15048c2ecf20Sopenharmony_ci		   "output field(s): overhead, period, sample plus all of sort keys"),
15058c2ecf20Sopenharmony_ci	OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
15068c2ecf20Sopenharmony_ci		    "Show a column with the number of samples"),
15078c2ecf20Sopenharmony_ci	OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
15088c2ecf20Sopenharmony_ci			   NULL, "enables call-graph recording and display",
15098c2ecf20Sopenharmony_ci			   &callchain_opt),
15108c2ecf20Sopenharmony_ci	OPT_CALLBACK(0, "call-graph", &callchain_param,
15118c2ecf20Sopenharmony_ci		     "record_mode[,record_size],print_type,threshold[,print_limit],order,sort_key[,branch]",
15128c2ecf20Sopenharmony_ci		     top_callchain_help, &parse_callchain_opt),
15138c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
15148c2ecf20Sopenharmony_ci		    "Accumulate callchains of children and show total overhead as well"),
15158c2ecf20Sopenharmony_ci	OPT_INTEGER(0, "max-stack", &top.max_stack,
15168c2ecf20Sopenharmony_ci		    "Set the maximum stack depth when parsing the callchain. "
15178c2ecf20Sopenharmony_ci		    "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
15188c2ecf20Sopenharmony_ci	OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
15198c2ecf20Sopenharmony_ci		   "ignore callees of these functions in call graphs",
15208c2ecf20Sopenharmony_ci		   report_parse_ignore_callees_opt),
15218c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
15228c2ecf20Sopenharmony_ci		    "Show a column with the sum of periods"),
15238c2ecf20Sopenharmony_ci	OPT_STRING(0, "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
15248c2ecf20Sopenharmony_ci		   "only consider symbols in these dsos"),
15258c2ecf20Sopenharmony_ci	OPT_STRING(0, "comms", &symbol_conf.comm_list_str, "comm[,comm...]",
15268c2ecf20Sopenharmony_ci		   "only consider symbols in these comms"),
15278c2ecf20Sopenharmony_ci	OPT_STRING(0, "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
15288c2ecf20Sopenharmony_ci		   "only consider these symbols"),
15298c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "source", &top.annotation_opts.annotate_src,
15308c2ecf20Sopenharmony_ci		    "Interleave source code with assembly code (default)"),
15318c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "asm-raw", &top.annotation_opts.show_asm_raw,
15328c2ecf20Sopenharmony_ci		    "Display raw encoding of assembly instructions (default)"),
15338c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
15348c2ecf20Sopenharmony_ci		    "Enable kernel symbol demangling"),
15358c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "no-bpf-event", &top.record_opts.no_bpf_event, "do not record bpf events"),
15368c2ecf20Sopenharmony_ci	OPT_STRING(0, "objdump", &top.annotation_opts.objdump_path, "path",
15378c2ecf20Sopenharmony_ci		    "objdump binary to use for disassembly and annotations"),
15388c2ecf20Sopenharmony_ci	OPT_STRING('M', "disassembler-style", &top.annotation_opts.disassembler_style, "disassembler style",
15398c2ecf20Sopenharmony_ci		   "Specify disassembler style (e.g. -M intel for intel syntax)"),
15408c2ecf20Sopenharmony_ci	OPT_STRING(0, "prefix", &top.annotation_opts.prefix, "prefix",
15418c2ecf20Sopenharmony_ci		    "Add prefix to source file path names in programs (with --prefix-strip)"),
15428c2ecf20Sopenharmony_ci	OPT_STRING(0, "prefix-strip", &top.annotation_opts.prefix_strip, "N",
15438c2ecf20Sopenharmony_ci		    "Strip first N entries of source file path name in programs (with --prefix)"),
15448c2ecf20Sopenharmony_ci	OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"),
15458c2ecf20Sopenharmony_ci	OPT_CALLBACK(0, "percent-limit", &top, "percent",
15468c2ecf20Sopenharmony_ci		     "Don't show entries under that percent", parse_percent_limit),
15478c2ecf20Sopenharmony_ci	OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
15488c2ecf20Sopenharmony_ci		     "How to display percentage of filtered entries", parse_filter_percentage),
15498c2ecf20Sopenharmony_ci	OPT_STRING('w', "column-widths", &symbol_conf.col_width_list_str,
15508c2ecf20Sopenharmony_ci		   "width[,width...]",
15518c2ecf20Sopenharmony_ci		   "don't try to adjust column width, use these fixed values"),
15528c2ecf20Sopenharmony_ci	OPT_UINTEGER(0, "proc-map-timeout", &proc_map_timeout,
15538c2ecf20Sopenharmony_ci			"per thread proc mmap processing timeout in ms"),
15548c2ecf20Sopenharmony_ci	OPT_CALLBACK_NOOPT('b', "branch-any", &opts->branch_stack,
15558c2ecf20Sopenharmony_ci		     "branch any", "sample any taken branches",
15568c2ecf20Sopenharmony_ci		     parse_branch_stack),
15578c2ecf20Sopenharmony_ci	OPT_CALLBACK('j', "branch-filter", &opts->branch_stack,
15588c2ecf20Sopenharmony_ci		     "branch filter mask", "branch stack filter modes",
15598c2ecf20Sopenharmony_ci		     parse_branch_stack),
15608c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "raw-trace", &symbol_conf.raw_trace,
15618c2ecf20Sopenharmony_ci		    "Show raw trace event output (do not use print fmt or plugins)"),
15628c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
15638c2ecf20Sopenharmony_ci		    "Show entries in a hierarchy"),
15648c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "overwrite", &top.record_opts.overwrite,
15658c2ecf20Sopenharmony_ci		    "Use a backward ring buffer, default: no"),
15668c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"),
15678c2ecf20Sopenharmony_ci	OPT_UINTEGER(0, "num-thread-synthesize", &top.nr_threads_synthesize,
15688c2ecf20Sopenharmony_ci			"number of thread to run event synthesize"),
15698c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "namespaces", &opts->record_namespaces,
15708c2ecf20Sopenharmony_ci		    "Record namespaces events"),
15718c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "all-cgroups", &opts->record_cgroup,
15728c2ecf20Sopenharmony_ci		    "Record cgroup events"),
15738c2ecf20Sopenharmony_ci	OPT_INTEGER(0, "group-sort-idx", &symbol_conf.group_sort_idx,
15748c2ecf20Sopenharmony_ci		    "Sort the output by the event at the index n in group. "
15758c2ecf20Sopenharmony_ci		    "If n is invalid, sort by the first event. "
15768c2ecf20Sopenharmony_ci		    "WARNING: should be used on grouped events."),
15778c2ecf20Sopenharmony_ci	OPT_BOOLEAN(0, "stitch-lbr", &top.stitch_lbr,
15788c2ecf20Sopenharmony_ci		    "Enable LBR callgraph stitching approach"),
15798c2ecf20Sopenharmony_ci#ifdef HAVE_LIBPFM
15808c2ecf20Sopenharmony_ci	OPT_CALLBACK(0, "pfm-events", &top.evlist, "event",
15818c2ecf20Sopenharmony_ci		"libpfm4 event selector. use 'perf list' to list available events",
15828c2ecf20Sopenharmony_ci		parse_libpfm_events_option),
15838c2ecf20Sopenharmony_ci#endif
15848c2ecf20Sopenharmony_ci	OPTS_EVSWITCH(&top.evswitch),
15858c2ecf20Sopenharmony_ci	OPT_END()
15868c2ecf20Sopenharmony_ci	};
15878c2ecf20Sopenharmony_ci	const char * const top_usage[] = {
15888c2ecf20Sopenharmony_ci		"perf top [<options>]",
15898c2ecf20Sopenharmony_ci		NULL
15908c2ecf20Sopenharmony_ci	};
15918c2ecf20Sopenharmony_ci	int status = hists__init();
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	if (status < 0)
15948c2ecf20Sopenharmony_ci		return status;
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_ci	top.annotation_opts.min_pcnt = 5;
15978c2ecf20Sopenharmony_ci	top.annotation_opts.context  = 4;
15988c2ecf20Sopenharmony_ci
15998c2ecf20Sopenharmony_ci	top.evlist = evlist__new();
16008c2ecf20Sopenharmony_ci	if (top.evlist == NULL)
16018c2ecf20Sopenharmony_ci		return -ENOMEM;
16028c2ecf20Sopenharmony_ci
16038c2ecf20Sopenharmony_ci	status = perf_config(perf_top_config, &top);
16048c2ecf20Sopenharmony_ci	if (status)
16058c2ecf20Sopenharmony_ci		return status;
16068c2ecf20Sopenharmony_ci	/*
16078c2ecf20Sopenharmony_ci	 * Since the per arch annotation init routine may need the cpuid, read
16088c2ecf20Sopenharmony_ci	 * it here, since we are not getting this from the perf.data header.
16098c2ecf20Sopenharmony_ci	 */
16108c2ecf20Sopenharmony_ci	status = perf_env__read_cpuid(&perf_env);
16118c2ecf20Sopenharmony_ci	if (status) {
16128c2ecf20Sopenharmony_ci		/*
16138c2ecf20Sopenharmony_ci		 * Some arches do not provide a get_cpuid(), so just use pr_debug, otherwise
16148c2ecf20Sopenharmony_ci		 * warn the user explicitely.
16158c2ecf20Sopenharmony_ci		 */
16168c2ecf20Sopenharmony_ci		eprintf(status == ENOSYS ? 1 : 0, verbose,
16178c2ecf20Sopenharmony_ci			"Couldn't read the cpuid for this machine: %s\n",
16188c2ecf20Sopenharmony_ci			str_error_r(errno, errbuf, sizeof(errbuf)));
16198c2ecf20Sopenharmony_ci	}
16208c2ecf20Sopenharmony_ci	top.evlist->env = &perf_env;
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci	argc = parse_options(argc, argv, options, top_usage, 0);
16238c2ecf20Sopenharmony_ci	if (argc)
16248c2ecf20Sopenharmony_ci		usage_with_options(top_usage, options);
16258c2ecf20Sopenharmony_ci
16268c2ecf20Sopenharmony_ci	if (annotate_check_args(&top.annotation_opts) < 0)
16278c2ecf20Sopenharmony_ci		goto out_delete_evlist;
16288c2ecf20Sopenharmony_ci
16298c2ecf20Sopenharmony_ci	if (!top.evlist->core.nr_entries &&
16308c2ecf20Sopenharmony_ci	    evlist__add_default(top.evlist) < 0) {
16318c2ecf20Sopenharmony_ci		pr_err("Not enough memory for event selector list\n");
16328c2ecf20Sopenharmony_ci		goto out_delete_evlist;
16338c2ecf20Sopenharmony_ci	}
16348c2ecf20Sopenharmony_ci
16358c2ecf20Sopenharmony_ci	status = evswitch__init(&top.evswitch, top.evlist, stderr);
16368c2ecf20Sopenharmony_ci	if (status)
16378c2ecf20Sopenharmony_ci		goto out_delete_evlist;
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci	if (symbol_conf.report_hierarchy) {
16408c2ecf20Sopenharmony_ci		/* disable incompatible options */
16418c2ecf20Sopenharmony_ci		symbol_conf.event_group = false;
16428c2ecf20Sopenharmony_ci		symbol_conf.cumulate_callchain = false;
16438c2ecf20Sopenharmony_ci
16448c2ecf20Sopenharmony_ci		if (field_order) {
16458c2ecf20Sopenharmony_ci			pr_err("Error: --hierarchy and --fields options cannot be used together\n");
16468c2ecf20Sopenharmony_ci			parse_options_usage(top_usage, options, "fields", 0);
16478c2ecf20Sopenharmony_ci			parse_options_usage(NULL, options, "hierarchy", 0);
16488c2ecf20Sopenharmony_ci			goto out_delete_evlist;
16498c2ecf20Sopenharmony_ci		}
16508c2ecf20Sopenharmony_ci	}
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci	if (top.stitch_lbr && !(callchain_param.record_mode == CALLCHAIN_LBR)) {
16538c2ecf20Sopenharmony_ci		pr_err("Error: --stitch-lbr must be used with --call-graph lbr\n");
16548c2ecf20Sopenharmony_ci		goto out_delete_evlist;
16558c2ecf20Sopenharmony_ci	}
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_ci	if (opts->branch_stack && callchain_param.enabled)
16588c2ecf20Sopenharmony_ci		symbol_conf.show_branchflag_count = true;
16598c2ecf20Sopenharmony_ci
16608c2ecf20Sopenharmony_ci	sort__mode = SORT_MODE__TOP;
16618c2ecf20Sopenharmony_ci	/* display thread wants entries to be collapsed in a different tree */
16628c2ecf20Sopenharmony_ci	perf_hpp_list.need_collapse = 1;
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci	if (top.use_stdio)
16658c2ecf20Sopenharmony_ci		use_browser = 0;
16668c2ecf20Sopenharmony_ci	else if (top.use_tui)
16678c2ecf20Sopenharmony_ci		use_browser = 1;
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci	setup_browser(false);
16708c2ecf20Sopenharmony_ci
16718c2ecf20Sopenharmony_ci	if (setup_sorting(top.evlist) < 0) {
16728c2ecf20Sopenharmony_ci		if (sort_order)
16738c2ecf20Sopenharmony_ci			parse_options_usage(top_usage, options, "s", 1);
16748c2ecf20Sopenharmony_ci		if (field_order)
16758c2ecf20Sopenharmony_ci			parse_options_usage(sort_order ? NULL : top_usage,
16768c2ecf20Sopenharmony_ci					    options, "fields", 0);
16778c2ecf20Sopenharmony_ci		goto out_delete_evlist;
16788c2ecf20Sopenharmony_ci	}
16798c2ecf20Sopenharmony_ci
16808c2ecf20Sopenharmony_ci	status = target__validate(target);
16818c2ecf20Sopenharmony_ci	if (status) {
16828c2ecf20Sopenharmony_ci		target__strerror(target, status, errbuf, BUFSIZ);
16838c2ecf20Sopenharmony_ci		ui__warning("%s\n", errbuf);
16848c2ecf20Sopenharmony_ci	}
16858c2ecf20Sopenharmony_ci
16868c2ecf20Sopenharmony_ci	status = target__parse_uid(target);
16878c2ecf20Sopenharmony_ci	if (status) {
16888c2ecf20Sopenharmony_ci		int saved_errno = errno;
16898c2ecf20Sopenharmony_ci
16908c2ecf20Sopenharmony_ci		target__strerror(target, status, errbuf, BUFSIZ);
16918c2ecf20Sopenharmony_ci		ui__error("%s\n", errbuf);
16928c2ecf20Sopenharmony_ci
16938c2ecf20Sopenharmony_ci		status = -saved_errno;
16948c2ecf20Sopenharmony_ci		goto out_delete_evlist;
16958c2ecf20Sopenharmony_ci	}
16968c2ecf20Sopenharmony_ci
16978c2ecf20Sopenharmony_ci	if (target__none(target))
16988c2ecf20Sopenharmony_ci		target->system_wide = true;
16998c2ecf20Sopenharmony_ci
17008c2ecf20Sopenharmony_ci	if (perf_evlist__create_maps(top.evlist, target) < 0) {
17018c2ecf20Sopenharmony_ci		ui__error("Couldn't create thread/CPU maps: %s\n",
17028c2ecf20Sopenharmony_ci			  errno == ENOENT ? "No such process" : str_error_r(errno, errbuf, sizeof(errbuf)));
17038c2ecf20Sopenharmony_ci		goto out_delete_evlist;
17048c2ecf20Sopenharmony_ci	}
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci	if (top.delay_secs < 1)
17078c2ecf20Sopenharmony_ci		top.delay_secs = 1;
17088c2ecf20Sopenharmony_ci
17098c2ecf20Sopenharmony_ci	if (record_opts__config(opts)) {
17108c2ecf20Sopenharmony_ci		status = -EINVAL;
17118c2ecf20Sopenharmony_ci		goto out_delete_evlist;
17128c2ecf20Sopenharmony_ci	}
17138c2ecf20Sopenharmony_ci
17148c2ecf20Sopenharmony_ci	top.sym_evsel = evlist__first(top.evlist);
17158c2ecf20Sopenharmony_ci
17168c2ecf20Sopenharmony_ci	if (!callchain_param.enabled) {
17178c2ecf20Sopenharmony_ci		symbol_conf.cumulate_callchain = false;
17188c2ecf20Sopenharmony_ci		perf_hpp__cancel_cumulate();
17198c2ecf20Sopenharmony_ci	}
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci	if (symbol_conf.cumulate_callchain && !callchain_param.order_set)
17228c2ecf20Sopenharmony_ci		callchain_param.order = ORDER_CALLER;
17238c2ecf20Sopenharmony_ci
17248c2ecf20Sopenharmony_ci	status = symbol__annotation_init();
17258c2ecf20Sopenharmony_ci	if (status < 0)
17268c2ecf20Sopenharmony_ci		goto out_delete_evlist;
17278c2ecf20Sopenharmony_ci
17288c2ecf20Sopenharmony_ci	annotation_config__init(&top.annotation_opts);
17298c2ecf20Sopenharmony_ci
17308c2ecf20Sopenharmony_ci	symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
17318c2ecf20Sopenharmony_ci	status = symbol__init(NULL);
17328c2ecf20Sopenharmony_ci	if (status < 0)
17338c2ecf20Sopenharmony_ci		goto out_delete_evlist;
17348c2ecf20Sopenharmony_ci
17358c2ecf20Sopenharmony_ci	sort__setup_elide(stdout);
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_ci	get_term_dimensions(&top.winsize);
17388c2ecf20Sopenharmony_ci	if (top.print_entries == 0) {
17398c2ecf20Sopenharmony_ci		perf_top__update_print_entries(&top);
17408c2ecf20Sopenharmony_ci		signal(SIGWINCH, winch_sig);
17418c2ecf20Sopenharmony_ci	}
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci	top.session = perf_session__new(NULL, false, NULL);
17448c2ecf20Sopenharmony_ci	if (IS_ERR(top.session)) {
17458c2ecf20Sopenharmony_ci		status = PTR_ERR(top.session);
17468c2ecf20Sopenharmony_ci		top.session = NULL;
17478c2ecf20Sopenharmony_ci		goto out_delete_evlist;
17488c2ecf20Sopenharmony_ci	}
17498c2ecf20Sopenharmony_ci
17508c2ecf20Sopenharmony_ci#ifdef HAVE_LIBBPF_SUPPORT
17518c2ecf20Sopenharmony_ci	if (!top.record_opts.no_bpf_event) {
17528c2ecf20Sopenharmony_ci		top.sb_evlist = evlist__new();
17538c2ecf20Sopenharmony_ci
17548c2ecf20Sopenharmony_ci		if (top.sb_evlist == NULL) {
17558c2ecf20Sopenharmony_ci			pr_err("Couldn't create side band evlist.\n.");
17568c2ecf20Sopenharmony_ci			goto out_delete_evlist;
17578c2ecf20Sopenharmony_ci		}
17588c2ecf20Sopenharmony_ci
17598c2ecf20Sopenharmony_ci		if (evlist__add_bpf_sb_event(top.sb_evlist, &perf_env)) {
17608c2ecf20Sopenharmony_ci			pr_err("Couldn't ask for PERF_RECORD_BPF_EVENT side band events.\n.");
17618c2ecf20Sopenharmony_ci			goto out_delete_evlist;
17628c2ecf20Sopenharmony_ci		}
17638c2ecf20Sopenharmony_ci	}
17648c2ecf20Sopenharmony_ci#endif
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_ci	if (perf_evlist__start_sb_thread(top.sb_evlist, target)) {
17678c2ecf20Sopenharmony_ci		pr_debug("Couldn't start the BPF side band thread:\nBPF programs starting from now on won't be annotatable\n");
17688c2ecf20Sopenharmony_ci		opts->no_bpf_event = true;
17698c2ecf20Sopenharmony_ci	}
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_ci	status = __cmd_top(&top);
17728c2ecf20Sopenharmony_ci
17738c2ecf20Sopenharmony_ci	if (!opts->no_bpf_event)
17748c2ecf20Sopenharmony_ci		perf_evlist__stop_sb_thread(top.sb_evlist);
17758c2ecf20Sopenharmony_ci
17768c2ecf20Sopenharmony_ciout_delete_evlist:
17778c2ecf20Sopenharmony_ci	evlist__delete(top.evlist);
17788c2ecf20Sopenharmony_ci	perf_session__delete(top.session);
17798c2ecf20Sopenharmony_ci
17808c2ecf20Sopenharmony_ci	return status;
17818c2ecf20Sopenharmony_ci}
1782