Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-05 08:40:17

0001 /*
0002  * SPDX-License-Identifier: BSD-3-Clause
0003  * Copyright © 2009 CNRS
0004  * Copyright © 2009-2023 Inria.  All rights reserved.
0005  * Copyright © 2009-2010, 2012 Université Bordeaux
0006  * See COPYING in top-level directory.
0007  */
0008 
0009 /** \file
0010  * \brief Macros to help interaction between hwloc and Linux libnuma.
0011  *
0012  * Applications that use both Linux libnuma and hwloc may want to
0013  * include this file so as to ease conversion between their respective types.
0014 */
0015 
0016 #ifndef HWLOC_LINUX_LIBNUMA_H
0017 #define HWLOC_LINUX_LIBNUMA_H
0018 
0019 #include "hwloc.h"
0020 
0021 #include <numa.h>
0022 
0023 
0024 #ifdef __cplusplus
0025 extern "C" {
0026 #endif
0027 
0028 
0029 /** \defgroup hwlocality_linux_libnuma_ulongs Interoperability with Linux libnuma unsigned long masks
0030  *
0031  * This interface helps converting between Linux libnuma unsigned long masks
0032  * and hwloc cpusets and nodesets.
0033  *
0034  * \note Topology \p topology must match the current machine.
0035  *
0036  * \note The behavior of libnuma is undefined if the kernel is not NUMA-aware.
0037  * (when CONFIG_NUMA is not set in the kernel configuration).
0038  * This helper and libnuma may thus not be strictly compatible in this case,
0039  * which may be detected by checking whether numa_available() returns -1.
0040  *
0041  * @{
0042  */
0043 
0044 
0045 /** \brief Convert hwloc CPU set \p cpuset into the array of unsigned long \p mask
0046  *
0047  * \p mask is the array of unsigned long that will be filled.
0048  * \p maxnode contains the maximal node number that may be stored in \p mask.
0049  * \p maxnode will be set to the maximal node number that was found, plus one.
0050  *
0051  * This function may be used before calling set_mempolicy, mbind, migrate_pages
0052  * or any other function that takes an array of unsigned long and a maximal
0053  * node number as input parameter.
0054  *
0055  * \return 0.
0056  *
0057  * \note On heterogeneous memory platforms, we may return multiple local NUMA nodes
0058  * even if libnuma reports only one (usually the first one).
0059  */
0060 static __hwloc_inline int
0061 hwloc_cpuset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset,
0062                     unsigned long *mask, unsigned long *maxnode)
0063 {
0064   int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
0065   unsigned long outmaxnode = -1;
0066   hwloc_obj_t node = NULL;
0067 
0068   /* round-up to the next ulong and clear all bytes */
0069   *maxnode = (*maxnode + 8*sizeof(*mask) - 1) & ~(8*sizeof(*mask) - 1);
0070   memset(mask, 0, *maxnode/8);
0071 
0072   while ((node = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, node)) != NULL) {
0073     if (node->os_index >= *maxnode)
0074       continue;
0075     mask[node->os_index/sizeof(*mask)/8] |= 1UL << (node->os_index % (sizeof(*mask)*8));
0076     if (outmaxnode == (unsigned long) -1 || outmaxnode < node->os_index)
0077       outmaxnode = node->os_index;
0078   }
0079 
0080   *maxnode = outmaxnode+1;
0081   return 0;
0082 }
0083 
0084 /** \brief Convert hwloc NUMA node set \p nodeset into the array of unsigned long \p mask
0085  *
0086  * \p mask is the array of unsigned long that will be filled.
0087  * \p maxnode contains the maximal node number that may be stored in \p mask.
0088  * \p maxnode will be set to the maximal node number that was found, plus one.
0089  *
0090  * This function may be used before calling set_mempolicy, mbind, migrate_pages
0091  * or any other function that takes an array of unsigned long and a maximal
0092  * node number as input parameter.
0093  *
0094  * \return 0.
0095  */
0096 static __hwloc_inline int
0097 hwloc_nodeset_to_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset,
0098                       unsigned long *mask, unsigned long *maxnode)
0099 {
0100   int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
0101   unsigned long outmaxnode = -1;
0102   hwloc_obj_t node = NULL;
0103 
0104   /* round-up to the next ulong and clear all bytes */
0105   *maxnode = (*maxnode + 8*sizeof(*mask) - 1) & ~(8*sizeof(*mask) - 1);
0106   memset(mask, 0, *maxnode/8);
0107 
0108   while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL) {
0109     if (node->os_index >= *maxnode)
0110       continue;
0111     if (!hwloc_bitmap_isset(nodeset, node->os_index))
0112       continue;
0113     mask[node->os_index/sizeof(*mask)/8] |= 1UL << (node->os_index % (sizeof(*mask)*8));
0114     if (outmaxnode == (unsigned long) -1 || outmaxnode < node->os_index)
0115       outmaxnode = node->os_index;
0116   }
0117 
0118   *maxnode = outmaxnode+1;
0119   return 0;
0120 }
0121 
0122 /** \brief Convert the array of unsigned long \p mask into hwloc CPU set
0123  *
0124  * \p mask is a array of unsigned long that will be read.
0125  * \p maxnode contains the maximal node number that may be read in \p mask.
0126  *
0127  * This function may be used after calling get_mempolicy or any other function
0128  * that takes an array of unsigned long as output parameter (and possibly
0129  * a maximal node number as input parameter).
0130  *
0131  * \return 0 on success.
0132  * \return -1 on error, for instance if failing an internal reallocation.
0133  */
0134 static __hwloc_inline int
0135 hwloc_cpuset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_cpuset_t cpuset,
0136                       const unsigned long *mask, unsigned long maxnode)
0137 {
0138   int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
0139   hwloc_obj_t node = NULL;
0140   hwloc_bitmap_zero(cpuset);
0141   while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
0142     if (node->os_index < maxnode
0143     && (mask[node->os_index/sizeof(*mask)/8] & (1UL << (node->os_index % (sizeof(*mask)*8)))))
0144       if (hwloc_bitmap_or(cpuset, cpuset, node->cpuset) < 0)
0145         return -1;
0146   return 0;
0147 }
0148 
0149 /** \brief Convert the array of unsigned long \p mask into hwloc NUMA node set
0150  *
0151  * \p mask is a array of unsigned long that will be read.
0152  * \p maxnode contains the maximal node number that may be read in \p mask.
0153  *
0154  * This function may be used after calling get_mempolicy or any other function
0155  * that takes an array of unsigned long as output parameter (and possibly
0156  * a maximal node number as input parameter).
0157  *
0158  * \return 0 on success.
0159  * \return -1 with errno set to \c ENOMEM if some internal reallocation failed.
0160  */
0161 static __hwloc_inline int
0162 hwloc_nodeset_from_linux_libnuma_ulongs(hwloc_topology_t topology, hwloc_nodeset_t nodeset,
0163                     const unsigned long *mask, unsigned long maxnode)
0164 {
0165   int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
0166   hwloc_obj_t node = NULL;
0167   hwloc_bitmap_zero(nodeset);
0168   while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
0169     if (node->os_index < maxnode
0170     && (mask[node->os_index/sizeof(*mask)/8] & (1UL << (node->os_index % (sizeof(*mask)*8)))))
0171       if (hwloc_bitmap_set(nodeset, node->os_index) < 0)
0172         return -1;
0173   return 0;
0174 }
0175 
0176 /** @} */
0177 
0178 
0179 
0180 /** \defgroup hwlocality_linux_libnuma_bitmask Interoperability with Linux libnuma bitmask
0181  *
0182  * This interface helps converting between Linux libnuma bitmasks
0183  * and hwloc cpusets and nodesets.
0184  *
0185  * \note Topology \p topology must match the current machine.
0186  *
0187  * \note The behavior of libnuma is undefined if the kernel is not NUMA-aware.
0188  * (when CONFIG_NUMA is not set in the kernel configuration).
0189  * This helper and libnuma may thus not be strictly compatible in this case,
0190  * which may be detected by checking whether numa_available() returns -1.
0191  *
0192  * @{
0193  */
0194 
0195 
0196 /** \brief Convert hwloc CPU set \p cpuset into the returned libnuma bitmask
0197  *
0198  * The returned bitmask should later be freed with numa_bitmask_free.
0199  *
0200  * This function may be used before calling many numa_ functions
0201  * that use a struct bitmask as an input parameter.
0202  *
0203  * \return newly allocated struct bitmask, or \c NULL on error.
0204  *
0205  * \note On heterogeneous memory platforms, we may return multiple local NUMA nodes
0206  * even if libnuma reports only one (usually the first one).
0207  */
0208 static __hwloc_inline struct bitmask *
0209 hwloc_cpuset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset) __hwloc_attribute_malloc;
0210 static __hwloc_inline struct bitmask *
0211 hwloc_cpuset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset)
0212 {
0213   int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
0214   hwloc_obj_t node = NULL;
0215   struct bitmask *bitmask = numa_allocate_cpumask();
0216   if (!bitmask)
0217     return NULL;
0218   while ((node = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, node)) != NULL)
0219     if (node->attr->numanode.local_memory)
0220       numa_bitmask_setbit(bitmask, node->os_index);
0221   return bitmask;
0222 }
0223 
0224 /** \brief Convert hwloc NUMA node set \p nodeset into the returned libnuma bitmask
0225  *
0226  * The returned bitmask should later be freed with numa_bitmask_free.
0227  *
0228  * This function may be used before calling many numa_ functions
0229  * that use a struct bitmask as an input parameter.
0230  *
0231  * \return newly allocated struct bitmask, or \c NULL on error.
0232  */
0233 static __hwloc_inline struct bitmask *
0234 hwloc_nodeset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset) __hwloc_attribute_malloc;
0235 static __hwloc_inline struct bitmask *
0236 hwloc_nodeset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset)
0237 {
0238   int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
0239   hwloc_obj_t node = NULL;
0240   struct bitmask *bitmask = numa_allocate_cpumask();
0241   if (!bitmask)
0242     return NULL;
0243   while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
0244     if (hwloc_bitmap_isset(nodeset, node->os_index) && node->attr->numanode.local_memory)
0245       numa_bitmask_setbit(bitmask, node->os_index);
0246   return bitmask;
0247 }
0248 
0249 /** \brief Convert libnuma bitmask \p bitmask into hwloc CPU set \p cpuset
0250  *
0251  * This function may be used after calling many numa_ functions
0252  * that use a struct bitmask as an output parameter.
0253  *
0254  * \return 0 on success.
0255  * \return -1 with errno set to \c ENOMEM if some internal reallocation failed.
0256  */
0257 static __hwloc_inline int
0258 hwloc_cpuset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_cpuset_t cpuset,
0259                     const struct bitmask *bitmask)
0260 {
0261   int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
0262   hwloc_obj_t node = NULL;
0263   hwloc_bitmap_zero(cpuset);
0264   while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
0265     if (numa_bitmask_isbitset(bitmask, node->os_index))
0266       if (hwloc_bitmap_or(cpuset, cpuset, node->cpuset) < 0)
0267         return -1;
0268   return 0;
0269 }
0270 
0271 /** \brief Convert libnuma bitmask \p bitmask into hwloc NUMA node set \p nodeset
0272  *
0273  * This function may be used after calling many numa_ functions
0274  * that use a struct bitmask as an output parameter.
0275  *
0276  * \return 0 on success.
0277  * \return -1 with errno set to \c ENOMEM if some internal reallocation failed.
0278  */
0279 static __hwloc_inline int
0280 hwloc_nodeset_from_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_nodeset_t nodeset,
0281                      const struct bitmask *bitmask)
0282 {
0283   int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
0284   hwloc_obj_t node = NULL;
0285   hwloc_bitmap_zero(nodeset);
0286   while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
0287     if (numa_bitmask_isbitset(bitmask, node->os_index))
0288       if (hwloc_bitmap_set(nodeset, node->os_index) < 0)
0289         return -1;
0290   return 0;
0291 }
0292 
0293 /** @} */
0294 
0295 
0296 #ifdef __cplusplus
0297 } /* extern "C" */
0298 #endif
0299 
0300 
0301 #endif /* HWLOC_LINUX_NUMA_H */