1 /*
2 * Copyright © 2012-2019 Inria. All rights reserved.
3 * See COPYING in top-level directory.
4 */
5
6 #include <private/private.h>
7 #include <hwloc-calc.h>
8 #include <hwloc.h>
9
10 #include "misc.h"
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15
usage(const char * callname __hwloc_attribute_unused,FILE * where)16 void usage(const char *callname __hwloc_attribute_unused, FILE *where)
17 {
18 fprintf(where, "Usage: hwloc-annotate [options] <input.xml> <output.xml> <location> <annotation>\n");
19 fprintf(where, " <location> may be:\n");
20 fprintf(where, " all, root, <type>:<logicalindex>, <type>:all\n");
21 fprintf(where, " <annotation> may be:\n");
22 fprintf(where, " info <name> <value>\n");
23 fprintf(where, " misc <name>\n");
24 fprintf(where, " none\n");
25 fprintf(where, "Options:\n");
26 fprintf(where, " --ci\tClear existing infos\n");
27 fprintf(where, " --ri\tReplace or remove existing infos with same name (annotation must be info)\n");
28 fprintf(where, " --cu\tClear existing userdata\n");
29 }
30
31 static char *infoname = NULL, *infovalue = NULL;
32
33 static char *miscname = NULL;
34
35 static int clearinfos = 0;
36 static int replaceinfos = 0;
37 static int clearuserdata = 0;
38
apply(hwloc_topology_t topology,hwloc_obj_t obj)39 static void apply(hwloc_topology_t topology, hwloc_obj_t obj)
40 {
41 unsigned i,j;
42 if (clearinfos) {
43 /* this may be considered dangerous, applications should not modify objects directly */
44 for(i=0; i<obj->infos_count; i++) {
45 free(obj->infos[i].name);
46 free(obj->infos[i].value);
47 }
48 free(obj->infos);
49 obj->infos = NULL;
50 obj->infos_count = 0;
51 }
52 if (clearuserdata) {
53 hwloc_utils_userdata_free(obj);
54 }
55 if (infoname) {
56 if (replaceinfos) {
57 /* this may be considered dangerous, applications should not modify objects directly */
58 for(i=0, j=0; i<obj->infos_count; i++) {
59 if (!strcmp(infoname, obj->infos[i].name)) {
60 /* remove info */
61 free(obj->infos[i].name);
62 free(obj->infos[i].value);
63 obj->infos[i].name = NULL;
64 } else {
65 if (i != j) {
66 /* shift info to where it belongs */
67 obj->infos[j].name = obj->infos[i].name;
68 obj->infos[j].value = obj->infos[i].value;
69 }
70 j++;
71 }
72 }
73 obj->infos_count = j;
74 if (!j) {
75 free(obj->infos);
76 obj->infos = NULL;
77 }
78 }
79 if (infovalue)
80 hwloc_obj_add_info(obj, infoname, infovalue);
81 }
82 if (miscname)
83 hwloc_topology_insert_misc_object_by_parent(topology, obj, miscname);
84 }
85
apply_recursive(hwloc_topology_t topology,hwloc_obj_t obj)86 static void apply_recursive(hwloc_topology_t topology, hwloc_obj_t obj)
87 {
88 unsigned i;
89 for(i=0; i<obj->arity; i++)
90 apply_recursive(topology, obj->children[i]);
91 apply(topology, obj);
92 }
93
94 static void
hwloc_calc_process_location_annotate_cb(struct hwloc_calc_location_context_s * lcontext,void * _data __hwloc_attribute_unused,hwloc_obj_t obj)95 hwloc_calc_process_location_annotate_cb(struct hwloc_calc_location_context_s *lcontext,
96 void *_data __hwloc_attribute_unused,
97 hwloc_obj_t obj)
98 {
99 apply(lcontext->topology, obj);
100 }
101
main(int argc,char * argv[])102 int main(int argc, char *argv[])
103 {
104 hwloc_topology_t topology;
105 char *callname, *input, *output, *location;
106 unsigned topodepth;
107 int err;
108
109 putenv((char *) "HWLOC_XML_VERBOSE=1");
110
111 callname = argv[0];
112 /* skip argv[0], handle options */
113 argc--;
114 argv++;
115
116 while (argc && *argv[0] == '-') {
117 if (!strcmp(argv[0], "--ci"))
118 clearinfos = 1;
119 else if (!strcmp(argv[0], "--ri"))
120 replaceinfos = 1;
121 else if (!strcmp(argv[0], "--cu"))
122 clearuserdata = 1;
123 else {
124 fprintf(stderr, "Unrecognized options: %s\n", argv[0]);
125 usage(callname, stderr);
126 exit(EXIT_FAILURE);
127 }
128 argc--;
129 argv++;
130 }
131
132 if (argc < 3) {
133 usage(callname, stderr);
134 exit(EXIT_FAILURE);
135 }
136 input = argv[0];
137 output = argv[1];
138 location = argv[2];
139 argc -= 3;
140 argv += 3;
141
142 if (argc < 1) {
143 usage(callname, stderr);
144 exit(EXIT_FAILURE);
145 }
146 if (!strcmp(argv[0], "info")) {
147 if (argc < 2 || (!replaceinfos && argc < 3)) {
148 usage(callname, stderr);
149 exit(EXIT_FAILURE);
150 }
151 infoname = argv[1];
152 infovalue = argc >= 3 ? argv[2] : NULL;
153
154 } else if (!strcmp(argv[0], "misc")) {
155 if (argc < 2) {
156 usage(callname, stderr);
157 exit(EXIT_FAILURE);
158 }
159 miscname = argv[1];
160
161 } else if (!strcmp(argv[0], "none")) {
162 /* do nothing (maybe clear) */
163 } else {
164 fprintf(stderr, "Unrecognized annotation type: %s\n", argv[0]);
165 usage(callname, stderr);
166 exit(EXIT_FAILURE);
167 }
168
169 if (replaceinfos && !infoname) {
170 fprintf(stderr, "--ri missing a info name\n");
171 usage(callname, stderr);
172 exit(EXIT_FAILURE);
173 }
174
175 hwloc_topology_init(&topology);
176 hwloc_topology_set_flags(topology, HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM | HWLOC_TOPOLOGY_FLAG_WHOLE_IO | HWLOC_TOPOLOGY_FLAG_ICACHES);
177 err = hwloc_topology_set_xml(topology, input);
178 if (err < 0)
179 goto out_with_topology;
180
181 putenv((char *) "HWLOC_XML_USERDATA_NOT_DECODED=1");
182 hwloc_topology_set_userdata_import_callback(topology, hwloc_utils_userdata_import_cb);
183 hwloc_topology_set_userdata_export_callback(topology, hwloc_utils_userdata_export_cb);
184
185 err = hwloc_topology_load(topology);
186 if (err < 0)
187 goto out_with_topology;
188
189 topodepth = hwloc_topology_get_depth(topology);
190
191 if (!strcmp(location, "all")) {
192 apply_recursive(topology, hwloc_get_root_obj(topology));
193 } else if (!strcmp(location, "root")) {
194 apply(topology, hwloc_get_root_obj(topology));
195 } else {
196 size_t typelen;
197 typelen = strspn(location, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
198 if (typelen && (location[typelen] == ':' || location[typelen] == '=' || location[typelen] == '[')) {
199 struct hwloc_calc_location_context_s lcontext;
200 lcontext.topology = topology;
201 lcontext.topodepth = topodepth;
202 lcontext.only_hbm = -1;
203 lcontext.logical = 1;
204 lcontext.verbose = 0;
205 err = hwloc_calc_process_location(&lcontext, location, typelen,
206 hwloc_calc_process_location_annotate_cb, topology);
207 }
208 }
209
210 err = hwloc_topology_export_xml(topology, output);
211 if (err < 0)
212 goto out;
213
214 hwloc_utils_userdata_free_recursive(hwloc_get_root_obj(topology));
215 hwloc_topology_destroy(topology);
216 exit(EXIT_SUCCESS);
217
218 out_with_topology:
219 hwloc_utils_userdata_free_recursive(hwloc_get_root_obj(topology));
220 hwloc_topology_destroy(topology);
221 out:
222 exit(EXIT_FAILURE);
223 }
224