Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/tools/perf/util/cpumap.c
10821 views
1
#include "util.h"
2
#include "../perf.h"
3
#include "cpumap.h"
4
#include <assert.h>
5
#include <stdio.h>
6
7
static struct cpu_map *cpu_map__default_new(void)
8
{
9
struct cpu_map *cpus;
10
int nr_cpus;
11
12
nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
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;
21
22
cpus->nr = nr_cpus;
23
}
24
25
return cpus;
26
}
27
28
static struct cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
29
{
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
41
static struct cpu_map *cpu_map__read_all_cpu_map(void)
42
{
43
struct cpu_map *cpus = NULL;
44
FILE *onlnf;
45
int nr_cpus = 0;
46
int *tmp_cpus = NULL, *tmp;
47
int max_entries = 0;
48
int n, cpu, prev;
49
char sep;
50
51
onlnf = fopen("/sys/devices/system/cpu/online", "r");
52
if (!onlnf)
53
return cpu_map__default_new();
54
55
sep = 0;
56
prev = -1;
57
for (;;) {
58
n = fscanf(onlnf, "%u%c", &cpu, &sep);
59
if (n <= 0)
60
break;
61
if (prev >= 0) {
62
int new_max = nr_cpus + cpu - prev - 1;
63
64
if (new_max >= max_entries) {
65
max_entries = new_max + MAX_NR_CPUS / 2;
66
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
67
if (tmp == NULL)
68
goto out_free_tmp;
69
tmp_cpus = tmp;
70
}
71
72
while (++prev < cpu)
73
tmp_cpus[nr_cpus++] = prev;
74
}
75
if (nr_cpus == max_entries) {
76
max_entries += MAX_NR_CPUS;
77
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
78
if (tmp == NULL)
79
goto out_free_tmp;
80
tmp_cpus = tmp;
81
}
82
83
tmp_cpus[nr_cpus++] = cpu;
84
if (n == 2 && sep == '-')
85
prev = cpu;
86
else
87
prev = -1;
88
if (n == 1 || sep == '\n')
89
break;
90
}
91
92
if (nr_cpus > 0)
93
cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
94
else
95
cpus = cpu_map__default_new();
96
out_free_tmp:
97
free(tmp_cpus);
98
fclose(onlnf);
99
return cpus;
100
}
101
102
struct cpu_map *cpu_map__new(const char *cpu_list)
103
{
104
struct cpu_map *cpus = NULL;
105
unsigned long start_cpu, end_cpu = 0;
106
char *p = NULL;
107
int i, nr_cpus = 0;
108
int *tmp_cpus = NULL, *tmp;
109
int max_entries = 0;
110
111
if (!cpu_list)
112
return cpu_map__read_all_cpu_map();
113
114
if (!isdigit(*cpu_list))
115
goto out;
116
117
while (isdigit(*cpu_list)) {
118
p = NULL;
119
start_cpu = strtoul(cpu_list, &p, 0);
120
if (start_cpu >= INT_MAX
121
|| (*p != '\0' && *p != ',' && *p != '-'))
122
goto invalid;
123
124
if (*p == '-') {
125
cpu_list = ++p;
126
p = NULL;
127
end_cpu = strtoul(cpu_list, &p, 0);
128
129
if (end_cpu >= INT_MAX || (*p != '\0' && *p != ','))
130
goto invalid;
131
132
if (end_cpu < start_cpu)
133
goto invalid;
134
} else {
135
end_cpu = start_cpu;
136
}
137
138
for (; start_cpu <= end_cpu; start_cpu++) {
139
/* check for duplicates */
140
for (i = 0; i < nr_cpus; i++)
141
if (tmp_cpus[i] == (int)start_cpu)
142
goto invalid;
143
144
if (nr_cpus == max_entries) {
145
max_entries += MAX_NR_CPUS;
146
tmp = realloc(tmp_cpus, max_entries * sizeof(int));
147
if (tmp == NULL)
148
goto invalid;
149
tmp_cpus = tmp;
150
}
151
tmp_cpus[nr_cpus++] = (int)start_cpu;
152
}
153
if (*p)
154
++p;
155
156
cpu_list = p;
157
}
158
159
if (nr_cpus > 0)
160
cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
161
else
162
cpus = cpu_map__default_new();
163
invalid:
164
free(tmp_cpus);
165
out:
166
return cpus;
167
}
168
169
struct cpu_map *cpu_map__dummy_new(void)
170
{
171
struct cpu_map *cpus = malloc(sizeof(*cpus) + sizeof(int));
172
173
if (cpus != NULL) {
174
cpus->nr = 1;
175
cpus->map[0] = -1;
176
}
177
178
return cpus;
179
}
180
181
void cpu_map__delete(struct cpu_map *map)
182
{
183
free(map);
184
}
185
186