tools/perf/util/intel-tpebs.c

Source file repositories/reference/linux-study-clean/tools/perf/util/intel-tpebs.c

File Facts

System
Linux kernel
Corpus path
tools/perf/util/intel-tpebs.c
Extension
.c
Size
15437 bytes
Lines
654
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct tpebs_retire_lat {
	struct list_head nd;
	/** @evsel: The evsel that opened the retire_lat event. */
	struct evsel *evsel;
	/** @event: Event passed to perf record. */
	char *event;
	/** @stats: Recorded retirement latency stats. */
	struct stats stats;
	/** @last: Last retirement latency read. */
	uint64_t last;
	/* Has the event been sent to perf record? */
	bool started;
};

static void tpebs_mtx_init(void)
{
	mutex_init(&tpebs_mtx);
}

static struct mutex *tpebs_mtx_get(void)
{
	static pthread_once_t tpebs_mtx_once = PTHREAD_ONCE_INIT;

	pthread_once(&tpebs_mtx_once, tpebs_mtx_init);
	return &tpebs_mtx;
}

static struct tpebs_retire_lat *tpebs_retire_lat__find(struct evsel *evsel)
	EXCLUSIVE_LOCKS_REQUIRED(tpebs_mtx_get());

static int evsel__tpebs_start_perf_record(struct evsel *evsel)
{
	const char **record_argv;
	int tpebs_event_size = 0, i = 0, ret;
	char control_fd_buf[32];
	char cpumap_buf[50];
	struct tpebs_retire_lat *t;

	list_for_each_entry(t, &tpebs_results, nd)
		tpebs_event_size++;

	record_argv = malloc((10 + 2 * tpebs_event_size) * sizeof(*record_argv));
	if (!record_argv)
		return -ENOMEM;

	record_argv[i++] = "perf";
	record_argv[i++] = "record";
	record_argv[i++] = "-W";
	record_argv[i++] = "--synth=no";

	scnprintf(control_fd_buf, sizeof(control_fd_buf), "--control=fd:%d,%d",
		  control_fd[0], ack_fd[1]);
	record_argv[i++] = control_fd_buf;

	record_argv[i++] = "-o";
	record_argv[i++] = PERF_DATA;

	if (!perf_cpu_map__is_any_cpu_or_is_empty(evsel->evlist->core.user_requested_cpus)) {
		cpu_map__snprint(evsel->evlist->core.user_requested_cpus, cpumap_buf,
				 sizeof(cpumap_buf));
		record_argv[i++] = "-C";
		record_argv[i++] = cpumap_buf;
	}

	list_for_each_entry(t, &tpebs_results, nd) {
		record_argv[i++] = "-e";
		record_argv[i++] = t->event;
	}
	record_argv[i++] = NULL;
	assert(i == 10 + 2 * tpebs_event_size || i == 8 + 2 * tpebs_event_size);
	/* Note, no workload given so system wide is implied. */

	assert(tpebs_cmd.pid == 0);
	tpebs_cmd.argv = record_argv;
	tpebs_cmd.out = -1;
	ret = start_command(&tpebs_cmd);
	zfree(&tpebs_cmd.argv);
	list_for_each_entry(t, &tpebs_results, nd)
		t->started = true;

	return ret;
}

static bool is_child_pid(pid_t parent, pid_t child)
{
	if (parent < 0 || child < 0)
		return false;

	while (true) {
		char path[PATH_MAX];

Annotation

Implementation Notes