1 /*
2 * Copyright © 2009 CNRS
3 * Copyright © 2009-2021 Inria. All rights reserved.
4 * Copyright © 2009-2010 Université Bordeaux
5 * Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
6 * See COPYING in top-level directory.
7 */
8
9 #include "private/autogen/config.h"
10 #include "hwloc.h"
11 #include "misc.h"
12
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif
16
usage(const char * callname __hwloc_attribute_unused,FILE * where)17 void usage(const char *callname __hwloc_attribute_unused, FILE *where)
18 {
19 fprintf(where, "Usage: hwloc-distrib [options] number\n");
20 fprintf(where, "Distribution options:\n");
21 fprintf(where, " --ignore <type> Ignore objects of the given type\n");
22 fprintf(where, " --from <type> Distribute starting from objects of the given type\n");
23 fprintf(where, " --to <type> Distribute down to objects of the given type\n");
24 fprintf(where, " --at <type> Distribute among objects of the given type\n");
25 fprintf(where, " --reverse Distribute by starting from last objects\n");
26 fprintf(where, "Input topology options:\n");
27 fprintf(where, " --restrict [nodeset=]<bitmap>\n");
28 fprintf(where, " Restrict the topology to some processors or NUMA nodes.\n");
29 fprintf(where, " --restrict-flags <n> Set the flags to be used during restrict\n");
30 fprintf(where, " --disallowed Include objects disallowed by administrative limitations\n");
31 hwloc_utils_input_format_usage(where, 0);
32 fprintf(where, "Formatting options:\n");
33 fprintf(where, " --single Singlify each output to a single CPU\n");
34 fprintf(where, " --taskset Show taskset-specific cpuset strings\n");
35 fprintf(where, "Miscellaneous options:\n");
36 fprintf(where, " -v --verbose Show verbose messages\n");
37 fprintf(where, " --version Report version and exit\n");
38 fprintf(where, " -h --help Show this usage\n");
39 }
40
main(int argc,char * argv[])41 int main(int argc, char *argv[])
42 {
43 long n = -1;
44 char *callname;
45 char *input = NULL;
46 enum hwloc_utils_input_format input_format = HWLOC_UTILS_INPUT_DEFAULT;
47 int taskset = 0;
48 int singlify = 0;
49 int verbose = 0;
50 char *restrictstring = NULL;
51 const char *from_type = NULL, *to_type = NULL;
52 hwloc_topology_t topology;
53 unsigned long flags = HWLOC_TOPOLOGY_FLAG_IMPORT_SUPPORT;
54 unsigned long restrict_flags = 0;
55 unsigned long dflags = 0;
56 int opt;
57 int err;
58
59 callname = strrchr(argv[0], '/');
60 if (!callname)
61 callname = argv[0];
62 else
63 callname++;
64
65 /* skip argv[0], handle options */
66 argv++;
67 argc--;
68
69 hwloc_utils_check_api_version(callname);
70
71 /* enable verbose backends */
72 if (!getenv("HWLOC_XML_VERBOSE"))
73 putenv((char *) "HWLOC_XML_VERBOSE=1");
74 if (!getenv("HWLOC_SYNTHETIC_VERBOSE"))
75 putenv((char *) "HWLOC_SYNTHETIC_VERBOSE=1");
76
77 hwloc_topology_init(&topology);
78
79 while (argc >= 1) {
80 if (!strcmp(argv[0], "--")) {
81 argc--;
82 argv++;
83 break;
84 }
85
86 opt = 0;
87
88 if (*argv[0] == '-') {
89 if (!strcmp(argv[0], "--single")) {
90 singlify = 1;
91 goto next;
92 }
93 if (!strcmp(argv[0], "--taskset")) {
94 taskset = 1;
95 goto next;
96 }
97 if (!strcmp(argv[0], "-v") || !strcmp(argv[0], "--verbose")) {
98 verbose = 1;
99 goto next;
100 }
101 if (!strcmp (argv[0], "--disallowed") || !strcmp (argv[0], "--whole-system")) {
102 flags |= HWLOC_TOPOLOGY_FLAG_INCLUDE_DISALLOWED;
103 goto next;
104 }
105 if (!strcmp(argv[0], "-h") || !strcmp(argv[0], "--help")) {
106 usage(callname, stdout);
107 return EXIT_SUCCESS;
108 }
109 if (hwloc_utils_lookup_input_option(argv, argc, &opt,
110 &input, &input_format,
111 callname)) {
112 opt = 1;
113 goto next;
114 }
115 else if (!strcmp (argv[0], "--ignore")) {
116 hwloc_obj_type_t type;
117 if (argc < 2) {
118 usage(callname, stderr);
119 exit(EXIT_FAILURE);
120 }
121 if (hwloc_type_sscanf(argv[1], &type, NULL, 0) < 0)
122 fprintf(stderr, "Unsupported type `%s' passed to --ignore, ignoring.\n", argv[1]);
123 else
124 hwloc_topology_set_type_filter(topology, type, HWLOC_TYPE_FILTER_KEEP_NONE);
125 opt = 1;
126 goto next;
127 }
128 else if (!strcmp (argv[0], "--from")) {
129 if (argc < 2) {
130 usage(callname, stderr);
131 exit(EXIT_FAILURE);
132 }
133 from_type = argv[1];
134 opt = 1;
135 goto next;
136 }
137 else if (!strcmp (argv[0], "--to")) {
138 if (argc < 2) {
139 usage(callname, stderr);
140 exit(EXIT_FAILURE);
141 }
142 to_type = argv[1];
143 opt = 1;
144 goto next;
145 }
146 else if (!strcmp (argv[0], "--at")) {
147 if (argc < 2) {
148 usage(callname, stderr);
149 exit(EXIT_FAILURE);
150 }
151 from_type = to_type = argv[1];
152 opt = 1;
153 goto next;
154 }
155 else if (!strcmp (argv[0], "--reverse")) {
156 dflags |= HWLOC_DISTRIB_FLAG_REVERSE;
157 goto next;
158 }
159 else if (!strcmp (argv[0], "--restrict")) {
160 if (argc < 2) {
161 usage (callname, stderr);
162 exit(EXIT_FAILURE);
163 }
164 if(strncmp(argv[1], "nodeset=", 8)) {
165 restrictstring = strdup(argv[1]);
166 } else {
167 restrictstring = strdup(argv[1]+8);
168 restrict_flags |= HWLOC_RESTRICT_FLAG_BYNODESET;
169 }
170 opt = 1;
171 goto next;
172 }
173 else if (!strcmp (argv[0], "--restrict-flags")) {
174 if (argc < 2) {
175 usage (callname, stderr);
176 exit(EXIT_FAILURE);
177 }
178 restrict_flags = hwloc_utils_parse_restrict_flags(argv[1]);
179 opt = 1;
180 goto next;
181 }
182 else if (!strcmp (argv[0], "--version")) {
183 printf("%s %s\n", callname, HWLOC_VERSION);
184 exit(EXIT_SUCCESS);
185 }
186
187 fprintf (stderr, "Unrecognized option: %s\n", argv[0]);
188 usage(callname, stderr);
189 return EXIT_FAILURE;
190 }
191
192 if (n != -1) {
193 fprintf(stderr,"duplicate number\n");
194 usage(callname, stderr);
195 return EXIT_FAILURE;
196 }
197 n = atol(argv[0]);
198
199 next:
200 argc -= opt+1;
201 argv += opt+1;
202 }
203
204 if (n == -1) {
205 fprintf(stderr,"need a number\n");
206 usage(callname, stderr);
207 return EXIT_FAILURE;
208 }
209
210 if (verbose)
211 fprintf(stderr, "distributing %ld\n", n);
212
213 {
214 unsigned i;
215 int from_depth, to_depth;
216 unsigned chunks;
217 hwloc_bitmap_t *cpuset;
218
219 cpuset = malloc(n * sizeof(hwloc_bitmap_t));
220
221 if (input) {
222 err = hwloc_utils_enable_input_format(topology, flags, input, &input_format, verbose, callname);
223 if (err) {
224 free(cpuset);
225 return EXIT_FAILURE;
226 }
227 }
228 hwloc_topology_set_flags(topology, flags);
229 err = hwloc_topology_load(topology);
230 if (err < 0) {
231 free(cpuset);
232 return EXIT_FAILURE;
233 }
234
235 if (restrictstring) {
236 hwloc_bitmap_t restrictset = hwloc_bitmap_alloc();
237 hwloc_bitmap_sscanf(restrictset, restrictstring);
238 err = hwloc_topology_restrict (topology, restrictset, restrict_flags);
239 if (err) {
240 perror("Restricting the topology");
241 /* FALLTHRU */
242 }
243 hwloc_bitmap_free(restrictset);
244 free(restrictstring);
245 }
246
247 from_depth = 0;
248 if (from_type) {
249 if (hwloc_type_sscanf_as_depth(from_type, NULL, topology, &from_depth) < 0 || from_depth < 0) {
250 fprintf(stderr, "Unsupported or unavailable type `%s' passed to --from, ignoring.\n", from_type);
251 return EXIT_FAILURE;
252 }
253 }
254
255 to_depth = INT_MAX;
256 if (to_type) {
257 if (hwloc_type_sscanf_as_depth(to_type, NULL, topology, &to_depth) < 0 || to_depth < 0) {
258 fprintf(stderr, "Unsupported or unavailable type `%s' passed to --to, ignoring.\n", to_type);
259 return EXIT_FAILURE;
260 }
261 }
262
263 chunks = hwloc_get_nbobjs_by_depth(topology, from_depth);
264 {
265 hwloc_obj_t *roots;
266
267 roots = malloc(chunks * sizeof(hwloc_obj_t));
268
269 for (i = 0; i < chunks; i++)
270 roots[i] = hwloc_get_obj_by_depth(topology, from_depth, i);
271
272 hwloc_distrib(topology, roots, chunks, cpuset, n, to_depth, dflags);
273
274 for (i = 0; (long) i < n; i++) {
275 char *str = NULL;
276 if (singlify) {
277 if (dflags & HWLOC_DISTRIB_FLAG_REVERSE) {
278 unsigned last = hwloc_bitmap_last(cpuset[i]);
279 hwloc_bitmap_only(cpuset[i], last);
280 } else {
281 hwloc_bitmap_singlify(cpuset[i]);
282 }
283 }
284 if (taskset)
285 hwloc_bitmap_taskset_asprintf(&str, cpuset[i]);
286 else
287 hwloc_bitmap_asprintf(&str, cpuset[i]);
288 printf("%s\n", str);
289 free(str);
290 hwloc_bitmap_free(cpuset[i]);
291 }
292
293 free(roots);
294 }
295
296 free(cpuset);
297 }
298
299 hwloc_topology_destroy(topology);
300
301 return EXIT_SUCCESS;
302 }
303