tools/perf/util/thread.c

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

File Facts

System
Linux kernel
Corpus path
tools/perf/util/thread.c
Extension
.c
Size
15459 bytes
Lines
624
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 thread__prepare_access_maps_cb_args {
	int err;
	struct maps *maps;
};

static int thread__prepare_access_maps_cb(struct map *map, void *data)
{
	bool initialized = false;
	struct thread__prepare_access_maps_cb_args *args = data;

	args->err = unwind__prepare_access(args->maps, map, &initialized);

	return (args->err || initialized) ? 1 : 0;
}

static int thread__prepare_access(struct thread *thread)
{
	struct thread__prepare_access_maps_cb_args args = {
		.err = 0,
	};

	if (dwarf_callchain_users) {
		args.maps = thread__maps(thread);
		maps__for_each_map(thread__maps(thread), thread__prepare_access_maps_cb, &args);
	}

	return args.err;
}

static int thread__clone_maps(struct thread *thread, struct thread *parent, bool do_maps_clone)
{
	/* This is new thread, we share map groups for process. */
	if (thread__pid(thread) == thread__pid(parent))
		return thread__prepare_access(thread);

	if (maps__equal(thread__maps(thread), thread__maps(parent))) {
		pr_debug("broken map groups on thread %d/%d parent %d/%d\n",
			 thread__pid(thread), thread__tid(thread),
			 thread__pid(parent), thread__tid(parent));
		return 0;
	}
	/* But this one is new process, copy maps. */
	return do_maps_clone ? maps__copy_from(thread__maps(thread), thread__maps(parent)) : 0;
}

int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp, bool do_maps_clone)
{
	if (thread__comm_set(parent)) {
		const char *comm = thread__comm_str(parent);
		int err;
		if (!comm)
			return -ENOMEM;
		err = thread__set_comm(thread, comm, timestamp);
		if (err)
			return err;
	}

	thread__set_ppid(thread, thread__tid(parent));
	return thread__clone_maps(thread, parent, do_maps_clone);
}

void thread__find_cpumode_addr_location(struct thread *thread, u64 addr,
					bool symbols, struct addr_location *al)
{
	size_t i;
	const u8 cpumodes[] = {
		PERF_RECORD_MISC_USER,
		PERF_RECORD_MISC_KERNEL,
		PERF_RECORD_MISC_GUEST_USER,
		PERF_RECORD_MISC_GUEST_KERNEL
	};

	for (i = 0; i < ARRAY_SIZE(cpumodes); i++) {
		if (symbols)
			thread__find_symbol(thread, cpumodes[i], addr, al);
		else
			thread__find_map(thread, cpumodes[i], addr, al);

		if (al->map)
			break;
	}
}

static uint16_t read_proc_e_machine_for_pid(pid_t pid, uint32_t *e_flags)
{
	char path[6 /* "/proc/" */ + 11 /* max length of pid */ + 5 /* "/exe\0" */];
	int fd;
	uint16_t e_machine = EM_NONE;

	snprintf(path, sizeof(path), "/proc/%d/exe", pid);

Annotation

Implementation Notes