1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <dirent.h> 2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <limits.h> 3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdbool.h> 4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdlib.h> 5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdio.h> 6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <sys/types.h> 7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <sys/stat.h> 8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <unistd.h> 9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "strlist.h" 10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <string.h> 11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "thread_map.h" 12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng/* Skip "." and ".." directories */ 14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int filter(const struct dirent *dir) 15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (dir->d_name[0] == '.') 17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 0; 18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng else 19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return 1; 20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct thread_map *thread_map__new_by_pid(pid_t pid) 23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread_map *threads; 25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char name[256]; 26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int items; 27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct dirent **namelist = NULL; 28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sprintf(name, "/proc/%d/task", pid); 31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng items = scandir(name, &namelist, filter, NULL); 32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (items <= 0) 33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads = malloc(sizeof(*threads) + sizeof(pid_t) * items); 36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (threads != NULL) { 37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < items; i++) 38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->map[i] = atoi(namelist[i]->d_name); 39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->nr = items; 40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i=0; i<items; i++) 43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(namelist[i]); 44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(namelist); 45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return threads; 47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct thread_map *thread_map__new_by_tid(pid_t tid) 50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread_map *threads = malloc(sizeof(*threads) + sizeof(pid_t)); 52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (threads != NULL) { 54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->map[0] = tid; 55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->nr = 1; 56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return threads; 59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct thread_map *thread_map__new_by_uid(uid_t uid) 62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng DIR *proc; 64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int max_threads = 32, items, i; 65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char path[256]; 66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct dirent dirent, *next, **namelist = NULL; 67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread_map *threads = malloc(sizeof(*threads) + 68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng max_threads * sizeof(pid_t)); 69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (threads == NULL) 70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out; 71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng proc = opendir("/proc"); 73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (proc == NULL) 74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_free_threads; 75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->nr = 0; 77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (!readdir_r(proc, &dirent, &next) && next) { 79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *end; 80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng bool grow = false; 81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct stat st; 82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pid_t pid = strtol(dirent.d_name, &end, 10); 83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (*end) /* only interested in proper numerical dirents */ 85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng snprintf(path, sizeof(path), "/proc/%s", dirent.d_name); 88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (stat(path, &st) != 0) 90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (st.st_uid != uid) 93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng snprintf(path, sizeof(path), "/proc/%d/task", pid); 96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng items = scandir(path, &namelist, filter, NULL); 97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (items <= 0) 98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_free_closedir; 99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng while (threads->nr + items >= max_threads) { 101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng max_threads *= 2; 102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng grow = true; 103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (grow) { 106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread_map *tmp; 107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng tmp = realloc(threads, (sizeof(*threads) + 109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng max_threads * sizeof(pid_t))); 110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (tmp == NULL) 111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_free_namelist; 112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads = tmp; 114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < items; i++) 117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->map[threads->nr + i] = atoi(namelist[i]->d_name); 118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < items; i++) 120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(namelist[i]); 121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(namelist); 122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->nr += items; 124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_closedir: 127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng closedir(proc); 128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout: 129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return threads; 130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_free_threads: 132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(threads); 133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_free_namelist: 136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < items; i++) 137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(namelist[i]); 138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(namelist); 139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_free_closedir: 141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(threads); 142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads = NULL; 143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_closedir; 144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct thread_map *thread_map__new(pid_t pid, pid_t tid, uid_t uid) 147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pid != -1) 149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return thread_map__new_by_pid(pid); 150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (tid == -1 && uid != UINT_MAX) 152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return thread_map__new_by_uid(uid); 153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return thread_map__new_by_tid(tid); 155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct thread_map *thread_map__new_by_pid_str(const char *pid_str) 158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread_map *threads = NULL, *nt; 160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char name[256]; 161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int items, total_tasks = 0; 162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct dirent **namelist = NULL; 163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i, j = 0; 164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pid_t pid, prev_pid = INT_MAX; 165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *end_ptr; 166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct str_node *pos; 167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct strlist *slist = strlist__new(false, pid_str); 168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!slist) 170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng strlist__for_each(pos, slist) { 173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pid = strtol(pos->s, &end_ptr, 10); 174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pid == INT_MIN || pid == INT_MAX || 176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (*end_ptr != '\0' && *end_ptr != ',')) 177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_free_threads; 178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pid == prev_pid) 180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sprintf(name, "/proc/%d/task", pid); 183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng items = scandir(name, &namelist, filter, NULL); 184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (items <= 0) 185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_free_threads; 186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng total_tasks += items; 188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nt = realloc(threads, (sizeof(*threads) + 189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng sizeof(pid_t) * total_tasks)); 190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nt == NULL) 191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_free_namelist; 192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads = nt; 194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < items; i++) { 196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->map[j++] = atoi(namelist[i]->d_name); 197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(namelist[i]); 198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->nr = total_tasks; 200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(namelist); 201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout: 204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng strlist__delete(slist); 205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return threads; 206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_free_namelist: 208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < items; i++) 209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(namelist[i]); 210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(namelist); 211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_free_threads: 213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(threads); 214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads = NULL; 215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out; 216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic struct thread_map *thread_map__new_by_tid_str(const char *tid_str) 219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct thread_map *threads = NULL, *nt; 221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int ntasks = 0; 222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng pid_t tid, prev_tid = INT_MAX; 223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng char *end_ptr; 224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct str_node *pos; 225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng struct strlist *slist; 226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng /* perf-stat expects threads to be generated even if tid not given */ 228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!tid_str) { 229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads = malloc(sizeof(*threads) + sizeof(pid_t)); 230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (threads != NULL) { 231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->map[0] = -1; 232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->nr = 1; 233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return threads; 235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng slist = strlist__new(false, tid_str); 238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!slist) 239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return NULL; 240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng strlist__for_each(pos, slist) { 242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng tid = strtol(pos->s, &end_ptr, 10); 243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (tid == INT_MIN || tid == INT_MAX || 245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng (*end_ptr != '\0' && *end_ptr != ',')) 246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_free_threads; 247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (tid == prev_tid) 249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng continue; 250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng ntasks++; 252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng nt = realloc(threads, sizeof(*threads) + sizeof(pid_t) * ntasks); 253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (nt == NULL) 255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out_free_threads; 256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads = nt; 258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->map[ntasks - 1] = tid; 259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->nr = ntasks; 260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng } 261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout: 262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return threads; 263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_free_threads: 265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(threads); 266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads = NULL; 267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng goto out; 268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct thread_map *thread_map__new_str(const char *pid, const char *tid, 271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng uid_t uid) 272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (pid) 274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return thread_map__new_by_pid_str(pid); 275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng if (!tid && uid != UINT_MAX) 277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return thread_map__new_by_uid(uid); 278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return thread_map__new_by_tid_str(tid); 280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengvoid thread_map__delete(struct thread_map *threads) 283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng free(threads); 285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengsize_t thread_map__fprintf(struct thread_map *threads, FILE *fp) 288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{ 289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng int i; 290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng size_t printed = fprintf(fp, "%d thread%s: ", 291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng threads->nr, threads->nr > 1 ? "s" : ""); 292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng for (i = 0; i < threads->nr; ++i) 293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng printed += fprintf(fp, "%s%d", i ? ", " : "", threads->map[i]); 294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng 295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng return printed + fprintf(fp, "\n"); 296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng} 297