tools/perf/tests/switch-tracking.c

Source file repositories/reference/linux-study-clean/tools/perf/tests/switch-tracking.c

File Facts

System
Linux kernel
Corpus path
tools/perf/tests/switch-tracking.c
Extension
.c
Size
13522 bytes
Lines
595
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 switch_tracking {
	struct evsel *switch_evsel;
	struct evsel *cycles_evsel;
	pid_t *tids;
	int nr_tids;
	int comm_seen[4];
	int cycles_before_comm_1;
	int cycles_between_comm_2_and_comm_3;
	int cycles_after_comm_4;
};

static int check_comm(struct switch_tracking *switch_tracking,
		      union perf_event *event, const char *comm, int nr)
{
	if (event->header.type == PERF_RECORD_COMM &&
	    (pid_t)event->comm.pid == getpid() &&
	    (pid_t)event->comm.tid == getpid() &&
	    strcmp(event->comm.comm, comm) == 0) {
		if (switch_tracking->comm_seen[nr]) {
			pr_debug("Duplicate comm event\n");
			return -1;
		}
		switch_tracking->comm_seen[nr] = 1;
		pr_debug3("comm event: %s nr: %d\n", event->comm.comm, nr);
		return 1;
	}
	return 0;
}

static int check_cpu(struct switch_tracking *switch_tracking, int cpu)
{
	int i, nr = cpu + 1;

	if (cpu < 0)
		return -1;

	if (!switch_tracking->tids) {
		switch_tracking->tids = calloc(nr, sizeof(pid_t));
		if (!switch_tracking->tids)
			return -1;
		for (i = 0; i < nr; i++)
			switch_tracking->tids[i] = -1;
		switch_tracking->nr_tids = nr;
		return 0;
	}

	if (cpu >= switch_tracking->nr_tids) {
		void *addr;

		addr = realloc(switch_tracking->tids, nr * sizeof(pid_t));
		if (!addr)
			return -1;
		switch_tracking->tids = addr;
		for (i = switch_tracking->nr_tids; i < nr; i++)
			switch_tracking->tids[i] = -1;
		switch_tracking->nr_tids = nr;
		return 0;
	}

	return 0;
}

static int process_sample_event(struct evlist *evlist,
				union perf_event *event,
				struct switch_tracking *switch_tracking)
{
	struct perf_sample sample;
	struct evsel *evsel;
	pid_t next_tid, prev_tid;
	int cpu, err;

	perf_sample__init(&sample, /*all=*/false);
	if (evlist__parse_sample(evlist, event, &sample)) {
		pr_debug("evlist__parse_sample failed\n");
		err = -1;
		goto out;
	}

	evsel = evlist__id2evsel(evlist, sample.id);
	if (evsel == switch_tracking->switch_evsel) {
		next_tid = evsel__intval(evsel, &sample, "next_pid");
		prev_tid = evsel__intval(evsel, &sample, "prev_pid");
		cpu = sample.cpu;
		pr_debug3("sched_switch: cpu: %d prev_tid %d next_tid %d\n",
			  cpu, prev_tid, next_tid);
		err = check_cpu(switch_tracking, cpu);
		if (err)
			goto out;
		/*
		 * Check for no missing sched_switch events i.e. that the

Annotation

Implementation Notes