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" 21*fd3f518fSIan Rogers #include <internal/threadmap.h> 22fd78260bSArnaldo Carvalho de Melo 23fd78260bSArnaldo Carvalho de Melo /* Skip "." and ".." directories */ 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 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 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 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); 1120d37aa34SArnaldo Carvalho de Melo if (items <= 0) 1130d37aa34SArnaldo Carvalho de Melo goto out_free_closedir; 1140d37aa34SArnaldo Carvalho de Melo 1150d37aa34SArnaldo Carvalho de Melo while (threads->nr + items >= max_threads) { 1160d37aa34SArnaldo Carvalho de Melo max_threads *= 2; 1170d37aa34SArnaldo Carvalho de Melo grow = true; 1180d37aa34SArnaldo Carvalho de Melo } 1190d37aa34SArnaldo Carvalho de Melo 1200d37aa34SArnaldo Carvalho de Melo if (grow) { 1219749b90eSJiri Olsa struct perf_thread_map *tmp; 1220d37aa34SArnaldo Carvalho de Melo 1234b49cce2SJiri Olsa tmp = perf_thread_map__realloc(threads, max_threads); 1240d37aa34SArnaldo Carvalho de Melo if (tmp == NULL) 1250d37aa34SArnaldo Carvalho de Melo goto out_free_namelist; 1260d37aa34SArnaldo Carvalho de Melo 1270d37aa34SArnaldo Carvalho de Melo threads = tmp; 1280d37aa34SArnaldo Carvalho de Melo } 1290d37aa34SArnaldo Carvalho de Melo 130e13798c7SJiri Olsa for (i = 0; i < items; i++) { 1314b49cce2SJiri Olsa perf_thread_map__set_pid(threads, threads->nr + i, 132e13798c7SJiri Olsa atoi(namelist[i]->d_name)); 133e13798c7SJiri Olsa } 1340d37aa34SArnaldo Carvalho de Melo 1350d37aa34SArnaldo Carvalho de Melo for (i = 0; i < items; i++) 13674cf249dSArnaldo Carvalho de Melo zfree(&namelist[i]); 1370d37aa34SArnaldo Carvalho de Melo free(namelist); 1380d37aa34SArnaldo Carvalho de Melo 1390d37aa34SArnaldo Carvalho de Melo threads->nr += items; 1400d37aa34SArnaldo Carvalho de Melo } 1410d37aa34SArnaldo Carvalho de Melo 1420d37aa34SArnaldo Carvalho de Melo out_closedir: 1430d37aa34SArnaldo Carvalho de Melo closedir(proc); 1440d37aa34SArnaldo Carvalho de Melo out: 1450d37aa34SArnaldo Carvalho de Melo return threads; 1460d37aa34SArnaldo Carvalho de Melo 1470d37aa34SArnaldo Carvalho de Melo out_free_threads: 1480d37aa34SArnaldo Carvalho de Melo free(threads); 1490d37aa34SArnaldo Carvalho de Melo return NULL; 1500d37aa34SArnaldo Carvalho de Melo 1510d37aa34SArnaldo Carvalho de Melo out_free_namelist: 1520d37aa34SArnaldo Carvalho de Melo for (i = 0; i < items; i++) 15374cf249dSArnaldo Carvalho de Melo zfree(&namelist[i]); 1540d37aa34SArnaldo Carvalho de Melo free(namelist); 1550d37aa34SArnaldo Carvalho de Melo 1560d37aa34SArnaldo Carvalho de Melo out_free_closedir: 15704662523SArnaldo Carvalho de Melo zfree(&threads); 1580d37aa34SArnaldo Carvalho de Melo goto out_closedir; 1590d37aa34SArnaldo Carvalho de Melo } 1600d37aa34SArnaldo Carvalho de Melo 1619749b90eSJiri Olsa struct perf_thread_map *thread_map__new_all_cpus(void) 1628d3cd4c3SArnaldo Carvalho de Melo { 1638d3cd4c3SArnaldo Carvalho de Melo return __thread_map__new_all_cpus(UINT_MAX); 1648d3cd4c3SArnaldo Carvalho de Melo } 1658d3cd4c3SArnaldo Carvalho de Melo 1669749b90eSJiri Olsa struct perf_thread_map *thread_map__new_by_uid(uid_t uid) 1678d3cd4c3SArnaldo Carvalho de Melo { 1688d3cd4c3SArnaldo Carvalho de Melo return __thread_map__new_all_cpus(uid); 1698d3cd4c3SArnaldo Carvalho de Melo } 1708d3cd4c3SArnaldo Carvalho de Melo 1719749b90eSJiri Olsa struct perf_thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid) 172fd78260bSArnaldo Carvalho de Melo { 173fd78260bSArnaldo Carvalho de Melo if (pid != -1) 174fd78260bSArnaldo Carvalho de Melo return thread_map__new_by_pid(pid); 1750d37aa34SArnaldo Carvalho de Melo 1760d37aa34SArnaldo Carvalho de Melo if (tid == -1 && uid != UINT_MAX) 1770d37aa34SArnaldo Carvalho de Melo return thread_map__new_by_uid(uid); 1780d37aa34SArnaldo Carvalho de Melo 179fd78260bSArnaldo Carvalho de Melo return thread_map__new_by_tid(tid); 180fd78260bSArnaldo Carvalho de Melo } 181fd78260bSArnaldo Carvalho de Melo 1829749b90eSJiri Olsa static struct perf_thread_map *thread_map__new_by_pid_str(const char *pid_str) 183b52956c9SDavid Ahern { 1849749b90eSJiri Olsa struct perf_thread_map *threads = NULL, *nt; 185b52956c9SDavid Ahern char name[256]; 186b52956c9SDavid Ahern int items, total_tasks = 0; 187b52956c9SDavid Ahern struct dirent **namelist = NULL; 188b52956c9SDavid Ahern int i, j = 0; 189b52956c9SDavid Ahern pid_t pid, prev_pid = INT_MAX; 190b52956c9SDavid Ahern char *end_ptr; 191b52956c9SDavid Ahern struct str_node *pos; 1924a77e218SArnaldo Carvalho de Melo struct strlist_config slist_config = { .dont_dupstr = true, }; 1934a77e218SArnaldo Carvalho de Melo struct strlist *slist = strlist__new(pid_str, &slist_config); 194b52956c9SDavid Ahern 195b52956c9SDavid Ahern if (!slist) 196b52956c9SDavid Ahern return NULL; 197b52956c9SDavid Ahern 198602a1f4dSArnaldo Carvalho de Melo strlist__for_each_entry(pos, slist) { 199b52956c9SDavid Ahern pid = strtol(pos->s, &end_ptr, 10); 200b52956c9SDavid Ahern 201b52956c9SDavid Ahern if (pid == INT_MIN || pid == INT_MAX || 202b52956c9SDavid Ahern (*end_ptr != '\0' && *end_ptr != ',')) 203b52956c9SDavid Ahern goto out_free_threads; 204b52956c9SDavid Ahern 205b52956c9SDavid Ahern if (pid == prev_pid) 206b52956c9SDavid Ahern continue; 207b52956c9SDavid Ahern 208b52956c9SDavid Ahern sprintf(name, "/proc/%d/task", pid); 209b52956c9SDavid Ahern items = scandir(name, &namelist, filter, NULL); 210b52956c9SDavid Ahern if (items <= 0) 211b52956c9SDavid Ahern goto out_free_threads; 212b52956c9SDavid Ahern 213b52956c9SDavid Ahern total_tasks += items; 2144b49cce2SJiri Olsa nt = perf_thread_map__realloc(threads, total_tasks); 215b52956c9SDavid Ahern if (nt == NULL) 216e8cdd947SFranck Bui-Huu goto out_free_namelist; 217b52956c9SDavid Ahern 218b52956c9SDavid Ahern threads = nt; 219b52956c9SDavid Ahern 220e8cdd947SFranck Bui-Huu for (i = 0; i < items; i++) { 2214b49cce2SJiri Olsa perf_thread_map__set_pid(threads, j++, atoi(namelist[i]->d_name)); 22274cf249dSArnaldo Carvalho de Melo zfree(&namelist[i]); 223e8cdd947SFranck Bui-Huu } 224e8cdd947SFranck Bui-Huu threads->nr = total_tasks; 225b52956c9SDavid Ahern free(namelist); 226b52956c9SDavid Ahern } 227b52956c9SDavid Ahern 228b52956c9SDavid Ahern out: 229b52956c9SDavid Ahern strlist__delete(slist); 230186fbb74SJiri Olsa if (threads) 231364fed35SElena Reshetova refcount_set(&threads->refcnt, 1); 232b52956c9SDavid Ahern return threads; 233b52956c9SDavid Ahern 234e8cdd947SFranck Bui-Huu out_free_namelist: 235e8cdd947SFranck Bui-Huu for (i = 0; i < items; i++) 23674cf249dSArnaldo Carvalho de Melo zfree(&namelist[i]); 237e8cdd947SFranck Bui-Huu free(namelist); 238e8cdd947SFranck Bui-Huu 239b52956c9SDavid Ahern out_free_threads: 24004662523SArnaldo Carvalho de Melo zfree(&threads); 241b52956c9SDavid Ahern goto out; 242b52956c9SDavid Ahern } 243b52956c9SDavid Ahern 2449749b90eSJiri Olsa struct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str) 245b52956c9SDavid Ahern { 2469749b90eSJiri Olsa struct perf_thread_map *threads = NULL, *nt; 247b52956c9SDavid Ahern int ntasks = 0; 248b52956c9SDavid Ahern pid_t tid, prev_tid = INT_MAX; 249b52956c9SDavid Ahern char *end_ptr; 250b52956c9SDavid Ahern struct str_node *pos; 2514a77e218SArnaldo Carvalho de Melo struct strlist_config slist_config = { .dont_dupstr = true, }; 252b52956c9SDavid Ahern struct strlist *slist; 253b52956c9SDavid Ahern 254b52956c9SDavid Ahern /* perf-stat expects threads to be generated even if tid not given */ 255641556c9SArnaldo Carvalho de Melo if (!tid_str) 2564b49cce2SJiri Olsa return perf_thread_map__new_dummy(); 257b52956c9SDavid Ahern 2584a77e218SArnaldo Carvalho de Melo slist = strlist__new(tid_str, &slist_config); 259b52956c9SDavid Ahern if (!slist) 260b52956c9SDavid Ahern return NULL; 261b52956c9SDavid Ahern 262602a1f4dSArnaldo Carvalho de Melo strlist__for_each_entry(pos, slist) { 263b52956c9SDavid Ahern tid = strtol(pos->s, &end_ptr, 10); 264b52956c9SDavid Ahern 265b52956c9SDavid Ahern if (tid == INT_MIN || tid == INT_MAX || 266b52956c9SDavid Ahern (*end_ptr != '\0' && *end_ptr != ',')) 267b52956c9SDavid Ahern goto out_free_threads; 268b52956c9SDavid Ahern 269b52956c9SDavid Ahern if (tid == prev_tid) 270b52956c9SDavid Ahern continue; 271b52956c9SDavid Ahern 272b52956c9SDavid Ahern ntasks++; 2734b49cce2SJiri Olsa nt = perf_thread_map__realloc(threads, ntasks); 274b52956c9SDavid Ahern 275b52956c9SDavid Ahern if (nt == NULL) 276b52956c9SDavid Ahern goto out_free_threads; 277b52956c9SDavid Ahern 278b52956c9SDavid Ahern threads = nt; 2794b49cce2SJiri Olsa perf_thread_map__set_pid(threads, ntasks - 1, tid); 280b52956c9SDavid Ahern threads->nr = ntasks; 281b52956c9SDavid Ahern } 282b52956c9SDavid Ahern out: 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); 2897ecb48fdSNamhyung Kim strlist__delete(slist); 290b52956c9SDavid Ahern goto out; 291b52956c9SDavid Ahern } 292b52956c9SDavid Ahern 2939749b90eSJiri Olsa struct perf_thread_map *thread_map__new_str(const char *pid, const char *tid, 294147c508fSJin Yao uid_t uid, bool all_threads) 295b52956c9SDavid Ahern { 296b52956c9SDavid Ahern if (pid) 297b52956c9SDavid Ahern return thread_map__new_by_pid_str(pid); 298b52956c9SDavid Ahern 299b52956c9SDavid Ahern if (!tid && uid != UINT_MAX) 300b52956c9SDavid Ahern return thread_map__new_by_uid(uid); 301b52956c9SDavid Ahern 302147c508fSJin Yao if (all_threads) 30373c0ca1eSJin Yao return thread_map__new_all_cpus(); 30473c0ca1eSJin Yao 305b52956c9SDavid Ahern return thread_map__new_by_tid_str(tid); 306b52956c9SDavid Ahern } 307b52956c9SDavid Ahern 3089749b90eSJiri Olsa size_t thread_map__fprintf(struct perf_thread_map *threads, FILE *fp) 3099ae7d335SArnaldo Carvalho de Melo { 3109ae7d335SArnaldo Carvalho de Melo int i; 3119ae7d335SArnaldo Carvalho de Melo size_t printed = fprintf(fp, "%d thread%s: ", 3129ae7d335SArnaldo Carvalho de Melo threads->nr, threads->nr > 1 ? "s" : ""); 3139ae7d335SArnaldo Carvalho de Melo for (i = 0; i < threads->nr; ++i) 314a2f354e3SJiri Olsa printed += fprintf(fp, "%s%d", i ? ", " : "", perf_thread_map__pid(threads, i)); 3159ae7d335SArnaldo Carvalho de Melo 3169ae7d335SArnaldo Carvalho de Melo return printed + fprintf(fp, "\n"); 3179ae7d335SArnaldo Carvalho de Melo } 318792402fdSJiri Olsa 319792402fdSJiri Olsa static int get_comm(char **comm, pid_t pid) 320792402fdSJiri Olsa { 321792402fdSJiri Olsa char *path; 322792402fdSJiri Olsa size_t size; 323792402fdSJiri Olsa int err; 324792402fdSJiri Olsa 325792402fdSJiri Olsa if (asprintf(&path, "%s/%d/comm", procfs__mountpoint(), pid) == -1) 326792402fdSJiri Olsa return -ENOMEM; 327792402fdSJiri Olsa 328792402fdSJiri Olsa err = filename__read_str(path, comm, &size); 329792402fdSJiri Olsa if (!err) { 330792402fdSJiri Olsa /* 331792402fdSJiri Olsa * We're reading 16 bytes, while filename__read_str 332792402fdSJiri Olsa * allocates data per BUFSIZ bytes, so we can safely 333792402fdSJiri Olsa * mark the end of the string. 334792402fdSJiri Olsa */ 335792402fdSJiri Olsa (*comm)[size] = 0; 33613c230abSArnaldo Carvalho de Melo strim(*comm); 337792402fdSJiri Olsa } 338792402fdSJiri Olsa 339792402fdSJiri Olsa free(path); 340792402fdSJiri Olsa return err; 341792402fdSJiri Olsa } 342792402fdSJiri Olsa 3439749b90eSJiri Olsa static void comm_init(struct perf_thread_map *map, int i) 344792402fdSJiri Olsa { 345a2f354e3SJiri Olsa pid_t pid = perf_thread_map__pid(map, i); 346792402fdSJiri Olsa char *comm = NULL; 347792402fdSJiri Olsa 348792402fdSJiri Olsa /* dummy pid comm initialization */ 349792402fdSJiri Olsa if (pid == -1) { 350792402fdSJiri Olsa map->map[i].comm = strdup("dummy"); 351792402fdSJiri Olsa return; 352792402fdSJiri Olsa } 353792402fdSJiri Olsa 354792402fdSJiri Olsa /* 355792402fdSJiri Olsa * The comm name is like extra bonus ;-), 356792402fdSJiri Olsa * so just warn if we fail for any reason. 357792402fdSJiri Olsa */ 358792402fdSJiri Olsa if (get_comm(&comm, pid)) 359792402fdSJiri Olsa pr_warning("Couldn't resolve comm name for pid %d\n", pid); 360792402fdSJiri Olsa 361792402fdSJiri Olsa map->map[i].comm = comm; 362792402fdSJiri Olsa } 363792402fdSJiri Olsa 3649749b90eSJiri Olsa void thread_map__read_comms(struct perf_thread_map *threads) 365792402fdSJiri Olsa { 366792402fdSJiri Olsa int i; 367792402fdSJiri Olsa 368792402fdSJiri Olsa for (i = 0; i < threads->nr; ++i) 369792402fdSJiri Olsa comm_init(threads, i); 370792402fdSJiri Olsa } 37159660942SJiri Olsa 3729749b90eSJiri Olsa static void thread_map__copy_event(struct perf_thread_map *threads, 37372932371SJiri Olsa struct perf_record_thread_map *event) 37459660942SJiri Olsa { 37559660942SJiri Olsa unsigned i; 37659660942SJiri Olsa 37759660942SJiri Olsa threads->nr = (int) event->nr; 37859660942SJiri Olsa 37959660942SJiri Olsa for (i = 0; i < event->nr; i++) { 3804b49cce2SJiri Olsa perf_thread_map__set_pid(threads, i, (pid_t) event->entries[i].pid); 38159660942SJiri Olsa threads->map[i].comm = strndup(event->entries[i].comm, 16); 38259660942SJiri Olsa } 38359660942SJiri Olsa 384364fed35SElena Reshetova refcount_set(&threads->refcnt, 1); 38559660942SJiri Olsa } 38659660942SJiri Olsa 38772932371SJiri Olsa struct perf_thread_map *thread_map__new_event(struct perf_record_thread_map *event) 38859660942SJiri Olsa { 3899749b90eSJiri Olsa struct perf_thread_map *threads; 39059660942SJiri Olsa 39159660942SJiri Olsa threads = thread_map__alloc(event->nr); 39259660942SJiri Olsa if (threads) 39359660942SJiri Olsa thread_map__copy_event(threads, event); 39459660942SJiri Olsa 39559660942SJiri Olsa return threads; 39659660942SJiri Olsa } 3973407df8bSJiri Olsa 3989749b90eSJiri Olsa bool thread_map__has(struct perf_thread_map *threads, pid_t pid) 3993407df8bSJiri Olsa { 4003407df8bSJiri Olsa int i; 4013407df8bSJiri Olsa 4023407df8bSJiri Olsa for (i = 0; i < threads->nr; ++i) { 4033407df8bSJiri Olsa if (threads->map[i].pid == pid) 4043407df8bSJiri Olsa return true; 4053407df8bSJiri Olsa } 4063407df8bSJiri Olsa 4073407df8bSJiri Olsa return false; 4083407df8bSJiri Olsa } 40938af91f0SJiri Olsa 4109749b90eSJiri Olsa int thread_map__remove(struct perf_thread_map *threads, int idx) 41138af91f0SJiri Olsa { 41238af91f0SJiri Olsa int i; 41338af91f0SJiri Olsa 41438af91f0SJiri Olsa if (threads->nr < 1) 41538af91f0SJiri Olsa return -EINVAL; 41638af91f0SJiri Olsa 41738af91f0SJiri Olsa if (idx >= threads->nr) 41838af91f0SJiri Olsa return -EINVAL; 41938af91f0SJiri Olsa 42038af91f0SJiri Olsa /* 42138af91f0SJiri Olsa * Free the 'idx' item and shift the rest up. 42238af91f0SJiri Olsa */ 423d8f9da24SArnaldo Carvalho de Melo zfree(&threads->map[idx].comm); 42438af91f0SJiri Olsa 42538af91f0SJiri Olsa for (i = idx; i < threads->nr - 1; i++) 42638af91f0SJiri Olsa threads->map[i] = threads->map[i + 1]; 42738af91f0SJiri Olsa 42838af91f0SJiri Olsa threads->nr--; 42938af91f0SJiri Olsa return 0; 43038af91f0SJiri Olsa } 431