18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <dirent.h> 38c2ecf20Sopenharmony_ci#include <errno.h> 48c2ecf20Sopenharmony_ci#include <limits.h> 58c2ecf20Sopenharmony_ci#include <stdbool.h> 68c2ecf20Sopenharmony_ci#include <stdlib.h> 78c2ecf20Sopenharmony_ci#include <stdio.h> 88c2ecf20Sopenharmony_ci#include <sys/types.h> 98c2ecf20Sopenharmony_ci#include <sys/stat.h> 108c2ecf20Sopenharmony_ci#include <unistd.h> 118c2ecf20Sopenharmony_ci#include "string2.h" 128c2ecf20Sopenharmony_ci#include "strlist.h" 138c2ecf20Sopenharmony_ci#include <string.h> 148c2ecf20Sopenharmony_ci#include <api/fs/fs.h> 158c2ecf20Sopenharmony_ci#include <linux/string.h> 168c2ecf20Sopenharmony_ci#include <linux/zalloc.h> 178c2ecf20Sopenharmony_ci#include "asm/bug.h" 188c2ecf20Sopenharmony_ci#include "thread_map.h" 198c2ecf20Sopenharmony_ci#include "debug.h" 208c2ecf20Sopenharmony_ci#include "event.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/* Skip "." and ".." directories */ 238c2ecf20Sopenharmony_cistatic int filter(const struct dirent *dir) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci if (dir->d_name[0] == '.') 268c2ecf20Sopenharmony_ci return 0; 278c2ecf20Sopenharmony_ci else 288c2ecf20Sopenharmony_ci return 1; 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define thread_map__alloc(__nr) perf_thread_map__realloc(NULL, __nr) 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistruct perf_thread_map *thread_map__new_by_pid(pid_t pid) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci struct perf_thread_map *threads; 368c2ecf20Sopenharmony_ci char name[256]; 378c2ecf20Sopenharmony_ci int items; 388c2ecf20Sopenharmony_ci struct dirent **namelist = NULL; 398c2ecf20Sopenharmony_ci int i; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci sprintf(name, "/proc/%d/task", pid); 428c2ecf20Sopenharmony_ci items = scandir(name, &namelist, filter, NULL); 438c2ecf20Sopenharmony_ci if (items <= 0) 448c2ecf20Sopenharmony_ci return NULL; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci threads = thread_map__alloc(items); 478c2ecf20Sopenharmony_ci if (threads != NULL) { 488c2ecf20Sopenharmony_ci for (i = 0; i < items; i++) 498c2ecf20Sopenharmony_ci perf_thread_map__set_pid(threads, i, atoi(namelist[i]->d_name)); 508c2ecf20Sopenharmony_ci threads->nr = items; 518c2ecf20Sopenharmony_ci refcount_set(&threads->refcnt, 1); 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci for (i=0; i<items; i++) 558c2ecf20Sopenharmony_ci zfree(&namelist[i]); 568c2ecf20Sopenharmony_ci free(namelist); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci return threads; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistruct perf_thread_map *thread_map__new_by_tid(pid_t tid) 628c2ecf20Sopenharmony_ci{ 638c2ecf20Sopenharmony_ci struct perf_thread_map *threads = thread_map__alloc(1); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci if (threads != NULL) { 668c2ecf20Sopenharmony_ci perf_thread_map__set_pid(threads, 0, tid); 678c2ecf20Sopenharmony_ci threads->nr = 1; 688c2ecf20Sopenharmony_ci refcount_set(&threads->refcnt, 1); 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci return threads; 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic struct perf_thread_map *__thread_map__new_all_cpus(uid_t uid) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci DIR *proc; 778c2ecf20Sopenharmony_ci int max_threads = 32, items, i; 788c2ecf20Sopenharmony_ci char path[NAME_MAX + 1 + 6]; 798c2ecf20Sopenharmony_ci struct dirent *dirent, **namelist = NULL; 808c2ecf20Sopenharmony_ci struct perf_thread_map *threads = thread_map__alloc(max_threads); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci if (threads == NULL) 838c2ecf20Sopenharmony_ci goto out; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci proc = opendir("/proc"); 868c2ecf20Sopenharmony_ci if (proc == NULL) 878c2ecf20Sopenharmony_ci goto out_free_threads; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci threads->nr = 0; 908c2ecf20Sopenharmony_ci refcount_set(&threads->refcnt, 1); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci while ((dirent = readdir(proc)) != NULL) { 938c2ecf20Sopenharmony_ci char *end; 948c2ecf20Sopenharmony_ci bool grow = false; 958c2ecf20Sopenharmony_ci pid_t pid = strtol(dirent->d_name, &end, 10); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci if (*end) /* only interested in proper numerical dirents */ 988c2ecf20Sopenharmony_ci continue; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci snprintf(path, sizeof(path), "/proc/%s", dirent->d_name); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if (uid != UINT_MAX) { 1038c2ecf20Sopenharmony_ci struct stat st; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci if (stat(path, &st) != 0 || st.st_uid != uid) 1068c2ecf20Sopenharmony_ci continue; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci snprintf(path, sizeof(path), "/proc/%d/task", pid); 1108c2ecf20Sopenharmony_ci items = scandir(path, &namelist, filter, NULL); 1118c2ecf20Sopenharmony_ci if (items <= 0) 1128c2ecf20Sopenharmony_ci goto out_free_closedir; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci while (threads->nr + items >= max_threads) { 1158c2ecf20Sopenharmony_ci max_threads *= 2; 1168c2ecf20Sopenharmony_ci grow = true; 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (grow) { 1208c2ecf20Sopenharmony_ci struct perf_thread_map *tmp; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci tmp = perf_thread_map__realloc(threads, max_threads); 1238c2ecf20Sopenharmony_ci if (tmp == NULL) 1248c2ecf20Sopenharmony_ci goto out_free_namelist; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci threads = tmp; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci for (i = 0; i < items; i++) { 1308c2ecf20Sopenharmony_ci perf_thread_map__set_pid(threads, threads->nr + i, 1318c2ecf20Sopenharmony_ci atoi(namelist[i]->d_name)); 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci for (i = 0; i < items; i++) 1358c2ecf20Sopenharmony_ci zfree(&namelist[i]); 1368c2ecf20Sopenharmony_ci free(namelist); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci threads->nr += items; 1398c2ecf20Sopenharmony_ci } 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ciout_closedir: 1428c2ecf20Sopenharmony_ci closedir(proc); 1438c2ecf20Sopenharmony_ciout: 1448c2ecf20Sopenharmony_ci return threads; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ciout_free_threads: 1478c2ecf20Sopenharmony_ci free(threads); 1488c2ecf20Sopenharmony_ci return NULL; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ciout_free_namelist: 1518c2ecf20Sopenharmony_ci for (i = 0; i < items; i++) 1528c2ecf20Sopenharmony_ci zfree(&namelist[i]); 1538c2ecf20Sopenharmony_ci free(namelist); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ciout_free_closedir: 1568c2ecf20Sopenharmony_ci zfree(&threads); 1578c2ecf20Sopenharmony_ci goto out_closedir; 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistruct perf_thread_map *thread_map__new_all_cpus(void) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci return __thread_map__new_all_cpus(UINT_MAX); 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistruct perf_thread_map *thread_map__new_by_uid(uid_t uid) 1668c2ecf20Sopenharmony_ci{ 1678c2ecf20Sopenharmony_ci return __thread_map__new_all_cpus(uid); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistruct perf_thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci if (pid != -1) 1738c2ecf20Sopenharmony_ci return thread_map__new_by_pid(pid); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (tid == -1 && uid != UINT_MAX) 1768c2ecf20Sopenharmony_ci return thread_map__new_by_uid(uid); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci return thread_map__new_by_tid(tid); 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic struct perf_thread_map *thread_map__new_by_pid_str(const char *pid_str) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci struct perf_thread_map *threads = NULL, *nt; 1848c2ecf20Sopenharmony_ci char name[256]; 1858c2ecf20Sopenharmony_ci int items, total_tasks = 0; 1868c2ecf20Sopenharmony_ci struct dirent **namelist = NULL; 1878c2ecf20Sopenharmony_ci int i, j = 0; 1888c2ecf20Sopenharmony_ci pid_t pid, prev_pid = INT_MAX; 1898c2ecf20Sopenharmony_ci char *end_ptr; 1908c2ecf20Sopenharmony_ci struct str_node *pos; 1918c2ecf20Sopenharmony_ci struct strlist_config slist_config = { .dont_dupstr = true, }; 1928c2ecf20Sopenharmony_ci struct strlist *slist = strlist__new(pid_str, &slist_config); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if (!slist) 1958c2ecf20Sopenharmony_ci return NULL; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci strlist__for_each_entry(pos, slist) { 1988c2ecf20Sopenharmony_ci pid = strtol(pos->s, &end_ptr, 10); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci if (pid == INT_MIN || pid == INT_MAX || 2018c2ecf20Sopenharmony_ci (*end_ptr != '\0' && *end_ptr != ',')) 2028c2ecf20Sopenharmony_ci goto out_free_threads; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (pid == prev_pid) 2058c2ecf20Sopenharmony_ci continue; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci sprintf(name, "/proc/%d/task", pid); 2088c2ecf20Sopenharmony_ci items = scandir(name, &namelist, filter, NULL); 2098c2ecf20Sopenharmony_ci if (items <= 0) 2108c2ecf20Sopenharmony_ci goto out_free_threads; 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci total_tasks += items; 2138c2ecf20Sopenharmony_ci nt = perf_thread_map__realloc(threads, total_tasks); 2148c2ecf20Sopenharmony_ci if (nt == NULL) 2158c2ecf20Sopenharmony_ci goto out_free_namelist; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci threads = nt; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci for (i = 0; i < items; i++) { 2208c2ecf20Sopenharmony_ci perf_thread_map__set_pid(threads, j++, atoi(namelist[i]->d_name)); 2218c2ecf20Sopenharmony_ci zfree(&namelist[i]); 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci threads->nr = total_tasks; 2248c2ecf20Sopenharmony_ci free(namelist); 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ciout: 2288c2ecf20Sopenharmony_ci strlist__delete(slist); 2298c2ecf20Sopenharmony_ci if (threads) 2308c2ecf20Sopenharmony_ci refcount_set(&threads->refcnt, 1); 2318c2ecf20Sopenharmony_ci return threads; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ciout_free_namelist: 2348c2ecf20Sopenharmony_ci for (i = 0; i < items; i++) 2358c2ecf20Sopenharmony_ci zfree(&namelist[i]); 2368c2ecf20Sopenharmony_ci free(namelist); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ciout_free_threads: 2398c2ecf20Sopenharmony_ci zfree(&threads); 2408c2ecf20Sopenharmony_ci goto out; 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistruct perf_thread_map *thread_map__new_by_tid_str(const char *tid_str) 2448c2ecf20Sopenharmony_ci{ 2458c2ecf20Sopenharmony_ci struct perf_thread_map *threads = NULL, *nt; 2468c2ecf20Sopenharmony_ci int ntasks = 0; 2478c2ecf20Sopenharmony_ci pid_t tid, prev_tid = INT_MAX; 2488c2ecf20Sopenharmony_ci char *end_ptr; 2498c2ecf20Sopenharmony_ci struct str_node *pos; 2508c2ecf20Sopenharmony_ci struct strlist_config slist_config = { .dont_dupstr = true, }; 2518c2ecf20Sopenharmony_ci struct strlist *slist; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* perf-stat expects threads to be generated even if tid not given */ 2548c2ecf20Sopenharmony_ci if (!tid_str) 2558c2ecf20Sopenharmony_ci return perf_thread_map__new_dummy(); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci slist = strlist__new(tid_str, &slist_config); 2588c2ecf20Sopenharmony_ci if (!slist) 2598c2ecf20Sopenharmony_ci return NULL; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci strlist__for_each_entry(pos, slist) { 2628c2ecf20Sopenharmony_ci tid = strtol(pos->s, &end_ptr, 10); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci if (tid == INT_MIN || tid == INT_MAX || 2658c2ecf20Sopenharmony_ci (*end_ptr != '\0' && *end_ptr != ',')) 2668c2ecf20Sopenharmony_ci goto out_free_threads; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci if (tid == prev_tid) 2698c2ecf20Sopenharmony_ci continue; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci ntasks++; 2728c2ecf20Sopenharmony_ci nt = perf_thread_map__realloc(threads, ntasks); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci if (nt == NULL) 2758c2ecf20Sopenharmony_ci goto out_free_threads; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci threads = nt; 2788c2ecf20Sopenharmony_ci perf_thread_map__set_pid(threads, ntasks - 1, tid); 2798c2ecf20Sopenharmony_ci threads->nr = ntasks; 2808c2ecf20Sopenharmony_ci } 2818c2ecf20Sopenharmony_ciout: 2828c2ecf20Sopenharmony_ci if (threads) 2838c2ecf20Sopenharmony_ci refcount_set(&threads->refcnt, 1); 2848c2ecf20Sopenharmony_ci return threads; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ciout_free_threads: 2878c2ecf20Sopenharmony_ci zfree(&threads); 2888c2ecf20Sopenharmony_ci strlist__delete(slist); 2898c2ecf20Sopenharmony_ci goto out; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistruct perf_thread_map *thread_map__new_str(const char *pid, const char *tid, 2938c2ecf20Sopenharmony_ci uid_t uid, bool all_threads) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci if (pid) 2968c2ecf20Sopenharmony_ci return thread_map__new_by_pid_str(pid); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (!tid && uid != UINT_MAX) 2998c2ecf20Sopenharmony_ci return thread_map__new_by_uid(uid); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci if (all_threads) 3028c2ecf20Sopenharmony_ci return thread_map__new_all_cpus(); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci return thread_map__new_by_tid_str(tid); 3058c2ecf20Sopenharmony_ci} 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cisize_t thread_map__fprintf(struct perf_thread_map *threads, FILE *fp) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci int i; 3108c2ecf20Sopenharmony_ci size_t printed = fprintf(fp, "%d thread%s: ", 3118c2ecf20Sopenharmony_ci threads->nr, threads->nr > 1 ? "s" : ""); 3128c2ecf20Sopenharmony_ci for (i = 0; i < threads->nr; ++i) 3138c2ecf20Sopenharmony_ci printed += fprintf(fp, "%s%d", i ? ", " : "", perf_thread_map__pid(threads, i)); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci return printed + fprintf(fp, "\n"); 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic int get_comm(char **comm, pid_t pid) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci char *path; 3218c2ecf20Sopenharmony_ci size_t size; 3228c2ecf20Sopenharmony_ci int err; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci if (asprintf(&path, "%s/%d/comm", procfs__mountpoint(), pid) == -1) 3258c2ecf20Sopenharmony_ci return -ENOMEM; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci err = filename__read_str(path, comm, &size); 3288c2ecf20Sopenharmony_ci if (!err) { 3298c2ecf20Sopenharmony_ci /* 3308c2ecf20Sopenharmony_ci * We're reading 16 bytes, while filename__read_str 3318c2ecf20Sopenharmony_ci * allocates data per BUFSIZ bytes, so we can safely 3328c2ecf20Sopenharmony_ci * mark the end of the string. 3338c2ecf20Sopenharmony_ci */ 3348c2ecf20Sopenharmony_ci (*comm)[size] = 0; 3358c2ecf20Sopenharmony_ci strim(*comm); 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci free(path); 3398c2ecf20Sopenharmony_ci return err; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic void comm_init(struct perf_thread_map *map, int i) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci pid_t pid = perf_thread_map__pid(map, i); 3458c2ecf20Sopenharmony_ci char *comm = NULL; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci /* dummy pid comm initialization */ 3488c2ecf20Sopenharmony_ci if (pid == -1) { 3498c2ecf20Sopenharmony_ci map->map[i].comm = strdup("dummy"); 3508c2ecf20Sopenharmony_ci return; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci /* 3548c2ecf20Sopenharmony_ci * The comm name is like extra bonus ;-), 3558c2ecf20Sopenharmony_ci * so just warn if we fail for any reason. 3568c2ecf20Sopenharmony_ci */ 3578c2ecf20Sopenharmony_ci if (get_comm(&comm, pid)) 3588c2ecf20Sopenharmony_ci pr_warning("Couldn't resolve comm name for pid %d\n", pid); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci map->map[i].comm = comm; 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_civoid thread_map__read_comms(struct perf_thread_map *threads) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci int i; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci for (i = 0; i < threads->nr; ++i) 3688c2ecf20Sopenharmony_ci comm_init(threads, i); 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistatic void thread_map__copy_event(struct perf_thread_map *threads, 3728c2ecf20Sopenharmony_ci struct perf_record_thread_map *event) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci unsigned i; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci threads->nr = (int) event->nr; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci for (i = 0; i < event->nr; i++) { 3798c2ecf20Sopenharmony_ci perf_thread_map__set_pid(threads, i, (pid_t) event->entries[i].pid); 3808c2ecf20Sopenharmony_ci threads->map[i].comm = strndup(event->entries[i].comm, 16); 3818c2ecf20Sopenharmony_ci } 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci refcount_set(&threads->refcnt, 1); 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_cistruct perf_thread_map *thread_map__new_event(struct perf_record_thread_map *event) 3878c2ecf20Sopenharmony_ci{ 3888c2ecf20Sopenharmony_ci struct perf_thread_map *threads; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci threads = thread_map__alloc(event->nr); 3918c2ecf20Sopenharmony_ci if (threads) 3928c2ecf20Sopenharmony_ci thread_map__copy_event(threads, event); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci return threads; 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cibool thread_map__has(struct perf_thread_map *threads, pid_t pid) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci int i; 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci for (i = 0; i < threads->nr; ++i) { 4028c2ecf20Sopenharmony_ci if (threads->map[i].pid == pid) 4038c2ecf20Sopenharmony_ci return true; 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci return false; 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ciint thread_map__remove(struct perf_thread_map *threads, int idx) 4108c2ecf20Sopenharmony_ci{ 4118c2ecf20Sopenharmony_ci int i; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci if (threads->nr < 1) 4148c2ecf20Sopenharmony_ci return -EINVAL; 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci if (idx >= threads->nr) 4178c2ecf20Sopenharmony_ci return -EINVAL; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci /* 4208c2ecf20Sopenharmony_ci * Free the 'idx' item and shift the rest up. 4218c2ecf20Sopenharmony_ci */ 4228c2ecf20Sopenharmony_ci zfree(&threads->map[idx].comm); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci for (i = idx; i < threads->nr - 1; i++) 4258c2ecf20Sopenharmony_ci threads->map[i] = threads->map[i + 1]; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci threads->nr--; 4288c2ecf20Sopenharmony_ci return 0; 4298c2ecf20Sopenharmony_ci} 430