OpenMPI  0.1.1
linux-libnuma.h
Go to the documentation of this file.
1 /*
2  * Copyright © 2009 CNRS
3  * Copyright © 2009-2010 inria. All rights reserved.
4  * Copyright © 2009-2010 Université Bordeaux 1
5  * See COPYING in top-level directory.
6  */
7 
8 /** \file
9  * \brief Macros to help interaction between hwloc and Linux libnuma.
10  *
11  * Applications that use both Linux libnuma and hwloc may want to
12  * include this file so as to ease conversion between their respective types.
13  *
14  * This helper also offers a consistent behavior on non-NUMA machines
15  * or non-NUMA-aware kernels by assuming that the machines have a single
16  * NUMA node.
17  *
18  * \note The behavior of libnuma is undefined if the kernel is not NUMA-aware.
19  * (when CONFIG_NUMA is not set in the kernel configuration).
20  * This helper and libnuma may thus not be strictly compatible in this case,
21  * which may be detected by checking whether numa_available() returns -1.
22  */
23 
24 #ifndef HWLOC_LINUX_LIBNUMA_H
25 #define HWLOC_LINUX_LIBNUMA_H
26 
27 #include <hwloc.h>
28 #include <numa.h>
29 
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 
36 /** \defgroup hwlocality_linux_libnuma_ulongs Helpers for manipulating Linux libnuma unsigned long masks
37  * @{
38  */
39 
40 
41 /** \brief Convert hwloc CPU set \p cpuset into the array of unsigned long \p mask
42  *
43  * \p mask is the array of unsigned long that will be filled.
44  * \p maxnode contains the maximal node number that may be stored in \p mask.
45  * \p maxnode will be set to the maximal node number that was found, plus one.
46  *
47  * This function may be used before calling set_mempolicy, mbind, migrate_pages
48  * or any other function that takes an array of unsigned long and a maximal
49  * node number as input parameter.
50  */
51 static __hwloc_inline int
53  unsigned long *mask, unsigned long *maxnode)
54 {
55  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
56  unsigned long outmaxnode = -1;
57 
58  /* round-up to the next ulong and clear all bytes */
59  *maxnode = (*maxnode + 8*sizeof(*mask) - 1) & ~(8*sizeof(*mask) - 1);
60  memset(mask, 0, *maxnode/8);
61 
62  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
63  hwloc_obj_t node = NULL;
64  while ((node = hwloc_get_next_obj_covering_cpuset_by_type(topology, cpuset, HWLOC_OBJ_NODE, node)) != NULL) {
65  if (node->os_index >= *maxnode)
66  continue;
67  mask[node->os_index/sizeof(*mask)/8] |= 1UL << (node->os_index % (sizeof(*mask)*8));
68  if (outmaxnode == (unsigned long) -1 || outmaxnode < node->os_index)
69  outmaxnode = node->os_index;
70  }
71 
72  } else {
73  /* if no numa, libnuma assumes we have a single node */
74  if (!hwloc_bitmap_iszero(cpuset)) {
75  mask[0] = 1;
76  outmaxnode = 0;
77  }
78  }
79 
80  *maxnode = outmaxnode+1;
81  return 0;
82 }
83 
84 /** \brief Convert hwloc NUMA node set \p nodeset into the array of unsigned long \p mask
85  *
86  * \p mask is the array of unsigned long that will be filled.
87  * \p maxnode contains the maximal node number that may be stored in \p mask.
88  * \p maxnode will be set to the maximal node number that was found, plus one.
89  *
90  * This function may be used before calling set_mempolicy, mbind, migrate_pages
91  * or any other function that takes an array of unsigned long and a maximal
92  * node number as input parameter.
93  */
94 static __hwloc_inline int
96  unsigned long *mask, unsigned long *maxnode)
97 {
98  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
99  unsigned long outmaxnode = -1;
100 
101  /* round-up to the next ulong and clear all bytes */
102  *maxnode = (*maxnode + 8*sizeof(*mask) - 1) & ~(8*sizeof(*mask) - 1);
103  memset(mask, 0, *maxnode/8);
104 
105  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
106  hwloc_obj_t node = NULL;
107  while ((node = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_NODE, node)) != NULL) {
108  if (node->os_index >= *maxnode)
109  continue;
110  if (!hwloc_bitmap_isset(nodeset, node->os_index))
111  continue;
112  mask[node->os_index/sizeof(*mask)/8] |= 1UL << (node->os_index % (sizeof(*mask)*8));
113  if (outmaxnode == (unsigned long) -1 || outmaxnode < node->os_index)
114  outmaxnode = node->os_index;
115  }
116 
117  } else {
118  /* if no numa, libnuma assumes we have a single node */
119  if (!hwloc_bitmap_iszero(nodeset)) {
120  mask[0] = 1;
121  outmaxnode = 0;
122  }
123  }
124 
125  *maxnode = outmaxnode+1;
126  return 0;
127 }
128 
129 /** \brief Convert the array of unsigned long \p mask into hwloc CPU set
130  *
131  * \p mask is a array of unsigned long that will be read.
132  * \p maxnode contains the maximal node number that may be read in \p mask.
133  *
134  * This function may be used after calling get_mempolicy or any other function
135  * that takes an array of unsigned long as output parameter (and possibly
136  * a maximal node number as input parameter).
137  */
138 static __hwloc_inline int
140  const unsigned long *mask, unsigned long maxnode)
141 {
142  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
143 
144  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
145  hwloc_obj_t node;
146  unsigned i;
147  hwloc_bitmap_zero(cpuset);
148  for(i=0; i<maxnode; i++)
149  if (mask[i/sizeof(*mask)/8] & (1UL << (i% (sizeof(*mask)*8)))) {
150  node = hwloc_get_obj_by_depth(topology, depth, i);
151  if (node)
152  hwloc_bitmap_or(cpuset, cpuset, node->cpuset);
153  }
154  } else {
155  /* if no numa, libnuma assumes we have a single node */
156  if (mask[0] & 1)
158  else
159  hwloc_bitmap_zero(cpuset);
160  }
161 
162  return 0;
163 }
164 
165 /** \brief Convert the array of unsigned long \p mask into hwloc NUMA node set
166  *
167  * \p mask is a array of unsigned long that will be read.
168  * \p maxnode contains the maximal node number that may be read in \p mask.
169  *
170  * This function may be used after calling get_mempolicy or any other function
171  * that takes an array of unsigned long as output parameter (and possibly
172  * a maximal node number as input parameter).
173  */
174 static __hwloc_inline int
176  const unsigned long *mask, unsigned long maxnode)
177 {
178  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
179 
180  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
181  hwloc_obj_t node;
182  unsigned i;
183  hwloc_bitmap_zero(nodeset);
184  for(i=0; i<maxnode; i++)
185  if (mask[i/sizeof(*mask)/8] & (1UL << (i% (sizeof(*mask)*8)))) {
186  node = hwloc_get_obj_by_depth(topology, depth, i);
187  if (node)
188  hwloc_bitmap_set(nodeset, node->os_index);
189  }
190  } else {
191  /* if no numa, libnuma assumes we have a single node */
192  if (mask[0] & 1)
193  hwloc_bitmap_fill(nodeset);
194  else
195  hwloc_bitmap_zero(nodeset);
196  }
197 
198  return 0;
199 }
200 
201 /** @} */
202 
203 
204 
205 /** \defgroup hwlocality_linux_libnuma_bitmask Helpers for manipulating Linux libnuma bitmask
206  * @{
207  */
208 
209 
210 /** \brief Convert hwloc CPU set \p cpuset into the returned libnuma bitmask
211  *
212  * The returned bitmask should later be freed with numa_bitmask_free.
213  *
214  * This function may be used before calling many numa_ functions
215  * that use a struct bitmask as an input parameter.
216  *
217  * \return newly allocated struct bitmask.
218  */
219 static __hwloc_inline struct bitmask * __hwloc_attribute_malloc
221 {
222  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
223  struct bitmask *bitmask = numa_allocate_cpumask();
224  if (!bitmask)
225  return NULL;
226 
227  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
228  hwloc_obj_t node = NULL;
229  while ((node = hwloc_get_next_obj_covering_cpuset_by_type(topology, cpuset, HWLOC_OBJ_NODE, node)) != NULL)
230  if (node->memory.local_memory)
231  numa_bitmask_setbit(bitmask, node->os_index);
232  } else {
233  /* if no numa, libnuma assumes we have a single node */
234  if (!hwloc_bitmap_iszero(cpuset))
235  numa_bitmask_setbit(bitmask, 0);
236  }
237 
238  return bitmask;
239 }
240 
241 /** \brief Convert hwloc NUMA node set \p nodeset into the returned libnuma bitmask
242  *
243  * The returned bitmask should later be freed with numa_bitmask_free.
244  *
245  * This function may be used before calling many numa_ functions
246  * that use a struct bitmask as an input parameter.
247  *
248  * \return newly allocated struct bitmask.
249  */
250 static __hwloc_inline struct bitmask * __hwloc_attribute_malloc
252 {
253  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
254  struct bitmask *bitmask = numa_allocate_cpumask();
255  if (!bitmask)
256  return NULL;
257 
258  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
259  hwloc_obj_t node = NULL;
260  while ((node = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_NODE, node)) != NULL)
261  if (hwloc_bitmap_isset(nodeset, node->os_index) && node->memory.local_memory)
262  numa_bitmask_setbit(bitmask, node->os_index);
263  } else {
264  /* if no numa, libnuma assumes we have a single node */
265  if (!hwloc_bitmap_iszero(nodeset))
266  numa_bitmask_setbit(bitmask, 0);
267  }
268 
269  return bitmask;
270 }
271 
272 /** \brief Convert libnuma bitmask \p bitmask into hwloc CPU set \p cpuset
273  *
274  * This function may be used after calling many numa_ functions
275  * that use a struct bitmask as an output parameter.
276  */
277 static __hwloc_inline int
279  const struct bitmask *bitmask)
280 {
281  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
282 
283  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
284  hwloc_obj_t node;
285  int i;
286  hwloc_bitmap_zero(cpuset);
287  for(i=0; i<NUMA_NUM_NODES; i++)
288  if (numa_bitmask_isbitset(bitmask, i)) {
289  node = hwloc_get_obj_by_depth(topology, depth, i);
290  if (node)
291  hwloc_bitmap_or(cpuset, cpuset, node->cpuset);
292  }
293  } else {
294  /* if no numa, libnuma assumes we have a single node */
295  if (numa_bitmask_isbitset(bitmask, 0))
297  else
298  hwloc_bitmap_zero(cpuset);
299  }
300 
301  return 0;
302 }
303 
304 /** \brief Convert libnuma bitmask \p bitmask into hwloc NUMA node set \p nodeset
305  *
306  * This function may be used after calling many numa_ functions
307  * that use a struct bitmask as an output parameter.
308  */
309 static __hwloc_inline int
311  const struct bitmask *bitmask)
312 {
313  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
314 
315  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
316  hwloc_obj_t node;
317  int i;
318  hwloc_bitmap_zero(nodeset);
319  for(i=0; i<NUMA_NUM_NODES; i++)
320  if (numa_bitmask_isbitset(bitmask, i)) {
321  node = hwloc_get_obj_by_depth(topology, depth, i);
322  if (node)
323  hwloc_bitmap_set(nodeset, node->os_index);
324  }
325  } else {
326  /* if no numa, libnuma assumes we have a single node */
327  if (numa_bitmask_isbitset(bitmask, 0))
328  hwloc_bitmap_fill(nodeset);
329  else
330  hwloc_bitmap_zero(nodeset);
331  }
332 
333  return 0;
334 }
335 
336 /** @} */
337 
338 
339 
340 #ifdef NUMA_VERSION1_COMPATIBILITY
341 /** \defgroup hwlocality_linux_libnuma_nodemask Helpers for manipulating Linux libnuma nodemask_t
342  * @{
343  */
344 
345 
346 /** \brief Convert hwloc CPU set \p cpuset into libnuma nodemask \p nodemask
347  *
348  * This function may be used before calling some old libnuma functions
349  * that use a nodemask_t as an input parameter.
350  */
351 static __hwloc_inline int
352 hwloc_cpuset_to_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset,
353  nodemask_t *nodemask)
354 {
355  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
356 
357  nodemask_zero(nodemask);
358 
359  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
360  hwloc_obj_t node = NULL;
361  while ((node = hwloc_get_next_obj_covering_cpuset_by_type(topology, cpuset, HWLOC_OBJ_NODE, node)) != NULL)
362  nodemask_set(nodemask, node->os_index);
363  } else {
364  /* if no numa, libnuma assumes we have a single node */
365  if (!hwloc_bitmap_iszero(cpuset))
366  nodemask_set(nodemask, 0);
367  }
368 
369  return 0;
370 }
371 
372 /** \brief Convert hwloc NUMA node set \p nodeset into libnuma nodemask \p nodemask
373  *
374  * This function may be used before calling some old libnuma functions
375  * that use a nodemask_t as an input parameter.
376  */
377 static __hwloc_inline int
378 hwloc_nodeset_to_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset,
379  nodemask_t *nodemask)
380 {
381  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
382 
383  nodemask_zero(nodemask);
384 
385  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
386  hwloc_obj_t node = NULL;
387  while ((node = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_NODE, node)) != NULL)
388  if (hwloc_bitmap_isset(nodeset, node->os_index))
389  nodemask_set(nodemask, node->os_index);
390  } else {
391  /* if no numa, libnuma assumes we have a single node */
392  if (!hwloc_bitmap_iszero(nodeset))
393  nodemask_set(nodemask, 0);
394  }
395 
396  return 0;
397 }
398 
399 /** \brief Convert libnuma nodemask \p nodemask into hwloc CPU set \p cpuset
400  *
401  * This function may be used before calling some old libnuma functions
402  * that use a nodemask_t as an output parameter.
403  */
404 static __hwloc_inline int
405 hwloc_cpuset_from_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_cpuset_t cpuset,
406  const nodemask_t *nodemask)
407 {
408  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
409 
410  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
411  hwloc_obj_t node;
412  int i;
413  hwloc_bitmap_zero(cpuset);
414  for(i=0; i<NUMA_NUM_NODES; i++)
415  if (nodemask_isset(nodemask, i)) {
416  node = hwloc_get_obj_by_depth(topology, depth, i);
417  if (node)
418  hwloc_bitmap_or(cpuset, cpuset, node->cpuset);
419  }
420  } else {
421  /* if no numa, libnuma assumes we have a single node */
422  if (nodemask_isset(nodemask, 0))
424  else
425  hwloc_bitmap_zero(cpuset);
426  }
427 
428  return 0;
429 }
430 
431 /** \brief Convert libnuma nodemask \p nodemask into hwloc NUMA node set \p nodeset
432  *
433  * This function may be used before calling some old libnuma functions
434  * that use a nodemask_t as an output parameter.
435  */
436 static __hwloc_inline int
437 hwloc_nodeset_from_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_nodeset_t nodeset,
438  const nodemask_t *nodemask)
439 {
440  int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE);
441 
442  if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) {
443  hwloc_obj_t node;
444  int i;
445  hwloc_bitmap_zero(nodeset);
446  for(i=0; i<NUMA_NUM_NODES; i++)
447  if (nodemask_isset(nodemask, i)) {
448  node = hwloc_get_obj_by_depth(topology, depth, i);
449  if (node)
450  hwloc_bitmap_set(nodeset, node->os_index);
451  }
452  } else {
453  /* if no numa, libnuma assumes we have a single node */
454  if (nodemask_isset(nodemask, 0))
455  hwloc_bitmap_fill(nodeset);
456  else
457  hwloc_bitmap_zero(nodeset);
458  }
459 
460  return 0;
461 }
462 
463 /** @} */
464 #endif /* NUMA_VERSION1_COMPATIBILITY */
465 
466 
467 #ifdef __cplusplus
468 } /* extern "C" */
469 #endif
470 
471 
472 #endif /* HWLOC_LINUX_NUMA_H */
HWLOC_DECLSPEC void hwloc_bitmap_zero(hwloc_bitmap_t bitmap)
Empty the bitmap bitmap.
HWLOC_DECLSPEC void hwloc_bitmap_copy(hwloc_bitmap_t dst, hwloc_const_bitmap_t src)
Copy the contents of bitmap src into the already allocated bitmap dst.
unsigned os_index
OS-provided physical index number.
Definition: hwloc.h:332
HWLOC_DECLSPEC int hwloc_bitmap_iszero(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure
Test whether bitmap bitmap is empty.
static __hwloc_inline struct bitmask *__hwloc_attribute_malloc hwloc_nodeset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset)
Convert hwloc NUMA node set nodeset into the returned libnuma bitmask.
Definition: linux-libnuma.h:251
struct hwloc_obj_memory_s memory
Memory attributes.
Definition: hwloc.h:335
static __hwloc_inline int hwloc_cpuset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, unsigned long *mask, unsigned long *maxnode)
Convert hwloc CPU set cpuset into the array of unsigned long mask.
Definition: linux-libnuma.h:52
HWLOC_DECLSPEC int hwloc_bitmap_isset(hwloc_const_bitmap_t bitmap, unsigned id) __hwloc_attribute_pure
Test whether index id is part of bitmap bitmap.
static __hwloc_inline hwloc_const_cpuset_t __hwloc_attribute_pure hwloc_topology_get_complete_cpuset(hwloc_topology_t topology)
Get complete CPU set.
Definition: helper.h:729
static __hwloc_inline int hwloc_nodeset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, unsigned long *mask, unsigned long *maxnode)
Convert hwloc NUMA node set nodeset into the array of unsigned long mask.
Definition: linux-libnuma.h:95
hwloc_uint64_t local_memory
Local memory (in bytes)
Definition: hwloc.h:311
static __hwloc_inline int hwloc_nodeset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_nodeset_t nodeset, const struct bitmask *bitmask)
Convert libnuma bitmask bitmask into hwloc NUMA node set nodeset.
Definition: linux-libnuma.h:310
static __hwloc_inline struct bitmask *__hwloc_attribute_malloc hwloc_cpuset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset)
Convert hwloc CPU set cpuset into the returned libnuma bitmask.
Definition: linux-libnuma.h:220
static __hwloc_inline hwloc_obj_t hwloc_get_next_obj_covering_cpuset_by_type(hwloc_topology_t topology, hwloc_const_cpuset_t set, hwloc_obj_type_t type, hwloc_obj_t prev)
Iterate through same-type objects covering at least CPU set set.
Definition: helper.h:475
Structure of a topology object.
Definition: hwloc.h:329
NUMA node.
Definition: hwloc.h:184
static __hwloc_inline int hwloc_cpuset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_cpuset_t cpuset, const unsigned long *mask, unsigned long maxnode)
Convert the array of unsigned long mask into hwloc CPU set.
Definition: linux-libnuma.h:139
No object of given type exists in the topology.
Definition: hwloc.h:1045
static __hwloc_inline hwloc_obj_t hwloc_get_next_obj_by_type(hwloc_topology_t topology, hwloc_obj_type_t type, hwloc_obj_t prev)
Returns the next object of type type.
Definition: helper.h:158
static __hwloc_inline int hwloc_nodeset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_nodeset_t nodeset, const unsigned long *mask, unsigned long maxnode)
Convert the array of unsigned long mask into hwloc NUMA node set.
Definition: linux-libnuma.h:175
HWLOC_DECLSPEC void hwloc_bitmap_fill(hwloc_bitmap_t bitmap)
Fill bitmap bitmap with all possible indexes (even if those objects don't exist or are otherwise unav...
HWLOC_DECLSPEC void hwloc_bitmap_set(hwloc_bitmap_t bitmap, unsigned id)
Add index id in bitmap bitmap.
static __hwloc_inline int hwloc_cpuset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_cpuset_t cpuset, const struct bitmask *bitmask)
Convert libnuma bitmask bitmask into hwloc CPU set cpuset.
Definition: linux-libnuma.h:278
HWLOC_DECLSPEC void hwloc_bitmap_or(hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2)
Or bitmaps bitmap1 and bitmap2 and store the result in bitmap res.
hwloc_cpuset_t cpuset
CPUs covered by this object.
Definition: hwloc.h:366
HWLOC_DECLSPEC hwloc_obj_t hwloc_get_obj_by_depth(hwloc_topology_t topology, unsigned depth, unsigned idx) __hwloc_attribute_pure
Returns the topology object at logical index idx from depth depth.
Definition: private.h:56
Definition: cpuset.c:38
HWLOC_DECLSPEC int hwloc_get_type_depth(hwloc_topology_t topology, hwloc_obj_type_t type)
Returns the depth of objects of type type.