Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:01:16

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