xref: /linux/tools/perf/util/thread_map.c (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2fd78260bSArnaldo Carvalho de Melo #include <dirent.h>
3a43783aeSArnaldo Carvalho de Melo #include <errno.h>
40d37aa34SArnaldo Carvalho de Melo #include <limits.h>
50d37aa34SArnaldo Carvalho de Melo #include <stdbool.h>
6fd78260bSArnaldo Carvalho de Melo #include <stdlib.h>
7fd78260bSArnaldo Carvalho de Melo #include <stdio.h>
80d37aa34SArnaldo Carvalho de Melo #include <sys/types.h>
90d37aa34SArnaldo Carvalho de Melo #include <sys/stat.h>
100d37aa34SArnaldo Carvalho de Melo #include <unistd.h>
11a067558eSArnaldo Carvalho de Melo #include "string2.h"
12b52956c9SDavid Ahern #include "strlist.h"
13b52956c9SDavid Ahern #include <string.h>
14792402fdSJiri Olsa #include <api/fs/fs.h>
1513c230abSArnaldo Carvalho de Melo #include <linux/string.h>
167f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h>
17186fbb74SJiri Olsa #include "asm/bug.h"
18fd78260bSArnaldo Carvalho de Melo #include "thread_map.h"
19792402fdSJiri Olsa #include "debug.h"
2059660942SJiri Olsa #include "event.h"
21fd3f518fSIan Rogers #include <internal/threadmap.h>
22fd78260bSArnaldo Carvalho de Melo 
23fd78260bSArnaldo Carvalho de Melo /* Skip "." and ".." directories */
filter(const struct dirent * dir)24fd78260bSArnaldo Carvalho de Melo static int filter(const struct dirent *dir)
25fd78260bSArnaldo Carvalho de Melo {
26fd78260bSArnaldo Carvalho de Melo 	if (dir->d_name[0] == '.')
27fd78260bSArnaldo Carvalho de Melo 		return 0;
28fd78260bSArnaldo Carvalho de Melo 	else
29fd78260bSArnaldo Carvalho de Melo 		return 1;
30fd78260bSArnaldo Carvalho de Melo }
31fd78260bSArnaldo Carvalho de Melo 
324b49cce2SJiri Olsa #define thread_map__alloc(__nr) perf_thread_map__realloc(NULL, __nr)
339d7e8c3aSJiri Olsa 
thread_map__new_by_pid(pid_t pid)349749b90eSJiri Olsa struct perf_thread_map *thread_map__new_by_pid(pid_t pid)
35fd78260bSArnaldo Carvalho de Melo {
369749b90eSJiri Olsa 	struct perf_thread_map *threads;
37fd78260bSArnaldo Carvalho de Melo 	char name[256];
38fd78260bSArnaldo Carvalho de Melo 	int items;
39fd78260bSArnaldo Carvalho de Melo 	struct dirent **namelist = NULL;
40fd78260bSArnaldo Carvalho de Melo 	int i;
41fd78260bSArnaldo Carvalho de Melo 
42fd78260bSArnaldo Carvalho de Melo 	sprintf(name, "/proc/%d/task", pid);
43fd78260bSArnaldo Carvalho de Melo 	items = scandir(name, &namelist, filter, NULL);
44fd78260bSArnaldo Carvalho de Melo 	if (items <= 0)
45fd78260bSArnaldo Carvalho de Melo 		return NULL;
46fd78260bSArnaldo Carvalho de Melo 
479d7e8c3aSJiri Olsa 	threads = thread_map__alloc(items);
48fd78260bSArnaldo Carvalho de Melo 	if (threads != NULL) {
49fd78260bSArnaldo Carvalho de Melo 		for (i = 0; i < items; i++)
504b49cce2SJiri Olsa 			perf_thread_map__set_pid(threads, i, atoi(namelist[i]->d_name));
51fd78260bSArnaldo Carvalho de Melo 		threads->nr = items;
52364fed35SElena Reshetova 		refcount_set(&threads->refcnt, 1);
53fd78260bSArnaldo Carvalho de Melo 	}
54fd78260bSArnaldo Carvalho de Melo 
55fd78260bSArnaldo Carvalho de Melo 	for (i=0; i<items; i++)
5674cf249dSArnaldo Carvalho de Melo 		zfree(&namelist[i]);
57fd78260bSArnaldo Carvalho de Melo 	free(namelist);
58fd78260bSArnaldo Carvalho de Melo 
59fd78260bSArnaldo Carvalho de Melo 	return threads;
60fd78260bSArnaldo Carvalho de Melo }
61fd78260bSArnaldo Carvalho de Melo 
thread_map__new_by_tid(pid_t tid)629749b90eSJiri Olsa struct perf_thread_map *thread_map__new_by_tid(pid_t tid)
63fd78260bSArnaldo Carvalho de Melo {
649749b90eSJiri Olsa 	struct perf_thread_map *threads = thread_map__alloc(1);
65fd78260bSArnaldo Carvalho de Melo 
66fd78260bSArnaldo Carvalho de Melo 	if (threads != NULL) {
674b49cce2SJiri Olsa 		perf_thread_map__set_pid(threads, 0, tid);
68fd78260bSArnaldo Carvalho de Melo 		threads->nr = 1;
69364fed35SElena Reshetova 		refcount_set(&threads->refcnt, 1);
70fd78260bSArnaldo Carvalho de Melo 	}
71fd78260bSArnaldo Carvalho de Melo 
72fd78260bSArnaldo Carvalho de Melo 	return threads;
73fd78260bSArnaldo Carvalho de Melo }
74fd78260bSArnaldo Carvalho de Melo 
__thread_map__new_all_cpus(uid_t uid)759749b90eSJiri Olsa static struct perf_thread_map *__thread_map__new_all_cpus(uid_t uid)
760d37aa34SArnaldo Carvalho de Melo {
770d37aa34SArnaldo Carvalho de Melo 	DIR *proc;
780d37aa34SArnaldo Carvalho de Melo 	int max_threads = 32, items, i;
79bdf23a9aSArnaldo Carvalho de Melo 	char path[NAME_MAX + 1 + 6];
803354cf71SArnaldo Carvalho de Melo 	struct dirent *dirent, **namelist = NULL;
819749b90eSJiri Olsa 	struct perf_thread_map *threads = thread_map__alloc(max_threads);
829d7e8c3aSJiri Olsa 
830d37aa34SArnaldo Carvalho de Melo 	if (threads == NULL)
840d37aa34SArnaldo Carvalho de Melo 		goto out;
850d37aa34SArnaldo Carvalho de Melo 
860d37aa34SArnaldo Carvalho de Melo 	proc = opendir("/proc");
870d37aa34SArnaldo Carvalho de Melo 	if (proc == NULL)
880d37aa34SArnaldo Carvalho de Melo 		goto out_free_threads;
890d37aa34SArnaldo Carvalho de Melo 
900d37aa34SArnaldo Carvalho de Melo 	threads->nr = 0;
91364fed35SElena Reshetova 	refcount_set(&threads->refcnt, 1);
920d37aa34SArnaldo Carvalho de Melo 
933354cf71SArnaldo Carvalho de Melo 	while ((dirent = readdir(proc)) != NULL) {
940d37aa34SArnaldo Carvalho de Melo 		char *end;
950d37aa34SArnaldo Carvalho de Melo 		bool grow = false;
963354cf71SArnaldo Carvalho de Melo 		pid_t pid = strtol(dirent->d_name, &end, 10);
970d37aa34SArnaldo Carvalho de Melo 
980d37aa34SArnaldo Carvalho de Melo 		if (*end) /* only interested in proper numerical dirents */
990d37aa34SArnaldo Carvalho de Melo 			continue;
1000d37aa34SArnaldo Carvalho de Melo 
1013354cf71SArnaldo Carvalho de Melo 		snprintf(path, sizeof(path), "/proc/%s", dirent->d_name);
1020d37aa34SArnaldo Carvalho de Melo 
1038d3cd4c3SArnaldo Carvalho de Melo 		if (uid != UINT_MAX) {
1048d3cd4c3SArnaldo Carvalho de Melo 			struct stat st;
1050d37aa34SArnaldo Carvalho de Melo 
1068d3cd4c3SArnaldo Carvalho de Melo 			if (stat(path, &st) != 0 || st.st_uid != uid)
1070d37aa34SArnaldo Carvalho de Melo 				continue;
1088d3cd4c3SArnaldo Carvalho de Melo 		}
1090d37aa34SArnaldo Carvalho de Melo 
1100d37aa34SArnaldo Carvalho de Melo 		snprintf(path, sizeof(path), "/proc/%d/task", pid);
1110d37aa34SArnaldo Carvalho de Melo 		items = scandir(path, &namelist, filter, NULL);
112*510e5287SIan Rogers 		if (items <= 0) {
113*510e5287SIan Rogers 			pr_debug("scandir for %d returned empty, skipping\n", pid);
114*510e5287SIan Rogers 			continue;
115*510e5287SIan Rogers 		}
1160d37aa34SArnaldo Carvalho de Melo 		while (threads->nr + items >= max_threads) {
1170d37aa34SArnaldo Carvalho de Melo 			max_threads *= 2;
1180d37aa34SArnaldo Carvalho de Melo 			grow = true;
1190d37aa34SArnaldo Carvalho de Melo 		}
1200d37aa34SArnaldo Carvalho de Melo 
1210d37aa34SArnaldo Carvalho de Melo 		if (grow) {
1229749b90eSJiri Olsa 			struct perf_thread_map *tmp;
1230d37aa34SArnaldo Carvalho de Melo 
1244b49cce2SJiri Olsa 			tmp = perf_thread_map__realloc(threads, max_threads);
1250d37aa34SArnaldo Carvalho de Melo 			if (tmp == NULL)
1260d37aa34SArnaldo Carvalho de Melo 				goto out_free_namelist;
1270d37aa34SArnaldo Carvalho de Melo 
1280d37aa34SArnaldo Carvalho de Melo 			threads = tmp;
1290d37aa34SArnaldo Carvalho de Melo 		}
1300d37aa34SArnaldo Carvalho de Melo 
131e13798c7SJiri Olsa 		for (i = 0; i < items; i++) {
1324b49cce2SJiri Olsa 			perf_thread_map__set_pid(threads, threads->nr + i,
133e13798c7SJiri Olsa 						    atoi(namelist[i]->d_name));
134e13798c7SJiri Olsa 		}
1350d37aa34SArnaldo Carvalho de Melo 
1360d37aa34SArnaldo Carvalho de Melo 		for (i = 0; i < items; i++)
13774cf249dSArnaldo Carvalho de Melo 			zfree(&namelist[i]);
1380d37aa34SArnaldo Carvalho de Melo 		free(namelist);
1390d37aa34SArnaldo Carvalho de Melo 
1400d37aa34SArnaldo Carvalho de Melo 		threads->nr += items;
1410d37aa34SArnaldo Carvalho de Melo 	}
1420d37aa34SArnaldo Carvalho de Melo 
1430d37aa34SArnaldo Carvalho de Melo out_closedir:
1440d37aa34SArnaldo Carvalho de Melo 	closedir(proc);
1450d37aa34SArnaldo Carvalho de Melo out:
1460d37aa34SArnaldo Carvalho de Melo 	return threads;
1470d37aa34SArnaldo Carvalho de Melo 
1480d37aa34SArnaldo Carvalho de Melo out_free_threads:
1490d37aa34SArnaldo Carvalho de Melo 	free(threads);
1500d37aa34SArnaldo Carvalho de Melo 	return NULL;
1510d37aa34SArnaldo Carvalho de Melo 
1520d37aa34SArnaldo Carvalho de Melo out_free_namelist:
1530d37aa34SArnaldo Carvalho de Melo 	for (i = 0; i < items; i++)
15474cf249dSArnaldo Carvalho de Melo 		zfree(&namelist[i]);
1550d37aa34SArnaldo Carvalho de Melo 	free(namelist);
15604662523SArnaldo Carvalho de Melo 	zfree(&threads);
1570d37aa34SArnaldo Carvalho de Melo 	goto out_closedir;
1580d37aa34SArnaldo Carvalho de Melo }
1590d37aa34SArnaldo Carvalho de Melo 
thread_map__new_all_cpus(void)1609749b90eSJiri Olsa struct perf_thread_map *thread_map__new_all_cpus(void)
1618d3cd4c3SArnaldo Carvalho de Melo {
1628d3cd4c3SArnaldo Carvalho de Melo 	return __thread_map__new_all_cpus(UINT_MAX);
1638d3cd4c3SArnaldo Carvalho de Melo }
1648d3cd4c3SArnaldo Carvalho de Melo 
thread_map__new_by_uid(uid_t uid)1659749b90eSJiri Olsa struct perf_thread_map *thread_map__new_by_uid(uid_t uid)
1668d3cd4c3SArnaldo Carvalho de Melo {
1678d3cd4c3SArnaldo Carvalho de Melo 	return __thread_map__new_all_cpus(uid);
1688d3cd4c3SArnaldo Carvalho de Melo }
1698d3cd4c3SArnaldo Carvalho de Melo 
thread_map__new(pid_t pid,pid_t tid,uid_t uid)1709749b90eSJiri Olsa struct perf_thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid)
171fd78260bSArnaldo Carvalho de Melo {
172fd78260bSArnaldo Carvalho de Melo 	if (pid != -1)
173fd78260bSArnaldo Carvalho de Melo 		return thread_map__new_by_pid(pid);
1740d37aa34SArnaldo Carvalho de Melo 
1750d37aa34SArnaldo Carvalho de Melo 	if (tid == -1 && uid != UINT_MAX)
1760d37aa34SArnaldo Carvalho de Melo 		return thread_map__new_by_uid(uid);
1770d37aa34SArnaldo Carvalho de Melo 
178fd78260bSArnaldo Carvalho de Melo 	return thread_map__new_by_tid(tid);
179fd78260bSArnaldo Carvalho de Melo }
180fd78260bSArnaldo Carvalho de Melo 
thread_map__new_by_pid_str(const char * pid_str)1819749b90eSJiri Olsa static struct perf_thread_map *thread_map__new_by_pid_str(const char *pid_str)
182b52956c9SDavid Ahern {
1839749b90eSJiri Olsa 	struct perf_thread_map *threads = NULL, *nt;
184b52956c9SDavid Ahern 	char name[256];
185b52956c9SDavid Ahern 	int items, total_tasks = 0;
186b52956c9SDavid Ahern 	struct dirent **namelist = NULL;
187b52956c9SDavid Ahern 	int i, j = 0;
188b52956c9SDavid Ahern 	pid_t pid, prev_pid = INT_MAX;
189b52956c9SDavid Ahern 	char *end_ptr;
190b52956c9SDavid Ahern 	struct str_node *pos;
1914a77e218SArnaldo Carvalho de Melo 	struct strlist_config slist_config = { .dont_dupstr = true, };
1924a77e218SArnaldo Carvalho de Melo 	struct strlist *slist = strlist__new(pid_str, &slist_config);
193b52956c9SDavid Ahern 
194b52956c9SDavid Ahern 	if (!slist)
195b52956c9SDavid Ahern 		return NULL;
196b52956c9SDavid Ahern 
197602a1f4dSArnaldo Carvalho de Melo 	strlist__for_each_entry(pos, slist) {
198b52956c9SDavid Ahern 		pid = strtol(pos->s, &end_ptr, 10);
199b52956c9SDavid Ahern 
200b52956c9SDavid Ahern 		if (pid == INT_MIN || pid == INT_MAX ||
201b52956c9SDavid Ahern 		    (*end_ptr != '\0' && *end_ptr != ','))
202b52956c9SDavid Ahern 			goto out_free_threads;
203b52956c9SDavid Ahern 
204b52956c9SDavid Ahern 		if (pid == prev_pid)
205b52956c9SDavid Ahern 			continue;
206b52956c9SDavid Ahern 
207b52956c9SDavid Ahern 		sprintf(name, "/proc/%d/task", pid);
208b52956c9SDavid Ahern 		items = scandir(name, &namelist, filter, NULL);
209b52956c9SDavid Ahern 		if (items <= 0)
210b52956c9SDavid Ahern 			goto out_free_threads;
211b52956c9SDavid Ahern 
212b52956c9SDavid Ahern 		total_tasks += items;
2134b49cce2SJiri Olsa 		nt = perf_thread_map__realloc(threads, total_tasks);
214b52956c9SDavid Ahern 		if (nt == NULL)
215e8cdd947SFranck Bui-Huu 			goto out_free_namelist;
216b52956c9SDavid Ahern 
217b52956c9SDavid Ahern 		threads = nt;
218b52956c9SDavid Ahern 
219e8cdd947SFranck Bui-Huu 		for (i = 0; i < items; i++) {
2204b49cce2SJiri Olsa 			perf_thread_map__set_pid(threads, j++, atoi(namelist[i]->d_name));
22174cf249dSArnaldo Carvalho de Melo 			zfree(&namelist[i]);
222e8cdd947SFranck Bui-Huu 		}
223e8cdd947SFranck Bui-Huu 		threads->nr = total_tasks;
224b52956c9SDavid Ahern 		free(namelist);
225b52956c9SDavid Ahern 	}
226b52956c9SDavid Ahern 
227b52956c9SDavid Ahern out:
228b52956c9SDavid Ahern 	strlist__delete(slist);
229186fbb74SJiri Olsa 	if (threads)
230364fed35SElena Reshetova 		refcount_set(&threads->refcnt, 1);
231b52956c9SDavid Ahern 	return threads;
232b52956c9SDavid Ahern 
233e8cdd947SFranck Bui-Huu out_free_namelist:
234e8cdd947SFranck Bui-Huu 	for (i = 0; i < items; i++)
23574cf249dSArnaldo Carvalho de Melo 		zfree(&namelist[i]);
236e8cdd947SFranck Bui-Huu 	free(namelist);
237e8cdd947SFranck Bui-Huu 
238b52956c9SDavid Ahern out_free_threads:
23904662523SArnaldo Carvalho de Melo 	zfree(&threads);
240b52956c9SDavid Ahern 	goto out;
241b52956c9SDavid Ahern }
242b52956c9SDavid Ahern 
thread_map__new_by_tid_str(const char * tid_str)2439749b90eSJiri Olsa struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str)
244b52956c9SDavid Ahern {
2459749b90eSJiri Olsa 	struct perf_thread_map *threads = NULL, *nt;
246b52956c9SDavid Ahern 	int ntasks = 0;
247b52956c9SDavid Ahern 	pid_t tid, prev_tid = INT_MAX;
248b52956c9SDavid Ahern 	char *end_ptr;
249b52956c9SDavid Ahern 	struct str_node *pos;
2504a77e218SArnaldo Carvalho de Melo 	struct strlist_config slist_config = { .dont_dupstr = true, };
251b52956c9SDavid Ahern 	struct strlist *slist;
252b52956c9SDavid Ahern 
253b52956c9SDavid Ahern 	/* perf-stat expects threads to be generated even if tid not given */
254641556c9SArnaldo Carvalho de Melo 	if (!tid_str)
2554b49cce2SJiri Olsa 		return perf_thread_map__new_dummy();
256b52956c9SDavid Ahern 
2574a77e218SArnaldo Carvalho de Melo 	slist = strlist__new(tid_str, &slist_config);
258b52956c9SDavid Ahern 	if (!slist)
259b52956c9SDavid Ahern 		return NULL;
260b52956c9SDavid Ahern 
261602a1f4dSArnaldo Carvalho de Melo 	strlist__for_each_entry(pos, slist) {
262b52956c9SDavid Ahern 		tid = strtol(pos->s, &end_ptr, 10);
263b52956c9SDavid Ahern 
264b52956c9SDavid Ahern 		if (tid == INT_MIN || tid == INT_MAX ||
265b52956c9SDavid Ahern 		    (*end_ptr != '\0' && *end_ptr != ','))
266b52956c9SDavid Ahern 			goto out_free_threads;
267b52956c9SDavid Ahern 
268b52956c9SDavid Ahern 		if (tid == prev_tid)
269b52956c9SDavid Ahern 			continue;
270b52956c9SDavid Ahern 
271b52956c9SDavid Ahern 		ntasks++;
2724b49cce2SJiri Olsa 		nt = perf_thread_map__realloc(threads, ntasks);
273b52956c9SDavid Ahern 
274b52956c9SDavid Ahern 		if (nt == NULL)
275b52956c9SDavid Ahern 			goto out_free_threads;
276b52956c9SDavid Ahern 
277b52956c9SDavid Ahern 		threads = nt;
2784b49cce2SJiri Olsa 		perf_thread_map__set_pid(threads, ntasks - 1, tid);
279b52956c9SDavid Ahern 		threads->nr = ntasks;
280b52956c9SDavid Ahern 	}
281b52956c9SDavid Ahern out:
2821eb3d924SYang Jihong 	strlist__delete(slist);
283186fbb74SJiri Olsa 	if (threads)
284364fed35SElena Reshetova 		refcount_set(&threads->refcnt, 1);
285b52956c9SDavid Ahern 	return threads;
286b52956c9SDavid Ahern 
287b52956c9SDavid Ahern out_free_threads:
28804662523SArnaldo Carvalho de Melo 	zfree(&threads);
289b52956c9SDavid Ahern 	goto out;
290b52956c9SDavid Ahern }
291b52956c9SDavid Ahern 
thread_map__new_str(const char * pid,const char * tid,uid_t uid,bool all_threads)2929749b90eSJiri Olsa struct perf_thread_map *thread_map__new_str(const char *pid, const char *tid,
293147c508fSJin Yao 				       uid_t uid, bool all_threads)
294b52956c9SDavid Ahern {
295b52956c9SDavid Ahern 	if (pid)
296b52956c9SDavid Ahern 		return thread_map__new_by_pid_str(pid);
297b52956c9SDavid Ahern 
298b52956c9SDavid Ahern 	if (!tid && uid != UINT_MAX)
299b52956c9SDavid Ahern 		return thread_map__new_by_uid(uid);
300b52956c9SDavid Ahern 
301147c508fSJin Yao 	if (all_threads)
30273c0ca1eSJin Yao 		return thread_map__new_all_cpus();
30373c0ca1eSJin Yao 
304b52956c9SDavid Ahern 	return thread_map__new_by_tid_str(tid);
305b52956c9SDavid Ahern }
306b52956c9SDavid Ahern 
thread_map__fprintf(struct perf_thread_map * threads,FILE * fp)3079749b90eSJiri Olsa size_t thread_map__fprintf(struct perf_thread_map *threads, FILE *fp)
3089ae7d335SArnaldo Carvalho de Melo {
3099ae7d335SArnaldo Carvalho de Melo 	int i;
3109ae7d335SArnaldo Carvalho de Melo 	size_t printed = fprintf(fp, "%d thread%s: ",
3119ae7d335SArnaldo Carvalho de Melo 				 threads->nr, threads->nr > 1 ? "s" : "");
3129ae7d335SArnaldo Carvalho de Melo 	for (i = 0; i < threads->nr; ++i)
313a2f354e3SJiri Olsa 		printed += fprintf(fp, "%s%d", i ? ", " : "", perf_thread_map__pid(threads, i));
3149ae7d335SArnaldo Carvalho de Melo 
3159ae7d335SArnaldo Carvalho de Melo 	return printed + fprintf(fp, "\n");
3169ae7d335SArnaldo Carvalho de Melo }
317792402fdSJiri Olsa 
get_comm(char ** comm,pid_t pid)318792402fdSJiri Olsa static int get_comm(char **comm, pid_t pid)
319792402fdSJiri Olsa {
320792402fdSJiri Olsa 	char *path;
321792402fdSJiri Olsa 	size_t size;
322792402fdSJiri Olsa 	int err;
323792402fdSJiri Olsa 
324792402fdSJiri Olsa 	if (asprintf(&path, "%s/%d/comm", procfs__mountpoint(), pid) == -1)
325792402fdSJiri Olsa 		return -ENOMEM;
326792402fdSJiri Olsa 
327792402fdSJiri Olsa 	err = filename__read_str(path, comm, &size);
328792402fdSJiri Olsa 	if (!err) {
329792402fdSJiri Olsa 		/*
330792402fdSJiri Olsa 		 * We're reading 16 bytes, while filename__read_str
331792402fdSJiri Olsa 		 * allocates data per BUFSIZ bytes, so we can safely
332792402fdSJiri Olsa 		 * mark the end of the string.
333792402fdSJiri Olsa 		 */
334792402fdSJiri Olsa 		(*comm)[size] = 0;
33513c230abSArnaldo Carvalho de Melo 		strim(*comm);
336792402fdSJiri Olsa 	}
337792402fdSJiri Olsa 
338792402fdSJiri Olsa 	free(path);
339792402fdSJiri Olsa 	return err;
340792402fdSJiri Olsa }
341792402fdSJiri Olsa 
comm_init(struct perf_thread_map * map,int i)3429749b90eSJiri Olsa static void comm_init(struct perf_thread_map *map, int i)
343792402fdSJiri Olsa {
344a2f354e3SJiri Olsa 	pid_t pid = perf_thread_map__pid(map, i);
345792402fdSJiri Olsa 	char *comm = NULL;
346792402fdSJiri Olsa 
347792402fdSJiri Olsa 	/* dummy pid comm initialization */
348792402fdSJiri Olsa 	if (pid == -1) {
349792402fdSJiri Olsa 		map->map[i].comm = strdup("dummy");
350792402fdSJiri Olsa 		return;
351792402fdSJiri Olsa 	}
352792402fdSJiri Olsa 
353792402fdSJiri Olsa 	/*
354792402fdSJiri Olsa 	 * The comm name is like extra bonus ;-),
355792402fdSJiri Olsa 	 * so just warn if we fail for any reason.
356792402fdSJiri Olsa 	 */
357792402fdSJiri Olsa 	if (get_comm(&comm, pid))
358792402fdSJiri Olsa 		pr_warning("Couldn't resolve comm name for pid %d\n", pid);
359792402fdSJiri Olsa 
360792402fdSJiri Olsa 	map->map[i].comm = comm;
361792402fdSJiri Olsa }
362792402fdSJiri Olsa 
thread_map__read_comms(struct perf_thread_map * threads)3639749b90eSJiri Olsa void thread_map__read_comms(struct perf_thread_map *threads)
364792402fdSJiri Olsa {
365792402fdSJiri Olsa 	int i;
366792402fdSJiri Olsa 
367792402fdSJiri Olsa 	for (i = 0; i < threads->nr; ++i)
368792402fdSJiri Olsa 		comm_init(threads, i);
369792402fdSJiri Olsa }
37059660942SJiri Olsa 
thread_map__copy_event(struct perf_thread_map * threads,struct perf_record_thread_map * event)3719749b90eSJiri Olsa static void thread_map__copy_event(struct perf_thread_map *threads,
37272932371SJiri Olsa 				   struct perf_record_thread_map *event)
37359660942SJiri Olsa {
37459660942SJiri Olsa 	unsigned i;
37559660942SJiri Olsa 
37659660942SJiri Olsa 	threads->nr = (int) event->nr;
37759660942SJiri Olsa 
37859660942SJiri Olsa 	for (i = 0; i < event->nr; i++) {
3794b49cce2SJiri Olsa 		perf_thread_map__set_pid(threads, i, (pid_t) event->entries[i].pid);
38059660942SJiri Olsa 		threads->map[i].comm = strndup(event->entries[i].comm, 16);
38159660942SJiri Olsa 	}
38259660942SJiri Olsa 
383364fed35SElena Reshetova 	refcount_set(&threads->refcnt, 1);
38459660942SJiri Olsa }
38559660942SJiri Olsa 
thread_map__new_event(struct perf_record_thread_map * event)38672932371SJiri Olsa struct perf_thread_map *thread_map__new_event(struct perf_record_thread_map *event)
38759660942SJiri Olsa {
3889749b90eSJiri Olsa 	struct perf_thread_map *threads;
38959660942SJiri Olsa 
39059660942SJiri Olsa 	threads = thread_map__alloc(event->nr);
39159660942SJiri Olsa 	if (threads)
39259660942SJiri Olsa 		thread_map__copy_event(threads, event);
39359660942SJiri Olsa 
39459660942SJiri Olsa 	return threads;
39559660942SJiri Olsa }
3963407df8bSJiri Olsa 
thread_map__has(struct perf_thread_map * threads,pid_t pid)3979749b90eSJiri Olsa bool thread_map__has(struct perf_thread_map *threads, pid_t pid)
3983407df8bSJiri Olsa {
3993407df8bSJiri Olsa 	int i;
4003407df8bSJiri Olsa 
4013407df8bSJiri Olsa 	for (i = 0; i < threads->nr; ++i) {
4023407df8bSJiri Olsa 		if (threads->map[i].pid == pid)
4033407df8bSJiri Olsa 			return true;
4043407df8bSJiri Olsa 	}
4053407df8bSJiri Olsa 
4063407df8bSJiri Olsa 	return false;
4073407df8bSJiri Olsa }
40838af91f0SJiri Olsa 
thread_map__remove(struct perf_thread_map * threads,int idx)4099749b90eSJiri Olsa int thread_map__remove(struct perf_thread_map *threads, int idx)
41038af91f0SJiri Olsa {
41138af91f0SJiri Olsa 	int i;
41238af91f0SJiri Olsa 
41338af91f0SJiri Olsa 	if (threads->nr < 1)
41438af91f0SJiri Olsa 		return -EINVAL;
41538af91f0SJiri Olsa 
41638af91f0SJiri Olsa 	if (idx >= threads->nr)
41738af91f0SJiri Olsa 		return -EINVAL;
41838af91f0SJiri Olsa 
41938af91f0SJiri Olsa 	/*
42038af91f0SJiri Olsa 	 * Free the 'idx' item and shift the rest up.
42138af91f0SJiri Olsa 	 */
422d8f9da24SArnaldo Carvalho de Melo 	zfree(&threads->map[idx].comm);
42338af91f0SJiri Olsa 
42438af91f0SJiri Olsa 	for (i = idx; i < threads->nr - 1; i++)
42538af91f0SJiri Olsa 		threads->map[i] = threads->map[i + 1];
42638af91f0SJiri Olsa 
42738af91f0SJiri Olsa 	threads->nr--;
42838af91f0SJiri Olsa 	return 0;
42938af91f0SJiri Olsa }
430