This source file includes following definitions.
- hwloc_look_darwin
- hwloc_set_darwin_hooks
- hwloc_darwin_component_instantiate
1
2
3
4
5
6
7
8
9
10
11
12
13
14 #include <private/autogen/config.h>
15
16 #include <sys/types.h>
17 #include <sys/sysctl.h>
18 #include <stdlib.h>
19 #include <inttypes.h>
20
21 #include <hwloc.h>
22 #include <private/private.h>
23 #include <private/debug.h>
24
25 static int
26 hwloc_look_darwin(struct hwloc_backend *backend)
27 {
28 struct hwloc_topology *topology = backend->topology;
29 int64_t _nprocs;
30 unsigned nprocs;
31 int64_t _npackages;
32 unsigned i, j, cpu;
33 struct hwloc_obj *obj;
34 size_t size;
35 int64_t l1dcachesize, l1icachesize;
36 int64_t cacheways[2];
37 int64_t l2cachesize;
38 int64_t l3cachesize;
39 int64_t cachelinesize;
40 int64_t memsize;
41 int64_t _tmp;
42 char cpumodel[64];
43 char cpuvendor[64];
44 char cpufamilynumber[20], cpumodelnumber[20], cpustepping[20];
45 int gotnuma = 0;
46 int gotnumamemory = 0;
47
48 if (topology->levels[0][0]->cpuset)
49
50 return -1;
51
52 hwloc_alloc_root_sets(topology->levels[0][0]);
53
54
55
56
57
58
59
60
61 if (hwloc_get_sysctlbyname("hw.logicalcpu", &_nprocs) || _nprocs <= 0)
62
63 if (hwloc_get_sysctlbyname("hw.ncpu", &_nprocs) || _nprocs <= 0)
64 return -1;
65
66 nprocs = _nprocs;
67 topology->support.discovery->pu = 1;
68
69 hwloc_debug("%u procs\n", nprocs);
70
71 size = sizeof(cpuvendor);
72 if (sysctlbyname("machdep.cpu.vendor", cpuvendor, &size, NULL, 0))
73 cpuvendor[0] = '\0';
74
75 size = sizeof(cpumodel);
76 if (sysctlbyname("machdep.cpu.brand_string", cpumodel, &size, NULL, 0))
77 cpumodel[0] = '\0';
78
79 if (hwloc_get_sysctlbyname("machdep.cpu.family", &_tmp))
80 cpufamilynumber[0] = '\0';
81 else
82 snprintf(cpufamilynumber, sizeof(cpufamilynumber), "%lld", (long long) _tmp);
83 if (hwloc_get_sysctlbyname("machdep.cpu.model", &_tmp))
84 cpumodelnumber[0] = '\0';
85 else
86 snprintf(cpumodelnumber, sizeof(cpumodelnumber), "%lld", (long long) _tmp);
87
88 if (hwloc_get_sysctlbyname("machdep.cpu.stepping", &_tmp))
89 cpustepping[0] = '\0';
90 else
91 snprintf(cpustepping, sizeof(cpustepping), "%lld", (long long) _tmp);
92
93 if (!hwloc_get_sysctlbyname("hw.packages", &_npackages) && _npackages > 0) {
94 unsigned npackages = _npackages;
95 int64_t _cores_per_package;
96 unsigned cores_per_package;
97 int64_t _logical_per_package;
98 unsigned logical_per_package;
99
100 hwloc_debug("%u packages\n", npackages);
101
102 if (!hwloc_get_sysctlbyname("machdep.cpu.thread_count", &_logical_per_package) && _logical_per_package > 0)
103
104 logical_per_package = _logical_per_package;
105 else if (!hwloc_get_sysctlbyname("machdep.cpu.logical_per_package", &_logical_per_package) && _logical_per_package > 0)
106
107
108
109 logical_per_package = _logical_per_package;
110 else
111
112 logical_per_package = nprocs / npackages;
113
114 hwloc_debug("%u threads per package\n", logical_per_package);
115
116 if (nprocs == npackages * logical_per_package
117 && hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_PACKAGE))
118 for (i = 0; i < npackages; i++) {
119 obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PACKAGE, i);
120 obj->cpuset = hwloc_bitmap_alloc();
121 for (cpu = i*logical_per_package; cpu < (i+1)*logical_per_package; cpu++)
122 hwloc_bitmap_set(obj->cpuset, cpu);
123
124 hwloc_debug_1arg_bitmap("package %u has cpuset %s\n",
125 i, obj->cpuset);
126
127 if (cpuvendor[0] != '\0')
128 hwloc_obj_add_info(obj, "CPUVendor", cpuvendor);
129 if (cpumodel[0] != '\0')
130 hwloc_obj_add_info(obj, "CPUModel", cpumodel);
131 if (cpufamilynumber[0] != '\0')
132 hwloc_obj_add_info(obj, "CPUFamilyNumber", cpufamilynumber);
133 if (cpumodelnumber[0] != '\0')
134 hwloc_obj_add_info(obj, "CPUModelNumber", cpumodelnumber);
135 if (cpustepping[0] != '\0')
136 hwloc_obj_add_info(obj, "CPUStepping", cpustepping);
137
138 hwloc_insert_object_by_cpuset(topology, obj);
139 }
140 else {
141 if (cpuvendor[0] != '\0')
142 hwloc_obj_add_info(topology->levels[0][0], "CPUVendor", cpuvendor);
143 if (cpumodel[0] != '\0')
144 hwloc_obj_add_info(topology->levels[0][0], "CPUModel", cpumodel);
145 if (cpufamilynumber[0] != '\0')
146 hwloc_obj_add_info(topology->levels[0][0], "CPUFamilyNumber", cpufamilynumber);
147 if (cpumodelnumber[0] != '\0')
148 hwloc_obj_add_info(topology->levels[0][0], "CPUModelNumber", cpumodelnumber);
149 if (cpustepping[0] != '\0')
150 hwloc_obj_add_info(topology->levels[0][0], "CPUStepping", cpustepping);
151 }
152
153 if (!hwloc_get_sysctlbyname("machdep.cpu.core_count", &_cores_per_package) && _cores_per_package > 0)
154
155 cores_per_package = _cores_per_package;
156 else if (!hwloc_get_sysctlbyname("machdep.cpu.cores_per_package", &_cores_per_package) && _cores_per_package > 0)
157
158
159
160 cores_per_package = _cores_per_package;
161 else
162
163 cores_per_package = 0;
164
165 if (cores_per_package > 0
166 && hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_CORE)) {
167 hwloc_debug("%u cores per package\n", cores_per_package);
168
169 if (!(logical_per_package % cores_per_package))
170 for (i = 0; i < npackages * cores_per_package; i++) {
171 obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_CORE, i);
172 obj->cpuset = hwloc_bitmap_alloc();
173 for (cpu = i*(logical_per_package/cores_per_package);
174 cpu < (i+1)*(logical_per_package/cores_per_package);
175 cpu++)
176 hwloc_bitmap_set(obj->cpuset, cpu);
177
178 hwloc_debug_1arg_bitmap("core %u has cpuset %s\n",
179 i, obj->cpuset);
180 hwloc_insert_object_by_cpuset(topology, obj);
181 }
182 }
183 } else {
184 if (cpuvendor[0] != '\0')
185 hwloc_obj_add_info(topology->levels[0][0], "CPUVendor", cpuvendor);
186 if (cpumodel[0] != '\0')
187 hwloc_obj_add_info(topology->levels[0][0], "CPUModel", cpumodel);
188 if (cpufamilynumber[0] != '\0')
189 hwloc_obj_add_info(topology->levels[0][0], "CPUFamilyNumber", cpufamilynumber);
190 if (cpumodelnumber[0] != '\0')
191 hwloc_obj_add_info(topology->levels[0][0], "CPUModelNumber", cpumodelnumber);
192 if (cpustepping[0] != '\0')
193 hwloc_obj_add_info(topology->levels[0][0], "CPUStepping", cpustepping);
194 }
195
196 if (hwloc_get_sysctlbyname("hw.l1dcachesize", &l1dcachesize))
197 l1dcachesize = 0;
198
199 if (hwloc_get_sysctlbyname("hw.l1icachesize", &l1icachesize))
200 l1icachesize = 0;
201
202 if (hwloc_get_sysctlbyname("hw.l2cachesize", &l2cachesize))
203 l2cachesize = 0;
204
205 if (hwloc_get_sysctlbyname("hw.l3cachesize", &l3cachesize))
206 l3cachesize = 0;
207
208 if (hwloc_get_sysctlbyname("machdep.cpu.cache.L1_associativity", &cacheways[0]))
209 cacheways[0] = 0;
210 else if (cacheways[0] == 0xff)
211 cacheways[0] = -1;
212
213 if (hwloc_get_sysctlbyname("machdep.cpu.cache.L2_associativity", &cacheways[1]))
214 cacheways[1] = 0;
215 else if (cacheways[1] == 0xff)
216 cacheways[1] = -1;
217
218 if (hwloc_get_sysctlbyname("hw.cachelinesize", &cachelinesize))
219 cachelinesize = 0;
220
221 if (hwloc_get_sysctlbyname("hw.memsize", &memsize))
222 memsize = 0;
223
224 if (!sysctlbyname("hw.cacheconfig", NULL, &size, NULL, 0)) {
225 unsigned n = size / sizeof(uint32_t);
226 uint64_t cacheconfig[n];
227 uint64_t cachesize[n];
228 uint32_t cacheconfig32[n];
229
230 if ((!sysctlbyname("hw.cacheconfig", cacheconfig, &size, NULL, 0))) {
231
232
233
234 if (cacheconfig[0] > 0xFFFFFFFFUL) {
235 memcpy(cacheconfig32, cacheconfig, size);
236 for (i = 0 ; i < size / sizeof(uint32_t); i++)
237 cacheconfig[i] = cacheconfig32[i];
238 }
239
240 memset(cachesize, 0, sizeof(uint64_t) * n);
241 size = sizeof(uint64_t) * n;
242 if (sysctlbyname("hw.cachesize", cachesize, &size, NULL, 0)) {
243 if (n > 0)
244 cachesize[0] = memsize;
245 if (n > 1)
246 cachesize[1] = l1dcachesize;
247 if (n > 2)
248 cachesize[2] = l2cachesize;
249 if (n > 3)
250 cachesize[3] = l3cachesize;
251 }
252
253 hwloc_debug("%s", "caches");
254 for (i = 0; i < n && cacheconfig[i]; i++)
255 hwloc_debug(" %"PRIu64"(%"PRIu64"kB)", cacheconfig[i], cachesize[i] / 1024);
256
257
258 n = i;
259 hwloc_debug("\n%u cache levels\n", n - 1);
260
261
262 for (i = 0; i < n; i++) {
263
264 for (j = 0; j < (nprocs / cacheconfig[i]); j++) {
265 if (!i) {
266 obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_NUMANODE, j);
267 obj->nodeset = hwloc_bitmap_alloc();
268 hwloc_bitmap_set(obj->nodeset, j);
269 gotnuma++;
270 } else {
271 obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1CACHE+i-1, HWLOC_UNKNOWN_INDEX);
272 }
273 obj->cpuset = hwloc_bitmap_alloc();
274 for (cpu = j*cacheconfig[i];
275 cpu < ((j+1)*cacheconfig[i]);
276 cpu++)
277 hwloc_bitmap_set(obj->cpuset, cpu);
278
279 if (i == 1 && l1icachesize
280 && hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1ICACHE)) {
281
282
283 hwloc_obj_t l1i = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1ICACHE, HWLOC_UNKNOWN_INDEX);
284 l1i->cpuset = hwloc_bitmap_dup(obj->cpuset);
285 hwloc_debug_1arg_bitmap("L1icache %u has cpuset %s\n",
286 j, l1i->cpuset);
287 l1i->attr->cache.depth = i;
288 l1i->attr->cache.size = l1icachesize;
289 l1i->attr->cache.linesize = cachelinesize;
290 l1i->attr->cache.associativity = 0;
291 l1i->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
292
293 hwloc_insert_object_by_cpuset(topology, l1i);
294 }
295 if (i) {
296 hwloc_debug_2args_bitmap("L%ucache %u has cpuset %s\n",
297 i, j, obj->cpuset);
298 obj->attr->cache.depth = i;
299 obj->attr->cache.size = cachesize[i];
300 obj->attr->cache.linesize = cachelinesize;
301 if (i <= sizeof(cacheways) / sizeof(cacheways[0]))
302 obj->attr->cache.associativity = cacheways[i-1];
303 else
304 obj->attr->cache.associativity = 0;
305 if (i == 1 && l1icachesize)
306 obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
307 else
308 obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
309 } else {
310 hwloc_debug_1arg_bitmap("node %u has cpuset %s\n",
311 j, obj->cpuset);
312 if (cachesize[i]) {
313 obj->attr->numanode.local_memory = cachesize[i];
314 gotnumamemory++;
315 }
316 obj->attr->numanode.page_types_len = 2;
317 obj->attr->numanode.page_types = malloc(2*sizeof(*obj->attr->numanode.page_types));
318 memset(obj->attr->numanode.page_types, 0, 2*sizeof(*obj->attr->numanode.page_types));
319 obj->attr->numanode.page_types[0].size = hwloc_getpagesize();
320 #if HAVE_DECL__SC_LARGE_PAGESIZE
321 obj->attr->numanode.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE);
322 #endif
323 }
324
325 if (hwloc_filter_check_keep_object_type(topology, obj->type))
326 hwloc_insert_object_by_cpuset(topology, obj);
327 else
328 hwloc_free_unlinked_object(obj);
329 }
330 }
331 }
332 }
333
334 if (gotnuma)
335 topology->support.discovery->numa = 1;
336 if (gotnumamemory)
337 topology->support.discovery->numa = 1;
338
339
340 hwloc_setup_pu_level(topology, nprocs);
341
342 hwloc_obj_add_info(topology->levels[0][0], "Backend", "Darwin");
343 hwloc_add_uname_info(topology, NULL);
344 return 0;
345 }
346
347 void
348 hwloc_set_darwin_hooks(struct hwloc_binding_hooks *hooks __hwloc_attribute_unused,
349 struct hwloc_topology_support *support __hwloc_attribute_unused)
350 {
351 }
352
353 static struct hwloc_backend *
354 hwloc_darwin_component_instantiate(struct hwloc_disc_component *component,
355 const void *_data1 __hwloc_attribute_unused,
356 const void *_data2 __hwloc_attribute_unused,
357 const void *_data3 __hwloc_attribute_unused)
358 {
359 struct hwloc_backend *backend;
360 backend = hwloc_backend_alloc(component);
361 if (!backend)
362 return NULL;
363 backend->discover = hwloc_look_darwin;
364 return backend;
365 }
366
367 static struct hwloc_disc_component hwloc_darwin_disc_component = {
368 HWLOC_DISC_COMPONENT_TYPE_CPU,
369 "darwin",
370 HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
371 hwloc_darwin_component_instantiate,
372 50,
373 1,
374 NULL
375 };
376
377 const struct hwloc_component hwloc_darwin_component = {
378 HWLOC_COMPONENT_ABI,
379 NULL, NULL,
380 HWLOC_COMPONENT_TYPE_DISC,
381 0,
382 &hwloc_darwin_disc_component
383 };