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(map: threads, idx: i, pid: array ? array[i] : -1); |
55 | |
56 | threads->nr = nr_threads; |
57 | refcount_set(r: &threads->refcnt, n: 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(nr_threads: 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(map: threads, idx: 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(r: &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(r: &map->refcnt)) |
90 | perf_thread_map__delete(threads: 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 | |