diff options
Diffstat (limited to 'hwloc-1.2.1/include/hwloc/linux-libnuma.h')
-rw-r--r-- | hwloc-1.2.1/include/hwloc/linux-libnuma.h | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/hwloc-1.2.1/include/hwloc/linux-libnuma.h b/hwloc-1.2.1/include/hwloc/linux-libnuma.h new file mode 100644 index 00000000..399b265f --- /dev/null +++ b/hwloc-1.2.1/include/hwloc/linux-libnuma.h @@ -0,0 +1,462 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2010 INRIA. All rights reserved. + * Copyright © 2009-2010 Université Bordeaux 1 + * See COPYING in top-level directory. + */ + +/** \file + * \brief Macros to help interaction between hwloc and Linux libnuma. + * + * Applications that use both Linux libnuma and hwloc may want to + * include this file so as to ease conversion between their respective types. + */ + +#ifndef HWLOC_LINUX_LIBNUMA_H +#define HWLOC_LINUX_LIBNUMA_H + +#include <hwloc.h> +#include <numa.h> + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** \defgroup hwlocality_linux_libnuma_ulongs Helpers for manipulating Linux libnuma unsigned long masks + * @{ + */ + + +/** \brief Convert hwloc CPU set \p cpuset into the array of unsigned long \p mask + * + * \p mask is the array of unsigned long that will be filled. + * \p maxnode contains the maximal node number that may be stored in \p mask. + * \p maxnode will be set to the maximal node number that was found, plus one. + * + * This function may be used before calling set_mempolicy, mbind, migrate_pages + * or any other function that takes an array of unsigned long and a maximal + * node number as input parameter. + */ +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) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + unsigned long outmaxnode = -1; + + /* round-up to the next ulong and clear all bytes */ + *maxnode = (*maxnode + 8*sizeof(*mask) - 1) & ~(8*sizeof(*mask) - 1); + memset(mask, 0, *maxnode/8); + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node = NULL; + while ((node = hwloc_get_next_obj_covering_cpuset_by_type(topology, cpuset, HWLOC_OBJ_NODE, node)) != NULL) { + if (node->os_index >= *maxnode) + continue; + mask[node->os_index/sizeof(*mask)/8] |= 1UL << (node->os_index % (sizeof(*mask)*8)); + if (outmaxnode == (unsigned long) -1 || outmaxnode < node->os_index) + outmaxnode = node->os_index; + } + + } else { + /* if no numa, libnuma assumes we have a single node */ + if (!hwloc_bitmap_iszero(cpuset)) { + mask[0] = 1; + outmaxnode = 0; + } + } + + *maxnode = outmaxnode+1; + return 0; +} + +/** \brief Convert hwloc NUMA node set \p nodeset into the array of unsigned long \p mask + * + * \p mask is the array of unsigned long that will be filled. + * \p maxnode contains the maximal node number that may be stored in \p mask. + * \p maxnode will be set to the maximal node number that was found, plus one. + * + * This function may be used before calling set_mempolicy, mbind, migrate_pages + * or any other function that takes an array of unsigned long and a maximal + * node number as input parameter. + */ +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) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + unsigned long outmaxnode = -1; + + /* round-up to the next ulong and clear all bytes */ + *maxnode = (*maxnode + 8*sizeof(*mask) - 1) & ~(8*sizeof(*mask) - 1); + memset(mask, 0, *maxnode/8); + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node = NULL; + while ((node = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_NODE, node)) != NULL) { + if (node->os_index >= *maxnode) + continue; + if (!hwloc_bitmap_isset(nodeset, node->os_index)) + continue; + mask[node->os_index/sizeof(*mask)/8] |= 1UL << (node->os_index % (sizeof(*mask)*8)); + if (outmaxnode == (unsigned long) -1 || outmaxnode < node->os_index) + outmaxnode = node->os_index; + } + + } else { + /* if no numa, libnuma assumes we have a single node */ + if (!hwloc_bitmap_iszero(nodeset)) { + mask[0] = 1; + outmaxnode = 0; + } + } + + *maxnode = outmaxnode+1; + return 0; +} + +/** \brief Convert the array of unsigned long \p mask into hwloc CPU set + * + * \p mask is a array of unsigned long that will be read. + * \p maxnode contains the maximal node number that may be read in \p mask. + * + * This function may be used after calling get_mempolicy or any other function + * that takes an array of unsigned long as output parameter (and possibly + * a maximal node number as input parameter). + */ +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) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node; + unsigned i; + hwloc_bitmap_zero(cpuset); + for(i=0; i<maxnode; i++) + if (mask[i/sizeof(*mask)/8] & (1UL << (i% (sizeof(*mask)*8)))) { + node = hwloc_get_obj_by_depth(topology, depth, i); + if (node) + hwloc_bitmap_or(cpuset, cpuset, node->cpuset); + } + } else { + /* if no numa, libnuma assumes we have a single node */ + if (mask[0] & 1) + hwloc_bitmap_copy(cpuset, hwloc_topology_get_complete_cpuset(topology)); + else + hwloc_bitmap_zero(cpuset); + } + + return 0; +} + +/** \brief Convert the array of unsigned long \p mask into hwloc NUMA node set + * + * \p mask is a array of unsigned long that will be read. + * \p maxnode contains the maximal node number that may be read in \p mask. + * + * This function may be used after calling get_mempolicy or any other function + * that takes an array of unsigned long as output parameter (and possibly + * a maximal node number as input parameter). + */ +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) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node; + unsigned i; + hwloc_bitmap_zero(nodeset); + for(i=0; i<maxnode; i++) + if (mask[i/sizeof(*mask)/8] & (1UL << (i% (sizeof(*mask)*8)))) { + node = hwloc_get_obj_by_depth(topology, depth, i); + if (node) + hwloc_bitmap_set(nodeset, node->os_index); + } + } else { + /* if no numa, libnuma assumes we have a single node */ + if (mask[0] & 1) + hwloc_bitmap_fill(nodeset); + else + hwloc_bitmap_zero(nodeset); + } + + return 0; +} + +/** @} */ + + + +/** \defgroup hwlocality_linux_libnuma_bitmask Helpers for manipulating Linux libnuma bitmask + * @{ + */ + + +/** \brief Convert hwloc CPU set \p cpuset into the returned libnuma bitmask + * + * The returned bitmask should later be freed with numa_bitmask_free. + * + * This function may be used before calling many numa_ functions + * that use a struct bitmask as an input parameter. + * + * \return newly allocated struct bitmask. + */ +static __hwloc_inline struct bitmask * __hwloc_attribute_malloc +hwloc_cpuset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + struct bitmask *bitmask = numa_allocate_cpumask(); + if (!bitmask) + return NULL; + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node = NULL; + while ((node = hwloc_get_next_obj_covering_cpuset_by_type(topology, cpuset, HWLOC_OBJ_NODE, node)) != NULL) + numa_bitmask_setbit(bitmask, node->os_index); + } else { + /* if no numa, libnuma assumes we have a single node */ + if (!hwloc_bitmap_iszero(cpuset)) + numa_bitmask_setbit(bitmask, 0); + } + + return bitmask; +} + +/** \brief Convert hwloc NUMA node set \p nodeset into the returned libnuma bitmask + * + * The returned bitmask should later be freed with numa_bitmask_free. + * + * This function may be used before calling many numa_ functions + * that use a struct bitmask as an input parameter. + * + * \return newly allocated struct bitmask. + */ +static __hwloc_inline struct bitmask * __hwloc_attribute_malloc +hwloc_nodeset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + struct bitmask *bitmask = numa_allocate_cpumask(); + if (!bitmask) + return NULL; + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node = NULL; + while ((node = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_NODE, node)) != NULL) + if (hwloc_bitmap_isset(nodeset, node->os_index)) + numa_bitmask_setbit(bitmask, node->os_index); + } else { + /* if no numa, libnuma assumes we have a single node */ + if (!hwloc_bitmap_iszero(nodeset)) + numa_bitmask_setbit(bitmask, 0); + } + + return bitmask; +} + +/** \brief Convert libnuma bitmask \p bitmask into hwloc CPU set \p cpuset + * + * This function may be used after calling many numa_ functions + * that use a struct bitmask as an output parameter. + */ +static __hwloc_inline int +hwloc_cpuset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_cpuset_t cpuset, + const struct bitmask *bitmask) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node; + int i; + hwloc_bitmap_zero(cpuset); + for(i=0; i<NUMA_NUM_NODES; i++) + if (numa_bitmask_isbitset(bitmask, i)) { + node = hwloc_get_obj_by_depth(topology, depth, i); + if (node) + hwloc_bitmap_or(cpuset, cpuset, node->cpuset); + } + } else { + /* if no numa, libnuma assumes we have a single node */ + if (numa_bitmask_isbitset(bitmask, 0)) + hwloc_bitmap_copy(cpuset, hwloc_topology_get_complete_cpuset(topology)); + else + hwloc_bitmap_zero(cpuset); + } + + return 0; +} + +/** \brief Convert libnuma bitmask \p bitmask into hwloc NUMA node set \p nodeset + * + * This function may be used after calling many numa_ functions + * that use a struct bitmask as an output parameter. + */ +static __hwloc_inline int +hwloc_nodeset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_nodeset_t nodeset, + const struct bitmask *bitmask) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node; + int i; + hwloc_bitmap_zero(nodeset); + for(i=0; i<NUMA_NUM_NODES; i++) + if (numa_bitmask_isbitset(bitmask, i)) { + node = hwloc_get_obj_by_depth(topology, depth, i); + if (node) + hwloc_bitmap_set(nodeset, node->os_index); + } + } else { + /* if no numa, libnuma assumes we have a single node */ + if (numa_bitmask_isbitset(bitmask, 0)) + hwloc_bitmap_fill(nodeset); + else + hwloc_bitmap_zero(nodeset); + } + + return 0; +} + +/** @} */ + + + +#ifdef NUMA_VERSION1_COMPATIBILITY +/** \defgroup hwlocality_linux_libnuma_nodemask Helpers for manipulating Linux libnuma nodemask_t + * @{ + */ + + +/** \brief Convert hwloc CPU set \p cpuset into libnuma nodemask \p nodemask + * + * This function may be used before calling some old libnuma functions + * that use a nodemask_t as an input parameter. + */ +static __hwloc_inline int +hwloc_cpuset_to_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset, + nodemask_t *nodemask) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + + nodemask_zero(nodemask); + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node = NULL; + while ((node = hwloc_get_next_obj_covering_cpuset_by_type(topology, cpuset, HWLOC_OBJ_NODE, node)) != NULL) + nodemask_set(nodemask, node->os_index); + } else { + /* if no numa, libnuma assumes we have a single node */ + if (!hwloc_bitmap_iszero(cpuset)) + nodemask_set(nodemask, 0); + } + + return 0; +} + +/** \brief Convert hwloc NUMA node set \p nodeset into libnuma nodemask \p nodemask + * + * This function may be used before calling some old libnuma functions + * that use a nodemask_t as an input parameter. + */ +static __hwloc_inline int +hwloc_nodeset_to_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, + nodemask_t *nodemask) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + + nodemask_zero(nodemask); + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node = NULL; + while ((node = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_NODE, node)) != NULL) + if (hwloc_bitmap_isset(nodeset, node->os_index)) + nodemask_set(nodemask, node->os_index); + } else { + /* if no numa, libnuma assumes we have a single node */ + if (!hwloc_bitmap_iszero(nodeset)) + nodemask_set(nodemask, 0); + } + + return 0; +} + +/** \brief Convert libnuma nodemask \p nodemask into hwloc CPU set \p cpuset + * + * This function may be used before calling some old libnuma functions + * that use a nodemask_t as an output parameter. + */ +static __hwloc_inline int +hwloc_cpuset_from_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_cpuset_t cpuset, + const nodemask_t *nodemask) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node; + int i; + hwloc_bitmap_zero(cpuset); + for(i=0; i<NUMA_NUM_NODES; i++) + if (nodemask_isset(nodemask, i)) { + node = hwloc_get_obj_by_depth(topology, depth, i); + if (node) + hwloc_bitmap_or(cpuset, cpuset, node->cpuset); + } + } else { + /* if no numa, libnuma assumes we have a single node */ + if (nodemask_isset(nodemask, 0)) + hwloc_bitmap_copy(cpuset, hwloc_topology_get_complete_cpuset(topology)); + else + hwloc_bitmap_zero(cpuset); + } + + return 0; +} + +/** \brief Convert libnuma nodemask \p nodemask into hwloc NUMA node set \p nodeset + * + * This function may be used before calling some old libnuma functions + * that use a nodemask_t as an output parameter. + */ +static __hwloc_inline int +hwloc_nodeset_from_linux_libnuma_nodemask(hwloc_topology_t topology, hwloc_nodeset_t nodeset, + const nodemask_t *nodemask) +{ + int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NODE); + + if (depth != HWLOC_TYPE_DEPTH_UNKNOWN) { + hwloc_obj_t node; + int i; + hwloc_bitmap_zero(nodeset); + for(i=0; i<NUMA_NUM_NODES; i++) + if (nodemask_isset(nodemask, i)) { + node = hwloc_get_obj_by_depth(topology, depth, i); + if (node) + hwloc_bitmap_set(nodeset, node->os_index); + } + } else { + /* if no numa, libnuma assumes we have a single node */ + if (nodemask_isset(nodemask, 0)) + hwloc_bitmap_fill(nodeset); + else + hwloc_bitmap_zero(nodeset); + } + + return 0; +} + +/** @} */ +#endif /* NUMA_VERSION1_COMPATIBILITY */ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif /* HWLOC_LINUX_NUMA_H */ |