mirror of https://github.com/xzeldon/htop.git
463 lines
14 KiB
C
463 lines
14 KiB
C
/*
|
|
* 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 */
|