Beispiel #1
0
struct thread_map *thread_map__new_by_pid(pid_t pid)
{
	struct thread_map *threads;
	char name[256];
	int items;
	struct dirent **namelist = NULL;
	int i;

	sprintf(name, "/proc/%d/task", pid);
	items = scandir(name, &namelist, filter, NULL);
	if (items <= 0)
		return NULL;

	threads = thread_map__alloc(items);
	if (threads != NULL) {
		for (i = 0; i < items; i++)
			thread_map__set_pid(threads, i, atoi(namelist[i]->d_name));
		threads->nr = items;
		atomic_set(&threads->refcnt, 1);
	}

	for (i=0; i<items; i++)
		zfree(&namelist[i]);
	free(namelist);

	return threads;
}
Beispiel #2
0
struct thread_map *thread_map__new_dummy(void)
{
	struct thread_map *threads = thread_map__alloc(1);

	if (threads != NULL) {
		thread_map__set_pid(threads, 0, -1);
		threads->nr = 1;
		atomic_set(&threads->refcnt, 1);
	}
	return threads;
}
Beispiel #3
0
struct thread_map *thread_map__new_by_tid(pid_t tid)
{
	struct thread_map *threads = thread_map__alloc(1);

	if (threads != NULL) {
		thread_map__set_pid(threads, 0, tid);
		threads->nr = 1;
		atomic_set(&threads->refcnt, 1);
	}

	return threads;
}
Beispiel #4
0
static void thread_map__copy_event(struct thread_map *threads,
				   struct thread_map_event *event)
{
	unsigned i;

	threads->nr = (int) event->nr;

	for (i = 0; i < event->nr; i++) {
		thread_map__set_pid(threads, i, (pid_t) event->entries[i].pid);
		threads->map[i].comm = strndup(event->entries[i].comm, 16);
	}

	atomic_set(&threads->refcnt, 1);
}
Beispiel #5
0
struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
{
	struct thread_map *threads = NULL, *nt;
	int ntasks = 0;
	pid_t tid, prev_tid = INT_MAX;
	char *end_ptr;
	struct str_node *pos;
	struct strlist_config slist_config = { .dont_dupstr = true, };
	struct strlist *slist;

	/* perf-stat expects threads to be generated even if tid not given */
	if (!tid_str)
		return thread_map__new_dummy();

	slist = strlist__new(tid_str, &slist_config);
	if (!slist)
		return NULL;

	strlist__for_each_entry(pos, slist) {
		tid = strtol(pos->s, &end_ptr, 10);

		if (tid == INT_MIN || tid == INT_MAX ||
		    (*end_ptr != '\0' && *end_ptr != ','))
			goto out_free_threads;

		if (tid == prev_tid)
			continue;

		ntasks++;
		nt = thread_map__realloc(threads, ntasks);

		if (nt == NULL)
			goto out_free_threads;

		threads = nt;
		thread_map__set_pid(threads, ntasks - 1, tid);
		threads->nr = ntasks;
	}
out:
	if (threads)
		atomic_set(&threads->refcnt, 1);
	return threads;

out_free_threads:
	zfree(&threads);
	strlist__delete(slist);
	goto out;
}
Beispiel #6
0
struct thread_map *thread_map__new_by_uid(uid_t uid)
{
	DIR *proc;
	int max_threads = 32, items, i;
	char path[256];
	struct dirent *dirent, **namelist = NULL;
	struct thread_map *threads = thread_map__alloc(max_threads);

	if (threads == NULL)
		goto out;

	proc = opendir("/proc");
	if (proc == NULL)
		goto out_free_threads;

	threads->nr = 0;
	atomic_set(&threads->refcnt, 1);

	while ((dirent = readdir(proc)) != NULL) {
		char *end;
		bool grow = false;
		struct stat st;
		pid_t pid = strtol(dirent->d_name, &end, 10);

		if (*end) /* only interested in proper numerical dirents */
			continue;

		snprintf(path, sizeof(path), "/proc/%s", dirent->d_name);

		if (stat(path, &st) != 0)
			continue;

		if (st.st_uid != uid)
			continue;

		snprintf(path, sizeof(path), "/proc/%d/task", pid);
		items = scandir(path, &namelist, filter, NULL);
		if (items <= 0)
			goto out_free_closedir;

		while (threads->nr + items >= max_threads) {
			max_threads *= 2;
			grow = true;
		}

		if (grow) {
			struct thread_map *tmp;

			tmp = thread_map__realloc(threads, max_threads);
			if (tmp == NULL)
				goto out_free_namelist;

			threads = tmp;
		}

		for (i = 0; i < items; i++) {
			thread_map__set_pid(threads, threads->nr + i,
					    atoi(namelist[i]->d_name));
		}

		for (i = 0; i < items; i++)
			zfree(&namelist[i]);
		free(namelist);

		threads->nr += items;
	}

out_closedir:
	closedir(proc);
out:
	return threads;

out_free_threads:
	free(threads);
	return NULL;

out_free_namelist:
	for (i = 0; i < items; i++)
		zfree(&namelist[i]);
	free(namelist);

out_free_closedir:
	zfree(&threads);
	goto out_closedir;
}
Beispiel #7
0
static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
{
	struct thread_map *threads = NULL, *nt;
	char name[256];
	int items, total_tasks = 0;
	struct dirent **namelist = NULL;
	int i, j = 0;
	pid_t pid, prev_pid = INT_MAX;
	char *end_ptr;
	struct str_node *pos;
	struct strlist_config slist_config = { .dont_dupstr = true, };
	struct strlist *slist = strlist__new(pid_str, &slist_config);

	if (!slist)
		return NULL;

	strlist__for_each_entry(pos, slist) {
		pid = strtol(pos->s, &end_ptr, 10);

		if (pid == INT_MIN || pid == INT_MAX ||
		    (*end_ptr != '\0' && *end_ptr != ','))
			goto out_free_threads;

		if (pid == prev_pid)
			continue;

		sprintf(name, "/proc/%d/task", pid);
		items = scandir(name, &namelist, filter, NULL);
		if (items <= 0)
			goto out_free_threads;

		total_tasks += items;
		nt = thread_map__realloc(threads, total_tasks);
		if (nt == NULL)
			goto out_free_namelist;

		threads = nt;

		for (i = 0; i < items; i++) {
			thread_map__set_pid(threads, j++, atoi(namelist[i]->d_name));
			zfree(&namelist[i]);
		}
		threads->nr = total_tasks;
		free(namelist);
	}

out:
	strlist__delete(slist);
	if (threads)
		atomic_set(&threads->refcnt, 1);
	return threads;

out_free_namelist:
	for (i = 0; i < items; i++)
		zfree(&namelist[i]);
	free(namelist);

out_free_threads:
	zfree(&threads);
	goto out;
}
int test__syscall_openat_tp_fields(int subtest __maybe_unused)
{
	struct record_opts opts = {
		.target = {
			.uid = UINT_MAX,
			.uses_mmap = true,
		},
		.no_buffering = true,
		.freq	      = 1,
		.mmap_pages   = 256,
		.raw_samples  = true,
	};
	const char *filename = "/etc/passwd";
	int flags = O_RDONLY | O_DIRECTORY;
	struct perf_evlist *evlist = perf_evlist__new();
	struct perf_evsel *evsel;
	int err = -1, i, nr_events = 0, nr_polls = 0;
	char sbuf[STRERR_BUFSIZE];

	if (evlist == NULL) {
		pr_debug("%s: perf_evlist__new\n", __func__);
		goto out;
	}

	evsel = perf_evsel__newtp("syscalls", "sys_enter_openat");
	if (IS_ERR(evsel)) {
		pr_debug("%s: perf_evsel__newtp\n", __func__);
		goto out_delete_evlist;
	}

	perf_evlist__add(evlist, evsel);

	err = perf_evlist__create_maps(evlist, &opts.target);
	if (err < 0) {
		pr_debug("%s: perf_evlist__create_maps\n", __func__);
		goto out_delete_evlist;
	}

	perf_evsel__config(evsel, &opts);

	thread_map__set_pid(evlist->threads, 0, getpid());

	err = perf_evlist__open(evlist);
	if (err < 0) {
		pr_debug("perf_evlist__open: %s\n",
			 strerror_r(errno, sbuf, sizeof(sbuf)));
		goto out_delete_evlist;
	}

	err = perf_evlist__mmap(evlist, UINT_MAX, false);
	if (err < 0) {
		pr_debug("perf_evlist__mmap: %s\n",
			 strerror_r(errno, sbuf, sizeof(sbuf)));
		goto out_delete_evlist;
	}

	perf_evlist__enable(evlist);

	/*
	 * Generate the event:
	 */
	openat(AT_FDCWD, filename, flags);

	while (1) {
		int before = nr_events;

		for (i = 0; i < evlist->nr_mmaps; i++) {
			union perf_event *event;

			while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
				const u32 type = event->header.type;
				int tp_flags;
				struct perf_sample sample;

				++nr_events;

				if (type != PERF_RECORD_SAMPLE) {
					perf_evlist__mmap_consume(evlist, i);
					continue;
				}

				err = perf_evsel__parse_sample(evsel, event, &sample);
				if (err) {
					pr_debug("Can't parse sample, err = %d\n", err);
					goto out_delete_evlist;
				}

				tp_flags = perf_evsel__intval(evsel, &sample, "flags");

				if (flags != tp_flags) {
					pr_debug("%s: Expected flags=%#x, got %#x\n",
						 __func__, flags, tp_flags);
					goto out_delete_evlist;
				}

				goto out_ok;
			}
		}

		if (nr_events == before)
			perf_evlist__poll(evlist, 10);

		if (++nr_polls > 5) {
			pr_debug("%s: no events!\n", __func__);
			goto out_delete_evlist;
		}
	}
out_ok:
	err = 0;
out_delete_evlist:
	perf_evlist__delete(evlist);
out:
	return err;
}