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