]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - tools/perf/util/cpumap.c
workqueue: make work_busy() test WORK_STRUCT_PENDING first
[mirror_ubuntu-jammy-kernel.git] / tools / perf / util / cpumap.c
CommitLineData
a12b51c4
PM
1#include "util.h"
2#include "../perf.h"
3#include "cpumap.h"
4#include <assert.h>
5#include <stdio.h>
6
60d567e2 7static struct cpu_map *cpu_map__default_new(void)
a12b51c4 8{
60d567e2
ACM
9 struct cpu_map *cpus;
10 int nr_cpus;
a12b51c4
PM
11
12 nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
60d567e2
ACM
13 if (nr_cpus < 0)
14 return NULL;
15
16 cpus = malloc(sizeof(*cpus) + nr_cpus * sizeof(int));
17 if (cpus != NULL) {
18 int i;
19 for (i = 0; i < nr_cpus; ++i)
20 cpus->map[i] = i;
a12b51c4 21
60d567e2
ACM
22 cpus->nr = nr_cpus;
23 }
a12b51c4 24
60d567e2 25 return cpus;
a12b51c4
PM
26}
27
60d567e2 28static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
a12b51c4 29{
60d567e2
ACM
30 size_t payload_size = nr_cpus * sizeof(int);
31 struct cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
32
33 if (cpus != NULL) {
34 cpus->nr = nr_cpus;
35 memcpy(cpus->map, tmp_cpus, payload_size);
36 }
37
38 return cpus;
39}
40
7ae92e74 41struct cpu_map *cpu_map__read(FILE *file)
60d567e2
ACM
42{
43 struct cpu_map *cpus = NULL;
a12b51c4 44 int nr_cpus = 0;
60d567e2
ACM
45 int *tmp_cpus = NULL, *tmp;
46 int max_entries = 0;
a12b51c4
PM
47 int n, cpu, prev;
48 char sep;
49
a12b51c4
PM
50 sep = 0;
51 prev = -1;
52 for (;;) {
7ae92e74 53 n = fscanf(file, "%u%c", &cpu, &sep);
a12b51c4
PM
54 if (n <= 0)
55 break;
56 if (prev >= 0) {
60d567e2
ACM
57 int new_max = nr_cpus + cpu - prev - 1;
58
59 if (new_max >= max_entries) {
60 max_entries = new_max + MAX_NR_CPUS / 2;
61 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
62 if (tmp == NULL)
63 goto out_free_tmp;
64 tmp_cpus = tmp;
65 }
66
a12b51c4 67 while (++prev < cpu)
60d567e2
ACM
68 tmp_cpus[nr_cpus++] = prev;
69 }
70 if (nr_cpus == max_entries) {
71 max_entries += MAX_NR_CPUS;
72 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
73 if (tmp == NULL)
74 goto out_free_tmp;
75 tmp_cpus = tmp;
a12b51c4 76 }
60d567e2
ACM
77
78 tmp_cpus[nr_cpus++] = cpu;
a12b51c4
PM
79 if (n == 2 && sep == '-')
80 prev = cpu;
81 else
82 prev = -1;
83 if (n == 1 || sep == '\n')
84 break;
85 }
a12b51c4 86
60d567e2
ACM
87 if (nr_cpus > 0)
88 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
89 else
90 cpus = cpu_map__default_new();
91out_free_tmp:
92 free(tmp_cpus);
7ae92e74
YZ
93 return cpus;
94}
95
96static struct cpu_map *cpu_map__read_all_cpu_map(void)
97{
98 struct cpu_map *cpus = NULL;
99 FILE *onlnf;
100
101 onlnf = fopen("/sys/devices/system/cpu/online", "r");
102 if (!onlnf)
103 return cpu_map__default_new();
104
105 cpus = cpu_map__read(onlnf);
60d567e2
ACM
106 fclose(onlnf);
107 return cpus;
a12b51c4 108}
c45c6ea2 109
60d567e2 110struct cpu_map *cpu_map__new(const char *cpu_list)
c45c6ea2 111{
60d567e2 112 struct cpu_map *cpus = NULL;
c45c6ea2
SE
113 unsigned long start_cpu, end_cpu = 0;
114 char *p = NULL;
115 int i, nr_cpus = 0;
60d567e2
ACM
116 int *tmp_cpus = NULL, *tmp;
117 int max_entries = 0;
c45c6ea2
SE
118
119 if (!cpu_list)
60d567e2 120 return cpu_map__read_all_cpu_map();
c45c6ea2
SE
121
122 if (!isdigit(*cpu_list))
60d567e2 123 goto out;
c45c6ea2
SE
124
125 while (isdigit(*cpu_list)) {
126 p = NULL;
127 start_cpu = strtoul(cpu_list, &p, 0);
128 if (start_cpu >= INT_MAX
129 || (*p != '\0' && *p != ',' && *p != '-'))
130 goto invalid;
131
132 if (*p == '-') {
133 cpu_list = ++p;
134 p = NULL;
135 end_cpu = strtoul(cpu_list, &p, 0);
136
137 if (end_cpu >= INT_MAX || (*p != '\0' && *p != ','))
138 goto invalid;
139
140 if (end_cpu < start_cpu)
141 goto invalid;
142 } else {
143 end_cpu = start_cpu;
144 }
145
146 for (; start_cpu <= end_cpu; start_cpu++) {
147 /* check for duplicates */
148 for (i = 0; i < nr_cpus; i++)
60d567e2 149 if (tmp_cpus[i] == (int)start_cpu)
c45c6ea2
SE
150 goto invalid;
151
60d567e2
ACM
152 if (nr_cpus == max_entries) {
153 max_entries += MAX_NR_CPUS;
154 tmp = realloc(tmp_cpus, max_entries * sizeof(int));
155 if (tmp == NULL)
156 goto invalid;
157 tmp_cpus = tmp;
158 }
159 tmp_cpus[nr_cpus++] = (int)start_cpu;
c45c6ea2
SE
160 }
161 if (*p)
162 ++p;
163
164 cpu_list = p;
165 }
c45c6ea2 166
60d567e2
ACM
167 if (nr_cpus > 0)
168 cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
169 else
170 cpus = cpu_map__default_new();
c45c6ea2 171invalid:
60d567e2
ACM
172 free(tmp_cpus);
173out:
174 return cpus;
175}
176
9ae7d335
ACM
177size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
178{
179 int i;
180 size_t printed = fprintf(fp, "%d cpu%s: ",
181 map->nr, map->nr > 1 ? "s" : "");
182 for (i = 0; i < map->nr; ++i)
183 printed += fprintf(fp, "%s%d", i ? ", " : "", map->map[i]);
184
185 return printed + fprintf(fp, "\n");
186}
187
60d567e2
ACM
188struct cpu_map *cpu_map__dummy_new(void)
189{
190 struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
191
192 if (cpus != NULL) {
193 cpus->nr = 1;
194 cpus->map[0] = -1;
195 }
196
197 return cpus;
c45c6ea2 198}
915fce20
ACM
199
200void cpu_map__delete(struct cpu_map *map)
201{
202 free(map);
203}