1fd78260bSArnaldo Carvalho de Melo #include <dirent.h> 20d37aa34SArnaldo Carvalho de Melo #include <limits.h> 30d37aa34SArnaldo Carvalho de Melo #include <stdbool.h> 4fd78260bSArnaldo Carvalho de Melo #include <stdlib.h> 5fd78260bSArnaldo Carvalho de Melo #include <stdio.h> 60d37aa34SArnaldo Carvalho de Melo #include <sys/types.h> 70d37aa34SArnaldo Carvalho de Melo #include <sys/stat.h> 80d37aa34SArnaldo Carvalho de Melo #include <unistd.h> 9b52956c9SDavid Ahern #include "strlist.h" 10b52956c9SDavid Ahern #include <string.h> 11792402fdSJiri Olsa #include <api/fs/fs.h> 12186fbb74SJiri Olsa #include "asm/bug.h" 13fd78260bSArnaldo Carvalho de Melo #include "thread_map.h" 1404662523SArnaldo Carvalho de Melo #include "util.h" 15792402fdSJiri Olsa #include "debug.h" 1659660942SJiri Olsa #include "event.h" 17fd78260bSArnaldo Carvalho de Melo 18fd78260bSArnaldo Carvalho de Melo /* Skip "." and ".." directories */ 19fd78260bSArnaldo Carvalho de Melo static int filter(const struct dirent *dir) 20fd78260bSArnaldo Carvalho de Melo { 21fd78260bSArnaldo Carvalho de Melo if (dir->d_name[0] == '.') 22fd78260bSArnaldo Carvalho de Melo return 0; 23fd78260bSArnaldo Carvalho de Melo else 24fd78260bSArnaldo Carvalho de Melo return 1; 25fd78260bSArnaldo Carvalho de Melo } 26fd78260bSArnaldo Carvalho de Melo 2762eea464SJiri Olsa static void thread_map__reset(struct thread_map *map, int start, int nr) 2862eea464SJiri Olsa { 2962eea464SJiri Olsa size_t size = (nr - start) * sizeof(map->map[0]); 3062eea464SJiri Olsa 3162eea464SJiri Olsa memset(&map->map[start], 0, size); 3262eea464SJiri Olsa } 3362eea464SJiri Olsa 349d7e8c3aSJiri Olsa static struct thread_map *thread_map__realloc(struct thread_map *map, int nr) 359d7e8c3aSJiri Olsa { 36060664f3SArnaldo Carvalho de Melo size_t size = sizeof(*map) + sizeof(map->map[0]) * nr; 3762eea464SJiri Olsa int start = map ? map->nr : 0; 389d7e8c3aSJiri Olsa 3962eea464SJiri Olsa map = realloc(map, size); 4062eea464SJiri Olsa /* 4162eea464SJiri Olsa * We only realloc to add more items, let's reset new items. 4262eea464SJiri Olsa */ 4362eea464SJiri Olsa if (map) 4462eea464SJiri Olsa thread_map__reset(map, start, nr); 4562eea464SJiri Olsa 4662eea464SJiri Olsa return map; 479d7e8c3aSJiri Olsa } 489d7e8c3aSJiri Olsa 499d7e8c3aSJiri Olsa #define thread_map__alloc(__nr) thread_map__realloc(NULL, __nr) 509d7e8c3aSJiri Olsa 51fd78260bSArnaldo Carvalho de Melo struct thread_map *thread_map__new_by_pid(pid_t pid) 52fd78260bSArnaldo Carvalho de Melo { 53fd78260bSArnaldo Carvalho de Melo struct thread_map *threads; 54fd78260bSArnaldo Carvalho de Melo char name[256]; 55fd78260bSArnaldo Carvalho de Melo int items; 56fd78260bSArnaldo Carvalho de Melo struct dirent **namelist = NULL; 57fd78260bSArnaldo Carvalho de Melo int i; 58fd78260bSArnaldo Carvalho de Melo 59fd78260bSArnaldo Carvalho de Melo sprintf(name, "/proc/%d/task", pid); 60fd78260bSArnaldo Carvalho de Melo items = scandir(name, &namelist, filter, NULL); 61fd78260bSArnaldo Carvalho de Melo if (items <= 0) 62fd78260bSArnaldo Carvalho de Melo return NULL; 63fd78260bSArnaldo Carvalho de Melo 649d7e8c3aSJiri Olsa threads = thread_map__alloc(items); 65fd78260bSArnaldo Carvalho de Melo if (threads != NULL) { 66fd78260bSArnaldo Carvalho de Melo for (i = 0; i < items; i++) 67e13798c7SJiri Olsa thread_map__set_pid(threads, i, atoi(namelist[i]->d_name)); 68fd78260bSArnaldo Carvalho de Melo threads->nr = items; 69186fbb74SJiri Olsa atomic_set(&threads->refcnt, 1); 70fd78260bSArnaldo Carvalho de Melo } 71fd78260bSArnaldo Carvalho de Melo 72fd78260bSArnaldo Carvalho de Melo for (i=0; i<items; i++) 7374cf249dSArnaldo Carvalho de Melo zfree(&namelist[i]); 74fd78260bSArnaldo Carvalho de Melo free(namelist); 75fd78260bSArnaldo Carvalho de Melo 76fd78260bSArnaldo Carvalho de Melo return threads; 77fd78260bSArnaldo Carvalho de Melo } 78fd78260bSArnaldo Carvalho de Melo 79fd78260bSArnaldo Carvalho de Melo struct thread_map *thread_map__new_by_tid(pid_t tid) 80fd78260bSArnaldo Carvalho de Melo { 819d7e8c3aSJiri Olsa struct thread_map *threads = thread_map__alloc(1); 82fd78260bSArnaldo Carvalho de Melo 83fd78260bSArnaldo Carvalho de Melo if (threads != NULL) { 84e13798c7SJiri Olsa thread_map__set_pid(threads, 0, tid); 85fd78260bSArnaldo Carvalho de Melo threads->nr = 1; 86186fbb74SJiri Olsa atomic_set(&threads->refcnt, 1); 87fd78260bSArnaldo Carvalho de Melo } 88fd78260bSArnaldo Carvalho de Melo 89fd78260bSArnaldo Carvalho de Melo return threads; 90fd78260bSArnaldo Carvalho de Melo } 91fd78260bSArnaldo Carvalho de Melo 920d37aa34SArnaldo Carvalho de Melo struct thread_map *thread_map__new_by_uid(uid_t uid) 930d37aa34SArnaldo Carvalho de Melo { 940d37aa34SArnaldo Carvalho de Melo DIR *proc; 950d37aa34SArnaldo Carvalho de Melo int max_threads = 32, items, i; 960d37aa34SArnaldo Carvalho de Melo char path[256]; 973354cf71SArnaldo Carvalho de Melo struct dirent *dirent, **namelist = NULL; 989d7e8c3aSJiri Olsa struct thread_map *threads = thread_map__alloc(max_threads); 999d7e8c3aSJiri Olsa 1000d37aa34SArnaldo Carvalho de Melo if (threads == NULL) 1010d37aa34SArnaldo Carvalho de Melo goto out; 1020d37aa34SArnaldo Carvalho de Melo 1030d37aa34SArnaldo Carvalho de Melo proc = opendir("/proc"); 1040d37aa34SArnaldo Carvalho de Melo if (proc == NULL) 1050d37aa34SArnaldo Carvalho de Melo goto out_free_threads; 1060d37aa34SArnaldo Carvalho de Melo 1070d37aa34SArnaldo Carvalho de Melo threads->nr = 0; 108186fbb74SJiri Olsa atomic_set(&threads->refcnt, 1); 1090d37aa34SArnaldo Carvalho de Melo 1103354cf71SArnaldo Carvalho de Melo while ((dirent = readdir(proc)) != NULL) { 1110d37aa34SArnaldo Carvalho de Melo char *end; 1120d37aa34SArnaldo Carvalho de Melo bool grow = false; 1130d37aa34SArnaldo Carvalho de Melo struct stat st; 1143354cf71SArnaldo Carvalho de Melo pid_t pid = strtol(dirent->d_name, &end, 10); 1150d37aa34SArnaldo Carvalho de Melo 1160d37aa34SArnaldo Carvalho de Melo if (*end) /* only interested in proper numerical dirents */ 1170d37aa34SArnaldo Carvalho de Melo continue; 1180d37aa34SArnaldo Carvalho de Melo 1193354cf71SArnaldo Carvalho de Melo snprintf(path, sizeof(path), "/proc/%s", dirent->d_name); 1200d37aa34SArnaldo Carvalho de Melo 1210d37aa34SArnaldo Carvalho de Melo if (stat(path, &st) != 0) 1220d37aa34SArnaldo Carvalho de Melo continue; 1230d37aa34SArnaldo Carvalho de Melo 1240d37aa34SArnaldo Carvalho de Melo if (st.st_uid != uid) 1250d37aa34SArnaldo Carvalho de Melo continue; 1260d37aa34SArnaldo Carvalho de Melo 1270d37aa34SArnaldo Carvalho de Melo snprintf(path, sizeof(path), "/proc/%d/task", pid); 1280d37aa34SArnaldo Carvalho de Melo items = scandir(path, &namelist, filter, NULL); 1290d37aa34SArnaldo Carvalho de Melo if (items <= 0) 1300d37aa34SArnaldo Carvalho de Melo goto out_free_closedir; 1310d37aa34SArnaldo Carvalho de Melo 1320d37aa34SArnaldo Carvalho de Melo while (threads->nr + items >= max_threads) { 1330d37aa34SArnaldo Carvalho de Melo max_threads *= 2; 1340d37aa34SArnaldo Carvalho de Melo grow = true; 1350d37aa34SArnaldo Carvalho de Melo } 1360d37aa34SArnaldo Carvalho de Melo 1370d37aa34SArnaldo Carvalho de Melo if (grow) { 1380d37aa34SArnaldo Carvalho de Melo struct thread_map *tmp; 1390d37aa34SArnaldo Carvalho de Melo 14008ae217bSArnaldo Carvalho de Melo tmp = thread_map__realloc(threads, max_threads); 1410d37aa34SArnaldo Carvalho de Melo if (tmp == NULL) 1420d37aa34SArnaldo Carvalho de Melo goto out_free_namelist; 1430d37aa34SArnaldo Carvalho de Melo 1440d37aa34SArnaldo Carvalho de Melo threads = tmp; 1450d37aa34SArnaldo Carvalho de Melo } 1460d37aa34SArnaldo Carvalho de Melo 147e13798c7SJiri Olsa for (i = 0; i < items; i++) { 148e13798c7SJiri Olsa thread_map__set_pid(threads, threads->nr + i, 149e13798c7SJiri Olsa atoi(namelist[i]->d_name)); 150e13798c7SJiri Olsa } 1510d37aa34SArnaldo Carvalho de Melo 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 threads->nr += items; 1570d37aa34SArnaldo Carvalho de Melo } 1580d37aa34SArnaldo Carvalho de Melo 1590d37aa34SArnaldo Carvalho de Melo out_closedir: 1600d37aa34SArnaldo Carvalho de Melo closedir(proc); 1610d37aa34SArnaldo Carvalho de Melo out: 1620d37aa34SArnaldo Carvalho de Melo return threads; 1630d37aa34SArnaldo Carvalho de Melo 1640d37aa34SArnaldo Carvalho de Melo out_free_threads: 1650d37aa34SArnaldo Carvalho de Melo free(threads); 1660d37aa34SArnaldo Carvalho de Melo return NULL; 1670d37aa34SArnaldo Carvalho de Melo 1680d37aa34SArnaldo Carvalho de Melo out_free_namelist: 1690d37aa34SArnaldo Carvalho de Melo for (i = 0; i < items; i++) 17074cf249dSArnaldo Carvalho de Melo zfree(&namelist[i]); 1710d37aa34SArnaldo Carvalho de Melo free(namelist); 1720d37aa34SArnaldo Carvalho de Melo 1730d37aa34SArnaldo Carvalho de Melo out_free_closedir: 17404662523SArnaldo Carvalho de Melo zfree(&threads); 1750d37aa34SArnaldo Carvalho de Melo goto out_closedir; 1760d37aa34SArnaldo Carvalho de Melo } 1770d37aa34SArnaldo Carvalho de Melo 1780d37aa34SArnaldo Carvalho de Melo struct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid) 179fd78260bSArnaldo Carvalho de Melo { 180fd78260bSArnaldo Carvalho de Melo if (pid != -1) 181fd78260bSArnaldo Carvalho de Melo return thread_map__new_by_pid(pid); 1820d37aa34SArnaldo Carvalho de Melo 1830d37aa34SArnaldo Carvalho de Melo if (tid == -1 && uid != UINT_MAX) 1840d37aa34SArnaldo Carvalho de Melo return thread_map__new_by_uid(uid); 1850d37aa34SArnaldo Carvalho de Melo 186fd78260bSArnaldo Carvalho de Melo return thread_map__new_by_tid(tid); 187fd78260bSArnaldo Carvalho de Melo } 188fd78260bSArnaldo Carvalho de Melo 189b52956c9SDavid Ahern static struct thread_map *thread_map__new_by_pid_str(const char *pid_str) 190b52956c9SDavid Ahern { 191b52956c9SDavid Ahern struct thread_map *threads = NULL, *nt; 192b52956c9SDavid Ahern char name[256]; 193b52956c9SDavid Ahern int items, total_tasks = 0; 194b52956c9SDavid Ahern struct dirent **namelist = NULL; 195b52956c9SDavid Ahern int i, j = 0; 196b52956c9SDavid Ahern pid_t pid, prev_pid = INT_MAX; 197b52956c9SDavid Ahern char *end_ptr; 198b52956c9SDavid Ahern struct str_node *pos; 1994a77e218SArnaldo Carvalho de Melo struct strlist_config slist_config = { .dont_dupstr = true, }; 2004a77e218SArnaldo Carvalho de Melo struct strlist *slist = strlist__new(pid_str, &slist_config); 201b52956c9SDavid Ahern 202b52956c9SDavid Ahern if (!slist) 203b52956c9SDavid Ahern return NULL; 204b52956c9SDavid Ahern 205602a1f4dSArnaldo Carvalho de Melo strlist__for_each_entry(pos, slist) { 206b52956c9SDavid Ahern pid = strtol(pos->s, &end_ptr, 10); 207b52956c9SDavid Ahern 208b52956c9SDavid Ahern if (pid == INT_MIN || pid == INT_MAX || 209b52956c9SDavid Ahern (*end_ptr != '\0' && *end_ptr != ',')) 210b52956c9SDavid Ahern goto out_free_threads; 211b52956c9SDavid Ahern 212b52956c9SDavid Ahern if (pid == prev_pid) 213b52956c9SDavid Ahern continue; 214b52956c9SDavid Ahern 215b52956c9SDavid Ahern sprintf(name, "/proc/%d/task", pid); 216b52956c9SDavid Ahern items = scandir(name, &namelist, filter, NULL); 217b52956c9SDavid Ahern if (items <= 0) 218b52956c9SDavid Ahern goto out_free_threads; 219b52956c9SDavid Ahern 220b52956c9SDavid Ahern total_tasks += items; 2219d7e8c3aSJiri Olsa nt = thread_map__realloc(threads, total_tasks); 222b52956c9SDavid Ahern if (nt == NULL) 223e8cdd947SFranck Bui-Huu goto out_free_namelist; 224b52956c9SDavid Ahern 225b52956c9SDavid Ahern threads = nt; 226b52956c9SDavid Ahern 227e8cdd947SFranck Bui-Huu for (i = 0; i < items; i++) { 228e13798c7SJiri Olsa thread_map__set_pid(threads, j++, atoi(namelist[i]->d_name)); 22974cf249dSArnaldo Carvalho de Melo zfree(&namelist[i]); 230e8cdd947SFranck Bui-Huu } 231e8cdd947SFranck Bui-Huu threads->nr = total_tasks; 232b52956c9SDavid Ahern free(namelist); 233b52956c9SDavid Ahern } 234b52956c9SDavid Ahern 235b52956c9SDavid Ahern out: 236b52956c9SDavid Ahern strlist__delete(slist); 237186fbb74SJiri Olsa if (threads) 238186fbb74SJiri Olsa atomic_set(&threads->refcnt, 1); 239b52956c9SDavid Ahern return threads; 240b52956c9SDavid Ahern 241e8cdd947SFranck Bui-Huu out_free_namelist: 242e8cdd947SFranck Bui-Huu for (i = 0; i < items; i++) 24374cf249dSArnaldo Carvalho de Melo zfree(&namelist[i]); 244e8cdd947SFranck Bui-Huu free(namelist); 245e8cdd947SFranck Bui-Huu 246b52956c9SDavid Ahern out_free_threads: 24704662523SArnaldo Carvalho de Melo zfree(&threads); 248b52956c9SDavid Ahern goto out; 249b52956c9SDavid Ahern } 250b52956c9SDavid Ahern 251641556c9SArnaldo Carvalho de Melo struct thread_map *thread_map__new_dummy(void) 252641556c9SArnaldo Carvalho de Melo { 2539d7e8c3aSJiri Olsa struct thread_map *threads = thread_map__alloc(1); 254641556c9SArnaldo Carvalho de Melo 255641556c9SArnaldo Carvalho de Melo if (threads != NULL) { 256e13798c7SJiri Olsa thread_map__set_pid(threads, 0, -1); 257641556c9SArnaldo Carvalho de Melo threads->nr = 1; 258186fbb74SJiri Olsa atomic_set(&threads->refcnt, 1); 259641556c9SArnaldo Carvalho de Melo } 260641556c9SArnaldo Carvalho de Melo return threads; 261641556c9SArnaldo Carvalho de Melo } 262641556c9SArnaldo Carvalho de Melo 263097be0f5SJiri Olsa struct thread_map *thread_map__new_by_tid_str(const char *tid_str) 264b52956c9SDavid Ahern { 265b52956c9SDavid Ahern struct thread_map *threads = NULL, *nt; 266b52956c9SDavid Ahern int ntasks = 0; 267b52956c9SDavid Ahern pid_t tid, prev_tid = INT_MAX; 268b52956c9SDavid Ahern char *end_ptr; 269b52956c9SDavid Ahern struct str_node *pos; 2704a77e218SArnaldo Carvalho de Melo struct strlist_config slist_config = { .dont_dupstr = true, }; 271b52956c9SDavid Ahern struct strlist *slist; 272b52956c9SDavid Ahern 273b52956c9SDavid Ahern /* perf-stat expects threads to be generated even if tid not given */ 274641556c9SArnaldo Carvalho de Melo if (!tid_str) 275641556c9SArnaldo Carvalho de Melo return thread_map__new_dummy(); 276b52956c9SDavid Ahern 2774a77e218SArnaldo Carvalho de Melo slist = strlist__new(tid_str, &slist_config); 278b52956c9SDavid Ahern if (!slist) 279b52956c9SDavid Ahern return NULL; 280b52956c9SDavid Ahern 281602a1f4dSArnaldo Carvalho de Melo strlist__for_each_entry(pos, slist) { 282b52956c9SDavid Ahern tid = strtol(pos->s, &end_ptr, 10); 283b52956c9SDavid Ahern 284b52956c9SDavid Ahern if (tid == INT_MIN || tid == INT_MAX || 285b52956c9SDavid Ahern (*end_ptr != '\0' && *end_ptr != ',')) 286b52956c9SDavid Ahern goto out_free_threads; 287b52956c9SDavid Ahern 288b52956c9SDavid Ahern if (tid == prev_tid) 289b52956c9SDavid Ahern continue; 290b52956c9SDavid Ahern 291b52956c9SDavid Ahern ntasks++; 2929d7e8c3aSJiri Olsa nt = thread_map__realloc(threads, ntasks); 293b52956c9SDavid Ahern 294b52956c9SDavid Ahern if (nt == NULL) 295b52956c9SDavid Ahern goto out_free_threads; 296b52956c9SDavid Ahern 297b52956c9SDavid Ahern threads = nt; 298e13798c7SJiri Olsa thread_map__set_pid(threads, ntasks - 1, tid); 299b52956c9SDavid Ahern threads->nr = ntasks; 300b52956c9SDavid Ahern } 301b52956c9SDavid Ahern out: 302186fbb74SJiri Olsa if (threads) 303186fbb74SJiri Olsa atomic_set(&threads->refcnt, 1); 304b52956c9SDavid Ahern return threads; 305b52956c9SDavid Ahern 306b52956c9SDavid Ahern out_free_threads: 30704662523SArnaldo Carvalho de Melo zfree(&threads); 3087ecb48fdSNamhyung Kim strlist__delete(slist); 309b52956c9SDavid Ahern goto out; 310b52956c9SDavid Ahern } 311b52956c9SDavid Ahern 312b52956c9SDavid Ahern struct thread_map *thread_map__new_str(const char *pid, const char *tid, 313b52956c9SDavid Ahern uid_t uid) 314b52956c9SDavid Ahern { 315b52956c9SDavid Ahern if (pid) 316b52956c9SDavid Ahern return thread_map__new_by_pid_str(pid); 317b52956c9SDavid Ahern 318b52956c9SDavid Ahern if (!tid && uid != UINT_MAX) 319b52956c9SDavid Ahern return thread_map__new_by_uid(uid); 320b52956c9SDavid Ahern 321b52956c9SDavid Ahern return thread_map__new_by_tid_str(tid); 322b52956c9SDavid Ahern } 323b52956c9SDavid Ahern 324186fbb74SJiri Olsa static void thread_map__delete(struct thread_map *threads) 325fd78260bSArnaldo Carvalho de Melo { 326186fbb74SJiri Olsa if (threads) { 327792402fdSJiri Olsa int i; 328792402fdSJiri Olsa 329186fbb74SJiri Olsa WARN_ONCE(atomic_read(&threads->refcnt) != 0, 330186fbb74SJiri Olsa "thread map refcnt unbalanced\n"); 331792402fdSJiri Olsa for (i = 0; i < threads->nr; i++) 332792402fdSJiri Olsa free(thread_map__comm(threads, i)); 333fd78260bSArnaldo Carvalho de Melo free(threads); 334fd78260bSArnaldo Carvalho de Melo } 335186fbb74SJiri Olsa } 336186fbb74SJiri Olsa 337186fbb74SJiri Olsa struct thread_map *thread_map__get(struct thread_map *map) 338186fbb74SJiri Olsa { 339186fbb74SJiri Olsa if (map) 340186fbb74SJiri Olsa atomic_inc(&map->refcnt); 341186fbb74SJiri Olsa return map; 342186fbb74SJiri Olsa } 343186fbb74SJiri Olsa 344186fbb74SJiri Olsa void thread_map__put(struct thread_map *map) 345186fbb74SJiri Olsa { 346186fbb74SJiri Olsa if (map && atomic_dec_and_test(&map->refcnt)) 347186fbb74SJiri Olsa thread_map__delete(map); 348186fbb74SJiri Olsa } 3499ae7d335SArnaldo Carvalho de Melo 3509ae7d335SArnaldo Carvalho de Melo size_t thread_map__fprintf(struct thread_map *threads, FILE *fp) 3519ae7d335SArnaldo Carvalho de Melo { 3529ae7d335SArnaldo Carvalho de Melo int i; 3539ae7d335SArnaldo Carvalho de Melo size_t printed = fprintf(fp, "%d thread%s: ", 3549ae7d335SArnaldo Carvalho de Melo threads->nr, threads->nr > 1 ? "s" : ""); 3559ae7d335SArnaldo Carvalho de Melo for (i = 0; i < threads->nr; ++i) 356e13798c7SJiri Olsa printed += fprintf(fp, "%s%d", i ? ", " : "", thread_map__pid(threads, i)); 3579ae7d335SArnaldo Carvalho de Melo 3589ae7d335SArnaldo Carvalho de Melo return printed + fprintf(fp, "\n"); 3599ae7d335SArnaldo Carvalho de Melo } 360792402fdSJiri Olsa 361792402fdSJiri Olsa static int get_comm(char **comm, pid_t pid) 362792402fdSJiri Olsa { 363792402fdSJiri Olsa char *path; 364792402fdSJiri Olsa size_t size; 365792402fdSJiri Olsa int err; 366792402fdSJiri Olsa 367792402fdSJiri Olsa if (asprintf(&path, "%s/%d/comm", procfs__mountpoint(), pid) == -1) 368792402fdSJiri Olsa return -ENOMEM; 369792402fdSJiri Olsa 370792402fdSJiri Olsa err = filename__read_str(path, comm, &size); 371792402fdSJiri Olsa if (!err) { 372792402fdSJiri Olsa /* 373792402fdSJiri Olsa * We're reading 16 bytes, while filename__read_str 374792402fdSJiri Olsa * allocates data per BUFSIZ bytes, so we can safely 375792402fdSJiri Olsa * mark the end of the string. 376792402fdSJiri Olsa */ 377792402fdSJiri Olsa (*comm)[size] = 0; 378792402fdSJiri Olsa rtrim(*comm); 379792402fdSJiri Olsa } 380792402fdSJiri Olsa 381792402fdSJiri Olsa free(path); 382792402fdSJiri Olsa return err; 383792402fdSJiri Olsa } 384792402fdSJiri Olsa 385792402fdSJiri Olsa static void comm_init(struct thread_map *map, int i) 386792402fdSJiri Olsa { 387792402fdSJiri Olsa pid_t pid = thread_map__pid(map, i); 388792402fdSJiri Olsa char *comm = NULL; 389792402fdSJiri Olsa 390792402fdSJiri Olsa /* dummy pid comm initialization */ 391792402fdSJiri Olsa if (pid == -1) { 392792402fdSJiri Olsa map->map[i].comm = strdup("dummy"); 393792402fdSJiri Olsa return; 394792402fdSJiri Olsa } 395792402fdSJiri Olsa 396792402fdSJiri Olsa /* 397792402fdSJiri Olsa * The comm name is like extra bonus ;-), 398792402fdSJiri Olsa * so just warn if we fail for any reason. 399792402fdSJiri Olsa */ 400792402fdSJiri Olsa if (get_comm(&comm, pid)) 401792402fdSJiri Olsa pr_warning("Couldn't resolve comm name for pid %d\n", pid); 402792402fdSJiri Olsa 403792402fdSJiri Olsa map->map[i].comm = comm; 404792402fdSJiri Olsa } 405792402fdSJiri Olsa 406792402fdSJiri Olsa void thread_map__read_comms(struct thread_map *threads) 407792402fdSJiri Olsa { 408792402fdSJiri Olsa int i; 409792402fdSJiri Olsa 410792402fdSJiri Olsa for (i = 0; i < threads->nr; ++i) 411792402fdSJiri Olsa comm_init(threads, i); 412792402fdSJiri Olsa } 41359660942SJiri Olsa 41459660942SJiri Olsa static void thread_map__copy_event(struct thread_map *threads, 41559660942SJiri Olsa struct thread_map_event *event) 41659660942SJiri Olsa { 41759660942SJiri Olsa unsigned i; 41859660942SJiri Olsa 41959660942SJiri Olsa threads->nr = (int) event->nr; 42059660942SJiri Olsa 42159660942SJiri Olsa for (i = 0; i < event->nr; i++) { 42259660942SJiri Olsa thread_map__set_pid(threads, i, (pid_t) event->entries[i].pid); 42359660942SJiri Olsa threads->map[i].comm = strndup(event->entries[i].comm, 16); 42459660942SJiri Olsa } 42559660942SJiri Olsa 42659660942SJiri Olsa atomic_set(&threads->refcnt, 1); 42759660942SJiri Olsa } 42859660942SJiri Olsa 42959660942SJiri Olsa struct thread_map *thread_map__new_event(struct thread_map_event *event) 43059660942SJiri Olsa { 43159660942SJiri Olsa struct thread_map *threads; 43259660942SJiri Olsa 43359660942SJiri Olsa threads = thread_map__alloc(event->nr); 43459660942SJiri Olsa if (threads) 43559660942SJiri Olsa thread_map__copy_event(threads, event); 43659660942SJiri Olsa 43759660942SJiri Olsa return threads; 43859660942SJiri Olsa } 4393407df8bSJiri Olsa 4403407df8bSJiri Olsa bool thread_map__has(struct thread_map *threads, pid_t pid) 4413407df8bSJiri Olsa { 4423407df8bSJiri Olsa int i; 4433407df8bSJiri Olsa 4443407df8bSJiri Olsa for (i = 0; i < threads->nr; ++i) { 4453407df8bSJiri Olsa if (threads->map[i].pid == pid) 4463407df8bSJiri Olsa return true; 4473407df8bSJiri Olsa } 4483407df8bSJiri Olsa 4493407df8bSJiri Olsa return false; 4503407df8bSJiri Olsa } 451*38af91f0SJiri Olsa 452*38af91f0SJiri Olsa int thread_map__remove(struct thread_map *threads, int idx) 453*38af91f0SJiri Olsa { 454*38af91f0SJiri Olsa int i; 455*38af91f0SJiri Olsa 456*38af91f0SJiri Olsa if (threads->nr < 1) 457*38af91f0SJiri Olsa return -EINVAL; 458*38af91f0SJiri Olsa 459*38af91f0SJiri Olsa if (idx >= threads->nr) 460*38af91f0SJiri Olsa return -EINVAL; 461*38af91f0SJiri Olsa 462*38af91f0SJiri Olsa /* 463*38af91f0SJiri Olsa * Free the 'idx' item and shift the rest up. 464*38af91f0SJiri Olsa */ 465*38af91f0SJiri Olsa free(threads->map[idx].comm); 466*38af91f0SJiri Olsa 467*38af91f0SJiri Olsa for (i = idx; i < threads->nr - 1; i++) 468*38af91f0SJiri Olsa threads->map[i] = threads->map[i + 1]; 469*38af91f0SJiri Olsa 470*38af91f0SJiri Olsa threads->nr--; 471*38af91f0SJiri Olsa return 0; 472*38af91f0SJiri Olsa } 473