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  
perf_thread_map__reset(struct perf_thread_map * map,int start,int nr)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  
perf_thread_map__realloc(struct perf_thread_map * map,int nr)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  
perf_thread_map__set_pid(struct perf_thread_map * map,int idx,pid_t pid)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  
perf_thread_map__comm(struct perf_thread_map * map,int idx)40  char *perf_thread_map__comm(struct perf_thread_map *map, int idx)
41  {
42  	return map->map[idx].comm;
43  }
44  
perf_thread_map__new_array(int nr_threads,pid_t * array)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  
perf_thread_map__new_dummy(void)62  struct perf_thread_map *perf_thread_map__new_dummy(void)
63  {
64  	return perf_thread_map__new_array(1, NULL);
65  }
66  
perf_thread_map__delete(struct perf_thread_map * threads)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  
perf_thread_map__get(struct perf_thread_map * map)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  
perf_thread_map__put(struct perf_thread_map * map)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  
perf_thread_map__nr(struct perf_thread_map * threads)93  int perf_thread_map__nr(struct perf_thread_map *threads)
94  {
95  	return threads ? threads->nr : 1;
96  }
97  
perf_thread_map__pid(struct perf_thread_map * map,int idx)98  pid_t perf_thread_map__pid(struct perf_thread_map *map, int idx)
99  {
100  	return map->map[idx].pid;
101  }
102