1 // SPDX-License-Identifier: GPL-2.0 2 #include <perf/threadmap.h> 3 #include <stdlib.h> 4 #include <linux/refcount.h> 5 #include <internal/threadmap.h> 6 #include <string.h> 7 #include <asm/bug.h> 8 #include <stdio.h> 9 10 static void perf_thread_map__reset(struct perf_thread_map *map, int start, int nr) 11 { 12 size_t size = (nr - start) * sizeof(map->map[0]); 13 14 memset(&map->map[start], 0, size); 15 map->err_thread = -1; 16 } 17 18 struct perf_thread_map *perf_thread_map__realloc(struct perf_thread_map *map, int nr) 19 { 20 size_t size = sizeof(*map) + sizeof(map->map[0]) * nr; 21 int start = map ? map->nr : 0; 22 23 map = realloc(map, size); 24 /* 25 * We only realloc to add more items, let's reset new items. 26 */ 27 if (map) 28 perf_thread_map__reset(map, start, nr); 29 30 return map; 31 } 32 33 #define thread_map__alloc(__nr) perf_thread_map__realloc(NULL, __nr) 34 35 void perf_thread_map__set_pid(struct perf_thread_map *map, int idx, pid_t pid) 36 { 37 map->map[idx].pid = pid; 38 } 39 40 char *perf_thread_map__comm(struct perf_thread_map *map, int idx) 41 { 42 return map->map[idx].comm; 43 } 44 45 struct perf_thread_map *perf_thread_map__new_array(int nr_threads, pid_t *array) 46 { 47 struct perf_thread_map *threads = thread_map__alloc(nr_threads); 48 int i; 49 50 if (!threads) 51 return NULL; 52 53 for (i = 0; i < nr_threads; i++) 54 perf_thread_map__set_pid(threads, i, array ? array[i] : -1); 55 56 threads->nr = nr_threads; 57 refcount_set(&threads->refcnt, 1); 58 59 return threads; 60 } 61 62 struct perf_thread_map *perf_thread_map__new_dummy(void) 63 { 64 return perf_thread_map__new_array(1, NULL); 65 } 66 67 static void perf_thread_map__delete(struct perf_thread_map *threads) 68 { 69 if (threads) { 70 int i; 71 72 WARN_ONCE(refcount_read(&threads->refcnt) != 0, 73 "thread map refcnt unbalanced\n"); 74 for (i = 0; i < threads->nr; i++) 75 free(perf_thread_map__comm(threads, i)); 76 free(threads); 77 } 78 } 79 80 struct perf_thread_map *perf_thread_map__get(struct perf_thread_map *map) 81 { 82 if (map) 83 refcount_inc(&map->refcnt); 84 return map; 85 } 86 87 void perf_thread_map__put(struct perf_thread_map *map) 88 { 89 if (map && refcount_dec_and_test(&map->refcnt)) 90 perf_thread_map__delete(map); 91 } 92 93 int perf_thread_map__nr(struct perf_thread_map *threads) 94 { 95 return threads ? threads->nr : 1; 96 } 97 98 pid_t perf_thread_map__pid(struct perf_thread_map *map, int idx) 99 { 100 return map->map[idx].pid; 101 } 102