@@ -1936,8 +1936,23 @@ hwloc__xml_export_object_contents (hwloc__xml_export_state_t state, hwloc_topolo
1936
1936
}
1937
1937
1938
1938
if (obj -> cpuset ) {
1939
- if (v1export && obj -> type == HWLOC_OBJ_NUMANODE && obj -> sibling_rank > 0 ) {
1940
- /* v1 non-first NUMA nodes have empty cpusets */
1939
+ int empty_cpusets = 0 ;
1940
+
1941
+ if (v1export && obj -> type == HWLOC_OBJ_NUMANODE ) {
1942
+ /* walk up this memory hierarchy to find-out if we are the first numa node.
1943
+ * v1 non-first NUMA nodes have empty cpusets.
1944
+ */
1945
+ hwloc_obj_t parent = obj ;
1946
+ while (!hwloc_obj_type_is_normal (parent -> type )) {
1947
+ if (parent -> sibling_rank > 0 ) {
1948
+ empty_cpusets = 1 ;
1949
+ break ;
1950
+ }
1951
+ parent = parent -> parent ;
1952
+ }
1953
+ }
1954
+
1955
+ if (empty_cpusets ) {
1941
1956
state -> new_prop (state , "cpuset" , "0x0" );
1942
1957
state -> new_prop (state , "online_cpuset" , "0x0" );
1943
1958
state -> new_prop (state , "complete_cpuset" , "0x0" );
@@ -2216,13 +2231,90 @@ hwloc__xml_v2export_object (hwloc__xml_export_state_t parentstate, hwloc_topolog
2216
2231
static void
2217
2232
hwloc__xml_v1export_object (hwloc__xml_export_state_t parentstate , hwloc_topology_t topology , hwloc_obj_t obj , unsigned long flags );
2218
2233
2234
+ static hwloc_obj_t
2235
+ hwloc__xml_v1export_object_next_numanode (hwloc_obj_t obj , hwloc_obj_t cur )
2236
+ {
2237
+ hwloc_obj_t parent ;
2238
+
2239
+ if (!cur ) {
2240
+ /* first numa node is on the very bottom left */
2241
+ cur = obj -> memory_first_child ;
2242
+ goto find_first ;
2243
+ }
2244
+
2245
+ /* walk-up until there's a next sibling */
2246
+ parent = cur ;
2247
+ while (1 ) {
2248
+ if (parent -> next_sibling ) {
2249
+ /* found a next sibling, we'll walk down-left from there */
2250
+ cur = parent -> next_sibling ;
2251
+ break ;
2252
+ }
2253
+ parent = parent -> parent ;
2254
+ if (parent == obj )
2255
+ return NULL ;
2256
+ }
2257
+
2258
+ find_first :
2259
+ while (cur -> type != HWLOC_OBJ_NUMANODE )
2260
+ cur = cur -> memory_first_child ;
2261
+ assert (cur );
2262
+ return cur ;
2263
+ }
2264
+
2265
+ static unsigned
2266
+ hwloc__xml_v1export_object_list_numanodes (hwloc_obj_t obj , hwloc_obj_t * first_p , hwloc_obj_t * * nodes_p )
2267
+ {
2268
+ hwloc_obj_t * nodes , cur ;
2269
+ unsigned nr ;
2270
+
2271
+ if (!obj -> memory_first_child ) {
2272
+ * first_p = NULL ;
2273
+ * nodes_p = NULL ;
2274
+ return 0 ;
2275
+ }
2276
+ /* we're sure there's at least one numa node */
2277
+
2278
+ nr = hwloc_bitmap_weight (obj -> nodeset );
2279
+ assert (nr > 0 );
2280
+ /* these are local nodes, but some of them may be attached above instead of here */
2281
+
2282
+ nodes = calloc (nr , sizeof (* nodes ));
2283
+ if (!nodes ) {
2284
+ /* only return the first node */
2285
+ cur = hwloc__xml_v1export_object_next_numanode (obj , NULL );
2286
+ assert (cur );
2287
+ * first_p = cur ;
2288
+ * nodes_p = NULL ;
2289
+ return 1 ;
2290
+ }
2291
+
2292
+ nr = 0 ;
2293
+ cur = NULL ;
2294
+ while (1 ) {
2295
+ cur = hwloc__xml_v1export_object_next_numanode (obj , cur );
2296
+ if (!cur )
2297
+ break ;
2298
+ nodes [nr ++ ] = cur ;
2299
+ }
2300
+
2301
+ * first_p = nodes [0 ];
2302
+ * nodes_p = nodes ;
2303
+ return nr ;
2304
+ }
2305
+
2219
2306
static void
2220
2307
hwloc__xml_v1export_object_with_memory (hwloc__xml_export_state_t parentstate , hwloc_topology_t topology , hwloc_obj_t obj , unsigned long flags )
2221
2308
{
2222
2309
struct hwloc__xml_export_state_s gstate , mstate , ostate , * state = parentstate ;
2223
2310
hwloc_obj_t child ;
2311
+ unsigned nr_numanodes ;
2312
+ hwloc_obj_t * numanodes , first_numanode ;
2313
+ unsigned i ;
2224
2314
2225
- if (obj -> parent -> arity > 1 && obj -> memory_arity > 1 && parentstate -> global -> v1_memory_group ) {
2315
+ nr_numanodes = hwloc__xml_v1export_object_list_numanodes (obj , & first_numanode , & numanodes );
2316
+
2317
+ if (obj -> parent -> arity > 1 && nr_numanodes > 1 && parentstate -> global -> v1_memory_group ) {
2226
2318
/* child has sibling, we must add a Group around those memory children */
2227
2319
hwloc_obj_t group = parentstate -> global -> v1_memory_group ;
2228
2320
parentstate -> new_child (parentstate , & gstate , "object" );
@@ -2239,10 +2331,8 @@ hwloc__xml_v1export_object_with_memory(hwloc__xml_export_state_t parentstate, hw
2239
2331
}
2240
2332
2241
2333
/* export first memory child */
2242
- child = obj -> memory_first_child ;
2243
- assert (child -> type == HWLOC_OBJ_NUMANODE );
2244
2334
state -> new_child (state , & mstate , "object" );
2245
- hwloc__xml_export_object_contents (& mstate , topology , child , flags );
2335
+ hwloc__xml_export_object_contents (& mstate , topology , first_numanode , flags );
2246
2336
2247
2337
/* then the actual object */
2248
2338
mstate .new_child (& mstate , & ostate , "object" );
@@ -2261,9 +2351,10 @@ hwloc__xml_v1export_object_with_memory(hwloc__xml_export_state_t parentstate, hw
2261
2351
mstate .end_object (& mstate , "object" );
2262
2352
2263
2353
/* now other memory children */
2264
- for_each_memory_child (child , obj )
2265
- if (child -> sibling_rank > 0 )
2266
- hwloc__xml_v1export_object (state , topology , child , flags );
2354
+ for (i = 1 ; i < nr_numanodes ; i ++ )
2355
+ hwloc__xml_v1export_object (state , topology , numanodes [i ], flags );
2356
+
2357
+ free (numanodes );
2267
2358
2268
2359
if (state == & gstate ) {
2269
2360
/* close group if any */
@@ -2351,18 +2442,22 @@ hwloc__xml_export_topology(hwloc__xml_export_state_t state, hwloc_topology_t top
2351
2442
hwloc_obj_t root = hwloc_get_root_obj (topology );
2352
2443
2353
2444
if (flags & HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1 ) {
2354
- if (root -> memory_first_child ) {
2445
+ hwloc_obj_t * numanodes , first_numanode ;
2446
+ unsigned nr_numanodes ;
2447
+
2448
+ nr_numanodes = hwloc__xml_v1export_object_list_numanodes (root , & first_numanode , & numanodes );
2449
+
2450
+ if (nr_numanodes ) {
2355
2451
/* we don't use hwloc__xml_v1export_object_with_memory() because we want/can keep root above the numa node */
2356
2452
struct hwloc__xml_export_state_s rstate , mstate ;
2357
2453
hwloc_obj_t child ;
2454
+ unsigned i ;
2358
2455
/* export the root */
2359
2456
state -> new_child (state , & rstate , "object" );
2360
2457
hwloc__xml_export_object_contents (& rstate , topology , root , flags );
2361
2458
/* export first memory child */
2362
- child = root -> memory_first_child ;
2363
- assert (child -> type == HWLOC_OBJ_NUMANODE );
2364
2459
rstate .new_child (& rstate , & mstate , "object" );
2365
- hwloc__xml_export_object_contents (& mstate , topology , child , flags );
2460
+ hwloc__xml_export_object_contents (& mstate , topology , first_numanode , flags );
2366
2461
/* then its normal/io/misc children */
2367
2462
for_each_child (child , root )
2368
2463
hwloc__xml_v1export_object (& mstate , topology , child , flags );
@@ -2373,15 +2468,16 @@ hwloc__xml_export_topology(hwloc__xml_export_state_t state, hwloc_topology_t top
2373
2468
/* close first memory child */
2374
2469
mstate .end_object (& mstate , "object" );
2375
2470
/* now other memory children */
2376
- for_each_memory_child (child , root )
2377
- if (child -> sibling_rank > 0 )
2378
- hwloc__xml_v1export_object (& rstate , topology , child , flags );
2471
+ for (i = 1 ; i < nr_numanodes ; i ++ )
2472
+ hwloc__xml_v1export_object (& rstate , topology , numanodes [i ], flags );
2379
2473
/* close the root */
2380
2474
rstate .end_object (& rstate , "object" );
2381
2475
} else {
2382
2476
hwloc__xml_v1export_object (state , topology , root , flags );
2383
2477
}
2384
2478
2479
+ free (numanodes );
2480
+
2385
2481
} else {
2386
2482
hwloc__xml_v2export_object (state , topology , root , flags );
2387
2483
hwloc__xml_v2export_distances (state , topology );
0 commit comments