tools/lib/perf/evlist.c

Source file repositories/reference/linux-study-clean/tools/lib/perf/evlist.c

File Facts

System
Linux kernel
Corpus path
tools/lib/perf/evlist.c
Extension
.c
Size
21163 bytes
Lines
841
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

if (perf_cpu_map__is_empty(evsel->pmu_cpus)) {
			/*
			 * Assume the unset PMU cpus were for a system-wide
			 * event, like a software or tracepoint.
			 */
			evsel->pmu_cpus = perf_cpu_map__new_online_cpus();
		}
		if (evlist->has_user_cpus && !evsel->system_wide) {
			/*
			 * Use the user CPUs unless the evsel is set to be
			 * system wide, such as the dummy event.
			 */
			evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus);
		} else {
			/*
			 * System wide and other modes, assume the cpu map
			 * should be set to all PMU CPUs.
			 */
			evsel->cpus = perf_cpu_map__get(evsel->pmu_cpus);
		}
	}
	/*
	 * Avoid "any CPU"(-1) for uncore and PMUs that require a CPU, even if
	 * requested.
	 */
	if (evsel->requires_cpu && perf_cpu_map__has_any_cpu(evsel->cpus)) {
		perf_cpu_map__put(evsel->cpus);
		evsel->cpus = perf_cpu_map__get(evsel->pmu_cpus);
	}

	/*
	 * Globally requested CPUs replace user requested unless the evsel is
	 * set to be system wide.
	 */
	if (evlist->has_user_cpus && !evsel->system_wide) {
		assert(!perf_cpu_map__has_any_cpu(evlist->user_requested_cpus));
		if (!perf_cpu_map__equal(evsel->cpus, evlist->user_requested_cpus)) {
			perf_cpu_map__put(evsel->cpus);
			evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus);
		}
	}

	/* Ensure cpus only references valid PMU CPUs. */
	if (!perf_cpu_map__has_any_cpu(evsel->cpus) &&
	    !perf_cpu_map__is_subset(evsel->pmu_cpus, evsel->cpus)) {
		struct perf_cpu_map *tmp = perf_cpu_map__intersect(evsel->pmu_cpus, evsel->cpus);

		perf_cpu_map__put(evsel->cpus);
		evsel->cpus = tmp;
	}

	/*
	 * Was event requested on all the PMU's CPUs but the user requested is
	 * any CPU (-1)? If so switch to using any CPU (-1) to reduce the number
	 * of events.
	 */
	if (!evsel->system_wide &&
	    !evsel->requires_cpu &&
	    perf_cpu_map__equal(evsel->cpus, evsel->pmu_cpus) &&
	    perf_cpu_map__has_any_cpu(evlist->user_requested_cpus)) {
		perf_cpu_map__put(evsel->cpus);
		evsel->cpus = perf_cpu_map__get(evlist->user_requested_cpus);
	}

	/*
	 * Tool events may only read on the first CPU index to avoid double
	 * counting things like duration_time. Make the evsel->cpus contain just
	 * that single entry otherwise we may spend time changing affinity to
	 * CPUs that just have tool events, etc.
	 */
	if (evsel->reads_only_on_cpu_idx0 && perf_cpu_map__nr(evsel->cpus) > 0) {
		struct perf_cpu_map *srcs[3] = {
			evlist->all_cpus,
			evlist->user_requested_cpus,
			evsel->pmu_cpus,
		};
		for (size_t i = 0; i < ARRAY_SIZE(srcs); i++) {
			if (!srcs[i])
				continue;

			perf_cpu_map__put(evsel->cpus);
			evsel->cpus = perf_cpu_map__new_int(perf_cpu_map__cpu(srcs[i], 0).cpu);
			break;
		}
	}

	/* Sanity check assert before the evsel is potentially removed. */
	assert(!evsel->requires_cpu || !perf_cpu_map__has_any_cpu(evsel->cpus));

	/*

Annotation

Implementation Notes