Merge pull request #3302 from ggouaillardet/poc/hwloc2
POC: add support for hwloc v2
Этот коммит содержится в:
Коммит
7c6bd7d48d
@ -159,7 +159,11 @@ tm_topology_t* hwloc_to_tm(char *filename,double **pcost)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
hwloc_topology_ignore_all_keep_structure(topology);
|
||||
#else
|
||||
#warning FIXME hwloc v2
|
||||
#endif
|
||||
hwloc_topology_load(topology);
|
||||
|
||||
|
||||
@ -229,7 +233,11 @@ tm_topology_t* get_local_topo_with_hwloc(void)
|
||||
|
||||
/* Build the topology */
|
||||
hwloc_topology_init(&topology);
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
hwloc_topology_ignore_all_keep_structure(topology);
|
||||
#else
|
||||
#warning FIXME hwloc v2
|
||||
#endif
|
||||
hwloc_topology_load(topology);
|
||||
|
||||
/* Test if symetric */
|
||||
|
@ -131,7 +131,7 @@ static int get_rsrc_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
|
||||
|
||||
/* get our root object */
|
||||
root = hwloc_get_root_obj(opal_hwloc_topology);
|
||||
rootset = opal_hwloc_base_get_available_cpus(opal_hwloc_topology, root);
|
||||
rootset = root->cpuset;
|
||||
|
||||
/* get our bindings */
|
||||
boundset = hwloc_bitmap_alloc();
|
||||
@ -324,7 +324,7 @@ static int get_layout_current_binding(char str[OMPI_AFFINITY_STRING_MAX])
|
||||
|
||||
/* get our root object */
|
||||
root = hwloc_get_root_obj(opal_hwloc_topology);
|
||||
rootset = opal_hwloc_base_get_available_cpus(opal_hwloc_topology, root);
|
||||
rootset = root->cpuset;
|
||||
|
||||
/* get our bindings */
|
||||
boundset = hwloc_bitmap_alloc();
|
||||
|
@ -19,7 +19,7 @@
|
||||
* Copyright (c) 2011-2015 NVIDIA Corporation. All rights reserved.
|
||||
* Copyright (c) 2012 Oak Ridge National Laboratory. All rights reserved
|
||||
* Copyright (c) 2013-2016 Intel, Inc. All rights reserved.
|
||||
* Copyright (c) 2014-2016 Research Organization for Information Science
|
||||
* Copyright (c) 2014-2017 Research Organization for Information Science
|
||||
* and Technology (RIST). All rights reserved.
|
||||
* Copyright (c) 2014 Bull SAS. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
@ -2331,6 +2331,7 @@ static float get_ib_dev_distance(struct ibv_device *dev)
|
||||
because we have no way of measuring. */
|
||||
float distance = 0;
|
||||
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
/* Override any distance logic so all devices are used */
|
||||
if (0 != mca_btl_openib_component.ignore_locality ||
|
||||
OPAL_SUCCESS != opal_hwloc_base_get_topology()) {
|
||||
@ -2475,6 +2476,9 @@ static float get_ib_dev_distance(struct ibv_device *dev)
|
||||
if (NULL != my_cpuset) {
|
||||
hwloc_bitmap_free(my_cpuset);
|
||||
}
|
||||
#else
|
||||
#warning FIXME get_ib_dev_distance is not implemented with hwloc v2
|
||||
#endif
|
||||
|
||||
return distance;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
* reserved.
|
||||
* Copyright (c) 2012-2015 NVIDIA Corporation. All rights reserved.
|
||||
* Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014 Research Organization for Information Science
|
||||
* Copyright (c) 2014-2017 Research Organization for Information Science
|
||||
* and Technology (RIST). All rights reserved.
|
||||
* Copyright (c) 2015-2016 Intel, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
@ -296,7 +296,6 @@ smcuda_btl_first_time_init(mca_btl_smcuda_t *smcuda_btl,
|
||||
num_mem_nodes > 0 && NULL != opal_process_info.cpuset) {
|
||||
int numa=0, w;
|
||||
unsigned n_bound=0;
|
||||
hwloc_cpuset_t avail;
|
||||
hwloc_obj_t obj;
|
||||
|
||||
/* count the number of NUMA nodes to which we are bound */
|
||||
@ -306,10 +305,8 @@ smcuda_btl_first_time_init(mca_btl_smcuda_t *smcuda_btl,
|
||||
OPAL_HWLOC_AVAILABLE))) {
|
||||
continue;
|
||||
}
|
||||
/* get that NUMA node's available cpus */
|
||||
avail = opal_hwloc_base_get_available_cpus(opal_hwloc_topology, obj);
|
||||
/* see if we intersect */
|
||||
if (hwloc_bitmap_intersects(avail, opal_hwloc_my_cpuset)) {
|
||||
/* see if we intersect with that NUMA node's cpus */
|
||||
if (hwloc_bitmap_intersects(obj->cpuset, opal_hwloc_my_cpuset)) {
|
||||
n_bound++;
|
||||
numa = w;
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2017 Cisco Systems, Inc. All rights reserved
|
||||
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
|
||||
* Copyright (c) 2017 Research Organization for Information Science
|
||||
* and Technology (RIST). All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -17,6 +19,12 @@
|
||||
|
||||
#include "opal/mca/hwloc/hwloc-internal.h"
|
||||
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
#define HWLOC_OBJ_L3CACHE HWLOC_OBJ_CACHE
|
||||
#define HWLOC_OBJ_L2CACHE HWLOC_OBJ_CACHE
|
||||
#define HWLOC_OBJ_L1CACHE HWLOC_OBJ_CACHE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Global functions for MCA overall hwloc open and close
|
||||
*/
|
||||
@ -81,6 +89,20 @@ OPAL_DECLSPEC extern char *opal_hwloc_base_topo_file;
|
||||
hwloc_bitmap_free(bind); \
|
||||
} while(0);
|
||||
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
#define OPAL_HWLOC_MAKE_OBJ_CACHE(level, obj, cache_level) \
|
||||
do { \
|
||||
obj = HWLOC_OBJ_CACHE; \
|
||||
cache_level = level; \
|
||||
} while(0)
|
||||
#else
|
||||
#define OPAL_HWLOC_MAKE_OBJ_CACHE(level, obj, cache_level) \
|
||||
do { \
|
||||
obj = HWLOC_OBJ_L##level##CACHE; \
|
||||
cache_level = 0; \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
OPAL_DECLSPEC opal_hwloc_locality_t opal_hwloc_base_get_relative_locality(hwloc_topology_t topo,
|
||||
char *cpuset1, char *cpuset2);
|
||||
|
||||
@ -132,9 +154,6 @@ typedef enum {
|
||||
*/
|
||||
OPAL_DECLSPEC extern opal_hwloc_base_mbfa_t opal_hwloc_base_mbfa;
|
||||
|
||||
/* some critical helper functions */
|
||||
OPAL_DECLSPEC int opal_hwloc_base_filter_cpus(hwloc_topology_t topo);
|
||||
|
||||
/**
|
||||
* Discover / load the hwloc topology (i.e., call hwloc_topology_init() and
|
||||
* hwloc_topology_load()).
|
||||
@ -150,8 +169,6 @@ OPAL_DECLSPEC int opal_hwloc_base_set_topology(char *topofile);
|
||||
* Free the hwloc topology.
|
||||
*/
|
||||
OPAL_DECLSPEC void opal_hwloc_base_free_topology(hwloc_topology_t topo);
|
||||
OPAL_DECLSPEC hwloc_cpuset_t opal_hwloc_base_get_available_cpus(hwloc_topology_t topo,
|
||||
hwloc_obj_t obj);
|
||||
OPAL_DECLSPEC unsigned int opal_hwloc_base_get_nbobjs_by_type(hwloc_topology_t topo,
|
||||
hwloc_obj_type_t target,
|
||||
unsigned cache_level,
|
||||
@ -285,6 +302,9 @@ OPAL_DECLSPEC char* opal_hwloc_base_get_location(char *locality,
|
||||
|
||||
OPAL_DECLSPEC opal_hwloc_locality_t opal_hwloc_compute_relative_locality(char *loc1, char *loc2);
|
||||
|
||||
OPAL_DECLSPEC int opal_hwloc_base_topology_export_xmlbuffer(hwloc_topology_t topology, char **xmlpath, int *buflen);
|
||||
|
||||
OPAL_DECLSPEC int opal_hwloc_base_topology_set_flags (hwloc_topology_t topology, unsigned long flags, bool io);
|
||||
END_C_DECLS
|
||||
|
||||
#endif /* OPAL_HWLOC_BASE_H */
|
||||
|
@ -31,7 +31,7 @@ int opal_hwloc_pack(opal_buffer_t *buffer, const void *src,
|
||||
t = tarray[i];
|
||||
|
||||
/* extract an xml-buffer representation of the tree */
|
||||
if (0 != hwloc_topology_export_xmlbuffer(t, &xmlbuffer, &len)) {
|
||||
if (0 != opal_hwloc_base_topology_export_xmlbuffer(t, &xmlbuffer, &len)) {
|
||||
return OPAL_ERROR;
|
||||
}
|
||||
|
||||
@ -106,9 +106,7 @@ int opal_hwloc_unpack(opal_buffer_t *buffer, void *dest,
|
||||
/* since we are loading this from an external source, we have to
|
||||
* explicitly set a flag so hwloc sets things up correctly
|
||||
*/
|
||||
if (0 != hwloc_topology_set_flags(t, (HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM |
|
||||
HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM |
|
||||
HWLOC_TOPOLOGY_FLAG_IO_DEVICES))) {
|
||||
if (0 != opal_hwloc_base_topology_set_flags(t, HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM, true)) {
|
||||
rc = OPAL_ERROR;
|
||||
hwloc_topology_destroy(t);
|
||||
goto cleanup;
|
||||
@ -137,11 +135,6 @@ int opal_hwloc_unpack(opal_buffer_t *buffer, void *dest,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* filter the cpus thru any default cpu set */
|
||||
if (OPAL_SUCCESS != (rc = opal_hwloc_base_filter_cpus(t))) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* pass it back */
|
||||
tarray[i] = t;
|
||||
|
||||
@ -197,10 +190,10 @@ int opal_hwloc_compare(const hwloc_topology_t topo1,
|
||||
* where we really need to do a tree-wise search so we only compare
|
||||
* the things we care about, and ignore stuff like MAC addresses
|
||||
*/
|
||||
if (0 != hwloc_topology_export_xmlbuffer(t1, &x1, &l1)) {
|
||||
if (0 != opal_hwloc_base_topology_export_xmlbuffer(t1, &x1, &l1)) {
|
||||
return OPAL_EQUAL;
|
||||
}
|
||||
if (0 != hwloc_topology_export_xmlbuffer(t2, &x2, &l2)) {
|
||||
if (0 != opal_hwloc_base_topology_export_xmlbuffer(t2, &x2, &l2)) {
|
||||
free(x1);
|
||||
return OPAL_EQUAL;
|
||||
}
|
||||
@ -269,18 +262,6 @@ static void print_hwloc_obj(char **output, char *prefix,
|
||||
free(tmp);
|
||||
tmp = tmp2;
|
||||
}
|
||||
if (NULL != obj->online_cpuset) {
|
||||
hwloc_bitmap_snprintf(string, OPAL_HWLOC_MAX_STRING, obj->online_cpuset);
|
||||
asprintf(&tmp2, "%s%sOnline: %s", tmp, pfx, string);
|
||||
free(tmp);
|
||||
tmp = tmp2;
|
||||
}
|
||||
if (NULL != obj->allowed_cpuset) {
|
||||
hwloc_bitmap_snprintf(string, OPAL_HWLOC_MAX_STRING, obj->allowed_cpuset);
|
||||
asprintf(&tmp2, "%s%sAllowed: %s", tmp, pfx, string);
|
||||
free(tmp);
|
||||
tmp = tmp2;
|
||||
}
|
||||
if (HWLOC_OBJ_MACHINE == obj->type) {
|
||||
/* root level object - add support values */
|
||||
support = (struct hwloc_topology_support*)hwloc_topology_get_support(topo);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2017 Cisco Systems, Inc. All rights reserved
|
||||
* Copyright (c) 2013-2017 Intel, Inc. All rights reserved.
|
||||
* Copyright (c) 2016 Research Organization for Information Science
|
||||
* Copyright (c) 2016-2017 Research Organization for Information Science
|
||||
* and Technology (RIST). All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
@ -50,9 +50,9 @@ hwloc_obj_type_t opal_hwloc_levels[] = {
|
||||
HWLOC_OBJ_MACHINE,
|
||||
HWLOC_OBJ_NODE,
|
||||
HWLOC_OBJ_SOCKET,
|
||||
HWLOC_OBJ_CACHE,
|
||||
HWLOC_OBJ_CACHE,
|
||||
HWLOC_OBJ_CACHE,
|
||||
HWLOC_OBJ_L3CACHE,
|
||||
HWLOC_OBJ_L2CACHE,
|
||||
HWLOC_OBJ_L1CACHE,
|
||||
HWLOC_OBJ_CORE,
|
||||
HWLOC_OBJ_PU
|
||||
};
|
||||
|
@ -110,104 +110,11 @@ hwloc_obj_t opal_hwloc_base_get_pu(hwloc_topology_t topo,
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* determine the node-level available cpuset based on
|
||||
* online vs allowed vs user-specified cpus
|
||||
*/
|
||||
int opal_hwloc_base_filter_cpus(hwloc_topology_t topo)
|
||||
{
|
||||
hwloc_obj_t root, pu;
|
||||
hwloc_cpuset_t avail = NULL, pucpus, res;
|
||||
opal_hwloc_topo_data_t *sum;
|
||||
opal_hwloc_obj_data_t *data;
|
||||
char **ranges=NULL, **range=NULL;
|
||||
int idx, cpu, start, end;
|
||||
|
||||
root = hwloc_get_root_obj(topo);
|
||||
|
||||
if (NULL == root->userdata) {
|
||||
root->userdata = (void*)OBJ_NEW(opal_hwloc_topo_data_t);
|
||||
}
|
||||
sum = (opal_hwloc_topo_data_t*)root->userdata;
|
||||
|
||||
/* should only ever enter here once, but check anyway */
|
||||
if (NULL != sum->available) {
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
/* process any specified default cpu set against this topology */
|
||||
if (NULL == opal_hwloc_base_cpu_list) {
|
||||
/* get the root available cpuset */
|
||||
avail = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_and(avail, root->online_cpuset, root->allowed_cpuset);
|
||||
OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base: no cpus specified - using root available cpuset"));
|
||||
} else {
|
||||
OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base: filtering cpuset"));
|
||||
/* find the specified logical cpus */
|
||||
ranges = opal_argv_split(opal_hwloc_base_cpu_list, ',');
|
||||
avail = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_zero(avail);
|
||||
res = hwloc_bitmap_alloc();
|
||||
pucpus = hwloc_bitmap_alloc();
|
||||
for (idx=0; idx < opal_argv_count(ranges); idx++) {
|
||||
range = opal_argv_split(ranges[idx], '-');
|
||||
switch (opal_argv_count(range)) {
|
||||
case 1:
|
||||
/* only one cpu given - get that object */
|
||||
cpu = strtoul(range[0], NULL, 10);
|
||||
if (NULL != (pu = opal_hwloc_base_get_pu(topo, cpu, OPAL_HWLOC_LOGICAL))) {
|
||||
hwloc_bitmap_and(pucpus, pu->online_cpuset, pu->allowed_cpuset);
|
||||
hwloc_bitmap_or(res, avail, pucpus);
|
||||
hwloc_bitmap_copy(avail, res);
|
||||
data = (opal_hwloc_obj_data_t*)pu->userdata;
|
||||
if (NULL == data) {
|
||||
pu->userdata = (void*)OBJ_NEW(opal_hwloc_obj_data_t);
|
||||
data = (opal_hwloc_obj_data_t*)pu->userdata;
|
||||
}
|
||||
data->npus++;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
/* range given */
|
||||
start = strtoul(range[0], NULL, 10);
|
||||
end = strtoul(range[1], NULL, 10);
|
||||
for (cpu=start; cpu <= end; cpu++) {
|
||||
if (NULL != (pu = opal_hwloc_base_get_pu(topo, cpu, OPAL_HWLOC_LOGICAL))) {
|
||||
hwloc_bitmap_and(pucpus, pu->online_cpuset, pu->allowed_cpuset);
|
||||
hwloc_bitmap_or(res, avail, pucpus);
|
||||
hwloc_bitmap_copy(avail, res);
|
||||
data = (opal_hwloc_obj_data_t*)pu->userdata;
|
||||
if (NULL == data) {
|
||||
pu->userdata = (void*)OBJ_NEW(opal_hwloc_obj_data_t);
|
||||
data = (opal_hwloc_obj_data_t*)pu->userdata;
|
||||
}
|
||||
data->npus++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
opal_argv_free(range);
|
||||
}
|
||||
if (NULL != ranges) {
|
||||
opal_argv_free(ranges);
|
||||
}
|
||||
hwloc_bitmap_free(res);
|
||||
hwloc_bitmap_free(pucpus);
|
||||
}
|
||||
|
||||
/* cache this info */
|
||||
sum->available = avail;
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
static void fill_cache_line_size(void)
|
||||
{
|
||||
int i = 0, cache_level = 2;
|
||||
unsigned size;
|
||||
unsigned int cache_object = HWLOC_OBJ_L2CACHE;
|
||||
hwloc_obj_t obj;
|
||||
bool found = false;
|
||||
|
||||
@ -217,10 +124,11 @@ static void fill_cache_line_size(void)
|
||||
i=0;
|
||||
while (1) {
|
||||
obj = opal_hwloc_base_get_obj_by_type(opal_hwloc_topology,
|
||||
HWLOC_OBJ_CACHE, cache_level,
|
||||
cache_object, cache_level,
|
||||
i, OPAL_HWLOC_LOGICAL);
|
||||
if (NULL == obj) {
|
||||
--cache_level;
|
||||
cache_object = HWLOC_OBJ_L1CACHE;
|
||||
break;
|
||||
} else {
|
||||
if (NULL != obj->attr &&
|
||||
@ -282,10 +190,9 @@ int opal_hwloc_base_get_topology(void)
|
||||
/* since we are loading this from an external source, we have to
|
||||
* explicitly set a flag so hwloc sets things up correctly
|
||||
*/
|
||||
if (0 != hwloc_topology_set_flags(opal_hwloc_topology,
|
||||
(HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM |
|
||||
HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM |
|
||||
HWLOC_TOPOLOGY_FLAG_IO_DEVICES))) {
|
||||
if (0 != opal_hwloc_base_topology_set_flags(opal_hwloc_topology,
|
||||
HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM,
|
||||
true)) {
|
||||
hwloc_topology_destroy(opal_hwloc_topology);
|
||||
free(val);
|
||||
return OPAL_ERROR;
|
||||
@ -297,22 +204,12 @@ int opal_hwloc_base_get_topology(void)
|
||||
return OPAL_ERROR;
|
||||
}
|
||||
free(val);
|
||||
/* filter the cpus thru any default cpu set */
|
||||
if (OPAL_SUCCESS != (rc = opal_hwloc_base_filter_cpus(opal_hwloc_topology))) {
|
||||
hwloc_topology_destroy(opal_hwloc_topology);
|
||||
return rc;
|
||||
}
|
||||
} else if (NULL == opal_hwloc_base_topo_file) {
|
||||
if (0 != hwloc_topology_init(&opal_hwloc_topology) ||
|
||||
0 != hwloc_topology_set_flags(opal_hwloc_topology,
|
||||
(HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM |
|
||||
HWLOC_TOPOLOGY_FLAG_IO_DEVICES)) ||
|
||||
0 != opal_hwloc_base_topology_set_flags(opal_hwloc_topology, 0, true) ||
|
||||
0 != hwloc_topology_load(opal_hwloc_topology)) {
|
||||
return OPAL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
if (OPAL_SUCCESS != (rc = opal_hwloc_base_filter_cpus(opal_hwloc_topology))) {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
if (OPAL_SUCCESS != (rc = opal_hwloc_base_set_topology(opal_hwloc_base_topo_file))) {
|
||||
return rc;
|
||||
@ -334,7 +231,6 @@ int opal_hwloc_base_get_topology(void)
|
||||
int opal_hwloc_base_set_topology(char *topofile)
|
||||
{
|
||||
struct hwloc_topology_support *support;
|
||||
int rc;
|
||||
|
||||
OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base:set_topology %s", topofile));
|
||||
@ -354,10 +250,9 @@ int opal_hwloc_base_set_topology(char *topofile)
|
||||
/* since we are loading this from an external source, we have to
|
||||
* explicitly set a flag so hwloc sets things up correctly
|
||||
*/
|
||||
if (0 != hwloc_topology_set_flags(opal_hwloc_topology,
|
||||
(HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM |
|
||||
HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM |
|
||||
HWLOC_TOPOLOGY_FLAG_IO_DEVICES))) {
|
||||
if (0 != opal_hwloc_base_topology_set_flags(opal_hwloc_topology,
|
||||
HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM,
|
||||
true)) {
|
||||
hwloc_topology_destroy(opal_hwloc_topology);
|
||||
return OPAL_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
@ -377,12 +272,6 @@ int opal_hwloc_base_set_topology(char *topofile)
|
||||
support->cpubind->set_thisproc_cpubind = true;
|
||||
support->membind->set_thisproc_membind = true;
|
||||
|
||||
/* filter the cpus thru any default cpu set */
|
||||
rc = opal_hwloc_base_filter_cpus(opal_hwloc_topology);
|
||||
if (OPAL_SUCCESS != rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* fill opal_cache_line_size global with the smallest L1 cache
|
||||
line size */
|
||||
fill_cache_line_size();
|
||||
@ -434,7 +323,6 @@ void opal_hwloc_base_free_topology(hwloc_topology_t topo)
|
||||
void opal_hwloc_base_get_local_cpuset(void)
|
||||
{
|
||||
hwloc_obj_t root;
|
||||
hwloc_cpuset_t base_cpus;
|
||||
|
||||
if (NULL != opal_hwloc_topology) {
|
||||
if (NULL == opal_hwloc_my_cpuset) {
|
||||
@ -447,8 +335,7 @@ void opal_hwloc_base_get_local_cpuset(void)
|
||||
HWLOC_CPUBIND_PROCESS) < 0) {
|
||||
/* we are not bound - use the root's available cpuset */
|
||||
root = hwloc_get_root_obj(opal_hwloc_topology);
|
||||
base_cpus = opal_hwloc_base_get_available_cpus(opal_hwloc_topology, root);
|
||||
hwloc_bitmap_copy(opal_hwloc_my_cpuset, base_cpus);
|
||||
hwloc_bitmap_copy(opal_hwloc_my_cpuset, root->cpuset);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -476,72 +363,6 @@ int opal_hwloc_base_report_bind_failure(const char *file,
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
hwloc_cpuset_t opal_hwloc_base_get_available_cpus(hwloc_topology_t topo,
|
||||
hwloc_obj_t obj)
|
||||
{
|
||||
hwloc_obj_t root;
|
||||
hwloc_cpuset_t avail, specd=NULL;
|
||||
opal_hwloc_topo_data_t *rdata;
|
||||
opal_hwloc_obj_data_t *data;
|
||||
|
||||
OPAL_OUTPUT_VERBOSE((10, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base: get available cpus"));
|
||||
|
||||
/* get the node-level information */
|
||||
root = hwloc_get_root_obj(topo);
|
||||
rdata = (opal_hwloc_topo_data_t*)root->userdata;
|
||||
/* bozo check */
|
||||
if (NULL == rdata) {
|
||||
rdata = OBJ_NEW(opal_hwloc_topo_data_t);
|
||||
root->userdata = (void*)rdata;
|
||||
OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base:get_available_cpus first time - filtering cpus"));
|
||||
}
|
||||
|
||||
/* are we asking about the root object? */
|
||||
if (obj == root) {
|
||||
OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base:get_available_cpus root object"));
|
||||
return rdata->available;
|
||||
}
|
||||
|
||||
/* some hwloc object types don't have cpus */
|
||||
if (NULL == obj->online_cpuset || NULL == obj->allowed_cpuset) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* see if we already have this info */
|
||||
if (NULL == (data = (opal_hwloc_obj_data_t*)obj->userdata)) {
|
||||
/* nope - create the object */
|
||||
data = OBJ_NEW(opal_hwloc_obj_data_t);
|
||||
obj->userdata = (void*)data;
|
||||
}
|
||||
|
||||
/* do we have the cpuset */
|
||||
if (NULL != data->available) {
|
||||
return data->available;
|
||||
}
|
||||
|
||||
/* find the available processors on this object */
|
||||
avail = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_and(avail, obj->online_cpuset, obj->allowed_cpuset);
|
||||
|
||||
/* filter this against the node-available processors */
|
||||
if (NULL == rdata->available) {
|
||||
hwloc_bitmap_free(avail);
|
||||
return NULL;
|
||||
}
|
||||
specd = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_and(specd, avail, rdata->available);
|
||||
|
||||
/* cache the info */
|
||||
data->available = specd;
|
||||
|
||||
/* cleanup */
|
||||
hwloc_bitmap_free(avail);
|
||||
return specd;
|
||||
}
|
||||
|
||||
static void df_search_cores(hwloc_obj_t obj, unsigned int *cnt)
|
||||
{
|
||||
unsigned k;
|
||||
@ -554,13 +375,6 @@ static void df_search_cores(hwloc_obj_t obj, unsigned int *cnt)
|
||||
obj->userdata = (void*)data;
|
||||
}
|
||||
if (NULL == opal_hwloc_base_cpu_list) {
|
||||
if (!hwloc_bitmap_intersects(obj->cpuset, obj->allowed_cpuset)) {
|
||||
/*
|
||||
* do not count not allowed cores (e.g. cores with zero allowed PU)
|
||||
* if SMT is enabled, do count cores with at least one allowed hwthread
|
||||
*/
|
||||
return;
|
||||
}
|
||||
data->npus = 1;
|
||||
}
|
||||
*cnt += data->npus;
|
||||
@ -607,7 +421,6 @@ unsigned int opal_hwloc_base_get_npus(hwloc_topology_t topo,
|
||||
{
|
||||
opal_hwloc_obj_data_t *data;
|
||||
unsigned int cnt = 0;
|
||||
hwloc_cpuset_t cpuset;
|
||||
|
||||
data = (opal_hwloc_obj_data_t*)obj->userdata;
|
||||
if (NULL == data || !data->npus_calculated) {
|
||||
@ -631,12 +444,13 @@ unsigned int opal_hwloc_base_get_npus(hwloc_topology_t topo,
|
||||
df_search_cores(obj, &cnt);
|
||||
}
|
||||
} else {
|
||||
hwloc_cpuset_t cpuset;
|
||||
|
||||
/* if we are treating cores as cpus, or the system can't detect
|
||||
* "cores", then get the available cpuset for this object - this will
|
||||
* create and store the data
|
||||
*/
|
||||
if (NULL == (cpuset = opal_hwloc_base_get_available_cpus(topo, obj))) {
|
||||
if (NULL == (cpuset = obj->cpuset)) {
|
||||
return 0;
|
||||
}
|
||||
/* count the number of bits that are set - there is
|
||||
@ -688,10 +502,13 @@ unsigned int opal_hwloc_base_get_obj_idx(hwloc_topology_t topo,
|
||||
return data->idx;
|
||||
}
|
||||
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
/* determine the number of objects of this type */
|
||||
if (HWLOC_OBJ_CACHE == obj->type) {
|
||||
cache_level = obj->attr->cache.depth;
|
||||
}
|
||||
#endif
|
||||
|
||||
nobjs = opal_hwloc_base_get_nbobjs_by_type(topo, obj->type, cache_level, rtype);
|
||||
|
||||
OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
|
||||
@ -741,9 +558,11 @@ static hwloc_obj_t df_search(hwloc_topology_t topo,
|
||||
opal_hwloc_obj_data_t *data;
|
||||
|
||||
if (target == start->type) {
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
if (HWLOC_OBJ_CACHE == start->type && cache_level != start->attr->cache.depth) {
|
||||
goto notfound;
|
||||
}
|
||||
#endif
|
||||
if (OPAL_HWLOC_LOGICAL == rtype) {
|
||||
/* the hwloc tree is composed of LOGICAL objects, so the only
|
||||
* time we come here is when we are looking for logical caches
|
||||
@ -797,7 +616,7 @@ static hwloc_obj_t df_search(hwloc_topology_t topo,
|
||||
}
|
||||
/* see if we already know our available cpuset */
|
||||
if (NULL == data->available) {
|
||||
data->available = opal_hwloc_base_get_available_cpus(topo, start);
|
||||
data->available = hwloc_bitmap_dup(start->cpuset);
|
||||
}
|
||||
if (NULL != data->available && !hwloc_bitmap_iszero(data->available)) {
|
||||
if (NULL != num_objs) {
|
||||
@ -848,7 +667,11 @@ unsigned int opal_hwloc_base_get_nbobjs_by_type(hwloc_topology_t topo,
|
||||
* use the hwloc accessor to get it, unless it is a CACHE
|
||||
* as these are treated as special cases
|
||||
*/
|
||||
if (OPAL_HWLOC_LOGICAL == rtype && HWLOC_OBJ_CACHE != target) {
|
||||
if (OPAL_HWLOC_LOGICAL == rtype
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
&& HWLOC_OBJ_CACHE != target
|
||||
#endif
|
||||
) {
|
||||
/* we should not get an error back, but just in case... */
|
||||
if (0 > (rc = hwloc_get_nbobjs_by_type(topo, target))) {
|
||||
opal_output(0, "UNKNOWN HWLOC ERROR");
|
||||
@ -914,9 +737,11 @@ static hwloc_obj_t df_search_min_bound(hwloc_topology_t topo,
|
||||
if (0 == (k = opal_hwloc_base_get_npus(topo, start))) {
|
||||
goto notfound;
|
||||
}
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
if (HWLOC_OBJ_CACHE == start->type && cache_level != start->attr->cache.depth) {
|
||||
goto notfound;
|
||||
}
|
||||
#endif
|
||||
/* see how many procs are bound to us */
|
||||
data = (opal_hwloc_obj_data_t*)start->userdata;
|
||||
if (NULL == data) {
|
||||
@ -979,10 +804,12 @@ hwloc_obj_t opal_hwloc_base_find_min_bound_target_under_obj(hwloc_topology_t top
|
||||
/* again, we have to treat caches differently as
|
||||
* the levels distinguish them
|
||||
*/
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
if (HWLOC_OBJ_CACHE == target &&
|
||||
cache_level < obj->attr->cache.depth) {
|
||||
goto moveon;
|
||||
}
|
||||
#endif
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -995,16 +822,17 @@ hwloc_obj_t opal_hwloc_base_find_min_bound_target_under_obj(hwloc_topology_t top
|
||||
loc = df_search_min_bound(topo, obj, target, cache_level, &min_bound);
|
||||
|
||||
if (NULL != loc) {
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
if (HWLOC_OBJ_CACHE == target) {
|
||||
OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base:min_bound_under_obj found min bound of %u on %s:%u:%u",
|
||||
min_bound, hwloc_obj_type_string(target),
|
||||
cache_level, loc->logical_index));
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base:min_bound_under_obj found min bound of %u on %s:%u",
|
||||
min_bound, hwloc_obj_type_string(target), loc->logical_index));
|
||||
}
|
||||
}
|
||||
|
||||
return loc;
|
||||
@ -1031,7 +859,11 @@ hwloc_obj_t opal_hwloc_base_get_obj_by_type(hwloc_topology_t topo,
|
||||
* use the hwloc accessor to get it, unless it is a CACHE
|
||||
* as these are treated as special cases
|
||||
*/
|
||||
if (OPAL_HWLOC_LOGICAL == rtype && HWLOC_OBJ_CACHE != target) {
|
||||
if (OPAL_HWLOC_LOGICAL == rtype
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
&& HWLOC_OBJ_CACHE != target
|
||||
#endif
|
||||
) {
|
||||
return hwloc_get_obj_by_type(topo, target, instance);
|
||||
}
|
||||
|
||||
@ -1094,7 +926,6 @@ static int socket_to_cpu_set(char *cpus,
|
||||
int lower_range, upper_range;
|
||||
int socket_id;
|
||||
hwloc_obj_t obj;
|
||||
hwloc_bitmap_t res;
|
||||
|
||||
if ('*' == cpus[0]) {
|
||||
/* requesting cpumask for ALL sockets */
|
||||
@ -1102,8 +933,7 @@ static int socket_to_cpu_set(char *cpus,
|
||||
/* set to all available processors - essentially,
|
||||
* this specification equates to unbound
|
||||
*/
|
||||
res = opal_hwloc_base_get_available_cpus(topo, obj);
|
||||
hwloc_bitmap_or(cpumask, cpumask, res);
|
||||
hwloc_bitmap_or(cpumask, cpumask, obj->cpuset);
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
@ -1114,8 +944,7 @@ static int socket_to_cpu_set(char *cpus,
|
||||
socket_id = atoi(range[0]);
|
||||
obj = opal_hwloc_base_get_obj_by_type(topo, HWLOC_OBJ_SOCKET, 0, socket_id, rtype);
|
||||
/* get the available cpus for this socket */
|
||||
res = opal_hwloc_base_get_available_cpus(topo, obj);
|
||||
hwloc_bitmap_or(cpumask, cpumask, res);
|
||||
hwloc_bitmap_or(cpumask, cpumask, obj->cpuset);
|
||||
break;
|
||||
|
||||
case 2: /* range of sockets was given */
|
||||
@ -1124,10 +953,8 @@ static int socket_to_cpu_set(char *cpus,
|
||||
/* cycle across the range of sockets */
|
||||
for (socket_id=lower_range; socket_id<=upper_range; socket_id++) {
|
||||
obj = opal_hwloc_base_get_obj_by_type(topo, HWLOC_OBJ_SOCKET, 0, socket_id, rtype);
|
||||
/* get the available cpus for this socket */
|
||||
res = opal_hwloc_base_get_available_cpus(topo, obj);
|
||||
/* set the corresponding bits in the bitmask */
|
||||
hwloc_bitmap_or(cpumask, cpumask, res);
|
||||
/* set the available cpus for this socket bits in the bitmask */
|
||||
hwloc_bitmap_or(cpumask, cpumask, obj->cpuset);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1151,7 +978,6 @@ static int socket_core_to_cpu_set(char *socket_core_list,
|
||||
int lower_range, upper_range;
|
||||
int socket_id, core_id;
|
||||
hwloc_obj_t socket, core;
|
||||
hwloc_cpuset_t res;
|
||||
unsigned int idx;
|
||||
hwloc_obj_type_t obj_type = HWLOC_OBJ_CORE;
|
||||
|
||||
@ -1181,9 +1007,8 @@ static int socket_core_to_cpu_set(char *socket_core_list,
|
||||
corestr = socket_core[i];
|
||||
}
|
||||
if ('*' == corestr[0]) {
|
||||
/* set to all available cpus on this socket */
|
||||
res = opal_hwloc_base_get_available_cpus(topo, socket);
|
||||
hwloc_bitmap_or(cpumask, cpumask, res);
|
||||
/* set to all cpus on this socket */
|
||||
hwloc_bitmap_or(cpumask, cpumask, socket->cpuset);
|
||||
/* we are done - already assigned all cores! */
|
||||
rc = OPAL_SUCCESS;
|
||||
break;
|
||||
@ -1207,8 +1032,7 @@ static int socket_core_to_cpu_set(char *socket_core_list,
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
/* get the cpus */
|
||||
res = opal_hwloc_base_get_available_cpus(topo, core);
|
||||
hwloc_bitmap_or(cpumask, cpumask, res);
|
||||
hwloc_bitmap_or(cpumask, cpumask, core->cpuset);
|
||||
}
|
||||
opal_argv_free(list);
|
||||
break;
|
||||
@ -1229,10 +1053,8 @@ static int socket_core_to_cpu_set(char *socket_core_list,
|
||||
opal_argv_free(socket_core);
|
||||
return OPAL_ERR_NOT_FOUND;
|
||||
}
|
||||
/* get the cpus */
|
||||
res = opal_hwloc_base_get_available_cpus(topo, core);
|
||||
/* add them into the result */
|
||||
hwloc_bitmap_or(cpumask, cpumask, res);
|
||||
/* get the cpus add them into the result */
|
||||
hwloc_bitmap_or(cpumask, cpumask, core->cpuset);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1257,7 +1079,6 @@ int opal_hwloc_base_cpu_list_parse(const char *slot_str,
|
||||
char **item, **rngs;
|
||||
int rc, i, j, k;
|
||||
hwloc_obj_t pu;
|
||||
hwloc_cpuset_t pucpus;
|
||||
char **range, **list;
|
||||
size_t range_cnt;
|
||||
int core_id, lower_range, upper_range;
|
||||
@ -1351,10 +1172,8 @@ int opal_hwloc_base_cpu_list_parse(const char *slot_str,
|
||||
opal_argv_free(list);
|
||||
return OPAL_ERR_SILENT;
|
||||
}
|
||||
/* get the available cpus for that object */
|
||||
pucpus = opal_hwloc_base_get_available_cpus(topo, pu);
|
||||
/* set that in the mask */
|
||||
hwloc_bitmap_or(cpumask, cpumask, pucpus);
|
||||
/* get the cpus for that object and set them in the massk*/
|
||||
hwloc_bitmap_or(cpumask, cpumask, pu->cpuset);
|
||||
}
|
||||
opal_argv_free(list);
|
||||
break;
|
||||
@ -1370,10 +1189,8 @@ int opal_hwloc_base_cpu_list_parse(const char *slot_str,
|
||||
opal_argv_free(rngs);
|
||||
return OPAL_ERR_SILENT;
|
||||
}
|
||||
/* get the available cpus for that object */
|
||||
pucpus = opal_hwloc_base_get_available_cpus(topo, pu);
|
||||
/* set that in the mask */
|
||||
hwloc_bitmap_or(cpumask, cpumask, pucpus);
|
||||
/* get the cpus for that object and set them in the mask*/
|
||||
hwloc_bitmap_or(cpumask, cpumask, pu->cpuset);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1398,7 +1215,6 @@ opal_hwloc_locality_t opal_hwloc_base_get_relative_locality(hwloc_topology_t top
|
||||
opal_hwloc_locality_t locality;
|
||||
hwloc_obj_t obj;
|
||||
unsigned depth, d, width, w;
|
||||
hwloc_cpuset_t avail;
|
||||
bool shared;
|
||||
hwloc_obj_type_t type;
|
||||
int sect1, sect2;
|
||||
@ -1432,7 +1248,13 @@ opal_hwloc_locality_t opal_hwloc_base_get_relative_locality(hwloc_topology_t top
|
||||
/* if it isn't one of interest, then ignore it */
|
||||
if (HWLOC_OBJ_NODE != type &&
|
||||
HWLOC_OBJ_SOCKET != type &&
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
HWLOC_OBJ_CACHE != type &&
|
||||
#else
|
||||
HWLOC_OBJ_L3CACHE != type &&
|
||||
HWLOC_OBJ_L2CACHE != type &&
|
||||
HWLOC_OBJ_L1CACHE != type &&
|
||||
#endif
|
||||
HWLOC_OBJ_CORE != type &&
|
||||
HWLOC_OBJ_PU != type) {
|
||||
continue;
|
||||
@ -1446,11 +1268,9 @@ opal_hwloc_locality_t opal_hwloc_base_get_relative_locality(hwloc_topology_t top
|
||||
for (w=0; w < width; w++) {
|
||||
/* get the object at this depth/index */
|
||||
obj = hwloc_get_obj_by_depth(topo, d, w);
|
||||
/* get the available cpuset for this obj */
|
||||
avail = opal_hwloc_base_get_available_cpus(topo, obj);
|
||||
/* see if our locations intersect with it */
|
||||
sect1 = hwloc_bitmap_intersects(avail, loc1);
|
||||
sect2 = hwloc_bitmap_intersects(avail, loc2);
|
||||
/* see if our locations intersect with the cpuset for this obj */
|
||||
sect1 = hwloc_bitmap_intersects(obj->cpuset, loc1);
|
||||
sect2 = hwloc_bitmap_intersects(obj->cpuset, loc2);
|
||||
/* if both intersect, then we share this level */
|
||||
if (sect1 && sect2) {
|
||||
shared = true;
|
||||
@ -1461,6 +1281,7 @@ opal_hwloc_locality_t opal_hwloc_base_get_relative_locality(hwloc_topology_t top
|
||||
case HWLOC_OBJ_SOCKET:
|
||||
locality |= OPAL_PROC_ON_SOCKET;
|
||||
break;
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
case HWLOC_OBJ_CACHE:
|
||||
if (3 == obj->attr->cache.depth) {
|
||||
locality |= OPAL_PROC_ON_L3CACHE;
|
||||
@ -1470,6 +1291,17 @@ opal_hwloc_locality_t opal_hwloc_base_get_relative_locality(hwloc_topology_t top
|
||||
locality |= OPAL_PROC_ON_L1CACHE;
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case HWLOC_OBJ_L3CACHE:
|
||||
locality |= OPAL_PROC_ON_L3CACHE;
|
||||
break;
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
locality |= OPAL_PROC_ON_L2CACHE;
|
||||
break;
|
||||
case HWLOC_OBJ_L1CACHE:
|
||||
locality |= OPAL_PROC_ON_L1CACHE;
|
||||
break;
|
||||
#endif
|
||||
case HWLOC_OBJ_CORE:
|
||||
locality |= OPAL_PROC_ON_CORE;
|
||||
break;
|
||||
@ -1866,9 +1698,7 @@ int opal_hwloc_base_cset2str(char *str, int len,
|
||||
|
||||
/* if the cpuset includes all available cpus, then we are unbound */
|
||||
root = hwloc_get_root_obj(topo);
|
||||
if (NULL == root->userdata) {
|
||||
opal_hwloc_base_filter_cpus(topo);
|
||||
} else {
|
||||
if (NULL != root->userdata) {
|
||||
sum = (opal_hwloc_topo_data_t*)root->userdata;
|
||||
if (NULL == sum->available) {
|
||||
return OPAL_ERROR;
|
||||
@ -1936,9 +1766,7 @@ int opal_hwloc_base_cset2mapstr(char *str, int len,
|
||||
|
||||
/* if the cpuset includes all available cpus, then we are unbound */
|
||||
root = hwloc_get_root_obj(topo);
|
||||
if (NULL == root->userdata) {
|
||||
opal_hwloc_base_filter_cpus(topo);
|
||||
} else {
|
||||
if (NULL != root->userdata) {
|
||||
sum = (opal_hwloc_topo_data_t*)root->userdata;
|
||||
if (NULL == sum->available) {
|
||||
return OPAL_ERROR;
|
||||
@ -2009,13 +1837,14 @@ static void sort_by_dist(hwloc_topology_t topo, char* device_name, opal_list_t *
|
||||
{
|
||||
hwloc_obj_t device_obj = NULL;
|
||||
hwloc_obj_t obj = NULL, root = NULL;
|
||||
const struct hwloc_distances_s* distances;
|
||||
struct hwloc_distances_s* distances;
|
||||
opal_rmaps_numa_node_t *numa_node;
|
||||
int close_node_index;
|
||||
float latency;
|
||||
unsigned int j;
|
||||
int depth;
|
||||
unsigned i;
|
||||
unsigned distances_nr = 0;
|
||||
|
||||
for (device_obj = hwloc_get_obj_by_type(topo, HWLOC_OBJ_OS_DEVICE, 0); device_obj; device_obj = hwloc_get_next_osdev(topo, device_obj)) {
|
||||
if (device_obj->attr->osdev.type == HWLOC_OBJ_OSDEV_OPENFABRICS
|
||||
@ -2036,6 +1865,7 @@ static void sort_by_dist(hwloc_topology_t topo, char* device_name, opal_list_t *
|
||||
}
|
||||
|
||||
/* find distance matrix for all numa nodes */
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
distances = hwloc_get_whole_distance_matrix_by_type(topo, HWLOC_OBJ_NODE);
|
||||
if (NULL == distances) {
|
||||
/* we can try to find distances under group object. This info can be there. */
|
||||
@ -2072,6 +1902,22 @@ static void sort_by_dist(hwloc_topology_t topo, char* device_name, opal_list_t *
|
||||
numa_node->dist_from_closed = latency;
|
||||
opal_list_append(sorted_list, &numa_node->super);
|
||||
}
|
||||
#else
|
||||
if (0 != hwloc_distances_get_by_type(topo, HWLOC_OBJ_NODE, &distances_nr, &distances, 0, 0) || 0 == distances_nr) {
|
||||
opal_output_verbose(5, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base:get_sorted_numa_list: There is no information about distances on the node.");
|
||||
return;
|
||||
}
|
||||
/* fill list of numa nodes */
|
||||
for (j = 0; j < distances->nbobjs; j++) {
|
||||
latency = distances->values[close_node_index + distances->nbobjs * j];
|
||||
numa_node = OBJ_NEW(opal_rmaps_numa_node_t);
|
||||
numa_node->index = j;
|
||||
numa_node->dist_from_closed = latency;
|
||||
opal_list_append(sorted_list, &numa_node->super);
|
||||
}
|
||||
hwloc_distances_release(topo, distances);
|
||||
#endif
|
||||
/* sort numa nodes by distance from the closest one to PCI */
|
||||
opal_list_sort(sorted_list, dist_cmp_fn);
|
||||
return;
|
||||
@ -2164,9 +2010,9 @@ char* opal_hwloc_base_get_topo_signature(hwloc_topology_t topo)
|
||||
|
||||
nnuma = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_NODE, 0, OPAL_HWLOC_AVAILABLE);
|
||||
nsocket = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_SOCKET, 0, OPAL_HWLOC_AVAILABLE);
|
||||
nl3 = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_CACHE, 3, OPAL_HWLOC_AVAILABLE);
|
||||
nl2 = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_CACHE, 2, OPAL_HWLOC_AVAILABLE);
|
||||
nl1 = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_CACHE, 1, OPAL_HWLOC_AVAILABLE);
|
||||
nl3 = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_L3CACHE, 3, OPAL_HWLOC_AVAILABLE);
|
||||
nl2 = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_L2CACHE, 2, OPAL_HWLOC_AVAILABLE);
|
||||
nl1 = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_L1CACHE, 1, OPAL_HWLOC_AVAILABLE);
|
||||
ncore = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_CORE, 0, OPAL_HWLOC_AVAILABLE);
|
||||
nhwt = opal_hwloc_base_get_nbobjs_by_type(topo, HWLOC_OBJ_PU, 0, OPAL_HWLOC_AVAILABLE);
|
||||
|
||||
@ -2203,7 +2049,7 @@ char* opal_hwloc_base_get_locality_string(hwloc_topology_t topo,
|
||||
hwloc_obj_t obj;
|
||||
char *locality=NULL, *tmp, *t2;
|
||||
unsigned depth, d, width, w;
|
||||
hwloc_cpuset_t cpuset, avail, result;
|
||||
hwloc_cpuset_t cpuset, result;
|
||||
hwloc_obj_type_t type;
|
||||
|
||||
/* if this proc is not bound, then there is no locality. We
|
||||
@ -2233,7 +2079,13 @@ char* opal_hwloc_base_get_locality_string(hwloc_topology_t topo,
|
||||
/* if it isn't one of interest, then ignore it */
|
||||
if (HWLOC_OBJ_NODE != type &&
|
||||
HWLOC_OBJ_SOCKET != type &&
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
HWLOC_OBJ_CACHE != type &&
|
||||
#else
|
||||
HWLOC_OBJ_L1CACHE != type &&
|
||||
HWLOC_OBJ_L2CACHE != type &&
|
||||
HWLOC_OBJ_L3CACHE != type &&
|
||||
#endif
|
||||
HWLOC_OBJ_CORE != type &&
|
||||
HWLOC_OBJ_PU != type) {
|
||||
continue;
|
||||
@ -2251,10 +2103,8 @@ char* opal_hwloc_base_get_locality_string(hwloc_topology_t topo,
|
||||
for (w=0; w < width; w++) {
|
||||
/* get the object at this depth/index */
|
||||
obj = hwloc_get_obj_by_depth(topo, d, w);
|
||||
/* get the available cpuset for this obj */
|
||||
avail = opal_hwloc_base_get_available_cpus(topo, obj);
|
||||
/* see if the location intersects with it */
|
||||
if (hwloc_bitmap_intersects(avail, cpuset)) {
|
||||
if (hwloc_bitmap_intersects(obj->cpuset, cpuset)) {
|
||||
hwloc_bitmap_set(result, w);
|
||||
}
|
||||
}
|
||||
@ -2277,6 +2127,7 @@ char* opal_hwloc_base_get_locality_string(hwloc_topology_t topo,
|
||||
}
|
||||
locality = t2;
|
||||
break;
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
case HWLOC_OBJ_CACHE:
|
||||
if (3 == obj->attr->cache.depth) {
|
||||
asprintf(&t2, "%sL3%s:", (NULL == locality) ? "" : locality, tmp);
|
||||
@ -2301,6 +2152,29 @@ char* opal_hwloc_base_get_locality_string(hwloc_topology_t topo,
|
||||
break;
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case HWLOC_OBJ_L3CACHE:
|
||||
asprintf(&t2, "%sL3%s:", (NULL == locality) ? "" : locality, tmp);
|
||||
if (NULL != locality) {
|
||||
free(locality);
|
||||
}
|
||||
locality = t2;
|
||||
break;
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
asprintf(&t2, "%sL2%s:", (NULL == locality) ? "" : locality, tmp);
|
||||
if (NULL != locality) {
|
||||
free(locality);
|
||||
}
|
||||
locality = t2;
|
||||
break;
|
||||
case HWLOC_OBJ_L1CACHE:
|
||||
asprintf(&t2, "%sL1%s:", (NULL == locality) ? "" : locality, tmp);
|
||||
if (NULL != locality) {
|
||||
free(locality);
|
||||
}
|
||||
locality = t2;
|
||||
break;
|
||||
#endif
|
||||
case HWLOC_OBJ_CORE:
|
||||
asprintf(&t2, "%sCR%s:", (NULL == locality) ? "" : locality, tmp);
|
||||
if (NULL != locality) {
|
||||
@ -2351,6 +2225,7 @@ char* opal_hwloc_base_get_location(char *locality,
|
||||
case HWLOC_OBJ_SOCKET:
|
||||
srch = "SK";
|
||||
break;
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
case HWLOC_OBJ_CACHE:
|
||||
if (3 == index) {
|
||||
srch = "L3";
|
||||
@ -2360,6 +2235,17 @@ char* opal_hwloc_base_get_location(char *locality,
|
||||
srch = "L0";
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case HWLOC_OBJ_L3CACHE:
|
||||
srch = "L3";
|
||||
break;
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
srch = "L2";
|
||||
break;
|
||||
case HWLOC_OBJ_L1CACHE:
|
||||
srch = "L0";
|
||||
break;
|
||||
#endif
|
||||
case HWLOC_OBJ_CORE:
|
||||
srch = "CR";
|
||||
break;
|
||||
@ -2445,3 +2331,23 @@ opal_hwloc_locality_t opal_hwloc_compute_relative_locality(char *loc1, char *loc
|
||||
hwloc_bitmap_free(bit2);
|
||||
return locality;
|
||||
}
|
||||
|
||||
int opal_hwloc_base_topology_export_xmlbuffer(hwloc_topology_t topology, char **xmlpath, int *buflen) {
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
return hwloc_topology_export_xmlbuffer(topology, xmlpath, buflen);
|
||||
#else
|
||||
return hwloc_topology_export_xmlbuffer(topology, xmlpath, buflen, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int opal_hwloc_base_topology_set_flags (hwloc_topology_t topology, unsigned long flags, bool io) {
|
||||
if (io) {
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
flags |= HWLOC_TOPOLOGY_FLAG_IO_DEVICES;
|
||||
#else
|
||||
int ret = hwloc_topology_set_io_types_filter(topology, HWLOC_TYPE_FILTER_KEEP_IMPORTANT);
|
||||
if (0 != ret) return ret;
|
||||
#endif
|
||||
}
|
||||
return hwloc_topology_set_flags(topology, flags);
|
||||
}
|
||||
|
19
opal/mca/hwloc/external/configure.m4
поставляемый
19
opal/mca/hwloc/external/configure.m4
поставляемый
@ -103,7 +103,8 @@ AC_DEFUN([MCA_opal_hwloc_external_CONFIG],[
|
||||
AS_IF([test "$with_hwloc" = "external"], [opal_hwloc_external_want=yes])
|
||||
AS_IF([test "$with_hwloc" != "" && \
|
||||
test "$with_hwloc" != "no" && \
|
||||
test "$with_hwloc" != "internal"], [opal_hwloc_external_want=yes])
|
||||
test "$with_hwloc" != "internal" && \
|
||||
test "$with_hwloc" != "future"], [opal_hwloc_external_want=yes])
|
||||
AS_IF([test "$with_hwloc" = "no"], [opal_hwloc_external_want=no])
|
||||
|
||||
# If we still want external support, try it
|
||||
@ -183,21 +184,7 @@ AC_DEFUN([MCA_opal_hwloc_external_CONFIG],[
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([Cannot continue])])
|
||||
AC_MSG_CHECKING([if external hwloc version is lower than 2.0])
|
||||
AS_IF([test "$opal_hwloc_dir" != ""],
|
||||
[opal_hwloc_external_CFLAGS_save=$CFLAGS
|
||||
CFLAGS="-I$opal_hwloc_dir/include $opal_hwloc_external_CFLAGS_save"])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([[#include <hwloc.h>]],
|
||||
[[
|
||||
#if HWLOC_API_VERSION >= 0x00020000
|
||||
#error "hwloc API version is greater or equal than 0x00020000"
|
||||
#endif
|
||||
]])],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([OMPI does not currently support hwloc v2 API
|
||||
Cannot continue])])
|
||||
|
||||
AS_IF([test "$opal_hwloc_dir" != ""],
|
||||
[CFLAGS=$opal_hwloc_external_CFLAGS_save])
|
||||
|
||||
|
@ -88,7 +88,8 @@ AC_DEFUN([MCA_opal_hwloc_hwloc1116_CONFIG],[
|
||||
|
||||
# Run the hwloc configuration - if no external hwloc, then set the prefixi
|
||||
# to minimize the chance that someone will use the internal symbols
|
||||
AS_IF([test "$opal_hwloc_external" = "no"],
|
||||
AS_IF([test "$opal_hwloc_external" = "no" &&
|
||||
test "$with_hwloc" != "future"],
|
||||
[HWLOC_SET_SYMBOL_PREFIX([opal_hwloc1116_])])
|
||||
|
||||
# save XML or graphical options
|
||||
|
39
opal/mca/hwloc/hwloc2x/Makefile.am
Обычный файл
39
opal/mca/hwloc/hwloc2x/Makefile.am
Обычный файл
@ -0,0 +1,39 @@
|
||||
#
|
||||
# Copyright (c) 2011-2016 Cisco Systems, Inc. All rights reserved.
|
||||
# Copyright (c) 2014-2015 Intel, Inc. All right reserved.
|
||||
# Copyright (c) 2016 Los Alamos National Security, LLC. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2017 Research Organization for Information Science
|
||||
# and Technology (RIST). All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
EXTRA_DIST = autogen.subdirs
|
||||
|
||||
SUBDIRS = hwloc
|
||||
DIST_SUBDIRS=hwloc
|
||||
|
||||
# Headers and sources
|
||||
headers = hwloc2x.h
|
||||
sources = hwloc2x_component.c
|
||||
|
||||
libs = hwloc/hwloc/libhwloc_embedded.la
|
||||
|
||||
# We only ever build this component statically
|
||||
noinst_LTLIBRARIES = libmca_hwloc_hwloc2x.la
|
||||
libmca_hwloc_hwloc2x_la_SOURCES = $(headers) $(sources)
|
||||
nodist_libmca_hwloc_hwloc2x_la_SOURCES = $(nodist_headers)
|
||||
libmca_hwloc_hwloc2x_la_LDFLAGS = -module -avoid-version
|
||||
libmca_hwloc_hwloc2x_la_LIBADD = $(libs)
|
||||
libmca_hwloc_hwloc2x_la_DEPENDENCIES = $(libs)
|
||||
|
||||
# Conditionally install the header files
|
||||
if WANT_INSTALL_HEADERS
|
||||
opaldir = $(opalincludedir)/$(subdir)
|
||||
nobase_opal_HEADERS = $(headers)
|
||||
nobase_nodist_opal_HEADERS = $(nodist_headers)
|
||||
endif
|
1
opal/mca/hwloc/hwloc2x/autogen.subdirs
Обычный файл
1
opal/mca/hwloc/hwloc2x/autogen.subdirs
Обычный файл
@ -0,0 +1 @@
|
||||
hwloc
|
112
opal/mca/hwloc/hwloc2x/configure.m4
Обычный файл
112
opal/mca/hwloc/hwloc2x/configure.m4
Обычный файл
@ -0,0 +1,112 @@
|
||||
# -*- shell-script -*-
|
||||
#
|
||||
# Copyright (c) 2009-2017 Cisco Systems, Inc. All rights reserved
|
||||
# Copyright (c) 2014-2015 Intel, Inc. All rights reserved.
|
||||
# Copyright (c) 2015-2017 Research Organization for Information Science
|
||||
# and Technology (RIST). All rights reserved.
|
||||
# Copyright (c) 2016 Los Alamos National Security, LLC. All rights
|
||||
# reserved.
|
||||
#
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
#
|
||||
# Priority
|
||||
#
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc2x_PRIORITY], [90])
|
||||
|
||||
#
|
||||
# Force this component to compile in static-only mode
|
||||
#
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc2x_COMPILE_MODE], [
|
||||
AC_MSG_CHECKING([for MCA component $2:$3 compile mode])
|
||||
$4="static"
|
||||
AC_MSG_RESULT([$$4])
|
||||
])
|
||||
|
||||
# MCA_hwloc_hwloc2x_POST_CONFIG()
|
||||
# ---------------------------------
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc2x_POST_CONFIG],[
|
||||
OPAL_VAR_SCOPE_PUSH([opal_hwloc_hwloc2x_basedir])
|
||||
|
||||
# If we won, then do all the rest of the setup
|
||||
AS_IF([test "$1" = "1" && test "$opal_hwloc_hwloc2x_support" = "yes"],
|
||||
[
|
||||
# Set this variable so that the framework m4 knows what
|
||||
# file to include in opal/mca/hwloc/hwloc-internal.h
|
||||
opal_hwloc_hwloc2x_basedir=opal/mca/hwloc/hwloc2x
|
||||
opal_hwloc_base_include="$opal_hwloc_hwloc2x_basedir/hwloc2x.h"
|
||||
|
||||
# Add some stuff to CPPFLAGS so that the rest of the source
|
||||
# tree can be built
|
||||
file=$opal_hwloc_hwloc2x_basedir/hwloc
|
||||
CPPFLAGS="-I$OPAL_TOP_SRCDIR/$file/include $CPPFLAGS"
|
||||
AS_IF([test "$OPAL_TOP_BUILDDIR" != "$OPAL_TOP_SRCDIR"],
|
||||
[CPPFLAGS="-I$OPAL_TOP_BUILDDIR/$file/include $CPPFLAGS"])
|
||||
unset file
|
||||
])
|
||||
OPAL_VAR_SCOPE_POP
|
||||
])dnl
|
||||
|
||||
|
||||
# MCA_hwloc_hwloc2x_CONFIG([action-if-found], [action-if-not-found])
|
||||
# --------------------------------------------------------------------
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc2x_CONFIG],[
|
||||
# Hwloc needs to know if we have Verbs support
|
||||
AC_REQUIRE([OPAL_CHECK_VERBS_DIR])
|
||||
|
||||
AC_CONFIG_FILES([opal/mca/hwloc/hwloc2x/Makefile])
|
||||
|
||||
OPAL_VAR_SCOPE_PUSH([HWLOC_VERSION opal_hwloc_hwloc2x_flags opal_hwloc_hwloc2x_save_CPPFLAGS opal_hwloc_hwloc2x_basedir opal_hwloc_hwloc2x_file opal_hwloc_future])
|
||||
|
||||
# default to this component not providing support
|
||||
opal_hwloc_hwloc2x_basedir=opal/mca/hwloc/hwloc2x
|
||||
opal_hwloc_hwloc2x_support=no
|
||||
|
||||
AS_IF([test "$with_hwloc" = "future"],
|
||||
[opal_hwloc_future="yes"],
|
||||
[opal_hwloc_future="no"])
|
||||
|
||||
opal_hwloc_hwloc2x_save_CPPFLAGS=$CPPFLAGS
|
||||
|
||||
# Run the hwloc configuration - if no external hwloc, then set the prefix
|
||||
# to minimize the chance that someone will use the internal symbols
|
||||
|
||||
opal_hwloc_hwloc2x_flags="--enable-embedded-mode --with-hwloc-symbol-prefix=opal_hwloc2x_ --disable-cairo --disable-pugins --enable-static --enable-xml"
|
||||
AS_IF([test "$opal_check_cuda_happy" = "yes"],
|
||||
[CPPFLAGS="$CPPFLAGS $opal_datatype_cuda_CPPFLAGS",
|
||||
opal_hwloc_hwloc2x_flags="$opal_hwloc_hwloc2x_flags --enable-nvml CPPFLAGS=\"$CPPFLAGS\""]
|
||||
[opal_hwloc_hwloc2x_flags="$opal_hwloc_hwloc2x_flags --disable-nvml"])
|
||||
|
||||
OPAL_CONFIG_SUBDIR([opal/mca/hwloc/hwloc2x/hwloc],
|
||||
[$opal_hwloc_hwloc2x_flags],
|
||||
[opal_hwloc_hwloc2x_support="yes"],
|
||||
[opal_hwloc_hwloc2x_support="no"])
|
||||
|
||||
CPPFLAGS=$opal_hwloc_hwloc2x_save_CPPFLAGS
|
||||
|
||||
# If we are not building the internal hwloc, then indicate that
|
||||
# this component should not be built. NOTE: we still did all the
|
||||
# above configury so that all the proper GNU Autotools
|
||||
# infrastructure is setup properly (e.g., w.r.t. SUBDIRS=hwloc in
|
||||
# this directory's Makefile.am, we still need the Autotools "make
|
||||
# distclean" infrastructure to work properly).
|
||||
AS_IF([test "$opal_hwloc_future" != "yes"],
|
||||
[AC_MSG_WARN([not using future hwloc; disqualifying this component])
|
||||
opal_hwloc_hwloc2x_support=no])
|
||||
|
||||
# Done!
|
||||
AS_IF([test "$opal_hwloc_hwloc2x_support" = "yes"],
|
||||
[AC_DEFINE_UNQUOTED([HWLOC_SYM_PREFIX],[opal_hwloc2x_])
|
||||
AC_DEFINE_UNQUOTED([HWLOC_SYM_PREFIX_CAPS], [OPAL_HWLOC2X_])
|
||||
AC_DEFINE_UNQUOTED([HWLOC_SYM_TRANSFORM], [1])
|
||||
AC_DEFINE([HAVE_DECL_HWLOC_OBJ_OSDEV_COPROC], [1])
|
||||
$1],
|
||||
[$2])
|
||||
|
||||
OPAL_VAR_SCOPE_POP
|
||||
])dnl
|
29
opal/mca/hwloc/hwloc2x/hwloc/AUTHORS
Обычный файл
29
opal/mca/hwloc/hwloc2x/hwloc/AUTHORS
Обычный файл
@ -0,0 +1,29 @@
|
||||
netloc Authors
|
||||
==============
|
||||
|
||||
The following cumulative list contains the names of most individuals who
|
||||
have committed code to the hwloc repository.
|
||||
|
||||
Name Affiliation(s)
|
||||
--------------------------- --------------------
|
||||
Cédric Augonnet University of Bordeaux
|
||||
Guillaume Beauchamp Inria
|
||||
Ahmad Boissetri Binzagr Inria
|
||||
Cyril Bordage Inria
|
||||
Nicholas Buroker UWL
|
||||
Jérôme Clet-Ortega University of Bordeaux
|
||||
Ludovic Courtès Inria
|
||||
Nathalie Furmento CNRS
|
||||
Brice Goglin Inria
|
||||
Joshua Hursey UWL
|
||||
Alexey Kardashevskiy IBM
|
||||
Douglas MacFarland UWL
|
||||
Antoine Rougier intern from University of Bordeaux
|
||||
Jeff Squyres Cisco
|
||||
Samuel Thibault University of Bordeaux
|
||||
|
||||
Affiliaion abbreviations:
|
||||
-------------------------
|
||||
Cisco = Cisco Systems, Inc.
|
||||
CNRS = Centre national de la recherche scientifique (France)
|
||||
UWL = University of Wisconsin-La Crosse
|
39
opal/mca/hwloc/hwloc2x/hwloc/COPYING
Обычный файл
39
opal/mca/hwloc/hwloc2x/hwloc/COPYING
Обычный файл
@ -0,0 +1,39 @@
|
||||
Copyright © 2004-2006 The Trustees of Indiana University and Indiana University Research and Technology Corporation. All rights reserved.
|
||||
Copyright © 2004-2005 The University of Tennessee and The University of Tennessee Research Foundation. All rights reserved.
|
||||
Copyright © 2004-2005 High Performance Computing Center Stuttgart, University of Stuttgart. All rights reserved.
|
||||
Copyright © 2004-2005 The Regents of the University of California. All rights reserved.
|
||||
Copyright © 2009 CNRS
|
||||
Copyright © 2009-2016 Inria. All rights reserved.
|
||||
Copyright © 2009-2015 Université Bordeaux
|
||||
Copyright © 2009-2015 Cisco Systems, Inc. All rights reserved.
|
||||
Copyright © 2009-2012 Oracle and/or its affiliates. All rights reserved.
|
||||
Copyright © 2010 IBM
|
||||
Copyright © 2010 Jirka Hladky
|
||||
Copyright © 2012 Aleksej Saushev, The NetBSD Foundation
|
||||
Copyright © 2012 Blue Brain Project, EPFL. All rights reserved.
|
||||
Copyright © 2013-2014 University of Wisconsin-La Crosse. All rights reserved.
|
||||
Copyright © 2015 Research Organization for Information Science and Technology (RIST). All rights reserved.
|
||||
Copyright © 2015-2016 Intel, Inc. All rights reserved.
|
||||
See COPYING in top-level directory.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
89
opal/mca/hwloc/hwloc2x/hwloc/Makefile.am
Обычный файл
89
opal/mca/hwloc/hwloc2x/hwloc/Makefile.am
Обычный файл
@ -0,0 +1,89 @@
|
||||
# Copyright © 2009-2016 Inria. All rights reserved.
|
||||
# Copyright © 2009 Université Bordeaux
|
||||
# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved.
|
||||
# See COPYING in top-level directory.
|
||||
|
||||
# Note that the -I directory must *exactly* match what was specified
|
||||
# via AC_CONFIG_MACRO_DIR in configure.ac.
|
||||
ACLOCAL_AMFLAGS = -I ./config
|
||||
|
||||
#
|
||||
# "make distcheck" requires that tarballs are able to be able to "make
|
||||
# dist", so we have to include config/distscript.sh.
|
||||
#
|
||||
EXTRA_DIST = \
|
||||
README VERSION COPYING AUTHORS \
|
||||
config/hwloc_get_version.sh \
|
||||
config/distscript.sh
|
||||
|
||||
SUBDIRS = include hwloc
|
||||
|
||||
if BUILD_NETLOC
|
||||
SUBDIRS += netloc
|
||||
endif
|
||||
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
SUBDIRS += utils tests contrib/systemd contrib/misc
|
||||
# We need doc/ if HWLOC_BUILD_DOXYGEN, or during make install if HWLOC_INSTALL_DOXYGEN.
|
||||
# There's no INSTALL_SUBDIRS, so always enter doc/ and check HWLOC_BUILD/INSTALL_DOXYGEN there
|
||||
SUBDIRS += doc
|
||||
endif
|
||||
|
||||
# Do not let automake automatically add the non-standalone dirs to the
|
||||
# distribution tarball if we're building in embedded mode.
|
||||
DIST_SUBDIRS = $(SUBDIRS)
|
||||
|
||||
# Only install the pkg file if we're building in standalone mode (and not on Windows)
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = hwloc.pc
|
||||
if BUILD_NETLOC
|
||||
# JMS Need to compare hwloc.pc and netloc.pc -- I think netloc.pc is
|
||||
# missing some things.
|
||||
# pkgconfig_DATA += netloc.pc Disabled until the netloc API is public
|
||||
EXTRA_DIST += netloc.pc
|
||||
if BUILD_NETLOCSCOTCH
|
||||
pkgconfig_DATA += netlocscotch.pc
|
||||
endif BUILD_NETLOCSCOTCH
|
||||
endif BUILD_NETLOC
|
||||
endif HWLOC_BUILD_STANDALONE
|
||||
|
||||
# Only install the valgrind suppressions file if we're building in
|
||||
# standalone mode
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
dist_pkgdata_DATA = contrib/hwloc-valgrind.supp
|
||||
endif
|
||||
|
||||
# Only install entire visual studio subdirectory if we're building in
|
||||
# standalone mode
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
EXTRA_DIST += contrib/windows
|
||||
endif
|
||||
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
dist-hook:
|
||||
sh "$(top_srcdir)/config/distscript.sh" "$(top_srcdir)" "$(distdir)" "$(HWLOC_VERSION)"
|
||||
endif HWLOC_BUILD_STANDALONE
|
||||
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
if HWLOC_HAVE_WINDOWS
|
||||
#
|
||||
# Winball specific rules
|
||||
#
|
||||
install-data-local:
|
||||
sed -e 's/$$/'$$'\015'/ < $(srcdir)/README > $(DESTDIR)$(prefix)/README.txt
|
||||
sed -e 's/$$/'$$'\015'/ < $(srcdir)/NEWS > $(DESTDIR)$(prefix)/NEWS.txt
|
||||
sed -e 's/$$/'$$'\015'/ < $(srcdir)/COPYING > $(DESTDIR)$(prefix)/COPYING.txt
|
||||
uninstall-local:
|
||||
rm -f $(DESTDIR)$(prefix)/README.txt $(DESTDIR)$(prefix)/NEWS.txt $(DESTDIR)$(prefix)/COPYING.txt
|
||||
endif HWLOC_HAVE_WINDOWS
|
||||
endif HWLOC_BUILD_STANDALONE
|
||||
|
||||
#
|
||||
# Build the documenation and top-level README file
|
||||
#
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
.PHONY: doc readme
|
||||
doc readme:
|
||||
$(MAKE) -C doc
|
||||
endif HWLOC_BUILD_STANDALONE
|
1482
opal/mca/hwloc/hwloc2x/hwloc/NEWS
Обычный файл
1482
opal/mca/hwloc/hwloc2x/hwloc/NEWS
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
65
opal/mca/hwloc/hwloc2x/hwloc/README
Обычный файл
65
opal/mca/hwloc/hwloc2x/hwloc/README
Обычный файл
@ -0,0 +1,65 @@
|
||||
Introduction
|
||||
|
||||
The Hardware Locality (hwloc) software project aims at easing the process of
|
||||
discovering hardware resources in parallel architectures. It offers
|
||||
command-line tools and a C API for consulting these resources, their locality,
|
||||
attributes, and interconnection. hwloc primarily aims at helping
|
||||
high-performance computing (HPC) applications, but is also applicable to any
|
||||
project seeking to exploit code and/or data locality on modern computing
|
||||
platforms.
|
||||
|
||||
hwloc is actually made of two subprojects distributed together:
|
||||
|
||||
* The original hwloc project for describing the internals of computing nodes.
|
||||
It is described in details between sections Hardware Locality (hwloc)
|
||||
Introduction and Network Locality (netloc).
|
||||
* The network-oriented companion called netloc (Network Locality), described
|
||||
in details starting at section Network Locality (netloc). Netloc may be
|
||||
disabled, but the original hwloc cannot. Both hwloc and netloc APIs are
|
||||
documented after these sections.
|
||||
|
||||
Installation
|
||||
|
||||
hwloc (http://www.open-mpi.org/projects/hwloc/) is available under the BSD
|
||||
license. It is hosted as a sub-project of the overall Open MPI project (http://
|
||||
www.open-mpi.org/). Note that hwloc does not require any functionality from
|
||||
Open MPI -- it is a wholly separate (and much smaller!) project and code base.
|
||||
It just happens to be hosted as part of the overall Open MPI project.
|
||||
|
||||
Nightly development snapshots are available on the web site. Additionally, the
|
||||
code can be directly cloned from Git:
|
||||
|
||||
shell$ git clone https://github.com/open-mpi/hwloc.git
|
||||
shell$ cd hwloc
|
||||
shell$ ./autogen.sh
|
||||
|
||||
Note that GNU Autoconf >=2.63, Automake >=1.11 and Libtool >=2.2.6 are required
|
||||
when building from a Git clone.
|
||||
|
||||
Installation by itself is the fairly common GNU-based process:
|
||||
|
||||
shell$ ./configure --prefix=...
|
||||
shell$ make
|
||||
shell$ make install
|
||||
|
||||
hwloc- and netloc-specific configure options and requirements are documented in
|
||||
sections hwloc Installation and Netloc Installation respectively.
|
||||
|
||||
Also note that if you install supplemental libraries in non-standard locations,
|
||||
hwloc's configure script may not be able to find them without some help. You
|
||||
may need to specify additional CPPFLAGS, LDFLAGS, or PKG_CONFIG_PATH values on
|
||||
the configure command line.
|
||||
|
||||
For example, if libpciaccess was installed into /opt/pciaccess, hwloc's
|
||||
configure script may not find it be default. Try adding PKG_CONFIG_PATH to the
|
||||
./configure command line, like this:
|
||||
|
||||
./configure PKG_CONFIG_PATH=/opt/pciaccess/lib/pkgconfig ...
|
||||
|
||||
Running the "lstopo" tool is a good way to check as a graphical output whether
|
||||
hwloc properly detected the architecture of your node. Netloc command-line
|
||||
tools can be used to display the network topology interconnecting your nodes.
|
||||
|
||||
|
||||
|
||||
See https://www.open-mpi.org/projects/hwloc/doc/ for more hwloc documentation.
|
47
opal/mca/hwloc/hwloc2x/hwloc/VERSION
Обычный файл
47
opal/mca/hwloc/hwloc2x/hwloc/VERSION
Обычный файл
@ -0,0 +1,47 @@
|
||||
# This is the VERSION file for hwloc, describing the precise version
|
||||
# of hwloc in this distribution. The various components of the version
|
||||
# number below are combined to form a single version number string.
|
||||
|
||||
# major, minor, and release are generally combined in the form
|
||||
# <major>.<minor>.<release>. If release is zero, then it is omitted.
|
||||
|
||||
# Please update HWLOC_VERSION in contrib/windows/private_config.h too.
|
||||
|
||||
major=2
|
||||
minor=0
|
||||
release=0
|
||||
|
||||
# greek is used for alpha or beta release tags. If it is non-empty,
|
||||
# it will be appended to the version number. It does not have to be
|
||||
# numeric. Common examples include a1 (alpha release 1), b1 (beta
|
||||
# release 1), sc2005 (Super Computing 2005 release). The only
|
||||
# requirement is that it must be entirely printable ASCII characters
|
||||
# and have no white space.
|
||||
|
||||
greek=a1
|
||||
|
||||
# The date when this release was created
|
||||
|
||||
date="Unreleased developer copy"
|
||||
|
||||
# If snapshot=1, then use the value from snapshot_version as the
|
||||
# entire hwloc version (i.e., ignore major, minor, release, and
|
||||
# greek). This is only set to 1 when making snapshot tarballs.
|
||||
snapshot=1
|
||||
snapshot_version=${major}.${minor}.${release}${greek}-git
|
||||
|
||||
# The shared library version of hwloc's public library. This version
|
||||
# is maintained in accordance with the "Library Interface Versions"
|
||||
# chapter from the GNU Libtool documentation. Notes:
|
||||
|
||||
# 1. Since version numbers are associated with *releases*, the version
|
||||
# number maintained on the hwloc git master (and developer branches)
|
||||
# is always 0:0:0.
|
||||
|
||||
# 2. Version numbers are described in the Libtool current:revision:age
|
||||
# format.
|
||||
|
||||
libhwloc_so_version=0:0:0
|
||||
libnetloc_so_version=0:0:0
|
||||
|
||||
# Please also update the <TargetName> lines in contrib/windows/libhwloc.vcxproj
|
2
opal/mca/hwloc/hwloc2x/hwloc/autogen.sh
Исполняемый файл
2
opal/mca/hwloc/hwloc2x/hwloc/autogen.sh
Исполняемый файл
@ -0,0 +1,2 @@
|
||||
:
|
||||
autoreconf ${autoreconf_args:-"-ivf"}
|
130
opal/mca/hwloc/hwloc2x/hwloc/config/distscript.sh
Исполняемый файл
130
opal/mca/hwloc/hwloc2x/hwloc/config/distscript.sh
Исполняемый файл
@ -0,0 +1,130 @@
|
||||
#!/bin/sh -f
|
||||
#
|
||||
# Copyright © 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright © 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright © 2004-2005 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright © 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright © 2010-2014 Inria. All rights reserved.
|
||||
# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
builddir="`pwd`"
|
||||
|
||||
srcdir=$1
|
||||
cd "$srcdir"
|
||||
srcdir=`pwd`
|
||||
cd "$builddir"
|
||||
|
||||
distdir="$builddir/$2"
|
||||
HWLOC_VERSION=$3
|
||||
|
||||
if test "$distdir" = ""; then
|
||||
echo "Must supply relative distdir as argv[2] -- aborting"
|
||||
exit 1
|
||||
elif test "$HWLOC_VERSION" = ""; then
|
||||
echo "Must supply version as argv[1] -- aborting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#========================================================================
|
||||
|
||||
start=`date`
|
||||
cat <<EOF
|
||||
|
||||
Creating hwloc distribution
|
||||
In directory: `pwd`
|
||||
Srcdir: $srcdir
|
||||
Builddir: $builddir
|
||||
Version: $HWLOC_VERSION
|
||||
Started: $start
|
||||
|
||||
EOF
|
||||
|
||||
umask 022
|
||||
|
||||
if test ! -d "$distdir"; then
|
||||
echo "*** ERROR: dist dir does not exist"
|
||||
echo "*** ERROR: $distdir"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test ! -d $srcdir/doc/doxygen-doc; then
|
||||
echo "*** The srcdir does not already have a doxygen-doc tree built."
|
||||
echo "*** hwloc's config/distscript.csh requires the docs to be built"
|
||||
echo "*** in the srcdir before executing 'make dist'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Trivial helper function
|
||||
doit() {
|
||||
echo $*
|
||||
eval $*
|
||||
}
|
||||
|
||||
echo "*** Copying doxygen-doc tree to dist..."
|
||||
echo "*** Directory: srcdir: $srcdir, distdir: $distdir, pwd: `pwd`"
|
||||
doit mkdir -p $distdir/doc/doxygen-doc
|
||||
doit chmod -R a=rwx $distdir/doc/doxygen-doc
|
||||
doit rm -rf $distdir/doc/doxygen-doc
|
||||
|
||||
# We want to copy the entire directory tree to the distdir. In some
|
||||
# cases, doxygen-doc may be a sym link, so we want the copy to follow
|
||||
# the sym links. It's a bit of a portability nightmare, so try a few
|
||||
# different ways...
|
||||
# This seems to work on OS X and Linux (but not Solaris)
|
||||
doit "tar c -C $srcdir -h -f - doc/doxygen-doc | tar x -C $distdir -f -"
|
||||
if test ! -d $distdir/doc/doxygen-doc; then
|
||||
# This seems to work on Linux and Solaris
|
||||
doit cp -rpf $srcdir/doc/doxygen-doc/ $distdir/doc
|
||||
fi
|
||||
if test ! -d $distdir/doc/doxygen-doc; then
|
||||
# This seems to work on OS X (probably redundant, but we know it works)
|
||||
doit cp -rpf $srcdir/doc/doxygen-doc $distdir/doc
|
||||
fi
|
||||
# If we still failed, just error out
|
||||
if test ! -d $distdir/doc/doxygen-doc; then
|
||||
echo "ERROR: Cannot seem to copy a directory to the distdir :-("
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "*** Copying new README"
|
||||
ls -lf $distdir/README
|
||||
doit cp -pf $srcdir/README $distdir
|
||||
|
||||
#########################################################
|
||||
# VERY IMPORTANT: Now go into the new distribution tree #
|
||||
#########################################################
|
||||
cd "$distdir"
|
||||
echo "*** Now in distdir: $distdir"
|
||||
|
||||
#
|
||||
# Remove all the latex source files from the distribution tree (the
|
||||
# PDFs are still there; we're just removing the latex source because
|
||||
# some of the filenames get really, really long...).
|
||||
#
|
||||
|
||||
echo "*** Removing latex source from dist tree"
|
||||
doit rm -rf doc/doxygen-doc/latex
|
||||
|
||||
#
|
||||
# All done
|
||||
#
|
||||
|
||||
cat <<EOF
|
||||
*** hwloc version $HWLOC_VERSION distribution created
|
||||
|
||||
Started: $start
|
||||
Ended: `date`
|
||||
|
||||
EOF
|
13
opal/mca/hwloc/hwloc2x/hwloc/config/distscript_embedded.sh
Исполняемый файл
13
opal/mca/hwloc/hwloc2x/hwloc/config/distscript_embedded.sh
Исполняемый файл
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
chmod u+w $2
|
||||
makefiles="$2/doc/Makefile.am $2/doc/examples/Makefile.am $2/doc/doxygen-config.cfg.in $2/utils/Makefile.am $2/utils/hwloc/Makefile.am $2/utils/lstopo/Makefile.am $2/utils/netloc/infiniband/Makefile.am $2/utils/netloc/draw/Makefile.am $2/utils/netloc/mpi/Makefile.am $2/tests/Makefile.am $2/tests/hwloc/Makefile.am $2/tests/hwloc/linux/Makefile.am $2/tests/hwloc/linux/allowed/Makefile.am $2/tests/hwloc/linux/gather/Makefile.am $2/tests/hwloc/x86/Makefile.am $2/tests/hwloc/xml/Makefile.am $2/tests/hwloc/ports/Makefile.am $2/tests/hwloc/rename/Makefile.am $2/tests/hwloc/linux/allowed/test-topology.sh.in $2/tests/hwloc/linux/gather/test-gather-topology.sh.in $2/tests/hwloc/linux/test-topology.sh.in $2/tests/hwloc/x86/test-topology.sh.in $2/tests/hwloc/xml/test-topology.sh.in $2/tests/hwloc/wrapper.sh.in $2/utils/hwloc/hwloc-compress-dir.in $2/utils/hwloc/hwloc-gather-topology.in $2/utils/hwloc/test-hwloc-annotate.sh.in $2/utils/hwloc/test-hwloc-calc.sh.in $2/utils/hwloc/test-hwloc-compress-dir.sh.in $2/utils/hwloc/test-hwloc-diffpatch.sh.in $2/utils/hwloc/test-hwloc-distrib.sh.in $2/utils/hwloc/test-hwloc-info.sh.in $2/utils/hwloc/test-fake-plugin.sh.in $2/utils/hwloc/test-hwloc-dump-hwdata/Makefile.am $2/utils/hwloc/test-hwloc-dump-hwdata/test-hwloc-dump-hwdata.sh.in $2/utils/lstopo/test-lstopo.sh.in $2/contrib/systemd/Makefile.am $2/contrib/misc/Makefile.am $2/tests/netloc/Makefile.am $2/tests/netloc/tests.sh.in $2/utils/lstopo/lstopo-windows.c"
|
||||
rm -f $makefiles
|
||||
for i in $makefiles; do
|
||||
[ -d $(dirname $i) ] || mkdir -p $(dirname $i)
|
||||
cat > $i << EOF
|
||||
# This is a dummy file that is not needed in embedded mode,
|
||||
# but sadly, automake *requires* it
|
||||
EOF
|
||||
done
|
||||
|
1364
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc.m4
Обычный файл
1364
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc.m4
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
534
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_check_attributes.m4
Обычный файл
534
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_check_attributes.m4
Обычный файл
@ -0,0 +1,534 @@
|
||||
# This macro set originally copied from Open MPI:
|
||||
# Copyright © 2004-2007 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright © 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright © 2004-2007 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright © 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# and renamed for hwloc:
|
||||
# Copyright © 2009 Inria. All rights reserved.
|
||||
# Copyright © 2009 Université Bordeaux
|
||||
# Copyright © 2010 Cisco Systems, Inc. All rights reserved.
|
||||
# See COPYING in top-level directory.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# - Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer listed
|
||||
# in this license in the documentation and/or other materials
|
||||
# provided with the distribution.
|
||||
#
|
||||
# - Neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# The copyright holders provide no reassurances that the source code
|
||||
# provided does not infringe any patent, copyright, or any other
|
||||
# intellectual property rights of third parties. The copyright holders
|
||||
# disclaim any liability to any recipient for claims brought against
|
||||
# recipient by any third party for infringement of that parties
|
||||
# intellectual property rights.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
#
|
||||
# Search the generated warnings for
|
||||
# keywords regarding skipping or ignoring certain attributes
|
||||
# Intel: ignore
|
||||
# Sun C++: skip
|
||||
#
|
||||
AC_DEFUN([_HWLOC_ATTRIBUTE_FAIL_SEARCH],[
|
||||
# Be safe for systems that have ancient Autoconf's (e.g., RHEL5)
|
||||
m4_ifdef([AC_PROG_GREP],
|
||||
[AC_REQUIRE([AC_PROG_GREP])],
|
||||
[GREP=grep])
|
||||
|
||||
if test -s conftest.err ; then
|
||||
for i in ignore skip ; do
|
||||
$GREP -iq $i conftest.err
|
||||
if test "$?" = "0" ; then
|
||||
hwloc_cv___attribute__[$1]=0
|
||||
break;
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])
|
||||
|
||||
#
|
||||
# HWLOC: Remove C++ compiler check. It can result in a circular
|
||||
# dependency in embedded situations.
|
||||
#
|
||||
# Check for one specific attribute by compiling with C
|
||||
# and possibly using a cross-check.
|
||||
#
|
||||
# If the cross-check is defined, a static function "usage" should be
|
||||
# defined, which is to be called from main (to circumvent warnings
|
||||
# regarding unused function in main file)
|
||||
# static int usage (int * argument);
|
||||
#
|
||||
# The last argument is for specific CFLAGS, that need to be set
|
||||
# for the compiler to generate a warning on the cross-check.
|
||||
# This may need adaption for future compilers / CFLAG-settings.
|
||||
#
|
||||
AC_DEFUN([_HWLOC_CHECK_SPECIFIC_ATTRIBUTE], [
|
||||
AC_MSG_CHECKING([for __attribute__([$1])])
|
||||
AC_CACHE_VAL(hwloc_cv___attribute__[$1], [
|
||||
#
|
||||
# Try to compile using the C compiler
|
||||
#
|
||||
AC_TRY_COMPILE([$2],[],
|
||||
[
|
||||
#
|
||||
# In case we did succeed: Fine, but was this due to the
|
||||
# attribute being ignored/skipped? Grep for IgNoRe/skip in conftest.err
|
||||
# and if found, reset the hwloc_cv__attribute__var=0
|
||||
#
|
||||
hwloc_cv___attribute__[$1]=1
|
||||
_HWLOC_ATTRIBUTE_FAIL_SEARCH([$1])
|
||||
],
|
||||
[hwloc_cv___attribute__[$1]=0])
|
||||
|
||||
#
|
||||
# If the attribute is supported by both compilers,
|
||||
# try to recompile a *cross-check*, IFF defined.
|
||||
#
|
||||
if test '(' "$hwloc_cv___attribute__[$1]" = "1" -a "[$3]" != "" ')' ; then
|
||||
ac_c_werror_flag_safe=$ac_c_werror_flag
|
||||
ac_c_werror_flag="yes"
|
||||
CFLAGS_safe=$CFLAGS
|
||||
CFLAGS="$CFLAGS [$4]"
|
||||
|
||||
AC_TRY_COMPILE([$3],
|
||||
[
|
||||
int i=4711;
|
||||
i=usage(&i);
|
||||
],
|
||||
[hwloc_cv___attribute__[$1]=0],
|
||||
[
|
||||
#
|
||||
# In case we did NOT succeed: Fine, but was this due to the
|
||||
# attribute being ignored? Grep for IgNoRe in conftest.err
|
||||
# and if found, reset the hwloc_cv__attribute__var=0
|
||||
#
|
||||
hwloc_cv___attribute__[$1]=1
|
||||
_HWLOC_ATTRIBUTE_FAIL_SEARCH([$1])
|
||||
])
|
||||
|
||||
ac_c_werror_flag=$ac_c_werror_flag_safe
|
||||
CFLAGS=$CFLAGS_safe
|
||||
fi
|
||||
])
|
||||
|
||||
if test "$hwloc_cv___attribute__[$1]" = "1" ; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
#
|
||||
# Test the availability of __attribute__ and with the help
|
||||
# of _HWLOC_CHECK_SPECIFIC_ATTRIBUTE for the support of
|
||||
# particular attributes. Compilers, that do not support an
|
||||
# attribute most often fail with a warning (when the warning
|
||||
# level is set).
|
||||
# The compilers output is parsed in _HWLOC_ATTRIBUTE_FAIL_SEARCH
|
||||
#
|
||||
# To add a new attributes __NAME__ add the
|
||||
# hwloc_cv___attribute__NAME
|
||||
# add a new check with _HWLOC_CHECK_SPECIFIC_ATTRIBUTE (possibly with a cross-check)
|
||||
# _HWLOC_CHECK_SPECIFIC_ATTRIBUTE([name], [int foo (int arg) __attribute__ ((__name__));], [], [])
|
||||
# and define the corresponding
|
||||
# AC_DEFINE_UNQUOTED(_HWLOC_HAVE_ATTRIBUTE_NAME, [$hwloc_cv___attribute__NAME],
|
||||
# [Whether your compiler has __attribute__ NAME or not])
|
||||
# and decide on a correct macro (in opal/include/opal_config_bottom.h):
|
||||
# # define __opal_attribute_NAME(x) __attribute__(__NAME__)
|
||||
#
|
||||
# Please use the "__"-notation of the attribute in order not to
|
||||
# clash with predefined names or macros (e.g. const, which some compilers
|
||||
# do not like..)
|
||||
#
|
||||
|
||||
|
||||
AC_DEFUN([_HWLOC_CHECK_ATTRIBUTES], [
|
||||
AC_MSG_CHECKING(for __attribute__)
|
||||
|
||||
AC_CACHE_VAL(hwloc_cv___attribute__, [
|
||||
AC_TRY_COMPILE(
|
||||
[#include <stdlib.h>
|
||||
/* Check for the longest available __attribute__ (since gcc-2.3) */
|
||||
struct foo {
|
||||
char a;
|
||||
int x[2] __attribute__ ((__packed__));
|
||||
};
|
||||
],
|
||||
[],
|
||||
[hwloc_cv___attribute__=1],
|
||||
[hwloc_cv___attribute__=0],
|
||||
)
|
||||
|
||||
if test "$hwloc_cv___attribute__" = "1" ; then
|
||||
AC_TRY_COMPILE(
|
||||
[#include <stdlib.h>
|
||||
/* Check for the longest available __attribute__ (since gcc-2.3) */
|
||||
struct foo {
|
||||
char a;
|
||||
int x[2] __attribute__ ((__packed__));
|
||||
};
|
||||
],
|
||||
[],
|
||||
[hwloc_cv___attribute__=1],
|
||||
[hwloc_cv___attribute__=0],
|
||||
)
|
||||
fi
|
||||
])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE, [$hwloc_cv___attribute__],
|
||||
[Whether your compiler has __attribute__ or not])
|
||||
|
||||
#
|
||||
# Now that we know the compiler support __attribute__ let's check which kind of
|
||||
# attributed are supported.
|
||||
#
|
||||
if test "$hwloc_cv___attribute__" = "0" ; then
|
||||
AC_MSG_RESULT([no])
|
||||
hwloc_cv___attribute__aligned=0
|
||||
hwloc_cv___attribute__always_inline=0
|
||||
hwloc_cv___attribute__cold=0
|
||||
hwloc_cv___attribute__const=0
|
||||
hwloc_cv___attribute__deprecated=0
|
||||
hwloc_cv___attribute__format=0
|
||||
hwloc_cv___attribute__hot=0
|
||||
hwloc_cv___attribute__malloc=0
|
||||
hwloc_cv___attribute__may_alias=0
|
||||
hwloc_cv___attribute__no_instrument_function=0
|
||||
hwloc_cv___attribute__nonnull=0
|
||||
hwloc_cv___attribute__noreturn=0
|
||||
hwloc_cv___attribute__packed=0
|
||||
hwloc_cv___attribute__pure=0
|
||||
hwloc_cv___attribute__sentinel=0
|
||||
hwloc_cv___attribute__unused=0
|
||||
hwloc_cv___attribute__warn_unused_result=0
|
||||
hwloc_cv___attribute__weak_alias=0
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([aligned],
|
||||
[struct foo { char text[4]; } __attribute__ ((__aligned__(8)));],
|
||||
[],
|
||||
[])
|
||||
|
||||
#
|
||||
# Ignored by PGI-6.2.5; -- recognized by output-parser
|
||||
#
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([always_inline],
|
||||
[int foo (int arg) __attribute__ ((__always_inline__));],
|
||||
[],
|
||||
[])
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([cold],
|
||||
[
|
||||
int foo(int arg1, int arg2) __attribute__ ((__cold__));
|
||||
int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; }
|
||||
],
|
||||
[],
|
||||
[])
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([const],
|
||||
[
|
||||
int foo(int arg1, int arg2) __attribute__ ((__const__));
|
||||
int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; }
|
||||
],
|
||||
[],
|
||||
[])
|
||||
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([deprecated],
|
||||
[
|
||||
int foo(int arg1, int arg2) __attribute__ ((__deprecated__));
|
||||
int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; }
|
||||
],
|
||||
[],
|
||||
[])
|
||||
|
||||
|
||||
HWLOC_ATTRIBUTE_CFLAGS=
|
||||
case "$hwloc_c_vendor" in
|
||||
gnu)
|
||||
HWLOC_ATTRIBUTE_CFLAGS="-Wall"
|
||||
;;
|
||||
intel)
|
||||
# we want specifically the warning on format string conversion
|
||||
HWLOC_ATTRIBUTE_CFLAGS="-we181"
|
||||
;;
|
||||
esac
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([format],
|
||||
[
|
||||
int this_printf (void *my_object, const char *my_format, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
],
|
||||
[
|
||||
static int usage (int * argument);
|
||||
extern int this_printf (int arg1, const char *my_format, ...) __attribute__ ((__format__ (__printf__, 2, 3)));
|
||||
|
||||
static int usage (int * argument) {
|
||||
return this_printf (*argument, "%d", argument); /* This should produce a format warning */
|
||||
}
|
||||
/* The autoconf-generated main-function is int main(), which produces a warning by itself */
|
||||
int main(void);
|
||||
],
|
||||
[$HWLOC_ATTRIBUTE_CFLAGS])
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([hot],
|
||||
[
|
||||
int foo(int arg1, int arg2) __attribute__ ((__hot__));
|
||||
int foo(int arg1, int arg2) { return arg1 * arg2 + arg1; }
|
||||
],
|
||||
[],
|
||||
[])
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([malloc],
|
||||
[
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
int * foo(int arg1) __attribute__ ((__malloc__));
|
||||
int * foo(int arg1) { return (int*) malloc(arg1); }
|
||||
],
|
||||
[],
|
||||
[])
|
||||
|
||||
|
||||
#
|
||||
# Attribute may_alias: No suitable cross-check available, that works for non-supporting compilers
|
||||
# Ignored by intel-9.1.045 -- turn off with -wd1292
|
||||
# Ignored by PGI-6.2.5; ignore not detected due to missing cross-check
|
||||
# The test case is chosen to match our only use in topology-xml-*.c, and reproduces an xlc-13.1.0 bug.
|
||||
#
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([may_alias],
|
||||
[struct { int i; } __attribute__ ((__may_alias__)) * p_value;],
|
||||
[],
|
||||
[])
|
||||
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([no_instrument_function],
|
||||
[int * foo(int arg1) __attribute__ ((__no_instrument_function__));],
|
||||
[],
|
||||
[])
|
||||
|
||||
|
||||
#
|
||||
# Attribute nonnull:
|
||||
# Ignored by intel-compiler 9.1.045 -- recognized by cross-check
|
||||
# Ignored by PGI-6.2.5 (pgCC) -- recognized by cross-check
|
||||
#
|
||||
HWLOC_ATTRIBUTE_CFLAGS=
|
||||
case "$hwloc_c_vendor" in
|
||||
gnu)
|
||||
HWLOC_ATTRIBUTE_CFLAGS="-Wall"
|
||||
;;
|
||||
intel)
|
||||
# we do not want to get ignored attributes warnings, but rather real warnings
|
||||
HWLOC_ATTRIBUTE_CFLAGS="-wd1292"
|
||||
;;
|
||||
esac
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([nonnull],
|
||||
[
|
||||
int square(int *arg) __attribute__ ((__nonnull__));
|
||||
int square(int *arg) { return *arg; }
|
||||
],
|
||||
[
|
||||
static int usage(int * argument);
|
||||
int square(int * argument) __attribute__ ((__nonnull__));
|
||||
int square(int * argument) { return (*argument) * (*argument); }
|
||||
|
||||
static int usage(int * argument) {
|
||||
return square( ((void*)0) ); /* This should produce an argument must be nonnull warning */
|
||||
}
|
||||
/* The autoconf-generated main-function is int main(), which produces a warning by itself */
|
||||
int main(void);
|
||||
],
|
||||
[$HWLOC_ATTRIBUTE_CFLAGS])
|
||||
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([noreturn],
|
||||
[
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
void fatal(int arg1) __attribute__ ((__noreturn__));
|
||||
void fatal(int arg1) { exit(arg1); }
|
||||
],
|
||||
[],
|
||||
[])
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([packed],
|
||||
[
|
||||
struct foo {
|
||||
char a;
|
||||
int x[2] __attribute__ ((__packed__));
|
||||
};
|
||||
],
|
||||
[],
|
||||
[])
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([pure],
|
||||
[
|
||||
int square(int arg) __attribute__ ((__pure__));
|
||||
int square(int arg) { return arg * arg; }
|
||||
],
|
||||
[],
|
||||
[])
|
||||
|
||||
#
|
||||
# Attribute sentinel:
|
||||
# Ignored by the intel-9.1.045 -- recognized by cross-check
|
||||
# intel-10.0beta works fine
|
||||
# Ignored by PGI-6.2.5 (pgCC) -- recognized by output-parser and cross-check
|
||||
# Ignored by pathcc-2.2.1 -- recognized by cross-check (through grep ignore)
|
||||
#
|
||||
HWLOC_ATTRIBUTE_CFLAGS=
|
||||
case "$hwloc_c_vendor" in
|
||||
gnu)
|
||||
HWLOC_ATTRIBUTE_CFLAGS="-Wall"
|
||||
;;
|
||||
intel)
|
||||
# we do not want to get ignored attributes warnings
|
||||
HWLOC_ATTRIBUTE_CFLAGS="-wd1292"
|
||||
;;
|
||||
esac
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([sentinel],
|
||||
[
|
||||
int my_execlp(const char * file, const char *arg, ...) __attribute__ ((__sentinel__));
|
||||
],
|
||||
[
|
||||
static int usage(int * argument);
|
||||
int my_execlp(const char * file, const char *arg, ...) __attribute__ ((__sentinel__));
|
||||
|
||||
static int usage(int * argument) {
|
||||
void * last_arg_should_be_null = argument;
|
||||
return my_execlp ("lala", "/home/there", last_arg_should_be_null); /* This should produce a warning */
|
||||
}
|
||||
/* The autoconf-generated main-function is int main(), which produces a warning by itself */
|
||||
int main(void);
|
||||
],
|
||||
[$HWLOC_ATTRIBUTE_CFLAGS])
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([unused],
|
||||
[
|
||||
int square(int arg1 __attribute__ ((__unused__)), int arg2);
|
||||
int square(int arg1, int arg2) { return arg2; }
|
||||
],
|
||||
[],
|
||||
[])
|
||||
|
||||
|
||||
#
|
||||
# Attribute warn_unused_result:
|
||||
# Ignored by the intel-compiler 9.1.045 -- recognized by cross-check
|
||||
# Ignored by pathcc-2.2.1 -- recognized by cross-check (through grep ignore)
|
||||
#
|
||||
HWLOC_ATTRIBUTE_CFLAGS=
|
||||
case "$hwloc_c_vendor" in
|
||||
gnu)
|
||||
HWLOC_ATTRIBUTE_CFLAGS="-Wall"
|
||||
;;
|
||||
intel)
|
||||
# we do not want to get ignored attributes warnings
|
||||
HWLOC_ATTRIBUTE_CFLAGS="-wd1292"
|
||||
;;
|
||||
esac
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([warn_unused_result],
|
||||
[
|
||||
int foo(int arg) __attribute__ ((__warn_unused_result__));
|
||||
int foo(int arg) { return arg + 3; }
|
||||
],
|
||||
[
|
||||
static int usage(int * argument);
|
||||
int foo(int arg) __attribute__ ((__warn_unused_result__));
|
||||
|
||||
int foo(int arg) { return arg + 3; }
|
||||
static int usage(int * argument) {
|
||||
foo (*argument); /* Should produce an unused result warning */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The autoconf-generated main-function is int main(), which produces a warning by itself */
|
||||
int main(void);
|
||||
],
|
||||
[$HWLOC_ATTRIBUTE_CFLAGS])
|
||||
|
||||
|
||||
_HWLOC_CHECK_SPECIFIC_ATTRIBUTE([weak_alias],
|
||||
[
|
||||
int foo(int arg);
|
||||
int foo(int arg) { return arg + 3; }
|
||||
int foo2(int arg) __attribute__ ((__weak__, __alias__("foo")));
|
||||
],
|
||||
[],
|
||||
[])
|
||||
|
||||
fi
|
||||
|
||||
# Now that all the values are set, define them
|
||||
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_ALIGNED, [$hwloc_cv___attribute__aligned],
|
||||
[Whether your compiler has __attribute__ aligned or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_ALWAYS_INLINE, [$hwloc_cv___attribute__always_inline],
|
||||
[Whether your compiler has __attribute__ always_inline or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_COLD, [$hwloc_cv___attribute__cold],
|
||||
[Whether your compiler has __attribute__ cold or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_CONST, [$hwloc_cv___attribute__const],
|
||||
[Whether your compiler has __attribute__ const or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_DEPRECATED, [$hwloc_cv___attribute__deprecated],
|
||||
[Whether your compiler has __attribute__ deprecated or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_FORMAT, [$hwloc_cv___attribute__format],
|
||||
[Whether your compiler has __attribute__ format or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_HOT, [$hwloc_cv___attribute__hot],
|
||||
[Whether your compiler has __attribute__ hot or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_MALLOC, [$hwloc_cv___attribute__malloc],
|
||||
[Whether your compiler has __attribute__ malloc or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_MAY_ALIAS, [$hwloc_cv___attribute__may_alias],
|
||||
[Whether your compiler has __attribute__ may_alias or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_NO_INSTRUMENT_FUNCTION, [$hwloc_cv___attribute__no_instrument_function],
|
||||
[Whether your compiler has __attribute__ no_instrument_function or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_NONNULL, [$hwloc_cv___attribute__nonnull],
|
||||
[Whether your compiler has __attribute__ nonnull or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_NORETURN, [$hwloc_cv___attribute__noreturn],
|
||||
[Whether your compiler has __attribute__ noreturn or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_PACKED, [$hwloc_cv___attribute__packed],
|
||||
[Whether your compiler has __attribute__ packed or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_PURE, [$hwloc_cv___attribute__pure],
|
||||
[Whether your compiler has __attribute__ pure or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_SENTINEL, [$hwloc_cv___attribute__sentinel],
|
||||
[Whether your compiler has __attribute__ sentinel or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_UNUSED, [$hwloc_cv___attribute__unused],
|
||||
[Whether your compiler has __attribute__ unused or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_WARN_UNUSED_RESULT, [$hwloc_cv___attribute__warn_unused_result],
|
||||
[Whether your compiler has __attribute__ warn unused result or not])
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_WEAK_ALIAS, [$hwloc_cv___attribute__weak_alias],
|
||||
[Whether your compiler has __attribute__ weak alias or not])
|
||||
])
|
||||
|
246
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_check_vendor.m4
Обычный файл
246
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_check_vendor.m4
Обычный файл
@ -0,0 +1,246 @@
|
||||
dnl -*- shell-script -*-
|
||||
dnl
|
||||
dnl Copyright © 2004-2005 The Trustees of Indiana University and Indiana
|
||||
dnl University Research and Technology
|
||||
dnl Corporation. All rights reserved.
|
||||
dnl Copyright © 2004-2005 The University of Tennessee and The University
|
||||
dnl of Tennessee Research Foundation. All rights
|
||||
dnl reserved.
|
||||
dnl Copyright © 2004-2005 High Performance Computing Center Stuttgart,
|
||||
dnl University of Stuttgart. All rights reserved.
|
||||
dnl Copyright © 2004-2005 The Regents of the University of California.
|
||||
dnl All rights reserved.
|
||||
dnl Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
dnl Copyright © 2015 Inria. All rights reserved.
|
||||
dnl $COPYRIGHT$
|
||||
dnl
|
||||
dnl Additional copyrights may follow
|
||||
dnl
|
||||
dnl $HEADER$
|
||||
dnl
|
||||
|
||||
dnl ------------------------------------------------------------------
|
||||
dnl This m4 file originally copied from Open MPI
|
||||
dnl config/ompi_check_vendor.m4.
|
||||
dnl ------------------------------------------------------------------
|
||||
|
||||
|
||||
# HWLOC_C_COMPILER_VENDOR(VENDOR_VARIABLE)
|
||||
# ---------------------------------------
|
||||
# Set shell variable VENDOR_VARIABLE to the name of the compiler
|
||||
# vendor for the current C compiler.
|
||||
#
|
||||
# See comment for _HWLOC_CHECK_COMPILER_VENDOR for a complete
|
||||
# list of currently detected compilers.
|
||||
AC_DEFUN([_HWLOC_C_COMPILER_VENDOR], [
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
|
||||
AC_CACHE_CHECK([for the C compiler vendor],
|
||||
[hwloc_cv_c_compiler_vendor],
|
||||
[AC_LANG_PUSH(C)
|
||||
_HWLOC_CHECK_COMPILER_VENDOR([hwloc_cv_c_compiler_vendor])
|
||||
AC_LANG_POP(C)])
|
||||
|
||||
$1="$hwloc_cv_c_compiler_vendor"
|
||||
])
|
||||
|
||||
|
||||
# workaround to avoid syntax error with Autoconf < 2.68:
|
||||
m4_ifndef([AC_LANG_DEFINES_PROVIDED],
|
||||
[m4_define([AC_LANG_DEFINES_PROVIDED])])
|
||||
|
||||
# HWLOC_IFDEF_IFELSE(symbol, [action-if-defined],
|
||||
# [action-if-not-defined])
|
||||
# ----------------------------------------------
|
||||
# Run compiler to determine if preprocessor symbol "symbol" is
|
||||
# defined by the compiler.
|
||||
AC_DEFUN([HWLOC_IFDEF_IFELSE], [
|
||||
AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED
|
||||
#ifndef $1
|
||||
#error "symbol $1 not defined"
|
||||
choke me
|
||||
#endif], [$2], [$3])])
|
||||
|
||||
|
||||
# HWLOC_IF_IFELSE(symbol, [action-if-defined],
|
||||
# [action-if-not-defined])
|
||||
# ----------------------------------------------
|
||||
# Run compiler to determine if preprocessor symbol "symbol" is
|
||||
# defined by the compiler.
|
||||
AC_DEFUN([HWLOC_IF_IFELSE], [
|
||||
AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED
|
||||
#if !( $1 )
|
||||
#error "condition $1 not met"
|
||||
choke me
|
||||
#endif], [$2], [$3])])
|
||||
|
||||
|
||||
# _HWLOC_CHECK_COMPILER_VENDOR(VENDOR_VARIABLE)
|
||||
# --------------------------------------------
|
||||
# Set shell variable VENDOR_VARIABLE to the name of the compiler
|
||||
# vendor for the compiler for the current language. Language must be
|
||||
# one of C, OBJC, or C++.
|
||||
#
|
||||
# thanks to http://predef.sourceforge.net/precomp.html for the list
|
||||
# of defines to check.
|
||||
AC_DEFUN([_HWLOC_CHECK_COMPILER_VENDOR], [
|
||||
hwloc_check_compiler_vendor_result="unknown"
|
||||
|
||||
# GNU is probably the most common, so check that one as soon as
|
||||
# possible. Intel and Android pretend to be GNU, so need to
|
||||
# check Intel and Android before checking for GNU.
|
||||
|
||||
# Android
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__ANDROID__],
|
||||
[hwloc_check_compiler_vendor_result="android"])])
|
||||
|
||||
# Intel
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IF_IFELSE([defined(__INTEL_COMPILER) || defined(__ICC)],
|
||||
[hwloc_check_compiler_vendor_result="intel"])])
|
||||
|
||||
# GNU
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__GNUC__],
|
||||
[hwloc_check_compiler_vendor_result="gnu"])])
|
||||
|
||||
# Borland Turbo C
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__TURBOC__],
|
||||
[hwloc_check_compiler_vendor_result="borland"])])
|
||||
|
||||
# Borland C++
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__BORLANDC__],
|
||||
[hwloc_check_compiler_vendor_result="borland"])])
|
||||
|
||||
# Comeau C++
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__COMO__],
|
||||
[hwloc_check_compiler_vendor_result="comeau"])])
|
||||
|
||||
# Compaq C/C++
|
||||
# OSF part actually not needed anymore but doesn't hurt
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IF_IFELSE([defined(__DECC) || defined(VAXC) || defined(__VAXC)],
|
||||
[hwloc_check_compiler_vendor_result="compaq"],
|
||||
[HWLOC_IF_IFELSE([defined(__osf__) && defined(__LANGUAGE_C__)],
|
||||
[hwloc_check_compiler_vendor_result="compaq"],
|
||||
[HWLOC_IFDEF_IFELSE([__DECCXX],
|
||||
[hwloc_check_compiler_vendor_result="compaq"])])])])
|
||||
|
||||
# Cray C/C++
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([_CRAYC],
|
||||
[hwloc_check_compiler_vendor_result="cray"])])
|
||||
|
||||
# Diab C/C++
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__DCC__],
|
||||
[hwloc_check_compiler_vendor_result="diab"])])
|
||||
|
||||
# Digital Mars
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IF_IFELSE([defined(__DMC__) || defined(__SC__) || defined(__ZTC__)],
|
||||
[hwloc_check_compiler_vendor_result="digital mars"])])
|
||||
|
||||
# HP ANSI C / aC++
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IF_IFELSE([defined(__HP_cc) || defined(__HP_aCC)],
|
||||
[hwloc_check_compiler_vendor_result="hp"])])
|
||||
|
||||
# IBM XL C/C++
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IF_IFELSE([defined(__xlC__) || defined(__IBMC__) || defined(__IBMCPP__)],
|
||||
[hwloc_check_compiler_vendor_result="ibm"],
|
||||
[HWLOC_IF_IFELSE([defined(_AIX) && !defined(__GNUC__)],
|
||||
[hwloc_check_compiler_vendor_result="ibm"])])])
|
||||
|
||||
# KAI C++ (rest in peace)
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__KCC],
|
||||
[hwloc_check_compiler_vendor_result="kai"])])
|
||||
|
||||
# LCC
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__LCC__],
|
||||
[hwloc_check_compiler_vendor_result="lcc"])])
|
||||
|
||||
# MetaWare High C/C++
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__HIGHC__],
|
||||
[hwloc_check_compiler_vendor_result="metaware high"])])
|
||||
|
||||
# Metrowerks Codewarrior
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__MWERKS__],
|
||||
[hwloc_check_compiler_vendor_result="metrowerks"])])
|
||||
|
||||
# MIPSpro (SGI)
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IF_IFELSE([defined(sgi) || defined(__sgi)],
|
||||
[hwloc_check_compiler_vendor_result="sgi"])])
|
||||
|
||||
# MPW C++
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IF_IFELSE([defined(__MRC__) || defined(MPW_C) || defined(MPW_CPLUS)],
|
||||
[hwloc_check_compiler_vendor_result="mpw"])])
|
||||
|
||||
# Microsoft
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[# Always use C compiler when checking for Microsoft, as
|
||||
# Visual C++ doesn't recognize .cc as a C++ file.
|
||||
AC_LANG_PUSH(C)
|
||||
HWLOC_IF_IFELSE([defined(_MSC_VER) || defined(__MSC_VER)],
|
||||
[hwloc_check_compiler_vendor_result="microsoft"])
|
||||
AC_LANG_POP(C)])
|
||||
|
||||
# Norcroft C
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__CC_NORCROFT],
|
||||
[hwloc_check_compiler_vendor_result="norcroft"])])
|
||||
|
||||
# Pelles C
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__POCC__],
|
||||
[hwloc_check_compiler_vendor_result="pelles"])])
|
||||
|
||||
# Portland Group
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__PGI],
|
||||
[hwloc_check_compiler_vendor_result="portland group"])])
|
||||
|
||||
# SAS/C
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IF_IFELSE([defined(SASC) || defined(__SASC) || defined(__SASC__)],
|
||||
[hwloc_check_compiler_vendor_result="sas"])])
|
||||
|
||||
# Sun Workshop C/C++
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IF_IFELSE([defined(__SUNPRO_C) || defined(__SUNPRO_CC)],
|
||||
[hwloc_check_compiler_vendor_result="sun"])])
|
||||
|
||||
# TenDRA C/C++
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__TenDRA__],
|
||||
[hwloc_check_compiler_vendor_result="tendra"])])
|
||||
|
||||
# Tiny C
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__TINYC__],
|
||||
[hwloc_check_compiler_vendor_result="tiny"])])
|
||||
|
||||
# USL C
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__USLC__],
|
||||
[hwloc_check_compiler_vendor_result="usl"])])
|
||||
|
||||
# Watcom C++
|
||||
AS_IF([test "$hwloc_check_compiler_vendor_result" = "unknown"],
|
||||
[HWLOC_IFDEF_IFELSE([__WATCOMC__],
|
||||
[hwloc_check_compiler_vendor_result="watcom"])])
|
||||
|
||||
$1="$hwloc_check_compiler_vendor_result"
|
||||
unset hwloc_check_compiler_vendor_result
|
||||
])
|
131
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_check_visibility.m4
Обычный файл
131
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_check_visibility.m4
Обычный файл
@ -0,0 +1,131 @@
|
||||
# This macro set originally copied from Open MPI:
|
||||
# Copyright © 2004-2005 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright © 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright © 2004-2007 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright © 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright © 2006-2007 Cisco Systems, Inc. All rights reserved.
|
||||
# and renamed/modified for hwloc:
|
||||
# Copyright © 2009 Inria. All rights reserved.
|
||||
# Copyright © 2009-2010 Université Bordeaux
|
||||
# Copyright © 2010-2012 Cisco Systems, Inc. All rights reserved.
|
||||
# See COPYING in top-level directory.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# - Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer listed
|
||||
# in this license in the documentation and/or other materials
|
||||
# provided with the distribution.
|
||||
#
|
||||
# - Neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# The copyright holders provide no reassurances that the source code
|
||||
# provided does not infringe any patent, copyright, or any other
|
||||
# intellectual property rights of third parties. The copyright holders
|
||||
# disclaim any liability to any recipient for claims brought against
|
||||
# recipient by any third party for infringement of that parties
|
||||
# intellectual property rights.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
# _HWLOC_CHECK_VISIBILITY
|
||||
# --------------------------------------------------------
|
||||
AC_DEFUN([_HWLOC_CHECK_VISIBILITY],[
|
||||
# Be safe for systems that have ancient Autoconf's (e.g., RHEL5)
|
||||
m4_ifdef([AC_PROG_GREP],
|
||||
[AC_REQUIRE([AC_PROG_GREP])],
|
||||
[GREP=grep])
|
||||
|
||||
# Check if the compiler has support for visibility, like some
|
||||
# versions of gcc, icc, Sun Studio cc.
|
||||
AC_ARG_ENABLE(visibility,
|
||||
AC_HELP_STRING([--enable-visibility],
|
||||
[enable visibility feature of certain compilers/linkers (default: enabled on platforms that support it)]))
|
||||
|
||||
case ${target} in
|
||||
*-*-aix*|*-*-mingw*|*-*-cygwin*|*-*-hpux*)
|
||||
enable_visibility=no
|
||||
;;
|
||||
esac
|
||||
|
||||
hwloc_visibility_define=0
|
||||
hwloc_msg="whether to enable symbol visibility"
|
||||
if test "$enable_visibility" = "no"; then
|
||||
AC_MSG_CHECKING([$hwloc_msg])
|
||||
AC_MSG_RESULT([no (disabled)])
|
||||
else
|
||||
CFLAGS_orig=$CFLAGS
|
||||
|
||||
hwloc_add=
|
||||
case "$hwloc_c_vendor" in
|
||||
sun)
|
||||
# Check using Sun Studio -xldscope=hidden flag
|
||||
hwloc_add=-xldscope=hidden
|
||||
CFLAGS="$CFLAGS_orig $hwloc_add -errwarn=%all"
|
||||
;;
|
||||
|
||||
*)
|
||||
# Check using -fvisibility=hidden
|
||||
hwloc_add=-fvisibility=hidden
|
||||
CFLAGS="$CFLAGS_orig $hwloc_add -Werror"
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_MSG_CHECKING([if $CC supports $hwloc_add])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <stdio.h>
|
||||
__attribute__((visibility("default"))) int foo;
|
||||
]],[[fprintf(stderr, "Hello, world\n");]])],
|
||||
[AS_IF([test -s conftest.err],
|
||||
[$GREP -iq visibility conftest.err
|
||||
# If we find "visibility" in the stderr, then
|
||||
# assume it doesn't work
|
||||
AS_IF([test "$?" = "0"], [hwloc_add=])])
|
||||
], [hwloc_add=])
|
||||
AS_IF([test "$hwloc_add" = ""],
|
||||
[AC_MSG_RESULT([no])],
|
||||
[AC_MSG_RESULT([yes])])
|
||||
|
||||
CFLAGS=$CFLAGS_orig
|
||||
HWLOC_VISIBILITY_CFLAGS=$hwloc_add
|
||||
|
||||
if test "$hwloc_add" != "" ; then
|
||||
hwloc_visibility_define=1
|
||||
AC_MSG_CHECKING([$hwloc_msg])
|
||||
AC_MSG_RESULT([yes (via $hwloc_add)])
|
||||
elif test "$enable_visibility" = "yes"; then
|
||||
AC_MSG_ERROR([Symbol visibility support requested but compiler does not seem to support it. Aborting])
|
||||
else
|
||||
AC_MSG_CHECKING([$hwloc_msg])
|
||||
AC_MSG_RESULT([no (unsupported)])
|
||||
fi
|
||||
unset hwloc_add
|
||||
fi
|
||||
|
||||
AC_DEFINE_UNQUOTED([HWLOC_C_HAVE_VISIBILITY], [$hwloc_visibility_define],
|
||||
[Whether C compiler supports symbol visibility or not])
|
||||
])
|
66
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_components.m4
Обычный файл
66
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_components.m4
Обычный файл
@ -0,0 +1,66 @@
|
||||
# Copyright © 2012 Inria. All rights reserved.
|
||||
# See COPYING in top-level directory.
|
||||
|
||||
|
||||
# HWLOC_PREPARE_FILTER_COMPONENTS
|
||||
#
|
||||
# Given a comma-separated list of names, define hwloc_<name>_component_maybeplugin=1.
|
||||
#
|
||||
# $1 = command-line given list of components to build as plugins
|
||||
#
|
||||
AC_DEFUN([HWLOC_PREPARE_FILTER_COMPONENTS], [
|
||||
for name in `echo [$1] | sed -e 's/,/ /g'` ; do
|
||||
str="hwloc_${name}_component_wantplugin=1"
|
||||
eval $str
|
||||
done
|
||||
])
|
||||
|
||||
|
||||
# HWLOC_FILTER_COMPONENTS
|
||||
#
|
||||
# For each component in hwloc_components,
|
||||
# check if hwloc_<name>_component_wantplugin=1 or enable_plugin=yes,
|
||||
# and check if hwloc_<name>_component_maybeplugin=1.
|
||||
# Add <name> to hwloc_[static|plugin]_components accordingly.
|
||||
# And set hwloc_<name>_component=[static|plugin] accordingly.
|
||||
#
|
||||
AC_DEFUN([HWLOC_FILTER_COMPONENTS], [
|
||||
for name in $hwloc_components ; do
|
||||
str="maybeplugin=\$hwloc_${name}_component_maybeplugin"
|
||||
eval $str
|
||||
str="wantplugin=\$hwloc_${name}_component_wantplugin"
|
||||
eval $str
|
||||
if test x$hwloc_have_plugins = xyes && test x$maybeplugin = x1 && test x$wantplugin = x1 -o x$enable_plugins = xyes; then
|
||||
hwloc_plugin_components="$hwloc_plugin_components $name"
|
||||
str="hwloc_${name}_component=plugin"
|
||||
else
|
||||
hwloc_static_components="$hwloc_static_components $name"
|
||||
str="hwloc_${name}_component=static"
|
||||
fi
|
||||
eval $str
|
||||
done
|
||||
])
|
||||
|
||||
|
||||
# HWLOC_LIST_STATIC_COMPONENTS
|
||||
#
|
||||
# Append to file $1 an array of components by listing component names in $2.
|
||||
#
|
||||
# $1 = filename
|
||||
# $2 = list of component names
|
||||
#
|
||||
AC_DEFUN([HWLOC_LIST_STATIC_COMPONENTS], [
|
||||
for comp in [$2]; do
|
||||
echo "HWLOC_DECLSPEC extern const struct hwloc_component hwloc_${comp}_component;" >>[$1]
|
||||
done
|
||||
cat <<EOF >>[$1]
|
||||
static const struct hwloc_component * hwloc_static_components[[]] = {
|
||||
EOF
|
||||
for comp in [$2]; do
|
||||
echo " &hwloc_${comp}_component," >>[$1]
|
||||
done
|
||||
cat <<EOF >>[$1]
|
||||
NULL
|
||||
};
|
||||
EOF
|
||||
])
|
98
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_get_version.sh
Исполняемый файл
98
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_get_version.sh
Исполняемый файл
@ -0,0 +1,98 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright © 2004-2006 The Trustees of Indiana University and Indiana
|
||||
# University Research and Technology
|
||||
# Corporation. All rights reserved.
|
||||
# Copyright © 2004-2005 The University of Tennessee and The University
|
||||
# of Tennessee Research Foundation. All rights
|
||||
# reserved.
|
||||
# Copyright © 2004-2005 High Performance Computing Center Stuttgart,
|
||||
# University of Stuttgart. All rights reserved.
|
||||
# Copyright © 2004-2005 The Regents of the University of California.
|
||||
# All rights reserved.
|
||||
# Copyright © 2008-2014 Cisco Systems, Inc. All rights reserved.
|
||||
# Copyright © 2014 Inria. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
srcfile="$1"
|
||||
option="$2"
|
||||
|
||||
if test -z "$srcfile"; then
|
||||
option="--help"
|
||||
else
|
||||
: ${srcdir=.}
|
||||
|
||||
if test -f "$srcfile"; then
|
||||
ompi_vers=`sed -n "
|
||||
t clear
|
||||
: clear
|
||||
s/^major/HWLOC_MAJOR_VERSION/
|
||||
s/^minor/HWLOC_MINOR_VERSION/
|
||||
s/^release/HWLOC_RELEASE_VERSION/
|
||||
s/^greek/HWLOC_GREEK_VERSION/
|
||||
s/\\\${major}/\\\${HWLOC_MAJOR_VERSION}/
|
||||
s/\\\${minor}/\\\${HWLOC_MINOR_VERSION}/
|
||||
s/\\\${release}/\\\${HWLOC_RELEASE_VERSION}/
|
||||
s/\\\${greek}/\\\${HWLOC_GREEK_VERSION}/
|
||||
s/^date/HWLOC_RELEASE_DATE/
|
||||
s/^snapshot_version/HWLOC_SNAPSHOT_VERSION/
|
||||
s/^snapshot/HWLOC_SNAPSHOT/
|
||||
t print
|
||||
b
|
||||
: print
|
||||
p" < "$srcfile"`
|
||||
eval "$ompi_vers"
|
||||
|
||||
HWLOC_VERSION="$HWLOC_MAJOR_VERSION.$HWLOC_MINOR_VERSION.$HWLOC_RELEASE_VERSION${HWLOC_GREEK_VERSION}"
|
||||
|
||||
# If HWLOC_SNAPSHOT=1, then use HWLOC_SNAPSHOT_VERSION
|
||||
if test "$HWLOC_SNAPSHOT" = "1"; then
|
||||
# First, verify that HWLOC_SNAPSHOT_VERSION isn't empty.
|
||||
if test -z "$HWLOC_SNAPSHOT_VERSION"; then
|
||||
echo "*** ERROR: $1 contains snapshot=1, but an empty value for snapshot_version" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
HWLOC_VERSION=$HWLOC_SNAPSHOT_VERSION
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$option" = ""; then
|
||||
option="--version"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$option" in
|
||||
--version)
|
||||
echo $HWLOC_VERSION
|
||||
;;
|
||||
--release-date)
|
||||
echo $HWLOC_RELEASE_DATE
|
||||
;;
|
||||
--snapshot)
|
||||
echo $HWLOC_SNAPSHOT
|
||||
;;
|
||||
-h|--help)
|
||||
cat <<EOF
|
||||
$0 <srcfile> <option>
|
||||
|
||||
<srcfile> - Text version file
|
||||
<option> - One of:
|
||||
--version - Show version number
|
||||
--release-date - Show the release date
|
||||
--snapshot - Show whether this is a snapshot release or not
|
||||
--help - This message
|
||||
EOF
|
||||
;;
|
||||
*)
|
||||
echo "Unrecognized option $option. Run $0 --help for options"
|
||||
;;
|
||||
esac
|
||||
|
||||
# All done
|
||||
|
||||
exit 0
|
470
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_internal.m4
Обычный файл
470
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_internal.m4
Обычный файл
@ -0,0 +1,470 @@
|
||||
dnl -*- Autoconf -*-
|
||||
dnl
|
||||
dnl Copyright © 2010-2017 Inria. All rights reserved.
|
||||
dnl Copyright © 2009, 2011 Université Bordeaux
|
||||
dnl Copyright © 2004-2005 The Trustees of Indiana University and Indiana
|
||||
dnl University Research and Technology
|
||||
dnl Corporation. All rights reserved.
|
||||
dnl Copyright © 2004-2005 The Regents of the University of California.
|
||||
dnl All rights reserved.
|
||||
dnl Copyright © 2004-2008 High Performance Computing Center Stuttgart,
|
||||
dnl University of Stuttgart. All rights reserved.
|
||||
dnl Copyright © 2006-2014 Cisco Systems, Inc. All rights reserved.
|
||||
dnl
|
||||
dnl See COPYING in top-level directory.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Probably only ever invoked by hwloc's configure.ac
|
||||
AC_DEFUN([HWLOC_BUILD_STANDALONE],[
|
||||
hwloc_mode=standalone
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Probably only ever invoked by hwloc's configure.ac
|
||||
AC_DEFUN([HWLOC_DEFINE_ARGS],[
|
||||
# Embedded mode, or standalone?
|
||||
AC_ARG_ENABLE([embedded-mode],
|
||||
AC_HELP_STRING([--enable-embedded-mode],
|
||||
[Using --enable-embedded-mode puts the HWLOC into "embedded" mode. The default is --disable-embedded-mode, meaning that the HWLOC is in "standalone" mode.]))
|
||||
|
||||
# Change the symbol prefix?
|
||||
AC_ARG_WITH([hwloc-symbol-prefix],
|
||||
AC_HELP_STRING([--with-hwloc-symbol-prefix=STRING],
|
||||
[STRING can be any valid C symbol name. It will be prefixed to all public HWLOC symbols. Default: "hwloc_"]))
|
||||
|
||||
# Debug mode?
|
||||
AC_ARG_ENABLE([debug],
|
||||
AC_HELP_STRING([--enable-debug],
|
||||
[Using --enable-debug enables various hwloc maintainer-level debugging controls. This option is not recomended for end users.]))
|
||||
|
||||
# Doxygen?
|
||||
AC_ARG_ENABLE([doxygen],
|
||||
[AC_HELP_STRING([--enable-doxygen],
|
||||
[enable support for building Doxygen documentation (note that this option is ONLY relevant in developer builds; Doxygen documentation is pre-built for tarball builds and this option is therefore ignored)])])
|
||||
|
||||
# Picky?
|
||||
AC_ARG_ENABLE(picky,
|
||||
AC_HELP_STRING([--disable-picky],
|
||||
[When in developer checkouts of hwloc and compiling with gcc, the default is to enable maximum compiler pickyness. Using --disable-picky or --enable-picky overrides any default setting]))
|
||||
|
||||
# Cairo?
|
||||
AC_ARG_ENABLE([cairo],
|
||||
AS_HELP_STRING([--disable-cairo],
|
||||
[Disable the Cairo back-end of hwloc's lstopo command]))
|
||||
|
||||
# CPUID
|
||||
AC_ARG_ENABLE([cpuid],
|
||||
AS_HELP_STRING([--disable-cpuid],
|
||||
[Disable the cpuid-based architecture specific support (x86 component)]))
|
||||
|
||||
# XML using libxml2?
|
||||
AC_ARG_ENABLE([libxml2],
|
||||
AS_HELP_STRING([--disable-libxml2],
|
||||
[Do not use libxml2 for XML support, use a custom minimalistic support]))
|
||||
|
||||
# I/O?
|
||||
AC_ARG_ENABLE([io],
|
||||
AS_HELP_STRING([--disable-io],
|
||||
[Disable I/O discovery entirely (PCI, LinuxIO, CUDA, OpenCL, NVML, GL)]))
|
||||
|
||||
# PCI?
|
||||
AC_ARG_ENABLE([pci],
|
||||
AS_HELP_STRING([--disable-pci],
|
||||
[Disable the PCI device discovery]))
|
||||
|
||||
# OpenCL?
|
||||
AC_ARG_ENABLE([opencl],
|
||||
AS_HELP_STRING([--disable-opencl],
|
||||
[Disable the OpenCL device discovery]))
|
||||
|
||||
# CUDA?
|
||||
AC_ARG_ENABLE([cuda],
|
||||
AS_HELP_STRING([--disable-cuda],
|
||||
[Disable the CUDA device discovery using libcudart]))
|
||||
|
||||
# NVML?
|
||||
AC_ARG_ENABLE([nvml],
|
||||
AS_HELP_STRING([--disable-nvml],
|
||||
[Disable the NVML device discovery]))
|
||||
|
||||
# GL/Display
|
||||
AC_ARG_ENABLE([gl],
|
||||
AS_HELP_STRING([--disable-gl],
|
||||
[Disable the GL display device discovery]))
|
||||
|
||||
# LibUdev
|
||||
AC_ARG_ENABLE([libudev],
|
||||
AS_HELP_STRING([--disable-libudev],
|
||||
[Disable the Linux libudev]))
|
||||
|
||||
# Plugins
|
||||
AC_ARG_ENABLE([plugins],
|
||||
AS_HELP_STRING([--enable-plugins=name,...],
|
||||
[Build the given components as dynamically-loaded plugins]))
|
||||
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
dnl We only build documentation if this is a developer checkout.
|
||||
dnl Distribution tarballs just install pre-built docuemntation that was
|
||||
dnl included in the tarball.
|
||||
|
||||
# Probably only ever invoked by hwloc's configure.ac
|
||||
AC_DEFUN([HWLOC_SETUP_DOCS],[
|
||||
cat <<EOF
|
||||
|
||||
###
|
||||
### Configuring hwloc documentation
|
||||
###
|
||||
EOF
|
||||
|
||||
AC_MSG_CHECKING([if this is a developer build])
|
||||
AS_IF([test ! -d "$srcdir/.hg" -a ! -d "$srcdir/.git"],
|
||||
[AC_MSG_RESULT([no (doxygen generation is optional)])
|
||||
test "x$enable_doxygen" = x && enable_doxygen=no],
|
||||
[AC_MSG_RESULT([yes])
|
||||
test "x$enable_doxygen" = x && enable_doxygen=yes])
|
||||
|
||||
# Generating the doxygen output requires a few tools. If we
|
||||
# don't have all of them, refuse the build the docs.
|
||||
AC_ARG_VAR([DOXYGEN], [Location of the doxygen program (required for building the hwloc doxygen documentation)])
|
||||
AC_PATH_TOOL([DOXYGEN], [doxygen])
|
||||
HWLOC_DOXYGEN_VERSION=`doxygen --version 2> /dev/null`
|
||||
|
||||
AC_ARG_VAR([PDFLATEX], [Location of the pdflatex program (required for building the hwloc doxygen documentation)])
|
||||
AC_PATH_TOOL([PDFLATEX], [pdflatex])
|
||||
|
||||
AC_ARG_VAR([MAKEINDEX], [Location of the makeindex program (required for building the hwloc doxygen documentation)])
|
||||
AC_PATH_TOOL([MAKEINDEX], [makeindex])
|
||||
|
||||
AC_ARG_VAR([FIG2DEV], [Location of the fig2dev program (required for building the hwloc doxygen documentation)])
|
||||
AC_PATH_TOOL([FIG2DEV], [fig2dev])
|
||||
|
||||
AC_ARG_VAR([GS], [Location of the gs program (required for building the hwloc doxygen documentation)])
|
||||
AC_PATH_TOOL([GS], [gs])
|
||||
|
||||
AC_ARG_VAR([EPSTOPDF], [Location of the epstopdf program (required for building the hwloc doxygen documentation)])
|
||||
AC_PATH_TOOL([EPSTOPDF], [epstopdf])
|
||||
|
||||
AC_MSG_CHECKING([if can build doxygen docs])
|
||||
AS_IF([test "x$DOXYGEN" != "x" -a "x$PDFLATEX" != "x" -a "x$MAKEINDEX" != "x" -a "x$FIG2DEV" != "x" -a "x$GS" != "x" -a "x$EPSTOPDF" != "x"],
|
||||
[hwloc_generate_doxs=yes], [hwloc_generate_doxs=no])
|
||||
AC_MSG_RESULT([$hwloc_generate_doxs])
|
||||
AS_IF([test "x$hwloc_generate_doxs" = xyes -a "x$HWLOC_DOXYGEN_VERSION" = x1.6.2],
|
||||
[hwloc_generate_doxs="no"; AC_MSG_WARN([doxygen 1.6.2 has broken short name support, disabling])])
|
||||
|
||||
AC_REQUIRE([AC_PROG_SED])
|
||||
|
||||
# Making the top-level README requires w3m or lynx.
|
||||
AC_ARG_VAR([W3M], [Location of the w3m program (required to building the top-level hwloc README file)])
|
||||
AC_PATH_TOOL([W3M], [w3m])
|
||||
AC_ARG_VAR([LYNX], [Location of the lynx program (required to building the top-level hwloc README file)])
|
||||
AC_PATH_TOOL([LYNX], [lynx])
|
||||
|
||||
AC_MSG_CHECKING([if can build top-level README])
|
||||
AS_IF([test "x$W3M" != "x"],
|
||||
[hwloc_generate_readme=yes
|
||||
HWLOC_W3_GENERATOR=$W3M],
|
||||
[AS_IF([test "x$LYNX" != "x"],
|
||||
[hwloc_generate_readme=yes
|
||||
HWLOC_W3_GENERATOR="$LYNX -dump -nolist"],
|
||||
[hwloc_generate_readme=no])])
|
||||
AC_SUBST(HWLOC_W3_GENERATOR)
|
||||
AC_MSG_RESULT([$hwloc_generate_readme])
|
||||
|
||||
# If any one of the above tools is missing, we will refuse to make dist.
|
||||
AC_MSG_CHECKING([if will build doxygen docs])
|
||||
AS_IF([test "x$hwloc_generate_doxs" = "xyes" -a "x$enable_doxygen" != "xno"],
|
||||
[], [hwloc_generate_doxs=no])
|
||||
AC_MSG_RESULT([$hwloc_generate_doxs])
|
||||
|
||||
# See if we want to install the doxygen docs
|
||||
AC_MSG_CHECKING([if will install doxygen docs])
|
||||
AS_IF([test "x$hwloc_generate_doxs" = "xyes" -o \
|
||||
-f "$srcdir/doc/doxygen-doc/man/man3/hwloc_distrib.3" -a \
|
||||
-f "$srcdir/doc/doxygen-doc/hwloc-a4.pdf" -a \
|
||||
-f "$srcdir/doc/doxygen-doc/hwloc-letter.pdf"],
|
||||
[hwloc_install_doxs=yes],
|
||||
[hwloc_install_doxs=no])
|
||||
AC_MSG_RESULT([$hwloc_install_doxs])
|
||||
|
||||
# For the common developer case, if we're in a developer checkout and
|
||||
# using the GNU compilers, turn on maximum warnings unless
|
||||
# specifically disabled by the user.
|
||||
AC_MSG_CHECKING([whether to enable "picky" compiler mode])
|
||||
hwloc_want_picky=0
|
||||
AS_IF([test "$hwloc_c_vendor" = "gnu"],
|
||||
[AS_IF([test -d "$srcdir/.hg" -o -d "$srcdir/.git"],
|
||||
[hwloc_want_picky=1])])
|
||||
if test "$enable_picky" = "yes"; then
|
||||
if test "$GCC" = "yes"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
hwloc_want_picky=1
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_WARN([Warning: --enable-picky used, but is currently only defined for the GCC compiler set -- automatically disabled])
|
||||
hwloc_want_picky=0
|
||||
fi
|
||||
elif test "$enable_picky" = "no"; then
|
||||
AC_MSG_RESULT([no])
|
||||
hwloc_want_picky=0
|
||||
else
|
||||
if test "$hwloc_want_picky" = 1; then
|
||||
AC_MSG_RESULT([yes (default)])
|
||||
else
|
||||
AC_MSG_RESULT([no (default)])
|
||||
fi
|
||||
fi
|
||||
if test "$hwloc_want_picky" = 1; then
|
||||
add="-Wall -Wunused-parameter -Wundef -Wno-long-long -Wsign-compare"
|
||||
add="$add -Wmissing-prototypes -Wstrict-prototypes"
|
||||
add="$add -Wcomment -pedantic -Wshadow"
|
||||
|
||||
HWLOC_CFLAGS="$HWLOC_CFLAGS $add"
|
||||
fi
|
||||
|
||||
# Generate some files for the docs
|
||||
AC_CONFIG_FILES(
|
||||
hwloc_config_prefix[doc/Makefile]
|
||||
hwloc_config_prefix[doc/examples/Makefile]
|
||||
hwloc_config_prefix[doc/doxygen-config.cfg])
|
||||
])
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Probably only ever invoked by hwloc's configure.ac
|
||||
AC_DEFUN([HWLOC_SETUP_UTILS],[
|
||||
cat <<EOF
|
||||
|
||||
###
|
||||
### Configuring hwloc command line utilities
|
||||
###
|
||||
EOF
|
||||
|
||||
AC_REQUIRE([AC_PROG_SED])
|
||||
|
||||
# runstatedir only supported in autoconf >= 2.70 and in some backports
|
||||
if test "x${runstatedir}" != "x"; then
|
||||
HWLOC_runstatedir=${runstatedir}
|
||||
else
|
||||
HWLOC_runstatedir='${localstatedir}/run'
|
||||
fi
|
||||
AC_SUBST([HWLOC_runstatedir])
|
||||
|
||||
# Cairo support
|
||||
hwloc_cairo_happy=no
|
||||
if test "x$enable_cairo" != "xno"; then
|
||||
HWLOC_PKG_CHECK_MODULES([CAIRO], [cairo], [cairo_fill], [cairo.h],
|
||||
[hwloc_cairo_happy=yes],
|
||||
[hwloc_cairo_happy=no])
|
||||
fi
|
||||
|
||||
if test "x$hwloc_cairo_happy" = "xyes"; then
|
||||
AC_DEFINE([HWLOC_HAVE_CAIRO], [1], [Define to 1 if you have the `cairo' library.])
|
||||
else
|
||||
AS_IF([test "$enable_cairo" = "yes"],
|
||||
[AC_MSG_WARN([--enable-cairo requested, but Cairo/X11 support was not found])
|
||||
AC_MSG_ERROR([Cannot continue])])
|
||||
fi
|
||||
|
||||
AC_CHECK_TYPES([wchar_t], [
|
||||
AC_CHECK_FUNCS([putwc])
|
||||
], [], [[#include <wchar.h>]])
|
||||
|
||||
HWLOC_XML_LOCALIZED=1
|
||||
AC_CHECK_HEADERS([locale.h xlocale.h], [
|
||||
AC_CHECK_FUNCS([setlocale])
|
||||
AC_CHECK_FUNCS([uselocale], [HWLOC_XML_LOCALIZED=0])
|
||||
])
|
||||
AC_SUBST([HWLOC_XML_LOCALIZED])
|
||||
AC_CHECK_HEADERS([langinfo.h], [
|
||||
AC_CHECK_FUNCS([nl_langinfo])
|
||||
])
|
||||
hwloc_old_LIBS="$LIBS"
|
||||
chosen_curses=""
|
||||
for curses in ncurses curses
|
||||
do
|
||||
for lib in "" -ltermcap -l${curses}w -l$curses
|
||||
do
|
||||
AC_MSG_CHECKING(termcap support using $curses and $lib)
|
||||
LIBS="$hwloc_old_LIBS $lib"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <$curses.h>
|
||||
#include <term.h>
|
||||
]], [[tparm(NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0)]])], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_SUBST([HWLOC_TERMCAP_LIBS], ["$LIBS"])
|
||||
AC_DEFINE([HWLOC_HAVE_LIBTERMCAP], [1],
|
||||
[Define to 1 if you have a library providing the termcap interface])
|
||||
chosen_curses=$curses
|
||||
], [
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
test "x$chosen_curses" != "x" && break
|
||||
done
|
||||
test "x$chosen_curses" != "x" && break
|
||||
done
|
||||
if test "$chosen_curses" = ncurses
|
||||
then
|
||||
AC_DEFINE([HWLOC_USE_NCURSES], [1], [Define to 1 if ncurses works, preferred over curses])
|
||||
fi
|
||||
LIBS="$hwloc_old_LIBS"
|
||||
unset hwloc_old_LIBS
|
||||
|
||||
_HWLOC_CHECK_DIFF_U
|
||||
_HWLOC_CHECK_DIFF_W
|
||||
|
||||
AC_CHECK_HEADERS([time.h], [
|
||||
AC_CHECK_FUNCS([clock_gettime])
|
||||
])
|
||||
|
||||
# Only generate this if we're building the utilities
|
||||
AC_CONFIG_FILES(
|
||||
hwloc_config_prefix[utils/Makefile]
|
||||
hwloc_config_prefix[utils/hwloc/Makefile]
|
||||
hwloc_config_prefix[utils/lstopo/Makefile]
|
||||
hwloc_config_prefix[hwloc.pc]
|
||||
|
||||
hwloc_config_prefix[utils/netloc/infiniband/Makefile]
|
||||
hwloc_config_prefix[utils/netloc/draw/Makefile]
|
||||
hwloc_config_prefix[utils/netloc/mpi/Makefile]
|
||||
hwloc_config_prefix[netloc.pc]
|
||||
hwloc_config_prefix[netlocscotch.pc]
|
||||
)
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Probably only ever invoked by hwloc's configure.ac
|
||||
AC_DEFUN([HWLOC_SETUP_TESTS],[
|
||||
cat <<EOF
|
||||
|
||||
###
|
||||
### Configuring tests
|
||||
###
|
||||
EOF
|
||||
|
||||
AC_CHECK_LIB([pthread], [pthread_self], [hwloc_have_pthread=yes])
|
||||
|
||||
# linux-libnuma.h testing requires libnuma with numa_bitmask_alloc()
|
||||
AC_CHECK_LIB([numa], [numa_available], [
|
||||
AC_CHECK_DECL([numa_bitmask_alloc], [hwloc_have_linux_libnuma=yes], [],
|
||||
[#include <numa.h>])
|
||||
])
|
||||
|
||||
AC_CHECK_HEADERS([infiniband/verbs.h], [
|
||||
AC_CHECK_LIB([ibverbs], [ibv_open_device],
|
||||
[AC_DEFINE([HAVE_LIBIBVERBS], 1, [Define to 1 if we have -libverbs])
|
||||
hwloc_have_libibverbs=yes])
|
||||
])
|
||||
|
||||
AC_CHECK_HEADERS([myriexpress.h], [
|
||||
AC_MSG_CHECKING(if MX_NUMA_NODE exists)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <myriexpress.h>]],
|
||||
[[int a = MX_NUMA_NODE;]])],
|
||||
[AC_MSG_RESULT(yes)
|
||||
AC_CHECK_LIB([myriexpress], [mx_get_info],
|
||||
[AC_DEFINE([HAVE_MYRIEXPRESS], 1, [Define to 1 if we have -lmyriexpress])
|
||||
hwloc_have_myriexpress=yes])],
|
||||
[AC_MSG_RESULT(no)])])
|
||||
|
||||
AC_CHECK_PROGS(XMLLINT, [xmllint])
|
||||
|
||||
AC_CHECK_PROGS(BUNZIPP, bunzip2, false)
|
||||
|
||||
AC_MSG_CHECKING(if CXX works)
|
||||
AC_LANG_PUSH([C++])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
int foo(void) {
|
||||
cout << "test" << endl;
|
||||
return 0;
|
||||
}
|
||||
]])], [hwloc_have_cxx=yes], [hwloc_have_cxx=no])
|
||||
AC_LANG_POP([C++])
|
||||
AC_MSG_RESULT([$hwloc_have_cxx])
|
||||
|
||||
_HWLOC_CHECK_DIFF_U
|
||||
|
||||
# Only generate these files if we're making the tests
|
||||
AC_CONFIG_FILES(
|
||||
hwloc_config_prefix[tests/Makefile]
|
||||
hwloc_config_prefix[tests/hwloc/Makefile]
|
||||
hwloc_config_prefix[tests/hwloc/linux/Makefile]
|
||||
hwloc_config_prefix[tests/hwloc/linux/allowed/Makefile]
|
||||
hwloc_config_prefix[tests/hwloc/linux/gather/Makefile]
|
||||
hwloc_config_prefix[tests/hwloc/x86/Makefile]
|
||||
hwloc_config_prefix[tests/hwloc/xml/Makefile]
|
||||
hwloc_config_prefix[tests/hwloc/ports/Makefile]
|
||||
hwloc_config_prefix[tests/hwloc/rename/Makefile]
|
||||
hwloc_config_prefix[tests/hwloc/linux/allowed/test-topology.sh]
|
||||
hwloc_config_prefix[tests/hwloc/linux/gather/test-gather-topology.sh]
|
||||
hwloc_config_prefix[tests/hwloc/linux/test-topology.sh]
|
||||
hwloc_config_prefix[tests/hwloc/x86/test-topology.sh]
|
||||
hwloc_config_prefix[tests/hwloc/xml/test-topology.sh]
|
||||
hwloc_config_prefix[tests/hwloc/wrapper.sh]
|
||||
hwloc_config_prefix[utils/hwloc/hwloc-compress-dir]
|
||||
hwloc_config_prefix[utils/hwloc/hwloc-gather-topology]
|
||||
hwloc_config_prefix[utils/hwloc/test-hwloc-annotate.sh]
|
||||
hwloc_config_prefix[utils/hwloc/test-hwloc-calc.sh]
|
||||
hwloc_config_prefix[utils/hwloc/test-hwloc-compress-dir.sh]
|
||||
hwloc_config_prefix[utils/hwloc/test-hwloc-diffpatch.sh]
|
||||
hwloc_config_prefix[utils/hwloc/test-hwloc-distrib.sh]
|
||||
hwloc_config_prefix[utils/hwloc/test-hwloc-info.sh]
|
||||
hwloc_config_prefix[utils/hwloc/test-fake-plugin.sh]
|
||||
hwloc_config_prefix[utils/hwloc/test-hwloc-dump-hwdata/Makefile]
|
||||
hwloc_config_prefix[utils/hwloc/test-hwloc-dump-hwdata/test-hwloc-dump-hwdata.sh]
|
||||
hwloc_config_prefix[utils/lstopo/test-lstopo.sh]
|
||||
hwloc_config_prefix[contrib/systemd/Makefile]
|
||||
hwloc_config_prefix[contrib/misc/Makefile]
|
||||
hwloc_config_prefix[tests/netloc/Makefile]
|
||||
hwloc_config_prefix[tests/netloc/tests.sh]
|
||||
)
|
||||
|
||||
AC_CONFIG_COMMANDS([chmoding-scripts], [
|
||||
chmod +x ]hwloc_config_prefix[tests/hwloc/linux/test-topology.sh \
|
||||
]hwloc_config_prefix[tests/hwloc/x86/test-topology.sh \
|
||||
]hwloc_config_prefix[tests/hwloc/xml/test-topology.sh \
|
||||
]hwloc_config_prefix[tests/hwloc/linux/allowed/test-topology.sh \
|
||||
]hwloc_config_prefix[tests/hwloc/linux/gather/test-gather-topology.sh \
|
||||
]hwloc_config_prefix[tests/hwloc/wrapper.sh \
|
||||
]hwloc_config_prefix[utils/hwloc/hwloc-compress-dir \
|
||||
]hwloc_config_prefix[utils/hwloc/hwloc-gather-topology \
|
||||
]hwloc_config_prefix[utils/hwloc/test-hwloc-annotate.sh \
|
||||
]hwloc_config_prefix[utils/hwloc/test-hwloc-calc.sh \
|
||||
]hwloc_config_prefix[utils/hwloc/test-hwloc-compress-dir.sh \
|
||||
]hwloc_config_prefix[utils/hwloc/test-hwloc-diffpatch.sh \
|
||||
]hwloc_config_prefix[utils/hwloc/test-hwloc-distrib.sh \
|
||||
]hwloc_config_prefix[utils/hwloc/test-hwloc-info.sh \
|
||||
]hwloc_config_prefix[utils/hwloc/test-fake-plugin.sh \
|
||||
]hwloc_config_prefix[utils/hwloc/test-hwloc-dump-hwdata/test-hwloc-dump-hwdata.sh \
|
||||
]hwloc_config_prefix[utils/lstopo/test-lstopo.sh \
|
||||
]hwloc_config_prefix[tests/netloc/tests.sh])
|
||||
|
||||
# These links are only needed in standalone mode. It would
|
||||
# be nice to m4 foreach this somehow, but whenever I tried
|
||||
# it, I got obscure "invalid tag" errors from
|
||||
# AC_CONFIG_LINKS. :-\ Since these tests are only run when
|
||||
# built in standalone mode, only generate them in
|
||||
# standalone mode.
|
||||
AC_CONFIG_LINKS(
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-solaris.c]:hwloc_config_prefix[hwloc/topology-solaris.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-solaris-chiptype.c]:hwloc_config_prefix[hwloc/topology-solaris-chiptype.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-aix.c]:hwloc_config_prefix[hwloc/topology-aix.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-windows.c]:hwloc_config_prefix[hwloc/topology-windows.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-darwin.c]:hwloc_config_prefix[hwloc/topology-darwin.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-freebsd.c]:hwloc_config_prefix[hwloc/topology-freebsd.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-netbsd.c]:hwloc_config_prefix[hwloc/topology-netbsd.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-hpux.c]:hwloc_config_prefix[hwloc/topology-hpux.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-bgq.c]:hwloc_config_prefix[hwloc/topology-bgq.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-opencl.c]:hwloc_config_prefix[hwloc/topology-opencl.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-cuda.c]:hwloc_config_prefix[hwloc/topology-cuda.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-nvml.c]:hwloc_config_prefix[hwloc/topology-nvml.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/topology-gl.c]:hwloc_config_prefix[hwloc/topology-gl.c]
|
||||
hwloc_config_prefix[tests/hwloc/ports/lstopo-windows.c]:hwloc_config_prefix[utils/lstopo/lstopo-windows.c])
|
||||
])
|
||||
])dnl
|
207
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_pkg.m4
Обычный файл
207
opal/mca/hwloc/hwloc2x/hwloc/config/hwloc_pkg.m4
Обычный файл
@ -0,0 +1,207 @@
|
||||
# Copyright © 2010 Cisco Systems, Inc. All rights reserved.
|
||||
# Copyright © 2015 Inria. All rights reserved.
|
||||
# See COPYING in top-level directory.
|
||||
#
|
||||
# hwloc modification to the following PKG_* macros -- add HWLOC_
|
||||
# prefix to make it "safe" to embed these macros in other packages.
|
||||
# Originally copied from the pkg-config package; see copyright and
|
||||
# license below.
|
||||
|
||||
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||
#
|
||||
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# HWLOC_PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||
# ----------------------------------
|
||||
# hwloc note: Per https://git.open-mpi.org/trac/hwloc/ticket/55, keep
|
||||
# the environment variable $PKG_CONFIG (vs. renaming it
|
||||
# $HWLOC_PKG_CONFIG). Short explanation: $PKG_CONFIG is a well-known
|
||||
# environment variable that can be set by users to override what these
|
||||
# .m4 macros do. There's no reason we should have a different env
|
||||
# variable name (e.g., $HWLOC_PKG_CONFIG). So leave it named
|
||||
# $PKG_CONFIG both here in this specific macro, and all the other
|
||||
# macros that use it.
|
||||
AC_DEFUN([HWLOC_PKG_PROG_PKG_CONFIG],
|
||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||
m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
|
||||
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
|
||||
|
||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
HWLOC_pkg_min_version=m4_default([$1], [0.9.0])
|
||||
AC_MSG_CHECKING([pkg-config is at least version $HWLOC_pkg_min_version])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version $HWLOC_pkg_min_version; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
|
||||
fi[]dnl
|
||||
])# HWLOC_PKG_PROG_PKG_CONFIG
|
||||
|
||||
# HWLOC_PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
#
|
||||
# Check to see whether a particular set of modules exists. Similar
|
||||
# to HWLOC_PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||
#
|
||||
#
|
||||
# Similar to HWLOC_PKG_CHECK_MODULES, make sure that the first instance of
|
||||
# this or HWLOC_PKG_CHECK_MODULES is called, or make sure to call
|
||||
# HWLOC_PKG_CHECK_EXISTS manually
|
||||
# --------------------------------------------------------------
|
||||
AC_DEFUN([HWLOC_PKG_CHECK_EXISTS],
|
||||
[AC_REQUIRE([HWLOC_PKG_PROG_PKG_CONFIG])dnl
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
AC_RUN_LOG([$PKG_CONFIG --exists --silence-errors "$1"]); then
|
||||
m4_ifval([$2], [$2], [:])
|
||||
m4_ifvaln([$3], [else
|
||||
$3])dnl
|
||||
fi])
|
||||
|
||||
|
||||
# _HWLOC_PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||
# ---------------------------------------------
|
||||
m4_define([_HWLOC_PKG_CONFIG],
|
||||
[if test -n "$PKG_CONFIG"; then
|
||||
if test -n "$$1"; then
|
||||
HWLOC_pkg_cv_[]$1="$$1"
|
||||
else
|
||||
HWLOC_PKG_CHECK_EXISTS([$3],
|
||||
[HWLOC_pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
|
||||
[HWLOC_pkg_failed=yes])
|
||||
fi
|
||||
else
|
||||
HWLOC_pkg_failed=untried
|
||||
fi[]
|
||||
])# _HWLOC_PKG_CONFIG
|
||||
|
||||
# _HWLOC_PKG_SHORT_ERRORS_SUPPORTED
|
||||
# -----------------------------
|
||||
AC_DEFUN([_HWLOC_PKG_SHORT_ERRORS_SUPPORTED],
|
||||
[AC_REQUIRE([HWLOC_PKG_PROG_PKG_CONFIG])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
HWLOC_pkg_short_errors_supported=yes
|
||||
else
|
||||
HWLOC_pkg_short_errors_supported=no
|
||||
fi[]dnl
|
||||
])# _HWLOC_PKG_SHORT_ERRORS_SUPPORTED
|
||||
|
||||
|
||||
# HWLOC_PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, FUNCTION, HEADER, [ACTION-IF-FOUND],
|
||||
# [ACTION-IF-NOT-FOUND])
|
||||
#
|
||||
#
|
||||
# Note that if there is a possibility the first call to
|
||||
# HWLOC_PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||
# explicit call to HWLOC_PKG_PROG_PKG_CONFIG in your configure.ac
|
||||
#
|
||||
#
|
||||
# --------------------------------------------------------------
|
||||
AC_DEFUN([HWLOC_PKG_CHECK_MODULES],[
|
||||
AC_REQUIRE([HWLOC_PKG_PROG_PKG_CONFIG])dnl
|
||||
AC_ARG_VAR([HWLOC_]$1[_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||
AC_ARG_VAR([HWLOC_]$1[_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||
|
||||
HWLOC_pkg_failed=no
|
||||
AC_MSG_CHECKING([for $1])
|
||||
|
||||
_HWLOC_PKG_CONFIG([HWLOC_][$1][_CFLAGS], [cflags], [$2])
|
||||
_HWLOC_PKG_CONFIG([HWLOC_][$1][_LIBS], [libs], [$2])
|
||||
|
||||
m4_define([_HWLOC_PKG_TEXT], [Alternatively, you may set the environment variables HWLOC_[]$1[]_CFLAGS
|
||||
and HWLOC_[]$1[]_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.])
|
||||
|
||||
# Check for failure of pkg-config
|
||||
if test $HWLOC_pkg_failed = yes; then
|
||||
_HWLOC_PKG_SHORT_ERRORS_SUPPORTED
|
||||
if test $HWLOC_pkg_short_errors_supported = yes; then
|
||||
HWLOC_[]$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2" 2>&1`
|
||||
else
|
||||
HWLOC_[]$1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$HWLOC_[]$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||
|
||||
ifelse([$6], , [AC_MSG_ERROR(dnl
|
||||
[Package requirements ($2) were not met:
|
||||
|
||||
$HWLOC_$1_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
_HWLOC_PKG_TEXT
|
||||
])],
|
||||
[AC_MSG_RESULT([no])
|
||||
$6])
|
||||
elif test $HWLOC_pkg_failed = untried; then
|
||||
ifelse([$6], , [AC_MSG_FAILURE(dnl
|
||||
[The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
_HWLOC_PKG_TEXT
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
|
||||
[AC_MSG_RESULT([cannot check without pkg-config])
|
||||
$6])
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
|
||||
# If we got good results from pkg-config, check that they
|
||||
# actually work (i.e., that we can link against the resulting
|
||||
# $LIBS). The canonical example why we do this is if
|
||||
# pkg-config returns 64 bit libraries but ./configure was run
|
||||
# with CFLAGS=-m32 LDFLAGS=-m32. pkg-config gave us valid
|
||||
# results, but we'll fail if we try to link. So detect that
|
||||
# failure now.
|
||||
# There are also cases on Mac where pkg-config returns paths
|
||||
# that do not actually exists until some magic is applied.
|
||||
# http://www.open-mpi.org/community/lists/hwloc-devel/2015/03/4402.php
|
||||
# So check whether we find the header as well.
|
||||
hwloc_cflags_save=$CFLAGS
|
||||
hwloc_cppflags_save=$CPPFLAGS
|
||||
hwloc_libs_save=$LIBS
|
||||
CFLAGS="$CFLAGS $HWLOC_pkg_cv_HWLOC_[]$1[]_CFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $HWLOC_pkg_cv_HWLOC_[]$1[]_CFLAGS"
|
||||
LIBS="$LIBS $HWLOC_pkg_cv_HWLOC_[]$1[]_LIBS"
|
||||
AC_CHECK_HEADER([$4], [
|
||||
AC_CHECK_FUNC([$3], [hwloc_result=yes], [hwloc_result=no])
|
||||
], [hwloc_result=no])
|
||||
CFLAGS=$hwloc_cflags_save
|
||||
CPPFLAGS=$hwloc_cppflags_save
|
||||
LIBS=$hwloc_libs_save
|
||||
|
||||
AC_MSG_CHECKING([for final $1 support])
|
||||
AS_IF([test "$hwloc_result" = "yes"],
|
||||
[HWLOC_[]$1[]_CFLAGS=$HWLOC_pkg_cv_HWLOC_[]$1[]_CFLAGS
|
||||
HWLOC_[]$1[]_LIBS=$HWLOC_pkg_cv_HWLOC_[]$1[]_LIBS
|
||||
AC_MSG_RESULT([yes])
|
||||
ifelse([$5], , :, [$5])],
|
||||
[AC_MSG_RESULT([no])
|
||||
ifelse([$6], , :, [$6])])
|
||||
fi[]dnl
|
||||
])# HWLOC_PKG_CHECK_MODULES
|
116
opal/mca/hwloc/hwloc2x/hwloc/config/netloc.m4
Обычный файл
116
opal/mca/hwloc/hwloc2x/hwloc/config/netloc.m4
Обычный файл
@ -0,0 +1,116 @@
|
||||
dnl -*- Autoconf -*-
|
||||
dnl
|
||||
dnl Copyright © 2014 Cisco Systems, Inc. All rights reserved.
|
||||
dnl
|
||||
dnl Copyright © 2014-2017 Inria. All rights reserved.
|
||||
dnl See COPYING in top-level directory.
|
||||
|
||||
# Main hwloc m4 macro, to be invoked by the user
|
||||
#
|
||||
# Expects:
|
||||
# 1. Configuration prefix
|
||||
# 2. What to do upon success
|
||||
# 3. What to do upon failure
|
||||
# 4. If non-empty, print the announcement banner
|
||||
#
|
||||
AC_DEFUN([NETLOC_SETUP_CORE],[
|
||||
AC_REQUIRE([HWLOC_SETUP_CORE])
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
|
||||
AS_IF([test "x$4" != "x"],
|
||||
[cat <<EOF
|
||||
|
||||
###
|
||||
### Configuring netloc core
|
||||
###
|
||||
EOF])
|
||||
|
||||
# If no prefix was defined, set a good value
|
||||
m4_ifval([$1],
|
||||
[m4_define([netloc_config_prefix],[$1/])],
|
||||
[m4_define([netloc_config_prefix], [])])
|
||||
|
||||
# These flags are specific to netloc, and should not be redundant
|
||||
# with hwloc. I.e., if the flag already exists in hwloc, there's
|
||||
# no need to put it here.
|
||||
NETLOC_CFLAGS=$HWLOC_CFLAGS
|
||||
NETLOC_CPPFLAGS=$HWLOC_CPPFLAGS
|
||||
NETLOC_LDFLAGS=$HWLOC_LDFLAGS
|
||||
NETLOC_LIBS=
|
||||
NETLOC_LIBS_PRIVATE=
|
||||
|
||||
# Setup the individual parts of Netloc
|
||||
netloc_happy=yes
|
||||
AS_IF([test "$netloc_happy" = "yes"],
|
||||
[NETLOC_CHECK_PLATFORM([netloc_happy])])
|
||||
|
||||
AC_SUBST(NETLOC_CFLAGS)
|
||||
AC_SUBST(NETLOC_CPPFLAGS)
|
||||
AC_SUBST(NETLOC_LDFLAGS)
|
||||
AC_SUBST(NETLOC_LIBS)
|
||||
AC_SUBST(NETLOC_LIBS_PRIVATE)
|
||||
|
||||
# Set these values explicitly for embedded builds. Exporting
|
||||
# these values through *_EMBEDDED_* values gives us the freedom to
|
||||
# do something different someday if we ever need to. There's no
|
||||
# need to fill these values in unless we're in embedded mode.
|
||||
# Indeed, if we're building in embedded mode, we want NETLOC_LIBS
|
||||
# to be empty so that nothing is linked into libnetloc_embedded.la
|
||||
# itself -- only the upper-layer will link in anything required.
|
||||
|
||||
AS_IF([test "$hwloc_mode" = "embedded"],
|
||||
[NETLOC_EMBEDDED_CFLAGS=$NETLOC_CFLAGS
|
||||
NETLOC_EMBEDDED_CPPFLAGS=$NETLOC_CPPFLAGS
|
||||
NETLOC_EMBEDDED_LDADD='$(HWLOC_top_builddir)/netloc/libnetloc_embedded.la'
|
||||
NETLOC_EMBEDDED_LIBS=$NETLOC_LIBS
|
||||
NETLOC_LIBS=],
|
||||
[AC_CONFIG_FILES(netloc_config_prefix[utils/netloc/infiniband/netloc_ib_gather_raw])
|
||||
AC_CONFIG_COMMANDS([chmoding-netloc-scripts], [
|
||||
chmod +x ]hwloc_config_prefix[utils/netloc/infiniband/netloc_ib_gather_raw
|
||||
])
|
||||
])
|
||||
AC_SUBST(NETLOC_EMBEDDED_CFLAGS)
|
||||
AC_SUBST(NETLOC_EMBEDDED_CPPFLAGS)
|
||||
AC_SUBST(NETLOC_EMBEDDED_LDADD)
|
||||
AC_SUBST(NETLOC_EMBEDDED_LIBS)
|
||||
|
||||
AC_CONFIG_FILES(
|
||||
netloc_config_prefix[netloc/Makefile]
|
||||
)
|
||||
|
||||
AS_IF([test "$netloc_happy" = "yes"],
|
||||
[$2],
|
||||
[$3])
|
||||
])dnl
|
||||
|
||||
AC_DEFUN([NETLOC_CHECK_PLATFORM], [
|
||||
AC_CHECK_FUNC([asprintf])
|
||||
AC_MSG_CHECKING([if netloc supports this platform])
|
||||
AS_IF([test "$ac_cv_func_asprintf" != "yes"],
|
||||
[$1=no netloc_missing_reason=" (asprintf missing)"])
|
||||
AS_IF([test "$hwloc_windows" = "yes"],
|
||||
[$1=no netloc_missing_reason=" (Windows platform)"])
|
||||
AC_MSG_RESULT([$$1$netloc_missing_reason])
|
||||
|
||||
AC_CHECK_LIB(scotch, SCOTCH_archSub,
|
||||
[scotch_found_headers=yes;
|
||||
AC_DEFINE([NETLOC_SCOTCH], [1],
|
||||
[Define to 1 if scotch is netlocscotch is enabled])
|
||||
], [], -lscotcherr)
|
||||
AC_CHECK_HEADERS([mpi.h],
|
||||
[mpi_found_headers=yes;
|
||||
MPI_CPPFLAGS=`mpicc -showme:compile 2>/dev/null`
|
||||
MPI_LDADD=`mpicc -showme:link 2>/dev/null`
|
||||
AC_SUBST(MPI_CPPFLAGS)
|
||||
AC_SUBST(MPI_LDADD)
|
||||
break;])
|
||||
|
||||
AC_CHECK_PROG([xz],[xz],[yes],[no])
|
||||
])dnl
|
||||
|
||||
AC_DEFUN([NETLOC_DO_AM_CONDITIONALS], [
|
||||
AM_CONDITIONAL([BUILD_NETLOC], [test "$netloc_happy" = "yes"])
|
||||
AM_CONDITIONAL([BUILD_NETLOCSCOTCH], [test "x$scotch_found_headers" = "xyes"])
|
||||
AM_CONDITIONAL([BUILD_MPITOOLS], [test "x$mpi_found_headers" = "xyes"])
|
||||
AM_CONDITIONAL([FOUND_XZ], [test "x$xz" = xyes])
|
||||
])dnl
|
271
opal/mca/hwloc/hwloc2x/hwloc/configure.ac
Обычный файл
271
opal/mca/hwloc/hwloc2x/hwloc/configure.ac
Обычный файл
@ -0,0 +1,271 @@
|
||||
# -*- shell-script -*-
|
||||
#
|
||||
# Copyright © 2009 CNRS
|
||||
# Copyright © 2009-2016 Inria. All rights reserved.
|
||||
# Copyright © 2009, 2011-2012 Université Bordeaux
|
||||
# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved.
|
||||
#
|
||||
# See COPYING in top-level directory.
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
####################################################################
|
||||
# Autoconf, Automake, and Libtool bootstrapping
|
||||
####################################################################
|
||||
|
||||
AC_INIT([hwloc],
|
||||
[m4_normalize(esyscmd([config/hwloc_get_version.sh VERSION --version]))],
|
||||
[http://www.open-mpi.org/projects/hwloc/], [hwloc])
|
||||
AC_PREREQ(2.63)
|
||||
AC_CONFIG_AUX_DIR(./config)
|
||||
# Note that this directory must *exactly* match what was specified via
|
||||
# -I in ACLOCAL_AMFLAGS in the top-level Makefile.am.
|
||||
AC_CONFIG_MACRO_DIR(./config)
|
||||
|
||||
cat <<EOF
|
||||
|
||||
###
|
||||
### Configuring hwloc distribution tarball
|
||||
### Startup tests
|
||||
###
|
||||
EOF
|
||||
|
||||
# This must be before AM_INIT_AUTOMAKE
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
# Init automake
|
||||
AM_INIT_AUTOMAKE([1.11 dist-bzip2 subdir-objects foreign tar-ustar parallel-tests -Wall -Werror])
|
||||
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
|
||||
|
||||
AC_LANG([C])
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
####################################################################
|
||||
# Setup the configure-results header file
|
||||
####################################################################
|
||||
|
||||
AH_TOP([/* -*- c -*-
|
||||
*
|
||||
* Copyright © 2009, 2011, 2012 CNRS, inria., Université Bordeaux All rights reserved.
|
||||
* Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*
|
||||
* This file is automatically generated by configure. Edits will be lost
|
||||
* the next time you run configure!
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_CONFIGURE_H
|
||||
#define HWLOC_CONFIGURE_H
|
||||
])
|
||||
AH_BOTTOM([
|
||||
#endif /* HWLOC_CONFIGURE_H */
|
||||
])
|
||||
|
||||
####################################################################
|
||||
# Setup Libtool
|
||||
####################################################################
|
||||
|
||||
# We want new Libtool. None of that old stuff. Pfft.
|
||||
m4_ifdef([LT_PREREQ], [],
|
||||
[m4_fatal([libtool version 2.2.6 or higher is required], [63])])
|
||||
LT_PREREQ([2.2.6])
|
||||
|
||||
# Setup libtool, but disable F77, Java and Windows Resource
|
||||
# Compiler support -- we don't need that stuff.
|
||||
AM_ENABLE_SHARED
|
||||
AM_DISABLE_STATIC
|
||||
|
||||
# This did not exist pre AM 1.11.x (where x is somewhere >0 and <3),
|
||||
# but it is necessary in AM 1.12.x.
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
|
||||
LT_INIT([dlopen win32-dll])
|
||||
LT_LANG([C])
|
||||
LT_LANG([C++])
|
||||
|
||||
####################################################################
|
||||
# Setup C, C++ compilers
|
||||
####################################################################
|
||||
|
||||
CFLAGS_save=$CFLAGS
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_CC_C99
|
||||
CFLAGS=$CFLAGS_save
|
||||
|
||||
AC_ARG_VAR(CC_FOR_BUILD,[build system C compiler])
|
||||
AS_IF([test -z "$CC_FOR_BUILD"],[
|
||||
AC_SUBST([CC_FOR_BUILD], [$CC])
|
||||
])
|
||||
|
||||
####################################################################
|
||||
# CLI arguments
|
||||
####################################################################
|
||||
|
||||
# Define hwloc's configure arguments
|
||||
HWLOC_DEFINE_ARGS
|
||||
|
||||
# If debug mode, add -g
|
||||
AS_IF([test "$hwloc_debug" = "1"],
|
||||
[CFLAGS="$CFLAGS -g"])
|
||||
|
||||
# If the user didn't specifically ask for embedding mode, default to
|
||||
# standalone mode
|
||||
AS_IF([test "$enable_embedded_mode" != "yes"],
|
||||
[AS_IF([test ! -d "$srcdir/doc"],
|
||||
[AC_MSG_WARN([The hwloc source tree looks incomplete for a standalone])
|
||||
AC_MSG_WARN([build. Perhaps this hwloc tree is intended for an embedded])
|
||||
AC_MSG_WARN([build? Try using the --enable-embedded-mode switch.])
|
||||
AC_MSG_ERROR([Cannot build standalone hwloc])],
|
||||
[HWLOC_BUILD_STANDALONE])])
|
||||
|
||||
####################################################################
|
||||
# Setup for the hwloc API
|
||||
####################################################################
|
||||
|
||||
AC_SUBST([libhwloc_so_version])
|
||||
|
||||
# Setup the hwloc core
|
||||
HWLOC_SETUP_CORE([], [], [AC_MSG_ERROR([Cannot build hwloc core])], [1])
|
||||
|
||||
####################################################################
|
||||
# Setup the netloc API
|
||||
####################################################################
|
||||
|
||||
AC_SUBST([libnetloc_so_version])
|
||||
|
||||
AC_ARG_ENABLE([netloc],
|
||||
[AC_HELP_STRING([--enable-netloc],
|
||||
[The Netloc functionality is enabled by default, but will be silently skipped it if cannot be built (e.g., not supported on your platform). Using --enable-netloc will cause configure to abort if Netloc cannot be build. Using --disable-netloc will cause configure to skip attempting to build netloc at all.])
|
||||
])
|
||||
|
||||
AS_IF([test "$enable_netloc" != "no"],
|
||||
[NETLOC_SETUP_CORE([], [],
|
||||
[AS_IF([test "$enable_netloc" = "yes"],
|
||||
[AC_MSG_ERROR([Cannot build netloc core])])
|
||||
],
|
||||
[1])
|
||||
])
|
||||
|
||||
####################################################################
|
||||
# Version information
|
||||
####################################################################
|
||||
|
||||
# HWLOC_VERSION was setup by HWLOC_SETUP_CORE above.
|
||||
|
||||
# Make configure depend on the VERSION file, since it's used in AC_INIT
|
||||
AC_SUBST([CONFIGURE_DEPENDENCIES], ['$(top_srcdir)/VERSION'])
|
||||
|
||||
# Override/fixup the version numbers set by AC_INIT, since on
|
||||
# developer builds, there's no good way to know what the version is
|
||||
# before running configure :(. We only use the base version number
|
||||
# for the version set in AC_INIT. This will always match reality
|
||||
# because we add the VERSION file (the only way to change the
|
||||
# major.minor.release{greek}) into the configure dependencies.
|
||||
PACKAGE_VERSION="$HWLOC_VERSION"
|
||||
PACKAGE_STRING="${PACKAGE_NAME} ${PACKAGE_VERSION}"
|
||||
VERSION="${PACKAGE_VERSION}"
|
||||
|
||||
# For standalone configurations, we also include a .so version number.
|
||||
|
||||
. $srcdir/VERSION
|
||||
|
||||
####################################################################
|
||||
# Setup the rest of the infrastructure
|
||||
####################################################################
|
||||
|
||||
# Setup hwloc's docs, utils, and tests
|
||||
AS_IF([test "$hwloc_mode" = "standalone"],
|
||||
[HWLOC_SETUP_DOCS
|
||||
HWLOC_SETUP_UTILS
|
||||
HWLOC_SETUP_TESTS])
|
||||
|
||||
cat <<EOF
|
||||
|
||||
###
|
||||
### Performing final hwloc configuration
|
||||
###
|
||||
EOF
|
||||
|
||||
# Run the AM_CONDITIONALs
|
||||
HWLOC_DO_AM_CONDITIONALS
|
||||
NETLOC_DO_AM_CONDITIONALS
|
||||
|
||||
####################################################################
|
||||
# Final output
|
||||
####################################################################
|
||||
|
||||
# Set the final flags
|
||||
CFLAGS="$HWLOC_EMBEDDED_CFLAGS $CFLAGS"
|
||||
CPPFLAGS="$HWLOC_EMBEDDED_CPPFLAGS $CPPFLAGS"
|
||||
LIBS="$HWLOC_EMBEDDED_LIBS $LIBS"
|
||||
|
||||
# Party on
|
||||
AC_OUTPUT
|
||||
|
||||
# Warn if we didn't have pkg-config
|
||||
if test "x$PKG_CONFIG" = x; then
|
||||
cat << EOF
|
||||
|
||||
************************************************************************
|
||||
Could not detect/enable some features such as libxml2 and Cairo support
|
||||
because pkg-config isn't available.
|
||||
************************************************************************
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Show which optional support we'll be building
|
||||
hwloc_xml_status=basic
|
||||
AS_IF([test "$hwloc_libxml2_happy" = "yes"], [hwloc_xml_status=full])
|
||||
netloc_status=no
|
||||
AS_IF([test "$netloc_happy" = "yes"], [netloc_status=yes])
|
||||
netlocscotch_status=no
|
||||
AS_IF([test "$scotch_found_headers" = "yes"], [netlocscotch_status=yes])
|
||||
|
||||
# Prepare the I/O summary
|
||||
hwloc_probeio_list=
|
||||
if test "x$hwloc_pciaccess_happy" = "xyes" -o "x$hwloc_linuxpci_happy" = "xyes"; then
|
||||
test "x$hwloc_pciaccess_happy" = "xyes" && hwloc_probepci_list=pciaccess
|
||||
test "x$hwloc_pciaccess_happy$hwloc_linuxpci_happy" = "xyesyes" && hwloc_probepci_list="${hwloc_probepci_list}+"
|
||||
test "x$hwloc_linuxio_happy" = "xyes" && hwloc_probepci_list="${hwloc_probepci_list}linux"
|
||||
hwloc_probeio_list="$hwloc_probeio_list PCI($hwloc_probepci_list)"
|
||||
fi
|
||||
test "x$hwloc_linuxio_happy" = "xyes" && hwloc_probeio_list="$hwloc_probeio_list LinuxIO"
|
||||
test "x$hwloc_opencl_happy" = "xyes" && hwloc_probeio_list="$hwloc_probeio_list OpenCL"
|
||||
test "x$hwloc_have_cudart" = "xyes" && hwloc_probeio_list="$hwloc_probeio_list CUDA"
|
||||
test "x$hwloc_nvml_happy" = "xyes" && hwloc_probeio_list="$hwloc_probeio_list NVML"
|
||||
test "x$hwloc_gl_happy" = "xyes" && hwloc_probeio_list="$hwloc_probeio_list GL"
|
||||
# if nothing, say "no"
|
||||
test "x$hwloc_probeio_list" = "x" && hwloc_probeio_list=" no"
|
||||
|
||||
# Beginning of generic support
|
||||
cat <<EOF
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
Hwloc optional build support status (more details can be found above):
|
||||
|
||||
Probe / display I/O devices:$hwloc_probeio_list
|
||||
Graphical output (Cairo): $hwloc_cairo_happy
|
||||
XML input / output: $hwloc_xml_status
|
||||
Netloc functionality: $netloc_status (with scotch: $netlocscotch_status)
|
||||
EOF
|
||||
|
||||
# Plugin support
|
||||
hwloc_plugin_summary=$hwloc_have_plugins
|
||||
test "x$hwloc_plugin_components" != "x" && hwloc_plugin_summary="yes ("`echo $hwloc_plugin_components`")" # echo removes the starting space
|
||||
cat <<EOF
|
||||
Plugin support: $hwloc_plugin_summary
|
||||
EOF
|
||||
|
||||
# End of generic support
|
||||
cat <<EOF
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
EOF
|
161
opal/mca/hwloc/hwloc2x/hwloc/contrib/hwloc-valgrind.supp
Обычный файл
161
opal/mca/hwloc/hwloc2x/hwloc/contrib/hwloc-valgrind.supp
Обычный файл
@ -0,0 +1,161 @@
|
||||
# Copyright © 2012-2015 Inria. All rights reserved.
|
||||
# See COPYING in top-level directory.
|
||||
|
||||
# suppressions file to be passed to valgrind with
|
||||
# --suppressions=/path/to/hwloc-valgrind.supp
|
||||
|
||||
# zlib (brought by libpci or libxml2) doesn't cleanup its global state
|
||||
{
|
||||
inflate_init
|
||||
Memcheck:Cond
|
||||
fun:inflateReset2
|
||||
fun:inflateInit2_
|
||||
}
|
||||
|
||||
# hwloc cannot free the global parser (with xmlCleanupParser()) because other threads may be using it
|
||||
{
|
||||
xml_init_parser
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:xmlInitParser
|
||||
}
|
||||
|
||||
# hwloc cannot free the global xml dict RMutex because it cannot call xmlCleanupParser() as explained above
|
||||
{
|
||||
xml_dict_create_new_rmutex
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
fun:xmlNewRMutex
|
||||
...
|
||||
fun:xmlDictCreate
|
||||
}
|
||||
|
||||
# ltdl dlopen global state?
|
||||
{
|
||||
ltdl_dlopen_doit_leak
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:dl_open_worker
|
||||
fun:_dl_catch_error
|
||||
fun:_dl_open
|
||||
fun:dlopen_doit
|
||||
}
|
||||
|
||||
# ltdl_dlclose_leak
|
||||
{
|
||||
ltdl_dlclose_leak
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:_dl_close_worker
|
||||
fun:_dl_close
|
||||
...
|
||||
fun:dlclose
|
||||
}
|
||||
|
||||
# lt_dlforeachfile abusing paths
|
||||
{
|
||||
lt_dlforeachfile_addr8
|
||||
Memcheck:Addr8
|
||||
fun:_wordcopy_fwd_dest_aligned
|
||||
fun:__GI_memmove
|
||||
fun:argz_insert
|
||||
...
|
||||
fun:lt_dlforeachfile
|
||||
}
|
||||
|
||||
# cuda
|
||||
{
|
||||
cuda_leak
|
||||
Memcheck:Leak
|
||||
...
|
||||
obj:*libcuda*
|
||||
}
|
||||
|
||||
# nvml
|
||||
{
|
||||
nvmlInit_cond
|
||||
Memcheck:Cond
|
||||
...
|
||||
obj:*nvidia-ml*
|
||||
...
|
||||
fun:nvmlInit
|
||||
}
|
||||
|
||||
# amd opencl
|
||||
{
|
||||
atical_leak
|
||||
Memcheck:Leak
|
||||
...
|
||||
obj:*libatical*
|
||||
}
|
||||
{
|
||||
atical_cond
|
||||
Memcheck:Cond
|
||||
...
|
||||
obj:*libatical*
|
||||
}
|
||||
{
|
||||
amdocl_leak
|
||||
Memcheck:Leak
|
||||
...
|
||||
obj:*libamdocl*
|
||||
}
|
||||
{
|
||||
amdocl_param
|
||||
Memcheck:Param
|
||||
write(buf)
|
||||
fun:*write*
|
||||
obj:*libamdocl*
|
||||
}
|
||||
{
|
||||
opencl_leak
|
||||
Memcheck:Leak
|
||||
...
|
||||
obj:*libOpenCL*
|
||||
...
|
||||
fun:clGetPlatformIDs
|
||||
}
|
||||
{
|
||||
libatiadl_xcb_leak
|
||||
Memcheck:Leak
|
||||
...
|
||||
obj:*libxcb*
|
||||
...
|
||||
fun:XOpenDisplay
|
||||
...
|
||||
obj:*libatiadl*
|
||||
}
|
||||
|
||||
#
|
||||
{
|
||||
libpciaccess_device_name_leak
|
||||
Memcheck:Leak
|
||||
...
|
||||
fun:pci_device_get_device_name
|
||||
fun:hwloc_look_libpci
|
||||
}
|
||||
{
|
||||
libpciaccess_leak
|
||||
Memcheck:Leak
|
||||
...
|
||||
obj:*libpciaccess*
|
||||
...
|
||||
fun:hwloc_look_libpci
|
||||
}
|
||||
|
||||
# libudev global hashes
|
||||
{
|
||||
libudev_hashmap_property
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:udev_device_get_property_value
|
||||
}
|
||||
{
|
||||
libudev_hashmap_sysname
|
||||
Memcheck:Leak
|
||||
fun:malloc
|
||||
...
|
||||
fun:udev_device_new_from_subsystem_sysname
|
||||
}
|
||||
|
2
opal/mca/hwloc/hwloc2x/hwloc/contrib/misc/Makefile.am
Обычный файл
2
opal/mca/hwloc/hwloc2x/hwloc/contrib/misc/Makefile.am
Обычный файл
@ -0,0 +1,2 @@
|
||||
# This is a dummy file that is not needed in embedded mode,
|
||||
# but sadly, automake *requires* it
|
2
opal/mca/hwloc/hwloc2x/hwloc/contrib/systemd/Makefile.am
Обычный файл
2
opal/mca/hwloc/hwloc2x/hwloc/contrib/systemd/Makefile.am
Обычный файл
@ -0,0 +1,2 @@
|
||||
# This is a dummy file that is not needed in embedded mode,
|
||||
# but sadly, automake *requires* it
|
2
opal/mca/hwloc/hwloc2x/hwloc/doc/Makefile.am
Обычный файл
2
opal/mca/hwloc/hwloc2x/hwloc/doc/Makefile.am
Обычный файл
@ -0,0 +1,2 @@
|
||||
# This is a dummy file that is not needed in embedded mode,
|
||||
# but sadly, automake *requires* it
|
2
opal/mca/hwloc/hwloc2x/hwloc/doc/doxygen-config.cfg.in
Обычный файл
2
opal/mca/hwloc/hwloc2x/hwloc/doc/doxygen-config.cfg.in
Обычный файл
@ -0,0 +1,2 @@
|
||||
# This is a dummy file that is not needed in embedded mode,
|
||||
# but sadly, automake *requires* it
|
2
opal/mca/hwloc/hwloc2x/hwloc/doc/examples/Makefile.am
Обычный файл
2
opal/mca/hwloc/hwloc2x/hwloc/doc/examples/Makefile.am
Обычный файл
@ -0,0 +1,2 @@
|
||||
# This is a dummy file that is not needed in embedded mode,
|
||||
# but sadly, automake *requires* it
|
12
opal/mca/hwloc/hwloc2x/hwloc/hwloc.pc.in
Обычный файл
12
opal/mca/hwloc/hwloc2x/hwloc/hwloc.pc.in
Обычный файл
@ -0,0 +1,12 @@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: hwloc
|
||||
Description: Hardware locality detection and management library
|
||||
Version: @HWLOC_VERSION@
|
||||
Requires.private: @HWLOC_REQUIRES@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -lhwloc
|
||||
Libs.private: @HWLOC_LIBS@ @HWLOC_LIBS_PRIVATE@
|
230
opal/mca/hwloc/hwloc2x/hwloc/hwloc/Makefile.am
Обычный файл
230
opal/mca/hwloc/hwloc2x/hwloc/hwloc/Makefile.am
Обычный файл
@ -0,0 +1,230 @@
|
||||
# Copyright © 2009-2016 Inria. All rights reserved.
|
||||
# Copyright © 2009-2012 Université Bordeaux
|
||||
# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved.
|
||||
# Copyright © 2011-2012 Oracle and/or its affiliates. All rights reserved.
|
||||
# See COPYING in top-level directory.
|
||||
|
||||
AM_CFLAGS = $(HWLOC_CFLAGS)
|
||||
AM_CPPFLAGS = $(HWLOC_CPPFLAGS) -DHWLOC_INSIDE_LIBHWLOC
|
||||
AM_LDFLAGS = $(HWLOC_LDFLAGS)
|
||||
|
||||
EXTRA_DIST = dolib.c
|
||||
|
||||
# If we're in standalone mode, build the installable library.
|
||||
# Otherwise, build the embedded library.
|
||||
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
lib_LTLIBRARIES = libhwloc.la
|
||||
else
|
||||
noinst_LTLIBRARIES = libhwloc_embedded.la
|
||||
endif
|
||||
|
||||
pluginsdir = @HWLOC_PLUGINS_DIR@
|
||||
plugins_LTLIBRARIES =
|
||||
plugins_ldflags = -module -avoid-version -lltdl
|
||||
# Beware that files are not rebuilt automatically when reconfiguring with different paths in these flags.
|
||||
AM_CPPFLAGS += -DHWLOC_PLUGINS_PATH=\"$(HWLOC_PLUGINS_PATH)\" -DRUNSTATEDIR=\"$(HWLOC_runstatedir)\"
|
||||
|
||||
# Sources and ldflags
|
||||
|
||||
sources = \
|
||||
topology.c \
|
||||
traversal.c \
|
||||
distances.c \
|
||||
components.c \
|
||||
bind.c \
|
||||
bitmap.c \
|
||||
pci-common.c \
|
||||
diff.c \
|
||||
misc.c \
|
||||
base64.c \
|
||||
topology-noos.c \
|
||||
topology-synthetic.c \
|
||||
topology-xml.c \
|
||||
topology-xml-nolibxml.c
|
||||
ldflags =
|
||||
|
||||
# Conditionally add to the sources and ldflags
|
||||
|
||||
if HWLOC_HAVE_LIBXML2
|
||||
if HWLOC_XML_LIBXML_BUILD_STATIC
|
||||
sources += topology-xml-libxml.c
|
||||
else
|
||||
plugins_LTLIBRARIES += hwloc_xml_libxml.la
|
||||
hwloc_xml_libxml_la_SOURCES = topology-xml-libxml.c
|
||||
hwloc_xml_libxml_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_LIBXML2_CFLAGS) -DHWLOC_INSIDE_PLUGIN
|
||||
hwloc_xml_libxml_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_LIBXML2_LIBS)
|
||||
endif
|
||||
endif HWLOC_HAVE_LIBXML2
|
||||
|
||||
if HWLOC_HAVE_PCIACCESS
|
||||
if HWLOC_PCI_BUILD_STATIC
|
||||
sources += topology-pci.c
|
||||
else
|
||||
plugins_LTLIBRARIES += hwloc_pci.la
|
||||
hwloc_pci_la_SOURCES = topology-pci.c
|
||||
hwloc_pci_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_PCIACCESS_CFLAGS) -DHWLOC_INSIDE_PLUGIN
|
||||
hwloc_pci_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_PCIACCESS_LIBS)
|
||||
endif
|
||||
endif HWLOC_HAVE_PCIACCESS
|
||||
|
||||
if HWLOC_HAVE_OPENCL
|
||||
if HWLOC_OPENCL_BUILD_STATIC
|
||||
sources += topology-opencl.c
|
||||
else
|
||||
plugins_LTLIBRARIES += hwloc_opencl.la
|
||||
hwloc_opencl_la_SOURCES = topology-opencl.c
|
||||
hwloc_opencl_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_OPENCL_CFLAGS) -DHWLOC_INSIDE_PLUGIN
|
||||
hwloc_opencl_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_OPENCL_LIBS)
|
||||
endif
|
||||
endif HWLOC_HAVE_OPENCL
|
||||
|
||||
if HWLOC_HAVE_CUDART
|
||||
if HWLOC_CUDA_BUILD_STATIC
|
||||
sources += topology-cuda.c
|
||||
else
|
||||
plugins_LTLIBRARIES += hwloc_cuda.la
|
||||
hwloc_cuda_la_SOURCES = topology-cuda.c
|
||||
hwloc_cuda_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_CUDA_CFLAGS) -DHWLOC_INSIDE_PLUGIN
|
||||
hwloc_cuda_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_CUDA_LIBS)
|
||||
endif
|
||||
endif HWLOC_HAVE_CUDART
|
||||
|
||||
if HWLOC_HAVE_NVML
|
||||
if HWLOC_NVML_BUILD_STATIC
|
||||
sources += topology-nvml.c
|
||||
else
|
||||
plugins_LTLIBRARIES += hwloc_nvml.la
|
||||
hwloc_nvml_la_SOURCES = topology-nvml.c
|
||||
hwloc_nvml_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_NVML_CFLAGS) -DHWLOC_INSIDE_PLUGIN
|
||||
hwloc_nvml_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_NVML_LIBS)
|
||||
endif
|
||||
endif HWLOC_HAVE_NVML
|
||||
|
||||
if HWLOC_HAVE_GL
|
||||
if HWLOC_GL_BUILD_STATIC
|
||||
sources += topology-gl.c
|
||||
else
|
||||
plugins_LTLIBRARIES += hwloc_gl.la
|
||||
hwloc_gl_la_SOURCES = topology-gl.c
|
||||
hwloc_gl_la_CFLAGS = $(AM_CFLAGS) $(HWLOC_GL_CFLAGS) -DHWLOC_INSIDE_PLUGIN
|
||||
hwloc_gl_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_GL_LIBS)
|
||||
endif
|
||||
endif HWLOC_HAVE_GL
|
||||
|
||||
if HWLOC_HAVE_SOLARIS
|
||||
sources += topology-solaris.c
|
||||
sources += topology-solaris-chiptype.c
|
||||
endif HWLOC_HAVE_SOLARIS
|
||||
|
||||
if HWLOC_HAVE_LINUX
|
||||
sources += topology-linux.c topology-hardwired.c
|
||||
endif HWLOC_HAVE_LINUX
|
||||
|
||||
if HWLOC_HAVE_BGQ
|
||||
sources += topology-bgq.c
|
||||
endif HWLOC_HAVE_BGQ
|
||||
|
||||
if HWLOC_HAVE_AIX
|
||||
sources += topology-aix.c
|
||||
ldflags += -lpthread
|
||||
endif HWLOC_HAVE_AIX
|
||||
|
||||
if HWLOC_HAVE_HPUX
|
||||
sources += topology-hpux.c
|
||||
ldflags += -lpthread
|
||||
endif HWLOC_HAVE_HPUX
|
||||
|
||||
if HWLOC_HAVE_WINDOWS
|
||||
sources += topology-windows.c
|
||||
endif HWLOC_HAVE_WINDOWS
|
||||
|
||||
if HWLOC_HAVE_DARWIN
|
||||
sources += topology-darwin.c
|
||||
endif HWLOC_HAVE_DARWIN
|
||||
|
||||
if HWLOC_HAVE_FREEBSD
|
||||
sources += topology-freebsd.c
|
||||
endif HWLOC_HAVE_FREEBSD
|
||||
|
||||
if HWLOC_HAVE_NETBSD
|
||||
sources += topology-netbsd.c
|
||||
ldflags += -lpthread
|
||||
endif HWLOC_HAVE_NETBSD
|
||||
|
||||
if HWLOC_HAVE_X86_CPUID
|
||||
sources += topology-x86.c
|
||||
endif HWLOC_HAVE_X86_CPUID
|
||||
|
||||
if HWLOC_HAVE_GCC
|
||||
ldflags += -no-undefined
|
||||
endif HWLOC_HAVE_GCC
|
||||
|
||||
|
||||
if HWLOC_HAVE_WINDOWS
|
||||
# Windows specific rules
|
||||
|
||||
LC_MESSAGES=C
|
||||
export LC_MESSAGES
|
||||
ldflags += -Xlinker --output-def -Xlinker .libs/libhwloc.def
|
||||
|
||||
if HWLOC_HAVE_MS_LIB
|
||||
dolib$(EXEEXT): dolib.c
|
||||
$(CC_FOR_BUILD) $< -o $@
|
||||
.libs/libhwloc.lib: libhwloc.la dolib$(EXEEXT)
|
||||
[ ! -r .libs/libhwloc.def ] || ./dolib$(EXEEXT) "$(HWLOC_MS_LIB)" $(HWLOC_MS_LIB_ARCH) .libs/libhwloc.def $(libhwloc_so_version) .libs/libhwloc.lib
|
||||
all-local: .libs/libhwloc.lib
|
||||
clean-local:
|
||||
$(RM) dolib$(EXEEXT)
|
||||
endif HWLOC_HAVE_MS_LIB
|
||||
|
||||
install-exec-hook:
|
||||
[ ! -r .libs/libhwloc.def ] || $(INSTALL) .libs/libhwloc.def $(DESTDIR)$(libdir)
|
||||
if HWLOC_HAVE_MS_LIB
|
||||
[ ! -r .libs/libhwloc.def ] || $(INSTALL) .libs/libhwloc.lib $(DESTDIR)$(libdir)
|
||||
[ ! -r .libs/libhwloc.def ] || $(INSTALL) .libs/libhwloc.exp $(DESTDIR)$(libdir)
|
||||
endif HWLOC_HAVE_MS_LIB
|
||||
|
||||
uninstall-local:
|
||||
rm -f $(DESTDIR)$(libdir)/libhwloc.def
|
||||
if HWLOC_HAVE_MS_LIB
|
||||
rm -f $(DESTDIR)$(libdir)/libhwloc.lib $(DESTDIR)$(libdir)/libhwloc.exp
|
||||
endif HWLOC_HAVE_MS_LIB
|
||||
|
||||
# End of Windows specific rules
|
||||
endif HWLOC_HAVE_WINDOWS
|
||||
|
||||
|
||||
# Installable library
|
||||
|
||||
libhwloc_la_SOURCES = $(sources)
|
||||
libhwloc_la_LDFLAGS = $(ldflags) -version-info $(libhwloc_so_version) $(HWLOC_LIBS)
|
||||
|
||||
if HWLOC_HAVE_PLUGINS
|
||||
AM_CPPFLAGS += $(LTDLINCL)
|
||||
libhwloc_la_LDFLAGS += -export-dynamic
|
||||
libhwloc_la_LIBADD = $(LIBLTDL)
|
||||
endif
|
||||
|
||||
# Embedded library (note the lack of a .so version number -- that
|
||||
# intentionally only appears in the installable library). Also note
|
||||
# the lack of _LDFLAGS -- all libs are added by the upper layer (via
|
||||
# HWLOC_EMBEDDED_LIBS).
|
||||
|
||||
libhwloc_embedded_la_SOURCES = $(sources)
|
||||
|
||||
# XML data (only install if we're building in standalone mode)
|
||||
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
xml_DATA = $(srcdir)/hwloc.dtd
|
||||
xmldir = $(pkgdatadir)
|
||||
EXTRA_DIST += hwloc.dtd
|
||||
endif
|
||||
|
||||
DISTCLEANFILES = static-components.h
|
||||
|
||||
if HWLOC_HAVE_PLUGINS
|
||||
check_LTLIBRARIES = hwloc_fake.la
|
||||
hwloc_fake_la_SOURCES = topology-fake.c
|
||||
hwloc_fake_la_LDFLAGS = $(plugins_ldflags) -rpath /nowhere # force libtool to build a shared-library even it's check-only
|
||||
endif
|
306
opal/mca/hwloc/hwloc2x/hwloc/hwloc/base64.c
Обычный файл
306
opal/mca/hwloc/hwloc2x/hwloc/hwloc/base64.c
Обычный файл
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright © 2012 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*
|
||||
* Modifications after import:
|
||||
* - removed all #if
|
||||
* - updated prototypes
|
||||
* - updated #include
|
||||
*/
|
||||
|
||||
/* $OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 by Internet Software Consortium.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||||
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||||
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Portions Copyright (c) 1995 by International Business Machines, Inc.
|
||||
*
|
||||
* International Business Machines, Inc. (hereinafter called IBM) grants
|
||||
* permission under its copyrights to use, copy, modify, and distribute this
|
||||
* Software with or without fee, provided that the above copyright notice and
|
||||
* all paragraphs of this notice appear in all copies, and that the name of IBM
|
||||
* not be used in connection with the marketing of any product incorporating
|
||||
* the Software or modifications thereof, without specific, written prior
|
||||
* permission.
|
||||
*
|
||||
* To the extent it has a right to do so, IBM grants an immunity from suit
|
||||
* under its patents, if any, for the use, sale or manufacture of products to
|
||||
* the extent that such products are used for performing Domain Name System
|
||||
* dynamic updates in TCP/IP networks by means of the Software. No immunity is
|
||||
* granted for any product per se or for any other function of any product.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
|
||||
* DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
|
||||
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*/
|
||||
|
||||
/* OPENBSD ORIGINAL: lib/libc/net/base64.c */
|
||||
|
||||
static const char Base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
static const char Pad64 = '=';
|
||||
|
||||
/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
|
||||
The following encoding technique is taken from RFC 1521 by Borenstein
|
||||
and Freed. It is reproduced here in a slightly edited form for
|
||||
convenience.
|
||||
|
||||
A 65-character subset of US-ASCII is used, enabling 6 bits to be
|
||||
represented per printable character. (The extra 65th character, "=",
|
||||
is used to signify a special processing function.)
|
||||
|
||||
The encoding process represents 24-bit groups of input bits as output
|
||||
strings of 4 encoded characters. Proceeding from left to right, a
|
||||
24-bit input group is formed by concatenating 3 8-bit input groups.
|
||||
These 24 bits are then treated as 4 concatenated 6-bit groups, each
|
||||
of which is translated into a single digit in the base64 alphabet.
|
||||
|
||||
Each 6-bit group is used as an index into an array of 64 printable
|
||||
characters. The character referenced by the index is placed in the
|
||||
output string.
|
||||
|
||||
Table 1: The Base64 Alphabet
|
||||
|
||||
Value Encoding Value Encoding Value Encoding Value Encoding
|
||||
0 A 17 R 34 i 51 z
|
||||
1 B 18 S 35 j 52 0
|
||||
2 C 19 T 36 k 53 1
|
||||
3 D 20 U 37 l 54 2
|
||||
4 E 21 V 38 m 55 3
|
||||
5 F 22 W 39 n 56 4
|
||||
6 G 23 X 40 o 57 5
|
||||
7 H 24 Y 41 p 58 6
|
||||
8 I 25 Z 42 q 59 7
|
||||
9 J 26 a 43 r 60 8
|
||||
10 K 27 b 44 s 61 9
|
||||
11 L 28 c 45 t 62 +
|
||||
12 M 29 d 46 u 63 /
|
||||
13 N 30 e 47 v
|
||||
14 O 31 f 48 w (pad) =
|
||||
15 P 32 g 49 x
|
||||
16 Q 33 h 50 y
|
||||
|
||||
Special processing is performed if fewer than 24 bits are available
|
||||
at the end of the data being encoded. A full encoding quantum is
|
||||
always completed at the end of a quantity. When fewer than 24 input
|
||||
bits are available in an input group, zero bits are added (on the
|
||||
right) to form an integral number of 6-bit groups. Padding at the
|
||||
end of the data is performed using the '=' character.
|
||||
|
||||
Since all base64 input is an integral number of octets, only the
|
||||
-------------------------------------------------
|
||||
following cases can arise:
|
||||
|
||||
(1) the final quantum of encoding input is an integral
|
||||
multiple of 24 bits; here, the final unit of encoded
|
||||
output will be an integral multiple of 4 characters
|
||||
with no "=" padding,
|
||||
(2) the final quantum of encoding input is exactly 8 bits;
|
||||
here, the final unit of encoded output will be two
|
||||
characters followed by two "=" padding characters, or
|
||||
(3) the final quantum of encoding input is exactly 16 bits;
|
||||
here, the final unit of encoded output will be three
|
||||
characters followed by one "=" padding character.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <private/private.h>
|
||||
|
||||
int
|
||||
hwloc_encode_to_base64(const char *src, size_t srclength, char *target, size_t targsize)
|
||||
{
|
||||
size_t datalength = 0;
|
||||
unsigned char input[3];
|
||||
unsigned char output[4];
|
||||
unsigned int i;
|
||||
|
||||
while (2 < srclength) {
|
||||
input[0] = *src++;
|
||||
input[1] = *src++;
|
||||
input[2] = *src++;
|
||||
srclength -= 3;
|
||||
|
||||
output[0] = input[0] >> 2;
|
||||
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
|
||||
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
|
||||
output[3] = input[2] & 0x3f;
|
||||
|
||||
if (datalength + 4 > targsize)
|
||||
return (-1);
|
||||
target[datalength++] = Base64[output[0]];
|
||||
target[datalength++] = Base64[output[1]];
|
||||
target[datalength++] = Base64[output[2]];
|
||||
target[datalength++] = Base64[output[3]];
|
||||
}
|
||||
|
||||
/* Now we worry about padding. */
|
||||
if (0 != srclength) {
|
||||
/* Get what's left. */
|
||||
input[0] = input[1] = input[2] = '\0';
|
||||
for (i = 0; i < srclength; i++)
|
||||
input[i] = *src++;
|
||||
|
||||
output[0] = input[0] >> 2;
|
||||
output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
|
||||
output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
|
||||
|
||||
if (datalength + 4 > targsize)
|
||||
return (-1);
|
||||
target[datalength++] = Base64[output[0]];
|
||||
target[datalength++] = Base64[output[1]];
|
||||
if (srclength == 1)
|
||||
target[datalength++] = Pad64;
|
||||
else
|
||||
target[datalength++] = Base64[output[2]];
|
||||
target[datalength++] = Pad64;
|
||||
}
|
||||
if (datalength >= targsize)
|
||||
return (-1);
|
||||
target[datalength] = '\0'; /* Returned value doesn't count \0. */
|
||||
return (int)(datalength);
|
||||
}
|
||||
|
||||
/* skips all whitespace anywhere.
|
||||
converts characters, four at a time, starting at (or after)
|
||||
src from base - 64 numbers into three 8 bit bytes in the target area.
|
||||
it returns the number of data bytes stored at the target, or -1 on error.
|
||||
*/
|
||||
|
||||
int
|
||||
hwloc_decode_from_base64(char const *src, char *target, size_t targsize)
|
||||
{
|
||||
unsigned int tarindex, state;
|
||||
int ch;
|
||||
char *pos;
|
||||
|
||||
state = 0;
|
||||
tarindex = 0;
|
||||
|
||||
while ((ch = *src++) != '\0') {
|
||||
if (isspace(ch)) /* Skip whitespace anywhere. */
|
||||
continue;
|
||||
|
||||
if (ch == Pad64)
|
||||
break;
|
||||
|
||||
pos = strchr(Base64, ch);
|
||||
if (pos == 0) /* A non-base64 character. */
|
||||
return (-1);
|
||||
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (target) {
|
||||
if (tarindex >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] = (char)(pos - Base64) << 2;
|
||||
}
|
||||
state = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (target) {
|
||||
if (tarindex + 1 >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64) >> 4;
|
||||
target[tarindex+1] = ((pos - Base64) & 0x0f)
|
||||
<< 4 ;
|
||||
}
|
||||
tarindex++;
|
||||
state = 2;
|
||||
break;
|
||||
case 2:
|
||||
if (target) {
|
||||
if (tarindex + 1 >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64) >> 2;
|
||||
target[tarindex+1] = ((pos - Base64) & 0x03)
|
||||
<< 6;
|
||||
}
|
||||
tarindex++;
|
||||
state = 3;
|
||||
break;
|
||||
case 3:
|
||||
if (target) {
|
||||
if (tarindex >= targsize)
|
||||
return (-1);
|
||||
target[tarindex] |= (pos - Base64);
|
||||
}
|
||||
tarindex++;
|
||||
state = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We are done decoding Base-64 chars. Let's see if we ended
|
||||
* on a byte boundary, and/or with erroneous trailing characters.
|
||||
*/
|
||||
|
||||
if (ch == Pad64) { /* We got a pad char. */
|
||||
ch = *src++; /* Skip it, get next. */
|
||||
switch (state) {
|
||||
case 0: /* Invalid = in first position */
|
||||
case 1: /* Invalid = in second position */
|
||||
return (-1);
|
||||
|
||||
case 2: /* Valid, means one byte of info */
|
||||
/* Skip any number of spaces. */
|
||||
for (; ch != '\0'; ch = *src++)
|
||||
if (!isspace(ch))
|
||||
break;
|
||||
/* Make sure there is another trailing = sign. */
|
||||
if (ch != Pad64)
|
||||
return (-1);
|
||||
ch = *src++; /* Skip the = */
|
||||
/* Fall through to "single trailing =" case. */
|
||||
/* FALLTHROUGH */
|
||||
|
||||
case 3: /* Valid, means two bytes of info */
|
||||
/*
|
||||
* We know this char is an =. Is there anything but
|
||||
* whitespace after it?
|
||||
*/
|
||||
for (; ch != '\0'; ch = *src++)
|
||||
if (!isspace(ch))
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Now make sure for cases 2 and 3 that the "extra"
|
||||
* bits that slopped past the last full byte were
|
||||
* zeros. If we don't check them, they become a
|
||||
* subliminal channel.
|
||||
*/
|
||||
if (target && target[tarindex] != 0)
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We ended by seeing the end of the string. Make sure we
|
||||
* have no partial bytes lying around.
|
||||
*/
|
||||
if (state != 0)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (tarindex);
|
||||
}
|
951
opal/mca/hwloc/hwloc2x/hwloc/hwloc/bind.c
Обычный файл
951
opal/mca/hwloc/hwloc2x/hwloc/hwloc/bind.c
Обычный файл
@ -0,0 +1,951 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010, 2012 Université Bordeaux
|
||||
* Copyright © 2011-2015 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <hwloc/helper.h>
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
/* <malloc.h> is only needed if we don't have posix_memalign() */
|
||||
#if defined(hwloc_getpagesize) && !defined(HAVE_POSIX_MEMALIGN) && defined(HAVE_MEMALIGN) && defined(HAVE_MALLOC_H)
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* TODO: HWLOC_GNU_SYS,
|
||||
*
|
||||
* We could use glibc's sched_setaffinity generically when it is available
|
||||
*
|
||||
* Darwin and OpenBSD don't seem to have binding facilities.
|
||||
*/
|
||||
|
||||
#define HWLOC_CPUBIND_ALLFLAGS (HWLOC_CPUBIND_PROCESS|HWLOC_CPUBIND_THREAD|HWLOC_CPUBIND_STRICT|HWLOC_CPUBIND_NOMEMBIND)
|
||||
|
||||
static hwloc_const_bitmap_t
|
||||
hwloc_fix_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t set)
|
||||
{
|
||||
hwloc_const_bitmap_t topology_set = hwloc_topology_get_topology_cpuset(topology);
|
||||
hwloc_const_bitmap_t complete_set = hwloc_topology_get_complete_cpuset(topology);
|
||||
|
||||
if (!topology_set) {
|
||||
/* The topology is composed of several systems, the cpuset is ambiguous. */
|
||||
errno = EXDEV;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hwloc_bitmap_iszero(set)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!hwloc_bitmap_isincluded(set, complete_set)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hwloc_bitmap_isincluded(topology_set, set))
|
||||
set = complete_set;
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_set_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t set, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
set = hwloc_fix_cpubind(topology, set);
|
||||
if (!set)
|
||||
return -1;
|
||||
|
||||
if (flags & HWLOC_CPUBIND_PROCESS) {
|
||||
if (topology->binding_hooks.set_thisproc_cpubind)
|
||||
return topology->binding_hooks.set_thisproc_cpubind(topology, set, flags);
|
||||
} else if (flags & HWLOC_CPUBIND_THREAD) {
|
||||
if (topology->binding_hooks.set_thisthread_cpubind)
|
||||
return topology->binding_hooks.set_thisthread_cpubind(topology, set, flags);
|
||||
} else {
|
||||
if (topology->binding_hooks.set_thisproc_cpubind) {
|
||||
int err = topology->binding_hooks.set_thisproc_cpubind(topology, set, flags);
|
||||
if (err >= 0 || errno != ENOSYS)
|
||||
return err;
|
||||
/* ENOSYS, fallback */
|
||||
}
|
||||
if (topology->binding_hooks.set_thisthread_cpubind)
|
||||
return topology->binding_hooks.set_thisthread_cpubind(topology, set, flags);
|
||||
}
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_get_cpubind(hwloc_topology_t topology, hwloc_bitmap_t set, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & HWLOC_CPUBIND_PROCESS) {
|
||||
if (topology->binding_hooks.get_thisproc_cpubind)
|
||||
return topology->binding_hooks.get_thisproc_cpubind(topology, set, flags);
|
||||
} else if (flags & HWLOC_CPUBIND_THREAD) {
|
||||
if (topology->binding_hooks.get_thisthread_cpubind)
|
||||
return topology->binding_hooks.get_thisthread_cpubind(topology, set, flags);
|
||||
} else {
|
||||
if (topology->binding_hooks.get_thisproc_cpubind) {
|
||||
int err = topology->binding_hooks.get_thisproc_cpubind(topology, set, flags);
|
||||
if (err >= 0 || errno != ENOSYS)
|
||||
return err;
|
||||
/* ENOSYS, fallback */
|
||||
}
|
||||
if (topology->binding_hooks.get_thisthread_cpubind)
|
||||
return topology->binding_hooks.get_thisthread_cpubind(topology, set, flags);
|
||||
}
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t set, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
set = hwloc_fix_cpubind(topology, set);
|
||||
if (!set)
|
||||
return -1;
|
||||
|
||||
if (topology->binding_hooks.set_proc_cpubind)
|
||||
return topology->binding_hooks.set_proc_cpubind(topology, pid, set, flags);
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t set, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (topology->binding_hooks.get_proc_cpubind)
|
||||
return topology->binding_hooks.get_proc_cpubind(topology, pid, set, flags);
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef hwloc_thread_t
|
||||
int
|
||||
hwloc_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_const_bitmap_t set, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
set = hwloc_fix_cpubind(topology, set);
|
||||
if (!set)
|
||||
return -1;
|
||||
|
||||
if (topology->binding_hooks.set_thread_cpubind)
|
||||
return topology->binding_hooks.set_thread_cpubind(topology, tid, set, flags);
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_get_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_bitmap_t set, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (topology->binding_hooks.get_thread_cpubind)
|
||||
return topology->binding_hooks.get_thread_cpubind(topology, tid, set, flags);
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
hwloc_get_last_cpu_location(hwloc_topology_t topology, hwloc_bitmap_t set, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & HWLOC_CPUBIND_PROCESS) {
|
||||
if (topology->binding_hooks.get_thisproc_last_cpu_location)
|
||||
return topology->binding_hooks.get_thisproc_last_cpu_location(topology, set, flags);
|
||||
} else if (flags & HWLOC_CPUBIND_THREAD) {
|
||||
if (topology->binding_hooks.get_thisthread_last_cpu_location)
|
||||
return topology->binding_hooks.get_thisthread_last_cpu_location(topology, set, flags);
|
||||
} else {
|
||||
if (topology->binding_hooks.get_thisproc_last_cpu_location) {
|
||||
int err = topology->binding_hooks.get_thisproc_last_cpu_location(topology, set, flags);
|
||||
if (err >= 0 || errno != ENOSYS)
|
||||
return err;
|
||||
/* ENOSYS, fallback */
|
||||
}
|
||||
if (topology->binding_hooks.get_thisthread_last_cpu_location)
|
||||
return topology->binding_hooks.get_thisthread_last_cpu_location(topology, set, flags);
|
||||
}
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_get_proc_last_cpu_location(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t set, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (topology->binding_hooks.get_proc_last_cpu_location)
|
||||
return topology->binding_hooks.get_proc_last_cpu_location(topology, pid, set, flags);
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define HWLOC_MEMBIND_ALLFLAGS (HWLOC_MEMBIND_PROCESS|HWLOC_MEMBIND_THREAD|HWLOC_MEMBIND_STRICT|HWLOC_MEMBIND_MIGRATE|HWLOC_MEMBIND_NOCPUBIND|HWLOC_MEMBIND_BYNODESET)
|
||||
|
||||
static hwloc_const_nodeset_t
|
||||
hwloc_fix_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset)
|
||||
{
|
||||
hwloc_const_bitmap_t topology_nodeset = hwloc_topology_get_topology_nodeset(topology);
|
||||
hwloc_const_bitmap_t complete_nodeset = hwloc_topology_get_complete_nodeset(topology);
|
||||
|
||||
if (!hwloc_topology_get_topology_cpuset(topology)) {
|
||||
/* The topology is composed of several systems, the nodeset is thus
|
||||
* ambiguous. */
|
||||
errno = EXDEV;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!complete_nodeset) {
|
||||
/* There is no NUMA node */
|
||||
errno = ENODEV;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hwloc_bitmap_iszero(nodeset)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!hwloc_bitmap_isincluded(nodeset, complete_nodeset)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (hwloc_bitmap_isincluded(topology_nodeset, nodeset))
|
||||
return complete_nodeset;
|
||||
|
||||
return nodeset;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_fix_membind_cpuset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_const_cpuset_t cpuset)
|
||||
{
|
||||
hwloc_const_bitmap_t topology_set = hwloc_topology_get_topology_cpuset(topology);
|
||||
hwloc_const_bitmap_t complete_set = hwloc_topology_get_complete_cpuset(topology);
|
||||
hwloc_const_bitmap_t complete_nodeset = hwloc_topology_get_complete_nodeset(topology);
|
||||
|
||||
if (!topology_set) {
|
||||
/* The topology is composed of several systems, the cpuset is thus
|
||||
* ambiguous. */
|
||||
errno = EXDEV;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!complete_nodeset) {
|
||||
/* There is no NUMA node */
|
||||
errno = ENODEV;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hwloc_bitmap_iszero(cpuset)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!hwloc_bitmap_isincluded(cpuset, complete_set)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hwloc_bitmap_isincluded(topology_set, cpuset)) {
|
||||
hwloc_bitmap_copy(nodeset, complete_nodeset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
hwloc_cpuset_to_nodeset(topology, cpuset, nodeset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_set_membind_by_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nodeset = hwloc_fix_membind(topology, nodeset);
|
||||
if (!nodeset)
|
||||
return -1;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_PROCESS) {
|
||||
if (topology->binding_hooks.set_thisproc_membind)
|
||||
return topology->binding_hooks.set_thisproc_membind(topology, nodeset, policy, flags);
|
||||
} else if (flags & HWLOC_MEMBIND_THREAD) {
|
||||
if (topology->binding_hooks.set_thisthread_membind)
|
||||
return topology->binding_hooks.set_thisthread_membind(topology, nodeset, policy, flags);
|
||||
} else {
|
||||
if (topology->binding_hooks.set_thisproc_membind) {
|
||||
int err = topology->binding_hooks.set_thisproc_membind(topology, nodeset, policy, flags);
|
||||
if (err >= 0 || errno != ENOSYS)
|
||||
return err;
|
||||
/* ENOSYS, fallback */
|
||||
}
|
||||
if (topology->binding_hooks.set_thisthread_membind)
|
||||
return topology->binding_hooks.set_thisthread_membind(topology, nodeset, policy, flags);
|
||||
}
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_set_membind(hwloc_topology_t topology, hwloc_const_bitmap_t set, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_set_membind_by_nodeset(topology, set, policy, flags);
|
||||
} else {
|
||||
hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
|
||||
if (hwloc_fix_membind_cpuset(topology, nodeset, set))
|
||||
ret = -1;
|
||||
else
|
||||
ret = hwloc_set_membind_by_nodeset(topology, nodeset, policy, flags);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_get_membind_by_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & HWLOC_MEMBIND_PROCESS) {
|
||||
if (topology->binding_hooks.get_thisproc_membind)
|
||||
return topology->binding_hooks.get_thisproc_membind(topology, nodeset, policy, flags);
|
||||
} else if (flags & HWLOC_MEMBIND_THREAD) {
|
||||
if (topology->binding_hooks.get_thisthread_membind)
|
||||
return topology->binding_hooks.get_thisthread_membind(topology, nodeset, policy, flags);
|
||||
} else {
|
||||
if (topology->binding_hooks.get_thisproc_membind) {
|
||||
int err = topology->binding_hooks.get_thisproc_membind(topology, nodeset, policy, flags);
|
||||
if (err >= 0 || errno != ENOSYS)
|
||||
return err;
|
||||
/* ENOSYS, fallback */
|
||||
}
|
||||
if (topology->binding_hooks.get_thisthread_membind)
|
||||
return topology->binding_hooks.get_thisthread_membind(topology, nodeset, policy, flags);
|
||||
}
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_get_membind(hwloc_topology_t topology, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_get_membind_by_nodeset(topology, set, policy, flags);
|
||||
} else {
|
||||
hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
|
||||
ret = hwloc_get_membind_by_nodeset(topology, nodeset, policy, flags);
|
||||
if (!ret)
|
||||
hwloc_cpuset_from_nodeset(topology, set, nodeset);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_set_proc_membind_by_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nodeset = hwloc_fix_membind(topology, nodeset);
|
||||
if (!nodeset)
|
||||
return -1;
|
||||
|
||||
if (topology->binding_hooks.set_proc_membind)
|
||||
return topology->binding_hooks.set_proc_membind(topology, pid, nodeset, policy, flags);
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hwloc_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t set, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_set_proc_membind_by_nodeset(topology, pid, set, policy, flags);
|
||||
} else {
|
||||
hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
|
||||
if (hwloc_fix_membind_cpuset(topology, nodeset, set))
|
||||
ret = -1;
|
||||
else
|
||||
ret = hwloc_set_proc_membind_by_nodeset(topology, pid, nodeset, policy, flags);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_get_proc_membind_by_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (topology->binding_hooks.get_proc_membind)
|
||||
return topology->binding_hooks.get_proc_membind(topology, pid, nodeset, policy, flags);
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_get_proc_membind_by_nodeset(topology, pid, set, policy, flags);
|
||||
} else {
|
||||
hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
|
||||
ret = hwloc_get_proc_membind_by_nodeset(topology, pid, nodeset, policy, flags);
|
||||
if (!ret)
|
||||
hwloc_cpuset_from_nodeset(topology, set, nodeset);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_set_area_membind_by_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!len)
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
|
||||
nodeset = hwloc_fix_membind(topology, nodeset);
|
||||
if (!nodeset)
|
||||
return -1;
|
||||
|
||||
if (topology->binding_hooks.set_area_membind)
|
||||
return topology->binding_hooks.set_area_membind(topology, addr, len, nodeset, policy, flags);
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_set_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_bitmap_t set, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_set_area_membind_by_nodeset(topology, addr, len, set, policy, flags);
|
||||
} else {
|
||||
hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
|
||||
if (hwloc_fix_membind_cpuset(topology, nodeset, set))
|
||||
ret = -1;
|
||||
else
|
||||
ret = hwloc_set_area_membind_by_nodeset(topology, addr, len, nodeset, policy, flags);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_get_area_membind_by_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
/* nothing to query */
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (topology->binding_hooks.get_area_membind)
|
||||
return topology->binding_hooks.get_area_membind(topology, addr, len, nodeset, policy, flags);
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_get_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_get_area_membind_by_nodeset(topology, addr, len, set, policy, flags);
|
||||
} else {
|
||||
hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
|
||||
ret = hwloc_get_area_membind_by_nodeset(topology, addr, len, nodeset, policy, flags);
|
||||
if (!ret)
|
||||
hwloc_cpuset_from_nodeset(topology, set, nodeset);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_get_area_memlocation_by_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, int flags)
|
||||
{
|
||||
if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!len)
|
||||
/* nothing to do */
|
||||
return 0;
|
||||
|
||||
if (topology->binding_hooks.get_area_memlocation)
|
||||
return topology->binding_hooks.get_area_memlocation(topology, addr, len, nodeset, flags);
|
||||
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_get_area_memlocation(hwloc_topology_t topology, const void *addr, size_t len, hwloc_cpuset_t set, int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_get_area_memlocation_by_nodeset(topology, addr, len, set, flags);
|
||||
} else {
|
||||
hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
|
||||
ret = hwloc_get_area_memlocation_by_nodeset(topology, addr, len, nodeset, flags);
|
||||
if (!ret)
|
||||
hwloc_cpuset_from_nodeset(topology, set, nodeset);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *
|
||||
hwloc_alloc_heap(hwloc_topology_t topology __hwloc_attribute_unused, size_t len)
|
||||
{
|
||||
void *p = NULL;
|
||||
#if defined(hwloc_getpagesize) && defined(HAVE_POSIX_MEMALIGN)
|
||||
errno = posix_memalign(&p, hwloc_getpagesize(), len);
|
||||
if (errno)
|
||||
p = NULL;
|
||||
#elif defined(hwloc_getpagesize) && defined(HAVE_MEMALIGN)
|
||||
p = memalign(hwloc_getpagesize(), len);
|
||||
#else
|
||||
p = malloc(len);
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
#ifdef MAP_ANONYMOUS
|
||||
void *
|
||||
hwloc_alloc_mmap(hwloc_topology_t topology __hwloc_attribute_unused, size_t len)
|
||||
{
|
||||
void * buffer = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
return buffer == MAP_FAILED ? NULL : buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
hwloc_free_heap(hwloc_topology_t topology __hwloc_attribute_unused, void *addr, size_t len __hwloc_attribute_unused)
|
||||
{
|
||||
free(addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MAP_ANONYMOUS
|
||||
int
|
||||
hwloc_free_mmap(hwloc_topology_t topology __hwloc_attribute_unused, void *addr, size_t len)
|
||||
{
|
||||
if (!addr)
|
||||
return 0;
|
||||
return munmap(addr, len);
|
||||
}
|
||||
#endif
|
||||
|
||||
void *
|
||||
hwloc_alloc(hwloc_topology_t topology, size_t len)
|
||||
{
|
||||
if (topology->binding_hooks.alloc)
|
||||
return topology->binding_hooks.alloc(topology, len);
|
||||
return hwloc_alloc_heap(topology, len);
|
||||
}
|
||||
|
||||
static void *
|
||||
hwloc_alloc_membind_by_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nodeset = hwloc_fix_membind(topology, nodeset);
|
||||
if (!nodeset)
|
||||
goto fallback;
|
||||
if (flags & HWLOC_MEMBIND_MIGRATE) {
|
||||
errno = EINVAL;
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
if (topology->binding_hooks.alloc_membind)
|
||||
return topology->binding_hooks.alloc_membind(topology, len, nodeset, policy, flags);
|
||||
else if (topology->binding_hooks.set_area_membind) {
|
||||
p = hwloc_alloc(topology, len);
|
||||
if (!p)
|
||||
return NULL;
|
||||
if (topology->binding_hooks.set_area_membind(topology, p, len, nodeset, policy, flags) && flags & HWLOC_MEMBIND_STRICT) {
|
||||
int error = errno;
|
||||
free(p);
|
||||
errno = error;
|
||||
return NULL;
|
||||
}
|
||||
return p;
|
||||
} else {
|
||||
errno = ENOSYS;
|
||||
}
|
||||
|
||||
fallback:
|
||||
if (flags & HWLOC_MEMBIND_STRICT)
|
||||
/* Report error */
|
||||
return NULL;
|
||||
/* Never mind, allocate anyway */
|
||||
return hwloc_alloc(topology, len);
|
||||
}
|
||||
|
||||
void *
|
||||
hwloc_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_bitmap_t set, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_alloc_membind_by_nodeset(topology, len, set, policy, flags);
|
||||
} else {
|
||||
hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
|
||||
if (hwloc_fix_membind_cpuset(topology, nodeset, set)) {
|
||||
if (flags & HWLOC_MEMBIND_STRICT)
|
||||
ret = NULL;
|
||||
else
|
||||
ret = hwloc_alloc(topology, len);
|
||||
} else
|
||||
ret = hwloc_alloc_membind_by_nodeset(topology, len, nodeset, policy, flags);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_free(hwloc_topology_t topology, void *addr, size_t len)
|
||||
{
|
||||
if (topology->binding_hooks.free_membind)
|
||||
return topology->binding_hooks.free_membind(topology, addr, len);
|
||||
return hwloc_free_heap(topology, addr, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Empty binding hooks always returning success
|
||||
*/
|
||||
|
||||
static int dontset_return_complete_cpuset(hwloc_topology_t topology, hwloc_cpuset_t set)
|
||||
{
|
||||
hwloc_const_cpuset_t cpuset = hwloc_topology_get_complete_cpuset(topology);
|
||||
if (cpuset) {
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int dontset_thisthread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int dontget_thisthread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return dontset_return_complete_cpuset(topology, set);
|
||||
}
|
||||
static int dontset_thisproc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int dontget_thisproc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return dontset_return_complete_cpuset(topology, set);
|
||||
}
|
||||
static int dontset_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int dontget_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_bitmap_t cpuset, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return dontset_return_complete_cpuset(topology, cpuset);
|
||||
}
|
||||
#ifdef hwloc_thread_t
|
||||
static int dontset_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int dontget_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid __hwloc_attribute_unused, hwloc_bitmap_t cpuset, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return dontset_return_complete_cpuset(topology, cpuset);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dontset_return_complete_nodeset(hwloc_topology_t topology, hwloc_nodeset_t set, hwloc_membind_policy_t *policy)
|
||||
{
|
||||
hwloc_const_nodeset_t nodeset = hwloc_topology_get_complete_nodeset(topology);
|
||||
if (nodeset) {
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_nodeset(topology));
|
||||
*policy = HWLOC_MEMBIND_DEFAULT;
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int dontset_thisproc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int dontget_thisproc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return dontset_return_complete_nodeset(topology, set, policy);
|
||||
}
|
||||
|
||||
static int dontset_thisthread_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int dontget_thisthread_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return dontset_return_complete_nodeset(topology, set, policy);
|
||||
}
|
||||
|
||||
static int dontset_proc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int dontget_proc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return dontset_return_complete_nodeset(topology, set, policy);
|
||||
}
|
||||
|
||||
static int dontset_area_membind(hwloc_topology_t topology __hwloc_attribute_unused, const void *addr __hwloc_attribute_unused, size_t size __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int dontget_area_membind(hwloc_topology_t topology __hwloc_attribute_unused, const void *addr __hwloc_attribute_unused, size_t size __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return dontset_return_complete_nodeset(topology, set, policy);
|
||||
}
|
||||
static int dontget_area_memlocation(hwloc_topology_t topology __hwloc_attribute_unused, const void *addr __hwloc_attribute_unused, size_t size __hwloc_attribute_unused, hwloc_bitmap_t set, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
hwloc_membind_policy_t policy;
|
||||
return dontset_return_complete_nodeset(topology, set, &policy);
|
||||
}
|
||||
|
||||
static void * dontalloc_membind(hwloc_topology_t topology __hwloc_attribute_unused, size_t size __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
static int dontfree_membind(hwloc_topology_t topology __hwloc_attribute_unused, void *addr __hwloc_attribute_unused, size_t size __hwloc_attribute_unused)
|
||||
{
|
||||
free(addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hwloc_set_dummy_hooks(struct hwloc_binding_hooks *hooks,
|
||||
struct hwloc_topology_support *support __hwloc_attribute_unused)
|
||||
{
|
||||
hooks->set_thisproc_cpubind = dontset_thisproc_cpubind;
|
||||
hooks->get_thisproc_cpubind = dontget_thisproc_cpubind;
|
||||
hooks->set_thisthread_cpubind = dontset_thisthread_cpubind;
|
||||
hooks->get_thisthread_cpubind = dontget_thisthread_cpubind;
|
||||
hooks->set_proc_cpubind = dontset_proc_cpubind;
|
||||
hooks->get_proc_cpubind = dontget_proc_cpubind;
|
||||
#ifdef hwloc_thread_t
|
||||
hooks->set_thread_cpubind = dontset_thread_cpubind;
|
||||
hooks->get_thread_cpubind = dontget_thread_cpubind;
|
||||
#endif
|
||||
hooks->get_thisproc_last_cpu_location = dontget_thisproc_cpubind; /* cpubind instead of last_cpu_location is ok */
|
||||
hooks->get_thisthread_last_cpu_location = dontget_thisthread_cpubind; /* cpubind instead of last_cpu_location is ok */
|
||||
hooks->get_proc_last_cpu_location = dontget_proc_cpubind; /* cpubind instead of last_cpu_location is ok */
|
||||
/* TODO: get_thread_last_cpu_location */
|
||||
hooks->set_thisproc_membind = dontset_thisproc_membind;
|
||||
hooks->get_thisproc_membind = dontget_thisproc_membind;
|
||||
hooks->set_thisthread_membind = dontset_thisthread_membind;
|
||||
hooks->get_thisthread_membind = dontget_thisthread_membind;
|
||||
hooks->set_proc_membind = dontset_proc_membind;
|
||||
hooks->get_proc_membind = dontget_proc_membind;
|
||||
hooks->set_area_membind = dontset_area_membind;
|
||||
hooks->get_area_membind = dontget_area_membind;
|
||||
hooks->get_area_memlocation = dontget_area_memlocation;
|
||||
hooks->alloc_membind = dontalloc_membind;
|
||||
hooks->free_membind = dontfree_membind;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_set_native_binding_hooks(struct hwloc_binding_hooks *hooks, struct hwloc_topology_support *support)
|
||||
{
|
||||
# ifdef HWLOC_LINUX_SYS
|
||||
hwloc_set_linuxfs_hooks(hooks, support);
|
||||
# endif /* HWLOC_LINUX_SYS */
|
||||
|
||||
# ifdef HWLOC_BGQ_SYS
|
||||
hwloc_set_bgq_hooks(hooks, support);
|
||||
# endif /* HWLOC_BGQ_SYS */
|
||||
|
||||
# ifdef HWLOC_AIX_SYS
|
||||
hwloc_set_aix_hooks(hooks, support);
|
||||
# endif /* HWLOC_AIX_SYS */
|
||||
|
||||
# ifdef HWLOC_SOLARIS_SYS
|
||||
hwloc_set_solaris_hooks(hooks, support);
|
||||
# endif /* HWLOC_SOLARIS_SYS */
|
||||
|
||||
# ifdef HWLOC_WIN_SYS
|
||||
hwloc_set_windows_hooks(hooks, support);
|
||||
# endif /* HWLOC_WIN_SYS */
|
||||
|
||||
# ifdef HWLOC_DARWIN_SYS
|
||||
hwloc_set_darwin_hooks(hooks, support);
|
||||
# endif /* HWLOC_DARWIN_SYS */
|
||||
|
||||
# ifdef HWLOC_FREEBSD_SYS
|
||||
hwloc_set_freebsd_hooks(hooks, support);
|
||||
# endif /* HWLOC_FREEBSD_SYS */
|
||||
|
||||
# ifdef HWLOC_NETBSD_SYS
|
||||
hwloc_set_netbsd_hooks(hooks, support);
|
||||
# endif /* HWLOC_NETBSD_SYS */
|
||||
|
||||
# ifdef HWLOC_HPUX_SYS
|
||||
hwloc_set_hpux_hooks(hooks, support);
|
||||
# endif /* HWLOC_HPUX_SYS */
|
||||
}
|
||||
|
||||
/* If the represented system is actually not this system, use dummy binding hooks. */
|
||||
void
|
||||
hwloc_set_binding_hooks(struct hwloc_topology *topology)
|
||||
{
|
||||
if (topology->is_thissystem) {
|
||||
hwloc_set_native_binding_hooks(&topology->binding_hooks, &topology->support);
|
||||
/* every hook not set above will return ENOSYS */
|
||||
} else {
|
||||
/* not this system, use dummy binding hooks that do nothing (but don't return ENOSYS) */
|
||||
hwloc_set_dummy_hooks(&topology->binding_hooks, &topology->support);
|
||||
}
|
||||
|
||||
/* if not is_thissystem, set_cpubind is fake
|
||||
* and get_cpubind returns the whole system cpuset,
|
||||
* so don't report that set/get_cpubind as supported
|
||||
*/
|
||||
if (topology->is_thissystem) {
|
||||
#define DO(which,kind) \
|
||||
if (topology->binding_hooks.kind) \
|
||||
topology->support.which##bind->kind = 1;
|
||||
DO(cpu,set_thisproc_cpubind);
|
||||
DO(cpu,get_thisproc_cpubind);
|
||||
DO(cpu,set_proc_cpubind);
|
||||
DO(cpu,get_proc_cpubind);
|
||||
DO(cpu,set_thisthread_cpubind);
|
||||
DO(cpu,get_thisthread_cpubind);
|
||||
#ifdef hwloc_thread_t
|
||||
DO(cpu,set_thread_cpubind);
|
||||
DO(cpu,get_thread_cpubind);
|
||||
#endif
|
||||
DO(cpu,get_thisproc_last_cpu_location);
|
||||
DO(cpu,get_proc_last_cpu_location);
|
||||
DO(cpu,get_thisthread_last_cpu_location);
|
||||
DO(mem,set_thisproc_membind);
|
||||
DO(mem,get_thisproc_membind);
|
||||
DO(mem,set_thisthread_membind);
|
||||
DO(mem,get_thisthread_membind);
|
||||
DO(mem,set_proc_membind);
|
||||
DO(mem,get_proc_membind);
|
||||
DO(mem,set_area_membind);
|
||||
DO(mem,get_area_membind);
|
||||
DO(mem,get_area_memlocation);
|
||||
DO(mem,alloc_membind);
|
||||
}
|
||||
}
|
1522
opal/mca/hwloc/hwloc2x/hwloc/hwloc/bitmap.c
Обычный файл
1522
opal/mca/hwloc/hwloc2x/hwloc/hwloc/bitmap.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
784
opal/mca/hwloc/hwloc2x/hwloc/hwloc/components.c
Обычный файл
784
opal/mca/hwloc/hwloc2x/hwloc/hwloc/components.c
Обычный файл
@ -0,0 +1,784 @@
|
||||
/*
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* Copyright © 2012 Université Bordeaux
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/xml.h>
|
||||
#include <private/misc.h>
|
||||
|
||||
#define HWLOC_COMPONENT_STOP_NAME "stop"
|
||||
#define HWLOC_COMPONENT_EXCLUDE_CHAR '-'
|
||||
#define HWLOC_COMPONENT_SEPS ","
|
||||
|
||||
/* list of all registered discovery components, sorted by priority, higher priority first.
|
||||
* noos is last because its priority is 0.
|
||||
* others' priority is 10.
|
||||
*/
|
||||
static struct hwloc_disc_component * hwloc_disc_components = NULL;
|
||||
|
||||
static unsigned hwloc_components_users = 0; /* first one initializes, last ones destroys */
|
||||
|
||||
static int hwloc_components_verbose = 0;
|
||||
#ifdef HWLOC_HAVE_PLUGINS
|
||||
static int hwloc_plugins_verbose = 0;
|
||||
static const char * hwloc_plugins_blacklist = NULL;
|
||||
#endif
|
||||
|
||||
/* hwloc_components_mutex serializes:
|
||||
* - loading/unloading plugins, and modifications of the hwloc_plugins list
|
||||
* - calls to ltdl, including in hwloc_check_plugin_namespace()
|
||||
* - registration of components with hwloc_disc_component_register()
|
||||
* and hwloc_xml_callbacks_register()
|
||||
*/
|
||||
#ifdef HWLOC_WIN_SYS
|
||||
/* Basic mutex on top of InterlockedCompareExchange() on windows,
|
||||
* Far from perfect, but easy to maintain, and way enough given that this code will never be needed for real. */
|
||||
#include <windows.h>
|
||||
static LONG hwloc_components_mutex = 0;
|
||||
#define HWLOC_COMPONENTS_LOCK() do { \
|
||||
while (InterlockedCompareExchange(&hwloc_components_mutex, 1, 0) != 0) \
|
||||
SwitchToThread(); \
|
||||
} while (0)
|
||||
#define HWLOC_COMPONENTS_UNLOCK() do { \
|
||||
assert(hwloc_components_mutex == 1); \
|
||||
hwloc_components_mutex = 0; \
|
||||
} while (0)
|
||||
|
||||
#elif defined HWLOC_HAVE_PTHREAD_MUTEX
|
||||
/* pthread mutex if available (except on windows) */
|
||||
#include <pthread.h>
|
||||
static pthread_mutex_t hwloc_components_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#define HWLOC_COMPONENTS_LOCK() pthread_mutex_lock(&hwloc_components_mutex)
|
||||
#define HWLOC_COMPONENTS_UNLOCK() pthread_mutex_unlock(&hwloc_components_mutex)
|
||||
|
||||
#else /* HWLOC_WIN_SYS || HWLOC_HAVE_PTHREAD_MUTEX */
|
||||
#error No mutex implementation available
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HWLOC_HAVE_PLUGINS
|
||||
|
||||
#include <ltdl.h>
|
||||
|
||||
/* array of pointers to dynamically loaded plugins */
|
||||
static struct hwloc__plugin_desc {
|
||||
char *name;
|
||||
struct hwloc_component *component;
|
||||
char *filename;
|
||||
lt_dlhandle handle;
|
||||
struct hwloc__plugin_desc *next;
|
||||
} *hwloc_plugins = NULL;
|
||||
|
||||
static int
|
||||
hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
|
||||
{
|
||||
const char *basename;
|
||||
lt_dlhandle handle;
|
||||
char *componentsymbolname = NULL;
|
||||
struct hwloc_component *component;
|
||||
struct hwloc__plugin_desc *desc, **prevdesc;
|
||||
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Plugin dlforeach found `%s'\n", filename);
|
||||
|
||||
basename = strrchr(filename, '/');
|
||||
if (!basename)
|
||||
basename = filename;
|
||||
else
|
||||
basename++;
|
||||
|
||||
if (hwloc_plugins_blacklist && strstr(hwloc_plugins_blacklist, basename)) {
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Plugin `%s' is blacklisted in the environment\n", basename);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* dlopen and get the component structure */
|
||||
handle = lt_dlopenext(filename);
|
||||
if (!handle) {
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Failed to load plugin: %s\n", lt_dlerror());
|
||||
goto out;
|
||||
}
|
||||
componentsymbolname = malloc(strlen(basename)+10+1);
|
||||
sprintf(componentsymbolname, "%s_component", basename);
|
||||
component = lt_dlsym(handle, componentsymbolname);
|
||||
if (!component) {
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Failed to find component symbol `%s'\n",
|
||||
componentsymbolname);
|
||||
goto out_with_handle;
|
||||
}
|
||||
if (component->abi != HWLOC_COMPONENT_ABI) {
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Plugin symbol ABI %u instead of %d\n",
|
||||
component->abi, HWLOC_COMPONENT_ABI);
|
||||
goto out_with_handle;
|
||||
}
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Plugin contains expected symbol `%s'\n",
|
||||
componentsymbolname);
|
||||
free(componentsymbolname);
|
||||
componentsymbolname = NULL;
|
||||
|
||||
if (HWLOC_COMPONENT_TYPE_DISC == component->type) {
|
||||
if (strncmp(basename, "hwloc_", 6)) {
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Plugin name `%s' doesn't match its type DISCOVERY\n", basename);
|
||||
goto out_with_handle;
|
||||
}
|
||||
} else if (HWLOC_COMPONENT_TYPE_XML == component->type) {
|
||||
if (strncmp(basename, "hwloc_xml_", 10)) {
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Plugin name `%s' doesn't match its type XML\n", basename);
|
||||
goto out_with_handle;
|
||||
}
|
||||
} else {
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Plugin name `%s' has invalid type %u\n",
|
||||
basename, (unsigned) component->type);
|
||||
goto out_with_handle;
|
||||
}
|
||||
|
||||
/* allocate a plugin_desc and queue it */
|
||||
desc = malloc(sizeof(*desc));
|
||||
if (!desc)
|
||||
goto out_with_handle;
|
||||
desc->name = strdup(basename);
|
||||
desc->filename = strdup(filename);
|
||||
desc->component = component;
|
||||
desc->handle = handle;
|
||||
desc->next = NULL;
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Plugin descriptor `%s' ready\n", basename);
|
||||
|
||||
/* append to the list */
|
||||
prevdesc = &hwloc_plugins;
|
||||
while (*prevdesc)
|
||||
prevdesc = &((*prevdesc)->next);
|
||||
*prevdesc = desc;
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Plugin descriptor `%s' queued\n", basename);
|
||||
return 0;
|
||||
|
||||
out_with_handle:
|
||||
lt_dlclose(handle);
|
||||
free(componentsymbolname); /* NULL if already freed */
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_plugins_exit(void)
|
||||
{
|
||||
struct hwloc__plugin_desc *desc, *next;
|
||||
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Closing all plugins\n");
|
||||
|
||||
desc = hwloc_plugins;
|
||||
while (desc) {
|
||||
next = desc->next;
|
||||
lt_dlclose(desc->handle);
|
||||
free(desc->name);
|
||||
free(desc->filename);
|
||||
free(desc);
|
||||
desc = next;
|
||||
}
|
||||
hwloc_plugins = NULL;
|
||||
|
||||
lt_dlexit();
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_plugins_init(void)
|
||||
{
|
||||
const char *verboseenv;
|
||||
const char *path = HWLOC_PLUGINS_PATH;
|
||||
const char *env;
|
||||
int err;
|
||||
|
||||
verboseenv = getenv("HWLOC_PLUGINS_VERBOSE");
|
||||
hwloc_plugins_verbose = verboseenv ? atoi(verboseenv) : 0;
|
||||
|
||||
hwloc_plugins_blacklist = getenv("HWLOC_PLUGINS_BLACKLIST");
|
||||
|
||||
err = lt_dlinit();
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
env = getenv("HWLOC_PLUGINS_PATH");
|
||||
if (env)
|
||||
path = env;
|
||||
|
||||
hwloc_plugins = NULL;
|
||||
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Starting plugin dlforeach in %s\n", path);
|
||||
err = lt_dlforeachfile(path, hwloc__dlforeach_cb, NULL);
|
||||
if (err)
|
||||
goto out_with_init;
|
||||
|
||||
return 0;
|
||||
|
||||
out_with_init:
|
||||
hwloc_plugins_exit();
|
||||
out:
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* HWLOC_HAVE_PLUGINS */
|
||||
|
||||
static const char *
|
||||
hwloc_disc_component_type_string(hwloc_disc_component_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case HWLOC_DISC_COMPONENT_TYPE_CPU: return "cpu";
|
||||
case HWLOC_DISC_COMPONENT_TYPE_GLOBAL: return "global";
|
||||
case HWLOC_DISC_COMPONENT_TYPE_MISC: return "misc";
|
||||
default: return "**unknown**";
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_disc_component_register(struct hwloc_disc_component *component,
|
||||
const char *filename)
|
||||
{
|
||||
struct hwloc_disc_component **prev;
|
||||
|
||||
/* check that the component name is valid */
|
||||
if (!strcmp(component->name, HWLOC_COMPONENT_STOP_NAME)) {
|
||||
if (hwloc_components_verbose)
|
||||
fprintf(stderr, "Cannot register discovery component with reserved name `" HWLOC_COMPONENT_STOP_NAME "'\n");
|
||||
return -1;
|
||||
}
|
||||
if (strchr(component->name, HWLOC_COMPONENT_EXCLUDE_CHAR)
|
||||
|| strcspn(component->name, HWLOC_COMPONENT_SEPS) != strlen(component->name)) {
|
||||
if (hwloc_components_verbose)
|
||||
fprintf(stderr, "Cannot register discovery component with name `%s' containing reserved characters `%c" HWLOC_COMPONENT_SEPS "'\n",
|
||||
component->name, HWLOC_COMPONENT_EXCLUDE_CHAR);
|
||||
return -1;
|
||||
}
|
||||
/* check that the component type is valid */
|
||||
switch ((unsigned) component->type) {
|
||||
case HWLOC_DISC_COMPONENT_TYPE_CPU:
|
||||
case HWLOC_DISC_COMPONENT_TYPE_GLOBAL:
|
||||
case HWLOC_DISC_COMPONENT_TYPE_MISC:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Cannot register discovery component `%s' with unknown type %u\n",
|
||||
component->name, (unsigned) component->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
prev = &hwloc_disc_components;
|
||||
while (NULL != *prev) {
|
||||
if (!strcmp((*prev)->name, component->name)) {
|
||||
/* if two components have the same name, only keep the highest priority one */
|
||||
if ((*prev)->priority < component->priority) {
|
||||
/* drop the existing component */
|
||||
if (hwloc_components_verbose)
|
||||
fprintf(stderr, "Dropping previously registered discovery component `%s', priority %u lower than new one %u\n",
|
||||
(*prev)->name, (*prev)->priority, component->priority);
|
||||
*prev = (*prev)->next;
|
||||
} else {
|
||||
/* drop the new one */
|
||||
if (hwloc_components_verbose)
|
||||
fprintf(stderr, "Ignoring new discovery component `%s', priority %u lower than previously registered one %u\n",
|
||||
component->name, component->priority, (*prev)->priority);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
prev = &((*prev)->next);
|
||||
}
|
||||
if (hwloc_components_verbose)
|
||||
fprintf(stderr, "Registered %s discovery component `%s' with priority %u (%s%s)\n",
|
||||
hwloc_disc_component_type_string(component->type), component->name, component->priority,
|
||||
filename ? "from plugin " : "statically build", filename ? filename : "");
|
||||
|
||||
prev = &hwloc_disc_components;
|
||||
while (NULL != *prev) {
|
||||
if ((*prev)->priority < component->priority)
|
||||
break;
|
||||
prev = &((*prev)->next);
|
||||
}
|
||||
component->next = *prev;
|
||||
*prev = component;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <static-components.h>
|
||||
|
||||
static void (**hwloc_component_finalize_cbs)(unsigned long);
|
||||
static unsigned hwloc_component_finalize_cb_count;
|
||||
|
||||
void
|
||||
hwloc_components_init(void)
|
||||
{
|
||||
#ifdef HWLOC_HAVE_PLUGINS
|
||||
struct hwloc__plugin_desc *desc;
|
||||
#endif
|
||||
const char *verboseenv;
|
||||
unsigned i;
|
||||
|
||||
HWLOC_COMPONENTS_LOCK();
|
||||
assert((unsigned) -1 != hwloc_components_users);
|
||||
if (0 != hwloc_components_users++) {
|
||||
HWLOC_COMPONENTS_UNLOCK();
|
||||
return;
|
||||
}
|
||||
|
||||
verboseenv = getenv("HWLOC_COMPONENTS_VERBOSE");
|
||||
hwloc_components_verbose = verboseenv ? atoi(verboseenv) : 0;
|
||||
|
||||
#ifdef HWLOC_HAVE_PLUGINS
|
||||
hwloc_plugins_init();
|
||||
#endif
|
||||
|
||||
hwloc_component_finalize_cbs = NULL;
|
||||
hwloc_component_finalize_cb_count = 0;
|
||||
/* count the max number of finalize callbacks */
|
||||
for(i=0; NULL != hwloc_static_components[i]; i++)
|
||||
hwloc_component_finalize_cb_count++;
|
||||
#ifdef HWLOC_HAVE_PLUGINS
|
||||
for(desc = hwloc_plugins; NULL != desc; desc = desc->next)
|
||||
hwloc_component_finalize_cb_count++;
|
||||
#endif
|
||||
if (hwloc_component_finalize_cb_count) {
|
||||
hwloc_component_finalize_cbs = calloc(hwloc_component_finalize_cb_count,
|
||||
sizeof(*hwloc_component_finalize_cbs));
|
||||
assert(hwloc_component_finalize_cbs);
|
||||
/* forget that max number and recompute the real one below */
|
||||
hwloc_component_finalize_cb_count = 0;
|
||||
}
|
||||
|
||||
/* hwloc_static_components is created by configure in static-components.h */
|
||||
for(i=0; NULL != hwloc_static_components[i]; i++) {
|
||||
if (hwloc_static_components[i]->flags) {
|
||||
fprintf(stderr, "Ignoring static component with invalid flags %lx\n",
|
||||
hwloc_static_components[i]->flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* initialize the component */
|
||||
if (hwloc_static_components[i]->init && hwloc_static_components[i]->init(0) < 0) {
|
||||
if (hwloc_components_verbose)
|
||||
fprintf(stderr, "Ignoring static component, failed to initialize\n");
|
||||
continue;
|
||||
}
|
||||
/* queue ->finalize() callback if any */
|
||||
if (hwloc_static_components[i]->finalize)
|
||||
hwloc_component_finalize_cbs[hwloc_component_finalize_cb_count++] = hwloc_static_components[i]->finalize;
|
||||
|
||||
/* register for real now */
|
||||
if (HWLOC_COMPONENT_TYPE_DISC == hwloc_static_components[i]->type)
|
||||
hwloc_disc_component_register(hwloc_static_components[i]->data, NULL);
|
||||
else if (HWLOC_COMPONENT_TYPE_XML == hwloc_static_components[i]->type)
|
||||
hwloc_xml_callbacks_register(hwloc_static_components[i]->data);
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* dynamic plugins */
|
||||
#ifdef HWLOC_HAVE_PLUGINS
|
||||
for(desc = hwloc_plugins; NULL != desc; desc = desc->next) {
|
||||
if (desc->component->flags) {
|
||||
fprintf(stderr, "Ignoring plugin `%s' component with invalid flags %lx\n",
|
||||
desc->name, desc->component->flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* initialize the component */
|
||||
if (desc->component->init && desc->component->init(0) < 0) {
|
||||
if (hwloc_components_verbose)
|
||||
fprintf(stderr, "Ignoring plugin `%s', failed to initialize\n", desc->name);
|
||||
continue;
|
||||
}
|
||||
/* queue ->finalize() callback if any */
|
||||
if (desc->component->finalize)
|
||||
hwloc_component_finalize_cbs[hwloc_component_finalize_cb_count++] = desc->component->finalize;
|
||||
|
||||
/* register for real now */
|
||||
if (HWLOC_COMPONENT_TYPE_DISC == desc->component->type)
|
||||
hwloc_disc_component_register(desc->component->data, desc->filename);
|
||||
else if (HWLOC_COMPONENT_TYPE_XML == desc->component->type)
|
||||
hwloc_xml_callbacks_register(desc->component->data);
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
HWLOC_COMPONENTS_UNLOCK();
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_backends_init(struct hwloc_topology *topology)
|
||||
{
|
||||
topology->backends = NULL;
|
||||
topology->backend_excludes = 0;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component *
|
||||
hwloc_disc_component_find(int type /* hwloc_disc_component_type_t or -1 if any */,
|
||||
const char *name /* name of NULL if any */)
|
||||
{
|
||||
struct hwloc_disc_component *comp = hwloc_disc_components;
|
||||
while (NULL != comp) {
|
||||
if ((-1 == type || type == (int) comp->type)
|
||||
&& (NULL == name || !strcmp(name, comp->name)))
|
||||
return comp;
|
||||
comp = comp->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* used by set_xml(), set_synthetic(), ... environment variables, ... to force the first backend */
|
||||
int
|
||||
hwloc_disc_component_force_enable(struct hwloc_topology *topology,
|
||||
int envvar_forced,
|
||||
int type, const char *name,
|
||||
const void *data1, const void *data2, const void *data3)
|
||||
{
|
||||
struct hwloc_disc_component *comp;
|
||||
struct hwloc_backend *backend;
|
||||
|
||||
if (topology->is_loaded) {
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
comp = hwloc_disc_component_find(type, name);
|
||||
if (!comp) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
backend = comp->instantiate(comp, data1, data2, data3);
|
||||
if (backend) {
|
||||
backend->envvar_forced = envvar_forced;
|
||||
if (topology->backends)
|
||||
hwloc_backends_disable_all(topology);
|
||||
return hwloc_backend_enable(topology, backend);
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_disc_component_try_enable(struct hwloc_topology *topology,
|
||||
struct hwloc_disc_component *comp,
|
||||
const char *comparg,
|
||||
int envvar_forced)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
|
||||
if (topology->backend_excludes & comp->type) {
|
||||
if (hwloc_components_verbose)
|
||||
/* do not warn if envvar_forced since system-wide HWLOC_COMPONENTS must be silently ignored after set_xml() etc.
|
||||
*/
|
||||
fprintf(stderr, "Excluding %s discovery component `%s', conflicts with excludes 0x%x\n",
|
||||
hwloc_disc_component_type_string(comp->type), comp->name, topology->backend_excludes);
|
||||
return -1;
|
||||
}
|
||||
|
||||
backend = comp->instantiate(comp, comparg, NULL, NULL);
|
||||
if (!backend) {
|
||||
if (hwloc_components_verbose || envvar_forced)
|
||||
fprintf(stderr, "Failed to instantiate discovery component `%s'\n", comp->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
backend->envvar_forced = envvar_forced;
|
||||
return hwloc_backend_enable(topology, backend);
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_disc_components_enable_others(struct hwloc_topology *topology)
|
||||
{
|
||||
struct hwloc_disc_component *comp;
|
||||
struct hwloc_backend *backend;
|
||||
int tryall = 1;
|
||||
const char *_env;
|
||||
char *env; /* we'll to modify the env value, so duplicate it */
|
||||
|
||||
_env = getenv("HWLOC_COMPONENTS");
|
||||
env = _env ? strdup(_env) : NULL;
|
||||
|
||||
/* enable explicitly listed components */
|
||||
if (env) {
|
||||
char *curenv = env;
|
||||
size_t s;
|
||||
|
||||
while (*curenv) {
|
||||
s = strcspn(curenv, HWLOC_COMPONENT_SEPS);
|
||||
if (s) {
|
||||
char c;
|
||||
|
||||
/* replace linuxpci with linuxio for backward compatibility with pre-v2.0 */
|
||||
if (!strncmp(curenv, "linuxpci", 8) && s == 8) {
|
||||
curenv[5] = 'i';
|
||||
curenv[6] = 'o';
|
||||
curenv[7] = *HWLOC_COMPONENT_SEPS;
|
||||
} else if (curenv[0] == HWLOC_COMPONENT_EXCLUDE_CHAR && !strncmp(curenv+1, "linuxpci", 8) && s == 9) {
|
||||
curenv[6] = 'i';
|
||||
curenv[7] = 'o';
|
||||
curenv[8] = *HWLOC_COMPONENT_SEPS;
|
||||
/* skip this name, it's a negated one */
|
||||
goto nextname;
|
||||
}
|
||||
|
||||
if (curenv[0] == HWLOC_COMPONENT_EXCLUDE_CHAR)
|
||||
goto nextname;
|
||||
|
||||
if (!strncmp(curenv, HWLOC_COMPONENT_STOP_NAME, s)) {
|
||||
tryall = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* save the last char and replace with \0 */
|
||||
c = curenv[s];
|
||||
curenv[s] = '\0';
|
||||
|
||||
comp = hwloc_disc_component_find(-1, curenv);
|
||||
if (comp) {
|
||||
hwloc_disc_component_try_enable(topology, comp, NULL, 1 /* envvar forced */);
|
||||
} else {
|
||||
fprintf(stderr, "Cannot find discovery component `%s'\n", curenv);
|
||||
}
|
||||
|
||||
/* restore chars (the second loop below needs env to be unmodified) */
|
||||
curenv[s] = c;
|
||||
}
|
||||
|
||||
nextname:
|
||||
curenv += s;
|
||||
if (*curenv)
|
||||
/* Skip comma */
|
||||
curenv++;
|
||||
}
|
||||
}
|
||||
|
||||
/* env is still the same, the above loop didn't modify it */
|
||||
|
||||
/* now enable remaining components (except the explicitly '-'-listed ones) */
|
||||
if (tryall) {
|
||||
comp = hwloc_disc_components;
|
||||
while (NULL != comp) {
|
||||
/* check if this component was explicitly excluded in env */
|
||||
if (env) {
|
||||
char *curenv = env;
|
||||
while (*curenv) {
|
||||
size_t s = strcspn(curenv, HWLOC_COMPONENT_SEPS);
|
||||
if (curenv[0] == HWLOC_COMPONENT_EXCLUDE_CHAR && !strncmp(curenv+1, comp->name, s-1) && strlen(comp->name) == s-1) {
|
||||
if (hwloc_components_verbose)
|
||||
fprintf(stderr, "Excluding %s discovery component `%s' because of HWLOC_COMPONENTS environment variable\n",
|
||||
hwloc_disc_component_type_string(comp->type), comp->name);
|
||||
goto nextcomp;
|
||||
}
|
||||
curenv += s;
|
||||
if (*curenv)
|
||||
/* Skip comma */
|
||||
curenv++;
|
||||
}
|
||||
}
|
||||
hwloc_disc_component_try_enable(topology, comp, NULL, 0 /* defaults, not envvar forced */);
|
||||
nextcomp:
|
||||
comp = comp->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (hwloc_components_verbose) {
|
||||
/* print a summary */
|
||||
int first = 1;
|
||||
backend = topology->backends;
|
||||
fprintf(stderr, "Final list of enabled discovery components: ");
|
||||
while (backend != NULL) {
|
||||
fprintf(stderr, "%s%s", first ? "" : ",", backend->component->name);
|
||||
backend = backend->next;
|
||||
first = 0;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
free(env);
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_components_fini(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
HWLOC_COMPONENTS_LOCK();
|
||||
assert(0 != hwloc_components_users);
|
||||
if (0 != --hwloc_components_users) {
|
||||
HWLOC_COMPONENTS_UNLOCK();
|
||||
return;
|
||||
}
|
||||
|
||||
for(i=0; i<hwloc_component_finalize_cb_count; i++)
|
||||
hwloc_component_finalize_cbs[hwloc_component_finalize_cb_count-i-1](0);
|
||||
free(hwloc_component_finalize_cbs);
|
||||
hwloc_component_finalize_cbs = NULL;
|
||||
hwloc_component_finalize_cb_count = 0;
|
||||
|
||||
/* no need to unlink/free the list of components, they'll be unloaded below */
|
||||
|
||||
hwloc_disc_components = NULL;
|
||||
hwloc_xml_callbacks_reset();
|
||||
|
||||
#ifdef HWLOC_HAVE_PLUGINS
|
||||
hwloc_plugins_exit();
|
||||
#endif
|
||||
|
||||
HWLOC_COMPONENTS_UNLOCK();
|
||||
}
|
||||
|
||||
struct hwloc_backend *
|
||||
hwloc_backend_alloc(struct hwloc_disc_component *component)
|
||||
{
|
||||
struct hwloc_backend * backend = malloc(sizeof(*backend));
|
||||
if (!backend) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
backend->component = component;
|
||||
backend->flags = 0;
|
||||
backend->discover = NULL;
|
||||
backend->get_pci_busid_cpuset = NULL;
|
||||
backend->disable = NULL;
|
||||
backend->is_thissystem = -1;
|
||||
backend->next = NULL;
|
||||
backend->envvar_forced = 0;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_backend_disable(struct hwloc_backend *backend)
|
||||
{
|
||||
if (backend->disable)
|
||||
backend->disable(backend);
|
||||
free(backend);
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_backend_enable(struct hwloc_topology *topology, struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_backend **pprev;
|
||||
|
||||
/* check backend flags */
|
||||
if (backend->flags) {
|
||||
fprintf(stderr, "Cannot enable %s discovery component `%s' with unknown flags %lx\n",
|
||||
hwloc_disc_component_type_string(backend->component->type), backend->component->name, backend->flags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* make sure we didn't already enable this backend, we don't want duplicates */
|
||||
pprev = &topology->backends;
|
||||
while (NULL != *pprev) {
|
||||
if ((*pprev)->component == backend->component) {
|
||||
if (hwloc_components_verbose)
|
||||
fprintf(stderr, "Cannot enable %s discovery component `%s' twice\n",
|
||||
hwloc_disc_component_type_string(backend->component->type), backend->component->name);
|
||||
hwloc_backend_disable(backend);
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
pprev = &((*pprev)->next);
|
||||
}
|
||||
|
||||
if (hwloc_components_verbose)
|
||||
fprintf(stderr, "Enabling %s discovery component `%s'\n",
|
||||
hwloc_disc_component_type_string(backend->component->type), backend->component->name);
|
||||
|
||||
/* enqueue at the end */
|
||||
pprev = &topology->backends;
|
||||
while (NULL != *pprev)
|
||||
pprev = &((*pprev)->next);
|
||||
backend->next = *pprev;
|
||||
*pprev = backend;
|
||||
|
||||
backend->topology = topology;
|
||||
topology->backend_excludes |= backend->component->excludes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_backends_is_thissystem(struct hwloc_topology *topology)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
const char *local_env;
|
||||
|
||||
/* Apply is_thissystem topology flag before we enforce envvar backends.
|
||||
* If the application changed the backend with set_foo(),
|
||||
* it may use set_flags() update the is_thissystem flag here.
|
||||
* If it changes the backend with environment variables below,
|
||||
* it may use HWLOC_THISSYSTEM envvar below as well.
|
||||
*/
|
||||
|
||||
topology->is_thissystem = 1;
|
||||
|
||||
/* apply thissystem from normally-given backends (envvar_forced=0, either set_foo() or defaults) */
|
||||
backend = topology->backends;
|
||||
while (backend != NULL) {
|
||||
if (backend->envvar_forced == 0 && backend->is_thissystem != -1) {
|
||||
assert(backend->is_thissystem == 0);
|
||||
topology->is_thissystem = 0;
|
||||
}
|
||||
backend = backend->next;
|
||||
}
|
||||
|
||||
/* override set_foo() with flags */
|
||||
if (topology->flags & HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM)
|
||||
topology->is_thissystem = 1;
|
||||
|
||||
/* now apply envvar-forced backend (envvar_forced=1) */
|
||||
backend = topology->backends;
|
||||
while (backend != NULL) {
|
||||
if (backend->envvar_forced == 1 && backend->is_thissystem != -1) {
|
||||
assert(backend->is_thissystem == 0);
|
||||
topology->is_thissystem = 0;
|
||||
}
|
||||
backend = backend->next;
|
||||
}
|
||||
|
||||
/* override with envvar-given flag */
|
||||
local_env = getenv("HWLOC_THISSYSTEM");
|
||||
if (local_env)
|
||||
topology->is_thissystem = atoi(local_env);
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_backends_find_callbacks(struct hwloc_topology *topology)
|
||||
{
|
||||
struct hwloc_backend *backend = topology->backends;
|
||||
/* use the first backend's get_pci_busid_cpuset callback */
|
||||
topology->get_pci_busid_cpuset_backend = NULL;
|
||||
while (backend != NULL) {
|
||||
if (backend->get_pci_busid_cpuset) {
|
||||
topology->get_pci_busid_cpuset_backend = backend;
|
||||
return;
|
||||
}
|
||||
backend = backend->next;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_backends_disable_all(struct hwloc_topology *topology)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
|
||||
while (NULL != (backend = topology->backends)) {
|
||||
struct hwloc_backend *next = backend->next;
|
||||
if (hwloc_components_verbose)
|
||||
fprintf(stderr, "Disabling %s discovery component `%s'\n",
|
||||
hwloc_disc_component_type_string(backend->component->type), backend->component->name);
|
||||
hwloc_backend_disable(backend);
|
||||
topology->backends = next;
|
||||
}
|
||||
topology->backends = NULL;
|
||||
topology->backend_excludes = 0;
|
||||
}
|
468
opal/mca/hwloc/hwloc2x/hwloc/hwloc/diff.c
Обычный файл
468
opal/mca/hwloc/hwloc2x/hwloc/hwloc/diff.c
Обычный файл
@ -0,0 +1,468 @@
|
||||
/*
|
||||
* Copyright © 2013-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <private/private.h>
|
||||
#include <private/misc.h>
|
||||
|
||||
int hwloc_topology_diff_destroy(hwloc_topology_diff_t diff)
|
||||
{
|
||||
hwloc_topology_diff_t next;
|
||||
while (diff) {
|
||||
next = diff->generic.next;
|
||||
switch (diff->generic.type) {
|
||||
default:
|
||||
break;
|
||||
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR:
|
||||
switch (diff->obj_attr.diff.generic.type) {
|
||||
default:
|
||||
break;
|
||||
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME:
|
||||
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO:
|
||||
free(diff->obj_attr.diff.string.name);
|
||||
free(diff->obj_attr.diff.string.oldvalue);
|
||||
free(diff->obj_attr.diff.string.newvalue);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
free(diff);
|
||||
diff = next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************
|
||||
* Computing diffs
|
||||
*/
|
||||
|
||||
static void hwloc_append_diff(hwloc_topology_diff_t newdiff,
|
||||
hwloc_topology_diff_t *firstdiffp,
|
||||
hwloc_topology_diff_t *lastdiffp)
|
||||
{
|
||||
if (*firstdiffp)
|
||||
(*lastdiffp)->generic.next = newdiff;
|
||||
else
|
||||
*firstdiffp = newdiff;
|
||||
*lastdiffp = newdiff;
|
||||
newdiff->generic.next = NULL;
|
||||
}
|
||||
|
||||
static int hwloc_append_diff_too_complex(hwloc_obj_t obj1,
|
||||
hwloc_topology_diff_t *firstdiffp,
|
||||
hwloc_topology_diff_t *lastdiffp)
|
||||
{
|
||||
hwloc_topology_diff_t newdiff;
|
||||
newdiff = malloc(sizeof(*newdiff));
|
||||
if (!newdiff)
|
||||
return -1;
|
||||
|
||||
newdiff->too_complex.type = HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX;
|
||||
newdiff->too_complex.obj_depth = obj1->depth;
|
||||
newdiff->too_complex.obj_index = obj1->logical_index;
|
||||
hwloc_append_diff(newdiff, firstdiffp, lastdiffp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hwloc_append_diff_obj_attr_string(hwloc_obj_t obj,
|
||||
hwloc_topology_diff_obj_attr_type_t type,
|
||||
const char *name,
|
||||
const char *oldvalue,
|
||||
const char *newvalue,
|
||||
hwloc_topology_diff_t *firstdiffp,
|
||||
hwloc_topology_diff_t *lastdiffp)
|
||||
{
|
||||
hwloc_topology_diff_t newdiff;
|
||||
newdiff = malloc(sizeof(*newdiff));
|
||||
if (!newdiff)
|
||||
return -1;
|
||||
|
||||
newdiff->obj_attr.type = HWLOC_TOPOLOGY_DIFF_OBJ_ATTR;
|
||||
newdiff->obj_attr.obj_depth = obj->depth;
|
||||
newdiff->obj_attr.obj_index = obj->logical_index;
|
||||
newdiff->obj_attr.diff.string.type = type;
|
||||
newdiff->obj_attr.diff.string.name = name ? strdup(name) : NULL;
|
||||
newdiff->obj_attr.diff.string.oldvalue = oldvalue ? strdup(oldvalue) : NULL;
|
||||
newdiff->obj_attr.diff.string.newvalue = newvalue ? strdup(newvalue) : NULL;
|
||||
hwloc_append_diff(newdiff, firstdiffp, lastdiffp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hwloc_append_diff_obj_attr_uint64(hwloc_obj_t obj,
|
||||
hwloc_topology_diff_obj_attr_type_t type,
|
||||
hwloc_uint64_t idx,
|
||||
hwloc_uint64_t oldvalue,
|
||||
hwloc_uint64_t newvalue,
|
||||
hwloc_topology_diff_t *firstdiffp,
|
||||
hwloc_topology_diff_t *lastdiffp)
|
||||
{
|
||||
hwloc_topology_diff_t newdiff;
|
||||
newdiff = malloc(sizeof(*newdiff));
|
||||
if (!newdiff)
|
||||
return -1;
|
||||
|
||||
newdiff->obj_attr.type = HWLOC_TOPOLOGY_DIFF_OBJ_ATTR;
|
||||
newdiff->obj_attr.obj_depth = obj->depth;
|
||||
newdiff->obj_attr.obj_index = obj->logical_index;
|
||||
newdiff->obj_attr.diff.uint64.type = type;
|
||||
newdiff->obj_attr.diff.uint64.index = idx;
|
||||
newdiff->obj_attr.diff.uint64.oldvalue = oldvalue;
|
||||
newdiff->obj_attr.diff.uint64.newvalue = newvalue;
|
||||
hwloc_append_diff(newdiff, firstdiffp, lastdiffp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_diff_trees(hwloc_topology_t topo1, hwloc_obj_t obj1,
|
||||
hwloc_topology_t topo2, hwloc_obj_t obj2,
|
||||
unsigned flags,
|
||||
hwloc_topology_diff_t *firstdiffp, hwloc_topology_diff_t *lastdiffp)
|
||||
{
|
||||
unsigned i;
|
||||
int err;
|
||||
hwloc_obj_t child1, child2;
|
||||
|
||||
if (obj1->depth != obj2->depth)
|
||||
goto out_too_complex;
|
||||
|
||||
if (obj1->type != obj2->type)
|
||||
goto out_too_complex;
|
||||
if ((!obj1->subtype) != (!obj2->subtype)
|
||||
|| (obj1->subtype && strcmp(obj1->subtype, obj2->subtype)))
|
||||
goto out_too_complex;
|
||||
|
||||
if (obj1->os_index != obj2->os_index)
|
||||
/* we could allow different os_index for non-PU non-NUMAnode objects
|
||||
* but it's likely useless anyway */
|
||||
goto out_too_complex;
|
||||
|
||||
#define _SETS_DIFFERENT(_set1, _set2) \
|
||||
( ( !(_set1) != !(_set2) ) \
|
||||
|| ( (_set1) && !hwloc_bitmap_isequal(_set1, _set2) ) )
|
||||
#define SETS_DIFFERENT(_set, _obj1, _obj2) _SETS_DIFFERENT((_obj1)->_set, (_obj2)->_set)
|
||||
if (SETS_DIFFERENT(cpuset, obj1, obj2)
|
||||
|| SETS_DIFFERENT(complete_cpuset, obj1, obj2)
|
||||
|| SETS_DIFFERENT(allowed_cpuset, obj1, obj2)
|
||||
|| SETS_DIFFERENT(nodeset, obj1, obj2)
|
||||
|| SETS_DIFFERENT(complete_nodeset, obj1, obj2)
|
||||
|| SETS_DIFFERENT(allowed_nodeset, obj1, obj2))
|
||||
goto out_too_complex;
|
||||
|
||||
/* no need to check logical_index, sibling_rank, symmetric_subtree,
|
||||
* the parents did it */
|
||||
|
||||
/* gp_index don't have to be strictly identical */
|
||||
|
||||
if ((!obj1->name) != (!obj2->name)
|
||||
|| (obj1->name && strcmp(obj1->name, obj2->name))) {
|
||||
err = hwloc_append_diff_obj_attr_string(obj1,
|
||||
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME,
|
||||
NULL,
|
||||
obj1->name,
|
||||
obj2->name,
|
||||
firstdiffp, lastdiffp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* memory */
|
||||
if (obj1->memory.local_memory != obj2->memory.local_memory) {
|
||||
err = hwloc_append_diff_obj_attr_uint64(obj1,
|
||||
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE,
|
||||
0,
|
||||
obj1->memory.local_memory,
|
||||
obj2->memory.local_memory,
|
||||
firstdiffp, lastdiffp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
/* ignore memory page_types */
|
||||
|
||||
/* type-specific attrs */
|
||||
switch (obj1->type) {
|
||||
default:
|
||||
break;
|
||||
case HWLOC_OBJ_L1CACHE:
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
case HWLOC_OBJ_L3CACHE:
|
||||
case HWLOC_OBJ_L4CACHE:
|
||||
case HWLOC_OBJ_L5CACHE:
|
||||
case HWLOC_OBJ_L1ICACHE:
|
||||
case HWLOC_OBJ_L2ICACHE:
|
||||
case HWLOC_OBJ_L3ICACHE:
|
||||
if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->cache)))
|
||||
goto out_too_complex;
|
||||
break;
|
||||
case HWLOC_OBJ_GROUP:
|
||||
if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->group)))
|
||||
goto out_too_complex;
|
||||
break;
|
||||
case HWLOC_OBJ_PCI_DEVICE:
|
||||
if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->pcidev)))
|
||||
goto out_too_complex;
|
||||
break;
|
||||
case HWLOC_OBJ_BRIDGE:
|
||||
if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->bridge)))
|
||||
goto out_too_complex;
|
||||
break;
|
||||
case HWLOC_OBJ_OS_DEVICE:
|
||||
if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->osdev)))
|
||||
goto out_too_complex;
|
||||
break;
|
||||
}
|
||||
|
||||
/* infos */
|
||||
if (obj1->infos_count != obj2->infos_count)
|
||||
goto out_too_complex;
|
||||
for(i=0; i<obj1->infos_count; i++) {
|
||||
if (strcmp(obj1->infos[i].name, obj2->infos[i].name))
|
||||
goto out_too_complex;
|
||||
if (strcmp(obj1->infos[i].value, obj2->infos[i].value)) {
|
||||
err = hwloc_append_diff_obj_attr_string(obj1,
|
||||
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO,
|
||||
obj1->infos[i].name,
|
||||
obj1->infos[i].value,
|
||||
obj2->infos[i].value,
|
||||
firstdiffp, lastdiffp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* ignore userdata */
|
||||
|
||||
/* children */
|
||||
for(child1 = obj1->first_child, child2 = obj2->first_child;
|
||||
child1 != NULL && child2 != NULL;
|
||||
child1 = child1->next_sibling, child2 = child2->next_sibling) {
|
||||
err = hwloc_diff_trees(topo1, child1,
|
||||
topo2, child2,
|
||||
flags,
|
||||
firstdiffp, lastdiffp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (child1 || child2)
|
||||
goto out_too_complex;
|
||||
|
||||
/* I/O children */
|
||||
for(child1 = obj1->io_first_child, child2 = obj2->io_first_child;
|
||||
child1 != NULL && child2 != NULL;
|
||||
child1 = child1->next_sibling, child2 = child2->next_sibling) {
|
||||
err = hwloc_diff_trees(topo1, child1,
|
||||
topo2, child2,
|
||||
flags,
|
||||
firstdiffp, lastdiffp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (child1 || child2)
|
||||
goto out_too_complex;
|
||||
|
||||
/* misc children */
|
||||
for(child1 = obj1->misc_first_child, child2 = obj2->misc_first_child;
|
||||
child1 != NULL && child2 != NULL;
|
||||
child1 = child1->next_sibling, child2 = child2->next_sibling) {
|
||||
err = hwloc_diff_trees(topo1, child1,
|
||||
topo2, child2,
|
||||
flags,
|
||||
firstdiffp, lastdiffp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (child1 || child2)
|
||||
goto out_too_complex;
|
||||
|
||||
return 0;
|
||||
|
||||
out_too_complex:
|
||||
hwloc_append_diff_too_complex(obj1, firstdiffp, lastdiffp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hwloc_topology_diff_build(hwloc_topology_t topo1,
|
||||
hwloc_topology_t topo2,
|
||||
unsigned long flags,
|
||||
hwloc_topology_diff_t *diffp)
|
||||
{
|
||||
hwloc_topology_diff_t lastdiff, tmpdiff;
|
||||
struct hwloc_internal_distances_s *dist1, *dist2;
|
||||
unsigned i;
|
||||
int err;
|
||||
|
||||
if (!topo1->is_loaded || !topo2->is_loaded) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags != 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*diffp = NULL;
|
||||
err = hwloc_diff_trees(topo1, hwloc_get_root_obj(topo1),
|
||||
topo2, hwloc_get_root_obj(topo2),
|
||||
flags,
|
||||
diffp, &lastdiff);
|
||||
if (!err) {
|
||||
tmpdiff = *diffp;
|
||||
while (tmpdiff) {
|
||||
if (tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX) {
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
tmpdiff = tmpdiff->generic.next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
/* distances */
|
||||
hwloc_internal_distances_refresh(topo1);
|
||||
hwloc_internal_distances_refresh(topo2);
|
||||
dist1 = topo1->first_dist;
|
||||
dist2 = topo2->first_dist;
|
||||
while (dist1 || dist2) {
|
||||
if (!!dist1 != !!dist2) {
|
||||
hwloc_append_diff_too_complex(hwloc_get_root_obj(topo1), diffp, &lastdiff);
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
if (dist1->type != dist2->type
|
||||
|| dist1->nbobjs != dist2->nbobjs
|
||||
|| dist1->kind != dist2->kind
|
||||
|| memcmp(dist1->values, dist2->values, dist1->nbobjs * dist1->nbobjs * sizeof(*dist1->values))) {
|
||||
hwloc_append_diff_too_complex(hwloc_get_root_obj(topo1), diffp, &lastdiff);
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
for(i=0; i<dist1->nbobjs; i++)
|
||||
/* gp_index isn't enforced above. so compare logical_index instead, which is enforced. requires distances refresh() above */
|
||||
if (dist1->objs[i]->logical_index != dist2->objs[i]->logical_index) {
|
||||
hwloc_append_diff_too_complex(hwloc_get_root_obj(topo1), diffp, &lastdiff);
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
dist1 = dist1->next;
|
||||
dist2 = dist2->next;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/********************
|
||||
* Applying diffs
|
||||
*/
|
||||
|
||||
static int
|
||||
hwloc_apply_diff_one(hwloc_topology_t topology,
|
||||
hwloc_topology_diff_t diff,
|
||||
unsigned long flags)
|
||||
{
|
||||
int reverse = !!(flags & HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE);
|
||||
|
||||
switch (diff->generic.type) {
|
||||
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR: {
|
||||
struct hwloc_topology_diff_obj_attr_s *obj_attr = &diff->obj_attr;
|
||||
hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, obj_attr->obj_depth, obj_attr->obj_index);
|
||||
if (!obj)
|
||||
return -1;
|
||||
|
||||
switch (obj_attr->diff.generic.type) {
|
||||
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE: {
|
||||
hwloc_obj_t tmpobj;
|
||||
hwloc_uint64_t oldvalue = reverse ? obj_attr->diff.uint64.newvalue : obj_attr->diff.uint64.oldvalue;
|
||||
hwloc_uint64_t newvalue = reverse ? obj_attr->diff.uint64.oldvalue : obj_attr->diff.uint64.newvalue;
|
||||
hwloc_uint64_t valuediff = newvalue - oldvalue;
|
||||
if (obj->memory.local_memory != oldvalue)
|
||||
return -1;
|
||||
obj->memory.local_memory = newvalue;
|
||||
tmpobj = obj;
|
||||
while (tmpobj) {
|
||||
tmpobj->memory.total_memory += valuediff;
|
||||
tmpobj = tmpobj->parent;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME: {
|
||||
const char *oldvalue = reverse ? obj_attr->diff.string.newvalue : obj_attr->diff.string.oldvalue;
|
||||
const char *newvalue = reverse ? obj_attr->diff.string.oldvalue : obj_attr->diff.string.newvalue;
|
||||
if (!obj->name || strcmp(obj->name, oldvalue))
|
||||
return -1;
|
||||
free(obj->name);
|
||||
obj->name = strdup(newvalue);
|
||||
break;
|
||||
}
|
||||
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO: {
|
||||
const char *name = obj_attr->diff.string.name;
|
||||
const char *oldvalue = reverse ? obj_attr->diff.string.newvalue : obj_attr->diff.string.oldvalue;
|
||||
const char *newvalue = reverse ? obj_attr->diff.string.oldvalue : obj_attr->diff.string.newvalue;
|
||||
unsigned i;
|
||||
int found = 0;
|
||||
for(i=0; i<obj->infos_count; i++) {
|
||||
if (!strcmp(obj->infos[i].name, name)
|
||||
&& !strcmp(obj->infos[i].value, oldvalue)) {
|
||||
free(obj->infos[i].value);
|
||||
obj->infos[i].value = strdup(newvalue);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hwloc_topology_diff_apply(hwloc_topology_t topology,
|
||||
hwloc_topology_diff_t diff,
|
||||
unsigned long flags)
|
||||
{
|
||||
hwloc_topology_diff_t tmpdiff, tmpdiff2;
|
||||
int err, nr;
|
||||
|
||||
if (!topology->is_loaded) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & ~HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmpdiff = diff;
|
||||
nr = 0;
|
||||
while (tmpdiff) {
|
||||
nr++;
|
||||
err = hwloc_apply_diff_one(topology, tmpdiff, flags);
|
||||
if (err < 0)
|
||||
goto cancel;
|
||||
tmpdiff = tmpdiff->generic.next;
|
||||
}
|
||||
return 0;
|
||||
|
||||
cancel:
|
||||
tmpdiff2 = tmpdiff;
|
||||
tmpdiff = diff;
|
||||
while (tmpdiff != tmpdiff2) {
|
||||
hwloc_apply_diff_one(topology, tmpdiff, flags ^ HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE);
|
||||
tmpdiff = tmpdiff->generic.next;
|
||||
}
|
||||
errno = EINVAL;
|
||||
return -nr; /* return the index (starting at 1) of the first element that couldn't be applied */
|
||||
}
|
927
opal/mca/hwloc/hwloc2x/hwloc/hwloc/distances.c
Обычный файл
927
opal/mca/hwloc/hwloc2x/hwloc/hwloc/distances.c
Обычный файл
@ -0,0 +1,927 @@
|
||||
/*
|
||||
* Copyright © 2010-2017 Inria. All rights reserved.
|
||||
* Copyright © 2011-2012 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/debug.h>
|
||||
#include <private/misc.h>
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
/******************************************************
|
||||
* Global init, prepare, destroy, dup
|
||||
*/
|
||||
|
||||
/* called during topology init() */
|
||||
void hwloc_internal_distances_init(struct hwloc_topology *topology)
|
||||
{
|
||||
topology->first_dist = topology->last_dist = NULL;
|
||||
}
|
||||
|
||||
/* called at the beginning of load() */
|
||||
void hwloc_internal_distances_prepare(struct hwloc_topology *topology)
|
||||
{
|
||||
char *env;
|
||||
hwloc_localeswitch_declare;
|
||||
|
||||
topology->grouping = 1;
|
||||
if (topology->type_filter[HWLOC_OBJ_GROUP] == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
topology->grouping = 0;
|
||||
env = getenv("HWLOC_GROUPING");
|
||||
if (env && !atoi(env))
|
||||
topology->grouping = 0;
|
||||
|
||||
if (topology->grouping) {
|
||||
topology->grouping_next_subkind = 0;
|
||||
|
||||
HWLOC_BUILD_ASSERT(sizeof(topology->grouping_accuracies)/sizeof(*topology->grouping_accuracies) == 5);
|
||||
topology->grouping_accuracies[0] = 0.0f;
|
||||
topology->grouping_accuracies[1] = 0.01f;
|
||||
topology->grouping_accuracies[2] = 0.02f;
|
||||
topology->grouping_accuracies[3] = 0.05f;
|
||||
topology->grouping_accuracies[4] = 0.1f;
|
||||
topology->grouping_nbaccuracies = 5;
|
||||
|
||||
hwloc_localeswitch_init();
|
||||
env = getenv("HWLOC_GROUPING_ACCURACY");
|
||||
if (!env) {
|
||||
/* only use 0.0 */
|
||||
topology->grouping_nbaccuracies = 1;
|
||||
} else if (strcmp(env, "try")) {
|
||||
/* use the given value */
|
||||
topology->grouping_nbaccuracies = 1;
|
||||
topology->grouping_accuracies[0] = (float) atof(env);
|
||||
} /* otherwise try all values */
|
||||
hwloc_localeswitch_fini();
|
||||
|
||||
topology->grouping_verbose = 0;
|
||||
env = getenv("HWLOC_GROUPING_VERBOSE");
|
||||
if (env)
|
||||
topology->grouping_verbose = atoi(env);
|
||||
}
|
||||
}
|
||||
|
||||
static void hwloc_internal_distances_free(struct hwloc_internal_distances_s *dist)
|
||||
{
|
||||
free(dist->indexes);
|
||||
free(dist->objs);
|
||||
free(dist->values);
|
||||
free(dist);
|
||||
}
|
||||
|
||||
/* called during topology destroy */
|
||||
void hwloc_internal_distances_destroy(struct hwloc_topology * topology)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist, *next = topology->first_dist;
|
||||
while ((dist = next) != NULL) {
|
||||
next = dist->next;
|
||||
hwloc_internal_distances_free(dist);
|
||||
}
|
||||
topology->first_dist = topology->last_dist = NULL;
|
||||
}
|
||||
|
||||
static int hwloc_internal_distances_dup_one(struct hwloc_topology *new, struct hwloc_internal_distances_s *olddist)
|
||||
{
|
||||
struct hwloc_internal_distances_s *newdist;
|
||||
unsigned nbobjs = olddist->nbobjs;
|
||||
|
||||
newdist = malloc(sizeof(*newdist));
|
||||
if (!newdist)
|
||||
return -1;
|
||||
|
||||
newdist->type = olddist->type;
|
||||
newdist->nbobjs = nbobjs;
|
||||
newdist->kind = olddist->kind;
|
||||
|
||||
newdist->indexes = malloc(nbobjs * sizeof(*newdist->indexes));
|
||||
newdist->objs = calloc(nbobjs, sizeof(*newdist->objs));
|
||||
newdist->objs_are_valid = 0;
|
||||
newdist->values = malloc(nbobjs*nbobjs * sizeof(*newdist->values));
|
||||
if (!newdist->indexes || !newdist->objs || !newdist->values) {
|
||||
hwloc_internal_distances_free(newdist);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(newdist->indexes, olddist->indexes, nbobjs * sizeof(*newdist->indexes));
|
||||
memcpy(newdist->values, olddist->values, nbobjs*nbobjs * sizeof(*newdist->values));
|
||||
|
||||
newdist->next = NULL;
|
||||
newdist->prev = new->last_dist;
|
||||
if (new->last_dist)
|
||||
new->last_dist->next = newdist;
|
||||
else
|
||||
new->first_dist = newdist;
|
||||
new->last_dist = newdist;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* called by topology_dup() */
|
||||
int hwloc_internal_distances_dup(struct hwloc_topology *new, struct hwloc_topology *old)
|
||||
{
|
||||
struct hwloc_internal_distances_s *olddist;
|
||||
int err;
|
||||
for(olddist = old->first_dist; olddist; olddist = olddist->next) {
|
||||
err = hwloc_internal_distances_dup_one(new, olddist);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* Remove distances from the topology
|
||||
*/
|
||||
|
||||
int hwloc_distances_remove(hwloc_topology_t topology)
|
||||
{
|
||||
if (!topology->is_loaded) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
hwloc_internal_distances_destroy(topology);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hwloc_distances_remove_by_depth(hwloc_topology_t topology, unsigned depth)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist, *next;
|
||||
hwloc_obj_type_t type;
|
||||
|
||||
if (!topology->is_loaded) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* switch back to types since we don't support groups for now */
|
||||
type = hwloc_get_depth_type(topology, depth);
|
||||
if (type == (hwloc_obj_type_t)-1) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
next = topology->first_dist;
|
||||
while ((dist = next) != NULL) {
|
||||
next = dist->next;
|
||||
if (dist->type == type) {
|
||||
if (next)
|
||||
next->prev = dist->prev;
|
||||
else
|
||||
topology->last_dist = dist->prev;
|
||||
if (dist->prev)
|
||||
dist->prev->next = dist->next;
|
||||
else
|
||||
topology->first_dist = dist->next;
|
||||
hwloc_internal_distances_free(dist);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* Add distances to the topology
|
||||
*/
|
||||
|
||||
static void
|
||||
hwloc__groups_by_distances(struct hwloc_topology *topology, unsigned nbobjs, struct hwloc_obj **objs, uint64_t *values, unsigned long kind, unsigned nbaccuracies, float *accuracies, int needcheck);
|
||||
|
||||
/* insert a distance matrix in the topology.
|
||||
* the caller gives us the distances and objs pointers, we'll free them later.
|
||||
*/
|
||||
static int
|
||||
hwloc_internal_distances__add(hwloc_topology_t topology,
|
||||
hwloc_obj_type_t type, unsigned nbobjs, hwloc_obj_t *objs, uint64_t *indexes, uint64_t *values,
|
||||
unsigned long kind)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist = calloc(1, sizeof(*dist));
|
||||
if (!dist)
|
||||
goto err;
|
||||
|
||||
dist->type = type;
|
||||
dist->nbobjs = nbobjs;
|
||||
dist->kind = kind;
|
||||
|
||||
if (!objs) {
|
||||
assert(indexes);
|
||||
/* we only have indexes, we'll refresh objs from there */
|
||||
dist->indexes = indexes;
|
||||
dist->objs = calloc(nbobjs, sizeof(hwloc_obj_t));
|
||||
if (!dist->objs)
|
||||
goto err_with_dist;
|
||||
dist->objs_are_valid = 0;
|
||||
|
||||
} else {
|
||||
unsigned i;
|
||||
assert(!indexes);
|
||||
/* we only have objs, generate the indexes arrays so that we can refresh objs later */
|
||||
dist->objs = objs;
|
||||
dist->objs_are_valid = 1;
|
||||
dist->indexes = malloc(nbobjs * sizeof(*dist->indexes));
|
||||
if (!dist->indexes)
|
||||
goto err_with_dist;
|
||||
if (dist->type == HWLOC_OBJ_PU || dist->type == HWLOC_OBJ_NUMANODE) {
|
||||
for(i=0; i<nbobjs; i++)
|
||||
dist->indexes[i] = objs[i]->os_index;
|
||||
} else {
|
||||
for(i=0; i<nbobjs; i++)
|
||||
dist->indexes[i] = objs[i]->gp_index;
|
||||
}
|
||||
}
|
||||
|
||||
dist->values = values;
|
||||
|
||||
if (topology->last_dist)
|
||||
topology->last_dist->next = dist;
|
||||
else
|
||||
topology->first_dist = dist;
|
||||
dist->prev = topology->last_dist;
|
||||
dist->next = NULL;
|
||||
topology->last_dist = dist;
|
||||
return 0;
|
||||
|
||||
err_with_dist:
|
||||
free(dist);
|
||||
err:
|
||||
free(objs);
|
||||
free(indexes);
|
||||
free(values);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int hwloc_internal_distances_add_by_index(hwloc_topology_t topology,
|
||||
hwloc_obj_type_t type, unsigned nbobjs, uint64_t *indexes, uint64_t *values,
|
||||
unsigned long kind, unsigned long flags)
|
||||
{
|
||||
if (nbobjs < 2) {
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* cannot group without objects,
|
||||
* and we don't group from XML anyway since the hwloc that generated the XML should have grouped already.
|
||||
*/
|
||||
if (flags & HWLOC_DISTANCES_FLAG_GROUP) {
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return hwloc_internal_distances__add(topology, type, nbobjs, NULL, indexes, values, kind);
|
||||
|
||||
err:
|
||||
free(indexes);
|
||||
free(values);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int hwloc_internal_distances_add(hwloc_topology_t topology,
|
||||
unsigned nbobjs, hwloc_obj_t *objs, uint64_t *values,
|
||||
unsigned long kind, unsigned long flags)
|
||||
{
|
||||
if (nbobjs < 2) {
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (topology->grouping && (flags & HWLOC_DISTANCES_FLAG_GROUP)) {
|
||||
float full_accuracy = 0.f;
|
||||
float *accuracies;
|
||||
unsigned nbaccuracies;
|
||||
|
||||
if (flags & HWLOC_DISTANCES_FLAG_GROUP_INACCURATE) {
|
||||
accuracies = topology->grouping_accuracies;
|
||||
nbaccuracies = topology->grouping_nbaccuracies;
|
||||
} else {
|
||||
accuracies = &full_accuracy;
|
||||
nbaccuracies = 1;
|
||||
}
|
||||
|
||||
if (topology->grouping_verbose) {
|
||||
unsigned i, j;
|
||||
int gp = (objs[0]->type != HWLOC_OBJ_NUMANODE && objs[0]->type != HWLOC_OBJ_PU);
|
||||
fprintf(stderr, "Trying to group objects using distance matrix:\n");
|
||||
fprintf(stderr, "%s", gp ? "gp_index" : "os_index");
|
||||
for(j=0; j<nbobjs; j++)
|
||||
fprintf(stderr, " % 5d", (int)(gp ? objs[j]->gp_index : objs[j]->os_index));
|
||||
fprintf(stderr, "\n");
|
||||
for(i=0; i<nbobjs; i++) {
|
||||
fprintf(stderr, " % 5d", (int)(gp ? objs[i]->gp_index : objs[i]->os_index));
|
||||
for(j=0; j<nbobjs; j++)
|
||||
fprintf(stderr, " % 5lld", (long long) values[i*nbobjs + j]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
hwloc__groups_by_distances(topology, nbobjs, objs, values,
|
||||
kind, nbaccuracies, accuracies, 1 /* check the first matrice */);
|
||||
}
|
||||
|
||||
return hwloc_internal_distances__add(topology, objs[0]->type, nbobjs, objs, NULL, values, kind);
|
||||
|
||||
err:
|
||||
free(objs);
|
||||
free(values);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define HWLOC_DISTANCES_KIND_FROM_ALL (HWLOC_DISTANCES_KIND_FROM_OS|HWLOC_DISTANCES_KIND_FROM_USER)
|
||||
#define HWLOC_DISTANCES_KIND_MEANS_ALL (HWLOC_DISTANCES_KIND_MEANS_LATENCY|HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH)
|
||||
#define HWLOC_DISTANCES_KIND_ALL (HWLOC_DISTANCES_KIND_FROM_ALL|HWLOC_DISTANCES_KIND_MEANS_ALL)
|
||||
#define HWLOC_DISTANCES_FLAG_ALL (HWLOC_DISTANCES_FLAG_GROUP|HWLOC_DISTANCES_FLAG_GROUP_INACCURATE)
|
||||
|
||||
/* The actual function exported to the user
|
||||
*/
|
||||
int hwloc_distances_add(hwloc_topology_t topology,
|
||||
unsigned nbobjs, hwloc_obj_t *objs, uint64_t *values,
|
||||
unsigned long kind, unsigned long flags)
|
||||
{
|
||||
hwloc_obj_type_t type;
|
||||
unsigned i;
|
||||
uint64_t *_values;
|
||||
hwloc_obj_t *_objs;
|
||||
int err;
|
||||
|
||||
if (nbobjs < 2 || !objs || !values || !topology->is_loaded) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if ((kind & ~HWLOC_DISTANCES_KIND_ALL)
|
||||
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_FROM_ALL) != 1
|
||||
|| hwloc_weight_long(kind & HWLOC_DISTANCES_KIND_MEANS_ALL) != 1
|
||||
|| (flags & ~HWLOC_DISTANCES_FLAG_ALL)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* no strict need to check for duplicates, things shouldn't break */
|
||||
|
||||
type = objs[0]->type;
|
||||
if (type == HWLOC_OBJ_GROUP) {
|
||||
/* not supported yet, would require we save the subkind together with the type. */
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i=1; i<nbobjs; i++)
|
||||
if (!objs[i] || objs[i]->type != type) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* copy the input arrays and give them to the topology */
|
||||
_objs = malloc(nbobjs*sizeof(hwloc_obj_t));
|
||||
_values = malloc(nbobjs*nbobjs*sizeof(*_values));
|
||||
if (!_objs || !_values)
|
||||
goto out_with_arrays;
|
||||
|
||||
memcpy(_objs, objs, nbobjs*sizeof(hwloc_obj_t));
|
||||
memcpy(_values, values, nbobjs*nbobjs*sizeof(*_values));
|
||||
err = hwloc_internal_distances_add(topology, nbobjs, _objs, _values, kind, flags);
|
||||
if (err < 0)
|
||||
goto out; /* _objs and _values freed in hwloc_internal_distances_add() */
|
||||
|
||||
/* in case we added some groups, see if we need to reconnect */
|
||||
hwloc_topology_reconnect(topology, 0);
|
||||
|
||||
return 0;
|
||||
|
||||
out_with_arrays:
|
||||
free(_values);
|
||||
free(_objs);
|
||||
out:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* Refresh objects in distances
|
||||
*/
|
||||
|
||||
static hwloc_obj_t hwloc_find_obj_by_type_and_gp_index(hwloc_topology_t topology, hwloc_obj_type_t type, uint64_t gp_index)
|
||||
{
|
||||
hwloc_obj_t obj = hwloc_get_obj_by_type(topology, type, 0);
|
||||
while (obj) {
|
||||
if (obj->gp_index == gp_index)
|
||||
return obj;
|
||||
obj = obj->next_cousin;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_internal_distances_restrict(struct hwloc_internal_distances_s *dist,
|
||||
hwloc_obj_t *objs,
|
||||
unsigned disappeared)
|
||||
{
|
||||
unsigned nbobjs = dist->nbobjs;
|
||||
unsigned i, newi;
|
||||
unsigned j, newj;
|
||||
|
||||
for(i=0, newi=0; i<nbobjs; i++)
|
||||
if (objs[i]) {
|
||||
for(j=0, newj=0; j<nbobjs; j++)
|
||||
if (objs[j]) {
|
||||
dist->values[newi*(nbobjs-disappeared)+newj] = dist->values[i*nbobjs+j];
|
||||
newj++;
|
||||
}
|
||||
newi++;
|
||||
}
|
||||
|
||||
for(i=0, newi=0; i<nbobjs; i++)
|
||||
if (objs[i]) {
|
||||
objs[newi] = objs[i];
|
||||
dist->indexes[newi] = dist->indexes[i];
|
||||
newi++;
|
||||
}
|
||||
|
||||
dist->nbobjs -= disappeared;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_internal_distances_refresh_one(hwloc_topology_t topology,
|
||||
struct hwloc_internal_distances_s *dist)
|
||||
{
|
||||
hwloc_obj_type_t type = dist->type;
|
||||
unsigned nbobjs = dist->nbobjs;
|
||||
hwloc_obj_t *objs = dist->objs;
|
||||
uint64_t *indexes = dist->indexes;
|
||||
unsigned disappeared = 0;
|
||||
unsigned i;
|
||||
|
||||
if (dist->objs_are_valid)
|
||||
return 0;
|
||||
|
||||
for(i=0; i<nbobjs; i++) {
|
||||
hwloc_obj_t obj;
|
||||
/* TODO use cpuset/nodeset to find pus/numas from the root?
|
||||
* faster than traversing the entire level?
|
||||
*/
|
||||
if (type == HWLOC_OBJ_PU)
|
||||
obj = hwloc_get_pu_obj_by_os_index(topology, (unsigned) indexes[i]);
|
||||
else if (type == HWLOC_OBJ_NUMANODE)
|
||||
obj = hwloc_get_numanode_obj_by_os_index(topology, (unsigned) indexes[i]);
|
||||
else
|
||||
obj = hwloc_find_obj_by_type_and_gp_index(topology, type, indexes[i]);
|
||||
objs[i] = obj;
|
||||
if (!obj)
|
||||
disappeared++;
|
||||
}
|
||||
|
||||
if (nbobjs-disappeared < 2)
|
||||
/* became useless, drop */
|
||||
return -1;
|
||||
|
||||
if (disappeared)
|
||||
hwloc_internal_distances_restrict(dist, objs, disappeared);
|
||||
|
||||
dist->objs_are_valid = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_internal_distances_refresh(hwloc_topology_t topology)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist, *next;
|
||||
|
||||
for(dist = topology->first_dist; dist; dist = next) {
|
||||
next = dist->next;
|
||||
|
||||
if (hwloc_internal_distances_refresh_one(topology, dist) < 0) {
|
||||
if (dist->prev)
|
||||
dist->prev->next = next;
|
||||
else
|
||||
topology->first_dist = next;
|
||||
if (next)
|
||||
next->prev = dist->prev;
|
||||
else
|
||||
topology->last_dist = dist->prev;
|
||||
hwloc_internal_distances_free(dist);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_internal_distances_invalidate_cached_objs(hwloc_topology_t topology)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist;
|
||||
for(dist = topology->first_dist; dist; dist = dist->next)
|
||||
dist->objs_are_valid = 0;
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* User API for getting distances
|
||||
*/
|
||||
|
||||
void
|
||||
hwloc_distances_release(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
struct hwloc_distances_s *distances)
|
||||
{
|
||||
free(distances->values);
|
||||
free(distances->objs);
|
||||
free(distances);
|
||||
}
|
||||
|
||||
static struct hwloc_distances_s *
|
||||
hwloc_distances_get_one(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
struct hwloc_internal_distances_s *dist)
|
||||
{
|
||||
struct hwloc_distances_s *distances;
|
||||
unsigned nbobjs;
|
||||
|
||||
distances = malloc(sizeof(*distances));
|
||||
if (!distances)
|
||||
return NULL;
|
||||
|
||||
nbobjs = distances->nbobjs = dist->nbobjs;
|
||||
|
||||
distances->objs = malloc(nbobjs * sizeof(hwloc_obj_t));
|
||||
if (!distances->objs)
|
||||
goto out;
|
||||
memcpy(distances->objs, dist->objs, nbobjs * sizeof(hwloc_obj_t));
|
||||
|
||||
distances->values = malloc(nbobjs * nbobjs * sizeof(*distances->values));
|
||||
if (!distances->values)
|
||||
goto out_with_objs;
|
||||
memcpy(distances->values, dist->values, nbobjs*nbobjs*sizeof(*distances->values));
|
||||
|
||||
distances->kind = dist->kind;
|
||||
return distances;
|
||||
|
||||
out_with_objs:
|
||||
free(distances->objs);
|
||||
out:
|
||||
free(distances);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__distances_get(hwloc_topology_t topology,
|
||||
hwloc_obj_type_t type,
|
||||
unsigned *nrp, struct hwloc_distances_s **distancesp,
|
||||
unsigned long kind, unsigned long flags __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_internal_distances_s *dist;
|
||||
unsigned nr = 0, i;
|
||||
|
||||
/* We could return the internal arrays (as const),
|
||||
* but it would require to prevent removing distances between get() and free().
|
||||
* Not performance critical anyway.
|
||||
*/
|
||||
|
||||
if (flags) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* we could refresh only the distances that match, but we won't have many distances anyway,
|
||||
* so performance is totally negligible.
|
||||
*/
|
||||
hwloc_internal_distances_refresh(topology);
|
||||
|
||||
for(dist = topology->first_dist; dist; dist = dist->next) {
|
||||
unsigned long kind_from = kind & HWLOC_DISTANCES_KIND_FROM_ALL;
|
||||
unsigned long kind_means = kind & HWLOC_DISTANCES_KIND_MEANS_ALL;
|
||||
|
||||
if (type != HWLOC_OBJ_TYPE_NONE && type != dist->type)
|
||||
continue;
|
||||
|
||||
if (kind_from && !(kind_from & dist->kind))
|
||||
continue;
|
||||
if (kind_means && !(kind_means & dist->kind))
|
||||
continue;
|
||||
|
||||
if (nr < *nrp) {
|
||||
struct hwloc_distances_s *distances = hwloc_distances_get_one(topology, dist);
|
||||
if (!distances)
|
||||
goto error;
|
||||
distancesp[nr] = distances;
|
||||
}
|
||||
nr++;
|
||||
}
|
||||
|
||||
for(i=nr; i<*nrp; i++)
|
||||
distancesp[i] = NULL;
|
||||
*nrp = nr;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
for(i=0; i<nr; i++)
|
||||
hwloc_distances_release(topology, distancesp[i]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_distances_get(hwloc_topology_t topology,
|
||||
unsigned *nrp, struct hwloc_distances_s **distancesp,
|
||||
unsigned long kind, unsigned long flags)
|
||||
{
|
||||
if (flags || !topology->is_loaded) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return hwloc__distances_get(topology, HWLOC_OBJ_TYPE_NONE, nrp, distancesp, kind, flags);
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_distances_get_by_depth(hwloc_topology_t topology, unsigned depth,
|
||||
unsigned *nrp, struct hwloc_distances_s **distancesp,
|
||||
unsigned long kind, unsigned long flags)
|
||||
{
|
||||
hwloc_obj_type_t type;
|
||||
|
||||
if (flags || !topology->is_loaded) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* switch back to types since we don't support groups for now */
|
||||
type = hwloc_get_depth_type(topology, depth);
|
||||
if (type == (hwloc_obj_type_t)-1) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return hwloc__distances_get(topology, type, nrp, distancesp, kind, flags);
|
||||
}
|
||||
|
||||
/******************************************************
|
||||
* Grouping objects according to distances
|
||||
*/
|
||||
|
||||
static void hwloc_report_user_distance_error(const char *msg, int line)
|
||||
{
|
||||
static int reported = 0;
|
||||
|
||||
if (!reported && !hwloc_hide_errors()) {
|
||||
fprintf(stderr, "****************************************************************************\n");
|
||||
fprintf(stderr, "* hwloc %s has encountered what looks like an error from user-given distances.\n", HWLOC_VERSION);
|
||||
fprintf(stderr, "*\n");
|
||||
fprintf(stderr, "* %s\n", msg);
|
||||
fprintf(stderr, "* Error occurred in topology.c line %d\n", line);
|
||||
fprintf(stderr, "*\n");
|
||||
fprintf(stderr, "* Please make sure that distances given through the interface or environment\n");
|
||||
fprintf(stderr, "* variables do not contradict any other topology information.\n");
|
||||
fprintf(stderr, "****************************************************************************\n");
|
||||
reported = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int hwloc_compare_values(uint64_t a, uint64_t b, float accuracy)
|
||||
{
|
||||
if (accuracy != 0.0f && fabsf((float)a-(float)b) < (float)a * accuracy)
|
||||
return 0;
|
||||
return a < b ? -1 : a == b ? 0 : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Place objects in groups if they are in a transitive graph of minimal values.
|
||||
* Return how many groups were created, or 0 if some incomplete distance graphs were found.
|
||||
*/
|
||||
static unsigned
|
||||
hwloc__find_groups_by_min_distance(unsigned nbobjs,
|
||||
uint64_t *_values,
|
||||
float accuracy,
|
||||
unsigned *groupids,
|
||||
int verbose)
|
||||
{
|
||||
uint64_t min_distance = UINT64_MAX;
|
||||
unsigned groupid = 1;
|
||||
unsigned i,j,k;
|
||||
unsigned skipped = 0;
|
||||
|
||||
#define VALUE(i, j) _values[(i) * nbobjs + (j)]
|
||||
|
||||
memset(groupids, 0, nbobjs*sizeof(*groupids));
|
||||
|
||||
/* find the minimal distance */
|
||||
for(i=0; i<nbobjs; i++)
|
||||
for(j=0; j<nbobjs; j++) /* check the entire matrix, it may not be perfectly symmetric depending on the accuracy */
|
||||
if (i != j && VALUE(i, j) < min_distance) /* no accuracy here, we want the real minimal */
|
||||
min_distance = VALUE(i, j);
|
||||
hwloc_debug(" found minimal distance %llu between objects\n", (unsigned long long) min_distance);
|
||||
|
||||
if (min_distance == UINT64_MAX)
|
||||
return 0;
|
||||
|
||||
/* build groups of objects connected with this distance */
|
||||
for(i=0; i<nbobjs; i++) {
|
||||
unsigned size;
|
||||
int firstfound;
|
||||
|
||||
/* if already grouped, skip */
|
||||
if (groupids[i])
|
||||
continue;
|
||||
|
||||
/* start a new group */
|
||||
groupids[i] = groupid;
|
||||
size = 1;
|
||||
firstfound = i;
|
||||
|
||||
while (firstfound != -1) {
|
||||
/* we added new objects to the group, the first one was firstfound.
|
||||
* rescan all connections from these new objects (starting at first found) to any other objects,
|
||||
* so as to find new objects minimally-connected by transivity.
|
||||
*/
|
||||
int newfirstfound = -1;
|
||||
for(j=firstfound; j<nbobjs; j++)
|
||||
if (groupids[j] == groupid)
|
||||
for(k=0; k<nbobjs; k++)
|
||||
if (!groupids[k] && !hwloc_compare_values(VALUE(j, k), min_distance, accuracy)) {
|
||||
groupids[k] = groupid;
|
||||
size++;
|
||||
if (newfirstfound == -1)
|
||||
newfirstfound = k;
|
||||
if (i == j)
|
||||
hwloc_debug(" object %u is minimally connected to %u\n", k, i);
|
||||
else
|
||||
hwloc_debug(" object %u is minimally connected to %u through %u\n", k, i, j);
|
||||
}
|
||||
firstfound = newfirstfound;
|
||||
}
|
||||
|
||||
if (size == 1) {
|
||||
/* cancel this useless group, ignore this object and try from the next one */
|
||||
groupids[i] = 0;
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* valid this group */
|
||||
groupid++;
|
||||
if (verbose)
|
||||
fprintf(stderr, " Found transitive graph with %u objects with minimal distance %llu accuracy %f\n",
|
||||
size, (unsigned long long) min_distance, accuracy);
|
||||
}
|
||||
|
||||
if (groupid == 2 && !skipped)
|
||||
/* we created a single group containing all objects, ignore it */
|
||||
return 0;
|
||||
|
||||
/* return the last id, since it's also the number of used group ids */
|
||||
return groupid-1;
|
||||
}
|
||||
|
||||
/* check that the matrix is ok */
|
||||
static int
|
||||
hwloc__check_grouping_matrix(unsigned nbobjs, uint64_t *_values, float accuracy, int verbose)
|
||||
{
|
||||
unsigned i,j;
|
||||
for(i=0; i<nbobjs; i++) {
|
||||
for(j=i+1; j<nbobjs; j++) {
|
||||
/* should be symmetric */
|
||||
if (hwloc_compare_values(VALUE(i, j), VALUE(j, i), accuracy)) {
|
||||
if (verbose)
|
||||
fprintf(stderr, " Distance matrix asymmetric ([%u,%u]=%llu != [%u,%u]=%llu), aborting\n",
|
||||
i, j, (unsigned long long) VALUE(i, j), j, i, (unsigned long long) VALUE(j, i));
|
||||
return -1;
|
||||
}
|
||||
/* diagonal is smaller than everything else */
|
||||
if (hwloc_compare_values(VALUE(i, j), VALUE(i, i), accuracy) <= 0) {
|
||||
if (verbose)
|
||||
fprintf(stderr, " Distance to self not strictly minimal ([%u,%u]=%llu <= [%u,%u]=%llu), aborting\n",
|
||||
i, j, (unsigned long long) VALUE(i, j), i, i, (unsigned long long) VALUE(i, i));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look at object physical distances to group them.
|
||||
*/
|
||||
static void
|
||||
hwloc__groups_by_distances(struct hwloc_topology *topology,
|
||||
unsigned nbobjs,
|
||||
struct hwloc_obj **objs,
|
||||
uint64_t *_values,
|
||||
unsigned long kind,
|
||||
unsigned nbaccuracies,
|
||||
float *accuracies,
|
||||
int needcheck)
|
||||
{
|
||||
unsigned *groupids = NULL;
|
||||
unsigned nbgroups = 0;
|
||||
unsigned i,j;
|
||||
int verbose = topology->grouping_verbose;
|
||||
|
||||
if (nbobjs <= 2)
|
||||
return;
|
||||
|
||||
if (!(kind & HWLOC_DISTANCES_KIND_MEANS_LATENCY))
|
||||
/* don't know use to use those for grouping */
|
||||
/* TODO hwloc__find_groups_by_max_distance() for bandwidth */
|
||||
return;
|
||||
|
||||
groupids = malloc(sizeof(unsigned) * nbobjs);
|
||||
if (NULL == groupids) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(i=0; i<nbaccuracies; i++) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Trying to group %u %s objects according to physical distances with accuracy %f\n",
|
||||
nbobjs, hwloc_type_name(objs[0]->type), accuracies[i]);
|
||||
if (needcheck && hwloc__check_grouping_matrix(nbobjs, _values, accuracies[i], verbose) < 0)
|
||||
continue;
|
||||
nbgroups = hwloc__find_groups_by_min_distance(nbobjs, _values, accuracies[i], groupids, verbose);
|
||||
if (nbgroups)
|
||||
break;
|
||||
}
|
||||
if (!nbgroups)
|
||||
goto outter_free;
|
||||
|
||||
/* For convenience, put these declarations inside a block. It's a
|
||||
crying shame we can't use C99 syntax here, and have to do a bunch
|
||||
of mallocs. :-( */
|
||||
{
|
||||
hwloc_obj_t *groupobjs = NULL;
|
||||
unsigned *groupsizes = NULL;
|
||||
uint64_t *groupvalues = NULL;
|
||||
unsigned failed = 0;
|
||||
|
||||
groupobjs = malloc(sizeof(hwloc_obj_t) * nbgroups);
|
||||
groupsizes = malloc(sizeof(unsigned) * nbgroups);
|
||||
groupvalues = malloc(sizeof(uint64_t) * nbgroups * nbgroups);
|
||||
if (NULL == groupobjs || NULL == groupsizes || NULL == groupvalues) {
|
||||
goto inner_free;
|
||||
}
|
||||
/* create new Group objects and record their size */
|
||||
memset(&(groupsizes[0]), 0, sizeof(groupsizes[0]) * nbgroups);
|
||||
for(i=0; i<nbgroups; i++) {
|
||||
/* create the Group object */
|
||||
hwloc_obj_t group_obj, res_obj;
|
||||
group_obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_GROUP, -1);
|
||||
group_obj->cpuset = hwloc_bitmap_alloc();
|
||||
group_obj->attr->group.kind = HWLOC_GROUP_KIND_DISTANCE;
|
||||
group_obj->attr->group.subkind = topology->grouping_next_subkind;
|
||||
for (j=0; j<nbobjs; j++)
|
||||
if (groupids[j] == i+1) {
|
||||
/* assemble the group sets */
|
||||
hwloc_obj_add_other_obj_sets(group_obj, objs[j]);
|
||||
groupsizes[i]++;
|
||||
}
|
||||
hwloc_debug_1arg_bitmap("adding Group object with %u objects and cpuset %s\n",
|
||||
groupsizes[i], group_obj->cpuset);
|
||||
res_obj = hwloc__insert_object_by_cpuset(topology, group_obj,
|
||||
(kind & HWLOC_DISTANCES_KIND_FROM_USER) ? hwloc_report_user_distance_error : hwloc_report_os_error);
|
||||
/* res_obj may be NULL on failure to insert. */
|
||||
if (!res_obj)
|
||||
failed++;
|
||||
/* or it may be different from groupobjs if we got groups from XML import before grouping */
|
||||
groupobjs[i] = res_obj;
|
||||
}
|
||||
topology->grouping_next_subkind++;
|
||||
|
||||
if (failed)
|
||||
/* don't try to group above if we got a NULL group here, just keep this incomplete level */
|
||||
goto inner_free;
|
||||
|
||||
/* factorize values */
|
||||
memset(&(groupvalues[0]), 0, sizeof(groupvalues[0]) * nbgroups * nbgroups);
|
||||
#undef VALUE
|
||||
#define VALUE(i, j) _values[(i) * nbobjs + (j)]
|
||||
#define GROUP_VALUE(i, j) groupvalues[(i) * nbgroups + (j)]
|
||||
for(i=0; i<nbobjs; i++)
|
||||
if (groupids[i])
|
||||
for(j=0; j<nbobjs; j++)
|
||||
if (groupids[j])
|
||||
GROUP_VALUE(groupids[i]-1, groupids[j]-1) += VALUE(i, j);
|
||||
for(i=0; i<nbgroups; i++)
|
||||
for(j=0; j<nbgroups; j++) {
|
||||
unsigned groupsize = groupsizes[i]*groupsizes[j];
|
||||
GROUP_VALUE(i, j) /= groupsize;
|
||||
}
|
||||
#ifdef HWLOC_DEBUG
|
||||
hwloc_debug("%s", "generated new distance matrix between groups:\n");
|
||||
hwloc_debug("%s", " index");
|
||||
for(j=0; j<nbgroups; j++)
|
||||
hwloc_debug(" % 5d", (int) j); /* print index because os_index is -1 for Groups */
|
||||
hwloc_debug("%s", "\n");
|
||||
for(i=0; i<nbgroups; i++) {
|
||||
hwloc_debug(" % 5d", (int) i);
|
||||
for(j=0; j<nbgroups; j++)
|
||||
hwloc_debug(" %llu", (unsigned long long) GROUP_VALUE(i, j));
|
||||
hwloc_debug("%s", "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
hwloc__groups_by_distances(topology, nbgroups, groupobjs, groupvalues, kind, nbaccuracies, accuracies, 0 /* no need to check generated matrix */);
|
||||
|
||||
inner_free:
|
||||
/* Safely free everything */
|
||||
free(groupobjs);
|
||||
free(groupsizes);
|
||||
free(groupvalues);
|
||||
}
|
||||
|
||||
outter_free:
|
||||
free(groupids);
|
||||
}
|
47
opal/mca/hwloc/hwloc2x/hwloc/hwloc/dolib.c
Обычный файл
47
opal/mca/hwloc/hwloc2x/hwloc/hwloc/dolib.c
Обычный файл
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009 inria. All rights reserved.
|
||||
* Copyright © 2009, 2012 Université Bordeaux
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/* Wrapper to avoid msys' tendency to turn / into \ and : into ; */
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *prog, *arch, *def, *version, *lib;
|
||||
char s[1024];
|
||||
char name[16];
|
||||
int current, age, revision;
|
||||
|
||||
if (argc != 6) {
|
||||
fprintf(stderr,"bad number of arguments");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
prog = argv[1];
|
||||
arch = argv[2];
|
||||
def = argv[3];
|
||||
version = argv[4];
|
||||
lib = argv[5];
|
||||
|
||||
if (sscanf(version, "%d:%d:%d", ¤t, &revision, &age) != 3)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
_snprintf(name, sizeof(name), "libhwloc-%d", current - age);
|
||||
printf("using soname %s\n", name);
|
||||
|
||||
_snprintf(s, sizeof(s), "\"%s\" /machine:%s /def:%s /name:%s /out:%s",
|
||||
prog, arch, def, name, lib);
|
||||
if (system(s)) {
|
||||
fprintf(stderr, "%s failed\n", s);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
166
opal/mca/hwloc/hwloc2x/hwloc/hwloc/misc.c
Обычный файл
166
opal/mca/hwloc/hwloc2x/hwloc/hwloc/misc.c
Обычный файл
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2015 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <private/private.h>
|
||||
#include <private/misc.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#ifdef HAVE_SYS_UTSNAME_H
|
||||
#include <sys/utsname.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef HAVE_PROGRAM_INVOCATION_NAME
|
||||
#include <errno.h>
|
||||
extern char *program_invocation_name;
|
||||
#endif
|
||||
#ifdef HAVE___PROGNAME
|
||||
extern char *__progname;
|
||||
#endif
|
||||
|
||||
int hwloc_snprintf(char *str, size_t size, const char *format, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list ap;
|
||||
static char bin;
|
||||
size_t fakesize;
|
||||
char *fakestr;
|
||||
|
||||
/* Some systems crash on str == NULL */
|
||||
if (!size) {
|
||||
str = &bin;
|
||||
size = 1;
|
||||
}
|
||||
|
||||
va_start(ap, format);
|
||||
ret = vsnprintf(str, size, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (ret >= 0 && (size_t) ret != size-1)
|
||||
return ret;
|
||||
|
||||
/* vsnprintf returned size-1 or -1. That could be a system which reports the
|
||||
* written data and not the actually required room. Try increasing buffer
|
||||
* size to get the latter. */
|
||||
|
||||
fakesize = size;
|
||||
fakestr = NULL;
|
||||
do {
|
||||
fakesize *= 2;
|
||||
free(fakestr);
|
||||
fakestr = malloc(fakesize);
|
||||
if (NULL == fakestr)
|
||||
return -1;
|
||||
va_start(ap, format);
|
||||
errno = 0;
|
||||
ret = vsnprintf(fakestr, fakesize, format, ap);
|
||||
va_end(ap);
|
||||
} while ((size_t) ret == fakesize-1 || (ret < 0 && (!errno || errno == ERANGE)));
|
||||
|
||||
if (ret >= 0 && size) {
|
||||
if (size > (size_t) ret+1)
|
||||
size = ret+1;
|
||||
memcpy(str, fakestr, size-1);
|
||||
str[size-1] = 0;
|
||||
}
|
||||
free(fakestr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hwloc_namecoloncmp(const char *haystack, const char *needle, size_t n)
|
||||
{
|
||||
size_t i = 0;
|
||||
while (*haystack && *haystack != ':') {
|
||||
int ha = *haystack++;
|
||||
int low_h = tolower(ha);
|
||||
int ne = *needle++;
|
||||
int low_n = tolower(ne);
|
||||
if (low_h != low_n)
|
||||
return 1;
|
||||
i++;
|
||||
}
|
||||
return i < n;
|
||||
}
|
||||
|
||||
void hwloc_add_uname_info(struct hwloc_topology *topology __hwloc_attribute_unused,
|
||||
void *cached_uname __hwloc_attribute_unused)
|
||||
{
|
||||
#ifdef HAVE_UNAME
|
||||
struct utsname _utsname, *utsname;
|
||||
|
||||
if (hwloc_obj_get_info_by_name(topology->levels[0][0], "OSName"))
|
||||
/* don't annotate twice */
|
||||
return;
|
||||
|
||||
if (cached_uname)
|
||||
utsname = (struct utsname *) cached_uname;
|
||||
else {
|
||||
utsname = &_utsname;
|
||||
if (uname(utsname) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
if (*utsname->sysname)
|
||||
hwloc_obj_add_info(topology->levels[0][0], "OSName", utsname->sysname);
|
||||
if (*utsname->release)
|
||||
hwloc_obj_add_info(topology->levels[0][0], "OSRelease", utsname->release);
|
||||
if (*utsname->version)
|
||||
hwloc_obj_add_info(topology->levels[0][0], "OSVersion", utsname->version);
|
||||
if (*utsname->nodename)
|
||||
hwloc_obj_add_info(topology->levels[0][0], "HostName", utsname->nodename);
|
||||
if (*utsname->machine)
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Architecture", utsname->machine);
|
||||
#endif /* HAVE_UNAME */
|
||||
}
|
||||
|
||||
char *
|
||||
hwloc_progname(struct hwloc_topology *topology __hwloc_attribute_unused)
|
||||
{
|
||||
#if HAVE_DECL_GETMODULEFILENAME
|
||||
char name[256], *basename;
|
||||
unsigned res = GetModuleFileName(NULL, name, sizeof(name));
|
||||
if (res == sizeof(name) || !res)
|
||||
return NULL;
|
||||
basename = strrchr(name, '\\');
|
||||
if (!basename)
|
||||
basename = name;
|
||||
else
|
||||
basename++;
|
||||
return strdup(basename);
|
||||
#else /* !HAVE_GETMODULEFILENAME */
|
||||
const char *name, *basename;
|
||||
#if HAVE_DECL_GETPROGNAME
|
||||
name = getprogname(); /* FreeBSD, NetBSD, some Solaris */
|
||||
#elif HAVE_DECL_GETEXECNAME
|
||||
name = getexecname(); /* Solaris */
|
||||
#elif defined HAVE_PROGRAM_INVOCATION_NAME
|
||||
name = program_invocation_name; /* Glibc. BGQ CNK. */
|
||||
/* could use program_invocation_short_name directly, but we have the code to remove the path below anyway */
|
||||
#elif defined HAVE___PROGNAME
|
||||
name = __progname; /* fallback for most unix, used for OpenBSD */
|
||||
#else
|
||||
/* TODO: _NSGetExecutablePath(path, &size) on Darwin */
|
||||
/* TODO: AIX, HPUX */
|
||||
name = NULL;
|
||||
#endif
|
||||
if (!name)
|
||||
return NULL;
|
||||
basename = strrchr(name, '/');
|
||||
if (!basename)
|
||||
basename = name;
|
||||
else
|
||||
basename++;
|
||||
return strdup(basename);
|
||||
#endif /* !HAVE_GETMODULEFILENAME */
|
||||
}
|
954
opal/mca/hwloc/hwloc2x/hwloc/hwloc/pci-common.c
Обычный файл
954
opal/mca/hwloc/hwloc2x/hwloc/hwloc/pci-common.c
Обычный файл
@ -0,0 +1,954 @@
|
||||
/*
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/plugins.h>
|
||||
#include <private/private.h>
|
||||
#include <private/debug.h>
|
||||
#include <private/misc.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HWLOC_WIN_SYS
|
||||
#include <io.h>
|
||||
#define open _open
|
||||
#define read _read
|
||||
#define close _close
|
||||
#endif
|
||||
|
||||
static void
|
||||
hwloc_pci_forced_locality_parse_one(struct hwloc_topology *topology,
|
||||
const char *string /* must contain a ' ' */,
|
||||
unsigned *allocated)
|
||||
{
|
||||
unsigned nr = topology->pci_forced_locality_nr;
|
||||
unsigned domain, bus_first, bus_last, dummy;
|
||||
hwloc_bitmap_t set;
|
||||
char *tmp;
|
||||
|
||||
if (sscanf(string, "%x:%x-%x %x", &domain, &bus_first, &bus_last, &dummy) == 4) {
|
||||
/* fine */
|
||||
} else if (sscanf(string, "%x:%x %x", &domain, &bus_first, &dummy) == 3) {
|
||||
bus_last = bus_first;
|
||||
} else if (sscanf(string, "%x %x", &domain, &dummy) == 2) {
|
||||
bus_first = 0;
|
||||
bus_last = 255;
|
||||
} else
|
||||
return;
|
||||
|
||||
tmp = strchr(string, ' ');
|
||||
if (!tmp)
|
||||
return;
|
||||
tmp++;
|
||||
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_sscanf(set, tmp);
|
||||
|
||||
if (!*allocated) {
|
||||
topology->pci_forced_locality = malloc(sizeof(*topology->pci_forced_locality));
|
||||
if (!topology->pci_forced_locality)
|
||||
goto out_with_set; /* failed to allocate, ignore this forced locality */
|
||||
*allocated = 1;
|
||||
} else if (nr >= *allocated) {
|
||||
struct hwloc_pci_forced_locality_s *tmplocs;
|
||||
tmplocs = realloc(topology->pci_forced_locality,
|
||||
2 * *allocated * sizeof(*topology->pci_forced_locality));
|
||||
if (!tmplocs)
|
||||
goto out_with_set; /* failed to allocate, ignore this forced locality */
|
||||
topology->pci_forced_locality = tmplocs;
|
||||
*allocated *= 2;
|
||||
}
|
||||
|
||||
topology->pci_forced_locality[nr].domain = domain;
|
||||
topology->pci_forced_locality[nr].bus_first = bus_first;
|
||||
topology->pci_forced_locality[nr].bus_last = bus_last;
|
||||
topology->pci_forced_locality[nr].cpuset = set;
|
||||
topology->pci_forced_locality_nr++;
|
||||
return;
|
||||
|
||||
out_with_set:
|
||||
hwloc_bitmap_free(set);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci_forced_locality_parse(struct hwloc_topology *topology, const char *_env)
|
||||
{
|
||||
char *env = strdup(_env);
|
||||
unsigned allocated = 0;
|
||||
char *tmp = env;
|
||||
|
||||
while (1) {
|
||||
size_t len = strcspn(tmp, ";\r\n");
|
||||
char *next = NULL;
|
||||
|
||||
if (tmp[len] != '\0') {
|
||||
tmp[len] = '\0';
|
||||
if (tmp[len+1] != '\0')
|
||||
next = &tmp[len]+1;
|
||||
}
|
||||
|
||||
hwloc_pci_forced_locality_parse_one(topology, tmp, &allocated);
|
||||
|
||||
if (next)
|
||||
tmp = next;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
free(env);
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_pci_discovery_init(struct hwloc_topology *topology)
|
||||
{
|
||||
topology->pci_nonzero_domains = 0;
|
||||
topology->need_pci_belowroot_apply_locality = 0;
|
||||
|
||||
topology->pci_has_forced_locality = 0;
|
||||
topology->pci_forced_locality_nr = 0;
|
||||
topology->pci_forced_locality = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_pci_discovery_prepare(struct hwloc_topology *topology)
|
||||
{
|
||||
char *env;
|
||||
|
||||
env = getenv("HWLOC_PCI_LOCALITY");
|
||||
if (env) {
|
||||
int fd;
|
||||
|
||||
topology->pci_has_forced_locality = 1;
|
||||
|
||||
fd = open(env, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
struct stat st;
|
||||
char *buffer;
|
||||
int err = fstat(fd, &st);
|
||||
if (!err) {
|
||||
if (st.st_size <= 64*1024) { /* random limit large enough to store multiple cpusets for thousands of PUs */
|
||||
buffer = malloc(st.st_size+1);
|
||||
if (read(fd, buffer, st.st_size) == st.st_size) {
|
||||
buffer[st.st_size] = '\0';
|
||||
hwloc_pci_forced_locality_parse(topology, buffer);
|
||||
}
|
||||
free(buffer);
|
||||
} else {
|
||||
fprintf(stderr, "Ignoring HWLOC_PCI_LOCALITY file `%s' too large (%lu bytes)\n",
|
||||
env, (unsigned long) st.st_size);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
} else
|
||||
hwloc_pci_forced_locality_parse(topology, env);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_pci_discovery_exit(struct hwloc_topology *topology __hwloc_attribute_unused)
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<topology->pci_forced_locality_nr; i++)
|
||||
hwloc_bitmap_free(topology->pci_forced_locality[i].cpuset);
|
||||
free(topology->pci_forced_locality);
|
||||
|
||||
hwloc_pci_discovery_init(topology);
|
||||
}
|
||||
|
||||
#ifdef HWLOC_DEBUG
|
||||
static void
|
||||
hwloc_pci_traverse_print_cb(void * cbdata __hwloc_attribute_unused,
|
||||
struct hwloc_obj *pcidev)
|
||||
{
|
||||
char busid[14];
|
||||
hwloc_obj_t parent;
|
||||
|
||||
/* indent */
|
||||
parent = pcidev->parent;
|
||||
while (parent) {
|
||||
hwloc_debug("%s", " ");
|
||||
parent = parent->parent;
|
||||
}
|
||||
|
||||
snprintf(busid, sizeof(busid), "%04x:%02x:%02x.%01x",
|
||||
pcidev->attr->pcidev.domain, pcidev->attr->pcidev.bus, pcidev->attr->pcidev.dev, pcidev->attr->pcidev.func);
|
||||
|
||||
if (pcidev->type == HWLOC_OBJ_BRIDGE) {
|
||||
if (pcidev->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_HOST)
|
||||
hwloc_debug("HostBridge");
|
||||
else
|
||||
hwloc_debug("%s Bridge [%04x:%04x]", busid,
|
||||
pcidev->attr->pcidev.vendor_id, pcidev->attr->pcidev.device_id);
|
||||
hwloc_debug(" to %04x:[%02x:%02x]\n",
|
||||
pcidev->attr->bridge.downstream.pci.domain, pcidev->attr->bridge.downstream.pci.secondary_bus, pcidev->attr->bridge.downstream.pci.subordinate_bus);
|
||||
} else
|
||||
hwloc_debug("%s Device [%04x:%04x (%04x:%04x) rev=%02x class=%04x]\n", busid,
|
||||
pcidev->attr->pcidev.vendor_id, pcidev->attr->pcidev.device_id,
|
||||
pcidev->attr->pcidev.subvendor_id, pcidev->attr->pcidev.subdevice_id,
|
||||
pcidev->attr->pcidev.revision, pcidev->attr->pcidev.class_id);
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci__traverse(void * cbdata, struct hwloc_obj *tree,
|
||||
void (*cb)(void * cbdata, struct hwloc_obj *))
|
||||
{
|
||||
struct hwloc_obj *child = tree;
|
||||
while (child) {
|
||||
cb(cbdata, child);
|
||||
if (child->type == HWLOC_OBJ_BRIDGE && child->io_first_child)
|
||||
hwloc_pci__traverse(cbdata, child->io_first_child, cb);
|
||||
child = child->next_sibling;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci_traverse(void * cbdata, struct hwloc_obj *tree,
|
||||
void (*cb)(void * cbdata, struct hwloc_obj *))
|
||||
{
|
||||
hwloc_pci__traverse(cbdata, tree, cb);
|
||||
}
|
||||
#endif /* HWLOC_DEBUG */
|
||||
|
||||
enum hwloc_pci_busid_comparison_e {
|
||||
HWLOC_PCI_BUSID_LOWER,
|
||||
HWLOC_PCI_BUSID_HIGHER,
|
||||
HWLOC_PCI_BUSID_INCLUDED,
|
||||
HWLOC_PCI_BUSID_SUPERSET
|
||||
};
|
||||
|
||||
static enum hwloc_pci_busid_comparison_e
|
||||
hwloc_pci_compare_busids(struct hwloc_obj *a, struct hwloc_obj *b)
|
||||
{
|
||||
#ifdef HWLOC_DEBUG
|
||||
if (a->type == HWLOC_OBJ_BRIDGE)
|
||||
assert(a->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI);
|
||||
if (b->type == HWLOC_OBJ_BRIDGE)
|
||||
assert(b->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI);
|
||||
#endif
|
||||
|
||||
if (a->attr->pcidev.domain < b->attr->pcidev.domain)
|
||||
return HWLOC_PCI_BUSID_LOWER;
|
||||
if (a->attr->pcidev.domain > b->attr->pcidev.domain)
|
||||
return HWLOC_PCI_BUSID_HIGHER;
|
||||
|
||||
if (a->type == HWLOC_OBJ_BRIDGE
|
||||
&& b->attr->pcidev.bus >= a->attr->bridge.downstream.pci.secondary_bus
|
||||
&& b->attr->pcidev.bus <= a->attr->bridge.downstream.pci.subordinate_bus)
|
||||
return HWLOC_PCI_BUSID_SUPERSET;
|
||||
if (b->type == HWLOC_OBJ_BRIDGE
|
||||
&& a->attr->pcidev.bus >= b->attr->bridge.downstream.pci.secondary_bus
|
||||
&& a->attr->pcidev.bus <= b->attr->bridge.downstream.pci.subordinate_bus)
|
||||
return HWLOC_PCI_BUSID_INCLUDED;
|
||||
|
||||
if (a->attr->pcidev.bus < b->attr->pcidev.bus)
|
||||
return HWLOC_PCI_BUSID_LOWER;
|
||||
if (a->attr->pcidev.bus > b->attr->pcidev.bus)
|
||||
return HWLOC_PCI_BUSID_HIGHER;
|
||||
|
||||
if (a->attr->pcidev.dev < b->attr->pcidev.dev)
|
||||
return HWLOC_PCI_BUSID_LOWER;
|
||||
if (a->attr->pcidev.dev > b->attr->pcidev.dev)
|
||||
return HWLOC_PCI_BUSID_HIGHER;
|
||||
|
||||
if (a->attr->pcidev.func < b->attr->pcidev.func)
|
||||
return HWLOC_PCI_BUSID_LOWER;
|
||||
if (a->attr->pcidev.func > b->attr->pcidev.func)
|
||||
return HWLOC_PCI_BUSID_HIGHER;
|
||||
|
||||
/* Should never reach here. Abort on both debug builds and
|
||||
non-debug builds */
|
||||
assert(0);
|
||||
fprintf(stderr, "Bad assertion in hwloc %s:%d (aborting)\n", __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci_add_object(struct hwloc_obj *parent, struct hwloc_obj **parent_io_first_child_p, struct hwloc_obj *new)
|
||||
{
|
||||
struct hwloc_obj **curp, **childp;
|
||||
|
||||
curp = parent_io_first_child_p;
|
||||
while (*curp) {
|
||||
enum hwloc_pci_busid_comparison_e comp = hwloc_pci_compare_busids(new, *curp);
|
||||
switch (comp) {
|
||||
case HWLOC_PCI_BUSID_HIGHER:
|
||||
/* go further */
|
||||
curp = &(*curp)->next_sibling;
|
||||
continue;
|
||||
case HWLOC_PCI_BUSID_INCLUDED:
|
||||
/* insert new below current bridge */
|
||||
hwloc_pci_add_object(*curp, &(*curp)->io_first_child, new);
|
||||
return;
|
||||
case HWLOC_PCI_BUSID_LOWER:
|
||||
case HWLOC_PCI_BUSID_SUPERSET: {
|
||||
/* insert new before current */
|
||||
new->next_sibling = *curp;
|
||||
*curp = new;
|
||||
new->parent = parent;
|
||||
if (new->type == HWLOC_OBJ_BRIDGE) {
|
||||
/* look at remaining siblings and move some below new */
|
||||
childp = &new->io_first_child;
|
||||
curp = &new->next_sibling;
|
||||
while (*curp) {
|
||||
hwloc_obj_t cur = *curp;
|
||||
if (hwloc_pci_compare_busids(new, cur) == HWLOC_PCI_BUSID_LOWER) {
|
||||
/* this sibling remains under root, after new. */
|
||||
if (cur->attr->pcidev.domain > new->attr->pcidev.domain
|
||||
|| cur->attr->pcidev.bus > new->attr->bridge.downstream.pci.subordinate_bus)
|
||||
/* this sibling is even above new's subordinate bus, no other sibling could go below new */
|
||||
return;
|
||||
curp = &cur->next_sibling;
|
||||
} else {
|
||||
/* this sibling goes under new */
|
||||
*childp = cur;
|
||||
*curp = cur->next_sibling;
|
||||
(*childp)->parent = new;
|
||||
(*childp)->next_sibling = NULL;
|
||||
childp = &(*childp)->next_sibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* add to the end of the list if higher than everybody */
|
||||
new->parent = parent;
|
||||
new->next_sibling = NULL;
|
||||
*curp = new;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_pci_tree_insert_by_busid(struct hwloc_obj **treep,
|
||||
struct hwloc_obj *obj)
|
||||
{
|
||||
hwloc_pci_add_object(NULL /* no parent on top of tree */, treep, obj);
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_pci_tree_attach_belowroot(struct hwloc_topology *topology, struct hwloc_obj *old_tree)
|
||||
{
|
||||
struct hwloc_obj **next_hb_p;
|
||||
enum hwloc_type_filter_e bfilter;
|
||||
|
||||
if (!old_tree)
|
||||
/* found nothing, exit */
|
||||
return 0;
|
||||
|
||||
#ifdef HWLOC_DEBUG
|
||||
hwloc_debug("%s", "\nPCI hierarchy:\n");
|
||||
hwloc_pci_traverse(NULL, old_tree, hwloc_pci_traverse_print_cb);
|
||||
hwloc_debug("%s", "\n");
|
||||
#endif
|
||||
|
||||
next_hb_p = &hwloc_get_root_obj(topology)->io_first_child;
|
||||
while (*next_hb_p)
|
||||
next_hb_p = &((*next_hb_p)->next_sibling);
|
||||
|
||||
bfilter = topology->type_filter[HWLOC_OBJ_BRIDGE];
|
||||
if (bfilter == HWLOC_TYPE_FILTER_KEEP_NONE) {
|
||||
*next_hb_p = old_tree;
|
||||
topology->modified = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* tree points to all objects connected to any upstream bus in the machine.
|
||||
* We now create one real hostbridge object per upstream bus.
|
||||
* It's not actually a PCI device so we have to create it.
|
||||
*/
|
||||
while (old_tree) {
|
||||
/* start a new host bridge */
|
||||
struct hwloc_obj *hostbridge = hwloc_alloc_setup_object(topology, HWLOC_OBJ_BRIDGE, -1);
|
||||
struct hwloc_obj **dstnextp = &hostbridge->io_first_child;
|
||||
struct hwloc_obj **srcnextp = &old_tree;
|
||||
struct hwloc_obj *child = *srcnextp;
|
||||
unsigned short current_domain = child->attr->pcidev.domain;
|
||||
unsigned char current_bus = child->attr->pcidev.bus;
|
||||
unsigned char current_subordinate = current_bus;
|
||||
|
||||
hwloc_debug("Starting new PCI hostbridge %04x:%02x\n", current_domain, current_bus);
|
||||
|
||||
next_child:
|
||||
/* remove next child from tree */
|
||||
*srcnextp = child->next_sibling;
|
||||
/* append it to hostbridge */
|
||||
*dstnextp = child;
|
||||
child->parent = hostbridge;
|
||||
child->next_sibling = NULL;
|
||||
dstnextp = &child->next_sibling;
|
||||
|
||||
/* compute hostbridge secondary/subordinate buses */
|
||||
if (child->type == HWLOC_OBJ_BRIDGE
|
||||
&& child->attr->bridge.downstream.pci.subordinate_bus > current_subordinate)
|
||||
current_subordinate = child->attr->bridge.downstream.pci.subordinate_bus;
|
||||
|
||||
/* use next child if it has the same domains/bus */
|
||||
child = *srcnextp;
|
||||
if (child
|
||||
&& child->attr->pcidev.domain == current_domain
|
||||
&& child->attr->pcidev.bus == current_bus)
|
||||
goto next_child;
|
||||
|
||||
/* finish setting up this hostbridge */
|
||||
hostbridge->attr->bridge.upstream_type = HWLOC_OBJ_BRIDGE_HOST;
|
||||
hostbridge->attr->bridge.downstream_type = HWLOC_OBJ_BRIDGE_PCI;
|
||||
hostbridge->attr->bridge.downstream.pci.domain = current_domain;
|
||||
hostbridge->attr->bridge.downstream.pci.secondary_bus = current_bus;
|
||||
hostbridge->attr->bridge.downstream.pci.subordinate_bus = current_subordinate;
|
||||
hwloc_debug("New PCI hostbridge %04x:[%02x-%02x]\n",
|
||||
current_domain, current_bus, current_subordinate);
|
||||
|
||||
if (current_domain)
|
||||
topology->pci_nonzero_domains = 1;
|
||||
|
||||
*next_hb_p = hostbridge;
|
||||
next_hb_p = &hostbridge->next_sibling;
|
||||
topology->modified = 1; /* needed in case somebody reconnects levels before the core calls hwloc_pci_belowroot_apply_locality()
|
||||
* or if hwloc_pci_belowroot_apply_locality() keeps hostbridges below root.
|
||||
*/
|
||||
}
|
||||
|
||||
done:
|
||||
topology->need_pci_belowroot_apply_locality = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_obj *
|
||||
hwloc_pci_fixup_busid_parent(struct hwloc_topology *topology __hwloc_attribute_unused,
|
||||
struct hwloc_pcidev_attr_s *busid,
|
||||
struct hwloc_obj *parent)
|
||||
{
|
||||
/* Xeon E5v3 in cluster-on-die mode only have PCI on the first NUMA node of each package.
|
||||
* but many dual-processor host report the second PCI hierarchy on 2nd NUMA of first package.
|
||||
*/
|
||||
if (parent->depth >= 2
|
||||
&& parent->type == HWLOC_OBJ_NUMANODE
|
||||
&& parent->sibling_rank == 1 && parent->parent->arity == 2
|
||||
&& parent->parent->type == HWLOC_OBJ_PACKAGE
|
||||
&& parent->parent->sibling_rank == 0 && parent->parent->parent->arity == 2) {
|
||||
const char *cpumodel = hwloc_obj_get_info_by_name(parent->parent, "CPUModel");
|
||||
if (cpumodel && strstr(cpumodel, "Xeon")) {
|
||||
if (!hwloc_hide_errors()) {
|
||||
fprintf(stderr, "****************************************************************************\n");
|
||||
fprintf(stderr, "* hwloc %s has encountered an incorrect PCI locality information.\n", HWLOC_VERSION);
|
||||
fprintf(stderr, "* PCI bus %04x:%02x is supposedly close to 2nd NUMA node of 1st package,\n",
|
||||
busid->domain, busid->bus);
|
||||
fprintf(stderr, "* however hwloc believes this is impossible on this architecture.\n");
|
||||
fprintf(stderr, "* Therefore the PCI bus will be moved to 1st NUMA node of 2nd package.\n");
|
||||
fprintf(stderr, "*\n");
|
||||
fprintf(stderr, "* If you feel this fixup is wrong, disable it by setting in your environment\n");
|
||||
fprintf(stderr, "* HWLOC_PCI_%04x_%02x_LOCALCPUS= (empty value), and report the problem\n",
|
||||
busid->domain, busid->bus);
|
||||
fprintf(stderr, "* to the hwloc's user mailing list together with the XML output of lstopo.\n");
|
||||
fprintf(stderr, "*\n");
|
||||
fprintf(stderr, "* You may silence this message by setting HWLOC_HIDE_ERRORS=1 in your environment.\n");
|
||||
fprintf(stderr, "****************************************************************************\n");
|
||||
}
|
||||
return parent->parent->next_sibling->first_child;
|
||||
}
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
static struct hwloc_obj *
|
||||
hwloc__pci_find_busid_parent(struct hwloc_topology *topology, struct hwloc_pcidev_attr_s *busid)
|
||||
{
|
||||
hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_obj_t parent;
|
||||
int forced = 0;
|
||||
int noquirks = 0;
|
||||
unsigned i;
|
||||
int err;
|
||||
|
||||
/* try to match a forced locality */
|
||||
if (topology->pci_has_forced_locality) {
|
||||
for(i=0; i<topology->pci_forced_locality_nr; i++) {
|
||||
if (busid->domain == topology->pci_forced_locality[i].domain
|
||||
&& busid->bus >= topology->pci_forced_locality[i].bus_first
|
||||
&& busid->bus <= topology->pci_forced_locality[i].bus_last) {
|
||||
hwloc_bitmap_copy(cpuset, topology->pci_forced_locality[i].cpuset);
|
||||
forced = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* if pci locality was forced, even empty, don't let quirks change what the OS reports */
|
||||
noquirks = 1;
|
||||
}
|
||||
|
||||
/* deprecated force locality variables */
|
||||
if (!forced) {
|
||||
const char *env;
|
||||
char envname[256];
|
||||
/* override the cpuset with the environment if given */
|
||||
snprintf(envname, sizeof(envname), "HWLOC_PCI_%04x_%02x_LOCALCPUS",
|
||||
busid->domain, busid->bus);
|
||||
env = getenv(envname);
|
||||
if (env) {
|
||||
static int reported = 0;
|
||||
if (!topology->pci_has_forced_locality && !reported) {
|
||||
fprintf(stderr, "Environment variable %s is deprecated, please use HWLOC_PCI_LOCALITY instead.\n", env);
|
||||
reported = 1;
|
||||
}
|
||||
if (*env) {
|
||||
/* force the cpuset */
|
||||
hwloc_debug("Overriding localcpus using %s in the environment\n", envname);
|
||||
hwloc_bitmap_sscanf(cpuset, env);
|
||||
forced = 1;
|
||||
}
|
||||
/* if env exists, even empty, don't let quirks change what the OS reports */
|
||||
noquirks = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!forced) {
|
||||
/* get the cpuset by asking the OS backend. */
|
||||
struct hwloc_backend *backend = topology->get_pci_busid_cpuset_backend;
|
||||
if (backend)
|
||||
err = backend->get_pci_busid_cpuset(backend, busid, cpuset);
|
||||
else
|
||||
err = -1;
|
||||
if (err < 0)
|
||||
/* if we got nothing, assume this PCI bus is attached to the top of hierarchy */
|
||||
hwloc_bitmap_copy(cpuset, hwloc_topology_get_topology_cpuset(topology));
|
||||
}
|
||||
|
||||
hwloc_debug_bitmap("Attaching PCI tree to cpuset %s\n", cpuset);
|
||||
|
||||
parent = hwloc_find_insert_io_parent_by_complete_cpuset(topology, cpuset);
|
||||
if (parent) {
|
||||
if (!noquirks)
|
||||
/* We found a valid parent. Check that the OS didn't report invalid locality */
|
||||
parent = hwloc_pci_fixup_busid_parent(topology, busid, parent);
|
||||
} else {
|
||||
/* Fallback to root */
|
||||
parent = hwloc_get_root_obj(topology);
|
||||
}
|
||||
|
||||
hwloc_bitmap_free(cpuset);
|
||||
return parent;
|
||||
}
|
||||
|
||||
struct hwloc_obj *
|
||||
hwloc_pci_find_busid_parent(struct hwloc_topology *topology,
|
||||
unsigned domain, unsigned bus, unsigned dev, unsigned func)
|
||||
{
|
||||
struct hwloc_pcidev_attr_s busid;
|
||||
busid.domain = domain;
|
||||
busid.bus = bus;
|
||||
busid.dev = dev;
|
||||
busid.func = func;
|
||||
return hwloc__pci_find_busid_parent(topology, &busid);
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_pci_belowroot_apply_locality(struct hwloc_topology *topology)
|
||||
{
|
||||
struct hwloc_obj *root = hwloc_get_root_obj(topology);
|
||||
struct hwloc_obj **listp, *obj;
|
||||
|
||||
if (!topology->need_pci_belowroot_apply_locality)
|
||||
return 0;
|
||||
topology->need_pci_belowroot_apply_locality = 0;
|
||||
|
||||
/* root->io_first_child contains some PCI hierarchies, any maybe some non-PCI things.
|
||||
* insert the PCI trees according to their PCI-locality.
|
||||
*/
|
||||
listp = &root->io_first_child;
|
||||
while ((obj = *listp) != NULL) {
|
||||
struct hwloc_pcidev_attr_s *busid;
|
||||
struct hwloc_obj *parent;
|
||||
|
||||
/* skip non-PCI objects */
|
||||
if (obj->type != HWLOC_OBJ_PCI_DEVICE
|
||||
&& !(obj->type == HWLOC_OBJ_BRIDGE && obj->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI)
|
||||
&& !(obj->type == HWLOC_OBJ_BRIDGE && obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI)) {
|
||||
listp = &obj->next_sibling;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (obj->type == HWLOC_OBJ_PCI_DEVICE
|
||||
|| (obj->type == HWLOC_OBJ_BRIDGE
|
||||
&& obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI))
|
||||
busid = &obj->attr->pcidev;
|
||||
else {
|
||||
/* hostbridges don't have a PCI busid for looking up locality, use their first child if PCI */
|
||||
hwloc_obj_t child = obj->io_first_child;
|
||||
if (child && (child->type == HWLOC_OBJ_PCI_DEVICE
|
||||
|| (child->type == HWLOC_OBJ_BRIDGE
|
||||
&& child->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI)))
|
||||
busid = &obj->io_first_child->attr->pcidev;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
/* attach the object (and children) where it belongs */
|
||||
parent = hwloc__pci_find_busid_parent(topology, busid);
|
||||
if (parent == root) {
|
||||
/* keep this object here */
|
||||
listp = &obj->next_sibling;
|
||||
} else {
|
||||
/* dequeue this object */
|
||||
*listp = obj->next_sibling;
|
||||
obj->next_sibling = NULL;
|
||||
hwloc_insert_object_by_parent(topology, parent, obj);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_obj *
|
||||
hwloc__pci_belowroot_find_by_busid(hwloc_obj_t parent,
|
||||
unsigned domain, unsigned bus, unsigned dev, unsigned func)
|
||||
{
|
||||
hwloc_obj_t child = parent->io_first_child;
|
||||
|
||||
for ( ; child; child = child->next_sibling) {
|
||||
if (child->type == HWLOC_OBJ_PCI_DEVICE
|
||||
|| (child->type == HWLOC_OBJ_BRIDGE
|
||||
&& child->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI)) {
|
||||
if (child->attr->pcidev.domain == domain
|
||||
&& child->attr->pcidev.bus == bus
|
||||
&& child->attr->pcidev.dev == dev
|
||||
&& child->attr->pcidev.func == func)
|
||||
/* that's the right bus id */
|
||||
return child;
|
||||
if (child->attr->pcidev.domain > domain
|
||||
|| (child->attr->pcidev.domain == domain
|
||||
&& child->attr->pcidev.bus > bus))
|
||||
/* bus id too high, won't find anything later, return parent */
|
||||
return parent;
|
||||
if (child->type == HWLOC_OBJ_BRIDGE
|
||||
&& child->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI
|
||||
&& child->attr->bridge.downstream.pci.domain == domain
|
||||
&& child->attr->bridge.downstream.pci.secondary_bus <= bus
|
||||
&& child->attr->bridge.downstream.pci.subordinate_bus >= bus)
|
||||
/* not the right bus id, but it's included in the bus below that bridge */
|
||||
return hwloc__pci_belowroot_find_by_busid(child, domain, bus, dev, func);
|
||||
|
||||
} else if (child->type == HWLOC_OBJ_BRIDGE
|
||||
&& child->attr->bridge.upstream_type != HWLOC_OBJ_BRIDGE_PCI
|
||||
&& child->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI
|
||||
/* non-PCI to PCI bridge, just look at the subordinate bus */
|
||||
&& child->attr->bridge.downstream.pci.domain == domain
|
||||
&& child->attr->bridge.downstream.pci.secondary_bus <= bus
|
||||
&& child->attr->bridge.downstream.pci.subordinate_bus >= bus) {
|
||||
/* contains our bus, recurse */
|
||||
return hwloc__pci_belowroot_find_by_busid(child, domain, bus, dev, func);
|
||||
}
|
||||
}
|
||||
/* didn't find anything, return parent */
|
||||
return parent;
|
||||
}
|
||||
|
||||
struct hwloc_obj *
|
||||
hwloc_pci_belowroot_find_by_busid(struct hwloc_topology *topology,
|
||||
unsigned domain, unsigned bus, unsigned dev, unsigned func)
|
||||
{
|
||||
hwloc_obj_t root = hwloc_get_root_obj(topology);
|
||||
hwloc_obj_t parent = hwloc__pci_belowroot_find_by_busid(root, domain, bus, dev, func);
|
||||
if (parent == root)
|
||||
return NULL;
|
||||
else
|
||||
return parent;
|
||||
}
|
||||
|
||||
#define HWLOC_PCI_STATUS 0x06
|
||||
#define HWLOC_PCI_STATUS_CAP_LIST 0x10
|
||||
#define HWLOC_PCI_CAPABILITY_LIST 0x34
|
||||
#define HWLOC_PCI_CAP_LIST_ID 0
|
||||
#define HWLOC_PCI_CAP_LIST_NEXT 1
|
||||
|
||||
unsigned
|
||||
hwloc_pci_find_cap(const unsigned char *config, unsigned cap)
|
||||
{
|
||||
unsigned char seen[256] = { 0 };
|
||||
unsigned char ptr; /* unsigned char to make sure we stay within the 256-byte config space */
|
||||
|
||||
if (!(config[HWLOC_PCI_STATUS] & HWLOC_PCI_STATUS_CAP_LIST))
|
||||
return 0;
|
||||
|
||||
for (ptr = config[HWLOC_PCI_CAPABILITY_LIST] & ~3;
|
||||
ptr; /* exit if next is 0 */
|
||||
ptr = config[ptr + HWLOC_PCI_CAP_LIST_NEXT] & ~3) {
|
||||
unsigned char id;
|
||||
|
||||
/* Looped around! */
|
||||
if (seen[ptr])
|
||||
break;
|
||||
seen[ptr] = 1;
|
||||
|
||||
id = config[ptr + HWLOC_PCI_CAP_LIST_ID];
|
||||
if (id == cap)
|
||||
return ptr;
|
||||
if (id == 0xff) /* exit if id is 0 or 0xff */
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define HWLOC_PCI_EXP_LNKSTA 0x12
|
||||
#define HWLOC_PCI_EXP_LNKSTA_SPEED 0x000f
|
||||
#define HWLOC_PCI_EXP_LNKSTA_WIDTH 0x03f0
|
||||
|
||||
int
|
||||
hwloc_pci_find_linkspeed(const unsigned char *config,
|
||||
unsigned offset, float *linkspeed)
|
||||
{
|
||||
unsigned linksta, speed, width;
|
||||
float lanespeed;
|
||||
|
||||
memcpy(&linksta, &config[offset + HWLOC_PCI_EXP_LNKSTA], 4);
|
||||
speed = linksta & HWLOC_PCI_EXP_LNKSTA_SPEED; /* PCIe generation */
|
||||
width = (linksta & HWLOC_PCI_EXP_LNKSTA_WIDTH) >> 4; /* how many lanes */
|
||||
/* PCIe Gen1 = 2.5GT/s signal-rate per lane with 8/10 encoding = 0.25GB/s data-rate per lane
|
||||
* PCIe Gen2 = 5 GT/s signal-rate per lane with 8/10 encoding = 0.5 GB/s data-rate per lane
|
||||
* PCIe Gen3 = 8 GT/s signal-rate per lane with 128/130 encoding = 1 GB/s data-rate per lane
|
||||
* PCIe Gen4 = 16 GT/s signal-rate per lane with 128/130 encoding = 2 GB/s data-rate per lane
|
||||
*/
|
||||
|
||||
/* lanespeed in Gbit/s */
|
||||
if (speed <= 2)
|
||||
lanespeed = 2.5f * speed * 0.8f;
|
||||
else
|
||||
lanespeed = 8.0f * (1<<(speed-3)) * 128/130; /* assume Gen5 will be 32 GT/s and so on */
|
||||
|
||||
/* linkspeed in GB/s */
|
||||
*linkspeed = lanespeed * width / 8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define HWLOC_PCI_HEADER_TYPE 0x0e
|
||||
#define HWLOC_PCI_HEADER_TYPE_BRIDGE 1
|
||||
#define HWLOC_PCI_CLASS_BRIDGE_PCI 0x0604
|
||||
|
||||
hwloc_obj_type_t
|
||||
hwloc_pci_check_bridge_type(unsigned device_class, const unsigned char *config)
|
||||
{
|
||||
unsigned char headertype;
|
||||
|
||||
if (device_class != HWLOC_PCI_CLASS_BRIDGE_PCI)
|
||||
return HWLOC_OBJ_PCI_DEVICE;
|
||||
|
||||
headertype = config[HWLOC_PCI_HEADER_TYPE] & 0x7f;
|
||||
return (headertype == HWLOC_PCI_HEADER_TYPE_BRIDGE)
|
||||
? HWLOC_OBJ_BRIDGE : HWLOC_OBJ_PCI_DEVICE;
|
||||
}
|
||||
|
||||
#define HWLOC_PCI_PRIMARY_BUS 0x18
|
||||
#define HWLOC_PCI_SECONDARY_BUS 0x19
|
||||
#define HWLOC_PCI_SUBORDINATE_BUS 0x1a
|
||||
|
||||
int
|
||||
hwloc_pci_setup_bridge_attr(hwloc_obj_t obj,
|
||||
const unsigned char *config)
|
||||
{
|
||||
struct hwloc_bridge_attr_s *battr = &obj->attr->bridge;
|
||||
struct hwloc_pcidev_attr_s *pattr = &battr->upstream.pci;
|
||||
|
||||
if (config[HWLOC_PCI_PRIMARY_BUS] != pattr->bus) {
|
||||
/* Sometimes the config space contains 00 instead of the actual primary bus number.
|
||||
* Always trust the bus ID because it was built by the system which has more information
|
||||
* to workaround such problems (e.g. ACPI information about PCI parent/children).
|
||||
*/
|
||||
hwloc_debug(" %04x:%02x:%02x.%01x bridge with (ignored) invalid PCI_PRIMARY_BUS %02x\n",
|
||||
pattr->domain, pattr->bus, pattr->dev, pattr->func, config[HWLOC_PCI_PRIMARY_BUS]);
|
||||
}
|
||||
|
||||
obj->type = HWLOC_OBJ_BRIDGE;
|
||||
battr->upstream_type = HWLOC_OBJ_BRIDGE_PCI;
|
||||
battr->downstream_type = HWLOC_OBJ_BRIDGE_PCI;
|
||||
battr->downstream.pci.domain = pattr->domain;
|
||||
battr->downstream.pci.secondary_bus = config[HWLOC_PCI_SECONDARY_BUS];
|
||||
battr->downstream.pci.subordinate_bus = config[HWLOC_PCI_SUBORDINATE_BUS];
|
||||
|
||||
if (battr->downstream.pci.secondary_bus <= pattr->bus
|
||||
|| battr->downstream.pci.subordinate_bus <= pattr->bus
|
||||
|| battr->downstream.pci.secondary_bus > battr->downstream.pci.subordinate_bus) {
|
||||
/* This should catch most cases of invalid bridge information
|
||||
* (e.g. 00 for secondary and subordinate).
|
||||
* Ideally we would also check that [secondary-subordinate] is included
|
||||
* in the parent bridge [secondary+1:subordinate]. But that's hard to do
|
||||
* because objects may be discovered out of order (especially in the fsroot case).
|
||||
*/
|
||||
hwloc_debug(" %04x:%02x:%02x.%01x bridge has invalid secondary-subordinate buses [%02x-%02x]\n",
|
||||
pattr->domain, pattr->bus, pattr->dev, pattr->func,
|
||||
battr->downstream.pci.secondary_bus, battr->downstream.pci.subordinate_bus);
|
||||
hwloc_free_unlinked_object(obj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
hwloc_pci_class_string(unsigned short class_id)
|
||||
{
|
||||
/* See https://pci-ids.ucw.cz/read/PD/ */
|
||||
switch ((class_id & 0xff00) >> 8) {
|
||||
case 0x00:
|
||||
switch (class_id) {
|
||||
case 0x0001: return "VGA";
|
||||
}
|
||||
break;
|
||||
case 0x01:
|
||||
switch (class_id) {
|
||||
case 0x0100: return "SCSI";
|
||||
case 0x0101: return "IDE";
|
||||
case 0x0102: return "Floppy";
|
||||
case 0x0103: return "IPI";
|
||||
case 0x0104: return "RAID";
|
||||
case 0x0105: return "ATA";
|
||||
case 0x0106: return "SATA";
|
||||
case 0x0107: return "SAS";
|
||||
case 0x0108: return "NVMExp";
|
||||
}
|
||||
return "Storage";
|
||||
case 0x02:
|
||||
switch (class_id) {
|
||||
case 0x0200: return "Ethernet";
|
||||
case 0x0201: return "TokenRing";
|
||||
case 0x0202: return "FDDI";
|
||||
case 0x0203: return "ATM";
|
||||
case 0x0204: return "ISDN";
|
||||
case 0x0205: return "WorldFip";
|
||||
case 0x0206: return "PICMG";
|
||||
case 0x0207: return "InfiniBand";
|
||||
case 0x0208: return "Fabric";
|
||||
}
|
||||
return "Network";
|
||||
case 0x03:
|
||||
switch (class_id) {
|
||||
case 0x0300: return "VGA";
|
||||
case 0x0301: return "XGA";
|
||||
case 0x0302: return "3D";
|
||||
}
|
||||
return "Display";
|
||||
case 0x04:
|
||||
switch (class_id) {
|
||||
case 0x0400: return "MultimediaVideo";
|
||||
case 0x0401: return "MultimediaAudio";
|
||||
case 0x0402: return "Telephony";
|
||||
case 0x0403: return "AudioDevice";
|
||||
}
|
||||
return "Multimedia";
|
||||
case 0x05:
|
||||
switch (class_id) {
|
||||
case 0x0500: return "RAM";
|
||||
case 0x0501: return "Flash";
|
||||
}
|
||||
return "Memory";
|
||||
case 0x06:
|
||||
switch (class_id) {
|
||||
case 0x0600: return "HostBridge";
|
||||
case 0x0601: return "ISABridge";
|
||||
case 0x0602: return "EISABridge";
|
||||
case 0x0603: return "MicroChannelBridge";
|
||||
case 0x0604: return "PCIBridge";
|
||||
case 0x0605: return "PCMCIABridge";
|
||||
case 0x0606: return "NubusBridge";
|
||||
case 0x0607: return "CardBusBridge";
|
||||
case 0x0608: return "RACEwayBridge";
|
||||
case 0x0609: return "SemiTransparentPCIBridge";
|
||||
case 0x060a: return "InfiniBandPCIHostBridge";
|
||||
}
|
||||
return "Bridge";
|
||||
case 0x07:
|
||||
switch (class_id) {
|
||||
case 0x0700: return "Serial";
|
||||
case 0x0701: return "Parallel";
|
||||
case 0x0702: return "MultiportSerial";
|
||||
case 0x0703: return "Model";
|
||||
case 0x0704: return "GPIB";
|
||||
case 0x0705: return "SmartCard";
|
||||
}
|
||||
return "Communication";
|
||||
case 0x08:
|
||||
switch (class_id) {
|
||||
case 0x0800: return "PIC";
|
||||
case 0x0801: return "DMA";
|
||||
case 0x0802: return "Timer";
|
||||
case 0x0803: return "RTC";
|
||||
case 0x0804: return "PCIHotPlug";
|
||||
case 0x0805: return "SDHost";
|
||||
case 0x0806: return "IOMMU";
|
||||
}
|
||||
return "SystemPeripheral";
|
||||
case 0x09:
|
||||
switch (class_id) {
|
||||
case 0x0900: return "Keyboard";
|
||||
case 0x0901: return "DigitizerPen";
|
||||
case 0x0902: return "Mouse";
|
||||
case 0x0903: return "Scanern";
|
||||
case 0x0904: return "Gameport";
|
||||
}
|
||||
return "Input";
|
||||
case 0x0a:
|
||||
return "DockingStation";
|
||||
case 0x0b:
|
||||
switch (class_id) {
|
||||
case 0x0b00: return "386";
|
||||
case 0x0b01: return "486";
|
||||
case 0x0b02: return "Pentium";
|
||||
/* 0x0b03 and 0x0b04 might be Pentium and P6 ? */
|
||||
case 0x0b10: return "Alpha";
|
||||
case 0x0b20: return "PowerPC";
|
||||
case 0x0b30: return "MIPS";
|
||||
case 0x0b40: return "Co-Processor";
|
||||
}
|
||||
return "Processor";
|
||||
case 0x0c:
|
||||
switch (class_id) {
|
||||
case 0x0c00: return "FireWire";
|
||||
case 0x0c01: return "ACCESS";
|
||||
case 0x0c02: return "SSA";
|
||||
case 0x0c03: return "USB";
|
||||
case 0x0c04: return "FibreChannel";
|
||||
case 0x0c05: return "SMBus";
|
||||
case 0x0c06: return "InfiniBand";
|
||||
case 0x0c07: return "IPMI-SMIC";
|
||||
case 0x0c08: return "SERCOS";
|
||||
case 0x0c09: return "CANBUS";
|
||||
}
|
||||
return "SerialBus";
|
||||
case 0x0d:
|
||||
switch (class_id) {
|
||||
case 0x0d00: return "IRDA";
|
||||
case 0x0d01: return "ConsumerIR";
|
||||
case 0x0d10: return "RF";
|
||||
case 0x0d11: return "Bluetooth";
|
||||
case 0x0d12: return "Broadband";
|
||||
case 0x0d20: return "802.1a";
|
||||
case 0x0d21: return "802.1b";
|
||||
}
|
||||
return "Wireless";
|
||||
case 0x0e:
|
||||
switch (class_id) {
|
||||
case 0x0e00: return "I2O";
|
||||
}
|
||||
return "Intelligent";
|
||||
case 0x0f:
|
||||
return "Satellite";
|
||||
case 0x10:
|
||||
return "Encryption";
|
||||
case 0x11:
|
||||
return "SignalProcessing";
|
||||
case 0x12:
|
||||
return "ProcessingAccelerator";
|
||||
case 0x13:
|
||||
return "Instrumentation";
|
||||
case 0x40:
|
||||
return "Co-Processor";
|
||||
}
|
||||
return "Other";
|
||||
}
|
875
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-aix.c
Обычный файл
875
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-aix.c
Обычный файл
@ -0,0 +1,875 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2011, 2013 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/* TODO: use SIGRECONFIG & dr_reconfig for state change */
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_DIRENT_H
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/misc.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#include <procinfo.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/rset.h>
|
||||
#include <sys/processor.h>
|
||||
#include <sys/thread.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/systemcfg.h>
|
||||
|
||||
#ifndef __power_pc
|
||||
#define __power_pc() 0
|
||||
#endif
|
||||
#ifndef __power_4
|
||||
#define __power_4() 0
|
||||
#endif
|
||||
#ifndef __power_5
|
||||
#define __power_5() 0
|
||||
#endif
|
||||
#ifndef __power_6
|
||||
#define __power_6() 0
|
||||
#endif
|
||||
#ifndef __power_7
|
||||
#define __power_7() 0
|
||||
#endif
|
||||
|
||||
static int
|
||||
hwloc_aix_set_sth_cpubind(hwloc_topology_t topology, rstype_t what, rsid_t who, pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
rsethandle_t rad;
|
||||
int res;
|
||||
unsigned cpu;
|
||||
|
||||
if (flags & HWLOC_CPUBIND_NOMEMBIND) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The resulting binding is always strict */
|
||||
|
||||
if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) {
|
||||
if (ra_detachrset(what, who, 0))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rad = rs_alloc(RS_EMPTY);
|
||||
hwloc_bitmap_foreach_begin(cpu, hwloc_set)
|
||||
rs_op(RS_ADDRESOURCE, rad, NULL, R_PROCS, cpu);
|
||||
hwloc_bitmap_foreach_end();
|
||||
|
||||
res = ra_attachrset(what, who, rad, 0);
|
||||
if (res < 0 && errno == EPERM) {
|
||||
/* EPERM may mean that one thread has ben bound with bindprocessor().
|
||||
* Unbind the entire process (we can't unbind individual threads)
|
||||
* and try again.
|
||||
*/
|
||||
bindprocessor(BINDPROCESS, pid, PROCESSOR_CLASS_ANY);
|
||||
res = ra_attachrset(what, who, rad, 0);
|
||||
}
|
||||
|
||||
rs_free(rad);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_sth_rset_cpubind(hwloc_topology_t topology, rstype_t what, rsid_t who, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused, int *boundp)
|
||||
{
|
||||
rsethandle_t rset;
|
||||
unsigned cpu, maxcpus;
|
||||
int res = -1;
|
||||
int bound = 0;
|
||||
|
||||
rset = rs_alloc(RS_EMPTY);
|
||||
|
||||
if (ra_getrset(what, who, 0, rset) == -1)
|
||||
goto out;
|
||||
|
||||
hwloc_bitmap_zero(hwloc_set);
|
||||
maxcpus = rs_getinfo(rset, R_MAXPROCS, 0);
|
||||
for (cpu = 0; cpu < maxcpus; cpu++)
|
||||
if (rs_op(RS_TESTRESOURCE, rset, NULL, R_PROCS, cpu) == 1)
|
||||
hwloc_bitmap_set(hwloc_set, cpu);
|
||||
else
|
||||
bound = 1;
|
||||
hwloc_bitmap_and(hwloc_set, hwloc_set, hwloc_topology_get_complete_cpuset(topology));
|
||||
res = 0;
|
||||
*boundp = bound;
|
||||
|
||||
out:
|
||||
rs_free(rset);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_pid_getthrds_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, pid_t pid, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
#if HWLOC_BITS_PER_LONG == 64
|
||||
struct thrdentry64 thread_info;
|
||||
tid64_t next_thread;
|
||||
#else
|
||||
struct thrdsinfo thread_info;
|
||||
tid_t next_thread;
|
||||
#endif
|
||||
|
||||
next_thread = 0;
|
||||
/* TODO: get multiple at once */
|
||||
#if HWLOC_BITS_PER_LONG == 64
|
||||
while (getthrds64 (pid, &thread_info, sizeof (thread_info),
|
||||
&next_thread, 1) == 1) {
|
||||
#else
|
||||
while (getthrds (pid, &thread_info, sizeof (thread_info),
|
||||
&next_thread, 1) == 1) {
|
||||
#endif
|
||||
if (PROCESSOR_CLASS_ANY != thread_info.ti_cpuid)
|
||||
hwloc_bitmap_set(hwloc_set, thread_info.ti_cpuid);
|
||||
else
|
||||
hwloc_bitmap_fill(hwloc_set);
|
||||
}
|
||||
/* TODO: what if the thread list changes and we get nothing? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_tid_getthrds_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, tid_t tid, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
#if HWLOC_BITS_PER_LONG == 64
|
||||
struct thrdentry64 thread_info;
|
||||
tid64_t next_thread;
|
||||
#else
|
||||
struct thrdsinfo thread_info;
|
||||
tid_t next_thread;
|
||||
#endif
|
||||
pid_t pid = getpid();
|
||||
|
||||
next_thread = 0;
|
||||
/* TODO: get multiple at once */
|
||||
#if HWLOC_BITS_PER_LONG == 64
|
||||
while (getthrds64 (pid, &thread_info, sizeof (thread_info),
|
||||
&next_thread, 1) == 1) {
|
||||
#else
|
||||
while (getthrds (pid, &thread_info, sizeof (thread_info),
|
||||
&next_thread, 1) == 1) {
|
||||
#endif
|
||||
if (thread_info.ti_tid == tid) {
|
||||
if (PROCESSOR_CLASS_ANY != thread_info.ti_cpuid)
|
||||
hwloc_bitmap_set(hwloc_set, thread_info.ti_cpuid);
|
||||
else
|
||||
hwloc_bitmap_fill(hwloc_set);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* TODO: what if the thread goes away in the meantime? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_pid = getpid();
|
||||
return hwloc_aix_set_sth_cpubind(topology, R_PROCESS, who, who.at_pid, hwloc_set, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
int ret, bound;
|
||||
rsid_t who;
|
||||
who.at_pid = getpid();
|
||||
ret = hwloc_aix_get_sth_rset_cpubind(topology, R_PROCESS, who, hwloc_set, flags, &bound);
|
||||
if (!ret && !bound) {
|
||||
hwloc_bitmap_zero(hwloc_set);
|
||||
ret = hwloc_aix_get_pid_getthrds_cpubind(topology, who.at_pid, hwloc_set, flags);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef R_THREAD
|
||||
static int
|
||||
hwloc_aix_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_tid = thread_self();
|
||||
return hwloc_aix_set_sth_cpubind(topology, R_THREAD, who, getpid(), hwloc_set, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
int ret, bound;
|
||||
rsid_t who;
|
||||
who.at_tid = thread_self();
|
||||
ret = hwloc_aix_get_sth_rset_cpubind(topology, R_THREAD, who, hwloc_set, flags, &bound);
|
||||
if (!ret && !bound) {
|
||||
hwloc_bitmap_zero(hwloc_set);
|
||||
ret = hwloc_aix_get_tid_getthrds_cpubind(topology, who.at_tid, hwloc_set, flags);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif /* R_THREAD */
|
||||
|
||||
static int
|
||||
hwloc_aix_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_pid = pid;
|
||||
return hwloc_aix_set_sth_cpubind(topology, R_PROCESS, who, pid, hwloc_set, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
int ret, bound;
|
||||
rsid_t who;
|
||||
who.at_pid = pid;
|
||||
ret = hwloc_aix_get_sth_rset_cpubind(topology, R_PROCESS, who, hwloc_set, flags, &bound);
|
||||
if (!ret && !bound) {
|
||||
hwloc_bitmap_zero(hwloc_set);
|
||||
ret = hwloc_aix_get_pid_getthrds_cpubind(topology, who.at_pid, hwloc_set, flags);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef R_THREAD
|
||||
#ifdef HWLOC_HAVE_PTHREAD_GETTHRDS_NP
|
||||
static int
|
||||
hwloc_aix_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
struct __pthrdsinfo info;
|
||||
int size;
|
||||
if ((errno = pthread_getthrds_np(&pthread, PTHRDSINFO_QUERY_TID, &info, sizeof(info), NULL, &size)))
|
||||
return -1;
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_tid = info.__pi_tid;
|
||||
return hwloc_aix_set_sth_cpubind(topology, R_THREAD, who, getpid(), hwloc_set, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
struct __pthrdsinfo info;
|
||||
int size;
|
||||
if (pthread_getthrds_np(&pthread, PTHRDSINFO_QUERY_TID, &info, sizeof(info), NULL, &size))
|
||||
return -1;
|
||||
{
|
||||
int ret, bound;
|
||||
rsid_t who;
|
||||
who.at_tid = info.__pi_tid;
|
||||
ret = hwloc_aix_get_sth_rset_cpubind(topology, R_THREAD, who, hwloc_set, flags, &bound);
|
||||
if (!ret && !bound) {
|
||||
hwloc_bitmap_zero(hwloc_set);
|
||||
ret = hwloc_aix_get_tid_getthrds_cpubind(topology, who.at_tid, hwloc_set, flags);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif /* HWLOC_HAVE_PTHREAD_GETTHRDS_NP */
|
||||
#endif /* R_THREAD */
|
||||
|
||||
static int
|
||||
hwloc_aix_get_thisthread_last_cpu_location(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
cpu_t cpu;
|
||||
|
||||
if (topology->pid) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cpu = mycpu();
|
||||
if (cpu < 0)
|
||||
return -1;
|
||||
|
||||
hwloc_bitmap_only(hwloc_set, cpu);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef P_DEFAULT
|
||||
|
||||
static int
|
||||
hwloc_aix_membind_policy_from_hwloc(uint_t *aix_policy, int policy)
|
||||
{
|
||||
switch (policy) {
|
||||
case HWLOC_MEMBIND_DEFAULT:
|
||||
case HWLOC_MEMBIND_BIND:
|
||||
*aix_policy = P_DEFAULT;
|
||||
break;
|
||||
case HWLOC_MEMBIND_FIRSTTOUCH:
|
||||
*aix_policy = P_FIRST_TOUCH;
|
||||
break;
|
||||
case HWLOC_MEMBIND_INTERLEAVE:
|
||||
*aix_policy = P_BALANCED;
|
||||
break;
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_prepare_membind(hwloc_topology_t topology, rsethandle_t *rad, hwloc_const_nodeset_t nodeset, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
rsethandle_t rset, noderad;
|
||||
int MCMlevel;
|
||||
int node;
|
||||
|
||||
MCMlevel = rs_getinfo(NULL, R_MCMSDL, 0);
|
||||
if ((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM))
|
||||
rset = rs_alloc(RS_ALL);
|
||||
else
|
||||
rset = rs_alloc(RS_PARTITION);
|
||||
*rad = rs_alloc(RS_EMPTY);
|
||||
noderad = rs_alloc(RS_EMPTY);
|
||||
|
||||
hwloc_bitmap_foreach_begin(node, nodeset)
|
||||
/* we used MCMlevel rad number for node->os_index during lookup */
|
||||
rs_getrad(rset, noderad, MCMlevel, node, 0);
|
||||
rs_op(RS_UNION, noderad, *rad, 0, 0);
|
||||
hwloc_bitmap_foreach_end();
|
||||
|
||||
rs_free(rset);
|
||||
rs_free(noderad);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_set_sth_membind(hwloc_topology_t topology, rstype_t what, rsid_t who, pid_t pid, hwloc_const_bitmap_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
rsethandle_t rad;
|
||||
int res;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_NOCPUBIND) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (policy) {
|
||||
case HWLOC_MEMBIND_DEFAULT:
|
||||
case HWLOC_MEMBIND_BIND:
|
||||
break;
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hwloc_aix_prepare_membind(topology, &rad, nodeset, flags))
|
||||
return -1;
|
||||
|
||||
res = ra_attachrset(what, who, rad, 0);
|
||||
if (res < 0 && errno == EPERM) {
|
||||
/* EPERM may mean that one thread has ben bound with bindprocessor().
|
||||
* Unbind the entire process (we can't unbind individual threads)
|
||||
* and try again.
|
||||
*/
|
||||
bindprocessor(BINDPROCESS, pid, PROCESSOR_CLASS_ANY);
|
||||
res = ra_attachrset(what, who, rad, 0);
|
||||
}
|
||||
|
||||
rs_free(rad);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_sth_membind(hwloc_topology_t topology, rstype_t what, rsid_t who, hwloc_bitmap_t nodeset, hwloc_membind_policy_t *policy, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
hwloc_bitmap_t hwloc_set;
|
||||
rsethandle_t rset;
|
||||
unsigned cpu, maxcpus;
|
||||
int res = -1;
|
||||
int depth, n, i;
|
||||
|
||||
depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
assert(depth >= 0);
|
||||
n = hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
|
||||
rset = rs_alloc(RS_EMPTY);
|
||||
|
||||
if (ra_getrset(what, who, 0, rset) == -1)
|
||||
goto out;
|
||||
|
||||
hwloc_set = hwloc_bitmap_alloc();
|
||||
|
||||
maxcpus = rs_getinfo(rset, R_MAXPROCS, 0);
|
||||
for (cpu = 0; cpu < maxcpus; cpu++)
|
||||
if (rs_op(RS_TESTRESOURCE, rset, NULL, R_PROCS, cpu) == 1)
|
||||
hwloc_bitmap_set(hwloc_set, cpu);
|
||||
hwloc_bitmap_and(hwloc_set, hwloc_set, hwloc_topology_get_complete_cpuset(topology));
|
||||
|
||||
hwloc_bitmap_zero(nodeset);
|
||||
for (i = 0; i < n; i++) {
|
||||
hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i);
|
||||
if (hwloc_bitmap_isincluded(obj->cpuset, hwloc_set))
|
||||
hwloc_bitmap_set(nodeset, obj->os_index);
|
||||
}
|
||||
|
||||
hwloc_bitmap_free(hwloc_set);
|
||||
|
||||
*policy = HWLOC_MEMBIND_BIND;
|
||||
res = 0;
|
||||
|
||||
out:
|
||||
rs_free(rset);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_set_thisproc_membind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_pid = getpid();
|
||||
return hwloc_aix_set_sth_membind(topology, R_PROCESS, who, who.at_pid, hwloc_set, policy, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_thisproc_membind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, hwloc_membind_policy_t *policy, int flags)
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_pid = getpid();
|
||||
return hwloc_aix_get_sth_membind(topology, R_PROCESS, who, hwloc_set, policy, flags);
|
||||
}
|
||||
|
||||
#ifdef R_THREAD
|
||||
static int
|
||||
hwloc_aix_set_thisthread_membind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_tid = thread_self();
|
||||
return hwloc_aix_set_sth_membind(topology, R_THREAD, who, getpid(), hwloc_set, policy, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_thisthread_membind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, hwloc_membind_policy_t *policy, int flags)
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_tid = thread_self();
|
||||
return hwloc_aix_get_sth_membind(topology, R_THREAD, who, hwloc_set, policy, flags);
|
||||
}
|
||||
#endif /* R_THREAD */
|
||||
|
||||
static int
|
||||
hwloc_aix_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_pid = pid;
|
||||
return hwloc_aix_set_sth_membind(topology, R_PROCESS, who, pid, hwloc_set, policy, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t hwloc_set, hwloc_membind_policy_t *policy, int flags)
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_pid = pid;
|
||||
return hwloc_aix_get_sth_membind(topology, R_PROCESS, who, hwloc_set, policy, flags);
|
||||
}
|
||||
|
||||
#ifdef R_THREAD
|
||||
#if 0 /* def HWLOC_HAVE_PTHREAD_GETTHRDS_NP */
|
||||
static int
|
||||
hwloc_aix_set_thread_membind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_const_bitmap_t hwloc_set, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
struct __pthrdsinfo info;
|
||||
int size;
|
||||
if ((errno = pthread_getthrds_np(&pthread, PTHRDSINFO_QUERY_TID, &info, sizeof(info), NULL, &size)))
|
||||
return -1;
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_tid = info.__pi_tid;
|
||||
return hwloc_aix_set_sth_membind(topology, R_THREAD, who, getpid(), hwloc_set, policy, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_aix_get_thread_membind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_bitmap_t hwloc_set, hwloc_membind_policy_t *policy, int flags)
|
||||
{
|
||||
struct __pthrdsinfo info;
|
||||
int size;
|
||||
if (pthread_getthrds_np(&pthread, PTHRDSINFO_QUERY_TID, &info, sizeof(info), NULL, &size))
|
||||
return -1;
|
||||
{
|
||||
rsid_t who;
|
||||
who.at_tid = info.__pi_tid;
|
||||
return hwloc_aix_get_sth_membind(topology, R_THREAD, who, hwloc_set, policy, flags);
|
||||
}
|
||||
}
|
||||
#endif /* HWLOC_HAVE_PTHREAD_GETTHRDS_NP */
|
||||
#endif /* R_THREAD */
|
||||
|
||||
#if 0
|
||||
/* TODO: seems to be right, but doesn't seem to be working (EINVAL), even after
|
||||
* aligning the range on 64K... */
|
||||
static int
|
||||
hwloc_aix_set_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
subrange_t subrange;
|
||||
rsid_t rsid = { .at_subrange = &subrange };
|
||||
uint_t aix_policy;
|
||||
int ret;
|
||||
fprintf(stderr,"yop\n");
|
||||
|
||||
if ((flags & (HWLOC_MEMBIND_MIGRATE|HWLOC_MEMBIND_STRICT))
|
||||
== (HWLOC_MEMBIND_MIGRATE|HWLOC_MEMBIND_STRICT)) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
subrange.su_offset = (uintptr_t) addr;
|
||||
subrange.su_length = len;
|
||||
subrange.su_rstype = R_RSET;
|
||||
|
||||
if (hwloc_aix_membind_policy_from_hwloc(&aix_policy, policy))
|
||||
return -1;
|
||||
|
||||
if (hwloc_aix_prepare_membind(topology, &subrange.su_rsid.at_rset, nodeset, flags))
|
||||
return -1;
|
||||
|
||||
subrange.su_policy = aix_policy;
|
||||
|
||||
res = ra_attachrset(R_SUBRANGE, rsid, subrange.su_rsid.at_rset, 0);
|
||||
if (res < 0 && errno == EPERM) {
|
||||
/* EPERM may mean that one thread has ben bound with bindprocessor().
|
||||
* Unbind the entire process (we can't unbind individual threads)
|
||||
* and try again.
|
||||
* FIXME: actually check that this EPERM can happen
|
||||
*/
|
||||
bindprocessor(BINDPROCESS, getpid(), PROCESSOR_CLASS_ANY);
|
||||
res = ra_attachrset(R_SUBRANGE, rsid, subrange.su_rsid.at_rset, 0);
|
||||
}
|
||||
|
||||
rs_free(subrange.su_rsid.at_rset);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void *
|
||||
hwloc_aix_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
void *ret;
|
||||
rsid_t rsid;
|
||||
uint_t aix_policy;
|
||||
|
||||
if (hwloc_aix_membind_policy_from_hwloc(&aix_policy, policy))
|
||||
return hwloc_alloc_or_fail(topology, len, flags);
|
||||
|
||||
if (hwloc_aix_prepare_membind(topology, &rsid.at_rset, nodeset, flags))
|
||||
return hwloc_alloc_or_fail(topology, len, flags);
|
||||
|
||||
ret = ra_mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0, R_RSET, rsid, aix_policy);
|
||||
|
||||
rs_free(rsid.at_rset);
|
||||
return ret == (void*)-1 ? NULL : ret;
|
||||
}
|
||||
#endif /* P_DEFAULT */
|
||||
|
||||
static void
|
||||
look_rset(int sdl, hwloc_obj_type_t type, struct hwloc_topology *topology, int level)
|
||||
{
|
||||
rsethandle_t rset, rad;
|
||||
int i,maxcpus,j;
|
||||
int nbnodes;
|
||||
struct hwloc_obj *obj;
|
||||
|
||||
if ((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM))
|
||||
rset = rs_alloc(RS_ALL);
|
||||
else
|
||||
rset = rs_alloc(RS_PARTITION);
|
||||
rad = rs_alloc(RS_EMPTY);
|
||||
nbnodes = rs_numrads(rset, sdl, 0);
|
||||
if (nbnodes == -1) {
|
||||
perror("rs_numrads");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < nbnodes; i++) {
|
||||
hwloc_bitmap_t cpuset;
|
||||
unsigned os_index = (unsigned) -1; /* no os_index except for PU and NUMANODE below */
|
||||
|
||||
if (rs_getrad(rset, rad, sdl, i, 0)) {
|
||||
fprintf(stderr,"rs_getrad(%d) failed: %s\n", i, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (!rs_getinfo(rad, R_NUMPROCS, 0))
|
||||
continue;
|
||||
|
||||
maxcpus = rs_getinfo(rad, R_MAXPROCS, 0);
|
||||
cpuset = hwloc_bitmap_alloc();
|
||||
for (j = 0; j < maxcpus; j++) {
|
||||
if (rs_op(RS_TESTRESOURCE, rad, NULL, R_PROCS, j))
|
||||
hwloc_bitmap_set(cpuset, j);
|
||||
}
|
||||
|
||||
if (type == HWLOC_OBJ_PU) {
|
||||
os_index = hwloc_bitmap_first(cpuset);
|
||||
hwloc_debug("Found PU #%u inside node %d for sdl %d\n", os_index, i, sdl);
|
||||
assert(hwloc_bitmap_weight(cpuset) == 1);
|
||||
} else if (type == HWLOC_OBJ_NUMANODE) {
|
||||
/* NUMA node os_index isn't used for binding, just use the rad number to get unique values.
|
||||
* Note that we'll use that fact in hwloc_aix_prepare_membind(). */
|
||||
os_index = i;
|
||||
hwloc_debug("Using os_index #%u for NUMA node inside node %d for sdl %d\n", os_index, i, sdl);
|
||||
}
|
||||
|
||||
obj = hwloc_alloc_setup_object(topology, type, os_index);
|
||||
obj->cpuset = cpuset;
|
||||
|
||||
switch(type) {
|
||||
case HWLOC_OBJ_NUMANODE:
|
||||
obj->nodeset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(obj->nodeset, i);
|
||||
obj->memory.local_memory = 0; /* TODO: odd, rs_getinfo(rad, R_MEMSIZE, 0) << 10 returns the total memory ... */
|
||||
obj->memory.page_types_len = 2;
|
||||
obj->memory.page_types = malloc(2*sizeof(*obj->memory.page_types));
|
||||
memset(obj->memory.page_types, 0, 2*sizeof(*obj->memory.page_types));
|
||||
obj->memory.page_types[0].size = hwloc_getpagesize();
|
||||
#if HAVE_DECL__SC_LARGE_PAGESIZE
|
||||
obj->memory.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE);
|
||||
#endif
|
||||
/* TODO: obj->memory.page_types[1].count = rs_getinfo(rset, R_LGPGFREE, 0) / hugepagesize */
|
||||
break;
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
obj->attr->cache.size = _system_configuration.L2_cache_size;
|
||||
obj->attr->cache.associativity = _system_configuration.L2_cache_asc;
|
||||
|
||||
obj->attr->cache.linesize = 0; /* unknown by default */
|
||||
if (__power_pc())
|
||||
if (__power_4() || __power_5() || __power_6() || __power_7())
|
||||
obj->attr->cache.linesize = 128;
|
||||
|
||||
obj->attr->cache.depth = 2;
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; /* OK for power[4567], unknown for others */
|
||||
break;
|
||||
case HWLOC_OBJ_GROUP:
|
||||
obj->attr->group.kind = HWLOC_GROUP_KIND_AIX_SDL_UNKNOWN;
|
||||
obj->attr->group.subkind = level;
|
||||
break;
|
||||
case HWLOC_OBJ_CORE:
|
||||
{
|
||||
hwloc_obj_t obj2, obj3;
|
||||
obj2 = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1CACHE, -1);
|
||||
obj2->cpuset = hwloc_bitmap_dup(obj->cpuset);
|
||||
obj2->attr->cache.size = _system_configuration.dcache_size;
|
||||
obj2->attr->cache.associativity = _system_configuration.dcache_asc;
|
||||
obj2->attr->cache.linesize = _system_configuration.dcache_line;
|
||||
obj2->attr->cache.depth = 1;
|
||||
if (_system_configuration.cache_attrib & (1<<30)) {
|
||||
/* Unified cache */
|
||||
obj2->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
hwloc_debug("Adding an L1u cache for core %d\n", i);
|
||||
} else {
|
||||
/* Separate Instruction and Data caches */
|
||||
obj2->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
|
||||
hwloc_debug("Adding an L1d cache for core %d\n", i);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1ICACHE)) {
|
||||
obj3 = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1ICACHE, -1);
|
||||
obj3->cpuset = hwloc_bitmap_dup(obj->cpuset);
|
||||
obj3->attr->cache.size = _system_configuration.icache_size;
|
||||
obj3->attr->cache.associativity = _system_configuration.icache_asc;
|
||||
obj3->attr->cache.linesize = _system_configuration.icache_line;
|
||||
obj3->attr->cache.depth = 1;
|
||||
obj3->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
hwloc_debug("Adding an L1i cache for core %d\n", i);
|
||||
hwloc_insert_object_by_cpuset(topology, obj3);
|
||||
}
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1CACHE))
|
||||
hwloc_insert_object_by_cpuset(topology, obj2);
|
||||
else
|
||||
hwloc_free_unlinked_object(obj2); /* FIXME: don't built at all, just build the cpuset in case l1/l1i needs it */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hwloc_debug_2args_bitmap("%s %d has cpuset %s\n",
|
||||
hwloc_type_name(type),
|
||||
i, obj->cpuset);
|
||||
if (hwloc_filter_check_keep_object_type(topology, obj->type))
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
else
|
||||
hwloc_free_unlinked_object(obj);
|
||||
}
|
||||
|
||||
rs_free(rset);
|
||||
rs_free(rad);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_look_aix(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
int i;
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
|
||||
/* TODO: R_LGPGDEF/R_LGPGFREE for large pages */
|
||||
|
||||
hwloc_debug("Note: SMPSDL is at %d\n", rs_getinfo(NULL, R_SMPSDL, 0));
|
||||
#ifdef R_REF1SDL
|
||||
hwloc_debug("Note: REF1SDL is at %d\n", rs_getinfo(NULL, R_REF1SDL, 0));
|
||||
#endif
|
||||
|
||||
for (i=0; i<=rs_getinfo(NULL, R_MAXSDL, 0); i++)
|
||||
{
|
||||
int known = 0;
|
||||
#if 0
|
||||
if (i == rs_getinfo(NULL, R_SMPSDL, 0))
|
||||
/* Not enabled for now because I'm not sure what it corresponds to. On
|
||||
* decrypthon it contains all the cpus. Is it a "machine" or a "system"
|
||||
* level ?
|
||||
*/
|
||||
{
|
||||
hwloc_debug("looking AIX \"SMP\" sdl %d\n", i);
|
||||
look_rset(i, HWLOC_OBJ_MACHINE, topology, i);
|
||||
known = 1;
|
||||
}
|
||||
#endif
|
||||
if (i == rs_getinfo(NULL, R_MCMSDL, 0))
|
||||
{
|
||||
hwloc_debug("looking AIX node sdl %d\n", i);
|
||||
look_rset(i, HWLOC_OBJ_NUMANODE, topology, i);
|
||||
known = 1;
|
||||
}
|
||||
# ifdef R_L2CSDL
|
||||
if (i == rs_getinfo(NULL, R_L2CSDL, 0))
|
||||
{
|
||||
hwloc_debug("looking AIX L2 sdl %d\n", i);
|
||||
look_rset(i, HWLOC_OBJ_L2CACHE, topology, i);
|
||||
known = 1;
|
||||
}
|
||||
# endif
|
||||
# ifdef R_PCORESDL
|
||||
if (i == rs_getinfo(NULL, R_PCORESDL, 0))
|
||||
{
|
||||
hwloc_debug("looking AIX core sdl %d\n", i);
|
||||
look_rset(i, HWLOC_OBJ_CORE, topology, i);
|
||||
known = 1;
|
||||
}
|
||||
# endif
|
||||
if (i == rs_getinfo(NULL, R_MAXSDL, 0))
|
||||
{
|
||||
hwloc_debug("looking AIX max sdl %d\n", i);
|
||||
look_rset(i, HWLOC_OBJ_PU, topology, i);
|
||||
known = 1;
|
||||
topology->support.discovery->pu = 1;
|
||||
}
|
||||
|
||||
/* Don't know how it should be rendered, make a misc object for it. */
|
||||
if (!known)
|
||||
{
|
||||
hwloc_debug("looking AIX unknown sdl %d\n", i);
|
||||
look_rset(i, HWLOC_OBJ_GROUP, topology, i);
|
||||
}
|
||||
}
|
||||
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "AIX");
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_set_aix_hooks(struct hwloc_binding_hooks *hooks,
|
||||
struct hwloc_topology_support *support __hwloc_attribute_unused)
|
||||
{
|
||||
hooks->set_proc_cpubind = hwloc_aix_set_proc_cpubind;
|
||||
hooks->get_proc_cpubind = hwloc_aix_get_proc_cpubind;
|
||||
#ifdef R_THREAD
|
||||
#ifdef HWLOC_HAVE_PTHREAD_GETTHRDS_NP
|
||||
hooks->set_thread_cpubind = hwloc_aix_set_thread_cpubind;
|
||||
hooks->get_thread_cpubind = hwloc_aix_get_thread_cpubind;
|
||||
#endif /* HWLOC_HAVE_PTHREAD_GETTHRDS_NP */
|
||||
#endif /* R_THREAD */
|
||||
hooks->set_thisproc_cpubind = hwloc_aix_set_thisproc_cpubind;
|
||||
hooks->get_thisproc_cpubind = hwloc_aix_get_thisproc_cpubind;
|
||||
#ifdef R_THREAD
|
||||
hooks->set_thisthread_cpubind = hwloc_aix_set_thisthread_cpubind;
|
||||
hooks->get_thisthread_cpubind = hwloc_aix_get_thisthread_cpubind;
|
||||
#endif /* R_THREAD */
|
||||
hooks->get_thisthread_last_cpu_location = hwloc_aix_get_thisthread_last_cpu_location;
|
||||
/* TODO: get_last_cpu_location: mycpu() only works for the current thread? */
|
||||
#ifdef P_DEFAULT
|
||||
hooks->set_proc_membind = hwloc_aix_set_proc_membind;
|
||||
hooks->get_proc_membind = hwloc_aix_get_proc_membind;
|
||||
#ifdef R_THREAD
|
||||
#if 0 /* def HWLOC_HAVE_PTHREAD_GETTHRDS_NP */
|
||||
/* Does it really make sense to set the memory binding of another thread? */
|
||||
hooks->set_thread_membind = hwloc_aix_set_thread_membind;
|
||||
hooks->get_thread_membind = hwloc_aix_get_thread_membind;
|
||||
#endif /* HWLOC_HAVE_PTHREAD_GETTHRDS_NP */
|
||||
#endif /* R_THREAD */
|
||||
hooks->set_thisproc_membind = hwloc_aix_set_thisproc_membind;
|
||||
hooks->get_thisproc_membind = hwloc_aix_get_thisproc_membind;
|
||||
#ifdef R_THREAD
|
||||
hooks->set_thisthread_membind = hwloc_aix_set_thisthread_membind;
|
||||
hooks->get_thisthread_membind = hwloc_aix_get_thisthread_membind;
|
||||
#endif /* R_THREAD */
|
||||
/* hooks->set_area_membind = hwloc_aix_set_area_membind; */
|
||||
/* get_area_membind is not available */
|
||||
hooks->alloc_membind = hwloc_aix_alloc_membind;
|
||||
hooks->alloc = hwloc_alloc_mmap;
|
||||
hooks->free_membind = hwloc_free_mmap;
|
||||
support->membind->firsttouch_membind = 1;
|
||||
support->membind->bind_membind = 1;
|
||||
support->membind->interleave_membind = 1;
|
||||
#endif /* P_DEFAULT */
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_aix_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_look_aix;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_aix_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_CPU,
|
||||
"aix",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_aix_component_instantiate,
|
||||
50,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct hwloc_component hwloc_aix_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
NULL, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_aix_disc_component
|
||||
};
|
301
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-bgq.c
Обычный файл
301
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-bgq.c
Обычный файл
@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright © 2013-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <spi/include/kernel/location.h>
|
||||
#include <spi/include/kernel/process.h>
|
||||
|
||||
#ifndef HWLOC_DISABLE_BGQ_PORT_TEST
|
||||
|
||||
#define HWLOC_BGQ_CORES 17 /* spare core ignored for now */
|
||||
|
||||
static int
|
||||
hwloc_bgq__get_allowed_resources(struct hwloc_topology *topology)
|
||||
{
|
||||
const char *env;
|
||||
unsigned i;
|
||||
|
||||
/* mark the 17th core (OS-reserved) as disallowed */
|
||||
hwloc_bitmap_clr_range(topology->levels[0][0]->allowed_cpuset, (HWLOC_BGQ_CORES-1)*4, HWLOC_BGQ_CORES*4-1);
|
||||
|
||||
if (topology->is_thissystem) { /* don't call CNK unless thissystem */
|
||||
env = getenv("BG_THREADMODEL");
|
||||
if (!env || atoi(env) != 2) {
|
||||
/* process cannot use cores/threads outside of its Kernel_ThreadMask() unless BG_THREADMODEL=2 */
|
||||
uint64_t bgmask = Kernel_ThreadMask(Kernel_MyTcoord());
|
||||
/* the mask is reversed, manually reverse it */
|
||||
for(i=0; i<64; i++)
|
||||
if (((bgmask >> i) & 1) == 0)
|
||||
hwloc_bitmap_clr(topology->levels[0][0]->allowed_cpuset, 63-i);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_look_bgq(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
hwloc_bitmap_t set;
|
||||
hwloc_obj_t obj;
|
||||
unsigned i;
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
|
||||
hwloc_bgq__get_allowed_resources(topology);
|
||||
|
||||
/* a single memory bank */
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_NUMANODE, 0);
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(set, 0, HWLOC_BGQ_CORES*4-1);
|
||||
obj->cpuset = set;
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(set, 0);
|
||||
obj->nodeset = set;
|
||||
obj->memory.local_memory = 16ULL*1024*1024*1024ULL;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(set, 0, HWLOC_BGQ_CORES*4-1);
|
||||
|
||||
/* shared L2 */
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L2CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L2CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
obj->attr->cache.depth = 2;
|
||||
obj->attr->cache.size = 32*1024*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 16;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
|
||||
/* package */
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_PACKAGE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PACKAGE, 0);
|
||||
obj->cpuset = set;
|
||||
hwloc_obj_add_info(obj, "CPUModel", "IBM PowerPC A2");
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
|
||||
/* Cores */
|
||||
for(i=0; i<HWLOC_BGQ_CORES; i++) {
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(set, i*4, i*4+3);
|
||||
|
||||
/* L1d */
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 16*1024;
|
||||
obj->attr->cache.linesize = 64;
|
||||
obj->attr->cache.associativity = 8;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
/* L1i */
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1ICACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1ICACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 16*1024;
|
||||
obj->attr->cache.linesize = 64;
|
||||
obj->attr->cache.associativity = 4;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
/* there's also a L1p "prefetch cache" of 4kB with 128B lines */
|
||||
|
||||
/* Core */
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_CORE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_CORE, i);
|
||||
obj->cpuset = set;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
}
|
||||
|
||||
/* PUs */
|
||||
hwloc_setup_pu_level(topology, HWLOC_BGQ_CORES*4);
|
||||
|
||||
/* Add BGQ specific information */
|
||||
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "BGQ");
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_bgq_get_thread_cpubind(hwloc_topology_t topology, pthread_t thread, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
unsigned pu;
|
||||
cpu_set_t bg_set;
|
||||
int err;
|
||||
|
||||
if (topology->pid) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
err = pthread_getaffinity_np(thread, sizeof(bg_set), &bg_set);
|
||||
if (err) {
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
for(pu=0; pu<64; pu++)
|
||||
if (CPU_ISSET(pu, &bg_set)) {
|
||||
/* the binding cannot contain multiple PUs */
|
||||
hwloc_bitmap_only(hwloc_set, pu);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_bgq_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
if (topology->pid) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
hwloc_bitmap_only(hwloc_set, Kernel_ProcessorID());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_bgq_set_thread_cpubind(hwloc_topology_t topology, pthread_t thread, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
unsigned pu;
|
||||
cpu_set_t bg_set;
|
||||
int err;
|
||||
|
||||
if (topology->pid) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
/* the binding cannot contain multiple PUs.
|
||||
* keep the first PU only, and error out if STRICT.
|
||||
*/
|
||||
if (hwloc_bitmap_weight(hwloc_set) != 1) {
|
||||
if ((flags & HWLOC_CPUBIND_STRICT)) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
pu = hwloc_bitmap_first(hwloc_set);
|
||||
CPU_ZERO(&bg_set);
|
||||
CPU_SET(pu, &bg_set);
|
||||
err = pthread_setaffinity_np(thread, sizeof(bg_set), &bg_set);
|
||||
if (err) {
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_bgq_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
return hwloc_bgq_set_thread_cpubind(topology, pthread_self(), hwloc_set, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_bgq_get_allowed_resources(struct hwloc_topology *topology)
|
||||
{
|
||||
/* Loading BGQ from XML isn't much useful since everything is hardwired anyway.
|
||||
* But still implement XML + this callback in case portable applications want to always use XMLs.
|
||||
*/
|
||||
|
||||
/* In theory, when applying local restrictions to a XML-loaded topology,
|
||||
* we should check that the current topology contains 1 NUMA nodes and 17*4 PUs.
|
||||
*
|
||||
* Just trust the user when he sets THISSYSTEM=1.
|
||||
*/
|
||||
return hwloc_bgq__get_allowed_resources(topology);
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_set_bgq_hooks(struct hwloc_binding_hooks *hooks __hwloc_attribute_unused,
|
||||
struct hwloc_topology_support *support __hwloc_attribute_unused)
|
||||
{
|
||||
hooks->set_thisthread_cpubind = hwloc_bgq_set_thisthread_cpubind;
|
||||
hooks->set_thread_cpubind = hwloc_bgq_set_thread_cpubind;
|
||||
hooks->get_thisthread_cpubind = hwloc_bgq_get_thisthread_cpubind;
|
||||
hooks->get_thread_cpubind = hwloc_bgq_get_thread_cpubind;
|
||||
/* threads cannot be bound to more than one PU, so get_last_cpu_location == get_cpubind */
|
||||
hooks->get_thisthread_last_cpu_location = hwloc_bgq_get_thisthread_cpubind;
|
||||
/* hooks->get_thread_last_cpu_location = hwloc_bgq_get_thread_cpubind; */
|
||||
|
||||
hooks->get_allowed_resources = hwloc_bgq_get_allowed_resources;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_bgq_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct utsname utsname;
|
||||
struct hwloc_backend *backend;
|
||||
int forced_nonbgq = 0;
|
||||
int err;
|
||||
|
||||
err = uname(&utsname);
|
||||
if (err || strcmp(utsname.sysname, "CNK") || strcmp(utsname.machine, "BGQ")) {
|
||||
const char *env = getenv("HWLOC_FORCE_BGQ");
|
||||
if (!env || !atoi(env)) {
|
||||
fprintf(stderr, "*** Found unexpected uname sysname `%s' machine `%s'.\n", utsname.sysname, utsname.machine);
|
||||
fprintf(stderr, "*** The BlueGene/Q backend (bgq) is only enabled by default on compute nodes\n"
|
||||
"*** (where uname returns sysname=CNK and machine=BGQ).\n"
|
||||
"*** If you know you *really* want to run the bgq backend on this non-compute node,\n"
|
||||
"*** set HWLOC_FORCE_BGQ=1 in the environment.\n"
|
||||
"*** If you just want to discover the native topology of this non-compute node,\n"
|
||||
"*** do not pass any BlueGene/Q-specific options on the configure command-line.\n");
|
||||
return NULL;
|
||||
} else {
|
||||
forced_nonbgq = 1;
|
||||
}
|
||||
}
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_look_bgq;
|
||||
if (forced_nonbgq)
|
||||
backend->is_thissystem = 0;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_bgq_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
"bgq",
|
||||
~0,
|
||||
hwloc_bgq_component_instantiate,
|
||||
50,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct hwloc_component hwloc_bgq_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
NULL, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_bgq_disc_component
|
||||
};
|
||||
|
||||
#endif /* !HWLOC_DISABLE_BGQ_PORT_TEST */
|
170
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-cuda.c
Обычный файл
170
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-cuda.c
Обычный файл
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright © 2011 Université Bordeaux
|
||||
* Copyright © 2012-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/plugins.h>
|
||||
#include <hwloc/cudart.h>
|
||||
|
||||
/* private headers allowed for convenience because this plugin is built within hwloc */
|
||||
#include <private/misc.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#include <cuda_runtime_api.h>
|
||||
|
||||
static unsigned hwloc_cuda_cores_per_MP(int major, int minor)
|
||||
{
|
||||
/* FP32 cores per MP, based on CUDA C Programming Guide, Annex G */
|
||||
switch (major) {
|
||||
case 1:
|
||||
switch (minor) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3: return 8;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (minor) {
|
||||
case 0: return 32;
|
||||
case 1: return 48;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
return 192;
|
||||
case 5:
|
||||
return 128;
|
||||
case 6:
|
||||
switch (minor) {
|
||||
case 0: return 64;
|
||||
case 1:
|
||||
case 2: return 128;
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
return 64;
|
||||
}
|
||||
hwloc_debug("unknown compute capability %d.%d, disabling core display.\n", major, minor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_cuda_discover(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
enum hwloc_type_filter_e filter;
|
||||
cudaError_t cures;
|
||||
int nb, i;
|
||||
|
||||
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_OS_DEVICE, &filter);
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
return 0;
|
||||
|
||||
cures = cudaGetDeviceCount(&nb);
|
||||
if (cures)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < nb; i++) {
|
||||
int domain, bus, dev;
|
||||
char cuda_name[32];
|
||||
char number[32];
|
||||
struct cudaDeviceProp prop;
|
||||
hwloc_obj_t cuda_device, parent;
|
||||
unsigned cores;
|
||||
|
||||
cuda_device = hwloc_alloc_setup_object(topology, HWLOC_OBJ_OS_DEVICE, -1);
|
||||
snprintf(cuda_name, sizeof(cuda_name), "cuda%d", i);
|
||||
cuda_device->name = strdup(cuda_name);
|
||||
cuda_device->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN;
|
||||
cuda_device->attr->osdev.type = HWLOC_OBJ_OSDEV_COPROC;
|
||||
|
||||
cuda_device->subtype = strdup("CUDA");
|
||||
hwloc_obj_add_info(cuda_device, "Backend", "CUDA");
|
||||
hwloc_obj_add_info(cuda_device, "GPUVendor", "NVIDIA Corporation");
|
||||
|
||||
cures = cudaGetDeviceProperties(&prop, i);
|
||||
if (!cures)
|
||||
hwloc_obj_add_info(cuda_device, "GPUModel", prop.name);
|
||||
|
||||
snprintf(number, sizeof(number), "%llu", ((unsigned long long) prop.totalGlobalMem) >> 10);
|
||||
hwloc_obj_add_info(cuda_device, "CUDAGlobalMemorySize", number);
|
||||
|
||||
snprintf(number, sizeof(number), "%llu", ((unsigned long long) prop.l2CacheSize) >> 10);
|
||||
hwloc_obj_add_info(cuda_device, "CUDAL2CacheSize", number);
|
||||
|
||||
snprintf(number, sizeof(number), "%d", prop.multiProcessorCount);
|
||||
hwloc_obj_add_info(cuda_device, "CUDAMultiProcessors", number);
|
||||
|
||||
cores = hwloc_cuda_cores_per_MP(prop.major, prop.minor);
|
||||
if (cores) {
|
||||
snprintf(number, sizeof(number), "%u", cores);
|
||||
hwloc_obj_add_info(cuda_device, "CUDACoresPerMP", number);
|
||||
}
|
||||
|
||||
snprintf(number, sizeof(number), "%llu", ((unsigned long long) prop.sharedMemPerBlock) >> 10);
|
||||
hwloc_obj_add_info(cuda_device, "CUDASharedMemorySizePerMP", number);
|
||||
|
||||
parent = NULL;
|
||||
if (hwloc_cudart_get_device_pci_ids(NULL /* topology unused */, i, &domain, &bus, &dev) == 0) {
|
||||
parent = hwloc_pci_belowroot_find_by_busid(topology, domain, bus, dev, 0);
|
||||
if (!parent)
|
||||
parent = hwloc_pci_find_busid_parent(topology, domain, bus, dev, 0);
|
||||
}
|
||||
if (!parent)
|
||||
parent = hwloc_get_root_obj(topology);
|
||||
|
||||
hwloc_insert_object_by_parent(topology, parent, cuda_device);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_cuda_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
/* the first callback will initialize those */
|
||||
backend->discover = hwloc_cuda_discover;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_cuda_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_MISC,
|
||||
"cuda",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_cuda_component_instantiate,
|
||||
10, /* after pci */
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
hwloc_cuda_component_init(unsigned long flags)
|
||||
{
|
||||
if (flags)
|
||||
return -1;
|
||||
if (hwloc_plugin_check_namespace("cuda", "hwloc_backend_alloc") < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_cuda_component;
|
||||
#endif
|
||||
|
||||
const struct hwloc_component hwloc_cuda_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
hwloc_cuda_component_init, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_cuda_disc_component
|
||||
};
|
307
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-darwin.c
Обычный файл
307
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-darwin.c
Обычный файл
@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2013 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/* Detect topology change: registering for power management changes and check
|
||||
* if for example hw.activecpu changed */
|
||||
|
||||
/* Apparently, Darwin people do not _want_ to provide binding functions. */
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
static int
|
||||
hwloc_look_darwin(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
int64_t _nprocs;
|
||||
unsigned nprocs;
|
||||
int64_t _npackages;
|
||||
unsigned i, j, cpu;
|
||||
struct hwloc_obj *obj;
|
||||
size_t size;
|
||||
int64_t l1dcachesize, l1icachesize;
|
||||
int64_t cacheways[2];
|
||||
int64_t l2cachesize;
|
||||
int64_t cachelinesize;
|
||||
int64_t memsize;
|
||||
char cpumodel[64];
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
|
||||
if (hwloc_get_sysctlbyname("hw.ncpu", &_nprocs) || _nprocs <= 0)
|
||||
return -1;
|
||||
nprocs = _nprocs;
|
||||
topology->support.discovery->pu = 1;
|
||||
|
||||
hwloc_debug("%u procs\n", nprocs);
|
||||
|
||||
size = sizeof(cpumodel);
|
||||
if (sysctlbyname("machdep.cpu.brand_string", cpumodel, &size, NULL, 0))
|
||||
cpumodel[0] = '\0';
|
||||
|
||||
if (!hwloc_get_sysctlbyname("hw.packages", &_npackages) && _npackages > 0) {
|
||||
unsigned npackages = _npackages;
|
||||
int64_t _cores_per_package;
|
||||
int64_t _logical_per_package;
|
||||
unsigned logical_per_package;
|
||||
|
||||
hwloc_debug("%u packages\n", npackages);
|
||||
|
||||
if (!hwloc_get_sysctlbyname("machdep.cpu.logical_per_package", &_logical_per_package) && _logical_per_package > 0)
|
||||
logical_per_package = _logical_per_package;
|
||||
else
|
||||
/* Assume the trivia. */
|
||||
logical_per_package = nprocs / npackages;
|
||||
|
||||
hwloc_debug("%u threads per package\n", logical_per_package);
|
||||
|
||||
if (nprocs == npackages * logical_per_package
|
||||
&& hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_PACKAGE))
|
||||
for (i = 0; i < npackages; i++) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PACKAGE, i);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
for (cpu = i*logical_per_package; cpu < (i+1)*logical_per_package; cpu++)
|
||||
hwloc_bitmap_set(obj->cpuset, cpu);
|
||||
|
||||
hwloc_debug_1arg_bitmap("package %u has cpuset %s\n",
|
||||
i, obj->cpuset);
|
||||
|
||||
if (cpumodel[0] != '\0')
|
||||
hwloc_obj_add_info(obj, "CPUModel", cpumodel);
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
else
|
||||
if (cpumodel[0] != '\0')
|
||||
hwloc_obj_add_info(topology->levels[0][0], "CPUModel", cpumodel);
|
||||
|
||||
if (!hwloc_get_sysctlbyname("machdep.cpu.cores_per_package", &_cores_per_package) && _cores_per_package > 0
|
||||
&& hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_CORE)) {
|
||||
unsigned cores_per_package = _cores_per_package;
|
||||
hwloc_debug("%u cores per package\n", cores_per_package);
|
||||
|
||||
if (!(logical_per_package % cores_per_package))
|
||||
for (i = 0; i < npackages * cores_per_package; i++) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_CORE, i);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
for (cpu = i*(logical_per_package/cores_per_package);
|
||||
cpu < (i+1)*(logical_per_package/cores_per_package);
|
||||
cpu++)
|
||||
hwloc_bitmap_set(obj->cpuset, cpu);
|
||||
|
||||
hwloc_debug_1arg_bitmap("core %u has cpuset %s\n",
|
||||
i, obj->cpuset);
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
}
|
||||
} else
|
||||
if (cpumodel[0] != '\0')
|
||||
hwloc_obj_add_info(topology->levels[0][0], "CPUModel", cpumodel);
|
||||
|
||||
if (hwloc_get_sysctlbyname("hw.l1dcachesize", &l1dcachesize))
|
||||
l1dcachesize = 0;
|
||||
|
||||
if (hwloc_get_sysctlbyname("hw.l1icachesize", &l1icachesize))
|
||||
l1icachesize = 0;
|
||||
|
||||
if (hwloc_get_sysctlbyname("hw.l2cachesize", &l2cachesize))
|
||||
l2cachesize = 0;
|
||||
|
||||
if (hwloc_get_sysctlbyname("machdep.cpu.cache.L1_associativity", &cacheways[0]))
|
||||
cacheways[0] = 0;
|
||||
else if (cacheways[0] == 0xff)
|
||||
cacheways[0] = -1;
|
||||
|
||||
if (hwloc_get_sysctlbyname("machdep.cpu.cache.L2_associativity", &cacheways[1]))
|
||||
cacheways[1] = 0;
|
||||
else if (cacheways[1] == 0xff)
|
||||
cacheways[1] = -1;
|
||||
|
||||
if (hwloc_get_sysctlbyname("hw.cachelinesize", &cachelinesize))
|
||||
cachelinesize = 0;
|
||||
|
||||
if (hwloc_get_sysctlbyname("hw.memsize", &memsize))
|
||||
memsize = 0;
|
||||
|
||||
if (!sysctlbyname("hw.cacheconfig", NULL, &size, NULL, 0)) {
|
||||
unsigned n = size / sizeof(uint32_t);
|
||||
uint64_t *cacheconfig = NULL;
|
||||
uint64_t *cachesize = NULL;
|
||||
uint32_t *cacheconfig32 = NULL;
|
||||
|
||||
cacheconfig = malloc(sizeof(uint64_t) * n);
|
||||
if (NULL == cacheconfig) {
|
||||
goto out;
|
||||
}
|
||||
cachesize = malloc(sizeof(uint64_t) * n);
|
||||
if (NULL == cachesize) {
|
||||
goto out;
|
||||
}
|
||||
cacheconfig32 = malloc(sizeof(uint32_t) * n);
|
||||
if (NULL == cacheconfig32) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((!sysctlbyname("hw.cacheconfig", cacheconfig, &size, NULL, 0))) {
|
||||
/* Yeech. Darwin seemingly has changed from 32bit to 64bit integers for
|
||||
* cacheconfig, with apparently no way for detection. Assume the machine
|
||||
* won't have more than 4 billion cpus */
|
||||
if (cacheconfig[0] > 0xFFFFFFFFUL) {
|
||||
memcpy(cacheconfig32, cacheconfig, size);
|
||||
for (i = 0 ; i < size / sizeof(uint32_t); i++)
|
||||
cacheconfig[i] = cacheconfig32[i];
|
||||
}
|
||||
|
||||
memset(cachesize, 0, sizeof(uint64_t) * n);
|
||||
size = sizeof(uint64_t) * n;
|
||||
if (sysctlbyname("hw.cachesize", cachesize, &size, NULL, 0)) {
|
||||
if (n > 0)
|
||||
cachesize[0] = memsize;
|
||||
if (n > 1)
|
||||
cachesize[1] = l1dcachesize;
|
||||
if (n > 2)
|
||||
cachesize[2] = l2cachesize;
|
||||
}
|
||||
|
||||
hwloc_debug("%s", "caches");
|
||||
for (i = 0; i < n && cacheconfig[i]; i++)
|
||||
hwloc_debug(" %"PRIu64"(%"PRIu64"kB)", cacheconfig[i], cachesize[i] / 1024);
|
||||
|
||||
/* Now we know how many caches there are */
|
||||
n = i;
|
||||
hwloc_debug("\n%u cache levels\n", n - 1);
|
||||
|
||||
/* For each cache level (0 is memory) */
|
||||
for (i = 0; i < n; i++) {
|
||||
/* cacheconfig tells us how many cpus share it, let's iterate on each cache */
|
||||
for (j = 0; j < (nprocs / cacheconfig[i]); j++) {
|
||||
if (!i) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_NUMANODE, j);
|
||||
obj->nodeset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(obj->nodeset, j);
|
||||
} else {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1CACHE+i-1, -1);
|
||||
}
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
for (cpu = j*cacheconfig[i];
|
||||
cpu < ((j+1)*cacheconfig[i]);
|
||||
cpu++)
|
||||
hwloc_bitmap_set(obj->cpuset, cpu);
|
||||
|
||||
if (i == 1 && l1icachesize
|
||||
&& hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1ICACHE)) {
|
||||
/* FIXME assuming that L1i and L1d are shared the same way. Darwin
|
||||
* does not yet provide a way to know. */
|
||||
hwloc_obj_t l1i = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1ICACHE, -1);
|
||||
l1i->cpuset = hwloc_bitmap_dup(obj->cpuset);
|
||||
hwloc_debug_1arg_bitmap("L1icache %u has cpuset %s\n",
|
||||
j, l1i->cpuset);
|
||||
l1i->attr->cache.depth = i;
|
||||
l1i->attr->cache.size = l1icachesize;
|
||||
l1i->attr->cache.linesize = cachelinesize;
|
||||
l1i->attr->cache.associativity = 0;
|
||||
l1i->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
|
||||
hwloc_insert_object_by_cpuset(topology, l1i);
|
||||
}
|
||||
if (i) {
|
||||
hwloc_debug_2args_bitmap("L%ucache %u has cpuset %s\n",
|
||||
i, j, obj->cpuset);
|
||||
obj->attr->cache.depth = i;
|
||||
obj->attr->cache.size = cachesize[i];
|
||||
obj->attr->cache.linesize = cachelinesize;
|
||||
if (i <= sizeof(cacheways) / sizeof(cacheways[0]))
|
||||
obj->attr->cache.associativity = cacheways[i-1];
|
||||
else
|
||||
obj->attr->cache.associativity = 0;
|
||||
if (i == 1 && l1icachesize)
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
|
||||
else
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
} else {
|
||||
hwloc_debug_1arg_bitmap("node %u has cpuset %s\n",
|
||||
j, obj->cpuset);
|
||||
obj->memory.local_memory = cachesize[i];
|
||||
obj->memory.page_types_len = 2;
|
||||
obj->memory.page_types = malloc(2*sizeof(*obj->memory.page_types));
|
||||
memset(obj->memory.page_types, 0, 2*sizeof(*obj->memory.page_types));
|
||||
obj->memory.page_types[0].size = hwloc_getpagesize();
|
||||
#if HAVE_DECL__SC_LARGE_PAGESIZE
|
||||
obj->memory.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, obj->type))
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
else
|
||||
hwloc_free_unlinked_object(obj); /* FIXME: don't built at all, just build the cpuset in case l1i needs it */
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
free(cacheconfig);
|
||||
free(cachesize);
|
||||
free(cacheconfig32);
|
||||
}
|
||||
|
||||
|
||||
/* add PU objects */
|
||||
hwloc_setup_pu_level(topology, nprocs);
|
||||
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "Darwin");
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_set_darwin_hooks(struct hwloc_binding_hooks *hooks __hwloc_attribute_unused,
|
||||
struct hwloc_topology_support *support __hwloc_attribute_unused)
|
||||
{
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_darwin_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_look_darwin;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_darwin_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_CPU,
|
||||
"darwin",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_darwin_component_instantiate,
|
||||
50,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct hwloc_component hwloc_darwin_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
NULL, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_darwin_disc_component
|
||||
};
|
61
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-fake.c
Обычный файл
61
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-fake.c
Обычный файл
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright © 2012-2014 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_fake_component_instantiate(struct hwloc_disc_component *component __hwloc_attribute_unused,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
if (getenv("HWLOC_DEBUG_FAKE_COMPONENT"))
|
||||
printf("fake component instantiated\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_fake_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_MISC, /* so that it's always enabled when using the OS discovery */
|
||||
"fake",
|
||||
0, /* nothing to exclude */
|
||||
hwloc_fake_component_instantiate,
|
||||
100, /* make sure it's loaded before anything conflicting excludes it */
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
hwloc_fake_component_init(unsigned long flags)
|
||||
{
|
||||
if (flags)
|
||||
return -1;
|
||||
if (hwloc_plugin_check_namespace("fake", "hwloc_backend_alloc") < 0)
|
||||
return -1;
|
||||
if (getenv("HWLOC_DEBUG_FAKE_COMPONENT"))
|
||||
printf("fake component initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_fake_component_finalize(unsigned long flags)
|
||||
{
|
||||
if (flags)
|
||||
return;
|
||||
if (getenv("HWLOC_DEBUG_FAKE_COMPONENT"))
|
||||
printf("fake component finalized\n");
|
||||
}
|
||||
|
||||
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_fake_component; /* never linked statically in the core */
|
||||
|
||||
const struct hwloc_component hwloc_fake_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
hwloc_fake_component_init, hwloc_fake_component_finalize,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_fake_disc_component
|
||||
};
|
254
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-freebsd.c
Обычный файл
254
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-freebsd.c
Обычный файл
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2015 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010, 2012 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/param.h>
|
||||
#include <pthread.h>
|
||||
#ifdef HAVE_PTHREAD_NP_H
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_CPUSET_H
|
||||
#include <sys/cpuset.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SYSCTL_H
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#if defined(HAVE_SYS_CPUSET_H) && defined(HAVE_CPUSET_SETAFFINITY)
|
||||
static void
|
||||
hwloc_freebsd_bsd2hwloc(hwloc_bitmap_t hwloc_cpuset, const cpuset_t *cset)
|
||||
{
|
||||
unsigned cpu;
|
||||
hwloc_bitmap_zero(hwloc_cpuset);
|
||||
for (cpu = 0; cpu < CPU_SETSIZE; cpu++)
|
||||
if (CPU_ISSET(cpu, cset))
|
||||
hwloc_bitmap_set(hwloc_cpuset, cpu);
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_freebsd_hwloc2bsd(hwloc_const_bitmap_t hwloc_cpuset, cpuset_t *cset)
|
||||
{
|
||||
unsigned cpu;
|
||||
CPU_ZERO(cset);
|
||||
for (cpu = 0; cpu < CPU_SETSIZE; cpu++)
|
||||
if (hwloc_bitmap_isset(hwloc_cpuset, cpu))
|
||||
CPU_SET(cpu, cset);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_freebsd_set_sth_affinity(hwloc_topology_t topology __hwloc_attribute_unused, cpulevel_t level, cpuwhich_t which, id_t id, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
cpuset_t cset;
|
||||
|
||||
hwloc_freebsd_hwloc2bsd(hwloc_cpuset, &cset);
|
||||
|
||||
if (cpuset_setaffinity(level, which, id, sizeof(cset), &cset))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_freebsd_get_sth_affinity(hwloc_topology_t topology __hwloc_attribute_unused, cpulevel_t level, cpuwhich_t which, id_t id, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
cpuset_t cset;
|
||||
|
||||
if (cpuset_getaffinity(level, which, id, sizeof(cset), &cset))
|
||||
return -1;
|
||||
|
||||
hwloc_freebsd_bsd2hwloc(hwloc_cpuset, &cset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_freebsd_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags)
|
||||
{
|
||||
return hwloc_freebsd_set_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, hwloc_cpuset, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_freebsd_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags)
|
||||
{
|
||||
return hwloc_freebsd_get_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, hwloc_cpuset, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_freebsd_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags)
|
||||
{
|
||||
return hwloc_freebsd_set_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, hwloc_cpuset, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_freebsd_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags)
|
||||
{
|
||||
return hwloc_freebsd_get_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, hwloc_cpuset, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_freebsd_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_cpuset, int flags)
|
||||
{
|
||||
return hwloc_freebsd_set_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, hwloc_cpuset, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_freebsd_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t hwloc_cpuset, int flags)
|
||||
{
|
||||
return hwloc_freebsd_get_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, hwloc_cpuset, flags);
|
||||
}
|
||||
|
||||
#ifdef hwloc_thread_t
|
||||
|
||||
#if HAVE_DECL_PTHREAD_SETAFFINITY_NP
|
||||
#pragma weak pthread_setaffinity_np
|
||||
static int
|
||||
hwloc_freebsd_set_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
int err;
|
||||
cpuset_t cset;
|
||||
|
||||
if (!pthread_setaffinity_np) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
hwloc_freebsd_hwloc2bsd(hwloc_cpuset, &cset);
|
||||
|
||||
err = pthread_setaffinity_np(tid, sizeof(cset), &cset);
|
||||
|
||||
if (err) {
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_DECL_PTHREAD_GETAFFINITY_NP
|
||||
#pragma weak pthread_getaffinity_np
|
||||
static int
|
||||
hwloc_freebsd_get_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
int err;
|
||||
cpuset_t cset;
|
||||
|
||||
if (!pthread_getaffinity_np) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = pthread_getaffinity_np(tid, sizeof(cset), &cset);
|
||||
|
||||
if (err) {
|
||||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
hwloc_freebsd_bsd2hwloc(hwloc_cpuset, &cset);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined HAVE_SYSCTL) && (defined HAVE_SYS_SYSCTL_H)
|
||||
static void
|
||||
hwloc_freebsd_node_meminfo_info(struct hwloc_topology *topology)
|
||||
{
|
||||
int mib[2] = { CTL_HW, HW_PHYSMEM };
|
||||
unsigned long physmem;
|
||||
size_t len = sizeof(physmem);
|
||||
sysctl(mib, 2, &physmem, &len, NULL, 0);
|
||||
topology->levels[0][0]->memory.local_memory = physmem;
|
||||
/* we don't know anything about NUMA nodes in this backend.
|
||||
* let another backend or the core move that memory to the right NUMA node */
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
hwloc_look_freebsd(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
unsigned nbprocs = hwloc_fallback_nbprocessors(topology);
|
||||
|
||||
if (!topology->levels[0][0]->cpuset) {
|
||||
/* Nobody (even the x86 backend) created objects yet, setup basic objects */
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
hwloc_setup_pu_level(topology, nbprocs);
|
||||
}
|
||||
|
||||
/* Add FreeBSD specific information */
|
||||
#if (defined HAVE_SYSCTL) && (defined HAVE_SYS_SYSCTL_H)
|
||||
hwloc_freebsd_node_meminfo_info(topology);
|
||||
#endif
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "FreeBSD");
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_set_freebsd_hooks(struct hwloc_binding_hooks *hooks __hwloc_attribute_unused,
|
||||
struct hwloc_topology_support *support __hwloc_attribute_unused)
|
||||
{
|
||||
#if defined(HAVE_SYS_CPUSET_H) && defined(HAVE_CPUSET_SETAFFINITY)
|
||||
hooks->set_thisproc_cpubind = hwloc_freebsd_set_thisproc_cpubind;
|
||||
hooks->get_thisproc_cpubind = hwloc_freebsd_get_thisproc_cpubind;
|
||||
hooks->set_thisthread_cpubind = hwloc_freebsd_set_thisthread_cpubind;
|
||||
hooks->get_thisthread_cpubind = hwloc_freebsd_get_thisthread_cpubind;
|
||||
hooks->set_proc_cpubind = hwloc_freebsd_set_proc_cpubind;
|
||||
hooks->get_proc_cpubind = hwloc_freebsd_get_proc_cpubind;
|
||||
#ifdef hwloc_thread_t
|
||||
#if HAVE_DECL_PTHREAD_SETAFFINITY_NP
|
||||
hooks->set_thread_cpubind = hwloc_freebsd_set_thread_cpubind;
|
||||
#endif
|
||||
#if HAVE_DECL_PTHREAD_GETAFFINITY_NP
|
||||
hooks->get_thread_cpubind = hwloc_freebsd_get_thread_cpubind;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
/* TODO: get_last_cpu_location: find out ki_lastcpu */
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_freebsd_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_look_freebsd;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_freebsd_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_CPU,
|
||||
"freebsd",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_freebsd_component_instantiate,
|
||||
50,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct hwloc_component hwloc_freebsd_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
NULL, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_freebsd_disc_component
|
||||
};
|
185
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-gl.c
Обычный файл
185
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-gl.c
Обычный файл
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright © 2012-2013 Blue Brain Project, BBP/EPFL. All rights reserved.
|
||||
* Copyright © 2012-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/plugins.h>
|
||||
|
||||
/* private headers allowed for convenience because this plugin is built within hwloc */
|
||||
#include <private/misc.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <NVCtrl/NVCtrl.h>
|
||||
#include <NVCtrl/NVCtrlLib.h>
|
||||
|
||||
#define HWLOC_GL_SERVER_MAX 10
|
||||
#define HWLOC_GL_SCREEN_MAX 10
|
||||
|
||||
static int
|
||||
hwloc_gl_discover(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
enum hwloc_type_filter_e filter;
|
||||
unsigned i;
|
||||
int err;
|
||||
|
||||
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_OS_DEVICE, &filter);
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < HWLOC_GL_SERVER_MAX; ++i) {
|
||||
Display* display;
|
||||
char displayName[10];
|
||||
int opcode, event, error;
|
||||
unsigned j;
|
||||
|
||||
/* open X server */
|
||||
snprintf(displayName, sizeof(displayName), ":%u", i);
|
||||
display = XOpenDisplay(displayName);
|
||||
if (!display)
|
||||
continue;
|
||||
|
||||
/* Check for NV-CONTROL extension (it's per server) */
|
||||
if(!XQueryExtension(display, "NV-CONTROL", &opcode, &event, &error)) {
|
||||
XCloseDisplay(display);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0; j < (unsigned) ScreenCount(display) && j < HWLOC_GL_SCREEN_MAX; j++) {
|
||||
hwloc_obj_t osdev, parent;
|
||||
const int screen = j;
|
||||
unsigned int *ptr_binary_data;
|
||||
int data_length;
|
||||
int gpu_number;
|
||||
int nv_ctrl_pci_bus;
|
||||
int nv_ctrl_pci_device;
|
||||
int nv_ctrl_pci_domain;
|
||||
int nv_ctrl_pci_func;
|
||||
char *productname;
|
||||
char name[64];
|
||||
|
||||
/* the server supports NV-CONTROL but it may contain non-NVIDIA screen that don't support it */
|
||||
if (!XNVCTRLIsNvScreen(display, screen))
|
||||
continue;
|
||||
|
||||
/* Gets the GPU number attached to the default screen. */
|
||||
/* For further details, see the <NVCtrl/NVCtrlLib.h> */
|
||||
err = XNVCTRLQueryTargetBinaryData (display, NV_CTRL_TARGET_TYPE_X_SCREEN, screen, 0,
|
||||
NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN,
|
||||
(unsigned char **) &ptr_binary_data, &data_length);
|
||||
if (!err)
|
||||
continue;
|
||||
|
||||
gpu_number = ptr_binary_data[1];
|
||||
free(ptr_binary_data);
|
||||
|
||||
#ifdef NV_CTRL_PCI_DOMAIN
|
||||
/* Gets the ID's of the GPU defined by gpu_number
|
||||
* For further details, see the <NVCtrl/NVCtrlLib.h> */
|
||||
err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
|
||||
NV_CTRL_PCI_DOMAIN, &nv_ctrl_pci_domain);
|
||||
if (!err)
|
||||
continue;
|
||||
#else
|
||||
nv_ctrl_pci_domain = 0;
|
||||
#endif
|
||||
|
||||
err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
|
||||
NV_CTRL_PCI_BUS, &nv_ctrl_pci_bus);
|
||||
if (!err)
|
||||
continue;
|
||||
|
||||
err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
|
||||
NV_CTRL_PCI_DEVICE, &nv_ctrl_pci_device);
|
||||
if (!err)
|
||||
continue;
|
||||
|
||||
err = XNVCTRLQueryTargetAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
|
||||
NV_CTRL_PCI_FUNCTION, &nv_ctrl_pci_func);
|
||||
if (!err)
|
||||
continue;
|
||||
|
||||
productname = NULL;
|
||||
err = XNVCTRLQueryTargetStringAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
|
||||
NV_CTRL_STRING_PRODUCT_NAME, &productname);
|
||||
|
||||
snprintf(name, sizeof(name), ":%u.%u", i, j);
|
||||
|
||||
osdev = hwloc_alloc_setup_object(topology, HWLOC_OBJ_OS_DEVICE, -1);
|
||||
osdev->name = strdup(name);
|
||||
osdev->logical_index = -1;
|
||||
osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_GPU;
|
||||
hwloc_obj_add_info(osdev, "Backend", "GL");
|
||||
hwloc_obj_add_info(osdev, "GPUVendor", "NVIDIA Corporation");
|
||||
if (productname)
|
||||
hwloc_obj_add_info(osdev, "GPUModel", productname);
|
||||
|
||||
parent = hwloc_pci_belowroot_find_by_busid(topology, nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func);
|
||||
if (!parent)
|
||||
parent = hwloc_pci_find_busid_parent(topology, nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func);
|
||||
if (!parent)
|
||||
parent = hwloc_get_root_obj(topology);
|
||||
|
||||
hwloc_insert_object_by_parent(topology, parent, osdev);
|
||||
|
||||
hwloc_debug("GL device %s (product %s) on PCI %04x:%02x:%02x.%01x\n",
|
||||
name, productname,
|
||||
(unsigned) nv_ctrl_pci_domain, (unsigned) nv_ctrl_pci_bus, (unsigned) nv_ctrl_pci_device, (unsigned) nv_ctrl_pci_func);
|
||||
}
|
||||
XCloseDisplay(display);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_gl_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_gl_discover;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_gl_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_MISC,
|
||||
"gl",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_gl_component_instantiate,
|
||||
10, /* after pci */
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
hwloc_gl_component_init(unsigned long flags)
|
||||
{
|
||||
if (flags)
|
||||
return -1;
|
||||
if (hwloc_plugin_check_namespace("gl", "hwloc_backend_alloc") < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_gl_component;
|
||||
#endif
|
||||
|
||||
const struct hwloc_component hwloc_gl_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
hwloc_gl_component_init, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_gl_disc_component
|
||||
};
|
223
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-hardwired.c
Обычный файл
223
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-hardwired.c
Обычный файл
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright © 2015-2016 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
|
||||
int hwloc_look_hardwired_fujitsu_k(struct hwloc_topology *topology)
|
||||
{
|
||||
/* If a broken core gets disabled, its bit disappears and other core bits are NOT shifted towards 0.
|
||||
* Node is not given to user job, not need to handle that case properly.
|
||||
*/
|
||||
unsigned i;
|
||||
hwloc_obj_t obj;
|
||||
hwloc_bitmap_t set;
|
||||
|
||||
for(i=0; i<8; i++) {
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(set, i);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1ICACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1ICACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 32*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 2;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 32*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 2;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_CORE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_CORE, i);
|
||||
obj->cpuset = set;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
}
|
||||
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(set, 0, 7);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L2CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L2CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
obj->attr->cache.depth = 2;
|
||||
obj->attr->cache.size = 6*1024*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 12;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_PACKAGE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PACKAGE, 0);
|
||||
obj->cpuset = set;
|
||||
hwloc_obj_add_info(obj, "CPUVendor", "Fujitsu");
|
||||
hwloc_obj_add_info(obj, "CPUModel", "SPARC64 VIIIfx");
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
|
||||
hwloc_setup_pu_level(topology, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hwloc_look_hardwired_fujitsu_fx10(struct hwloc_topology *topology)
|
||||
{
|
||||
/* If a broken core gets disabled, its bit disappears and other core bits are NOT shifted towards 0.
|
||||
* Node is not given to user job, not need to handle that case properly.
|
||||
*/
|
||||
unsigned i;
|
||||
hwloc_obj_t obj;
|
||||
hwloc_bitmap_t set;
|
||||
|
||||
for(i=0; i<16; i++) {
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(set, i);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1ICACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1ICACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 32*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 2;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 32*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 2;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_CORE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_CORE, i);
|
||||
obj->cpuset = set;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
}
|
||||
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(set, 0, 15);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L2CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L2CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
obj->attr->cache.depth = 2;
|
||||
obj->attr->cache.size = 12*1024*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 24;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_PACKAGE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PACKAGE, 0);
|
||||
obj->cpuset = set;
|
||||
hwloc_obj_add_info(obj, "CPUVendor", "Fujitsu");
|
||||
hwloc_obj_add_info(obj, "CPUModel", "SPARC64 IXfx");
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
|
||||
hwloc_setup_pu_level(topology, 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hwloc_look_hardwired_fujitsu_fx100(struct hwloc_topology *topology)
|
||||
{
|
||||
/* If a broken core gets disabled, its bit disappears and other core bits are NOT shifted towards 0.
|
||||
* Node is not given to user job, not need to handle that case properly.
|
||||
*/
|
||||
unsigned i;
|
||||
hwloc_obj_t obj;
|
||||
hwloc_bitmap_t set;
|
||||
|
||||
for(i=0; i<34; i++) {
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(set, i);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1ICACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1ICACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 64*1024;
|
||||
obj->attr->cache.linesize = 256;
|
||||
obj->attr->cache.associativity = 4;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 64*1024;
|
||||
obj->attr->cache.linesize = 256;
|
||||
obj->attr->cache.associativity = 4;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_CORE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_CORE, i);
|
||||
obj->cpuset = set;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
}
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L2CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L2CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(obj->cpuset, 0, 15);
|
||||
hwloc_bitmap_set(obj->cpuset, 32);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
obj->attr->cache.depth = 2;
|
||||
obj->attr->cache.size = 12*1024*1024;
|
||||
obj->attr->cache.linesize = 256;
|
||||
obj->attr->cache.associativity = 24;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L2CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(obj->cpuset, 16, 31);
|
||||
hwloc_bitmap_set(obj->cpuset, 33);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
obj->attr->cache.depth = 2;
|
||||
obj->attr->cache.size = 12*1024*1024;
|
||||
obj->attr->cache.linesize = 256;
|
||||
obj->attr->cache.associativity = 24;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_PACKAGE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PACKAGE, 0);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(obj->cpuset, 0, 33);
|
||||
hwloc_obj_add_info(obj, "CPUVendor", "Fujitsu");
|
||||
hwloc_obj_add_info(obj, "CPUModel", "SPARC64 XIfx");
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
|
||||
hwloc_setup_pu_level(topology, 34);
|
||||
|
||||
return 0;
|
||||
}
|
312
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-hpux.c
Обычный файл
312
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-hpux.c
Обычный файл
@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010, 2013 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/* TODO: psets? (Only for root)
|
||||
* since 11i 1.6:
|
||||
_SC_PSET_SUPPORT
|
||||
pset_create/destroy/assign/setattr
|
||||
pset_ctl/getattr
|
||||
pset_bind()
|
||||
pthread_pset_bind_np()
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#include <sys/mpctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pthread.h>
|
||||
|
||||
static ldom_t
|
||||
hwloc_hpux_find_ldom(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set)
|
||||
{
|
||||
int has_numa = sysconf(_SC_CCNUMA_SUPPORT) == 1;
|
||||
hwloc_obj_t obj;
|
||||
|
||||
if (!has_numa)
|
||||
return -1;
|
||||
|
||||
obj = hwloc_get_first_largest_obj_inside_cpuset(topology, hwloc_set);
|
||||
if (!hwloc_bitmap_isequal(obj->cpuset, hwloc_set))
|
||||
/* Does not correspond to exactly one node */
|
||||
return -1;
|
||||
/* obj is the highest possibly matching object, but some (single) child (with same cpuset) could match too */
|
||||
while (obj->type != HWLOC_OBJ_NUMANODE) {
|
||||
/* try the first child, in case it has the same cpuset */
|
||||
if (!obj->first_child
|
||||
|| !obj->first_child->cpuset
|
||||
|| !hwloc_bitmap_isequal(obj->cpuset, obj->first_child->cpuset))
|
||||
return -1;
|
||||
obj = obj->first_child;
|
||||
}
|
||||
|
||||
return obj->os_index;
|
||||
}
|
||||
|
||||
static spu_t
|
||||
hwloc_hpux_find_spu(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t hwloc_set)
|
||||
{
|
||||
spu_t cpu;
|
||||
|
||||
cpu = hwloc_bitmap_first(hwloc_set);
|
||||
if (cpu != -1 && hwloc_bitmap_weight(hwloc_set) == 1)
|
||||
return cpu;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Note: get_cpubind not available on HP-UX */
|
||||
static int
|
||||
hwloc_hpux_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
ldom_t ldom;
|
||||
spu_t cpu;
|
||||
|
||||
/* Drop previous binding */
|
||||
mpctl(MPC_SETLDOM, MPC_LDOMFLOAT, pid);
|
||||
mpctl(MPC_SETPROCESS, MPC_SPUFLOAT, pid);
|
||||
|
||||
if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology)))
|
||||
return 0;
|
||||
|
||||
ldom = hwloc_hpux_find_ldom(topology, hwloc_set);
|
||||
if (ldom != -1)
|
||||
return mpctl(MPC_SETLDOM, ldom, pid);
|
||||
|
||||
cpu = hwloc_hpux_find_spu(topology, hwloc_set);
|
||||
if (cpu != -1)
|
||||
return mpctl((flags & HWLOC_CPUBIND_STRICT) ? MPC_SETPROCESS_FORCE : MPC_SETPROCESS, cpu, pid);
|
||||
|
||||
errno = EXDEV;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_hpux_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
return hwloc_hpux_set_proc_cpubind(topology, MPC_SELFPID, hwloc_set, flags);
|
||||
}
|
||||
|
||||
#ifdef hwloc_thread_t
|
||||
static int
|
||||
hwloc_hpux_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
ldom_t ldom, ldom2;
|
||||
spu_t cpu, cpu2;
|
||||
|
||||
/* Drop previous binding */
|
||||
pthread_ldom_bind_np(&ldom2, PTHREAD_LDOMFLOAT_NP, pthread);
|
||||
pthread_processor_bind_np(PTHREAD_BIND_ADVISORY_NP, &cpu2, PTHREAD_SPUFLOAT_NP, pthread);
|
||||
|
||||
if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology)))
|
||||
return 0;
|
||||
|
||||
ldom = hwloc_hpux_find_ldom(topology, hwloc_set);
|
||||
if (ldom != -1)
|
||||
return pthread_ldom_bind_np(&ldom2, ldom, pthread);
|
||||
|
||||
cpu = hwloc_hpux_find_spu(topology, hwloc_set);
|
||||
if (cpu != -1)
|
||||
return pthread_processor_bind_np((flags & HWLOC_CPUBIND_STRICT) ? PTHREAD_BIND_FORCED_NP : PTHREAD_BIND_ADVISORY_NP, &cpu2, cpu, pthread);
|
||||
|
||||
errno = EXDEV;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_hpux_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
return hwloc_hpux_set_thread_cpubind(topology, PTHREAD_SELFTID_NP, hwloc_set, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* According to HP docs, HP-UX up to 11iv2 don't support migration */
|
||||
|
||||
#ifdef MAP_MEM_FIRST_TOUCH
|
||||
static void*
|
||||
hwloc_hpux_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
int mmap_flags;
|
||||
void *p;
|
||||
|
||||
/* Can not give a set of nodes. */
|
||||
if (!hwloc_bitmap_isequal(nodeset, hwloc_topology_get_complete_nodeset(topology))) {
|
||||
errno = EXDEV;
|
||||
return hwloc_alloc_or_fail(topology, len, flags);
|
||||
}
|
||||
|
||||
switch (policy) {
|
||||
case HWLOC_MEMBIND_DEFAULT:
|
||||
case HWLOC_MEMBIND_BIND:
|
||||
mmap_flags = 0;
|
||||
break;
|
||||
case HWLOC_MEMBIND_FIRSTTOUCH:
|
||||
mmap_flags = MAP_MEM_FIRST_TOUCH;
|
||||
break;
|
||||
case HWLOC_MEMBIND_INTERLEAVE:
|
||||
mmap_flags = MAP_MEM_INTERLEAVED;
|
||||
break;
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | mmap_flags, -1, 0);
|
||||
return p == MAP_FAILED ? NULL : p;
|
||||
}
|
||||
#endif /* MAP_MEM_FIRST_TOUCH */
|
||||
|
||||
static int
|
||||
hwloc_look_hpux(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
int has_numa = sysconf(_SC_CCNUMA_SUPPORT) == 1;
|
||||
hwloc_obj_t *nodes = NULL, obj;
|
||||
spu_t currentcpu;
|
||||
ldom_t currentnode;
|
||||
int i, nbnodes = 0;
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
|
||||
if (has_numa) {
|
||||
nbnodes = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
|
||||
MPC_GETNUMLDOMS_SYS : MPC_GETNUMLDOMS, 0, 0);
|
||||
|
||||
hwloc_debug("%d nodes\n", nbnodes);
|
||||
|
||||
nodes = malloc(nbnodes * sizeof(*nodes));
|
||||
|
||||
i = 0;
|
||||
currentnode = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
|
||||
MPC_GETFIRSTLDOM_SYS : MPC_GETFIRSTLDOM, 0, 0);
|
||||
while (currentnode != -1 && i < nbnodes) {
|
||||
hwloc_debug("node %d is %d\n", i, currentnode);
|
||||
nodes[i] = obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_NUMANODE, currentnode);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
obj->nodeset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(obj->nodeset, currentnode);
|
||||
/* TODO: obj->attr->node.memory_kB */
|
||||
/* TODO: obj->attr->node.huge_page_free */
|
||||
|
||||
currentnode = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
|
||||
MPC_GETNEXTLDOM_SYS : MPC_GETNEXTLDOM, currentnode, 0);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
currentcpu = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
|
||||
MPC_GETFIRSTSPU_SYS : MPC_GETFIRSTSPU, 0,0);
|
||||
while (currentcpu != -1) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PU, currentcpu);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(obj->cpuset, currentcpu);
|
||||
|
||||
hwloc_debug("cpu %d\n", currentcpu);
|
||||
|
||||
if (nodes) {
|
||||
/* Add this cpu to its node */
|
||||
currentnode = mpctl(MPC_SPUTOLDOM, currentcpu, 0);
|
||||
/* Hopefully it's just the same as previous cpu */
|
||||
if (i >= nbnodes || (ldom_t) nodes[i]->os_index != currentnode)
|
||||
for (i = 0; i < nbnodes; i++)
|
||||
if ((ldom_t) nodes[i]->os_index == currentnode)
|
||||
break;
|
||||
if (i < nbnodes) {
|
||||
hwloc_bitmap_set(nodes[i]->cpuset, currentcpu);
|
||||
hwloc_debug("is in node %d\n", i);
|
||||
} else {
|
||||
hwloc_debug("%s", "is in no node?!\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Add cpu */
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
|
||||
currentcpu = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
|
||||
MPC_GETNEXTSPU_SYS : MPC_GETNEXTSPU, currentcpu, 0);
|
||||
}
|
||||
|
||||
if (nodes) {
|
||||
/* Add nodes */
|
||||
for (i = 0 ; i < nbnodes ; i++)
|
||||
hwloc_insert_object_by_cpuset(topology, nodes[i]);
|
||||
free(nodes);
|
||||
}
|
||||
|
||||
topology->support.discovery->pu = 1;
|
||||
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "HP-UX");
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_set_hpux_hooks(struct hwloc_binding_hooks *hooks,
|
||||
struct hwloc_topology_support *support __hwloc_attribute_unused)
|
||||
{
|
||||
hooks->set_proc_cpubind = hwloc_hpux_set_proc_cpubind;
|
||||
hooks->set_thisproc_cpubind = hwloc_hpux_set_thisproc_cpubind;
|
||||
#ifdef hwloc_thread_t
|
||||
hooks->set_thread_cpubind = hwloc_hpux_set_thread_cpubind;
|
||||
hooks->set_thisthread_cpubind = hwloc_hpux_set_thisthread_cpubind;
|
||||
#endif
|
||||
#ifdef MAP_MEM_FIRST_TOUCH
|
||||
hooks->alloc_membind = hwloc_hpux_alloc_membind;
|
||||
hooks->alloc = hwloc_alloc_mmap;
|
||||
hooks->free_membind = hwloc_free_mmap;
|
||||
support->membind->firsttouch_membind = 1;
|
||||
support->membind->bind_membind = 1;
|
||||
support->membind->interleave_membind = 1;
|
||||
#endif /* MAP_MEM_FIRST_TOUCH */
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_hpux_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_look_hpux;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_hpux_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_CPU,
|
||||
"hpux",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_hpux_component_instantiate,
|
||||
50,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct hwloc_component hwloc_hpux_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
NULL, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_hpux_disc_component
|
||||
};
|
5790
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-linux.c
Обычный файл
5790
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-linux.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
213
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-netbsd.c
Обычный файл
213
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-netbsd.c
Обычный файл
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright © 2012 Aleksej Saushev, The NetBSD Foundation
|
||||
* Copyright © 2009-2015 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#define _NETBSD_SOURCE /* request "_np" functions */
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/param.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#ifdef HAVE_SYS_SYSCTL_H
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
static void
|
||||
hwloc_netbsd_bsd2hwloc(hwloc_bitmap_t hwloc_cpuset, const cpuset_t *cpuset)
|
||||
{
|
||||
unsigned cpu, cpulimit;
|
||||
int found = 0;
|
||||
hwloc_bitmap_zero(hwloc_cpuset);
|
||||
cpulimit = cpuset_size(cpuset) * CHAR_BIT;
|
||||
for (cpu = 0; cpu < cpulimit; cpu++)
|
||||
if (cpuset_isset(cpu, cpuset)) {
|
||||
hwloc_bitmap_set(hwloc_cpuset, cpu);
|
||||
found++;
|
||||
}
|
||||
/* when never bound, it returns an empty set, fill it instead */
|
||||
if (!found)
|
||||
hwloc_bitmap_fill(hwloc_cpuset);
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_netbsd_hwloc2bsd(hwloc_const_bitmap_t hwloc_cpuset, cpuset_t *cpuset)
|
||||
{
|
||||
unsigned cpu, cpulimit;
|
||||
cpuset_zero(cpuset);
|
||||
cpulimit = cpuset_size(cpuset) * CHAR_BIT;
|
||||
for (cpu = 0; cpu < cpulimit; cpu++)
|
||||
if (hwloc_bitmap_isset(hwloc_cpuset, cpu))
|
||||
cpuset_set(cpu, cpuset);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_netbsd_set_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
int status;
|
||||
cpuset_t *cpuset = cpuset_create();
|
||||
hwloc_netbsd_hwloc2bsd(hwloc_cpuset, cpuset);
|
||||
status = sched_setaffinity_np(pid, cpuset_size(cpuset), cpuset);
|
||||
cpuset_destroy(cpuset);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_netbsd_get_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
int status;
|
||||
cpuset_t *cpuset = cpuset_create();
|
||||
status = sched_getaffinity_np(pid, cpuset_size(cpuset), cpuset);
|
||||
hwloc_netbsd_bsd2hwloc(hwloc_cpuset, cpuset);
|
||||
cpuset_destroy(cpuset);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
hwloc_netbsd_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags)
|
||||
{
|
||||
return hwloc_netbsd_set_proc_cpubind(topology, 0, hwloc_cpuset, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_netbsd_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags)
|
||||
{
|
||||
return hwloc_netbsd_get_proc_cpubind(topology, 0, hwloc_cpuset, flags);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
hwloc_netbsd_set_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
int status;
|
||||
cpuset_t *cpuset = cpuset_create();
|
||||
hwloc_netbsd_hwloc2bsd(hwloc_cpuset, cpuset);
|
||||
status = pthread_setaffinity_np(tid, cpuset_size(cpuset), cpuset);
|
||||
cpuset_destroy(cpuset);
|
||||
|
||||
if (status) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_netbsd_get_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
int status;
|
||||
cpuset_t *cpuset = cpuset_create();
|
||||
status = pthread_getaffinity_np(tid, cpuset_size(cpuset), cpuset);
|
||||
hwloc_netbsd_bsd2hwloc(hwloc_cpuset, cpuset);
|
||||
cpuset_destroy(cpuset);
|
||||
|
||||
if (status) {
|
||||
errno = status;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
hwloc_netbsd_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags)
|
||||
{
|
||||
return hwloc_netbsd_set_thread_cpubind(topology, pthread_self(), hwloc_cpuset, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_netbsd_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags)
|
||||
{
|
||||
return hwloc_netbsd_get_thread_cpubind(topology, pthread_self(), hwloc_cpuset, flags);
|
||||
}
|
||||
|
||||
#if (defined HAVE_SYSCTL) && (defined HAVE_SYS_SYSCTL_H)
|
||||
static void
|
||||
hwloc_netbsd_node_meminfo_info(struct hwloc_topology *topology)
|
||||
{
|
||||
int mib[2] = { CTL_HW, HW_PHYSMEM64 };
|
||||
unsigned long physmem;
|
||||
size_t len = sizeof(physmem);
|
||||
sysctl(mib, 2, &physmem, &len, NULL, 0);
|
||||
topology->levels[0][0]->memory.local_memory = physmem;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
hwloc_look_netbsd(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
unsigned nbprocs = hwloc_fallback_nbprocessors(topology);
|
||||
|
||||
if (!topology->levels[0][0]->cpuset) {
|
||||
/* Nobody (even the x86 backend) created objects yet, setup basic objects */
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
hwloc_setup_pu_level(topology, nbprocs);
|
||||
}
|
||||
|
||||
/* Add NetBSD specific information */
|
||||
#if (defined HAVE_SYSCTL) && (defined HAVE_SYS_SYSCTL_H)
|
||||
hwloc_netbsd_node_meminfo_info(topology);
|
||||
#endif
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "NetBSD");
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_set_netbsd_hooks(struct hwloc_binding_hooks *hooks __hwloc_attribute_unused,
|
||||
struct hwloc_topology_support *support __hwloc_attribute_unused)
|
||||
{
|
||||
hooks->set_proc_cpubind = hwloc_netbsd_set_proc_cpubind;
|
||||
hooks->get_proc_cpubind = hwloc_netbsd_get_proc_cpubind;
|
||||
hooks->set_thisproc_cpubind = hwloc_netbsd_set_thisproc_cpubind;
|
||||
hooks->get_thisproc_cpubind = hwloc_netbsd_get_thisproc_cpubind;
|
||||
|
||||
hooks->set_thread_cpubind = hwloc_netbsd_set_thread_cpubind;
|
||||
hooks->get_thread_cpubind = hwloc_netbsd_get_thread_cpubind;
|
||||
hooks->set_thisthread_cpubind = hwloc_netbsd_set_thisthread_cpubind;
|
||||
hooks->get_thisthread_cpubind = hwloc_netbsd_get_thisthread_cpubind;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_netbsd_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_look_netbsd;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_netbsd_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_CPU,
|
||||
"netbsd",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_netbsd_component_instantiate,
|
||||
50,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct hwloc_component hwloc_netbsd_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
NULL, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_netbsd_disc_component
|
||||
};
|
57
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-noos.c
Обычный файл
57
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-noos.c
Обычный файл
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2015 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
|
||||
static int
|
||||
hwloc_look_noos(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
hwloc_setup_pu_level(topology, hwloc_fallback_nbprocessors(topology));
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_noos_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_look_noos;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_noos_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_CPU,
|
||||
"no_os",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_noos_component_instantiate,
|
||||
40, /* lower than native OS component, higher than globals */
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct hwloc_component hwloc_noos_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
NULL, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_noos_disc_component
|
||||
};
|
146
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-nvml.c
Обычный файл
146
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-nvml.c
Обычный файл
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright © 2012-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/plugins.h>
|
||||
|
||||
/* private headers allowed for convenience because this plugin is built within hwloc */
|
||||
#include <private/misc.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#include <nvml.h>
|
||||
|
||||
static int
|
||||
hwloc_nvml_discover(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
enum hwloc_type_filter_e filter;
|
||||
nvmlReturn_t ret;
|
||||
unsigned nb, i;
|
||||
|
||||
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_OS_DEVICE, &filter);
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
return 0;
|
||||
|
||||
ret = nvmlInit();
|
||||
if (NVML_SUCCESS != ret)
|
||||
return -1;
|
||||
ret = nvmlDeviceGetCount(&nb);
|
||||
if (NVML_SUCCESS != ret || !nb) {
|
||||
nvmlShutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(i=0; i<nb; i++) {
|
||||
nvmlPciInfo_t pci;
|
||||
nvmlDevice_t device;
|
||||
hwloc_obj_t osdev, parent;
|
||||
char buffer[64];
|
||||
|
||||
ret = nvmlDeviceGetHandleByIndex(i, &device);
|
||||
assert(ret == NVML_SUCCESS);
|
||||
|
||||
osdev = hwloc_alloc_setup_object(topology, HWLOC_OBJ_OS_DEVICE, -1);
|
||||
snprintf(buffer, sizeof(buffer), "nvml%u", i);
|
||||
osdev->name = strdup(buffer);
|
||||
osdev->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN;
|
||||
osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_GPU;
|
||||
|
||||
hwloc_obj_add_info(osdev, "Backend", "NVML");
|
||||
hwloc_obj_add_info(osdev, "GPUVendor", "NVIDIA Corporation");
|
||||
|
||||
buffer[0] = '\0';
|
||||
ret = nvmlDeviceGetName(device, buffer, sizeof(buffer));
|
||||
hwloc_obj_add_info(osdev, "GPUModel", buffer);
|
||||
|
||||
/* these may fail with NVML_ERROR_NOT_SUPPORTED on old devices */
|
||||
buffer[0] = '\0';
|
||||
ret = nvmlDeviceGetSerial(device, buffer, sizeof(buffer));
|
||||
if (buffer[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "NVIDIASerial", buffer);
|
||||
|
||||
buffer[0] = '\0';
|
||||
ret = nvmlDeviceGetUUID(device, buffer, sizeof(buffer));
|
||||
if (buffer[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "NVIDIAUUID", buffer);
|
||||
|
||||
parent = NULL;
|
||||
if (NVML_SUCCESS == nvmlDeviceGetPciInfo(device, &pci)) {
|
||||
parent = hwloc_pci_belowroot_find_by_busid(topology, pci.domain, pci.bus, pci.device, 0);
|
||||
if (!parent)
|
||||
parent = hwloc_pci_find_busid_parent(topology, pci.domain, pci.bus, pci.device, 0);
|
||||
#if HAVE_DECL_NVMLDEVICEGETMAXPCIELINKGENERATION
|
||||
if (parent && parent->type == HWLOC_OBJ_PCI_DEVICE) {
|
||||
unsigned maxwidth = 0, maxgen = 0;
|
||||
float lanespeed;
|
||||
nvmlDeviceGetMaxPcieLinkWidth(device, &maxwidth);
|
||||
nvmlDeviceGetMaxPcieLinkGeneration(device, &maxgen);
|
||||
/* PCIe Gen1 = 2.5GT/s signal-rate per lane with 8/10 encoding = 0.25GB/s data-rate per lane
|
||||
* PCIe Gen2 = 5 GT/s signal-rate per lane with 8/10 encoding = 0.5 GB/s data-rate per lane
|
||||
* PCIe Gen3 = 8 GT/s signal-rate per lane with 128/130 encoding = 1 GB/s data-rate per lane
|
||||
*/
|
||||
lanespeed = maxgen <= 2 ? 2.5 * maxgen * 0.8 : 8.0 * 128/130; /* Gbit/s per lane */
|
||||
if (lanespeed * maxwidth != 0.)
|
||||
/* we found the max link speed, replace the current link speed found by pci (or none) */
|
||||
parent->attr->pcidev.linkspeed = lanespeed * maxwidth / 8; /* GB/s */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (!parent)
|
||||
parent = hwloc_get_root_obj(topology);
|
||||
|
||||
hwloc_insert_object_by_parent(topology, parent, osdev);
|
||||
}
|
||||
|
||||
nvmlShutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_nvml_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_nvml_discover;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_nvml_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_MISC,
|
||||
"nvml",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_nvml_component_instantiate,
|
||||
5, /* after pci, and after cuda since likely less useful */
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
hwloc_nvml_component_init(unsigned long flags)
|
||||
{
|
||||
if (flags)
|
||||
return -1;
|
||||
if (hwloc_plugin_check_namespace("nvml", "hwloc_backend_alloc") < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_nvml_component;
|
||||
#endif
|
||||
|
||||
const struct hwloc_component hwloc_nvml_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
hwloc_nvml_component_init, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_nvml_disc_component
|
||||
};
|
203
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-opencl.c
Обычный файл
203
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-opencl.c
Обычный файл
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright © 2012-2017 Inria. All rights reserved.
|
||||
* Copyright © 2013 Université Bordeaux. All right reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/plugins.h>
|
||||
|
||||
/* private headers allowed for convenience because this plugin is built within hwloc */
|
||||
#include <private/misc.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#include <CL/cl_ext.h>
|
||||
|
||||
static int
|
||||
hwloc_opencl_discover(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
enum hwloc_type_filter_e filter;
|
||||
cl_platform_id *platform_ids = NULL;
|
||||
cl_uint nr_platforms;
|
||||
cl_int clret;
|
||||
unsigned j;
|
||||
|
||||
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_OS_DEVICE, &filter);
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
return 0;
|
||||
|
||||
clret = clGetPlatformIDs(0, NULL, &nr_platforms);
|
||||
if (CL_SUCCESS != clret || !nr_platforms)
|
||||
return -1;
|
||||
hwloc_debug("%u OpenCL platforms\n", nr_platforms);
|
||||
platform_ids = malloc(nr_platforms * sizeof(*platform_ids));
|
||||
if (!platform_ids)
|
||||
return -1;
|
||||
clret = clGetPlatformIDs(nr_platforms, platform_ids, &nr_platforms);
|
||||
if (CL_SUCCESS != clret || !nr_platforms) {
|
||||
free(platform_ids);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(j=0; j<nr_platforms; j++) {
|
||||
cl_device_id *device_ids = NULL;
|
||||
cl_uint nr_devices;
|
||||
unsigned i;
|
||||
|
||||
clret = clGetDeviceIDs(platform_ids[j], CL_DEVICE_TYPE_ALL, 0, NULL, &nr_devices);
|
||||
if (CL_SUCCESS != clret)
|
||||
continue;
|
||||
device_ids = malloc(nr_devices * sizeof(*device_ids));
|
||||
clret = clGetDeviceIDs(platform_ids[j], CL_DEVICE_TYPE_ALL, nr_devices, device_ids, &nr_devices);
|
||||
if (CL_SUCCESS != clret) {
|
||||
free(device_ids);
|
||||
continue;
|
||||
}
|
||||
|
||||
for(i=0; i<nr_devices; i++) {
|
||||
cl_platform_id platform_id = 0;
|
||||
cl_device_type type;
|
||||
#ifdef CL_DEVICE_TOPOLOGY_AMD
|
||||
cl_device_topology_amd amdtopo;
|
||||
#endif
|
||||
cl_ulong globalmemsize;
|
||||
cl_uint computeunits;
|
||||
hwloc_obj_t osdev, parent;
|
||||
char buffer[64];
|
||||
|
||||
hwloc_debug("This is opencl%ud%u\n", j, i);
|
||||
|
||||
#ifdef CL_DEVICE_TOPOLOGY_AMD
|
||||
clret = clGetDeviceInfo(device_ids[i], CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
|
||||
if (CL_SUCCESS != clret) {
|
||||
hwloc_debug("no AMD-specific device information: %d\n", clret);
|
||||
continue;
|
||||
} else if (CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD != amdtopo.raw.type) {
|
||||
hwloc_debug("AMD-specific device topology reports non-PCIe device type: %u\n", amdtopo.raw.type);
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
continue;
|
||||
#endif
|
||||
|
||||
osdev = hwloc_alloc_setup_object(topology, HWLOC_OBJ_OS_DEVICE, -1);
|
||||
snprintf(buffer, sizeof(buffer), "opencl%ud%u", j, i);
|
||||
osdev->name = strdup(buffer);
|
||||
osdev->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN;
|
||||
osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_COPROC;
|
||||
|
||||
osdev->subtype = strdup("OpenCL");
|
||||
hwloc_obj_add_info(osdev, "Backend", "OpenCL");
|
||||
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL);
|
||||
if (type == CL_DEVICE_TYPE_GPU)
|
||||
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "GPU");
|
||||
else if (type == CL_DEVICE_TYPE_ACCELERATOR)
|
||||
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "Accelerator");
|
||||
else if (type == CL_DEVICE_TYPE_CPU)
|
||||
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "CPU");
|
||||
else if (type == CL_DEVICE_TYPE_CUSTOM)
|
||||
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "Custom");
|
||||
else
|
||||
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "Unknown");
|
||||
|
||||
buffer[0] = '\0';
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL);
|
||||
if (buffer[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "GPUVendor", buffer);
|
||||
|
||||
buffer[0] = '\0';
|
||||
#ifdef CL_DEVICE_BOARD_NAME_AMD
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_BOARD_NAME_AMD, sizeof(buffer), buffer, NULL);
|
||||
#else
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_NAME, sizeof(buffer), buffer, NULL);
|
||||
#endif
|
||||
if (buffer[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "GPUModel", buffer);
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%u", j);
|
||||
hwloc_obj_add_info(osdev, "OpenCLPlatformIndex", buffer);
|
||||
|
||||
buffer[0] = '\0';
|
||||
clret = clGetDeviceInfo(device_ids[i], CL_DEVICE_PLATFORM, sizeof(platform_id), &platform_id, NULL);
|
||||
if (CL_SUCCESS == clret) {
|
||||
clGetPlatformInfo(platform_id, CL_PLATFORM_NAME, sizeof(buffer), buffer, NULL);
|
||||
if (buffer[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "OpenCLPlatformName", buffer);
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%u", i);
|
||||
hwloc_obj_add_info(osdev, "OpenCLPlatformDeviceIndex", buffer);
|
||||
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(computeunits), &computeunits, NULL);
|
||||
snprintf(buffer, sizeof(buffer), "%u", computeunits);
|
||||
hwloc_obj_add_info(osdev, "OpenCLComputeUnits", buffer);
|
||||
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(globalmemsize), &globalmemsize, NULL);
|
||||
snprintf(buffer, sizeof(buffer), "%llu", (unsigned long long) globalmemsize / 1024);
|
||||
hwloc_obj_add_info(osdev, "OpenCLGlobalMemorySize", buffer);
|
||||
|
||||
parent = NULL;
|
||||
#ifdef CL_DEVICE_TOPOLOGY_AMD
|
||||
parent = hwloc_pci_belowroot_find_by_busid(topology, 0, amdtopo.pcie.bus, amdtopo.pcie.device, amdtopo.pcie.function);
|
||||
if (!parent)
|
||||
parent = hwloc_pci_find_busid_parent(topology, 0, amdtopo.pcie.bus, amdtopo.pcie.device, amdtopo.pcie.function);
|
||||
#endif
|
||||
if (!parent)
|
||||
parent = hwloc_get_root_obj(topology);
|
||||
|
||||
hwloc_insert_object_by_parent(topology, parent, osdev);
|
||||
}
|
||||
free(device_ids);
|
||||
}
|
||||
free(platform_ids);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_opencl_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_opencl_discover;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_opencl_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_MISC,
|
||||
"opencl",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_opencl_component_instantiate,
|
||||
10, /* after pci */
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
hwloc_opencl_component_init(unsigned long flags)
|
||||
{
|
||||
if (flags)
|
||||
return -1;
|
||||
if (hwloc_plugin_check_namespace("opencl", "hwloc_backend_alloc") < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_opencl_component;
|
||||
#endif
|
||||
|
||||
const struct hwloc_component hwloc_opencl_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
hwloc_opencl_component_init, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_opencl_disc_component
|
||||
};
|
323
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-pci.c
Обычный файл
323
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-pci.c
Обычный файл
@ -0,0 +1,323 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* Copyright © 2009-2011, 2013 Université Bordeaux
|
||||
* Copyright © 2014 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright © 2015 Research Organization for Information Science
|
||||
* and Technology (RIST). All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/helper.h>
|
||||
#include <hwloc/plugins.h>
|
||||
|
||||
/* private headers allowed for convenience because this plugin is built within hwloc */
|
||||
#include <private/debug.h>
|
||||
#include <private/misc.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include <pciaccess.h>
|
||||
|
||||
#ifndef PCI_HEADER_TYPE
|
||||
#define PCI_HEADER_TYPE 0x0e
|
||||
#endif
|
||||
#ifndef PCI_HEADER_TYPE_BRIDGE
|
||||
#define PCI_HEADER_TYPE_BRIDGE 1
|
||||
#endif
|
||||
|
||||
#ifndef PCI_CLASS_DEVICE
|
||||
#define PCI_CLASS_DEVICE 0x0a
|
||||
#endif
|
||||
#ifndef PCI_CLASS_BRIDGE_PCI
|
||||
#define PCI_CLASS_BRIDGE_PCI 0x0604
|
||||
#endif
|
||||
|
||||
#ifndef PCI_REVISION_ID
|
||||
#define PCI_REVISION_ID 0x08
|
||||
#endif
|
||||
|
||||
#ifndef PCI_SUBSYSTEM_VENDOR_ID
|
||||
#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
|
||||
#endif
|
||||
#ifndef PCI_SUBSYSTEM_ID
|
||||
#define PCI_SUBSYSTEM_ID 0x2e
|
||||
#endif
|
||||
|
||||
#ifndef PCI_PRIMARY_BUS
|
||||
#define PCI_PRIMARY_BUS 0x18
|
||||
#endif
|
||||
#ifndef PCI_SECONDARY_BUS
|
||||
#define PCI_SECONDARY_BUS 0x19
|
||||
#endif
|
||||
#ifndef PCI_SUBORDINATE_BUS
|
||||
#define PCI_SUBORDINATE_BUS 0x1a
|
||||
#endif
|
||||
|
||||
#ifndef PCI_CAP_ID_EXP
|
||||
#define PCI_CAP_ID_EXP 0x10
|
||||
#endif
|
||||
|
||||
#ifndef PCI_CAP_NORMAL
|
||||
#define PCI_CAP_NORMAL 1
|
||||
#endif
|
||||
|
||||
#define CONFIG_SPACE_CACHESIZE 256
|
||||
|
||||
|
||||
static int
|
||||
hwloc_look_pci(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
enum hwloc_type_filter_e pfilter, bfilter;
|
||||
struct hwloc_obj *tree = NULL, *tmp;
|
||||
int ret;
|
||||
struct pci_device_iterator *iter;
|
||||
struct pci_device *pcidev;
|
||||
|
||||
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_PCI_DEVICE, &pfilter);
|
||||
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_BRIDGE, &bfilter);
|
||||
if (bfilter == HWLOC_TYPE_FILTER_KEEP_NONE
|
||||
&& pfilter == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
return 0;
|
||||
|
||||
/* don't do anything if another backend attached PCI already
|
||||
* (they are attached to root until later in the core discovery)
|
||||
*/
|
||||
tmp = hwloc_get_root_obj(topology)->io_first_child;
|
||||
while (tmp) {
|
||||
if (tmp->type == HWLOC_OBJ_PCI_DEVICE
|
||||
|| (tmp->type == HWLOC_OBJ_BRIDGE && tmp->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI)) {
|
||||
hwloc_debug("%s", "PCI objects already added, ignoring linuxpci backend.\n");
|
||||
return 0;
|
||||
}
|
||||
tmp = tmp->next_sibling;
|
||||
}
|
||||
|
||||
hwloc_debug("%s", "\nScanning PCI buses...\n");
|
||||
|
||||
/* initialize PCI scanning */
|
||||
ret = pci_system_init();
|
||||
if (ret) {
|
||||
hwloc_debug("%s", "Can not initialize libpciaccess\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
iter = pci_slot_match_iterator_create(NULL);
|
||||
|
||||
/* iterate over devices */
|
||||
for (pcidev = pci_device_next(iter);
|
||||
pcidev;
|
||||
pcidev = pci_device_next(iter))
|
||||
{
|
||||
const char *vendorname, *devicename;
|
||||
unsigned char config_space_cache[CONFIG_SPACE_CACHESIZE];
|
||||
hwloc_obj_type_t type;
|
||||
struct hwloc_obj *obj;
|
||||
unsigned domain;
|
||||
unsigned device_class;
|
||||
unsigned short tmp16;
|
||||
unsigned offset;
|
||||
|
||||
/* initialize the config space in case we fail to read it (missing permissions, etc). */
|
||||
memset(config_space_cache, 0xff, CONFIG_SPACE_CACHESIZE);
|
||||
pci_device_probe(pcidev);
|
||||
pci_device_cfg_read(pcidev, config_space_cache, 0, CONFIG_SPACE_CACHESIZE, NULL);
|
||||
|
||||
/* try to read the domain */
|
||||
domain = pcidev->domain;
|
||||
|
||||
/* try to read the device_class */
|
||||
device_class = pcidev->device_class >> 8;
|
||||
|
||||
/* bridge or pci dev? */
|
||||
type = hwloc_pci_check_bridge_type(device_class, config_space_cache);
|
||||
|
||||
/* filtered? */
|
||||
if (type == HWLOC_OBJ_PCI_DEVICE) {
|
||||
enum hwloc_type_filter_e filter;
|
||||
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_PCI_DEVICE, &filter);
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
continue;
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_IMPORTANT
|
||||
&& !hwloc_filter_check_pcidev_subtype_important(device_class))
|
||||
continue;
|
||||
} else if (type == HWLOC_OBJ_BRIDGE) {
|
||||
enum hwloc_type_filter_e filter;
|
||||
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_BRIDGE, &filter);
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
continue;
|
||||
/* HWLOC_TYPE_FILTER_KEEP_IMPORTANT filtered later in the core */
|
||||
}
|
||||
|
||||
/* fixup SR-IOV buggy VF device/vendor IDs */
|
||||
if (0xffff == pcidev->vendor_id && 0xffff == pcidev->device_id) {
|
||||
/* SR-IOV puts ffff:ffff in Virtual Function config space.
|
||||
* The actual VF device ID is stored at a special (dynamic) location in the Physical Function config space.
|
||||
* VF and PF have the same vendor ID.
|
||||
*
|
||||
* libpciaccess just returns ffff:ffff, needs to be fixed.
|
||||
* linuxpci is OK because sysfs files are already fixed in the kernel.
|
||||
* (pciutils is OK when it uses those Linux sysfs files.)
|
||||
*
|
||||
* Reading these files is an easy way to work around the libpciaccess issue on Linux,
|
||||
* but we have no way to know if this is caused by SR-IOV or not.
|
||||
*
|
||||
* TODO:
|
||||
* If PF has CAP_ID_PCIX or CAP_ID_EXP (offset>0),
|
||||
* look for extended capability PCI_EXT_CAP_ID_SRIOV (need extended config space (more than 256 bytes)),
|
||||
* then read the VF device ID after it (PCI_IOV_DID bytes later).
|
||||
* Needs access to extended config space (needs root on Linux).
|
||||
* TODO:
|
||||
* Add string info attributes in VF and PF objects?
|
||||
*/
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
/* Workaround for Linux (the kernel returns the VF device/vendor IDs). */
|
||||
char path[64];
|
||||
char value[16];
|
||||
FILE *file;
|
||||
size_t read;
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/vendor",
|
||||
domain, pcidev->bus, pcidev->dev, pcidev->func);
|
||||
file = fopen(path, "r");
|
||||
if (file) {
|
||||
read = fread(value, 1, sizeof(value), file);
|
||||
fclose(file);
|
||||
if (read)
|
||||
/* fixup the pciaccess struct so that pci_device_get_vendor_name() is correct later. */
|
||||
pcidev->vendor_id = strtoul(value, NULL, 16);
|
||||
}
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/device",
|
||||
domain, pcidev->bus, pcidev->dev, pcidev->func);
|
||||
file = fopen(path, "r");
|
||||
if (file) {
|
||||
read = fread(value, 1, sizeof(value), file);
|
||||
fclose(file);
|
||||
if (read)
|
||||
/* fixup the pciaccess struct so that pci_device_get_device_name() is correct later. */
|
||||
pcidev->device_id = strtoul(value, NULL, 16);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
obj = hwloc_alloc_setup_object(topology, type, -1);
|
||||
obj->attr->pcidev.domain = domain;
|
||||
obj->attr->pcidev.bus = pcidev->bus;
|
||||
obj->attr->pcidev.dev = pcidev->dev;
|
||||
obj->attr->pcidev.func = pcidev->func;
|
||||
obj->attr->pcidev.vendor_id = pcidev->vendor_id;
|
||||
obj->attr->pcidev.device_id = pcidev->device_id;
|
||||
obj->attr->pcidev.class_id = device_class;
|
||||
obj->attr->pcidev.revision = config_space_cache[PCI_REVISION_ID];
|
||||
|
||||
obj->attr->pcidev.linkspeed = 0; /* unknown */
|
||||
offset = hwloc_pci_find_cap(config_space_cache, PCI_CAP_ID_EXP);
|
||||
|
||||
if (offset > 0 && offset + 20 /* size of PCI express block up to link status */ <= CONFIG_SPACE_CACHESIZE)
|
||||
hwloc_pci_find_linkspeed(config_space_cache, offset, &obj->attr->pcidev.linkspeed);
|
||||
|
||||
if (type == HWLOC_OBJ_BRIDGE) {
|
||||
if (hwloc_pci_setup_bridge_attr(obj, config_space_cache) < 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (obj->type == HWLOC_OBJ_PCI_DEVICE) {
|
||||
memcpy(&tmp16, &config_space_cache[PCI_SUBSYSTEM_VENDOR_ID], sizeof(tmp16));
|
||||
obj->attr->pcidev.subvendor_id = tmp16;
|
||||
memcpy(&tmp16, &config_space_cache[PCI_SUBSYSTEM_ID], sizeof(tmp16));
|
||||
obj->attr->pcidev.subdevice_id = tmp16;
|
||||
} else {
|
||||
/* TODO:
|
||||
* bridge must lookup PCI_CAP_ID_SSVID and then look at offset+PCI_SSVID_VENDOR/DEVICE_ID
|
||||
* cardbus must look at PCI_CB_SUBSYSTEM_VENDOR_ID and PCI_CB_SUBSYSTEM_ID
|
||||
*/
|
||||
}
|
||||
|
||||
/* get the vendor name */
|
||||
vendorname = pci_device_get_vendor_name(pcidev);
|
||||
if (vendorname && *vendorname)
|
||||
hwloc_obj_add_info(obj, "PCIVendor", vendorname);
|
||||
|
||||
/* get the device name */
|
||||
devicename = pci_device_get_device_name(pcidev);
|
||||
if (devicename && *devicename)
|
||||
hwloc_obj_add_info(obj, "PCIDevice", devicename);
|
||||
|
||||
hwloc_debug(" %04x:%02x:%02x.%01x %04x %04x:%04x %s %s\n",
|
||||
domain, pcidev->bus, pcidev->dev, pcidev->func,
|
||||
device_class, pcidev->vendor_id, pcidev->device_id,
|
||||
vendorname && *vendorname ? vendorname : "??",
|
||||
devicename && *devicename ? devicename : "??");
|
||||
|
||||
hwloc_pci_tree_insert_by_busid(&tree, obj);
|
||||
}
|
||||
|
||||
/* finalize device scanning */
|
||||
pci_iterator_destroy(iter);
|
||||
pci_system_cleanup();
|
||||
|
||||
hwloc_pci_tree_attach_belowroot(topology, tree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_pci_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
|
||||
#ifdef HWLOC_SOLARIS_SYS
|
||||
if ((uid_t)0 != geteuid())
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_look_pci;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_pci_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_MISC,
|
||||
"pci",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_pci_component_instantiate,
|
||||
20,
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
hwloc_pci_component_init(unsigned long flags)
|
||||
{
|
||||
if (flags)
|
||||
return -1;
|
||||
if (hwloc_plugin_check_namespace("pci", "hwloc_backend_alloc") < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_pci_component;
|
||||
#endif
|
||||
|
||||
const struct hwloc_component hwloc_pci_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
hwloc_pci_component_init, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_pci_disc_component
|
||||
};
|
346
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-solaris-chiptype.c
Обычный файл
346
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-solaris-chiptype.c
Обычный файл
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright © 2009-2010 Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright © 2013 Université Bordeaux. All rights reserved.
|
||||
* Copyright © 2016 Inria. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <private/solaris-chiptype.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
|
||||
#ifdef HAVE_PICL_H
|
||||
#include <sys/systeminfo.h>
|
||||
#include <picl.h>
|
||||
|
||||
/*****************************************************************************
|
||||
Order of this list is important for the assign_value and
|
||||
assign_string_value routines
|
||||
*****************************************************************************/
|
||||
|
||||
static const char* items[] = {
|
||||
"clock-frequency",
|
||||
"cpu-mhz",
|
||||
"ecache-size",
|
||||
"l2-cache-size",
|
||||
"sectored-l2-cache-size",
|
||||
"implementation#",
|
||||
"manufacturer#",
|
||||
"compatible",
|
||||
"ProcessorType",
|
||||
"vendor-id",
|
||||
"brand-string"
|
||||
};
|
||||
|
||||
#define NUM_ITEMS (sizeof(items) / sizeof(items[0]))
|
||||
|
||||
/*****************************************************************************
|
||||
SPARC strings for chip modes and implementation
|
||||
*****************************************************************************/
|
||||
static const char* sparc_modes[] = {
|
||||
"UNKNOWN",
|
||||
"SPITFIRE",
|
||||
"BLACKBIRD",
|
||||
"CHEETAH",
|
||||
"SPARC64_VI",
|
||||
"T1",
|
||||
"T2",
|
||||
"SPARC64_VII",
|
||||
"ROCK",
|
||||
"T5"
|
||||
/* needs T4, T3 and T2+ ? */
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
Default values are for Unknown so we can build up from there.
|
||||
*****************************************************************************/
|
||||
|
||||
static long dss_chip_mode = MODE_UNKNOWN;
|
||||
static long dss_chip_impl = IMPL_SPITFIRE;
|
||||
static long dss_chip_cache = TWO_MEG_CACHE;
|
||||
static long dss_chip_manufacturer = TI_MANUFACTURER;
|
||||
static long long dss_chip_speed = SPITFIRE_SPEED;
|
||||
static char dss_chip_type[PICL_PROPNAMELEN_MAX];
|
||||
static char dss_chip_model[PICL_PROPNAMELEN_MAX];
|
||||
static int called_cpu_probe = 0;
|
||||
|
||||
/*****************************************************************************
|
||||
Assigns values based on the value of index. For this reason, the order of
|
||||
the items array is important.
|
||||
*****************************************************************************/
|
||||
static void assign_value(int index, long long val) {
|
||||
if (index == 0) { /* clock-frequency */
|
||||
dss_chip_speed = val;
|
||||
}
|
||||
if (index == 1) { /* cpu-mhz */
|
||||
dss_chip_speed = val * 1000000; /* Scale since value was in MHz */
|
||||
}
|
||||
else if ((index >= 2) && (index <= 4)) {
|
||||
/* ecache-size, l2-cache-size, sectored-l2-cache-size */
|
||||
dss_chip_cache = val;
|
||||
}
|
||||
else if (index == 5) {
|
||||
/* implementation# T1, T2, and Rock do not have this, see RFE 6615268 */
|
||||
dss_chip_impl = val;
|
||||
if (dss_chip_impl == IMPL_SPITFIRE) {
|
||||
dss_chip_mode = 1;
|
||||
}
|
||||
else if ((dss_chip_impl >= IMPL_BLACKBIRD) &&
|
||||
(dss_chip_impl <= IMPL_HUMMINGBIRD)) {
|
||||
dss_chip_mode = 2;
|
||||
}
|
||||
else if ((dss_chip_impl >= IMPL_CHEETAH) &&
|
||||
(dss_chip_impl <= IMPL_PANTHER)) {
|
||||
dss_chip_mode = 3;
|
||||
}
|
||||
else if (dss_chip_impl == IMPL_SPARC64_VI) {
|
||||
dss_chip_mode = 4;
|
||||
}
|
||||
else if (dss_chip_impl == IMPL_NIAGARA) {
|
||||
dss_chip_mode = 5;
|
||||
}
|
||||
else if (dss_chip_impl == IMPL_NIAGARA_2) {
|
||||
dss_chip_mode = 6;
|
||||
}
|
||||
else if (dss_chip_impl == IMPL_SPARC64_VII) {
|
||||
dss_chip_mode = 7;
|
||||
}
|
||||
else if (dss_chip_impl == IMPL_ROCK) {
|
||||
dss_chip_mode = 8;
|
||||
}
|
||||
}
|
||||
else if (index == 6) { /* manufacturer# */
|
||||
dss_chip_manufacturer = val;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Assigns values based on the value of index. For this reason, the order of
|
||||
the items array is important.
|
||||
*****************************************************************************/
|
||||
static void assign_string_value(int index, char* string_val) {
|
||||
if (index == 7) { /* compatible */
|
||||
if (strncasecmp(string_val, "FJSV,SPARC64-VI",
|
||||
PICL_PROPNAMELEN_MAX) == 0) {
|
||||
dss_chip_mode = 4;
|
||||
}
|
||||
else if (strncasecmp(string_val, "SUNW,UltraSPARC-T1",
|
||||
PICL_PROPNAMELEN_MAX) == 0) {
|
||||
dss_chip_mode = 5;
|
||||
}
|
||||
else if (strncasecmp(string_val, "SUNW,UltraSPARC-T2",
|
||||
PICL_PROPNAMELEN_MAX) == 0) {
|
||||
dss_chip_mode = 6;
|
||||
}
|
||||
else if (strncasecmp(string_val, "FJSV,SPARC64-VII",
|
||||
PICL_PROPNAMELEN_MAX) == 0) {
|
||||
dss_chip_mode = 7;
|
||||
}
|
||||
else if (strncasecmp(string_val, "SUNW,Rock",
|
||||
PICL_PROPNAMELEN_MAX) == 0) {
|
||||
dss_chip_mode = 8;
|
||||
}
|
||||
else if (strncasecmp(string_val, "SPARC-T5",
|
||||
PICL_PROPNAMELEN_MAX) == 0) {
|
||||
dss_chip_mode = 9;
|
||||
}
|
||||
} else if (index == 8) { /* ProcessorType */
|
||||
strncpy(&dss_chip_type[0], string_val, PICL_PROPNAMELEN_MAX);
|
||||
} else if (index == 10) { /* brand-string */
|
||||
strncpy(&dss_chip_model[0], string_val, PICL_PROPNAMELEN_MAX);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Gets called by probe_cpu. Cycles through the table values until we find
|
||||
what we are looking for.
|
||||
*****************************************************************************/
|
||||
static void search_table(int index, picl_prophdl_t table_hdl) {
|
||||
|
||||
picl_prophdl_t col_hdl;
|
||||
picl_prophdl_t row_hdl;
|
||||
picl_propinfo_t p_info;
|
||||
int val;
|
||||
char string_val[PICL_PROPNAMELEN_MAX];
|
||||
|
||||
for (val = picl_get_next_by_col(table_hdl, &row_hdl); val != PICL_ENDOFLIST;
|
||||
val = picl_get_next_by_col(row_hdl, &row_hdl)) {
|
||||
if (val == PICL_SUCCESS) {
|
||||
for (col_hdl = row_hdl; val != PICL_ENDOFLIST;
|
||||
val = picl_get_next_by_row(col_hdl, &col_hdl)) {
|
||||
if (val == PICL_SUCCESS) {
|
||||
val = picl_get_propinfo(col_hdl, &p_info);
|
||||
if (val == PICL_SUCCESS) {
|
||||
if (p_info.type == PICL_PTYPE_CHARSTRING) {
|
||||
val = picl_get_propval(col_hdl, &string_val, sizeof(string_val));
|
||||
if (val == PICL_SUCCESS) {
|
||||
assign_string_value(index, string_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Gets called by picl_walk_tree_by_class. Then it cycles through the properties
|
||||
until we find what we are looking for. Once we are done, we return
|
||||
PICL_WALK_TERMINATE to stop picl_walk_tree_by_class from traversing the tree.
|
||||
|
||||
Note that PICL_PTYPE_UNSIGNED_INT and PICL_PTYPE_INT can either be 4-bytes
|
||||
or 8-bytes.
|
||||
*****************************************************************************/
|
||||
static int probe_cpu(picl_nodehdl_t node_hdl, void* dummy_arg __hwloc_attribute_unused) {
|
||||
|
||||
picl_prophdl_t p_hdl;
|
||||
picl_prophdl_t table_hdl;
|
||||
picl_propinfo_t p_info;
|
||||
long long long_long_val;
|
||||
unsigned int uint_val;
|
||||
unsigned int index;
|
||||
int int_val;
|
||||
int val;
|
||||
char string_val[PICL_PROPNAMELEN_MAX];
|
||||
|
||||
val = picl_get_first_prop(node_hdl, &p_hdl);
|
||||
while (val == PICL_SUCCESS) {
|
||||
called_cpu_probe = 1;
|
||||
val = picl_get_propinfo(p_hdl, &p_info);
|
||||
if (val == PICL_SUCCESS) {
|
||||
for (index = 0; index < NUM_ITEMS; index++) {
|
||||
if (strcasecmp(p_info.name, items[index]) == 0) {
|
||||
if (p_info.type == PICL_PTYPE_UNSIGNED_INT) {
|
||||
if (p_info.size == sizeof(uint_val)) {
|
||||
val = picl_get_propval(p_hdl, &uint_val, sizeof(uint_val));
|
||||
if (val == PICL_SUCCESS) {
|
||||
long_long_val = uint_val;
|
||||
assign_value(index, long_long_val);
|
||||
}
|
||||
}
|
||||
else if (p_info.size == sizeof(long_long_val)) {
|
||||
val = picl_get_propval(p_hdl, &long_long_val,
|
||||
sizeof(long_long_val));
|
||||
if (val == PICL_SUCCESS) {
|
||||
assign_value(index, long_long_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (p_info.type == PICL_PTYPE_INT) {
|
||||
if (p_info.size == sizeof(int_val)) {
|
||||
val = picl_get_propval(p_hdl, &int_val, sizeof(int_val));
|
||||
if (val == PICL_SUCCESS) {
|
||||
long_long_val = int_val;
|
||||
assign_value(index, long_long_val);
|
||||
}
|
||||
}
|
||||
else if (p_info.size == sizeof(long_long_val)) {
|
||||
val = picl_get_propval(p_hdl, &long_long_val,
|
||||
sizeof(long_long_val));
|
||||
if (val == PICL_SUCCESS) {
|
||||
assign_value(index, long_long_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (p_info.type == PICL_PTYPE_CHARSTRING) {
|
||||
val = picl_get_propval(p_hdl, &string_val, sizeof(string_val));
|
||||
if (val == PICL_SUCCESS) {
|
||||
assign_string_value(index, string_val);
|
||||
}
|
||||
}
|
||||
else if (p_info.type == PICL_PTYPE_TABLE) {
|
||||
val = picl_get_propval(p_hdl, &table_hdl, p_info.size);
|
||||
if (val == PICL_SUCCESS) {
|
||||
search_table(index, table_hdl);
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else if (index == NUM_ITEMS-1) {
|
||||
if (p_info.type == PICL_PTYPE_CHARSTRING) {
|
||||
val = picl_get_propval(p_hdl, &string_val, sizeof(string_val));
|
||||
if (val == PICL_SUCCESS) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val = picl_get_next_prop(p_hdl, &p_hdl);
|
||||
}
|
||||
return PICL_WALK_TERMINATE;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
Initializes, gets the root, then walks the picl tree looking for information
|
||||
|
||||
Currently, the "core" class is only needed for OPL systems
|
||||
*****************************************************************************/
|
||||
char* hwloc_solaris_get_chip_type(void) {
|
||||
picl_nodehdl_t root;
|
||||
int val;
|
||||
static char chip_type[PICL_PROPNAMELEN_MAX];
|
||||
|
||||
val = picl_initialize();
|
||||
if (val != PICL_SUCCESS) { /* Can't initialize session with PICL daemon */
|
||||
return(NULL);
|
||||
}
|
||||
val = picl_get_root(&root);
|
||||
if (val != PICL_SUCCESS) { /* Failed to get root node of the PICL tree */
|
||||
return(NULL);
|
||||
}
|
||||
val = picl_walk_tree_by_class(root, "cpu", (void *)NULL, probe_cpu);
|
||||
val = picl_walk_tree_by_class(root, "core", (void *)NULL, probe_cpu);
|
||||
picl_shutdown();
|
||||
|
||||
if (called_cpu_probe) {
|
||||
#if (defined HWLOC_X86_64_ARCH) || (defined HWLOC_X86_32_ARCH)
|
||||
/* PICL returns some corrupted chip_type strings on x86,
|
||||
* and CPUType only used on Sparc anyway, at least for now.
|
||||
* So we just ignore this attribute on x86. */
|
||||
#else
|
||||
strncpy(chip_type, dss_chip_type, PICL_PROPNAMELEN_MAX);
|
||||
#endif
|
||||
} else {
|
||||
/* no picl information on machine available */
|
||||
sysinfo(SI_HW_PROVIDER, chip_type, PICL_PROPNAMELEN_MAX);
|
||||
}
|
||||
return(chip_type);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Initializes, gets the root, then walks the picl tree looking for information
|
||||
|
||||
Currently, the "core" class is only needed for OPL systems
|
||||
*****************************************************************************/
|
||||
char *hwloc_solaris_get_chip_model(void) {
|
||||
|
||||
if (called_cpu_probe) {
|
||||
if (dss_chip_mode != MODE_UNKNOWN) { /* SPARC chip */
|
||||
strncpy(dss_chip_model, sparc_modes[dss_chip_mode],
|
||||
PICL_PROPNAMELEN_MAX);
|
||||
}
|
||||
} else {
|
||||
/* no picl information on machine available */
|
||||
sysinfo(SI_PLATFORM, dss_chip_model, PICL_PROPNAMELEN_MAX);
|
||||
}
|
||||
return(dss_chip_model);
|
||||
}
|
||||
|
||||
#else
|
||||
char* hwloc_solaris_get_chip_type(void) {
|
||||
return NULL;
|
||||
}
|
||||
char *hwloc_solaris_get_chip_model(void) {
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
817
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-solaris.c
Обычный файл
817
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-solaris.c
Обычный файл
@ -0,0 +1,817 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* Copyright © 2009-2011 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright © 2011 Oracle and/or its affiliates. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/debug.h>
|
||||
#include <private/solaris-chiptype.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#ifdef HAVE_DIRENT_H
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/processor.h>
|
||||
#include <sys/procset.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifdef HAVE_LIBLGRP
|
||||
# include <sys/lgrp_user.h>
|
||||
#endif
|
||||
|
||||
/* TODO: use psets? (only for root)
|
||||
* TODO: get cache info from prtdiag? (it is setgid sys to be able to read from
|
||||
* crw-r----- 1 root sys 88, 0 nov 3 14:35 /devices/pseudo/devinfo@0:devinfo
|
||||
* and run (apparently undocumented) ioctls on it.
|
||||
*/
|
||||
|
||||
static int
|
||||
hwloc_solaris_set_sth_cpubind(hwloc_topology_t topology, idtype_t idtype, id_t id, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
unsigned target_cpu;
|
||||
|
||||
/* The resulting binding is always strict */
|
||||
|
||||
if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) {
|
||||
if (processor_bind(idtype, id, PBIND_NONE, NULL) != 0)
|
||||
return -1;
|
||||
#ifdef HAVE_LIBLGRP
|
||||
if (!(flags & HWLOC_CPUBIND_NOMEMBIND)) {
|
||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
int n, i;
|
||||
assert (depth >= 0);
|
||||
n = hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
for (i = 0; i < n; i++) {
|
||||
hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i);
|
||||
lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_NONE);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBLGRP */
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBLGRP
|
||||
if (!(flags & HWLOC_CPUBIND_NOMEMBIND)) {
|
||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
int n, i, ok;
|
||||
assert(depth >= 0);
|
||||
n = hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
hwloc_bitmap_t target = hwloc_bitmap_alloc();
|
||||
for (i = 0; i < n; i++) {
|
||||
hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i);
|
||||
if (hwloc_bitmap_isincluded(obj->cpuset, hwloc_set))
|
||||
hwloc_bitmap_or(target, target, obj->cpuset);
|
||||
}
|
||||
|
||||
ok = hwloc_bitmap_isequal(target, hwloc_set);
|
||||
hwloc_bitmap_free(target);
|
||||
|
||||
if (ok) {
|
||||
/* Ok, managed to achieve hwloc_set by just combining NUMA nodes */
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i);
|
||||
|
||||
if (hwloc_bitmap_isincluded(obj->cpuset, hwloc_set)) {
|
||||
lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_STRONG);
|
||||
} else {
|
||||
if (flags & HWLOC_CPUBIND_STRICT)
|
||||
lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_NONE);
|
||||
else
|
||||
lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_WEAK);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBLGRP */
|
||||
|
||||
if (hwloc_bitmap_weight(hwloc_set) != 1) {
|
||||
errno = EXDEV;
|
||||
return -1;
|
||||
}
|
||||
|
||||
target_cpu = hwloc_bitmap_first(hwloc_set);
|
||||
|
||||
if (processor_bind(idtype, id,
|
||||
(processorid_t) (target_cpu), NULL) != 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
return hwloc_solaris_set_sth_cpubind(topology, P_PID, pid, hwloc_set, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
return hwloc_solaris_set_sth_cpubind(topology, P_PID, P_MYID, hwloc_set, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
return hwloc_solaris_set_sth_cpubind(topology, P_LWPID, P_MYID, hwloc_set, flags);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBLGRP
|
||||
static int
|
||||
hwloc_solaris_get_sth_cpubind(hwloc_topology_t topology, idtype_t idtype, id_t id, hwloc_bitmap_t hwloc_set, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
processorid_t binding;
|
||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
int n;
|
||||
int i;
|
||||
|
||||
assert(depth >= 0);
|
||||
|
||||
/* first check if processor_bind() was used to bind to a single processor rather than to an lgroup */
|
||||
if ( processor_bind(idtype, id, PBIND_QUERY, &binding) == 0 && binding != PBIND_NONE ) {
|
||||
hwloc_bitmap_only(hwloc_set, binding);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if not, check lgroups */
|
||||
hwloc_bitmap_zero(hwloc_set);
|
||||
n = hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
for (i = 0; i < n; i++) {
|
||||
hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i);
|
||||
lgrp_affinity_t aff = lgrp_affinity_get(idtype, id, obj->os_index);
|
||||
|
||||
if (aff == LGRP_AFF_STRONG)
|
||||
hwloc_bitmap_or(hwloc_set, hwloc_set, obj->cpuset);
|
||||
}
|
||||
|
||||
if (hwloc_bitmap_iszero(hwloc_set))
|
||||
hwloc_bitmap_copy(hwloc_set, hwloc_topology_get_complete_cpuset(topology));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
return hwloc_solaris_get_sth_cpubind(topology, P_PID, pid, hwloc_set, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
return hwloc_solaris_get_sth_cpubind(topology, P_PID, P_MYID, hwloc_set, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
return hwloc_solaris_get_sth_cpubind(topology, P_LWPID, P_MYID, hwloc_set, flags);
|
||||
}
|
||||
#endif /* HAVE_LIBLGRP */
|
||||
|
||||
/* TODO: given thread, probably not easy because of the historical n:m implementation */
|
||||
#ifdef HAVE_LIBLGRP
|
||||
static int
|
||||
hwloc_solaris_set_sth_membind(hwloc_topology_t topology, idtype_t idtype, id_t id, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
int depth;
|
||||
int n, i;
|
||||
|
||||
switch (policy) {
|
||||
case HWLOC_MEMBIND_DEFAULT:
|
||||
case HWLOC_MEMBIND_BIND:
|
||||
break;
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & HWLOC_MEMBIND_NOCPUBIND) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
assert(depth >= 0);
|
||||
n = hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i);
|
||||
if (hwloc_bitmap_isset(nodeset, obj->os_index)) {
|
||||
lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_STRONG);
|
||||
} else {
|
||||
if (flags & HWLOC_CPUBIND_STRICT)
|
||||
lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_NONE);
|
||||
else
|
||||
lgrp_affinity_set(idtype, id, obj->os_index, LGRP_AFF_WEAK);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_solaris_set_sth_membind(topology, P_PID, pid, nodeset, policy, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_set_thisproc_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_solaris_set_sth_membind(topology, P_PID, P_MYID, nodeset, policy, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_set_thisthread_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_solaris_set_sth_membind(topology, P_LWPID, P_MYID, nodeset, policy, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_get_sth_membind(hwloc_topology_t topology, idtype_t idtype, id_t id, hwloc_nodeset_t nodeset, hwloc_membind_policy_t *policy, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
int n;
|
||||
int i;
|
||||
|
||||
assert(depth >= 0);
|
||||
|
||||
hwloc_bitmap_zero(nodeset);
|
||||
n = hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, depth, i);
|
||||
lgrp_affinity_t aff = lgrp_affinity_get(idtype, id, obj->os_index);
|
||||
|
||||
if (aff == LGRP_AFF_STRONG)
|
||||
hwloc_bitmap_set(nodeset, obj->os_index);
|
||||
}
|
||||
|
||||
if (hwloc_bitmap_iszero(nodeset))
|
||||
hwloc_bitmap_copy(nodeset, hwloc_topology_get_complete_nodeset(topology));
|
||||
|
||||
*policy = HWLOC_MEMBIND_BIND;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t *policy, int flags)
|
||||
{
|
||||
return hwloc_solaris_get_sth_membind(topology, P_PID, pid, nodeset, policy, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_get_thisproc_membind(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t *policy, int flags)
|
||||
{
|
||||
return hwloc_solaris_get_sth_membind(topology, P_PID, P_MYID, nodeset, policy, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_solaris_get_thisthread_membind(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t *policy, int flags)
|
||||
{
|
||||
return hwloc_solaris_get_sth_membind(topology, P_LWPID, P_MYID, nodeset, policy, flags);
|
||||
}
|
||||
#endif /* HAVE_LIBLGRP */
|
||||
|
||||
|
||||
#ifdef MADV_ACCESS_LWP
|
||||
static int
|
||||
hwloc_solaris_set_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
int advice;
|
||||
size_t remainder;
|
||||
|
||||
/* Can not give a set of nodes just for an area. */
|
||||
if (!hwloc_bitmap_isequal(nodeset, hwloc_topology_get_complete_nodeset(topology))) {
|
||||
errno = EXDEV;
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (policy) {
|
||||
case HWLOC_MEMBIND_DEFAULT:
|
||||
case HWLOC_MEMBIND_BIND:
|
||||
advice = MADV_ACCESS_DEFAULT;
|
||||
break;
|
||||
case HWLOC_MEMBIND_FIRSTTOUCH:
|
||||
case HWLOC_MEMBIND_NEXTTOUCH:
|
||||
advice = MADV_ACCESS_LWP;
|
||||
break;
|
||||
case HWLOC_MEMBIND_INTERLEAVE:
|
||||
advice = MADV_ACCESS_MANY;
|
||||
break;
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
remainder = (uintptr_t) addr & (sysconf(_SC_PAGESIZE)-1);
|
||||
addr = (char*) addr - remainder;
|
||||
len += remainder;
|
||||
return madvise((void*) addr, len, advice);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBLGRP
|
||||
static void
|
||||
browse(struct hwloc_topology *topology, lgrp_cookie_t cookie, lgrp_id_t lgrp, hwloc_obj_t *glob_lgrps, unsigned *curlgrp)
|
||||
{
|
||||
int n;
|
||||
hwloc_obj_t obj;
|
||||
lgrp_mem_size_t mem_size;
|
||||
|
||||
n = lgrp_cpus(cookie, lgrp, NULL, 0, LGRP_CONTENT_HIERARCHY);
|
||||
if (n == -1)
|
||||
return;
|
||||
|
||||
/* Is this lgrp a NUMA node? */
|
||||
if ((mem_size = lgrp_mem_size(cookie, lgrp, LGRP_MEM_SZ_INSTALLED, LGRP_CONTENT_DIRECT)) > 0)
|
||||
{
|
||||
int i;
|
||||
processorid_t *cpuids;
|
||||
cpuids = malloc(sizeof(processorid_t) * n);
|
||||
assert(cpuids != NULL);
|
||||
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_NUMANODE, lgrp);
|
||||
obj->nodeset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(obj->nodeset, lgrp);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
glob_lgrps[(*curlgrp)++] = obj;
|
||||
|
||||
lgrp_cpus(cookie, lgrp, cpuids, n, LGRP_CONTENT_HIERARCHY);
|
||||
for (i = 0; i < n ; i++) {
|
||||
hwloc_debug("node %ld's cpu %d is %d\n", lgrp, i, cpuids[i]);
|
||||
hwloc_bitmap_set(obj->cpuset, cpuids[i]);
|
||||
}
|
||||
hwloc_debug_1arg_bitmap("node %ld has cpuset %s\n",
|
||||
lgrp, obj->cpuset);
|
||||
|
||||
/* or LGRP_MEM_SZ_FREE */
|
||||
hwloc_debug("node %ld has %lldkB\n", lgrp, mem_size/1024);
|
||||
obj->memory.local_memory = mem_size;
|
||||
obj->memory.page_types_len = 2;
|
||||
obj->memory.page_types = malloc(2*sizeof(*obj->memory.page_types));
|
||||
memset(obj->memory.page_types, 0, 2*sizeof(*obj->memory.page_types));
|
||||
obj->memory.page_types[0].size = hwloc_getpagesize();
|
||||
#if HAVE_DECL__SC_LARGE_PAGESIZE
|
||||
obj->memory.page_types[1].size = sysconf(_SC_LARGE_PAGESIZE);
|
||||
#endif
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
free(cpuids);
|
||||
}
|
||||
|
||||
n = lgrp_children(cookie, lgrp, NULL, 0);
|
||||
{
|
||||
lgrp_id_t *lgrps;
|
||||
int i;
|
||||
|
||||
lgrps = malloc(sizeof(lgrp_id_t) * n);
|
||||
assert(lgrps != NULL);
|
||||
lgrp_children(cookie, lgrp, lgrps, n);
|
||||
hwloc_debug("lgrp %ld has %d children\n", lgrp, n);
|
||||
for (i = 0; i < n ; i++)
|
||||
{
|
||||
browse(topology, cookie, lgrps[i], glob_lgrps, curlgrp);
|
||||
}
|
||||
hwloc_debug("lgrp %ld's children done\n", lgrp);
|
||||
free(lgrps);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_look_lgrp(struct hwloc_topology *topology)
|
||||
{
|
||||
lgrp_cookie_t cookie;
|
||||
unsigned curlgrp = 0;
|
||||
int nlgrps;
|
||||
lgrp_id_t root;
|
||||
|
||||
if ((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM))
|
||||
cookie = lgrp_init(LGRP_VIEW_OS);
|
||||
else
|
||||
cookie = lgrp_init(LGRP_VIEW_CALLER);
|
||||
if (cookie == LGRP_COOKIE_NONE)
|
||||
{
|
||||
hwloc_debug("lgrp_init failed: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
nlgrps = lgrp_nlgrps(cookie);
|
||||
root = lgrp_root(cookie);
|
||||
if (nlgrps > 0) {
|
||||
hwloc_obj_t *glob_lgrps = calloc(nlgrps, sizeof(hwloc_obj_t));
|
||||
browse(topology, cookie, root, glob_lgrps, &curlgrp);
|
||||
#if HAVE_DECL_LGRP_LATENCY_COOKIE
|
||||
if (nlgrps > 1) {
|
||||
uint64_t *distances = calloc(curlgrp*curlgrp, sizeof(uint64_t));
|
||||
unsigned i, j;
|
||||
for (i = 0; i < curlgrp; i++) {
|
||||
for (j = 0; j < curlgrp; j++)
|
||||
distances[i*curlgrp+j] = (uint64_t) lgrp_latency_cookie(cookie, glob_lgrps[i]->os_index, glob_lgrps[j]->os_index, LGRP_LAT_CPU_TO_MEM);
|
||||
}
|
||||
hwloc_internal_distances_add(topology, curlgrp, glob_lgrps, distances,
|
||||
HWLOC_DISTANCES_KIND_FROM_OS|HWLOC_DISTANCES_KIND_MEANS_LATENCY,
|
||||
HWLOC_DISTANCES_FLAG_GROUP);
|
||||
} else
|
||||
#endif /* HAVE_DECL_LGRP_LATENCY_COOKIE */
|
||||
free(glob_lgrps);
|
||||
}
|
||||
lgrp_fini(cookie);
|
||||
}
|
||||
#endif /* LIBLGRP */
|
||||
|
||||
#ifdef HAVE_LIBKSTAT
|
||||
#include <kstat.h>
|
||||
static int
|
||||
hwloc_look_kstat(struct hwloc_topology *topology)
|
||||
{
|
||||
/* FIXME this assumes that all packages are identical */
|
||||
char *CPUType = hwloc_solaris_get_chip_type();
|
||||
char *CPUModel = hwloc_solaris_get_chip_model();
|
||||
|
||||
kstat_ctl_t *kc = kstat_open();
|
||||
kstat_t *ksp;
|
||||
kstat_named_t *stat;
|
||||
unsigned look_cores = 1, look_chips = 1;
|
||||
|
||||
unsigned Pproc_max = 0;
|
||||
unsigned Pproc_alloc = 256;
|
||||
struct hwloc_solaris_Pproc {
|
||||
unsigned Lpkg, Ppkg, Lcore, Lproc;
|
||||
} * Pproc = malloc(Pproc_alloc * sizeof(*Pproc));
|
||||
|
||||
unsigned Lproc_num = 0;
|
||||
unsigned Lproc_alloc = 256;
|
||||
struct hwloc_solaris_Lproc {
|
||||
unsigned Pproc;
|
||||
} * Lproc = malloc(Lproc_alloc * sizeof(*Lproc));
|
||||
|
||||
unsigned Lcore_num = 0;
|
||||
unsigned Lcore_alloc = 256;
|
||||
struct hwloc_solaris_Lcore {
|
||||
unsigned Pcore, Ppkg;
|
||||
} * Lcore = malloc(Lcore_alloc * sizeof(*Lcore));
|
||||
|
||||
unsigned Lpkg_num = 0;
|
||||
unsigned Lpkg_alloc = 256;
|
||||
struct hwloc_solaris_Lpkg {
|
||||
unsigned Ppkg;
|
||||
} * Lpkg = malloc(Lpkg_alloc * sizeof(*Lpkg));
|
||||
|
||||
unsigned pkgid, coreid, cpuid;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < Pproc_alloc; i++) {
|
||||
Pproc[i].Lproc = -1;
|
||||
Pproc[i].Lpkg = -1;
|
||||
Pproc[i].Ppkg = -1;
|
||||
Pproc[i].Lcore = -1;
|
||||
}
|
||||
|
||||
if (!kc) {
|
||||
hwloc_debug("kstat_open failed: %s\n", strerror(errno));
|
||||
free(Pproc);
|
||||
free(Lproc);
|
||||
free(Lcore);
|
||||
free(Lpkg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
|
||||
{
|
||||
if (strncmp("cpu_info", ksp->ks_module, 8))
|
||||
continue;
|
||||
|
||||
cpuid = ksp->ks_instance;
|
||||
|
||||
if (kstat_read(kc, ksp, NULL) == -1)
|
||||
{
|
||||
fprintf(stderr, "kstat_read failed for CPU%u: %s\n", cpuid, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
hwloc_debug("cpu%u\n", cpuid);
|
||||
hwloc_bitmap_set(topology->levels[0][0]->complete_cpuset, cpuid);
|
||||
|
||||
stat = (kstat_named_t *) kstat_data_lookup(ksp, "state");
|
||||
if (!stat)
|
||||
hwloc_debug("could not read state for CPU%u: %s\n", cpuid, strerror(errno));
|
||||
else if (stat->data_type != KSTAT_DATA_CHAR)
|
||||
hwloc_debug("unknown kstat type %d for cpu state\n", stat->data_type);
|
||||
else
|
||||
{
|
||||
hwloc_debug("cpu%u's state is %s\n", cpuid, stat->value.c);
|
||||
if (strcmp(stat->value.c, "on-line")) {
|
||||
/* Not online.
|
||||
* It was marked as existing in complete_cpuset above, ignore everything else.
|
||||
* We wouldn't get the all topology information about parents anyway.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpuid >= Pproc_alloc) {
|
||||
struct hwloc_solaris_Pproc *tmp = realloc(Pproc, 2*Pproc_alloc * sizeof(*Pproc));
|
||||
if (!tmp)
|
||||
goto err;
|
||||
Pproc = tmp;
|
||||
Pproc_alloc *= 2;
|
||||
for(i = Pproc_alloc/2; i < Pproc_alloc; i++) {
|
||||
Pproc[i].Lproc = -1;
|
||||
Pproc[i].Lpkg = -1;
|
||||
Pproc[i].Ppkg = -1;
|
||||
Pproc[i].Lcore = -1;
|
||||
}
|
||||
}
|
||||
Pproc[cpuid].Lproc = Lproc_num;
|
||||
|
||||
if (Lproc_num >= Lproc_alloc) {
|
||||
struct hwloc_solaris_Lproc *tmp = realloc(Lproc, 2*Lproc_alloc * sizeof(*Lproc));
|
||||
if (!tmp)
|
||||
goto err;
|
||||
Lproc = tmp;
|
||||
Lproc_alloc *= 2;
|
||||
}
|
||||
Lproc[Lproc_num].Pproc = cpuid;
|
||||
Lproc_num++;
|
||||
|
||||
if (cpuid >= Pproc_max)
|
||||
Pproc_max = cpuid + 1;
|
||||
|
||||
if (look_chips) do {
|
||||
/* Get Chip ID */
|
||||
stat = (kstat_named_t *) kstat_data_lookup(ksp, "chip_id");
|
||||
if (!stat)
|
||||
{
|
||||
if (Lpkg_num)
|
||||
fprintf(stderr, "could not read package id for CPU%u: %s\n", cpuid, strerror(errno));
|
||||
else
|
||||
hwloc_debug("could not read package id for CPU%u: %s\n", cpuid, strerror(errno));
|
||||
look_chips = 0;
|
||||
continue;
|
||||
}
|
||||
switch (stat->data_type) {
|
||||
case KSTAT_DATA_INT32:
|
||||
pkgid = stat->value.i32;
|
||||
break;
|
||||
case KSTAT_DATA_UINT32:
|
||||
pkgid = stat->value.ui32;
|
||||
break;
|
||||
#ifdef _INT64_TYPE
|
||||
case KSTAT_DATA_UINT64:
|
||||
pkgid = stat->value.ui64;
|
||||
break;
|
||||
case KSTAT_DATA_INT64:
|
||||
pkgid = stat->value.i64;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "chip_id type %d unknown\n", stat->data_type);
|
||||
look_chips = 0;
|
||||
continue;
|
||||
}
|
||||
Pproc[cpuid].Ppkg = pkgid;
|
||||
for (i = 0; i < Lpkg_num; i++)
|
||||
if (pkgid == Lpkg[i].Ppkg)
|
||||
break;
|
||||
Pproc[cpuid].Lpkg = i;
|
||||
hwloc_debug("%u on package %u (%u)\n", cpuid, i, pkgid);
|
||||
if (i == Lpkg_num) {
|
||||
if (Lpkg_num == Lpkg_alloc) {
|
||||
struct hwloc_solaris_Lpkg *tmp = realloc(Lpkg, 2*Lpkg_alloc * sizeof(*Lpkg));
|
||||
if (!tmp)
|
||||
goto err;
|
||||
Lpkg = tmp;
|
||||
Lpkg_alloc *= 2;
|
||||
}
|
||||
Lpkg[Lpkg_num++].Ppkg = pkgid;
|
||||
}
|
||||
} while(0);
|
||||
|
||||
if (look_cores) do {
|
||||
/* Get Core ID */
|
||||
stat = (kstat_named_t *) kstat_data_lookup(ksp, "core_id");
|
||||
if (!stat)
|
||||
{
|
||||
if (Lcore_num)
|
||||
fprintf(stderr, "could not read core id for CPU%u: %s\n", cpuid, strerror(errno));
|
||||
else
|
||||
hwloc_debug("could not read core id for CPU%u: %s\n", cpuid, strerror(errno));
|
||||
look_cores = 0;
|
||||
continue;
|
||||
}
|
||||
switch (stat->data_type) {
|
||||
case KSTAT_DATA_INT32:
|
||||
coreid = stat->value.i32;
|
||||
break;
|
||||
case KSTAT_DATA_UINT32:
|
||||
coreid = stat->value.ui32;
|
||||
break;
|
||||
#ifdef _INT64_TYPE
|
||||
case KSTAT_DATA_UINT64:
|
||||
coreid = stat->value.ui64;
|
||||
break;
|
||||
case KSTAT_DATA_INT64:
|
||||
coreid = stat->value.i64;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
fprintf(stderr, "core_id type %d unknown\n", stat->data_type);
|
||||
look_cores = 0;
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < Lcore_num; i++)
|
||||
if (coreid == Lcore[i].Pcore && Pproc[cpuid].Ppkg == Lcore[i].Ppkg)
|
||||
break;
|
||||
Pproc[cpuid].Lcore = i;
|
||||
hwloc_debug("%u on core %u (%u)\n", cpuid, i, coreid);
|
||||
if (i == Lcore_num) {
|
||||
if (Lcore_num == Lcore_alloc) {
|
||||
struct hwloc_solaris_Lcore *tmp = realloc(Lcore, 2*Lcore_alloc * sizeof(*Lcore));
|
||||
if (!tmp)
|
||||
goto err;
|
||||
Lcore = tmp;
|
||||
Lcore_alloc *= 2;
|
||||
}
|
||||
Lcore[Lcore_num].Ppkg = Pproc[cpuid].Ppkg;
|
||||
Lcore[Lcore_num++].Pcore = coreid;
|
||||
}
|
||||
} while(0);
|
||||
|
||||
/* Note: there is also clog_id for the Thread ID (not unique) and
|
||||
* pkg_core_id for the core ID (not unique). They are not useful to us
|
||||
* however. */
|
||||
}
|
||||
|
||||
if (look_chips
|
||||
&& hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_PACKAGE)) {
|
||||
struct hwloc_obj *obj;
|
||||
unsigned j,k;
|
||||
hwloc_debug("%u Packages\n", Lpkg_num);
|
||||
for (j = 0; j < Lpkg_num; j++) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PACKAGE, Lpkg[j].Ppkg);
|
||||
if (CPUType)
|
||||
hwloc_obj_add_info(obj, "CPUType", CPUType);
|
||||
if (CPUModel)
|
||||
hwloc_obj_add_info(obj, "CPUModel", CPUModel);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
for(k=0; k<Pproc_max; k++)
|
||||
if (Pproc[k].Lpkg == j)
|
||||
hwloc_bitmap_set(obj->cpuset, k);
|
||||
hwloc_debug_1arg_bitmap("Package %u has cpuset %s\n", j, obj->cpuset);
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
hwloc_debug("%s", "\n");
|
||||
}
|
||||
|
||||
if (look_cores
|
||||
&& hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_CORE)) {
|
||||
struct hwloc_obj *obj;
|
||||
unsigned j,k;
|
||||
hwloc_debug("%u Cores\n", Lcore_num);
|
||||
for (j = 0; j < Lcore_num; j++) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_CORE, Lcore[j].Pcore);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
for(k=0; k<Pproc_max; k++)
|
||||
if (Pproc[k].Lcore == j)
|
||||
hwloc_bitmap_set(obj->cpuset, k);
|
||||
hwloc_debug_1arg_bitmap("Core %u has cpuset %s\n", j, obj->cpuset);
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
hwloc_debug("%s", "\n");
|
||||
}
|
||||
|
||||
if (Lproc_num) {
|
||||
struct hwloc_obj *obj;
|
||||
unsigned j,k;
|
||||
hwloc_debug("%u PUs\n", Lproc_num);
|
||||
for (j = 0; j < Lproc_num; j++) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PU, Lproc[j].Pproc);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
for(k=0; k<Pproc_max; k++)
|
||||
if (Pproc[k].Lproc == j)
|
||||
hwloc_bitmap_set(obj->cpuset, k);
|
||||
hwloc_debug_1arg_bitmap("PU %u has cpuset %s\n", j, obj->cpuset);
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
hwloc_debug("%s", "\n");
|
||||
}
|
||||
|
||||
kstat_close(kc);
|
||||
|
||||
free(Pproc);
|
||||
free(Lproc);
|
||||
free(Lcore);
|
||||
free(Lpkg);
|
||||
return Lproc_num > 0;
|
||||
|
||||
err:
|
||||
kstat_close(kc);
|
||||
|
||||
free(Pproc);
|
||||
free(Lproc);
|
||||
free(Lcore);
|
||||
free(Lpkg);
|
||||
return 0;
|
||||
}
|
||||
#endif /* LIBKSTAT */
|
||||
|
||||
static int
|
||||
hwloc_look_solaris(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
unsigned nbprocs = hwloc_fallback_nbprocessors (topology);
|
||||
int alreadypus = 0;
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
|
||||
#ifdef HAVE_LIBLGRP
|
||||
hwloc_look_lgrp(topology);
|
||||
#endif /* HAVE_LIBLGRP */
|
||||
#ifdef HAVE_LIBKSTAT
|
||||
if (hwloc_look_kstat(topology) > 0)
|
||||
alreadypus = 1;
|
||||
#endif /* HAVE_LIBKSTAT */
|
||||
if (!alreadypus)
|
||||
hwloc_setup_pu_level(topology, nbprocs);
|
||||
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "Solaris");
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_set_solaris_hooks(struct hwloc_binding_hooks *hooks,
|
||||
struct hwloc_topology_support *support __hwloc_attribute_unused)
|
||||
{
|
||||
hooks->set_proc_cpubind = hwloc_solaris_set_proc_cpubind;
|
||||
hooks->set_thisproc_cpubind = hwloc_solaris_set_thisproc_cpubind;
|
||||
hooks->set_thisthread_cpubind = hwloc_solaris_set_thisthread_cpubind;
|
||||
#ifdef HAVE_LIBLGRP
|
||||
hooks->get_proc_cpubind = hwloc_solaris_get_proc_cpubind;
|
||||
hooks->get_thisproc_cpubind = hwloc_solaris_get_thisproc_cpubind;
|
||||
hooks->get_thisthread_cpubind = hwloc_solaris_get_thisthread_cpubind;
|
||||
hooks->set_proc_membind = hwloc_solaris_set_proc_membind;
|
||||
hooks->set_thisproc_membind = hwloc_solaris_set_thisproc_membind;
|
||||
hooks->set_thisthread_membind = hwloc_solaris_set_thisthread_membind;
|
||||
hooks->get_proc_membind = hwloc_solaris_get_proc_membind;
|
||||
hooks->get_thisproc_membind = hwloc_solaris_get_thisproc_membind;
|
||||
hooks->get_thisthread_membind = hwloc_solaris_get_thisthread_membind;
|
||||
#endif /* HAVE_LIBLGRP */
|
||||
#ifdef MADV_ACCESS_LWP
|
||||
hooks->set_area_membind = hwloc_solaris_set_area_membind;
|
||||
support->membind->firsttouch_membind = 1;
|
||||
support->membind->bind_membind = 1;
|
||||
support->membind->interleave_membind = 1;
|
||||
support->membind->nexttouch_membind = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_solaris_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_look_solaris;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_solaris_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_CPU,
|
||||
"solaris",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_solaris_component_instantiate,
|
||||
50,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct hwloc_component hwloc_solaris_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
NULL, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_solaris_disc_component
|
||||
};
|
1215
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-synthetic.c
Обычный файл
1215
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-synthetic.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
1171
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-windows.c
Обычный файл
1171
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-windows.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
1437
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-x86.c
Обычный файл
1437
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-x86.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
569
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-xml-libxml.c
Обычный файл
569
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-xml-libxml.c
Обычный файл
@ -0,0 +1,569 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2011 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/plugins.h>
|
||||
|
||||
/* private headers allowed because this plugin is built within hwloc */
|
||||
#include <private/xml.h>
|
||||
#include <private/debug.h>
|
||||
#include <private/misc.h>
|
||||
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
|
||||
/*******************
|
||||
* Common routines *
|
||||
*******************/
|
||||
|
||||
static void hwloc_libxml2_error_callback(void * ctx __hwloc_attribute_unused, const char * msg __hwloc_attribute_unused, ...) { /* do nothing */ }
|
||||
|
||||
/* by default, do not cleanup to avoid issues with concurrent libxml users */
|
||||
static int hwloc_libxml2_needs_cleanup = 0;
|
||||
|
||||
static void
|
||||
hwloc_libxml2_init_once(void)
|
||||
{
|
||||
static int checked = 0;
|
||||
if (!checked) {
|
||||
/* disable stderr warnings */
|
||||
xmlSetGenericErrorFunc(NULL, hwloc__xml_verbose() ? xmlGenericError : hwloc_libxml2_error_callback);
|
||||
/* enforce libxml2 cleanup ? */
|
||||
if (getenv("HWLOC_LIBXML_CLEANUP"))
|
||||
hwloc_libxml2_needs_cleanup = 1;
|
||||
checked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_libxml2_cleanup(void)
|
||||
{
|
||||
if (hwloc_libxml2_needs_cleanup) {
|
||||
xmlCleanupParser();
|
||||
}
|
||||
}
|
||||
|
||||
/*******************
|
||||
* Import routines *
|
||||
*******************/
|
||||
|
||||
typedef struct hwloc__libxml_import_state_data_s {
|
||||
xmlNode *node; /* current libxml node, always valid */
|
||||
xmlNode *child; /* last processed child, or NULL if none yet */
|
||||
xmlAttr *attr; /* last processed attribute, or NULL if none yet */
|
||||
} __hwloc_attribute_may_alias * hwloc__libxml_import_state_data_t;
|
||||
|
||||
static int
|
||||
hwloc__libxml_import_next_attr(hwloc__xml_import_state_t state, char **namep, char **valuep)
|
||||
{
|
||||
hwloc__libxml_import_state_data_t lstate = (void*) state->data;
|
||||
|
||||
xmlAttr *attr;
|
||||
if (lstate->attr)
|
||||
attr = lstate->attr->next;
|
||||
else
|
||||
attr = lstate->node->properties;
|
||||
for (; attr; attr = attr->next)
|
||||
if (attr->type == XML_ATTRIBUTE_NODE) {
|
||||
/* use the first valid attribute content */
|
||||
xmlNode *subnode;
|
||||
for (subnode = attr->children; subnode; subnode = subnode->next) {
|
||||
if (subnode->type == XML_TEXT_NODE) {
|
||||
if (subnode->content && subnode->content[0] != '\0' && subnode->content[0] != '\n') {
|
||||
*namep = (char *) attr->name;
|
||||
*valuep = (char *) subnode->content;
|
||||
lstate->attr = attr;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (hwloc__xml_verbose())
|
||||
fprintf(stderr, "ignoring unexpected xml attr node type %u\n", subnode->type);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (hwloc__xml_verbose())
|
||||
fprintf(stderr, "ignoring unexpected xml attr type %u\n", attr->type);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__libxml_import_find_child(hwloc__xml_import_state_t state,
|
||||
hwloc__xml_import_state_t childstate,
|
||||
char **tagp)
|
||||
{
|
||||
hwloc__libxml_import_state_data_t lstate = (void*) state->data;
|
||||
hwloc__libxml_import_state_data_t lchildstate = (void*) childstate->data;
|
||||
xmlNode *child;
|
||||
childstate->parent = state;
|
||||
childstate->global = state->global;
|
||||
if (!lstate->child)
|
||||
return 0;
|
||||
child = lstate->child->next;
|
||||
for (; child; child = child->next)
|
||||
if (child->type == XML_ELEMENT_NODE) {
|
||||
lstate->child = lchildstate->node = child;
|
||||
lchildstate->child = child->children;
|
||||
lchildstate->attr = NULL;
|
||||
*tagp = (char*) child->name;
|
||||
return 1;
|
||||
} else if (child->type == XML_TEXT_NODE) {
|
||||
if (child->content && child->content[0] != '\0' && child->content[0] != '\n')
|
||||
if (hwloc__xml_verbose())
|
||||
fprintf(stderr, "ignoring object text content %s\n", (const char*) child->content);
|
||||
} else if (child->type != XML_COMMENT_NODE) {
|
||||
if (hwloc__xml_verbose())
|
||||
fprintf(stderr, "ignoring unexpected xml node type %u\n", child->type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__libxml_import_close_tag(hwloc__xml_import_state_t state __hwloc_attribute_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__libxml_import_close_child(hwloc__xml_import_state_t state __hwloc_attribute_unused)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__libxml_import_get_content(hwloc__xml_import_state_t state,
|
||||
char **beginp, size_t expected_length)
|
||||
{
|
||||
hwloc__libxml_import_state_data_t lstate = (void*) state->data;
|
||||
xmlNode *child;
|
||||
size_t length;
|
||||
|
||||
child = lstate->node->children;
|
||||
if (!child || child->type != XML_TEXT_NODE) {
|
||||
if (expected_length)
|
||||
return -1;
|
||||
*beginp = "";
|
||||
return 0;
|
||||
}
|
||||
|
||||
length = strlen((char *) child->content);
|
||||
if (length != expected_length)
|
||||
return -1;
|
||||
*beginp = (char *) child->content;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__libxml_import_close_content(hwloc__xml_import_state_t state __hwloc_attribute_unused)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_libxml_look_init(struct hwloc_xml_backend_data_s *bdata,
|
||||
struct hwloc__xml_import_state_s *state)
|
||||
{
|
||||
hwloc__libxml_import_state_data_t lstate = (void*) state->data;
|
||||
xmlNode* root_node;
|
||||
xmlDtd *dtd;
|
||||
|
||||
assert(sizeof(*lstate) <= sizeof(state->data));
|
||||
|
||||
dtd = xmlGetIntSubset((xmlDoc*) bdata->data);
|
||||
if (!dtd) {
|
||||
if (hwloc__xml_verbose())
|
||||
fprintf(stderr, "Loading XML topology without DTD\n");
|
||||
} else if (strcmp((char *) dtd->SystemID, "hwloc.dtd")) {
|
||||
if (hwloc__xml_verbose())
|
||||
fprintf(stderr, "Loading XML topology with wrong DTD SystemID (%s instead of %s)\n",
|
||||
(char *) dtd->SystemID, "hwloc.dtd");
|
||||
}
|
||||
|
||||
root_node = xmlDocGetRootElement((xmlDoc*) bdata->data);
|
||||
|
||||
if (strcmp((const char *) root_node->name, "topology") && strcmp((const char *) root_node->name, "root")) {
|
||||
/* root node should be in "topology" class (or "root" if importing from < 1.0) */
|
||||
if (hwloc__xml_verbose())
|
||||
fprintf(stderr, "ignoring object of class `%s' not at the top the xml hierarchy\n", (const char *) root_node->name);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
state->global->next_attr = hwloc__libxml_import_next_attr;
|
||||
state->global->find_child = hwloc__libxml_import_find_child;
|
||||
state->global->close_tag = hwloc__libxml_import_close_tag;
|
||||
state->global->close_child = hwloc__libxml_import_close_child;
|
||||
state->global->get_content = hwloc__libxml_import_get_content;
|
||||
state->global->close_content = hwloc__libxml_import_close_content;
|
||||
state->parent = NULL;
|
||||
lstate->node = root_node;
|
||||
lstate->child = root_node->children;
|
||||
lstate->attr = NULL;
|
||||
return 0; /* success */
|
||||
|
||||
failed:
|
||||
return -1; /* failed */
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_libxml_import_diff(struct hwloc__xml_import_state_s *state, const char *xmlpath, const char *xmlbuffer, int xmlbuflen, hwloc_topology_diff_t *firstdiffp, char **refnamep)
|
||||
{
|
||||
hwloc__libxml_import_state_data_t lstate = (void*) state->data;
|
||||
char *refname = NULL;
|
||||
xmlDoc *doc = NULL;
|
||||
xmlNode* root_node;
|
||||
xmlDtd *dtd;
|
||||
int ret;
|
||||
|
||||
assert(sizeof(*lstate) <= sizeof(state->data));
|
||||
|
||||
LIBXML_TEST_VERSION;
|
||||
hwloc_libxml2_init_once();
|
||||
|
||||
errno = 0; /* set to 0 so that we know if libxml2 changed it */
|
||||
|
||||
if (xmlpath)
|
||||
doc = xmlReadFile(xmlpath, NULL, 0);
|
||||
else if (xmlbuffer)
|
||||
doc = xmlReadMemory(xmlbuffer, xmlbuflen, "", NULL, 0);
|
||||
|
||||
if (!doc) {
|
||||
if (!errno)
|
||||
/* libxml2 read the file fine, but it got an error during parsing */
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dtd = xmlGetIntSubset(doc);
|
||||
if (!dtd) {
|
||||
if (hwloc__xml_verbose())
|
||||
fprintf(stderr, "Loading XML topologydiff without DTD\n");
|
||||
} else if (strcmp((char *) dtd->SystemID, "hwloc.dtd")) {
|
||||
if (hwloc__xml_verbose())
|
||||
fprintf(stderr, "Loading XML topologydiff with wrong DTD SystemID (%s instead of %s)\n",
|
||||
(char *) dtd->SystemID, "hwloc.dtd");
|
||||
}
|
||||
|
||||
root_node = xmlDocGetRootElement(doc);
|
||||
|
||||
if (strcmp((const char *) root_node->name, "topologydiff")) {
|
||||
/* root node should be in "topologydiff" class */
|
||||
if (hwloc__xml_verbose())
|
||||
fprintf(stderr, "ignoring object of class `%s' not at the top the xml hierarchy\n", (const char *) root_node->name);
|
||||
goto out_with_doc;
|
||||
}
|
||||
|
||||
state->global->next_attr = hwloc__libxml_import_next_attr;
|
||||
state->global->find_child = hwloc__libxml_import_find_child;
|
||||
state->global->close_tag = hwloc__libxml_import_close_tag;
|
||||
state->global->close_child = hwloc__libxml_import_close_child;
|
||||
state->global->get_content = hwloc__libxml_import_get_content;
|
||||
state->global->close_content = hwloc__libxml_import_close_content;
|
||||
state->parent = NULL;
|
||||
lstate->node = root_node;
|
||||
lstate->child = root_node->children;
|
||||
lstate->attr = NULL;
|
||||
|
||||
while (1) {
|
||||
char *attrname, *attrvalue;
|
||||
if (state->global->next_attr(state, &attrname, &attrvalue) < 0)
|
||||
break;
|
||||
if (!strcmp(attrname, "refname")) {
|
||||
free(refname);
|
||||
refname = strdup(attrvalue);
|
||||
} else
|
||||
goto out_with_doc;
|
||||
}
|
||||
|
||||
ret = hwloc__xml_import_diff(state, firstdiffp);
|
||||
if (refnamep && !ret)
|
||||
*refnamep = refname;
|
||||
else
|
||||
free(refname);
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
hwloc_libxml2_cleanup();
|
||||
return ret;
|
||||
|
||||
out_with_doc:
|
||||
free(refname);
|
||||
xmlFreeDoc(doc);
|
||||
hwloc_libxml2_cleanup();
|
||||
out:
|
||||
return -1; /* failed */
|
||||
}
|
||||
|
||||
/********************
|
||||
* Backend routines *
|
||||
********************/
|
||||
|
||||
static void
|
||||
hwloc_libxml_backend_exit(struct hwloc_xml_backend_data_s *bdata)
|
||||
{
|
||||
xmlFreeDoc((xmlDoc*)bdata->data);
|
||||
hwloc_libxml2_cleanup();
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_libxml_backend_init(struct hwloc_xml_backend_data_s *bdata,
|
||||
const char *xmlpath, const char *xmlbuffer, int xmlbuflen)
|
||||
{
|
||||
xmlDoc *doc = NULL;
|
||||
|
||||
LIBXML_TEST_VERSION;
|
||||
hwloc_libxml2_init_once();
|
||||
|
||||
errno = 0; /* set to 0 so that we know if libxml2 changed it */
|
||||
|
||||
if (xmlpath)
|
||||
doc = xmlReadFile(xmlpath, NULL, 0);
|
||||
else if (xmlbuffer)
|
||||
doc = xmlReadMemory(xmlbuffer, xmlbuflen, "", NULL, 0);
|
||||
|
||||
if (!doc) {
|
||||
if (!errno)
|
||||
/* libxml2 read the file fine, but it got an error during parsing */
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bdata->look_init = hwloc_libxml_look_init;
|
||||
bdata->look_failed = NULL;
|
||||
bdata->backend_exit = hwloc_libxml_backend_exit;
|
||||
bdata->data = doc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************
|
||||
* Export routines *
|
||||
*******************/
|
||||
|
||||
typedef struct hwloc__libxml_export_state_data_s {
|
||||
xmlNodePtr current_node; /* current node to output */
|
||||
} __hwloc_attribute_may_alias * hwloc__libxml_export_state_data_t;
|
||||
|
||||
static void
|
||||
hwloc__libxml_export_new_child(hwloc__xml_export_state_t parentstate,
|
||||
hwloc__xml_export_state_t state,
|
||||
const char *name)
|
||||
{
|
||||
hwloc__libxml_export_state_data_t lpdata = (void *) parentstate->data;
|
||||
hwloc__libxml_export_state_data_t ldata = (void *) state->data;
|
||||
|
||||
state->parent = parentstate;
|
||||
state->new_child = parentstate->new_child;
|
||||
state->new_prop = parentstate->new_prop;
|
||||
state->add_content = parentstate->add_content;
|
||||
state->end_object = parentstate->end_object;
|
||||
|
||||
ldata->current_node = xmlNewChild(lpdata->current_node, NULL, BAD_CAST name, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__libxml_export_new_prop(hwloc__xml_export_state_t state, const char *name, const char *value)
|
||||
{
|
||||
hwloc__libxml_export_state_data_t ldata = (void *) state->data;
|
||||
xmlNewProp(ldata->current_node, BAD_CAST name, BAD_CAST value);
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__libxml_export_end_object(hwloc__xml_export_state_t state __hwloc_attribute_unused, const char *name __hwloc_attribute_unused)
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__libxml_export_add_content(hwloc__xml_export_state_t state, const char *buffer, size_t length)
|
||||
{
|
||||
hwloc__libxml_export_state_data_t ldata = (void *) state->data;
|
||||
xmlNodeAddContentLen(ldata->current_node, BAD_CAST buffer, length);
|
||||
}
|
||||
|
||||
static xmlDocPtr
|
||||
hwloc__libxml2_prepare_export(hwloc_topology_t topology, unsigned long flags)
|
||||
{
|
||||
struct hwloc__xml_export_state_s state;
|
||||
hwloc__libxml_export_state_data_t data = (void *) state.data;
|
||||
xmlDocPtr doc = NULL; /* document pointer */
|
||||
xmlNodePtr root_node = NULL; /* root pointer */
|
||||
|
||||
assert(sizeof(*data) <= sizeof(state.data));
|
||||
|
||||
LIBXML_TEST_VERSION;
|
||||
hwloc_libxml2_init_once();
|
||||
|
||||
/* Creates a new document, a node and set it as a root node. */
|
||||
doc = xmlNewDoc(BAD_CAST "1.0");
|
||||
root_node = xmlNewNode(NULL, BAD_CAST "topology");
|
||||
xmlDocSetRootElement(doc, root_node);
|
||||
|
||||
/* Creates a DTD declaration. Isn't mandatory. */
|
||||
(void) xmlCreateIntSubset(doc, BAD_CAST "topology", NULL, BAD_CAST "hwloc.dtd");
|
||||
|
||||
state.new_child = hwloc__libxml_export_new_child;
|
||||
state.new_prop = hwloc__libxml_export_new_prop;
|
||||
state.add_content = hwloc__libxml_export_add_content;
|
||||
state.end_object = hwloc__libxml_export_end_object;
|
||||
|
||||
data->current_node = root_node;
|
||||
|
||||
hwloc__xml_export_topology (&state, topology, flags);
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_libxml_export_file(hwloc_topology_t topology, const char *filename, unsigned long flags)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
int ret;
|
||||
|
||||
errno = 0; /* set to 0 so that we know if libxml2 changed it */
|
||||
|
||||
doc = hwloc__libxml2_prepare_export(topology, flags);
|
||||
ret = xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1);
|
||||
xmlFreeDoc(doc);
|
||||
hwloc_libxml2_cleanup();
|
||||
|
||||
if (ret < 0) {
|
||||
if (!errno)
|
||||
/* libxml2 likely got an error before doing I/O */
|
||||
errno = EINVAL;
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_libxml_export_buffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen, unsigned long flags)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
|
||||
doc = hwloc__libxml2_prepare_export(topology, flags);
|
||||
xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)xmlbuffer, buflen, "UTF-8", 1);
|
||||
xmlFreeDoc(doc);
|
||||
hwloc_libxml2_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static xmlDocPtr
|
||||
hwloc__libxml2_prepare_export_diff(hwloc_topology_diff_t diff, const char *refname)
|
||||
{
|
||||
struct hwloc__xml_export_state_s state;
|
||||
hwloc__libxml_export_state_data_t data = (void *) state.data;
|
||||
xmlDocPtr doc = NULL; /* document pointer */
|
||||
xmlNodePtr root_node = NULL; /* root pointer */
|
||||
|
||||
assert(sizeof(*data) <= sizeof(state.data));
|
||||
|
||||
LIBXML_TEST_VERSION;
|
||||
hwloc_libxml2_init_once();
|
||||
|
||||
/* Creates a new document, a node and set it as a root node. */
|
||||
doc = xmlNewDoc(BAD_CAST "1.0");
|
||||
root_node = xmlNewNode(NULL, BAD_CAST "topologydiff");
|
||||
if (refname)
|
||||
xmlNewProp(root_node, BAD_CAST "refname", BAD_CAST refname);
|
||||
xmlDocSetRootElement(doc, root_node);
|
||||
|
||||
/* Creates a DTD declaration. Isn't mandatory. */
|
||||
(void) xmlCreateIntSubset(doc, BAD_CAST "topologydiff", NULL, BAD_CAST "hwloc.dtd");
|
||||
|
||||
state.new_child = hwloc__libxml_export_new_child;
|
||||
state.new_prop = hwloc__libxml_export_new_prop;
|
||||
state.add_content = hwloc__libxml_export_add_content;
|
||||
state.end_object = hwloc__libxml_export_end_object;
|
||||
|
||||
data->current_node = root_node;
|
||||
|
||||
hwloc__xml_export_diff (&state, diff);
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_libxml_export_diff_file(hwloc_topology_diff_t diff, const char *refname, const char *filename)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
int ret;
|
||||
|
||||
errno = 0; /* set to 0 so that we know if libxml2 changed it */
|
||||
|
||||
doc = hwloc__libxml2_prepare_export_diff(diff, refname);
|
||||
ret = xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1);
|
||||
xmlFreeDoc(doc);
|
||||
hwloc_libxml2_cleanup();
|
||||
|
||||
if (ret < 0) {
|
||||
if (!errno)
|
||||
/* libxml2 likely got an error before doing I/O */
|
||||
errno = EINVAL;
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_libxml_export_diff_buffer(hwloc_topology_diff_t diff, const char *refname, char **xmlbuffer, int *buflen)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
|
||||
doc = hwloc__libxml2_prepare_export_diff(diff, refname);
|
||||
xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)xmlbuffer, buflen, "UTF-8", 1);
|
||||
xmlFreeDoc(doc);
|
||||
hwloc_libxml2_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_libxml_free_buffer(void *xmlbuffer)
|
||||
{
|
||||
xmlFree(BAD_CAST xmlbuffer);
|
||||
}
|
||||
|
||||
/*************
|
||||
* Callbacks *
|
||||
*************/
|
||||
|
||||
static struct hwloc_xml_callbacks hwloc_xml_libxml_callbacks = {
|
||||
hwloc_libxml_backend_init,
|
||||
hwloc_libxml_export_file,
|
||||
hwloc_libxml_export_buffer,
|
||||
hwloc_libxml_free_buffer,
|
||||
hwloc_libxml_import_diff,
|
||||
hwloc_libxml_export_diff_file,
|
||||
hwloc_libxml_export_diff_buffer
|
||||
};
|
||||
|
||||
static struct hwloc_xml_component hwloc_libxml_xml_component = {
|
||||
NULL,
|
||||
&hwloc_xml_libxml_callbacks
|
||||
};
|
||||
|
||||
static int
|
||||
hwloc_xml_libxml_component_init(unsigned long flags)
|
||||
{
|
||||
if (flags)
|
||||
return -1;
|
||||
if (hwloc_plugin_check_namespace("xml_libxml", "hwloc__xml_verbose") < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_xml_libxml_component;
|
||||
#endif
|
||||
|
||||
const struct hwloc_component hwloc_xml_libxml_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
hwloc_xml_libxml_component_init, NULL,
|
||||
HWLOC_COMPONENT_TYPE_XML,
|
||||
0,
|
||||
&hwloc_libxml_xml_component
|
||||
};
|
873
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-xml-nolibxml.c
Обычный файл
873
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-xml-nolibxml.c
Обычный файл
@ -0,0 +1,873 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* Copyright © 2009-2011 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/plugins.h>
|
||||
#include <private/private.h>
|
||||
#include <private/misc.h>
|
||||
#include <private/xml.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/*******************
|
||||
* Import routines *
|
||||
*******************/
|
||||
|
||||
struct hwloc__nolibxml_backend_data_s {
|
||||
size_t buflen; /* size of both buffer and copy buffers, set during backend_init() */
|
||||
char *buffer; /* allocated and filled during backend_init() */
|
||||
char *copy; /* allocated during backend_init(), used later during actual parsing */
|
||||
};
|
||||
|
||||
typedef struct hwloc__nolibxml_import_state_data_s {
|
||||
char *tagbuffer; /* buffer containing the next tag */
|
||||
char *attrbuffer; /* buffer containing the next attribute of the current node */
|
||||
char *tagname; /* tag name of the current node */
|
||||
int closed; /* set if the current node is auto-closing */
|
||||
} __hwloc_attribute_may_alias * hwloc__nolibxml_import_state_data_t;
|
||||
|
||||
static char *
|
||||
hwloc__nolibxml_import_ignore_spaces(char *buffer)
|
||||
{
|
||||
return buffer + strspn(buffer, " \t\n");
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__nolibxml_import_next_attr(hwloc__xml_import_state_t state, char **namep, char **valuep)
|
||||
{
|
||||
hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
|
||||
size_t namelen;
|
||||
size_t len, escaped;
|
||||
char *buffer, *value, *end;
|
||||
|
||||
if (!nstate->attrbuffer)
|
||||
return -1;
|
||||
|
||||
/* find the beginning of an attribute */
|
||||
buffer = hwloc__nolibxml_import_ignore_spaces(nstate->attrbuffer);
|
||||
namelen = strspn(buffer, "abcdefghijklmnopqrstuvwxyz_");
|
||||
if (buffer[namelen] != '=' || buffer[namelen+1] != '\"')
|
||||
return -1;
|
||||
buffer[namelen] = '\0';
|
||||
*namep = buffer;
|
||||
|
||||
/* find the beginning of its value, and unescape it */
|
||||
*valuep = value = buffer+namelen+2;
|
||||
len = 0; escaped = 0;
|
||||
while (value[len+escaped] != '\"') {
|
||||
if (value[len+escaped] == '&') {
|
||||
if (!strncmp(&value[1+len+escaped], "#10;", 4)) {
|
||||
escaped += 4;
|
||||
value[len] = '\n';
|
||||
} else if (!strncmp(&value[1+len+escaped], "#13;", 4)) {
|
||||
escaped += 4;
|
||||
value[len] = '\r';
|
||||
} else if (!strncmp(&value[1+len+escaped], "#9;", 3)) {
|
||||
escaped += 3;
|
||||
value[len] = '\t';
|
||||
} else if (!strncmp(&value[1+len+escaped], "quot;", 5)) {
|
||||
escaped += 5;
|
||||
value[len] = '\"';
|
||||
} else if (!strncmp(&value[1+len+escaped], "lt;", 3)) {
|
||||
escaped += 3;
|
||||
value[len] = '<';
|
||||
} else if (!strncmp(&value[1+len+escaped], "gt;", 3)) {
|
||||
escaped += 3;
|
||||
value[len] = '>';
|
||||
} else if (!strncmp(&value[1+len+escaped], "amp;", 4)) {
|
||||
escaped += 4;
|
||||
value[len] = '&';
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
value[len] = value[len+escaped];
|
||||
}
|
||||
len++;
|
||||
if (value[len+escaped] == '\0')
|
||||
return -1;
|
||||
}
|
||||
value[len] = '\0';
|
||||
|
||||
/* find next attribute */
|
||||
end = &value[len+escaped+1]; /* skip the ending " */
|
||||
nstate->attrbuffer = hwloc__nolibxml_import_ignore_spaces(end);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__nolibxml_import_find_child(hwloc__xml_import_state_t state,
|
||||
hwloc__xml_import_state_t childstate,
|
||||
char **tagp)
|
||||
{
|
||||
hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
|
||||
hwloc__nolibxml_import_state_data_t nchildstate = (void*) childstate->data;
|
||||
char *buffer = nstate->tagbuffer;
|
||||
char *end;
|
||||
size_t namelen;
|
||||
|
||||
childstate->parent = state;
|
||||
childstate->global = state->global;
|
||||
|
||||
/* auto-closed tags have no children */
|
||||
if (nstate->closed)
|
||||
return 0;
|
||||
|
||||
/* find the beginning of the tag */
|
||||
buffer = hwloc__nolibxml_import_ignore_spaces(buffer);
|
||||
if (buffer[0] != '<')
|
||||
return -1;
|
||||
buffer++;
|
||||
|
||||
/* if closing tag, return nothing and do not advance */
|
||||
if (buffer[0] == '/')
|
||||
return 0;
|
||||
|
||||
/* normal tag */
|
||||
*tagp = nchildstate->tagname = buffer;
|
||||
|
||||
/* find the end, mark it and return it */
|
||||
end = strchr(buffer, '>');
|
||||
if (!end)
|
||||
return -1;
|
||||
end[0] = '\0';
|
||||
nchildstate->tagbuffer = end+1;
|
||||
|
||||
/* handle auto-closing tags */
|
||||
if (end[-1] == '/') {
|
||||
nchildstate->closed = 1;
|
||||
end[-1] = '\0';
|
||||
} else
|
||||
nchildstate->closed = 0;
|
||||
|
||||
/* find attributes */
|
||||
namelen = strspn(buffer, "abcdefghijklmnopqrstuvwxyz1234567890_");
|
||||
|
||||
if (buffer[namelen] == '\0') {
|
||||
/* no attributes */
|
||||
nchildstate->attrbuffer = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (buffer[namelen] != ' ')
|
||||
return -1;
|
||||
|
||||
/* found a space, likely starting attributes */
|
||||
buffer[namelen] = '\0';
|
||||
nchildstate->attrbuffer = buffer+namelen+1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__nolibxml_import_close_tag(hwloc__xml_import_state_t state)
|
||||
{
|
||||
hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
|
||||
char *buffer = nstate->tagbuffer;
|
||||
char *end;
|
||||
|
||||
/* auto-closed tags need nothing */
|
||||
if (nstate->closed)
|
||||
return 0;
|
||||
|
||||
/* find the beginning of the tag */
|
||||
buffer = hwloc__nolibxml_import_ignore_spaces(buffer);
|
||||
if (buffer[0] != '<')
|
||||
return -1;
|
||||
buffer++;
|
||||
|
||||
/* find the end, mark it and return it to the parent */
|
||||
end = strchr(buffer, '>');
|
||||
if (!end)
|
||||
return -1;
|
||||
end[0] = '\0';
|
||||
nstate->tagbuffer = end+1;
|
||||
|
||||
/* if closing tag, return nothing */
|
||||
if (buffer[0] != '/' || strcmp(buffer+1, nstate->tagname) )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__nolibxml_import_close_child(hwloc__xml_import_state_t state)
|
||||
{
|
||||
hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
|
||||
hwloc__nolibxml_import_state_data_t nparent = (void*) state->parent->data;
|
||||
nparent->tagbuffer = nstate->tagbuffer;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__nolibxml_import_get_content(hwloc__xml_import_state_t state,
|
||||
char **beginp, size_t expected_length)
|
||||
{
|
||||
hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
|
||||
char *buffer = nstate->tagbuffer;
|
||||
size_t length;
|
||||
char *end;
|
||||
|
||||
/* auto-closed tags have no content */
|
||||
if (nstate->closed) {
|
||||
if (expected_length)
|
||||
return -1;
|
||||
*beginp = "";
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* find the next tag, where the content ends */
|
||||
end = strchr(buffer, '<');
|
||||
if (!end)
|
||||
return -1;
|
||||
|
||||
length = (size_t) (end-buffer);
|
||||
if (length != expected_length)
|
||||
return -1;
|
||||
nstate->tagbuffer = end;
|
||||
*end = '\0'; /* mark as 0-terminated for now */
|
||||
*beginp = buffer;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__nolibxml_import_close_content(hwloc__xml_import_state_t state)
|
||||
{
|
||||
/* put back the '<' that we overwrote to 0-terminate the content */
|
||||
hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
|
||||
if (!nstate->closed)
|
||||
*nstate->tagbuffer = '<';
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_nolibxml_look_init(struct hwloc_xml_backend_data_s *bdata,
|
||||
struct hwloc__xml_import_state_s *state)
|
||||
{
|
||||
hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
|
||||
struct hwloc__nolibxml_backend_data_s *nbdata = bdata->data;
|
||||
char *buffer;
|
||||
|
||||
assert(sizeof(*nstate) <= sizeof(state->data));
|
||||
|
||||
/* use a copy in the temporary buffer, we may modify during parsing */
|
||||
buffer = nbdata->copy;
|
||||
memcpy(buffer, nbdata->buffer, nbdata->buflen);
|
||||
|
||||
/* skip headers */
|
||||
while (!strncmp(buffer, "<?xml ", 6) || !strncmp(buffer, "<!DOCTYPE ", 10)) {
|
||||
buffer = strchr(buffer, '\n');
|
||||
if (!buffer)
|
||||
goto failed;
|
||||
buffer++;
|
||||
}
|
||||
|
||||
/* find topology tag */
|
||||
if (strncmp(buffer, "<topology>", 10))
|
||||
goto failed;
|
||||
|
||||
state->global->next_attr = hwloc__nolibxml_import_next_attr;
|
||||
state->global->find_child = hwloc__nolibxml_import_find_child;
|
||||
state->global->close_tag = hwloc__nolibxml_import_close_tag;
|
||||
state->global->close_child = hwloc__nolibxml_import_close_child;
|
||||
state->global->get_content = hwloc__nolibxml_import_get_content;
|
||||
state->global->close_content = hwloc__nolibxml_import_close_content;
|
||||
state->parent = NULL;
|
||||
nstate->closed = 0;
|
||||
nstate->tagbuffer = buffer+10;
|
||||
nstate->tagname = (char *) "topology";
|
||||
nstate->attrbuffer = NULL;
|
||||
return 0; /* success */
|
||||
|
||||
failed:
|
||||
return -1; /* failed */
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_nolibxml_look_failed(struct hwloc_xml_backend_data_s *bdata __hwloc_attribute_unused)
|
||||
{
|
||||
/* not only when verbose */
|
||||
fprintf(stderr, "Failed to parse XML input with the minimalistic parser. If it was not\n"
|
||||
"generated by hwloc, try enabling full XML support with libxml2.\n");
|
||||
}
|
||||
|
||||
/********************
|
||||
* Backend routines *
|
||||
********************/
|
||||
|
||||
static void
|
||||
hwloc_nolibxml_backend_exit(struct hwloc_xml_backend_data_s *bdata)
|
||||
{
|
||||
struct hwloc__nolibxml_backend_data_s *nbdata = bdata->data;
|
||||
free(nbdata->buffer);
|
||||
free(nbdata->copy);
|
||||
free(nbdata);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_nolibxml_read_file(const char *xmlpath, char **bufferp, size_t *buflenp)
|
||||
{
|
||||
FILE * file;
|
||||
size_t buflen, offset, readlen;
|
||||
struct stat statbuf;
|
||||
char *buffer, *tmp;
|
||||
size_t ret;
|
||||
|
||||
if (!strcmp(xmlpath, "-"))
|
||||
xmlpath = "/dev/stdin";
|
||||
|
||||
file = fopen(xmlpath, "r");
|
||||
if (!file)
|
||||
goto out;
|
||||
|
||||
/* find the required buffer size for regular files, or use 4k when unknown, we'll realloc later if needed */
|
||||
buflen = 4096;
|
||||
if (!stat(xmlpath, &statbuf))
|
||||
if (S_ISREG(statbuf.st_mode))
|
||||
buflen = statbuf.st_size+1; /* one additional byte so that the first fread() gets EOF too */
|
||||
|
||||
buffer = malloc(buflen+1); /* one more byte for the ending \0 */
|
||||
if (!buffer)
|
||||
goto out_with_file;
|
||||
|
||||
offset = 0; readlen = buflen;
|
||||
while (1) {
|
||||
ret = fread(buffer+offset, 1, readlen, file);
|
||||
|
||||
offset += ret;
|
||||
buffer[offset] = 0;
|
||||
|
||||
if (ret != readlen)
|
||||
break;
|
||||
|
||||
buflen *= 2;
|
||||
tmp = realloc(buffer, buflen+1);
|
||||
if (!tmp)
|
||||
goto out_with_buffer;
|
||||
buffer = tmp;
|
||||
readlen = buflen/2;
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
*bufferp = buffer;
|
||||
*buflenp = offset+1;
|
||||
return 0;
|
||||
|
||||
out_with_buffer:
|
||||
free(buffer);
|
||||
out_with_file:
|
||||
fclose(file);
|
||||
out:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_nolibxml_backend_init(struct hwloc_xml_backend_data_s *bdata,
|
||||
const char *xmlpath, const char *xmlbuffer, int xmlbuflen)
|
||||
{
|
||||
struct hwloc__nolibxml_backend_data_s *nbdata = malloc(sizeof(*nbdata));
|
||||
|
||||
if (!nbdata)
|
||||
goto out;
|
||||
bdata->data = nbdata;
|
||||
|
||||
if (xmlbuffer) {
|
||||
nbdata->buffer = malloc(xmlbuflen);
|
||||
if (!nbdata->buffer)
|
||||
goto out_with_nbdata;
|
||||
nbdata->buflen = xmlbuflen;
|
||||
memcpy(nbdata->buffer, xmlbuffer, xmlbuflen);
|
||||
|
||||
} else {
|
||||
int err = hwloc_nolibxml_read_file(xmlpath, &nbdata->buffer, &nbdata->buflen);
|
||||
if (err < 0)
|
||||
goto out_with_nbdata;
|
||||
}
|
||||
|
||||
/* allocate a temporary copy buffer that we may modify during parsing */
|
||||
nbdata->copy = malloc(nbdata->buflen);
|
||||
if (!nbdata->copy)
|
||||
goto out_with_buffer;
|
||||
|
||||
bdata->look_init = hwloc_nolibxml_look_init;
|
||||
bdata->look_failed = hwloc_nolibxml_look_failed;
|
||||
bdata->backend_exit = hwloc_nolibxml_backend_exit;
|
||||
return 0;
|
||||
|
||||
out_with_buffer:
|
||||
free(nbdata->buffer);
|
||||
out_with_nbdata:
|
||||
free(nbdata);
|
||||
out:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_nolibxml_import_diff(struct hwloc__xml_import_state_s *state,
|
||||
const char *xmlpath, const char *xmlbuffer, int xmlbuflen,
|
||||
hwloc_topology_diff_t *firstdiffp, char **refnamep)
|
||||
{
|
||||
hwloc__nolibxml_import_state_data_t nstate = (void*) state->data;
|
||||
struct hwloc__xml_import_state_s childstate;
|
||||
char *refname = NULL;
|
||||
char *buffer, *tmp, *tag;
|
||||
size_t buflen;
|
||||
int ret;
|
||||
|
||||
assert(sizeof(*nstate) <= sizeof(state->data));
|
||||
|
||||
if (xmlbuffer) {
|
||||
buffer = malloc(xmlbuflen);
|
||||
if (!buffer)
|
||||
goto out;
|
||||
memcpy(buffer, xmlbuffer, xmlbuflen);
|
||||
buflen = xmlbuflen;
|
||||
|
||||
} else {
|
||||
ret = hwloc_nolibxml_read_file(xmlpath, &buffer, &buflen);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* skip headers */
|
||||
tmp = buffer;
|
||||
while (!strncmp(tmp, "<?xml ", 6) || !strncmp(tmp, "<!DOCTYPE ", 10)) {
|
||||
tmp = strchr(tmp, '\n');
|
||||
if (!tmp)
|
||||
goto out_with_buffer;
|
||||
tmp++;
|
||||
}
|
||||
|
||||
state->global->next_attr = hwloc__nolibxml_import_next_attr;
|
||||
state->global->find_child = hwloc__nolibxml_import_find_child;
|
||||
state->global->close_tag = hwloc__nolibxml_import_close_tag;
|
||||
state->global->close_child = hwloc__nolibxml_import_close_child;
|
||||
state->global->get_content = hwloc__nolibxml_import_get_content;
|
||||
state->global->close_content = hwloc__nolibxml_import_close_content;
|
||||
state->parent = NULL;
|
||||
nstate->closed = 0;
|
||||
nstate->tagbuffer = tmp;
|
||||
nstate->tagname = NULL;
|
||||
nstate->attrbuffer = NULL;
|
||||
|
||||
/* find root */
|
||||
ret = hwloc__nolibxml_import_find_child(state, &childstate, &tag);
|
||||
if (ret < 0)
|
||||
goto out_with_buffer;
|
||||
if (strcmp(tag, "topologydiff"))
|
||||
goto out_with_buffer;
|
||||
|
||||
while (1) {
|
||||
char *attrname, *attrvalue;
|
||||
if (hwloc__nolibxml_import_next_attr(&childstate, &attrname, &attrvalue) < 0)
|
||||
break;
|
||||
if (!strcmp(attrname, "refname")) {
|
||||
free(refname);
|
||||
refname = strdup(attrvalue);
|
||||
} else
|
||||
goto out_with_buffer;
|
||||
}
|
||||
|
||||
ret = hwloc__xml_import_diff(&childstate, firstdiffp);
|
||||
if (refnamep && !ret)
|
||||
*refnamep = refname;
|
||||
else
|
||||
free(refname);
|
||||
|
||||
free(buffer);
|
||||
return ret;
|
||||
|
||||
out_with_buffer:
|
||||
free(buffer);
|
||||
out:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*******************
|
||||
* Export routines *
|
||||
*******************/
|
||||
|
||||
typedef struct hwloc__nolibxml_export_state_data_s {
|
||||
char *buffer; /* (moving) buffer where to write */
|
||||
size_t written; /* how many bytes were written (or would have be written if not truncated) */
|
||||
size_t remaining; /* how many bytes are still available in the buffer */
|
||||
unsigned indent; /* indentation level for the next line */
|
||||
unsigned nr_children;
|
||||
unsigned has_content;
|
||||
} __hwloc_attribute_may_alias * hwloc__nolibxml_export_state_data_t;
|
||||
|
||||
static void
|
||||
hwloc__nolibxml_export_update_buffer(hwloc__nolibxml_export_state_data_t ndata, int res)
|
||||
{
|
||||
if (res >= 0) {
|
||||
ndata->written += res;
|
||||
if (res >= (int) ndata->remaining)
|
||||
res = ndata->remaining>0 ? (int)ndata->remaining-1 : 0;
|
||||
ndata->buffer += res;
|
||||
ndata->remaining -= res;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
hwloc__nolibxml_export_escape_string(const char *src)
|
||||
{
|
||||
size_t fulllen, sublen;
|
||||
char *escaped, *dst;
|
||||
|
||||
fulllen = strlen(src);
|
||||
|
||||
sublen = strcspn(src, "\n\r\t\"<>&");
|
||||
if (sublen == fulllen)
|
||||
return NULL; /* nothing to escape */
|
||||
|
||||
escaped = malloc(fulllen*6+1); /* escaped chars are replaced by at most 6 char */
|
||||
dst = escaped;
|
||||
|
||||
memcpy(dst, src, sublen);
|
||||
src += sublen;
|
||||
dst += sublen;
|
||||
|
||||
while (*src) {
|
||||
int replen;
|
||||
switch (*src) {
|
||||
case '\n': strcpy(dst, " "); replen=5; break;
|
||||
case '\r': strcpy(dst, " "); replen=5; break;
|
||||
case '\t': strcpy(dst, "	"); replen=4; break;
|
||||
case '\"': strcpy(dst, """); replen=6; break;
|
||||
case '<': strcpy(dst, "<"); replen=4; break;
|
||||
case '>': strcpy(dst, ">"); replen=4; break;
|
||||
case '&': strcpy(dst, "&"); replen=5; break;
|
||||
default: replen=0; break;
|
||||
}
|
||||
dst+=replen; src++;
|
||||
|
||||
sublen = strcspn(src, "\n\r\t\"<>&");
|
||||
memcpy(dst, src, sublen);
|
||||
src += sublen;
|
||||
dst += sublen;
|
||||
}
|
||||
|
||||
*dst = 0;
|
||||
return escaped;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__nolibxml_export_new_child(hwloc__xml_export_state_t parentstate,
|
||||
hwloc__xml_export_state_t state,
|
||||
const char *name)
|
||||
{
|
||||
hwloc__nolibxml_export_state_data_t npdata = (void *) parentstate->data;
|
||||
hwloc__nolibxml_export_state_data_t ndata = (void *) state->data;
|
||||
int res;
|
||||
|
||||
assert(!npdata->has_content);
|
||||
if (!npdata->nr_children) {
|
||||
res = hwloc_snprintf(npdata->buffer, npdata->remaining, ">\n");
|
||||
hwloc__nolibxml_export_update_buffer(npdata, res);
|
||||
}
|
||||
npdata->nr_children++;
|
||||
|
||||
state->parent = parentstate;
|
||||
state->new_child = parentstate->new_child;
|
||||
state->new_prop = parentstate->new_prop;
|
||||
state->add_content = parentstate->add_content;
|
||||
state->end_object = parentstate->end_object;
|
||||
|
||||
ndata->buffer = npdata->buffer;
|
||||
ndata->written = npdata->written;
|
||||
ndata->remaining = npdata->remaining;
|
||||
ndata->indent = npdata->indent + 2;
|
||||
|
||||
ndata->nr_children = 0;
|
||||
ndata->has_content = 0;
|
||||
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining, "%*s<%s", (int) npdata->indent, "", name);
|
||||
hwloc__nolibxml_export_update_buffer(ndata, res);
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__nolibxml_export_new_prop(hwloc__xml_export_state_t state, const char *name, const char *value)
|
||||
{
|
||||
hwloc__nolibxml_export_state_data_t ndata = (void *) state->data;
|
||||
char *escaped = hwloc__nolibxml_export_escape_string(value);
|
||||
int res = hwloc_snprintf(ndata->buffer, ndata->remaining, " %s=\"%s\"", name, escaped ? (const char *) escaped : value);
|
||||
hwloc__nolibxml_export_update_buffer(ndata, res);
|
||||
free(escaped);
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__nolibxml_export_end_object(hwloc__xml_export_state_t state, const char *name)
|
||||
{
|
||||
hwloc__nolibxml_export_state_data_t ndata = (void *) state->data;
|
||||
hwloc__nolibxml_export_state_data_t npdata = (void *) state->parent->data;
|
||||
int res;
|
||||
|
||||
assert (!(ndata->has_content && ndata->nr_children));
|
||||
if (ndata->has_content) {
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining, "</%s>\n", name);
|
||||
} else if (ndata->nr_children) {
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining, "%*s</%s>\n", (int) npdata->indent, "", name);
|
||||
} else {
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining, "/>\n");
|
||||
}
|
||||
hwloc__nolibxml_export_update_buffer(ndata, res);
|
||||
|
||||
npdata->buffer = ndata->buffer;
|
||||
npdata->written = ndata->written;
|
||||
npdata->remaining = ndata->remaining;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc__nolibxml_export_add_content(hwloc__xml_export_state_t state, const char *buffer, size_t length)
|
||||
{
|
||||
hwloc__nolibxml_export_state_data_t ndata = (void *) state->data;
|
||||
int res;
|
||||
|
||||
assert(!ndata->nr_children);
|
||||
if (!ndata->has_content) {
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining, ">");
|
||||
hwloc__nolibxml_export_update_buffer(ndata, res);
|
||||
}
|
||||
ndata->has_content = 1;
|
||||
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining, buffer, length);
|
||||
hwloc__nolibxml_export_update_buffer(ndata, res);
|
||||
}
|
||||
|
||||
static size_t
|
||||
hwloc___nolibxml_prepare_export(hwloc_topology_t topology, char *xmlbuffer, int buflen, unsigned long flags)
|
||||
{
|
||||
struct hwloc__xml_export_state_s state, childstate;
|
||||
hwloc__nolibxml_export_state_data_t ndata = (void *) &state.data;
|
||||
int res;
|
||||
|
||||
assert(sizeof(*ndata) <= sizeof(state.data));
|
||||
|
||||
state.new_child = hwloc__nolibxml_export_new_child;
|
||||
state.new_prop = hwloc__nolibxml_export_new_prop;
|
||||
state.add_content = hwloc__nolibxml_export_add_content;
|
||||
state.end_object = hwloc__nolibxml_export_end_object;
|
||||
|
||||
ndata->indent = 0;
|
||||
ndata->written = 0;
|
||||
ndata->buffer = xmlbuffer;
|
||||
ndata->remaining = buflen;
|
||||
|
||||
ndata->nr_children = 1; /* don't close a non-existing previous tag when opening the topology tag */
|
||||
ndata->has_content = 0;
|
||||
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining,
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<!DOCTYPE topology SYSTEM \"hwloc.dtd\">\n");
|
||||
hwloc__nolibxml_export_update_buffer(ndata, res);
|
||||
hwloc__nolibxml_export_new_child(&state, &childstate, "topology");
|
||||
hwloc__xml_export_topology (&childstate, topology, flags);
|
||||
hwloc__nolibxml_export_end_object(&childstate, "topology");
|
||||
|
||||
return ndata->written+1;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_nolibxml_export_buffer(hwloc_topology_t topology, char **bufferp, int *buflenp, unsigned long flags)
|
||||
{
|
||||
char *buffer;
|
||||
size_t bufferlen, res;
|
||||
|
||||
bufferlen = 16384; /* random guess for large enough default */
|
||||
buffer = malloc(bufferlen);
|
||||
if (!buffer)
|
||||
return -1;
|
||||
res = hwloc___nolibxml_prepare_export(topology, buffer, (int)bufferlen, flags);
|
||||
|
||||
if (res > bufferlen) {
|
||||
char *tmp = realloc(buffer, res);
|
||||
if (!tmp) {
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
buffer = tmp;
|
||||
hwloc___nolibxml_prepare_export(topology, buffer, (int)res, flags);
|
||||
}
|
||||
|
||||
*bufferp = buffer;
|
||||
*buflenp = (int)res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_nolibxml_export_file(hwloc_topology_t topology, const char *filename, unsigned long flags)
|
||||
{
|
||||
FILE *file;
|
||||
char *buffer;
|
||||
int bufferlen;
|
||||
int ret;
|
||||
|
||||
ret = hwloc_nolibxml_export_buffer(topology, &buffer, &bufferlen, flags);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
if (!strcmp(filename, "-")) {
|
||||
file = stdout;
|
||||
} else {
|
||||
file = fopen(filename, "w");
|
||||
if (!file) {
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = (int)fwrite(buffer, 1, bufferlen-1 /* don't write the ending \0 */, file);
|
||||
if (ret == bufferlen-1) {
|
||||
ret = 0;
|
||||
} else {
|
||||
errno = ferror(file);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
if (file != stdout)
|
||||
fclose(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t
|
||||
hwloc___nolibxml_prepare_export_diff(hwloc_topology_diff_t diff, const char *refname, char *xmlbuffer, int buflen)
|
||||
{
|
||||
struct hwloc__xml_export_state_s state, childstate;
|
||||
hwloc__nolibxml_export_state_data_t ndata = (void *) &state.data;
|
||||
int res;
|
||||
|
||||
assert(sizeof(*ndata) <= sizeof(state.data));
|
||||
|
||||
state.new_child = hwloc__nolibxml_export_new_child;
|
||||
state.new_prop = hwloc__nolibxml_export_new_prop;
|
||||
state.add_content = hwloc__nolibxml_export_add_content;
|
||||
state.end_object = hwloc__nolibxml_export_end_object;
|
||||
|
||||
ndata->indent = 0;
|
||||
ndata->written = 0;
|
||||
ndata->buffer = xmlbuffer;
|
||||
ndata->remaining = buflen;
|
||||
|
||||
ndata->nr_children = 1; /* don't close a non-existing previous tag when opening the topology tag */
|
||||
ndata->has_content = 0;
|
||||
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining,
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<!DOCTYPE topologydiff SYSTEM \"hwloc.dtd\">\n");
|
||||
hwloc__nolibxml_export_update_buffer(ndata, res);
|
||||
hwloc__nolibxml_export_new_child(&state, &childstate, "topologydiff");
|
||||
if (refname)
|
||||
hwloc__nolibxml_export_new_prop(&childstate, "refname", refname);
|
||||
hwloc__xml_export_diff (&childstate, diff);
|
||||
hwloc__nolibxml_export_end_object(&childstate, "topologydiff");
|
||||
|
||||
return ndata->written+1;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_nolibxml_export_diff_buffer(hwloc_topology_diff_t diff, const char *refname, char **bufferp, int *buflenp)
|
||||
{
|
||||
char *buffer;
|
||||
size_t bufferlen, res;
|
||||
|
||||
bufferlen = 16384; /* random guess for large enough default */
|
||||
buffer = malloc(bufferlen);
|
||||
if (!buffer)
|
||||
return -1;
|
||||
res = hwloc___nolibxml_prepare_export_diff(diff, refname, buffer, (int)bufferlen);
|
||||
|
||||
if (res > bufferlen) {
|
||||
char *tmp = realloc(buffer, res);
|
||||
if (!tmp) {
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
buffer = tmp;
|
||||
hwloc___nolibxml_prepare_export_diff(diff, refname, buffer, (int)res);
|
||||
}
|
||||
|
||||
*bufferp = buffer;
|
||||
*buflenp = (int)res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_nolibxml_export_diff_file(hwloc_topology_diff_t diff, const char *refname, const char *filename)
|
||||
{
|
||||
FILE *file;
|
||||
char *buffer;
|
||||
int bufferlen;
|
||||
int ret;
|
||||
|
||||
ret = hwloc_nolibxml_export_diff_buffer(diff, refname, &buffer, &bufferlen);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
if (!strcmp(filename, "-")) {
|
||||
file = stdout;
|
||||
} else {
|
||||
file = fopen(filename, "w");
|
||||
if (!file) {
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ret = (int)fwrite(buffer, 1, bufferlen-1 /* don't write the ending \0 */, file);
|
||||
if (ret == bufferlen-1) {
|
||||
ret = 0;
|
||||
} else {
|
||||
errno = ferror(file);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
|
||||
if (file != stdout)
|
||||
fclose(file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_nolibxml_free_buffer(void *xmlbuffer)
|
||||
{
|
||||
free(xmlbuffer);
|
||||
}
|
||||
|
||||
/*************
|
||||
* Callbacks *
|
||||
*************/
|
||||
|
||||
static struct hwloc_xml_callbacks hwloc_xml_nolibxml_callbacks = {
|
||||
hwloc_nolibxml_backend_init,
|
||||
hwloc_nolibxml_export_file,
|
||||
hwloc_nolibxml_export_buffer,
|
||||
hwloc_nolibxml_free_buffer,
|
||||
hwloc_nolibxml_import_diff,
|
||||
hwloc_nolibxml_export_diff_file,
|
||||
hwloc_nolibxml_export_diff_buffer
|
||||
};
|
||||
|
||||
static struct hwloc_xml_component hwloc_nolibxml_xml_component = {
|
||||
&hwloc_xml_nolibxml_callbacks,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct hwloc_component hwloc_xml_nolibxml_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
NULL, NULL,
|
||||
HWLOC_COMPONENT_TYPE_XML,
|
||||
0,
|
||||
&hwloc_nolibxml_xml_component
|
||||
};
|
2398
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-xml.c
Обычный файл
2398
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology-xml.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
3684
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology.c
Обычный файл
3684
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
553
opal/mca/hwloc/hwloc2x/hwloc/hwloc/traversal.c
Обычный файл
553
opal/mca/hwloc/hwloc2x/hwloc/hwloc/traversal.c
Обычный файл
@ -0,0 +1,553 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/misc.h>
|
||||
#include <private/debug.h>
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif /* HAVE_STRINGS_H */
|
||||
|
||||
int
|
||||
hwloc_get_type_depth (struct hwloc_topology *topology, hwloc_obj_type_t type)
|
||||
{
|
||||
return topology->type_depth[type];
|
||||
}
|
||||
|
||||
hwloc_obj_type_t
|
||||
hwloc_get_depth_type (hwloc_topology_t topology, unsigned depth)
|
||||
{
|
||||
if (depth >= topology->nb_levels)
|
||||
switch (depth) {
|
||||
case HWLOC_TYPE_DEPTH_BRIDGE:
|
||||
return HWLOC_OBJ_BRIDGE;
|
||||
case HWLOC_TYPE_DEPTH_PCI_DEVICE:
|
||||
return HWLOC_OBJ_PCI_DEVICE;
|
||||
case HWLOC_TYPE_DEPTH_OS_DEVICE:
|
||||
return HWLOC_OBJ_OS_DEVICE;
|
||||
case HWLOC_TYPE_DEPTH_MISC:
|
||||
return HWLOC_OBJ_MISC;
|
||||
default:
|
||||
return HWLOC_OBJ_TYPE_NONE;
|
||||
}
|
||||
return topology->levels[depth][0]->type;
|
||||
}
|
||||
|
||||
unsigned
|
||||
hwloc_get_nbobjs_by_depth (struct hwloc_topology *topology, unsigned depth)
|
||||
{
|
||||
if (depth >= topology->nb_levels) {
|
||||
unsigned l = HWLOC_SLEVEL_FROM_DEPTH(depth);
|
||||
if (l < HWLOC_NR_SLEVELS)
|
||||
return topology->slevels[l].nbobjs;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return topology->level_nbobjects[depth];
|
||||
}
|
||||
|
||||
struct hwloc_obj *
|
||||
hwloc_get_obj_by_depth (struct hwloc_topology *topology, unsigned depth, unsigned idx)
|
||||
{
|
||||
if (depth >= topology->nb_levels) {
|
||||
unsigned l = HWLOC_SLEVEL_FROM_DEPTH(depth);
|
||||
if (l < HWLOC_NR_SLEVELS)
|
||||
return idx < topology->slevels[l].nbobjs ? topology->slevels[l].objs[idx] : NULL;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
if (idx >= topology->level_nbobjects[depth])
|
||||
return NULL;
|
||||
return topology->levels[depth][idx];
|
||||
}
|
||||
|
||||
unsigned hwloc_get_closest_objs (struct hwloc_topology *topology, struct hwloc_obj *src, struct hwloc_obj **objs, unsigned max)
|
||||
{
|
||||
struct hwloc_obj *parent, *nextparent, **src_objs;
|
||||
int i,src_nbobjects;
|
||||
unsigned stored = 0;
|
||||
|
||||
if (!src->cpuset)
|
||||
return 0;
|
||||
|
||||
src_nbobjects = topology->level_nbobjects[src->depth];
|
||||
src_objs = topology->levels[src->depth];
|
||||
|
||||
parent = src;
|
||||
while (stored < max) {
|
||||
while (1) {
|
||||
nextparent = parent->parent;
|
||||
if (!nextparent)
|
||||
goto out;
|
||||
if (!hwloc_bitmap_isequal(parent->cpuset, nextparent->cpuset))
|
||||
break;
|
||||
parent = nextparent;
|
||||
}
|
||||
|
||||
/* traverse src's objects and find those that are in nextparent and were not in parent */
|
||||
for(i=0; i<src_nbobjects; i++) {
|
||||
if (hwloc_bitmap_isincluded(src_objs[i]->cpuset, nextparent->cpuset)
|
||||
&& !hwloc_bitmap_isincluded(src_objs[i]->cpuset, parent->cpuset)) {
|
||||
objs[stored++] = src_objs[i];
|
||||
if (stored == max)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
parent = nextparent;
|
||||
}
|
||||
|
||||
out:
|
||||
return stored;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__get_largest_objs_inside_cpuset (struct hwloc_obj *current, hwloc_const_bitmap_t set,
|
||||
struct hwloc_obj ***res, int *max)
|
||||
{
|
||||
int gotten = 0;
|
||||
unsigned i;
|
||||
|
||||
/* the caller must ensure this */
|
||||
if (*max <= 0)
|
||||
return 0;
|
||||
|
||||
if (hwloc_bitmap_isequal(current->cpuset, set)) {
|
||||
**res = current;
|
||||
(*res)++;
|
||||
(*max)--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i=0; i<current->arity; i++) {
|
||||
hwloc_bitmap_t subset;
|
||||
int ret;
|
||||
|
||||
/* split out the cpuset part corresponding to this child and see if there's anything to do */
|
||||
if (!hwloc_bitmap_intersects(set,current->children[i]->cpuset))
|
||||
continue;
|
||||
|
||||
subset = hwloc_bitmap_dup(set);
|
||||
hwloc_bitmap_and(subset, subset, current->children[i]->cpuset);
|
||||
ret = hwloc__get_largest_objs_inside_cpuset (current->children[i], subset, res, max);
|
||||
gotten += ret;
|
||||
hwloc_bitmap_free(subset);
|
||||
|
||||
/* if no more room to store remaining objects, return what we got so far */
|
||||
if (!*max)
|
||||
break;
|
||||
}
|
||||
|
||||
return gotten;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_get_largest_objs_inside_cpuset (struct hwloc_topology *topology, hwloc_const_bitmap_t set,
|
||||
struct hwloc_obj **objs, int max)
|
||||
{
|
||||
struct hwloc_obj *current = topology->levels[0][0];
|
||||
|
||||
if (!hwloc_bitmap_isincluded(set, current->cpuset))
|
||||
return -1;
|
||||
|
||||
if (max <= 0)
|
||||
return 0;
|
||||
|
||||
return hwloc__get_largest_objs_inside_cpuset (current, set, &objs, &max);
|
||||
}
|
||||
|
||||
const char *
|
||||
hwloc_type_name (hwloc_obj_type_t obj)
|
||||
{
|
||||
switch (obj)
|
||||
{
|
||||
case HWLOC_OBJ_SYSTEM: return "System";
|
||||
case HWLOC_OBJ_MACHINE: return "Machine";
|
||||
case HWLOC_OBJ_MISC: return "Misc";
|
||||
case HWLOC_OBJ_GROUP: return "Group";
|
||||
case HWLOC_OBJ_NUMANODE: return "NUMANode";
|
||||
case HWLOC_OBJ_PACKAGE: return "Package";
|
||||
case HWLOC_OBJ_L1CACHE: return "L1Cache";
|
||||
case HWLOC_OBJ_L2CACHE: return "L2Cache";
|
||||
case HWLOC_OBJ_L3CACHE: return "L3Cache";
|
||||
case HWLOC_OBJ_L4CACHE: return "L4Cache";
|
||||
case HWLOC_OBJ_L5CACHE: return "L5Cache";
|
||||
case HWLOC_OBJ_L1ICACHE: return "L1iCache";
|
||||
case HWLOC_OBJ_L2ICACHE: return "L2iCache";
|
||||
case HWLOC_OBJ_L3ICACHE: return "L3iCache";
|
||||
case HWLOC_OBJ_CORE: return "Core";
|
||||
case HWLOC_OBJ_BRIDGE: return "Bridge";
|
||||
case HWLOC_OBJ_PCI_DEVICE: return "PCIDev";
|
||||
case HWLOC_OBJ_OS_DEVICE: return "OSDev";
|
||||
case HWLOC_OBJ_PU: return "PU";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_type_sscanf(const char *string, hwloc_obj_type_t *typep,
|
||||
union hwloc_obj_attr_u *attrp, size_t attrsize)
|
||||
{
|
||||
hwloc_obj_type_t type = (hwloc_obj_type_t) -1;
|
||||
unsigned depthattr = (unsigned) -1;
|
||||
hwloc_obj_cache_type_t cachetypeattr = (hwloc_obj_cache_type_t) -1; /* unspecified */
|
||||
hwloc_obj_bridge_type_t ubtype = (hwloc_obj_bridge_type_t) -1;
|
||||
hwloc_obj_osdev_type_t ostype = (hwloc_obj_osdev_type_t) -1;
|
||||
char *end;
|
||||
|
||||
/* never match the ending \0 since we want to match things like core:2 too.
|
||||
* just use hwloc_strncasecmp() everywhere.
|
||||
*/
|
||||
|
||||
/* types without a custom depth */
|
||||
if (!hwloc_strncasecmp(string, "system", 2)) {
|
||||
type = HWLOC_OBJ_SYSTEM;
|
||||
} else if (!hwloc_strncasecmp(string, "machine", 2)) {
|
||||
type = HWLOC_OBJ_MACHINE;
|
||||
} else if (!hwloc_strncasecmp(string, "node", 2)
|
||||
|| !hwloc_strncasecmp(string, "numa", 2)) { /* matches node and numanode */
|
||||
type = HWLOC_OBJ_NUMANODE;
|
||||
} else if (!hwloc_strncasecmp(string, "package", 2)
|
||||
|| !hwloc_strncasecmp(string, "socket", 2)) { /* backward compat with v1.10 */
|
||||
type = HWLOC_OBJ_PACKAGE;
|
||||
} else if (!hwloc_strncasecmp(string, "core", 2)) {
|
||||
type = HWLOC_OBJ_CORE;
|
||||
} else if (!hwloc_strncasecmp(string, "pu", 2)) {
|
||||
type = HWLOC_OBJ_PU;
|
||||
} else if (!hwloc_strncasecmp(string, "misc", 4)) {
|
||||
type = HWLOC_OBJ_MISC;
|
||||
|
||||
} else if (!hwloc_strncasecmp(string, "bridge", 4)) {
|
||||
type = HWLOC_OBJ_BRIDGE;
|
||||
} else if (!hwloc_strncasecmp(string, "hostbridge", 6)) {
|
||||
type = HWLOC_OBJ_BRIDGE;
|
||||
ubtype = HWLOC_OBJ_BRIDGE_HOST;
|
||||
} else if (!hwloc_strncasecmp(string, "pcibridge", 5)) {
|
||||
type = HWLOC_OBJ_BRIDGE;
|
||||
ubtype = HWLOC_OBJ_BRIDGE_PCI;
|
||||
|
||||
} else if (!hwloc_strncasecmp(string, "pci", 3)) {
|
||||
type = HWLOC_OBJ_PCI_DEVICE;
|
||||
|
||||
} else if (!hwloc_strncasecmp(string, "os", 2)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
} else if (!hwloc_strncasecmp(string, "bloc", 4)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_BLOCK;
|
||||
} else if (!hwloc_strncasecmp(string, "net", 3)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_NETWORK;
|
||||
} else if (!hwloc_strncasecmp(string, "openfab", 7)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_OPENFABRICS;
|
||||
} else if (!hwloc_strncasecmp(string, "dma", 3)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_DMA;
|
||||
} else if (!hwloc_strncasecmp(string, "gpu", 3)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_GPU;
|
||||
} else if (!hwloc_strncasecmp(string, "copro", 5)
|
||||
|| !hwloc_strncasecmp(string, "co-pro", 6)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_COPROC;
|
||||
|
||||
/* types with depthattr */
|
||||
} else if ((string[0] == 'l' || string[0] == 'L') && string[1] >= '0' && string[1] <= '9') {
|
||||
depthattr = strtol(string+1, &end, 10);
|
||||
if (*end == 'i') {
|
||||
if (depthattr >= 1 && depthattr <= 3) {
|
||||
type = HWLOC_OBJ_L1ICACHE + depthattr-1;
|
||||
cachetypeattr = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
} else
|
||||
return -1;
|
||||
} else {
|
||||
if (depthattr >= 1 && depthattr <= 5) {
|
||||
type = HWLOC_OBJ_L1CACHE + depthattr-1;
|
||||
cachetypeattr = *end == 'd' ? HWLOC_OBJ_CACHE_DATA : HWLOC_OBJ_CACHE_UNIFIED;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else if (!hwloc_strncasecmp(string, "group", 2)) {
|
||||
size_t length;
|
||||
type = HWLOC_OBJ_GROUP;
|
||||
length = strcspn(string, "0123456789");
|
||||
if (length <= 5 && !hwloc_strncasecmp(string, "group", length)
|
||||
&& string[length] >= '0' && string[length] <= '9') {
|
||||
depthattr = strtol(string+length, &end, 10);
|
||||
}
|
||||
|
||||
} else
|
||||
return -1;
|
||||
|
||||
*typep = type;
|
||||
if (attrp) {
|
||||
if (hwloc_obj_type_is_cache(type) && attrsize >= sizeof(attrp->cache)) {
|
||||
attrp->cache.depth = depthattr;
|
||||
attrp->cache.type = cachetypeattr;
|
||||
} else if (type == HWLOC_OBJ_GROUP && attrsize >= sizeof(attrp->group)) {
|
||||
attrp->group.depth = depthattr;
|
||||
} else if (type == HWLOC_OBJ_BRIDGE && attrsize >= sizeof(attrp->bridge)) {
|
||||
attrp->bridge.upstream_type = ubtype;
|
||||
attrp->bridge.downstream_type = HWLOC_OBJ_BRIDGE_PCI; /* nothing else so far */
|
||||
} else if (type == HWLOC_OBJ_OS_DEVICE && attrsize >= sizeof(attrp->osdev)) {
|
||||
attrp->osdev.type = ostype;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_type_sscanf_as_depth(const char *string, hwloc_obj_type_t *typep,
|
||||
hwloc_topology_t topology, int *depthp)
|
||||
{
|
||||
union hwloc_obj_attr_u attr;
|
||||
hwloc_obj_type_t type;
|
||||
int depth;
|
||||
int err;
|
||||
|
||||
err = hwloc_type_sscanf(string, &type, &attr, sizeof(attr));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
depth = hwloc_get_type_depth(topology, type);
|
||||
if (type == HWLOC_OBJ_GROUP
|
||||
&& depth == HWLOC_TYPE_DEPTH_MULTIPLE
|
||||
&& attr.group.depth != (unsigned)-1) {
|
||||
unsigned l;
|
||||
depth = HWLOC_TYPE_DEPTH_UNKNOWN;
|
||||
for(l=0; l<topology->nb_levels; l++) {
|
||||
if (topology->levels[l][0]->type == HWLOC_OBJ_GROUP
|
||||
&& topology->levels[l][0]->attr->group.depth == attr.group.depth) {
|
||||
depth = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typep)
|
||||
*typep = type;
|
||||
*depthp = (unsigned) depth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* hwloc_obj_cache_type_letter(hwloc_obj_cache_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case HWLOC_OBJ_CACHE_UNIFIED: return "";
|
||||
case HWLOC_OBJ_CACHE_DATA: return "d";
|
||||
case HWLOC_OBJ_CACHE_INSTRUCTION: return "i";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, int verbose)
|
||||
{
|
||||
hwloc_obj_type_t type = obj->type;
|
||||
switch (type) {
|
||||
case HWLOC_OBJ_MISC:
|
||||
case HWLOC_OBJ_SYSTEM:
|
||||
case HWLOC_OBJ_MACHINE:
|
||||
case HWLOC_OBJ_NUMANODE:
|
||||
case HWLOC_OBJ_PACKAGE:
|
||||
case HWLOC_OBJ_CORE:
|
||||
case HWLOC_OBJ_PU:
|
||||
return hwloc_snprintf(string, size, "%s", hwloc_type_name(type));
|
||||
case HWLOC_OBJ_L1CACHE:
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
case HWLOC_OBJ_L3CACHE:
|
||||
case HWLOC_OBJ_L4CACHE:
|
||||
case HWLOC_OBJ_L5CACHE:
|
||||
case HWLOC_OBJ_L1ICACHE:
|
||||
case HWLOC_OBJ_L2ICACHE:
|
||||
case HWLOC_OBJ_L3ICACHE:
|
||||
return hwloc_snprintf(string, size, "L%u%s%s", obj->attr->cache.depth,
|
||||
hwloc_obj_cache_type_letter(obj->attr->cache.type),
|
||||
verbose ? "Cache" : "");
|
||||
case HWLOC_OBJ_GROUP:
|
||||
if (obj->attr->group.depth != (unsigned) -1)
|
||||
return hwloc_snprintf(string, size, "%s%u", hwloc_type_name(type), obj->attr->group.depth);
|
||||
else
|
||||
return hwloc_snprintf(string, size, "%s", hwloc_type_name(type));
|
||||
case HWLOC_OBJ_BRIDGE:
|
||||
return snprintf(string, size, obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI ? "PCIBridge" : "HostBridge");
|
||||
case HWLOC_OBJ_PCI_DEVICE:
|
||||
return hwloc_snprintf(string, size, "PCI");
|
||||
case HWLOC_OBJ_OS_DEVICE:
|
||||
switch (obj->attr->osdev.type) {
|
||||
case HWLOC_OBJ_OSDEV_BLOCK: return hwloc_snprintf(string, size, "Block");
|
||||
case HWLOC_OBJ_OSDEV_NETWORK: return hwloc_snprintf(string, size, verbose ? "Network" : "Net");
|
||||
case HWLOC_OBJ_OSDEV_OPENFABRICS: return hwloc_snprintf(string, size, "OpenFabrics");
|
||||
case HWLOC_OBJ_OSDEV_DMA: return hwloc_snprintf(string, size, "DMA");
|
||||
case HWLOC_OBJ_OSDEV_GPU: return hwloc_snprintf(string, size, "GPU");
|
||||
case HWLOC_OBJ_OSDEV_COPROC: return hwloc_snprintf(string, size, verbose ? "Co-Processor" : "CoProc");
|
||||
default:
|
||||
if (size > 0)
|
||||
*string = '\0';
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (size > 0)
|
||||
*string = '\0';
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_obj_attr_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, const char * separator, int verbose)
|
||||
{
|
||||
const char *prefix = "";
|
||||
char *tmp = string;
|
||||
ssize_t tmplen = size;
|
||||
int ret = 0;
|
||||
int res;
|
||||
|
||||
/* make sure we output at least an empty string */
|
||||
if (size)
|
||||
*string = '\0';
|
||||
|
||||
/* print memory attributes */
|
||||
res = 0;
|
||||
if (verbose) {
|
||||
if (obj->memory.local_memory)
|
||||
res = hwloc_snprintf(tmp, tmplen, "%slocal=%lu%s%stotal=%lu%s",
|
||||
prefix,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->memory.local_memory, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->memory.total_memory, verbose),
|
||||
separator,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->memory.total_memory, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->memory.local_memory, verbose));
|
||||
else if (obj->memory.total_memory)
|
||||
res = hwloc_snprintf(tmp, tmplen, "%stotal=%lu%s",
|
||||
prefix,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->memory.total_memory, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->memory.total_memory, verbose));
|
||||
} else {
|
||||
if (obj->memory.local_memory)
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%lu%s",
|
||||
prefix,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->memory.local_memory, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->memory.local_memory, verbose));
|
||||
}
|
||||
if (res < 0)
|
||||
return -1;
|
||||
ret += res;
|
||||
if (ret > 0)
|
||||
prefix = separator;
|
||||
if (res >= tmplen)
|
||||
res = tmplen>0 ? (int)tmplen - 1 : 0;
|
||||
tmp += res;
|
||||
tmplen -= res;
|
||||
|
||||
/* printf type-specific attributes */
|
||||
res = 0;
|
||||
switch (obj->type) {
|
||||
case HWLOC_OBJ_L1CACHE:
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
case HWLOC_OBJ_L3CACHE:
|
||||
case HWLOC_OBJ_L4CACHE:
|
||||
case HWLOC_OBJ_L5CACHE:
|
||||
case HWLOC_OBJ_L1ICACHE:
|
||||
case HWLOC_OBJ_L2ICACHE:
|
||||
case HWLOC_OBJ_L3ICACHE:
|
||||
if (verbose) {
|
||||
char assoc[32];
|
||||
if (obj->attr->cache.associativity == -1)
|
||||
snprintf(assoc, sizeof(assoc), "%sfully-associative", separator);
|
||||
else if (obj->attr->cache.associativity == 0)
|
||||
*assoc = '\0';
|
||||
else
|
||||
snprintf(assoc, sizeof(assoc), "%sways=%d", separator, obj->attr->cache.associativity);
|
||||
res = hwloc_snprintf(tmp, tmplen, "%ssize=%lu%s%slinesize=%u%s",
|
||||
prefix,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->attr->cache.size, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose),
|
||||
separator, obj->attr->cache.linesize,
|
||||
assoc);
|
||||
} else
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%lu%s",
|
||||
prefix,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->attr->cache.size, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose));
|
||||
break;
|
||||
case HWLOC_OBJ_BRIDGE:
|
||||
if (verbose) {
|
||||
char up[128], down[64];
|
||||
/* upstream is PCI or HOST */
|
||||
if (obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI) {
|
||||
char linkspeed[64]= "";
|
||||
if (obj->attr->pcidev.linkspeed)
|
||||
snprintf(linkspeed, sizeof(linkspeed), "%slink=%.2fGB/s", separator, obj->attr->pcidev.linkspeed);
|
||||
snprintf(up, sizeof(up), "busid=%04x:%02x:%02x.%01x%sid=%04x:%04x%sclass=%04x(%s)%s",
|
||||
obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func, separator,
|
||||
obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id, separator,
|
||||
obj->attr->pcidev.class_id, hwloc_pci_class_string(obj->attr->pcidev.class_id), linkspeed);
|
||||
} else
|
||||
*up = '\0';
|
||||
/* downstream is_PCI */
|
||||
snprintf(down, sizeof(down), "buses=%04x:[%02x-%02x]",
|
||||
obj->attr->bridge.downstream.pci.domain, obj->attr->bridge.downstream.pci.secondary_bus, obj->attr->bridge.downstream.pci.subordinate_bus);
|
||||
if (*up)
|
||||
res = snprintf(string, size, "%s%s%s", up, separator, down);
|
||||
else
|
||||
res = snprintf(string, size, "%s", down);
|
||||
}
|
||||
break;
|
||||
case HWLOC_OBJ_PCI_DEVICE:
|
||||
if (verbose) {
|
||||
char linkspeed[64]= "";
|
||||
if (obj->attr->pcidev.linkspeed)
|
||||
snprintf(linkspeed, sizeof(linkspeed), "%slink=%.2fGB/s", separator, obj->attr->pcidev.linkspeed);
|
||||
res = snprintf(string, size, "busid=%04x:%02x:%02x.%01x%sid=%04x:%04x%sclass=%04x(%s)%s",
|
||||
obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func, separator,
|
||||
obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id, separator,
|
||||
obj->attr->pcidev.class_id, hwloc_pci_class_string(obj->attr->pcidev.class_id), linkspeed);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (res < 0)
|
||||
return -1;
|
||||
ret += res;
|
||||
if (ret > 0)
|
||||
prefix = separator;
|
||||
if (res >= tmplen)
|
||||
res = tmplen>0 ? (int)tmplen - 1 : 0;
|
||||
tmp += res;
|
||||
tmplen -= res;
|
||||
|
||||
/* printf infos */
|
||||
if (verbose) {
|
||||
unsigned i;
|
||||
for(i=0; i<obj->infos_count; i++) {
|
||||
if (strchr(obj->infos[i].value, ' '))
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%s=\"%s\"",
|
||||
prefix,
|
||||
obj->infos[i].name, obj->infos[i].value);
|
||||
else
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%s=%s",
|
||||
prefix,
|
||||
obj->infos[i].name, obj->infos[i].value);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
ret += res;
|
||||
if (res >= tmplen)
|
||||
res = tmplen>0 ? (int)tmplen - 1 : 0;
|
||||
tmp += res;
|
||||
tmplen -= res;
|
||||
if (ret > 0)
|
||||
prefix = separator;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
65
opal/mca/hwloc/hwloc2x/hwloc/include/Makefile.am
Обычный файл
65
opal/mca/hwloc/hwloc2x/hwloc/include/Makefile.am
Обычный файл
@ -0,0 +1,65 @@
|
||||
# Copyright © 2009-2016 Inria. All rights reserved.
|
||||
# Copyright © 2009-2010 Université Bordeaux
|
||||
# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved.
|
||||
# Copyright © 2011 Oracle and/or its affiliates. All rights reserved.
|
||||
# See COPYING in top-level directory.
|
||||
|
||||
# Only install the headers if we're in standalone mode (meaning:
|
||||
# *don't* install the headers if we're in embedded mode).
|
||||
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
include_HEADERS = hwloc.h
|
||||
|
||||
if BUILD_NETLOCSCOTCH
|
||||
include_HEADERS += netloc.h netlocscotch.h
|
||||
endif
|
||||
|
||||
include_hwlocdir = $(includedir)/hwloc
|
||||
include_hwloc_HEADERS = \
|
||||
hwloc/bitmap.h \
|
||||
hwloc/helper.h \
|
||||
hwloc/inlines.h \
|
||||
hwloc/diff.h \
|
||||
hwloc/distances.h \
|
||||
hwloc/export.h \
|
||||
hwloc/myriexpress.h \
|
||||
hwloc/openfabrics-verbs.h \
|
||||
hwloc/opencl.h \
|
||||
hwloc/cuda.h \
|
||||
hwloc/cudart.h \
|
||||
hwloc/nvml.h \
|
||||
hwloc/plugins.h \
|
||||
hwloc/gl.h \
|
||||
hwloc/intel-mic.h \
|
||||
hwloc/rename.h \
|
||||
hwloc/deprecated.h
|
||||
include_hwloc_autogendir = $(includedir)/hwloc/autogen
|
||||
nodist_include_hwloc_autogen_HEADERS = hwloc/autogen/config.h
|
||||
|
||||
noinst_HEADERS = \
|
||||
private/private.h \
|
||||
private/debug.h \
|
||||
private/misc.h \
|
||||
private/xml.h \
|
||||
private/components.h \
|
||||
private/cpuid-x86.h \
|
||||
private/netloc.h \
|
||||
netloc/utarray.h \
|
||||
netloc/uthash.h
|
||||
|
||||
if HWLOC_HAVE_LINUX
|
||||
include_hwloc_HEADERS += \
|
||||
hwloc/linux.h \
|
||||
hwloc/linux-libnuma.h
|
||||
endif HWLOC_HAVE_LINUX
|
||||
|
||||
if HWLOC_HAVE_SOLARIS
|
||||
include_hwloc_HEADERS += \
|
||||
private/solaris-chiptype.h
|
||||
endif HWLOC_HAVE_SOLARIS
|
||||
|
||||
if HWLOC_HAVE_SCHED_SETAFFINITY
|
||||
include_hwloc_HEADERS += hwloc/glibc-sched.h
|
||||
endif HWLOC_HAVE_SCHED_SETAFFINITY
|
||||
|
||||
endif HWLOC_BUILD_STANDALONE
|
2184
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc.h
Обычный файл
2184
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc.h
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
201
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/autogen/config.h.in
Обычный файл
201
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/autogen/config.h.in
Обычный файл
@ -0,0 +1,201 @@
|
||||
/* -*- c -*-
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2014 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/* The configuration file */
|
||||
|
||||
#ifndef HWLOC_CONFIG_H
|
||||
#define HWLOC_CONFIG_H
|
||||
|
||||
#if (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
|
||||
# define __hwloc_restrict __restrict
|
||||
#else
|
||||
# if __STDC_VERSION__ >= 199901L
|
||||
# define __hwloc_restrict restrict
|
||||
# else
|
||||
# define __hwloc_restrict
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Note that if we're compiling C++, then just use the "inline"
|
||||
keyword, since it's part of C++ */
|
||||
#if defined(c_plusplus) || defined(__cplusplus)
|
||||
# define __hwloc_inline inline
|
||||
#elif defined(_MSC_VER) || defined(__HP_cc)
|
||||
# define __hwloc_inline __inline
|
||||
#else
|
||||
# define __hwloc_inline __inline__
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note: this is public. We can not assume anything from the compiler used
|
||||
* by the application and thus the HWLOC_HAVE_* macros below are not
|
||||
* fetched from the autoconf result here. We only automatically use a few
|
||||
* well-known easy cases.
|
||||
*/
|
||||
|
||||
/* Some handy constants to make the logic below a little more readable */
|
||||
#if defined(__cplusplus) && \
|
||||
(__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR >= 4))
|
||||
#define GXX_ABOVE_3_4 1
|
||||
#else
|
||||
#define GXX_ABOVE_3_4 0
|
||||
#endif
|
||||
|
||||
#if !defined(__cplusplus) && \
|
||||
(__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
|
||||
#define GCC_ABOVE_2_95 1
|
||||
#else
|
||||
#define GCC_ABOVE_2_95 0
|
||||
#endif
|
||||
|
||||
#if !defined(__cplusplus) && \
|
||||
(__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96))
|
||||
#define GCC_ABOVE_2_96 1
|
||||
#else
|
||||
#define GCC_ABOVE_2_96 0
|
||||
#endif
|
||||
|
||||
#if !defined(__cplusplus) && \
|
||||
(__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
|
||||
#define GCC_ABOVE_3_3 1
|
||||
#else
|
||||
#define GCC_ABOVE_3_3 0
|
||||
#endif
|
||||
|
||||
/* Maybe before gcc 2.95 too */
|
||||
#ifdef HWLOC_HAVE_ATTRIBUTE_UNUSED
|
||||
#define __HWLOC_HAVE_ATTRIBUTE_UNUSED HWLOC_HAVE_ATTRIBUTE_UNUSED
|
||||
#elif defined(__GNUC__)
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_UNUSED (GXX_ABOVE_3_4 || GCC_ABOVE_2_95)
|
||||
#else
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_UNUSED 0
|
||||
#endif
|
||||
#if __HWLOC_HAVE_ATTRIBUTE_UNUSED
|
||||
# define __hwloc_attribute_unused __attribute__((__unused__))
|
||||
#else
|
||||
# define __hwloc_attribute_unused
|
||||
#endif
|
||||
|
||||
#ifdef HWLOC_HAVE_ATTRIBUTE_MALLOC
|
||||
#define __HWLOC_HAVE_ATTRIBUTE_MALLOC HWLOC_HAVE_ATTRIBUTE_MALLOC
|
||||
#elif defined(__GNUC__)
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_MALLOC (GXX_ABOVE_3_4 || GCC_ABOVE_2_96)
|
||||
#else
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_MALLOC 0
|
||||
#endif
|
||||
#if __HWLOC_HAVE_ATTRIBUTE_MALLOC
|
||||
# define __hwloc_attribute_malloc __attribute__((__malloc__))
|
||||
#else
|
||||
# define __hwloc_attribute_malloc
|
||||
#endif
|
||||
|
||||
#ifdef HWLOC_HAVE_ATTRIBUTE_CONST
|
||||
#define __HWLOC_HAVE_ATTRIBUTE_CONST HWLOC_HAVE_ATTRIBUTE_CONST
|
||||
#elif defined(__GNUC__)
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_CONST (GXX_ABOVE_3_4 || GCC_ABOVE_2_95)
|
||||
#else
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_CONST 0
|
||||
#endif
|
||||
#if __HWLOC_HAVE_ATTRIBUTE_CONST
|
||||
# define __hwloc_attribute_const __attribute__((__const__))
|
||||
#else
|
||||
# define __hwloc_attribute_const
|
||||
#endif
|
||||
|
||||
#ifdef HWLOC_HAVE_ATTRIBUTE_PURE
|
||||
#define __HWLOC_HAVE_ATTRIBUTE_PURE HWLOC_HAVE_ATTRIBUTE_PURE
|
||||
#elif defined(__GNUC__)
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_PURE (GXX_ABOVE_3_4 || GCC_ABOVE_2_96)
|
||||
#else
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_PURE 0
|
||||
#endif
|
||||
#if __HWLOC_HAVE_ATTRIBUTE_PURE
|
||||
# define __hwloc_attribute_pure __attribute__((__pure__))
|
||||
#else
|
||||
# define __hwloc_attribute_pure
|
||||
#endif
|
||||
|
||||
#ifdef HWLOC_HAVE_ATTRIBUTE_DEPRECATED
|
||||
#define __HWLOC_HAVE_ATTRIBUTE_DEPRECATED HWLOC_HAVE_ATTRIBUTE_DEPRECATED
|
||||
#elif defined(__GNUC__)
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_DEPRECATED (GXX_ABOVE_3_4 || GCC_ABOVE_3_3)
|
||||
#else
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_DEPRECATED 0
|
||||
#endif
|
||||
#if __HWLOC_HAVE_ATTRIBUTE_DEPRECATED
|
||||
# define __hwloc_attribute_deprecated __attribute__((__deprecated__))
|
||||
#else
|
||||
# define __hwloc_attribute_deprecated
|
||||
#endif
|
||||
|
||||
#ifdef HWLOC_HAVE_ATTRIBUTE_MAY_ALIAS
|
||||
#define __HWLOC_HAVE_ATTRIBUTE_MAY_ALIAS HWLOC_HAVE_ATTRIBUTE_MAY_ALIAS
|
||||
#elif defined(__GNUC__)
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_MAY_ALIAS (GXX_ABOVE_3_4 || GCC_ABOVE_3_3)
|
||||
#else
|
||||
# define __HWLOC_HAVE_ATTRIBUTE_MAY_ALIAS 0
|
||||
#endif
|
||||
#if __HWLOC_HAVE_ATTRIBUTE_MAY_ALIAS
|
||||
# define __hwloc_attribute_may_alias __attribute__((__may_alias__))
|
||||
#else
|
||||
# define __hwloc_attribute_may_alias
|
||||
#endif
|
||||
|
||||
#ifdef HWLOC_C_HAVE_VISIBILITY
|
||||
# if HWLOC_C_HAVE_VISIBILITY
|
||||
# define HWLOC_DECLSPEC __attribute__((__visibility__("default")))
|
||||
# else
|
||||
# define HWLOC_DECLSPEC
|
||||
# endif
|
||||
#else
|
||||
# define HWLOC_DECLSPEC
|
||||
#endif
|
||||
|
||||
/* Defined to 1 on Linux */
|
||||
#undef HWLOC_LINUX_SYS
|
||||
|
||||
/* Defined to 1 if the CPU_SET macro works */
|
||||
#undef HWLOC_HAVE_CPU_SET
|
||||
|
||||
/* Defined to 1 if you have the `windows.h' header. */
|
||||
#undef HWLOC_HAVE_WINDOWS_H
|
||||
#undef hwloc_pid_t
|
||||
#undef hwloc_thread_t
|
||||
|
||||
#ifdef HWLOC_HAVE_WINDOWS_H
|
||||
|
||||
# include <windows.h>
|
||||
typedef DWORDLONG hwloc_uint64_t;
|
||||
|
||||
#else /* HWLOC_HAVE_WINDOWS_H */
|
||||
|
||||
# ifdef hwloc_thread_t
|
||||
# include <pthread.h>
|
||||
# endif /* hwloc_thread_t */
|
||||
|
||||
/* Defined to 1 if you have the <stdint.h> header file. */
|
||||
# undef HWLOC_HAVE_STDINT_H
|
||||
|
||||
# include <unistd.h>
|
||||
# ifdef HWLOC_HAVE_STDINT_H
|
||||
# include <stdint.h>
|
||||
# endif
|
||||
typedef uint64_t hwloc_uint64_t;
|
||||
|
||||
#endif /* HWLOC_HAVE_WINDOWS_H */
|
||||
|
||||
/* Whether we need to re-define all the hwloc public symbols or not */
|
||||
#undef HWLOC_SYM_TRANSFORM
|
||||
|
||||
/* The hwloc symbol prefix */
|
||||
#undef HWLOC_SYM_PREFIX
|
||||
|
||||
/* The hwloc symbol prefix in all caps */
|
||||
#undef HWLOC_SYM_PREFIX_CAPS
|
||||
|
||||
#endif /* HWLOC_CONFIG_H */
|
376
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/bitmap.h
Обычный файл
376
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/bitmap.h
Обычный файл
@ -0,0 +1,376 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief The bitmap API, for use in hwloc itself.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_BITMAP_H
|
||||
#define HWLOC_BITMAP_H
|
||||
|
||||
#include <hwloc/autogen/config.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_bitmap The bitmap API
|
||||
*
|
||||
* The ::hwloc_bitmap_t type represents a set of objects, typically OS
|
||||
* processors -- which may actually be hardware threads (represented
|
||||
* by ::hwloc_cpuset_t, which is a typedef for ::hwloc_bitmap_t) -- or
|
||||
* memory nodes (represented by ::hwloc_nodeset_t, which is also a
|
||||
* typedef for ::hwloc_bitmap_t).
|
||||
*
|
||||
* <em>Both CPU and node sets are always indexed by OS physical number.</em>
|
||||
*
|
||||
* \note CPU sets and nodesets are described in \ref hwlocality_object_sets.
|
||||
*
|
||||
* A bitmap may be of infinite size (all bits are set after some point).
|
||||
* A bitmap may even be full if all bits are set.
|
||||
*
|
||||
* \note Several examples of using the bitmap API are available under the
|
||||
* doc/examples/ directory in the source tree.
|
||||
* Regression tests such as tests/hwloc/hwloc_bitmap*.c also make intensive use
|
||||
* of this API.
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** \brief
|
||||
* Set of bits represented as an opaque pointer to an internal bitmap.
|
||||
*/
|
||||
typedef struct hwloc_bitmap_s * hwloc_bitmap_t;
|
||||
/** \brief a non-modifiable ::hwloc_bitmap_t */
|
||||
typedef const struct hwloc_bitmap_s * hwloc_const_bitmap_t;
|
||||
|
||||
|
||||
/*
|
||||
* Bitmap allocation, freeing and copying.
|
||||
*/
|
||||
|
||||
/** \brief Allocate a new empty bitmap.
|
||||
*
|
||||
* \returns A valid bitmap or \c NULL.
|
||||
*
|
||||
* The bitmap should be freed by a corresponding call to
|
||||
* hwloc_bitmap_free().
|
||||
*/
|
||||
HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_alloc(void) __hwloc_attribute_malloc;
|
||||
|
||||
/** \brief Allocate a new full bitmap. */
|
||||
HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_alloc_full(void) __hwloc_attribute_malloc;
|
||||
|
||||
/** \brief Free bitmap \p bitmap.
|
||||
*
|
||||
* If \p bitmap is \c NULL, no operation is performed.
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_free(hwloc_bitmap_t bitmap);
|
||||
|
||||
/** \brief Duplicate bitmap \p bitmap by allocating a new bitmap and copying \p bitmap contents.
|
||||
*
|
||||
* If \p bitmap is \c NULL, \c NULL is returned.
|
||||
*/
|
||||
HWLOC_DECLSPEC hwloc_bitmap_t hwloc_bitmap_dup(hwloc_const_bitmap_t bitmap) __hwloc_attribute_malloc;
|
||||
|
||||
/** \brief Copy the contents of bitmap \p src into the already allocated bitmap \p dst */
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_copy(hwloc_bitmap_t dst, hwloc_const_bitmap_t src);
|
||||
|
||||
|
||||
/*
|
||||
* Bitmap/String Conversion
|
||||
*/
|
||||
|
||||
/** \brief Stringify a bitmap.
|
||||
*
|
||||
* Up to \p buflen characters may be written in buffer \p buf.
|
||||
*
|
||||
* If \p buflen is 0, \p buf may safely be \c NULL.
|
||||
*
|
||||
* \return the number of character that were actually written if not truncating,
|
||||
* or that would have been written (not including the ending \\0).
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Stringify a bitmap into a newly allocated string.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Parse a bitmap string and stores it in bitmap \p bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
|
||||
|
||||
/** \brief Stringify a bitmap in the list format.
|
||||
*
|
||||
* Lists are comma-separated indexes or ranges.
|
||||
* Ranges are dash separated indexes.
|
||||
* The last range may not have an ending indexes if the bitmap is infinitely set.
|
||||
*
|
||||
* Up to \p buflen characters may be written in buffer \p buf.
|
||||
*
|
||||
* If \p buflen is 0, \p buf may safely be \c NULL.
|
||||
*
|
||||
* \return the number of character that were actually written if not truncating,
|
||||
* or that would have been written (not including the ending \\0).
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_list_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Stringify a bitmap into a newly allocated list string.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_list_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Parse a list string and stores it in bitmap \p bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_list_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
|
||||
|
||||
/** \brief Stringify a bitmap in the taskset-specific format.
|
||||
*
|
||||
* The taskset command manipulates bitmap strings that contain a single
|
||||
* (possible very long) hexadecimal number starting with 0x.
|
||||
*
|
||||
* Up to \p buflen characters may be written in buffer \p buf.
|
||||
*
|
||||
* If \p buflen is 0, \p buf may safely be \c NULL.
|
||||
*
|
||||
* \return the number of character that were actually written if not truncating,
|
||||
* or that would have been written (not including the ending \\0).
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_taskset_snprintf(char * __hwloc_restrict buf, size_t buflen, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Stringify a bitmap into a newly allocated taskset-specific string.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_taskset_asprintf(char ** strp, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
/** \brief Parse a taskset-specific bitmap string and stores it in bitmap \p bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_taskset_sscanf(hwloc_bitmap_t bitmap, const char * __hwloc_restrict string);
|
||||
|
||||
|
||||
/*
|
||||
* Building bitmaps.
|
||||
*/
|
||||
|
||||
/** \brief Empty the bitmap \p bitmap */
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_zero(hwloc_bitmap_t bitmap);
|
||||
|
||||
/** \brief Fill bitmap \p bitmap with all possible indexes (even if those objects don't exist or are otherwise unavailable) */
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_fill(hwloc_bitmap_t bitmap);
|
||||
|
||||
/** \brief Empty the bitmap \p bitmap and add bit \p id */
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_only(hwloc_bitmap_t bitmap, unsigned id);
|
||||
|
||||
/** \brief Fill the bitmap \p and clear the index \p id */
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_allbut(hwloc_bitmap_t bitmap, unsigned id);
|
||||
|
||||
/** \brief Setup bitmap \p bitmap from unsigned long \p mask */
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_from_ulong(hwloc_bitmap_t bitmap, unsigned long mask);
|
||||
|
||||
/** \brief Setup bitmap \p bitmap from unsigned long \p mask used as \p i -th subset */
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_from_ith_ulong(hwloc_bitmap_t bitmap, unsigned i, unsigned long mask);
|
||||
|
||||
|
||||
/*
|
||||
* Modifying bitmaps.
|
||||
*/
|
||||
|
||||
/** \brief Add index \p id in bitmap \p bitmap */
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_set(hwloc_bitmap_t bitmap, unsigned id);
|
||||
|
||||
/** \brief Add indexes from \p begin to \p end in bitmap \p bitmap.
|
||||
*
|
||||
* If \p end is \c -1, the range is infinite.
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_set_range(hwloc_bitmap_t bitmap, unsigned begin, int end);
|
||||
|
||||
/** \brief Replace \p i -th subset of bitmap \p bitmap with unsigned long \p mask */
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_set_ith_ulong(hwloc_bitmap_t bitmap, unsigned i, unsigned long mask);
|
||||
|
||||
/** \brief Remove index \p id from bitmap \p bitmap */
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_clr(hwloc_bitmap_t bitmap, unsigned id);
|
||||
|
||||
/** \brief Remove indexes from \p begin to \p end in bitmap \p bitmap.
|
||||
*
|
||||
* If \p end is \c -1, the range is infinite.
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_clr_range(hwloc_bitmap_t bitmap, unsigned begin, int end);
|
||||
|
||||
/** \brief Keep a single index among those set in bitmap \p bitmap
|
||||
*
|
||||
* May be useful before binding so that the process does not
|
||||
* have a chance of migrating between multiple logical CPUs
|
||||
* in the original mask.
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_singlify(hwloc_bitmap_t bitmap);
|
||||
|
||||
|
||||
/*
|
||||
* Consulting bitmaps.
|
||||
*/
|
||||
|
||||
/** \brief Convert the beginning part of bitmap \p bitmap into unsigned long \p mask */
|
||||
HWLOC_DECLSPEC unsigned long hwloc_bitmap_to_ulong(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Convert the \p i -th subset of bitmap \p bitmap into unsigned long mask */
|
||||
HWLOC_DECLSPEC unsigned long hwloc_bitmap_to_ith_ulong(hwloc_const_bitmap_t bitmap, unsigned i) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Test whether index \p id is part of bitmap \p bitmap */
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_isset(hwloc_const_bitmap_t bitmap, unsigned id) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Test whether bitmap \p bitmap is empty */
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_iszero(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Test whether bitmap \p bitmap is completely full
|
||||
*
|
||||
* \note A full bitmap is always infinitely set.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_isfull(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Compute the first index (least significant bit) in bitmap \p bitmap
|
||||
*
|
||||
* \return -1 if no index is set in \p bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_first(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Compute the next index in bitmap \p bitmap which is after index \p prev
|
||||
*
|
||||
* If \p prev is -1, the first index is returned.
|
||||
*
|
||||
* \return -1 if no index with higher index is set in \p bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_next(hwloc_const_bitmap_t bitmap, int prev) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Compute the last index (most significant bit) in bitmap \p bitmap
|
||||
*
|
||||
* \return -1 if no index is set in \p bitmap, or if \p bitmap is infinitely set.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_last(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Compute the "weight" of bitmap \p bitmap (i.e., number of
|
||||
* indexes that are in the bitmap).
|
||||
*
|
||||
* \return the number of indexes that are in the bitmap.
|
||||
*
|
||||
* \return -1 if \p bitmap is infinitely set.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_weight(hwloc_const_bitmap_t bitmap) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Loop macro iterating on bitmap \p bitmap
|
||||
*
|
||||
* The loop must start with hwloc_bitmap_foreach_begin() and end
|
||||
* with hwloc_bitmap_foreach_end() followed by a terminating ';'.
|
||||
*
|
||||
* \p index is the loop variable; it should be an unsigned int. The
|
||||
* first iteration will set \p index to the lowest index in the bitmap.
|
||||
* Successive iterations will iterate through, in order, all remaining
|
||||
* indexes set in the bitmap. To be specific: each iteration will return a
|
||||
* value for \p index such that hwloc_bitmap_isset(bitmap, index) is true.
|
||||
*
|
||||
* The assert prevents the loop from being infinite if the bitmap is infinitely set.
|
||||
*
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define hwloc_bitmap_foreach_begin(id, bitmap) \
|
||||
do { \
|
||||
assert(hwloc_bitmap_weight(bitmap) != -1); \
|
||||
for (id = hwloc_bitmap_first(bitmap); \
|
||||
(unsigned) id != (unsigned) -1; \
|
||||
id = hwloc_bitmap_next(bitmap, id)) {
|
||||
|
||||
/** \brief End of loop macro iterating on a bitmap.
|
||||
*
|
||||
* Needs a terminating ';'.
|
||||
*
|
||||
* \sa hwloc_bitmap_foreach_begin()
|
||||
* \hideinitializer
|
||||
*/
|
||||
#define hwloc_bitmap_foreach_end() \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Combining bitmaps.
|
||||
*/
|
||||
|
||||
/** \brief Or bitmaps \p bitmap1 and \p bitmap2 and store the result in bitmap \p res
|
||||
*
|
||||
* \p res can be the same as \p bitmap1 or \p bitmap2
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_or (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
|
||||
|
||||
/** \brief And bitmaps \p bitmap1 and \p bitmap2 and store the result in bitmap \p res
|
||||
*
|
||||
* \p res can be the same as \p bitmap1 or \p bitmap2
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_and (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
|
||||
|
||||
/** \brief And bitmap \p bitmap1 and the negation of \p bitmap2 and store the result in bitmap \p res
|
||||
*
|
||||
* \p res can be the same as \p bitmap1 or \p bitmap2
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_andnot (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
|
||||
|
||||
/** \brief Xor bitmaps \p bitmap1 and \p bitmap2 and store the result in bitmap \p res
|
||||
*
|
||||
* \p res can be the same as \p bitmap1 or \p bitmap2
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_xor (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2);
|
||||
|
||||
/** \brief Negate bitmap \p bitmap and store the result in bitmap \p res
|
||||
*
|
||||
* \p res can be the same as \p bitmap
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_bitmap_not (hwloc_bitmap_t res, hwloc_const_bitmap_t bitmap);
|
||||
|
||||
|
||||
/*
|
||||
* Comparing bitmaps.
|
||||
*/
|
||||
|
||||
/** \brief Test whether bitmaps \p bitmap1 and \p bitmap2 intersects */
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_intersects (hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Test whether bitmap \p sub_bitmap is part of bitmap \p super_bitmap.
|
||||
*
|
||||
* \note The empty bitmap is considered included in any other bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_isincluded (hwloc_const_bitmap_t sub_bitmap, hwloc_const_bitmap_t super_bitmap) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Test whether bitmap \p bitmap1 is equal to bitmap \p bitmap2 */
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_isequal (hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Compare bitmaps \p bitmap1 and \p bitmap2 using their lowest index.
|
||||
*
|
||||
* Smaller least significant bit is smaller.
|
||||
* The empty bitmap is considered higher than anything.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_compare_first(hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
|
||||
|
||||
/** \brief Compare bitmaps \p bitmap1 and \p bitmap2 in lexicographic order.
|
||||
*
|
||||
* Lexicographic comparison of bitmaps, starting for their highest indexes.
|
||||
* Compare last indexes first, then second, etc.
|
||||
* The empty bitmap is considered lower than anything.
|
||||
*
|
||||
* \note This is different from the non-existing hwloc_bitmap_compare_last()
|
||||
* which would only compare the highest index of each bitmap.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_bitmap_compare(hwloc_const_bitmap_t bitmap1, hwloc_const_bitmap_t bitmap2) __hwloc_attribute_pure;
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_BITMAP_H */
|
220
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/cuda.h
Обычный файл
220
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/cuda.h
Обычный файл
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright © 2010-2016 Inria. All rights reserved.
|
||||
* Copyright © 2010-2011 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Macros to help interaction between hwloc and the CUDA Driver API.
|
||||
*
|
||||
* Applications that use both hwloc and the CUDA Driver API may want to
|
||||
* include this file so as to get topology information for CUDA devices.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_CUDA_H
|
||||
#define HWLOC_CUDA_H
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/autogen/config.h>
|
||||
#include <hwloc/helper.h>
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
#include <hwloc/linux.h>
|
||||
#endif
|
||||
|
||||
#include <cuda.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_cuda Interoperability with the CUDA Driver API
|
||||
*
|
||||
* This interface offers ways to retrieve topology information about
|
||||
* CUDA devices when using the CUDA Driver API.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Return the domain, bus and device IDs of the CUDA device \p cudevice.
|
||||
*
|
||||
* Device \p cudevice must match the local machine.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cuda_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
CUdevice cudevice, int *domain, int *bus, int *dev)
|
||||
{
|
||||
CUresult cres;
|
||||
|
||||
#if CUDA_VERSION >= 4000
|
||||
cres = cuDeviceGetAttribute(domain, CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, cudevice);
|
||||
if (cres != CUDA_SUCCESS) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
*domain = 0;
|
||||
#endif
|
||||
cres = cuDeviceGetAttribute(bus, CU_DEVICE_ATTRIBUTE_PCI_BUS_ID, cudevice);
|
||||
if (cres != CUDA_SUCCESS) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
cres = cuDeviceGetAttribute(dev, CU_DEVICE_ATTRIBUTE_PCI_DEVICE_ID, cudevice);
|
||||
if (cres != CUDA_SUCCESS) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Get the CPU set of logical processors that are physically
|
||||
* close to device \p cudevice.
|
||||
*
|
||||
* Return the CPU set describing the locality of the CUDA device \p cudevice.
|
||||
*
|
||||
* Topology \p topology and device \p cudevice must match the local machine.
|
||||
* I/O devices detection and the CUDA component are not needed in the topology.
|
||||
*
|
||||
* The function only returns the locality of the device.
|
||||
* If more information about the device is needed, OS objects should
|
||||
* be used instead, see hwloc_cuda_get_device_osdev()
|
||||
* and hwloc_cuda_get_device_osdev_by_index().
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cuda_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
CUdevice cudevice, hwloc_cpuset_t set)
|
||||
{
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
|
||||
#define HWLOC_CUDA_DEVICE_SYSFS_PATH_MAX 128
|
||||
char path[HWLOC_CUDA_DEVICE_SYSFS_PATH_MAX];
|
||||
int domainid, busid, deviceid;
|
||||
|
||||
if (hwloc_cuda_get_device_pci_ids(topology, cudevice, &domainid, &busid, &deviceid))
|
||||
return -1;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.0/local_cpus", domainid, busid, deviceid);
|
||||
if (hwloc_linux_read_path_as_cpumask(path, set) < 0
|
||||
|| hwloc_bitmap_iszero(set))
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#else
|
||||
/* Non-Linux systems simply get a full cpuset */
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc PCI device object corresponding to the
|
||||
* CUDA device \p cudevice.
|
||||
*
|
||||
* Return the PCI device object describing the CUDA device \p cudevice.
|
||||
* Return NULL if there is none.
|
||||
*
|
||||
* Topology \p topology and device \p cudevice must match the local machine.
|
||||
* I/O devices detection must be enabled in topology \p topology.
|
||||
* The CUDA component is not needed in the topology.
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_cuda_get_device_pcidev(hwloc_topology_t topology, CUdevice cudevice)
|
||||
{
|
||||
int domain, bus, dev;
|
||||
|
||||
if (hwloc_cuda_get_device_pci_ids(topology, cudevice, &domain, &bus, &dev))
|
||||
return NULL;
|
||||
|
||||
return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, 0);
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to CUDA device \p cudevice.
|
||||
*
|
||||
* Return the hwloc OS device object that describes the given
|
||||
* CUDA device \p cudevice. Return NULL if there is none.
|
||||
*
|
||||
* Topology \p topology and device \p cudevice must match the local machine.
|
||||
* I/O devices detection and the NVML component must be enabled in the topology.
|
||||
* If not, the locality of the object may still be found using
|
||||
* hwloc_cuda_get_device_cpuset().
|
||||
*
|
||||
* \note This function cannot work if PCI devices are filtered out.
|
||||
*
|
||||
* \note The corresponding hwloc PCI device may be found by looking
|
||||
* at the result parent pointer (unless PCI devices are filtered out).
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_cuda_get_device_osdev(hwloc_topology_t topology, CUdevice cudevice)
|
||||
{
|
||||
hwloc_obj_t osdev = NULL;
|
||||
int domain, bus, dev;
|
||||
|
||||
if (hwloc_cuda_get_device_pci_ids(topology, cudevice, &domain, &bus, &dev))
|
||||
return NULL;
|
||||
|
||||
osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
hwloc_obj_t pcidev = osdev->parent;
|
||||
if (strncmp(osdev->name, "cuda", 4))
|
||||
continue;
|
||||
if (pcidev
|
||||
&& pcidev->type == HWLOC_OBJ_PCI_DEVICE
|
||||
&& (int) pcidev->attr->pcidev.domain == domain
|
||||
&& (int) pcidev->attr->pcidev.bus == bus
|
||||
&& (int) pcidev->attr->pcidev.dev == dev
|
||||
&& pcidev->attr->pcidev.func == 0)
|
||||
return osdev;
|
||||
/* if PCI are filtered out, we need a info attr to match on */
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to the
|
||||
* CUDA device whose index is \p idx.
|
||||
*
|
||||
* Return the OS device object describing the CUDA device whose
|
||||
* index is \p idx. Return NULL if there is none.
|
||||
*
|
||||
* The topology \p topology does not necessarily have to match the current
|
||||
* machine. For instance the topology may be an XML import of a remote host.
|
||||
* I/O devices detection and the CUDA component must be enabled in the topology.
|
||||
*
|
||||
* \note The corresponding PCI device object can be obtained by looking
|
||||
* at the OS device parent object (unless PCI devices are filtered out).
|
||||
*
|
||||
* \note This function is identical to hwloc_cudart_get_device_osdev_by_index().
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_cuda_get_device_osdev_by_index(hwloc_topology_t topology, unsigned idx)
|
||||
{
|
||||
hwloc_obj_t osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type
|
||||
&& osdev->name
|
||||
&& !strncmp("cuda", osdev->name, 4)
|
||||
&& atoi(osdev->name + 4) == (int) idx)
|
||||
return osdev;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_CUDA_H */
|
177
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/cudart.h
Обычный файл
177
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/cudart.h
Обычный файл
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright © 2010-2017 Inria. All rights reserved.
|
||||
* Copyright © 2010-2011 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Macros to help interaction between hwloc and the CUDA Runtime API.
|
||||
*
|
||||
* Applications that use both hwloc and the CUDA Runtime API may want to
|
||||
* include this file so as to get topology information for CUDA devices.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_CUDART_H
|
||||
#define HWLOC_CUDART_H
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/autogen/config.h>
|
||||
#include <hwloc/helper.h>
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
#include <hwloc/linux.h>
|
||||
#endif
|
||||
|
||||
#include <cuda.h> /* for CUDA_VERSION */
|
||||
#include <cuda_runtime_api.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_cudart Interoperability with the CUDA Runtime API
|
||||
*
|
||||
* This interface offers ways to retrieve topology information about
|
||||
* CUDA devices when using the CUDA Runtime API.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Return the domain, bus and device IDs of the CUDA device whose index is \p idx.
|
||||
*
|
||||
* Device index \p idx must match the local machine.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cudart_get_device_pci_ids(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
int idx, int *domain, int *bus, int *dev)
|
||||
{
|
||||
cudaError_t cerr;
|
||||
struct cudaDeviceProp prop;
|
||||
|
||||
cerr = cudaGetDeviceProperties(&prop, idx);
|
||||
if (cerr) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if CUDA_VERSION >= 4000
|
||||
*domain = prop.pciDomainID;
|
||||
#else
|
||||
*domain = 0;
|
||||
#endif
|
||||
|
||||
*bus = prop.pciBusID;
|
||||
*dev = prop.pciDeviceID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Get the CPU set of logical processors that are physically
|
||||
* close to device \p idx.
|
||||
*
|
||||
* Return the CPU set describing the locality of the CUDA device
|
||||
* whose index is \p idx.
|
||||
*
|
||||
* Topology \p topology and device \p idx must match the local machine.
|
||||
* I/O devices detection and the CUDA component are not needed in the topology.
|
||||
*
|
||||
* The function only returns the locality of the device.
|
||||
* If more information about the device is needed, OS objects should
|
||||
* be used instead, see hwloc_cudart_get_device_osdev_by_index().
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cudart_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
int idx, hwloc_cpuset_t set)
|
||||
{
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
|
||||
#define HWLOC_CUDART_DEVICE_SYSFS_PATH_MAX 128
|
||||
char path[HWLOC_CUDART_DEVICE_SYSFS_PATH_MAX];
|
||||
int domain, bus, dev;
|
||||
|
||||
if (hwloc_cudart_get_device_pci_ids(topology, idx, &domain, &bus, &dev))
|
||||
return -1;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.0/local_cpus", (unsigned) domain, (unsigned) bus, (unsigned) dev);
|
||||
if (hwloc_linux_read_path_as_cpumask(path, set) < 0
|
||||
|| hwloc_bitmap_iszero(set))
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#else
|
||||
/* Non-Linux systems simply get a full cpuset */
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc PCI device object corresponding to the
|
||||
* CUDA device whose index is \p idx.
|
||||
*
|
||||
* Return the PCI device object describing the CUDA device whose
|
||||
* index is \p idx. Return NULL if there is none.
|
||||
*
|
||||
* Topology \p topology and device \p idx must match the local machine.
|
||||
* I/O devices detection must be enabled in topology \p topology.
|
||||
* The CUDA component is not needed in the topology.
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_cudart_get_device_pcidev(hwloc_topology_t topology, int idx)
|
||||
{
|
||||
int domain, bus, dev;
|
||||
|
||||
if (hwloc_cudart_get_device_pci_ids(topology, idx, &domain, &bus, &dev))
|
||||
return NULL;
|
||||
|
||||
return hwloc_get_pcidev_by_busid(topology, domain, bus, dev, 0);
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to the
|
||||
* CUDA device whose index is \p idx.
|
||||
*
|
||||
* Return the OS device object describing the CUDA device whose
|
||||
* index is \p idx. Return NULL if there is none.
|
||||
*
|
||||
* The topology \p topology does not necessarily have to match the current
|
||||
* machine. For instance the topology may be an XML import of a remote host.
|
||||
* I/O devices detection and the CUDA component must be enabled in the topology.
|
||||
* If not, the locality of the object may still be found using
|
||||
* hwloc_cudart_get_device_cpuset().
|
||||
*
|
||||
* \note The corresponding PCI device object can be obtained by looking
|
||||
* at the OS device parent object (unless PCI devices are filtered out).
|
||||
*
|
||||
* \note This function is identical to hwloc_cuda_get_device_osdev_by_index().
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_cudart_get_device_osdev_by_index(hwloc_topology_t topology, unsigned idx)
|
||||
{
|
||||
hwloc_obj_t osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type
|
||||
&& osdev->name
|
||||
&& !strncmp("cuda", osdev->name, 4)
|
||||
&& atoi(osdev->name + 4) == (int) idx)
|
||||
return osdev;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_CUDART_H */
|
216
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/deprecated.h
Обычный файл
216
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/deprecated.h
Обычный файл
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the inline code of functions declared in hwloc.h
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_DEPRECATED_H
|
||||
#define HWLOC_DEPRECATED_H
|
||||
|
||||
#ifndef HWLOC_H
|
||||
#error Please include the main hwloc.h instead
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* backward compat with v1.10 before Socket->Package renaming */
|
||||
#define HWLOC_OBJ_SOCKET HWLOC_OBJ_PACKAGE
|
||||
/* backward compat with v1.10 before Node->NUMANode clarification */
|
||||
#define HWLOC_OBJ_NODE HWLOC_OBJ_NUMANODE
|
||||
|
||||
/** \brief Insert a misc object by parent.
|
||||
*
|
||||
* Identical to hwloc_topology_insert_misc_object().
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_topology_insert_misc_object_by_parent(hwloc_topology_t topology, hwloc_obj_t parent, const char *name) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_topology_insert_misc_object_by_parent(hwloc_topology_t topology, hwloc_obj_t parent, const char *name)
|
||||
{
|
||||
return hwloc_topology_insert_misc_object(topology, parent, name);
|
||||
}
|
||||
|
||||
/** \brief Stringify the cpuset containing a set of objects.
|
||||
*
|
||||
* If \p size is 0, \p string may safely be \c NULL.
|
||||
*
|
||||
* \return the number of character that were actually written if not truncating,
|
||||
* or that would have been written (not including the ending \\0).
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_obj_cpuset_snprintf(char *str, size_t size, size_t nobj, struct hwloc_obj * const *objs) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_obj_cpuset_snprintf(char *str, size_t size, size_t nobj, struct hwloc_obj * const *objs)
|
||||
{
|
||||
hwloc_bitmap_t set = hwloc_bitmap_alloc();
|
||||
int res;
|
||||
unsigned i;
|
||||
|
||||
hwloc_bitmap_zero(set);
|
||||
for(i=0; i<nobj; i++)
|
||||
if (objs[i]->cpuset)
|
||||
hwloc_bitmap_or(set, set, objs[i]->cpuset);
|
||||
|
||||
res = hwloc_bitmap_snprintf(str, size, set);
|
||||
hwloc_bitmap_free(set);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** \brief Return a stringified topology object type.
|
||||
*
|
||||
* Deprecated by the identical hwloc_type_name()
|
||||
*/
|
||||
static __hwloc_inline const char *
|
||||
hwloc_obj_type_string (hwloc_obj_type_t type) __hwloc_attribute_const; /* not deprecated in early 2.x releases because widely used and prototype unchanged */
|
||||
static __hwloc_inline const char *
|
||||
hwloc_obj_type_string (hwloc_obj_type_t type)
|
||||
{
|
||||
return hwloc_type_name(type);
|
||||
}
|
||||
|
||||
/** \brief Convert a type string into a type and some attributes.
|
||||
*
|
||||
* Deprecated by hwloc_type_sscanf()
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, void *typeattrp, size_t typeattrsize) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, void *typeattrp, size_t typeattrsize)
|
||||
{
|
||||
union hwloc_obj_attr_u attr;
|
||||
int err = hwloc_type_sscanf(string, typep, &attr, sizeof(attr));
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (hwloc_obj_type_is_cache(*typep)) {
|
||||
if (depthattrp)
|
||||
*depthattrp = attr.cache.depth;
|
||||
if (typeattrp && typeattrsize >= sizeof(hwloc_obj_cache_type_t))
|
||||
memcpy(typeattrp, &attr.cache.type, sizeof(hwloc_obj_cache_type_t));
|
||||
} else if (*typep == HWLOC_OBJ_GROUP) {
|
||||
if (depthattrp)
|
||||
*depthattrp = attr.group.depth;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Set the default memory binding policy of the current
|
||||
* process or thread to prefer the NUMA node(s) specified by physical \p nodeset
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_set_membind(topology, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Query the default memory binding policy and physical locality of the
|
||||
* current process or thread.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
return hwloc_get_membind(topology, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Set the default memory binding policy of the specified
|
||||
* process to prefer the NUMA node(s) specified by physical \p nodeset
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_set_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_set_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_set_proc_membind(topology, pid, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Query the default memory binding policy and physical locality of the
|
||||
* specified process.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_get_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_get_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
return hwloc_get_proc_membind(topology, pid, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Bind the already-allocated memory identified by (addr, len)
|
||||
* to the NUMA node(s) in physical \p nodeset.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_set_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_set_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_set_area_membind(topology, addr, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Query the physical NUMA node(s) and binding policy of the memory
|
||||
* identified by (\p addr, \p len ).
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_get_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_get_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
return hwloc_get_area_membind(topology, addr, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Allocate some memory on the given physical nodeset \p nodeset
|
||||
*/
|
||||
static __hwloc_inline void *
|
||||
hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_malloc __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline void *
|
||||
hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_alloc_membind(topology, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Allocate some memory on the given nodeset \p nodeset.
|
||||
*/
|
||||
static __hwloc_inline void *
|
||||
hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_malloc __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline void *
|
||||
hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_alloc_membind_policy(topology, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Convert a CPU set into a NUMA node set and handle non-NUMA cases
|
||||
*/
|
||||
static __hwloc_inline void
|
||||
hwloc_cpuset_to_nodeset_strict(hwloc_topology_t topology, hwloc_const_cpuset_t _cpuset, hwloc_nodeset_t nodeset) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline void
|
||||
hwloc_cpuset_to_nodeset_strict(hwloc_topology_t topology, hwloc_const_cpuset_t _cpuset, hwloc_nodeset_t nodeset)
|
||||
{
|
||||
hwloc_cpuset_to_nodeset(topology, _cpuset, nodeset);
|
||||
}
|
||||
|
||||
/** \brief Convert a NUMA node set into a CPU set and handle non-NUMA cases
|
||||
*/
|
||||
static __hwloc_inline void
|
||||
hwloc_cpuset_from_nodeset_strict(hwloc_topology_t topology, hwloc_cpuset_t _cpuset, hwloc_const_nodeset_t nodeset) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline void
|
||||
hwloc_cpuset_from_nodeset_strict(hwloc_topology_t topology, hwloc_cpuset_t _cpuset, hwloc_const_nodeset_t nodeset)
|
||||
{
|
||||
hwloc_cpuset_from_nodeset(topology, _cpuset, nodeset);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_DEPRECATED_H */
|
284
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/diff.h
Обычный файл
284
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/diff.h
Обычный файл
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright © 2013-2016 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Topology differences.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_DIFF_H
|
||||
#define HWLOC_DIFF_H
|
||||
|
||||
#ifndef HWLOC_H
|
||||
#error Please include the main hwloc.h instead
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#elif 0
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_diff Topology differences
|
||||
*
|
||||
* Applications that manipulate many similar topologies, for instance
|
||||
* one for each node of a homogeneous cluster, may want to compress
|
||||
* topologies to reduce the memory footprint.
|
||||
*
|
||||
* This file offers a way to manipulate the difference between topologies
|
||||
* and export/import it to/from XML.
|
||||
* Compression may therefore be achieved by storing one topology
|
||||
* entirely while the others are only described by their differences
|
||||
* with the former.
|
||||
* The actual topology can be reconstructed when actually needed by
|
||||
* applying the precomputed difference to the reference topology.
|
||||
*
|
||||
* This interface targets very similar nodes.
|
||||
* Only very simple differences between topologies are actually
|
||||
* supported, for instance a change in the memory size, the name
|
||||
* of the object, or some info attribute.
|
||||
* More complex differences such as adding or removing objects cannot
|
||||
* be represented in the difference structures and therefore return
|
||||
* errors.
|
||||
*
|
||||
* It means that there is no need to apply the difference when
|
||||
* looking at the tree organization (how many levels, how many
|
||||
* objects per level, what kind of objects, CPU and node sets, etc)
|
||||
* and when binding to objects.
|
||||
* However the difference must be applied when looking at object
|
||||
* attributes such as the name, the memory size or info attributes.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** \brief Type of one object attribute difference.
|
||||
*/
|
||||
typedef enum hwloc_topology_diff_obj_attr_type_e {
|
||||
/** \brief The object local memory is modified.
|
||||
* The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_uint64_s
|
||||
* (and the index field is ignored).
|
||||
*/
|
||||
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE,
|
||||
|
||||
/** \brief The object name is modified.
|
||||
* The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_string_s
|
||||
* (and the name field is ignored).
|
||||
*/
|
||||
|
||||
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME,
|
||||
/** \brief the value of an info attribute is modified.
|
||||
* The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_string_s.
|
||||
*/
|
||||
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO
|
||||
} hwloc_topology_diff_obj_attr_type_t;
|
||||
|
||||
/** \brief One object attribute difference.
|
||||
*/
|
||||
union hwloc_topology_diff_obj_attr_u {
|
||||
struct hwloc_topology_diff_obj_attr_generic_s {
|
||||
/* each part of the union must start with these */
|
||||
hwloc_topology_diff_obj_attr_type_t type;
|
||||
} generic;
|
||||
|
||||
/** \brief Integer attribute modification with an optional index. */
|
||||
struct hwloc_topology_diff_obj_attr_uint64_s {
|
||||
/* used for storing integer attributes */
|
||||
hwloc_topology_diff_obj_attr_type_t type;
|
||||
hwloc_uint64_t index; /* not used for SIZE */
|
||||
hwloc_uint64_t oldvalue;
|
||||
hwloc_uint64_t newvalue;
|
||||
} uint64;
|
||||
|
||||
/** \brief String attribute modification with an optional name */
|
||||
struct hwloc_topology_diff_obj_attr_string_s {
|
||||
/* used for storing name and info pairs */
|
||||
hwloc_topology_diff_obj_attr_type_t type;
|
||||
char *name; /* not used for NAME */
|
||||
char *oldvalue;
|
||||
char *newvalue;
|
||||
} string;
|
||||
};
|
||||
|
||||
|
||||
/** \brief Type of one element of a difference list.
|
||||
*/
|
||||
typedef enum hwloc_topology_diff_type_e {
|
||||
/** \brief An object attribute was changed.
|
||||
* The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_obj_attr_s.
|
||||
*/
|
||||
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR,
|
||||
|
||||
/** \brief The difference is too complex,
|
||||
* it cannot be represented. The difference below
|
||||
* this object has not been checked.
|
||||
* hwloc_topology_diff_build() will return 1.
|
||||
*
|
||||
* The union is a hwloc_topology_diff_obj_attr_u::hwloc_topology_diff_too_complex_s.
|
||||
*/
|
||||
HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX
|
||||
} hwloc_topology_diff_type_t;
|
||||
|
||||
/** \brief One element of a difference list between two topologies.
|
||||
*/
|
||||
typedef union hwloc_topology_diff_u {
|
||||
struct hwloc_topology_diff_generic_s {
|
||||
/* each part of the union must start with these */
|
||||
hwloc_topology_diff_type_t type;
|
||||
union hwloc_topology_diff_u * next; /* pointer to the next element of the list, or NULL */
|
||||
} generic;
|
||||
|
||||
/* A difference in an object attribute. */
|
||||
struct hwloc_topology_diff_obj_attr_s {
|
||||
hwloc_topology_diff_type_t type; /* must be ::HWLOC_TOPOLOGY_DIFF_OBJ_ATTR */
|
||||
union hwloc_topology_diff_u * next;
|
||||
/* List of attribute differences for a single object */
|
||||
unsigned obj_depth;
|
||||
unsigned obj_index;
|
||||
union hwloc_topology_diff_obj_attr_u diff;
|
||||
} obj_attr;
|
||||
|
||||
/* A difference that is too complex. */
|
||||
struct hwloc_topology_diff_too_complex_s {
|
||||
hwloc_topology_diff_type_t type; /* must be ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX */
|
||||
union hwloc_topology_diff_u * next;
|
||||
/* Where we had to stop computing the diff in the first topology */
|
||||
unsigned obj_depth;
|
||||
unsigned obj_index;
|
||||
} too_complex;
|
||||
} * hwloc_topology_diff_t;
|
||||
|
||||
|
||||
/** \brief Compute the difference between 2 topologies.
|
||||
*
|
||||
* The difference is stored as a list of ::hwloc_topology_diff_t entries
|
||||
* starting at \p diff.
|
||||
* It is computed by doing a depth-first traversal of both topology trees
|
||||
* simultaneously.
|
||||
*
|
||||
* If the difference between 2 objects is too complex to be represented
|
||||
* (for instance if some objects have different types, or different numbers
|
||||
* of children), a special diff entry of type ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX
|
||||
* is queued.
|
||||
* The computation of the diff does not continue below these objects.
|
||||
* So each such diff entry means that the difference between two subtrees
|
||||
* could not be computed.
|
||||
*
|
||||
* \return 0 if the difference can be represented properly.
|
||||
*
|
||||
* \return 0 with \p diff pointing to NULL if there is no difference
|
||||
* between the topologies.
|
||||
*
|
||||
* \return 1 if the difference is too complex (see above). Some entries in
|
||||
* the list will be of type ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX.
|
||||
*
|
||||
* \return -1 on any other error.
|
||||
*
|
||||
* \note \p flags is currently not used. It should be 0.
|
||||
*
|
||||
* \note The output diff has to be freed with hwloc_topology_diff_destroy().
|
||||
*
|
||||
* \note The output diff can only be exported to XML or passed to
|
||||
* hwloc_topology_diff_apply() if 0 was returned, i.e. if no entry of type
|
||||
* ::HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX is listed.
|
||||
*
|
||||
* \note The output diff may be modified by removing some entries from
|
||||
* the list. The removed entries should be freed by passing them to
|
||||
* to hwloc_topology_diff_destroy() (possible as another list).
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_build(hwloc_topology_t topology, hwloc_topology_t newtopology, unsigned long flags, hwloc_topology_diff_t *diff);
|
||||
|
||||
/** \brief Flags to be given to hwloc_topology_diff_apply().
|
||||
*/
|
||||
enum hwloc_topology_diff_apply_flags_e {
|
||||
/** \brief Apply topology diff in reverse direction.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE = (1UL<<0)
|
||||
};
|
||||
|
||||
/** \brief Apply a topology diff to an existing topology.
|
||||
*
|
||||
* \p flags is an OR'ed set of ::hwloc_topology_diff_apply_flags_e.
|
||||
*
|
||||
* The new topology is modified in place. hwloc_topology_dup()
|
||||
* may be used to duplicate it before patching.
|
||||
*
|
||||
* If the difference cannot be applied entirely, all previous applied
|
||||
* elements are unapplied before returning.
|
||||
*
|
||||
* \return 0 on success.
|
||||
*
|
||||
* \return -N if applying the difference failed while trying
|
||||
* to apply the N-th part of the difference. For instance -1
|
||||
* is returned if the very first difference element could not
|
||||
* be applied.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_apply(hwloc_topology_t topology, hwloc_topology_diff_t diff, unsigned long flags);
|
||||
|
||||
/** \brief Destroy a list of topology differences.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_destroy(hwloc_topology_diff_t diff);
|
||||
|
||||
/** \brief Load a list of topology differences from a XML file.
|
||||
*
|
||||
* If not \c NULL, \p refname will be filled with the identifier
|
||||
* string of the reference topology for the difference file,
|
||||
* if any was specified in the XML file.
|
||||
* This identifier is usually the name of the other XML file
|
||||
* that contains the reference topology.
|
||||
*
|
||||
* \note the pointer returned in refname should later be freed
|
||||
* by the caller.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_load_xml(const char *xmlpath, hwloc_topology_diff_t *diff, char **refname);
|
||||
|
||||
/** \brief Export a list of topology differences to a XML file.
|
||||
*
|
||||
* If not \c NULL, \p refname defines an identifier string
|
||||
* for the reference topology which was used as a base when
|
||||
* computing this difference.
|
||||
* This identifier is usually the name of the other XML file
|
||||
* that contains the reference topology.
|
||||
* This attribute is given back when reading the diff from XML.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_export_xml(hwloc_topology_diff_t diff, const char *refname, const char *xmlpath);
|
||||
|
||||
/** \brief Load a list of topology differences from a XML buffer.
|
||||
*
|
||||
* If not \c NULL, \p refname will be filled with the identifier
|
||||
* string of the reference topology for the difference file,
|
||||
* if any was specified in the XML file.
|
||||
* This identifier is usually the name of the other XML file
|
||||
* that contains the reference topology.
|
||||
*
|
||||
* \note the pointer returned in refname should later be freed
|
||||
* by the caller.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_load_xmlbuffer(const char *xmlbuffer, int buflen, hwloc_topology_diff_t *diff, char **refname);
|
||||
|
||||
/** \brief Export a list of topology differences to a XML buffer.
|
||||
*
|
||||
* If not \c NULL, \p refname defines an identifier string
|
||||
* for the reference topology which was used as a base when
|
||||
* computing this difference.
|
||||
* This identifier is usually the name of the other XML file
|
||||
* that contains the reference topology.
|
||||
* This attribute is given back when reading the diff from XML.
|
||||
*
|
||||
* \note The XML buffer should later be freed with hwloc_free_xmlbuffer().
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_export_xmlbuffer(hwloc_topology_diff_t diff, const char *refname, char **xmlbuffer, int *buflen);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_DIFF_H */
|
223
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/distances.h
Обычный файл
223
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/distances.h
Обычный файл
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright © 2010-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Object distances.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_DISTANCES_H
|
||||
#define HWLOC_DISTANCES_H
|
||||
|
||||
#ifndef HWLOC_H
|
||||
#error Please include the main hwloc.h instead
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#elif 0
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_distances_get Retrieve distances between objects
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Matrix of distances between a set of objects.
|
||||
*
|
||||
* This matrix often contains latencies between NUMA nodes
|
||||
* (as reported in the System Locality Distance Information Table (SLIT)
|
||||
* in the ACPI specification), which may or may not be physically accurate.
|
||||
* It corresponds to the latency for accessing the memory of one node
|
||||
* from a core in another node.
|
||||
* The corresponding kind is ::HWLOC_DISTANCES_KIND_FROM_OS | ::HWLOC_DISTANCES_KIND_FROM_USER.
|
||||
*
|
||||
* The matrix may also contain bandwidths between random sets of objects,
|
||||
* possibly provided by the user, as specified in the \p kind attribute.
|
||||
*/
|
||||
struct hwloc_distances_s {
|
||||
unsigned nbobjs; /**< \brief Number of objects described by the distance matrix. */
|
||||
hwloc_obj_t *objs; /**< \brief Array of objects described by the distance matrix. */
|
||||
unsigned long kind; /**< \brief OR'ed set of ::hwloc_distances_kind_e. */
|
||||
hwloc_uint64_t *values; /**< \brief Matrix of distances between objects, stored as a one-dimension array.
|
||||
*
|
||||
* Distance from i-th to j-th object is stored in slot i*nbobjs+j.
|
||||
* The meaning of the value depends on the \p kind attribute.
|
||||
*/
|
||||
};
|
||||
|
||||
/** \brief Kinds of distance matrices.
|
||||
*
|
||||
* The \p kind attribute of struct hwloc_distances_s is a OR'ed set
|
||||
* of kinds.
|
||||
*
|
||||
* A kind of format HWLOC_DISTANCES_KIND_FROM_* specifies where the
|
||||
* distance information comes from, if known.
|
||||
*
|
||||
* A kind of format HWLOC_DISTANCES_KIND_MEANS_* specifies whether
|
||||
* values are latencies or bandwidths, if applicable.
|
||||
*/
|
||||
enum hwloc_distances_kind_e {
|
||||
/** \brief These distances were obtained from the operating system or hardware.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_KIND_FROM_OS = (1UL<<0),
|
||||
/** \brief These distances were provided by the user.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_KIND_FROM_USER = (1UL<<1),
|
||||
|
||||
/** \brief Distance values are similar to latencies between objects.
|
||||
* Values are smaller for closer objects, hence minimal on the diagonal
|
||||
* of the matrix (distance between an object and itself).
|
||||
* It could also be the number of network hops between objects, etc.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_KIND_MEANS_LATENCY = (1UL<<2),
|
||||
/** \brief Distance values are similar to bandwidths between objects.
|
||||
* Values are higher for closer objects, hence maximal on the diagonal
|
||||
* of the matrix (distance between an object and itself).
|
||||
* Such values are currently ignored for distance-based grouping.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH = (1UL<<3)
|
||||
};
|
||||
|
||||
/** \brief Retrieve distance matrices.
|
||||
*
|
||||
* Retrieve distance matrices from the topology into the \p distances array.
|
||||
*
|
||||
* \p flags is currently unused, should be \c 0.
|
||||
*
|
||||
* \p kind serves as a filter. If \c 0, all distance matrices are returned.
|
||||
* If it contains some HWLOC_DISTANCES_KIND_FROM_*, only distances whose kind
|
||||
* matches one of these are returned.
|
||||
* If it contains some HWLOC_DISTANCES_KIND_MEANS_*, only distances whose kind
|
||||
* matches one of these are returned.
|
||||
*
|
||||
* On input, \p nr points to the number of distances that may be stored in \p distances.
|
||||
* On output, \p nr points to the number of distances that were actually found,
|
||||
* even if some of them couldn't be stored in \p distances.
|
||||
* Distances that couldn't be stored are ignored, but the function still returns
|
||||
* success (\c 0). The caller may find out by comparing the value pointed by \p nr
|
||||
* before and after the function call.
|
||||
*
|
||||
* Each distance structure returned in the \p distances array should be released
|
||||
* by the caller using hwloc_distances_release().
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_distances_get(hwloc_topology_t topology,
|
||||
unsigned *nr, struct hwloc_distances_s **distances,
|
||||
unsigned long kind, unsigned long flags);
|
||||
|
||||
/** \brief Retrieve distance matrices for object at a specific depth in the topology.
|
||||
*
|
||||
* Identical to hwloc_distances_get() with the additional \p depth filter.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_distances_get_by_depth(hwloc_topology_t topology, unsigned depth,
|
||||
unsigned *nr, struct hwloc_distances_s **distances,
|
||||
unsigned long kind, unsigned long flags);
|
||||
|
||||
/** \brief Retrieve distance matrices for object of a specific type.
|
||||
*
|
||||
* Identical to hwloc_distances_get() with the additional \p type filter.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_distances_get_by_type(hwloc_topology_t topology, hwloc_obj_type_t type,
|
||||
unsigned *nr, struct hwloc_distances_s **distances,
|
||||
unsigned long kind, unsigned long flags)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, type);
|
||||
if (depth < 0) {
|
||||
*nr = 0;
|
||||
return 0;
|
||||
}
|
||||
return hwloc_distances_get_by_depth(topology, depth, nr, distances, kind, flags);
|
||||
}
|
||||
|
||||
/** \brief Release a distance structure previously returned by hwloc_distances_get(). */
|
||||
HWLOC_DECLSPEC void
|
||||
hwloc_distances_release(hwloc_topology_t topology, struct hwloc_distances_s *distances);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_distances_add Add or remove distances between objects
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Flags for adding a new distances to a topology. */
|
||||
enum hwloc_distances_flag_e {
|
||||
/** \brief Try to group objects based on the newly provided distance information.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_FLAG_GROUP = (1UL<<0),
|
||||
/** \brief If grouping, consider the distance values as inaccurate and relax the
|
||||
* comparisons during the grouping algorithms. The actual accuracy may be modified
|
||||
* through the HWLOC_GROUPING_ACCURACY environment variable (see \ref envvar).
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_FLAG_GROUP_INACCURATE = (1UL<<1)
|
||||
};
|
||||
|
||||
/** \brief Provide a distance matrix.
|
||||
*
|
||||
* Provide the matrix of distances between a set of objects given by \p nbobjs
|
||||
* and the \p objs array. \p nbobjs must be at least 2.
|
||||
* The distances are stored as a one-dimension array in \p values.
|
||||
* The distance from object i to object j is in slot i*nbobjs+j.
|
||||
*
|
||||
* \p kind specifies the kind of distance as a OR'ed set of ::hwloc_distances_kind_e.
|
||||
*
|
||||
* \p flags configures the behavior of the function using an optional OR'ed set of
|
||||
* ::hwloc_distances_flag_e.
|
||||
*
|
||||
* Objects must be of the same type. They cannot be of type Group.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_distances_add(hwloc_topology_t topology,
|
||||
unsigned nbobjs, hwloc_obj_t *objs, hwloc_uint64_t *values,
|
||||
unsigned long kind, unsigned long flags);
|
||||
|
||||
/** \brief Remove all distance matrices from a topology.
|
||||
*
|
||||
* Remove all distance matrices, either provided by the user or
|
||||
* gathered through the OS.
|
||||
*
|
||||
* If these distances were used to group objects, these additional
|
||||
*Group objects are not removed from the topology.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_distances_remove(hwloc_topology_t topology);
|
||||
|
||||
/** \brief Remove distance matrices for objects at a specific depth in the topology.
|
||||
*
|
||||
* Identical to hwloc_distances_remove() but only applies to one level of the topology.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_distances_remove_by_depth(hwloc_topology_t topology, unsigned depth);
|
||||
|
||||
/** \brief Remove distance matrices for objects of a specific type in the topology.
|
||||
*
|
||||
* Identical to hwloc_distances_remove() but only applies to one level of the topology.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_distances_remove_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, type);
|
||||
if (depth < 0)
|
||||
return 0;
|
||||
return hwloc_distances_remove_by_depth(topology, depth);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_DISTANCES_H */
|
236
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/export.h
Обычный файл
236
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/export.h
Обычный файл
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Exporting Topologies to XML or to Synthetic strings.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_EXPORT_H
|
||||
#define HWLOC_EXPORT_H
|
||||
|
||||
#ifndef HWLOC_H
|
||||
#error Please include the main hwloc.h instead
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#elif 0
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_xmlexport Exporting Topologies to XML
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Flags for exporting XML topologies.
|
||||
*
|
||||
* Flags to be given as a OR'ed set to hwloc_topology_export_xml().
|
||||
*/
|
||||
enum hwloc_topology_export_xml_flags_e {
|
||||
/** \brief Export XML that is loadable by hwloc v1.x.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1 = (1UL<<0)
|
||||
};
|
||||
|
||||
/** \brief Export the topology into an XML file.
|
||||
*
|
||||
* This file may be loaded later through hwloc_topology_set_xml().
|
||||
*
|
||||
* \p flags is a OR'ed set of ::hwloc_topology_export_xml_flags_e.
|
||||
*
|
||||
* \return -1 if a failure occured.
|
||||
*
|
||||
* \note See also hwloc_topology_set_userdata_export_callback()
|
||||
* for exporting application-specific object userdata.
|
||||
*
|
||||
* \note The topology-specific userdata pointer is ignored when exporting to XML.
|
||||
*
|
||||
* \note Only printable characters may be exported to XML string attributes.
|
||||
* Any other character, especially any non-ASCII character, will be silently
|
||||
* dropped.
|
||||
*
|
||||
* \note If \p name is "-", the XML output is sent to the standard output.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_export_xml(hwloc_topology_t topology, const char *xmlpath, unsigned long flags);
|
||||
|
||||
/** \brief Export the topology into a newly-allocated XML memory buffer.
|
||||
*
|
||||
* \p xmlbuffer is allocated by the callee and should be freed with
|
||||
* hwloc_free_xmlbuffer() later in the caller.
|
||||
*
|
||||
* This memory buffer may be loaded later through hwloc_topology_set_xmlbuffer().
|
||||
*
|
||||
* \p flags is a OR'ed set of ::hwloc_topology_export_xml_flags_e.
|
||||
*
|
||||
* \return -1 if a failure occured.
|
||||
*
|
||||
* \note See also hwloc_topology_set_userdata_export_callback()
|
||||
* for exporting application-specific object userdata.
|
||||
*
|
||||
* \note The topology-specific userdata pointer is ignored when exporting to XML.
|
||||
*
|
||||
* \note Only printable characters may be exported to XML string attributes.
|
||||
* Any other character, especially any non-ASCII character, will be silently
|
||||
* dropped.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_export_xmlbuffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen, unsigned long flags);
|
||||
|
||||
/** \brief Free a buffer allocated by hwloc_topology_export_xmlbuffer() */
|
||||
HWLOC_DECLSPEC void hwloc_free_xmlbuffer(hwloc_topology_t topology, char *xmlbuffer);
|
||||
|
||||
/** \brief Set the application-specific callback for exporting object userdata
|
||||
*
|
||||
* The object userdata pointer is not exported to XML by default because hwloc
|
||||
* does not know what it contains.
|
||||
*
|
||||
* This function lets applications set \p export_cb to a callback function
|
||||
* that converts this opaque userdata into an exportable string.
|
||||
*
|
||||
* \p export_cb is invoked during XML export for each object whose
|
||||
* \p userdata pointer is not \c NULL.
|
||||
* The callback should use hwloc_export_obj_userdata() or
|
||||
* hwloc_export_obj_userdata_base64() to actually export
|
||||
* something to XML (possibly multiple times per object).
|
||||
*
|
||||
* \p export_cb may be set to \c NULL if userdata should not be exported to XML.
|
||||
*
|
||||
* \note The topology-specific userdata pointer is ignored when exporting to XML.
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_topology_set_userdata_export_callback(hwloc_topology_t topology,
|
||||
void (*export_cb)(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj));
|
||||
|
||||
/** \brief Export some object userdata to XML
|
||||
*
|
||||
* This function may only be called from within the export() callback passed
|
||||
* to hwloc_topology_set_userdata_export_callback().
|
||||
* It may be invoked one of multiple times to export some userdata to XML.
|
||||
* The \p buffer content of length \p length is stored with optional name
|
||||
* \p name.
|
||||
*
|
||||
* When importing this XML file, the import() callback (if set) will be
|
||||
* called exactly as many times as hwloc_export_obj_userdata() was called
|
||||
* during export(). It will receive the corresponding \p name, \p buffer
|
||||
* and \p length arguments.
|
||||
*
|
||||
* \p reserved, \p topology and \p obj must be the first three parameters
|
||||
* that were given to the export callback.
|
||||
*
|
||||
* Only printable characters may be exported to XML string attributes.
|
||||
* If a non-printable character is passed in \p name or \p buffer,
|
||||
* the function returns -1 with errno set to EINVAL.
|
||||
*
|
||||
* If exporting binary data, the application should first encode into
|
||||
* printable characters only (or use hwloc_export_obj_userdata_base64()).
|
||||
* It should also take care of portability issues if the export may
|
||||
* be reimported on a different architecture.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_export_obj_userdata(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length);
|
||||
|
||||
/** \brief Encode and export some object userdata to XML
|
||||
*
|
||||
* This function is similar to hwloc_export_obj_userdata() but it encodes
|
||||
* the input buffer into printable characters before exporting.
|
||||
* On import, decoding is automatically performed before the data is given
|
||||
* to the import() callback if any.
|
||||
*
|
||||
* This function may only be called from within the export() callback passed
|
||||
* to hwloc_topology_set_userdata_export_callback().
|
||||
*
|
||||
* The function does not take care of portability issues if the export
|
||||
* may be reimported on a different architecture.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_export_obj_userdata_base64(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length);
|
||||
|
||||
/** \brief Set the application-specific callback for importing userdata
|
||||
*
|
||||
* On XML import, userdata is ignored by default because hwloc does not know
|
||||
* how to store it in memory.
|
||||
*
|
||||
* This function lets applications set \p import_cb to a callback function
|
||||
* that will get the XML-stored userdata and store it in the object as expected
|
||||
* by the application.
|
||||
*
|
||||
* \p import_cb is called during hwloc_topology_load() as many times as
|
||||
* hwloc_export_obj_userdata() was called during export. The topology
|
||||
* is not entirely setup yet. Object attributes are ready to consult,
|
||||
* but links between objects are not.
|
||||
*
|
||||
* \p import_cb may be \c NULL if userdata should be ignored during import.
|
||||
*
|
||||
* \note \p buffer contains \p length characters followed by a null byte ('\0').
|
||||
*
|
||||
* \note This function should be called before hwloc_topology_load().
|
||||
*
|
||||
* \note The topology-specific userdata pointer is ignored when importing from XML.
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_topology_set_userdata_import_callback(hwloc_topology_t topology,
|
||||
void (*import_cb)(hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length));
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
/** \defgroup hwlocality_syntheticexport Exporting Topologies to Synthetic
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Flags for exporting synthetic topologies.
|
||||
*
|
||||
* Flags to be given as a OR'ed set to hwloc_topology_export_synthetic().
|
||||
*/
|
||||
enum hwloc_topology_export_synthetic_flags_e {
|
||||
/** \brief Export extended types such as L2dcache as basic types such as Cache.
|
||||
*
|
||||
* This is required if loading the synthetic description with hwloc < 1.9.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES = (1UL<<0),
|
||||
|
||||
/** \brief Do not export level attributes.
|
||||
*
|
||||
* Ignore level attributes such as memory/cache sizes or PU indexes.
|
||||
* This is required if loading the synthetic description with hwloc < 1.10.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS = (1UL<<1)
|
||||
};
|
||||
|
||||
/** \brief Export the topology as a synthetic string.
|
||||
*
|
||||
* At most \p buflen characters will be written in \p buffer,
|
||||
* including the terminating \0.
|
||||
*
|
||||
* This exported string may be given back to hwloc_topology_set_synthetic().
|
||||
*
|
||||
* \p flags is a OR'ed set of ::hwloc_topology_export_synthetic_flags_e.
|
||||
*
|
||||
* \return The number of characters that were written,
|
||||
* not including the terminating \0.
|
||||
*
|
||||
* \return -1 if the topology could not be exported,
|
||||
* for instance if it is not symmetric.
|
||||
*
|
||||
* \note I/O and Misc children are ignored, the synthetic string only
|
||||
* describes normal children.
|
||||
*
|
||||
* \note A 1024-byte buffer should be large enough for exporting
|
||||
* topologies in the vast majority of cases.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_export_synthetic(hwloc_topology_t topology, char *buffer, size_t buflen, unsigned long flags);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_EXPORT_H */
|
135
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/gl.h
Обычный файл
135
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/gl.h
Обычный файл
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright © 2012 Blue Brain Project, EPFL. All rights reserved.
|
||||
* Copyright © 2012-2013 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Macros to help interaction between hwloc and OpenGL displays.
|
||||
*
|
||||
* Applications that use both hwloc and OpenGL may want to include
|
||||
* this file so as to get topology information for OpenGL displays.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_GL_H
|
||||
#define HWLOC_GL_H
|
||||
|
||||
#include <hwloc.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_gl Interoperability with OpenGL displays
|
||||
*
|
||||
* This interface offers ways to retrieve topology information about
|
||||
* OpenGL displays.
|
||||
*
|
||||
* Only the NVIDIA display locality information is currently available,
|
||||
* using the NV-CONTROL X11 extension and the NVCtrl library.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to the
|
||||
* OpenGL display given by port and device index.
|
||||
*
|
||||
* Return the OS device object describing the OpenGL display
|
||||
* whose port (server) is \p port and device (screen) is \p device.
|
||||
* Return NULL if there is none.
|
||||
*
|
||||
* The topology \p topology does not necessarily have to match the current
|
||||
* machine. For instance the topology may be an XML import of a remote host.
|
||||
* I/O devices detection and the GL component must be enabled in the topology.
|
||||
*
|
||||
* \note The corresponding PCI device object can be obtained by looking
|
||||
* at the OS device parent object (unless PCI devices are filtered out).
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_gl_get_display_osdev_by_port_device(hwloc_topology_t topology,
|
||||
unsigned port, unsigned device)
|
||||
{
|
||||
unsigned x = (unsigned) -1, y = (unsigned) -1;
|
||||
hwloc_obj_t osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
if (HWLOC_OBJ_OSDEV_GPU == osdev->attr->osdev.type
|
||||
&& osdev->name
|
||||
&& sscanf(osdev->name, ":%u.%u", &x, &y) == 2
|
||||
&& port == x && device == y)
|
||||
return osdev;
|
||||
}
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to the
|
||||
* OpenGL display given by name.
|
||||
*
|
||||
* Return the OS device object describing the OpenGL display
|
||||
* whose name is \p name, built as ":port.device" such as ":0.0" .
|
||||
* Return NULL if there is none.
|
||||
*
|
||||
* The topology \p topology does not necessarily have to match the current
|
||||
* machine. For instance the topology may be an XML import of a remote host.
|
||||
* I/O devices detection and the GL component must be enabled in the topology.
|
||||
*
|
||||
* \note The corresponding PCI device object can be obtained by looking
|
||||
* at the OS device parent object (unless PCI devices are filtered out).
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_gl_get_display_osdev_by_name(hwloc_topology_t topology,
|
||||
const char *name)
|
||||
{
|
||||
hwloc_obj_t osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
if (HWLOC_OBJ_OSDEV_GPU == osdev->attr->osdev.type
|
||||
&& osdev->name
|
||||
&& !strcmp(name, osdev->name))
|
||||
return osdev;
|
||||
}
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** \brief Get the OpenGL display port and device corresponding
|
||||
* to the given hwloc OS object.
|
||||
*
|
||||
* Return the OpenGL display port (server) in \p port and device (screen)
|
||||
* in \p screen that correspond to the given hwloc OS device object.
|
||||
* Return \c -1 if there is none.
|
||||
*
|
||||
* The topology \p topology does not necessarily have to match the current
|
||||
* machine. For instance the topology may be an XML import of a remote host.
|
||||
* I/O devices detection and the GL component must be enabled in the topology.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_gl_get_display_by_osdev(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
hwloc_obj_t osdev,
|
||||
unsigned *port, unsigned *device)
|
||||
{
|
||||
unsigned x = -1, y = -1;
|
||||
if (HWLOC_OBJ_OSDEV_GPU == osdev->attr->osdev.type
|
||||
&& sscanf(osdev->name, ":%u.%u", &x, &y) == 2) {
|
||||
*port = x;
|
||||
*device = y;
|
||||
return 0;
|
||||
}
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_GL_H */
|
||||
|
125
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/glibc-sched.h
Обычный файл
125
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/glibc-sched.h
Обычный файл
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2013 inria. All rights reserved.
|
||||
* Copyright © 2009-2011 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Macros to help interaction between hwloc and glibc scheduling routines.
|
||||
*
|
||||
* Applications that use both hwloc and glibc scheduling routines such as
|
||||
* sched_getaffinity() or pthread_attr_setaffinity_np() may want to include
|
||||
* this file so as to ease conversion between their respective types.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_GLIBC_SCHED_H
|
||||
#define HWLOC_GLIBC_SCHED_H
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/helper.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if !defined _GNU_SOURCE || !defined _SCHED_H || (!defined CPU_SETSIZE && !defined sched_priority)
|
||||
#error Please make sure to include sched.h before including glibc-sched.h, and define _GNU_SOURCE before any inclusion of sched.h
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HWLOC_HAVE_CPU_SET
|
||||
|
||||
|
||||
/** \defgroup hwlocality_glibc_sched Interoperability with glibc sched affinity
|
||||
*
|
||||
* This interface offers ways to convert between hwloc cpusets and glibc cpusets
|
||||
* such as those manipulated by sched_getaffinity() or pthread_attr_setaffinity_np().
|
||||
*
|
||||
* \note Topology \p topology must match the current machine.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** \brief Convert hwloc CPU set \p toposet into glibc sched affinity CPU set \p schedset
|
||||
*
|
||||
* This function may be used before calling sched_setaffinity or any other function
|
||||
* that takes a cpu_set_t as input parameter.
|
||||
*
|
||||
* \p schedsetsize should be sizeof(cpu_set_t) unless \p schedset was dynamically allocated with CPU_ALLOC
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cpuset_to_glibc_sched_affinity(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_cpuset_t hwlocset,
|
||||
cpu_set_t *schedset, size_t schedsetsize)
|
||||
{
|
||||
#ifdef CPU_ZERO_S
|
||||
unsigned cpu;
|
||||
CPU_ZERO_S(schedsetsize, schedset);
|
||||
hwloc_bitmap_foreach_begin(cpu, hwlocset)
|
||||
CPU_SET_S(cpu, schedsetsize, schedset);
|
||||
hwloc_bitmap_foreach_end();
|
||||
#else /* !CPU_ZERO_S */
|
||||
unsigned cpu;
|
||||
CPU_ZERO(schedset);
|
||||
assert(schedsetsize == sizeof(cpu_set_t));
|
||||
hwloc_bitmap_foreach_begin(cpu, hwlocset)
|
||||
CPU_SET(cpu, schedset);
|
||||
hwloc_bitmap_foreach_end();
|
||||
#endif /* !CPU_ZERO_S */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Convert glibc sched affinity CPU set \p schedset into hwloc CPU set
|
||||
*
|
||||
* This function may be used before calling sched_setaffinity or any other function
|
||||
* that takes a cpu_set_t as input parameter.
|
||||
*
|
||||
* \p schedsetsize should be sizeof(cpu_set_t) unless \p schedset was dynamically allocated with CPU_ALLOC
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_cpuset_from_glibc_sched_affinity(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_cpuset_t hwlocset,
|
||||
const cpu_set_t *schedset, size_t schedsetsize)
|
||||
{
|
||||
int cpu;
|
||||
#ifdef CPU_ZERO_S
|
||||
int count;
|
||||
#endif
|
||||
hwloc_bitmap_zero(hwlocset);
|
||||
#ifdef CPU_ZERO_S
|
||||
count = CPU_COUNT_S(schedsetsize, schedset);
|
||||
cpu = 0;
|
||||
while (count) {
|
||||
if (CPU_ISSET_S(cpu, schedsetsize, schedset)) {
|
||||
hwloc_bitmap_set(hwlocset, cpu);
|
||||
count--;
|
||||
}
|
||||
cpu++;
|
||||
}
|
||||
#else /* !CPU_ZERO_S */
|
||||
/* sched.h does not support dynamic cpu_set_t (introduced in glibc 2.7),
|
||||
* assume we have a very old interface without CPU_COUNT (added in 2.6)
|
||||
*/
|
||||
assert(schedsetsize == sizeof(cpu_set_t));
|
||||
for(cpu=0; cpu<CPU_SETSIZE; cpu++)
|
||||
if (CPU_ISSET(cpu, schedset))
|
||||
hwloc_bitmap_set(hwlocset, cpu);
|
||||
#endif /* !CPU_ZERO_S */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#endif /* CPU_SET */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_GLIBC_SCHED_H */
|
1081
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/helper.h
Обычный файл
1081
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/helper.h
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
140
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/inlines.h
Обычный файл
140
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/inlines.h
Обычный файл
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the inline code of functions declared in hwloc.h
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_INLINES_H
|
||||
#define HWLOC_INLINES_H
|
||||
|
||||
#ifndef HWLOC_H
|
||||
#error Please include the main hwloc.h instead
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static __hwloc_inline int
|
||||
hwloc_get_type_or_below_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, type);
|
||||
|
||||
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
|
||||
return depth;
|
||||
|
||||
/* find the highest existing level with type order >= */
|
||||
for(depth = hwloc_get_type_depth(topology, HWLOC_OBJ_PU); ; depth--)
|
||||
if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) < 0)
|
||||
return depth+1;
|
||||
|
||||
/* Shouldn't ever happen, as there is always a SYSTEM level with lower order and known depth. */
|
||||
/* abort(); */
|
||||
}
|
||||
|
||||
static __hwloc_inline int
|
||||
hwloc_get_type_or_above_depth (hwloc_topology_t topology, hwloc_obj_type_t type)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, type);
|
||||
|
||||
if (depth != HWLOC_TYPE_DEPTH_UNKNOWN)
|
||||
return depth;
|
||||
|
||||
/* find the lowest existing level with type order <= */
|
||||
for(depth = 0; ; depth++)
|
||||
if (hwloc_compare_types(hwloc_get_depth_type(topology, depth), type) > 0)
|
||||
return depth-1;
|
||||
|
||||
/* Shouldn't ever happen, as there is always a PU level with higher order and known depth. */
|
||||
/* abort(); */
|
||||
}
|
||||
|
||||
static __hwloc_inline int
|
||||
hwloc_get_nbobjs_by_type (hwloc_topology_t topology, hwloc_obj_type_t type)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, type);
|
||||
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
|
||||
return 0;
|
||||
if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
|
||||
return -1; /* FIXME: agregate nbobjs from different levels? */
|
||||
return hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
}
|
||||
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_get_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type, unsigned idx)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, type);
|
||||
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN)
|
||||
return NULL;
|
||||
if (depth == HWLOC_TYPE_DEPTH_MULTIPLE)
|
||||
return NULL;
|
||||
return hwloc_get_obj_by_depth(topology, depth, idx);
|
||||
}
|
||||
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_get_next_obj_by_depth (hwloc_topology_t topology, unsigned depth, hwloc_obj_t prev)
|
||||
{
|
||||
if (!prev)
|
||||
return hwloc_get_obj_by_depth (topology, depth, 0);
|
||||
if (prev->depth != depth)
|
||||
return NULL;
|
||||
return prev->next_cousin;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, type);
|
||||
if (depth == HWLOC_TYPE_DEPTH_UNKNOWN || depth == HWLOC_TYPE_DEPTH_MULTIPLE)
|
||||
return NULL;
|
||||
return hwloc_get_next_obj_by_depth (topology, depth, prev);
|
||||
}
|
||||
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_get_root_obj (hwloc_topology_t topology)
|
||||
{
|
||||
return hwloc_get_obj_by_depth (topology, 0, 0);
|
||||
}
|
||||
|
||||
static __hwloc_inline const char *
|
||||
hwloc_obj_get_info_by_name(hwloc_obj_t obj, const char *name)
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<obj->infos_count; i++)
|
||||
if (!strcmp(obj->infos[i].name, name))
|
||||
return obj->infos[i].value;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static __hwloc_inline void *
|
||||
hwloc_alloc_membind_policy(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t set, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
void *p = hwloc_alloc_membind(topology, len, set, policy, flags);
|
||||
if (p)
|
||||
return p;
|
||||
hwloc_set_membind(topology, set, policy, flags);
|
||||
p = hwloc_alloc(topology, len);
|
||||
if (p && policy != HWLOC_MEMBIND_FIRSTTOUCH)
|
||||
/* Enforce the binding by touching the data */
|
||||
memset(p, 0, len);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_INLINES_H */
|
134
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/intel-mic.h
Обычный файл
134
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/intel-mic.h
Обычный файл
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright © 2013-2016 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Macros to help interaction between hwloc and Intel Xeon Phi (MIC).
|
||||
*
|
||||
* Applications that use both hwloc and Intel Xeon Phi (MIC) may want to
|
||||
* include this file so as to get topology information for MIC devices.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_INTEL_MIC_H
|
||||
#define HWLOC_INTEL_MIC_H
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/autogen/config.h>
|
||||
#include <hwloc/helper.h>
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
#include <hwloc/linux.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_intel_mic Interoperability with Intel Xeon Phi (MIC)
|
||||
*
|
||||
* This interface offers ways to retrieve topology information about
|
||||
* Intel Xeon Phi (MIC) devices.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Get the CPU set of logical processors that are physically
|
||||
* close to MIC device whose index is \p idx.
|
||||
*
|
||||
* Return the CPU set describing the locality of the MIC device whose index is \p idx.
|
||||
*
|
||||
* Topology \p topology and device index \p idx must match the local machine.
|
||||
* I/O devices detection is not needed in the topology.
|
||||
*
|
||||
* The function only returns the locality of the device.
|
||||
* If more information about the device is needed, OS objects should
|
||||
* be used instead, see hwloc_intel_mic_get_device_osdev_by_index().
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_intel_mic_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
int idx __hwloc_attribute_unused,
|
||||
hwloc_cpuset_t set)
|
||||
{
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
|
||||
#define HWLOC_INTEL_MIC_DEVICE_SYSFS_PATH_MAX 128
|
||||
char path[HWLOC_INTEL_MIC_DEVICE_SYSFS_PATH_MAX];
|
||||
DIR *sysdir = NULL;
|
||||
struct dirent *dirent;
|
||||
unsigned pcibus, pcidev, pcifunc;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(path, "/sys/class/mic/mic%d", idx);
|
||||
sysdir = opendir(path);
|
||||
if (!sysdir)
|
||||
return -1;
|
||||
|
||||
while ((dirent = readdir(sysdir)) != NULL) {
|
||||
if (sscanf(dirent->d_name, "pci_%02x:%02x.%02x", &pcibus, &pcidev, &pcifunc) == 3) {
|
||||
sprintf(path, "/sys/class/mic/mic%d/pci_%02x:%02x.%02x/local_cpus", idx, pcibus, pcidev, pcifunc);
|
||||
if (hwloc_linux_read_path_as_cpumask(path, set) < 0
|
||||
|| hwloc_bitmap_iszero(set))
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(sysdir);
|
||||
#else
|
||||
/* Non-Linux systems simply get a full cpuset */
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to the
|
||||
* MIC device for the given index.
|
||||
*
|
||||
* Return the OS device object describing the MIC device whose index is \p idx.
|
||||
* Return NULL if there is none.
|
||||
*
|
||||
* The topology \p topology does not necessarily have to match the current
|
||||
* machine. For instance the topology may be an XML import of a remote host.
|
||||
* I/O devices detection must be enabled in the topology.
|
||||
*
|
||||
* \note The corresponding PCI device object can be obtained by looking
|
||||
* at the OS device parent object.
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_intel_mic_get_device_osdev_by_index(hwloc_topology_t topology,
|
||||
unsigned idx)
|
||||
{
|
||||
hwloc_obj_t osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type
|
||||
&& osdev->name
|
||||
&& !strncmp("mic", osdev->name, 3)
|
||||
&& atoi(osdev->name + 3) == (int) idx)
|
||||
return osdev;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_INTEL_MIC_H */
|
273
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/linux-libnuma.h
Обычный файл
273
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/linux-libnuma.h
Обычный файл
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2014 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010, 2012 Université Bordeaux
|
||||
* 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 Interoperability with Linux libnuma unsigned long masks
|
||||
*
|
||||
* This interface helps converting between Linux libnuma unsigned long masks
|
||||
* and hwloc cpusets and nodesets.
|
||||
*
|
||||
* \note Topology \p topology must match the current machine.
|
||||
*
|
||||
* \note The behavior of libnuma is undefined if the kernel is not NUMA-aware.
|
||||
* (when CONFIG_NUMA is not set in the kernel configuration).
|
||||
* This helper and libnuma may thus not be strictly compatible in this case,
|
||||
* which may be detected by checking whether numa_available() returns -1.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** \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_NUMANODE);
|
||||
unsigned long outmaxnode = -1;
|
||||
hwloc_obj_t node = NULL;
|
||||
|
||||
/* 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);
|
||||
|
||||
while ((node = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, 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;
|
||||
}
|
||||
|
||||
*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_NUMANODE);
|
||||
unsigned long outmaxnode = -1;
|
||||
hwloc_obj_t node = NULL;
|
||||
|
||||
/* 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);
|
||||
|
||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, 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;
|
||||
}
|
||||
|
||||
*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_NUMANODE);
|
||||
hwloc_obj_t node = NULL;
|
||||
hwloc_bitmap_zero(cpuset);
|
||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
||||
if (node->os_index < maxnode
|
||||
&& (mask[node->os_index/sizeof(*mask)/8] & (1UL << (node->os_index % (sizeof(*mask)*8)))))
|
||||
hwloc_bitmap_or(cpuset, cpuset, node->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_NUMANODE);
|
||||
hwloc_obj_t node = NULL;
|
||||
hwloc_bitmap_zero(nodeset);
|
||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
||||
if (node->os_index < maxnode
|
||||
&& (mask[node->os_index/sizeof(*mask)/8] & (1UL << (node->os_index % (sizeof(*mask)*8)))))
|
||||
hwloc_bitmap_set(nodeset, node->os_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_linux_libnuma_bitmask Interoperability with Linux libnuma bitmask
|
||||
*
|
||||
* This interface helps converting between Linux libnuma bitmasks
|
||||
* and hwloc cpusets and nodesets.
|
||||
*
|
||||
* \note Topology \p topology must match the current machine.
|
||||
*
|
||||
* \note The behavior of libnuma is undefined if the kernel is not NUMA-aware.
|
||||
* (when CONFIG_NUMA is not set in the kernel configuration).
|
||||
* This helper and libnuma may thus not be strictly compatible in this case,
|
||||
* which may be detected by checking whether numa_available() returns -1.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** \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_cpuset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset) __hwloc_attribute_malloc;
|
||||
static __hwloc_inline struct bitmask *
|
||||
hwloc_cpuset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_cpuset_t cpuset)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
hwloc_obj_t node = NULL;
|
||||
struct bitmask *bitmask = numa_allocate_cpumask();
|
||||
if (!bitmask)
|
||||
return NULL;
|
||||
while ((node = hwloc_get_next_obj_covering_cpuset_by_depth(topology, cpuset, depth, node)) != NULL)
|
||||
if (node->memory.local_memory)
|
||||
numa_bitmask_setbit(bitmask, node->os_index);
|
||||
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_nodeset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset) __hwloc_attribute_malloc;
|
||||
static __hwloc_inline struct bitmask *
|
||||
hwloc_nodeset_to_linux_libnuma_bitmask(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
hwloc_obj_t node = NULL;
|
||||
struct bitmask *bitmask = numa_allocate_cpumask();
|
||||
if (!bitmask)
|
||||
return NULL;
|
||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
||||
if (hwloc_bitmap_isset(nodeset, node->os_index) && node->memory.local_memory)
|
||||
numa_bitmask_setbit(bitmask, node->os_index);
|
||||
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_NUMANODE);
|
||||
hwloc_obj_t node = NULL;
|
||||
hwloc_bitmap_zero(cpuset);
|
||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
||||
if (numa_bitmask_isbitset(bitmask, node->os_index))
|
||||
hwloc_bitmap_or(cpuset, cpuset, node->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_NUMANODE);
|
||||
hwloc_obj_t node = NULL;
|
||||
hwloc_bitmap_zero(nodeset);
|
||||
while ((node = hwloc_get_next_obj_by_depth(topology, depth, node)) != NULL)
|
||||
if (numa_bitmask_isbitset(bitmask, node->os_index))
|
||||
hwloc_bitmap_set(nodeset, node->os_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_LINUX_NUMA_H */
|
79
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/linux.h
Обычный файл
79
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/linux.h
Обычный файл
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2011 Université Bordeaux
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Macros to help interaction between hwloc and Linux.
|
||||
*
|
||||
* Applications that use hwloc on Linux may want to include this file
|
||||
* if using some low-level Linux features.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_LINUX_H
|
||||
#define HWLOC_LINUX_H
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_linux Linux-specific helpers
|
||||
*
|
||||
* This includes helpers for manipulating Linux kernel cpumap files, and hwloc
|
||||
* equivalents of the Linux sched_setaffinity and sched_getaffinity system calls.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Bind a thread \p tid on cpus given in cpuset \p set
|
||||
*
|
||||
* The behavior is exactly the same as the Linux sched_setaffinity system call,
|
||||
* but uses a hwloc cpuset.
|
||||
*
|
||||
* \note This is equivalent to calling hwloc_set_proc_cpubind() with
|
||||
* HWLOC_CPUBIND_THREAD as flags.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_linux_set_tid_cpubind(hwloc_topology_t topology, pid_t tid, hwloc_const_cpuset_t set);
|
||||
|
||||
/** \brief Get the current binding of thread \p tid
|
||||
*
|
||||
* The behavior is exactly the same as the Linux sched_getaffinity system call,
|
||||
* but uses a hwloc cpuset.
|
||||
*
|
||||
* \note This is equivalent to calling hwloc_get_proc_cpubind() with
|
||||
* ::HWLOC_CPUBIND_THREAD as flags.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_linux_get_tid_cpubind(hwloc_topology_t topology, pid_t tid, hwloc_cpuset_t set);
|
||||
|
||||
/** \brief Get the last physical CPU where thread \p tid ran.
|
||||
*
|
||||
* \note This is equivalent to calling hwloc_get_proc_last_cpu_location() with
|
||||
* ::HWLOC_CPUBIND_THREAD as flags.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_linux_get_tid_last_cpu_location(hwloc_topology_t topology, pid_t tid, hwloc_bitmap_t set);
|
||||
|
||||
/** \brief Convert a linux kernel cpumask file \p path into a hwloc bitmap \p set.
|
||||
*
|
||||
* Might be used when reading CPU set from sysfs attributes such as topology
|
||||
* and caches for processors, or local_cpus for devices.
|
||||
*
|
||||
* \note This function ignores the HWLOC_FSROOT environment variable.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_linux_read_path_as_cpumask(const char *path, hwloc_bitmap_t set);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_LINUX_H */
|
127
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/myriexpress.h
Обычный файл
127
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/myriexpress.h
Обычный файл
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright © 2010-2014 Inria. All rights reserved.
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Macros to help interaction between hwloc and Myrinet Express.
|
||||
*
|
||||
* Applications that use both hwloc and Myrinet Express verbs may want to
|
||||
* include this file so as to get topology information for Myrinet hardware.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_MYRIEXPRESS_H
|
||||
#define HWLOC_MYRIEXPRESS_H
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/autogen/config.h>
|
||||
|
||||
#include <myriexpress.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_myriexpress Interoperability with Myrinet Express
|
||||
*
|
||||
* This interface offers ways to retrieve topology information about
|
||||
* Myrinet Express hardware.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Get the CPU set of logical processors that are physically
|
||||
* close the MX board \p id.
|
||||
*
|
||||
* Return the CPU set describing the locality of the Myrinet Express
|
||||
* board whose index is \p id.
|
||||
*
|
||||
* Topology \p topology and device \p id must match the local machine.
|
||||
* I/O devices detection is not needed in the topology.
|
||||
*
|
||||
* The function only returns the locality of the device.
|
||||
* No additional information about the device is available.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_mx_board_get_device_cpuset(hwloc_topology_t topology,
|
||||
unsigned id, hwloc_cpuset_t set)
|
||||
{
|
||||
uint32_t in, out;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
in = id;
|
||||
if (mx_get_info(NULL, MX_NUMA_NODE, &in, sizeof(in), &out, sizeof(out)) != MX_SUCCESS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (out != (uint32_t) -1) {
|
||||
hwloc_obj_t obj = NULL;
|
||||
while ((obj = hwloc_get_next_obj_by_type(topology, HWLOC_OBJ_NUMANODE, obj)) != NULL)
|
||||
if (obj->os_index == out) {
|
||||
hwloc_bitmap_copy(set, obj->cpuset);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* fallback to the full topology cpuset */
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Get the CPU set of logical processors that are physically
|
||||
* close the MX endpoint \p endpoint.
|
||||
*
|
||||
* Return the CPU set describing the locality of the Myrinet Express
|
||||
* board that runs the MX endpoint \p endpoint.
|
||||
*
|
||||
* Topology \p topology and device \p id must match the local machine.
|
||||
* I/O devices detection is not needed in the topology.
|
||||
*
|
||||
* The function only returns the locality of the endpoint.
|
||||
* No additional information about the endpoint or device is available.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_mx_endpoint_get_device_cpuset(hwloc_topology_t topology,
|
||||
mx_endpoint_t endpoint, hwloc_cpuset_t set)
|
||||
{
|
||||
uint64_t nid;
|
||||
uint32_t nindex, eid;
|
||||
mx_endpoint_addr_t eaddr;
|
||||
|
||||
if (mx_get_endpoint_addr(endpoint, &eaddr) != MX_SUCCESS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mx_decompose_endpoint_addr(eaddr, &nid, &eid) != MX_SUCCESS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mx_nic_id_to_board_number(nid, &nindex) != MX_SUCCESS) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return hwloc_mx_board_get_device_cpuset(topology, nindex, set);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_MYRIEXPRESS_H */
|
181
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/nvml.h
Обычный файл
181
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/nvml.h
Обычный файл
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright © 2012-2016 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Macros to help interaction between hwloc and the NVIDIA Management Library.
|
||||
*
|
||||
* Applications that use both hwloc and the NVIDIA Management Library may want to
|
||||
* include this file so as to get topology information for NVML devices.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_NVML_H
|
||||
#define HWLOC_NVML_H
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/autogen/config.h>
|
||||
#include <hwloc/helper.h>
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
#include <hwloc/linux.h>
|
||||
#endif
|
||||
|
||||
#include <nvml.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_nvml Interoperability with the NVIDIA Management Library
|
||||
*
|
||||
* This interface offers ways to retrieve topology information about
|
||||
* devices managed by the NVIDIA Management Library (NVML).
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Get the CPU set of logical processors that are physically
|
||||
* close to NVML device \p device.
|
||||
*
|
||||
* Return the CPU set describing the locality of the NVML device \p device.
|
||||
*
|
||||
* Topology \p topology and device \p device must match the local machine.
|
||||
* I/O devices detection and the NVML component are not needed in the topology.
|
||||
*
|
||||
* The function only returns the locality of the device.
|
||||
* If more information about the device is needed, OS objects should
|
||||
* be used instead, see hwloc_nvml_get_device_osdev()
|
||||
* and hwloc_nvml_get_device_osdev_by_index().
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_nvml_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
nvmlDevice_t device, hwloc_cpuset_t set)
|
||||
{
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
/* If we're on Linux, use the sysfs mechanism to get the local cpus */
|
||||
#define HWLOC_NVML_DEVICE_SYSFS_PATH_MAX 128
|
||||
char path[HWLOC_NVML_DEVICE_SYSFS_PATH_MAX];
|
||||
nvmlReturn_t nvres;
|
||||
nvmlPciInfo_t pci;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
nvres = nvmlDeviceGetPciInfo(device, &pci);
|
||||
if (NVML_SUCCESS != nvres) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.0/local_cpus", pci.domain, pci.bus, pci.device);
|
||||
if (hwloc_linux_read_path_as_cpumask(path, set) < 0
|
||||
|| hwloc_bitmap_iszero(set))
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#else
|
||||
/* Non-Linux systems simply get a full cpuset */
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to the
|
||||
* NVML device whose index is \p idx.
|
||||
*
|
||||
* Return the OS device object describing the NVML device whose
|
||||
* index is \p idx. Returns NULL if there is none.
|
||||
*
|
||||
* The topology \p topology does not necessarily have to match the current
|
||||
* machine. For instance the topology may be an XML import of a remote host.
|
||||
* I/O devices detection and the NVML component must be enabled in the topology.
|
||||
*
|
||||
* \note The corresponding PCI device object can be obtained by looking
|
||||
* at the OS device parent object (unless PCI devices are filtered out).
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_nvml_get_device_osdev_by_index(hwloc_topology_t topology, unsigned idx)
|
||||
{
|
||||
hwloc_obj_t osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
if (HWLOC_OBJ_OSDEV_GPU == osdev->attr->osdev.type
|
||||
&& osdev->name
|
||||
&& !strncmp("nvml", osdev->name, 4)
|
||||
&& atoi(osdev->name + 4) == (int) idx)
|
||||
return osdev;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to NVML device \p device.
|
||||
*
|
||||
* Return the hwloc OS device object that describes the given
|
||||
* NVML device \p device. Return NULL if there is none.
|
||||
*
|
||||
* Topology \p topology and device \p device must match the local machine.
|
||||
* I/O devices detection and the NVML component must be enabled in the topology.
|
||||
* If not, the locality of the object may still be found using
|
||||
* hwloc_nvml_get_device_cpuset().
|
||||
*
|
||||
* \note The corresponding hwloc PCI device may be found by looking
|
||||
* at the result parent pointer (unless PCI devices are filtered out).
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_nvml_get_device_osdev(hwloc_topology_t topology, nvmlDevice_t device)
|
||||
{
|
||||
hwloc_obj_t osdev;
|
||||
nvmlReturn_t nvres;
|
||||
nvmlPciInfo_t pci;
|
||||
char uuid[64];
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nvres = nvmlDeviceGetPciInfo(device, &pci);
|
||||
if (NVML_SUCCESS != nvres)
|
||||
return NULL;
|
||||
|
||||
nvres = nvmlDeviceGetUUID(device, uuid, sizeof(uuid));
|
||||
if (NVML_SUCCESS != nvres)
|
||||
uuid[0] = '\0';
|
||||
|
||||
osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
hwloc_obj_t pcidev = osdev->parent;
|
||||
const char *info;
|
||||
|
||||
if (strncmp(osdev->name, "nvml", 4))
|
||||
continue;
|
||||
|
||||
if (pcidev
|
||||
&& pcidev->type == HWLOC_OBJ_PCI_DEVICE
|
||||
&& pcidev->attr->pcidev.domain == pci.domain
|
||||
&& pcidev->attr->pcidev.bus == pci.bus
|
||||
&& pcidev->attr->pcidev.dev == pci.device
|
||||
&& pcidev->attr->pcidev.func == 0)
|
||||
return osdev;
|
||||
|
||||
info = hwloc_obj_get_info_by_name(osdev, "NVIDIAUUID");
|
||||
if (info && !strcmp(info, uuid))
|
||||
return osdev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_NVML_H */
|
196
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/opencl.h
Обычный файл
196
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/opencl.h
Обычный файл
@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright © 2012-2017 Inria. All rights reserved.
|
||||
* Copyright © 2013 Université Bordeaux. All right reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Macros to help interaction between hwloc and the OpenCL interface.
|
||||
*
|
||||
* Applications that use both hwloc and OpenCL may want to
|
||||
* include this file so as to get topology information for OpenCL devices.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_OPENCL_H
|
||||
#define HWLOC_OPENCL_H
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/autogen/config.h>
|
||||
#include <hwloc/helper.h>
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
#include <hwloc/linux.h>
|
||||
#endif
|
||||
|
||||
#include <CL/cl.h>
|
||||
#include <CL/cl_ext.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_opencl Interoperability with OpenCL
|
||||
*
|
||||
* This interface offers ways to retrieve topology information about
|
||||
* OpenCL devices.
|
||||
*
|
||||
* Only the AMD OpenCL interface currently offers useful locality information
|
||||
* about its devices.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Get the CPU set of logical processors that are physically
|
||||
* close to OpenCL device \p device.
|
||||
*
|
||||
* Return the CPU set describing the locality of the OpenCL device \p device.
|
||||
*
|
||||
* Topology \p topology and device \p device must match the local machine.
|
||||
* I/O devices detection and the OpenCL component are not needed in the topology.
|
||||
*
|
||||
* The function only returns the locality of the device.
|
||||
* If more information about the device is needed, OS objects should
|
||||
* be used instead, see hwloc_opencl_get_device_osdev()
|
||||
* and hwloc_opencl_get_device_osdev_by_index().
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux with the AMD OpenCL implementation; other systems will simply
|
||||
* get a full cpuset.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_opencl_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
cl_device_id device __hwloc_attribute_unused,
|
||||
hwloc_cpuset_t set)
|
||||
{
|
||||
#if (defined HWLOC_LINUX_SYS) && (defined CL_DEVICE_TOPOLOGY_AMD)
|
||||
/* If we're on Linux + AMD OpenCL, use the AMD extension + the sysfs mechanism to get the local cpus */
|
||||
#define HWLOC_OPENCL_DEVICE_SYSFS_PATH_MAX 128
|
||||
char path[HWLOC_OPENCL_DEVICE_SYSFS_PATH_MAX];
|
||||
cl_device_topology_amd amdtopo;
|
||||
cl_int clret;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
clret = clGetDeviceInfo(device, CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
|
||||
if (CL_SUCCESS != clret) {
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
return 0;
|
||||
}
|
||||
if (CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD != amdtopo.raw.type) {
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
return 0;
|
||||
}
|
||||
|
||||
sprintf(path, "/sys/bus/pci/devices/0000:%02x:%02x.%01x/local_cpus",
|
||||
(unsigned) amdtopo.pcie.bus, (unsigned) amdtopo.pcie.device, (unsigned) amdtopo.pcie.function);
|
||||
if (hwloc_linux_read_path_as_cpumask(path, set) < 0
|
||||
|| hwloc_bitmap_iszero(set))
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#else
|
||||
/* Non-Linux + AMD OpenCL systems simply get a full cpuset */
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to the
|
||||
* OpenCL device for the given indexes.
|
||||
*
|
||||
* Return the OS device object describing the OpenCL device
|
||||
* whose platform index is \p platform_index,
|
||||
* and whose device index within this platform if \p device_index.
|
||||
* Return NULL if there is none.
|
||||
*
|
||||
* The topology \p topology does not necessarily have to match the current
|
||||
* machine. For instance the topology may be an XML import of a remote host.
|
||||
* I/O devices detection and the OpenCL component must be enabled in the topology.
|
||||
*
|
||||
* \note The corresponding PCI device object can be obtained by looking
|
||||
* at the OS device parent object (unless PCI devices are filtered out).
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_opencl_get_device_osdev_by_index(hwloc_topology_t topology,
|
||||
unsigned platform_index, unsigned device_index)
|
||||
{
|
||||
unsigned x = (unsigned) -1, y = (unsigned) -1;
|
||||
hwloc_obj_t osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
if (HWLOC_OBJ_OSDEV_COPROC == osdev->attr->osdev.type
|
||||
&& osdev->name
|
||||
&& sscanf(osdev->name, "opencl%ud%u", &x, &y) == 2
|
||||
&& platform_index == x && device_index == y)
|
||||
return osdev;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to OpenCL device \p device.
|
||||
*
|
||||
* Return the hwloc OS device object that describes the given
|
||||
* OpenCL device \p device. Return NULL if there is none.
|
||||
*
|
||||
* Topology \p topology and device \p device must match the local machine.
|
||||
* I/O devices detection and the OpenCL component must be enabled in the topology.
|
||||
* If not, the locality of the object may still be found using
|
||||
* hwloc_opencl_get_device_cpuset().
|
||||
*
|
||||
* \note This function cannot work if PCI devices are filtered out.
|
||||
*
|
||||
* \note The corresponding hwloc PCI device may be found by looking
|
||||
* at the result parent pointer (unless PCI devices are filtered out).
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_opencl_get_device_osdev(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
cl_device_id device __hwloc_attribute_unused)
|
||||
{
|
||||
#ifdef CL_DEVICE_TOPOLOGY_AMD
|
||||
hwloc_obj_t osdev;
|
||||
cl_device_topology_amd amdtopo;
|
||||
cl_int clret;
|
||||
|
||||
clret = clGetDeviceInfo(device, CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
|
||||
if (CL_SUCCESS != clret) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
if (CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD != amdtopo.raw.type) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
hwloc_obj_t pcidev = osdev->parent;
|
||||
if (strncmp(osdev->name, "opencl", 6))
|
||||
continue;
|
||||
if (pcidev
|
||||
&& pcidev->type == HWLOC_OBJ_PCI_DEVICE
|
||||
&& pcidev->attr->pcidev.domain == 0
|
||||
&& pcidev->attr->pcidev.bus == amdtopo.pcie.bus
|
||||
&& pcidev->attr->pcidev.dev == amdtopo.pcie.device
|
||||
&& pcidev->attr->pcidev.func == amdtopo.pcie.function)
|
||||
return osdev;
|
||||
/* if PCI are filtered out, we need a info attr to match on */
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_OPENCL_H */
|
150
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/openfabrics-verbs.h
Обычный файл
150
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/openfabrics-verbs.h
Обычный файл
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Macros to help interaction between hwloc and OpenFabrics
|
||||
* verbs.
|
||||
*
|
||||
* Applications that use both hwloc and OpenFabrics verbs may want to
|
||||
* include this file so as to get topology information for OpenFabrics
|
||||
* hardware (InfiniBand, etc).
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_OPENFABRICS_VERBS_H
|
||||
#define HWLOC_OPENFABRICS_VERBS_H
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/autogen/config.h>
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
#include <hwloc/linux.h>
|
||||
#endif
|
||||
|
||||
#include <infiniband/verbs.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_openfabrics Interoperability with OpenFabrics
|
||||
*
|
||||
* This interface offers ways to retrieve topology information about
|
||||
* OpenFabrics devices (InfiniBand, Omni-Path, usNIC, etc).
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Get the CPU set of logical processors that are physically
|
||||
* close to device \p ibdev.
|
||||
*
|
||||
* Return the CPU set describing the locality of the OpenFabrics
|
||||
* device \p ibdev (InfiniBand, etc).
|
||||
*
|
||||
* Topology \p topology and device \p ibdev must match the local machine.
|
||||
* I/O devices detection is not needed in the topology.
|
||||
*
|
||||
* The function only returns the locality of the device.
|
||||
* If more information about the device is needed, OS objects should
|
||||
* be used instead, see hwloc_ibv_get_device_osdev()
|
||||
* and hwloc_ibv_get_device_osdev_by_name().
|
||||
*
|
||||
* This function is currently only implemented in a meaningful way for
|
||||
* Linux; other systems will simply get a full cpuset.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_ibv_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
struct ibv_device *ibdev, hwloc_cpuset_t set)
|
||||
{
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
/* If we're on Linux, use the verbs-provided sysfs mechanism to
|
||||
get the local cpus */
|
||||
#define HWLOC_OPENFABRICS_VERBS_SYSFS_PATH_MAX 128
|
||||
char path[HWLOC_OPENFABRICS_VERBS_SYSFS_PATH_MAX];
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(path, "/sys/class/infiniband/%s/device/local_cpus",
|
||||
ibv_get_device_name(ibdev));
|
||||
if (hwloc_linux_read_path_as_cpumask(path, set) < 0
|
||||
|| hwloc_bitmap_iszero(set))
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#else
|
||||
/* Non-Linux systems simply get a full cpuset */
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to the OpenFabrics
|
||||
* device named \p ibname.
|
||||
*
|
||||
* Return the OS device object describing the OpenFabrics device
|
||||
* (InfiniBand, Omni-Path, usNIC, etc) whose name is \p ibname
|
||||
* (mlx5_0, hfi1_0, usnic_0, qib0, etc).
|
||||
* Returns NULL if there is none.
|
||||
* The name \p ibname is usually obtained from ibv_get_device_name().
|
||||
*
|
||||
* The topology \p topology does not necessarily have to match the current
|
||||
* machine. For instance the topology may be an XML import of a remote host.
|
||||
* I/O devices detection must be enabled in the topology.
|
||||
*
|
||||
* \note The corresponding PCI device object can be obtained by looking
|
||||
* at the OS device parent object.
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_ibv_get_device_osdev_by_name(hwloc_topology_t topology,
|
||||
const char *ibname)
|
||||
{
|
||||
hwloc_obj_t osdev = NULL;
|
||||
while ((osdev = hwloc_get_next_osdev(topology, osdev)) != NULL) {
|
||||
if (HWLOC_OBJ_OSDEV_OPENFABRICS == osdev->attr->osdev.type
|
||||
&& osdev->name && !strcmp(ibname, osdev->name))
|
||||
return osdev;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** \brief Get the hwloc OS device object corresponding to the OpenFabrics
|
||||
* device \p ibdev.
|
||||
*
|
||||
* Return the OS device object describing the OpenFabrics device \p ibdev
|
||||
* (InfiniBand, etc). Returns NULL if there is none.
|
||||
*
|
||||
* Topology \p topology and device \p ibdev must match the local machine.
|
||||
* I/O devices detection must be enabled in the topology.
|
||||
* If not, the locality of the object may still be found using
|
||||
* hwloc_ibv_get_device_cpuset().
|
||||
*
|
||||
* \note The corresponding PCI device object can be obtained by looking
|
||||
* at the OS device parent object.
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_ibv_get_device_osdev(hwloc_topology_t topology,
|
||||
struct ibv_device *ibdev)
|
||||
{
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
return hwloc_ibv_get_device_osdev_by_name(topology, ibv_get_device_name(ibdev));
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_OPENFABRICS_VERBS_H */
|
522
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/plugins.h
Обычный файл
522
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/plugins.h
Обычный файл
@ -0,0 +1,522 @@
|
||||
/*
|
||||
* Copyright © 2013-2016 Inria. All rights reserved.
|
||||
* Copyright © 2016 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_PLUGINS_H
|
||||
#define HWLOC_PLUGINS_H
|
||||
|
||||
/** \file
|
||||
* \brief Public interface for building hwloc plugins.
|
||||
*/
|
||||
|
||||
struct hwloc_backend;
|
||||
|
||||
#include <hwloc.h>
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
/* needed for hwloc_plugin_check_namespace() */
|
||||
#include <ltdl.h>
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_disc_components Components and Plugins: Discovery components
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Discovery component type */
|
||||
typedef enum hwloc_disc_component_type_e {
|
||||
/** \brief CPU-only discovery through the OS, or generic no-OS support.
|
||||
* \hideinitializer */
|
||||
HWLOC_DISC_COMPONENT_TYPE_CPU = (1<<0),
|
||||
|
||||
/** \brief xml or synthetic,
|
||||
* platform-specific components such as bgq.
|
||||
* Anything the discovers CPU and everything else.
|
||||
* No misc backend is expected to complement a global component.
|
||||
* \hideinitializer */
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL = (1<<1),
|
||||
|
||||
/** \brief OpenCL, Cuda, etc.
|
||||
* \hideinitializer */
|
||||
HWLOC_DISC_COMPONENT_TYPE_MISC = (1<<2)
|
||||
} hwloc_disc_component_type_t;
|
||||
|
||||
/** \brief Discovery component structure
|
||||
*
|
||||
* This is the major kind of components, taking care of the discovery.
|
||||
* They are registered by generic components, either statically-built or as plugins.
|
||||
*/
|
||||
struct hwloc_disc_component {
|
||||
/** \brief Discovery component type */
|
||||
hwloc_disc_component_type_t type;
|
||||
|
||||
/** \brief Name.
|
||||
* If this component is built as a plugin, this name does not have to match the plugin filename.
|
||||
*/
|
||||
const char *name;
|
||||
|
||||
/** \brief Component types to exclude, as an OR'ed set of ::hwloc_disc_component_type_e.
|
||||
*
|
||||
* For a GLOBAL component, this usually includes all other types (~0).
|
||||
*
|
||||
* Other components only exclude types that may bring conflicting
|
||||
* topology information. MISC components should likely not be excluded
|
||||
* since they usually bring non-primary additional information.
|
||||
*/
|
||||
unsigned excludes;
|
||||
|
||||
/** \brief Instantiate callback to create a backend from the component.
|
||||
* Parameters data1, data2, data3 are NULL except for components
|
||||
* that have special enabling routines such as hwloc_topology_set_xml(). */
|
||||
struct hwloc_backend * (*instantiate)(struct hwloc_disc_component *component, const void *data1, const void *data2, const void *data3);
|
||||
|
||||
/** \brief Component priority.
|
||||
* Used to sort topology->components, higher priority first.
|
||||
* Also used to decide between two components with the same name.
|
||||
*
|
||||
* Usual values are
|
||||
* 50 for native OS (or platform) components,
|
||||
* 45 for x86,
|
||||
* 40 for no-OS fallback,
|
||||
* 30 for global components (xml, synthetic),
|
||||
* 20 for pci,
|
||||
* 10 for other misc components (opencl etc.).
|
||||
*/
|
||||
unsigned priority;
|
||||
|
||||
/** \private Used internally to list components by priority on topology->components
|
||||
* (the component structure is usually read-only,
|
||||
* the core copies it before using this field for queueing)
|
||||
*/
|
||||
struct hwloc_disc_component * next;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_disc_backends Components and Plugins: Discovery backends
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Discovery backend structure
|
||||
*
|
||||
* A backend is the instantiation of a discovery component.
|
||||
* When a component gets enabled for a topology,
|
||||
* its instantiate() callback creates a backend.
|
||||
*
|
||||
* hwloc_backend_alloc() initializes all fields to default values
|
||||
* that the component may change (except "component" and "next")
|
||||
* before enabling the backend with hwloc_backend_enable().
|
||||
*/
|
||||
struct hwloc_backend {
|
||||
/** \private Reserved for the core, set by hwloc_backend_alloc() */
|
||||
struct hwloc_disc_component * component;
|
||||
/** \private Reserved for the core, set by hwloc_backend_enable() */
|
||||
struct hwloc_topology * topology;
|
||||
/** \private Reserved for the core. Set to 1 if forced through envvar, 0 otherwise. */
|
||||
int envvar_forced;
|
||||
/** \private Reserved for the core. Used internally to list backends topology->backends. */
|
||||
struct hwloc_backend * next;
|
||||
|
||||
/** \brief Backend flags, currently always 0. */
|
||||
unsigned long flags;
|
||||
|
||||
/** \brief Backend-specific 'is_thissystem' property.
|
||||
* Set to 0 or 1 if the backend should enforce the thissystem flag when it gets enabled.
|
||||
* Set to -1 if the backend doesn't care (default). */
|
||||
int is_thissystem;
|
||||
|
||||
/** \brief Backend private data, or NULL if none. */
|
||||
void * private_data;
|
||||
/** \brief Callback for freeing the private_data.
|
||||
* May be NULL.
|
||||
*/
|
||||
void (*disable)(struct hwloc_backend *backend);
|
||||
|
||||
/** \brief Main discovery callback.
|
||||
* returns -1 on error, either because it couldn't add its objects ot the existing topology,
|
||||
* or because of an actual discovery/gathering failure.
|
||||
* May be NULL if type is ::HWLOC_DISC_COMPONENT_TYPE_MISC. */
|
||||
int (*discover)(struct hwloc_backend *backend);
|
||||
|
||||
/** \brief Callback used by the PCI backend to retrieve the locality of a PCI object from the OS/cpu backend.
|
||||
* May be NULL. */
|
||||
int (*get_pci_busid_cpuset)(struct hwloc_backend *backend, struct hwloc_pcidev_attr_s *busid, hwloc_bitmap_t cpuset);
|
||||
};
|
||||
|
||||
/** \brief Allocate a backend structure, set good default values, initialize backend->component and topology, etc.
|
||||
* The caller will then modify whatever needed, and call hwloc_backend_enable().
|
||||
*/
|
||||
HWLOC_DECLSPEC struct hwloc_backend * hwloc_backend_alloc(struct hwloc_disc_component *component);
|
||||
|
||||
/** \brief Enable a previously allocated and setup backend. */
|
||||
HWLOC_DECLSPEC int hwloc_backend_enable(struct hwloc_topology *topology, struct hwloc_backend *backend);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_generic_components Components and Plugins: Generic components
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Generic component type */
|
||||
typedef enum hwloc_component_type_e {
|
||||
/** \brief The data field must point to a struct hwloc_disc_component. */
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
|
||||
/** \brief The data field must point to a struct hwloc_xml_component. */
|
||||
HWLOC_COMPONENT_TYPE_XML
|
||||
} hwloc_component_type_t;
|
||||
|
||||
/** \brief Generic component structure
|
||||
*
|
||||
* Generic components structure, either statically listed by configure in static-components.h
|
||||
* or dynamically loaded as a plugin.
|
||||
*/
|
||||
struct hwloc_component {
|
||||
/** \brief Component ABI version, set to ::HWLOC_COMPONENT_ABI */
|
||||
unsigned abi;
|
||||
|
||||
/** \brief Process-wide component initialization callback.
|
||||
*
|
||||
* This optional callback is called when the component is registered
|
||||
* to the hwloc core (after loading the plugin).
|
||||
*
|
||||
* When the component is built as a plugin, this callback
|
||||
* should call hwloc_check_plugin_namespace()
|
||||
* and return an negative error code on error.
|
||||
*
|
||||
* \p flags is always 0 for now.
|
||||
*
|
||||
* \return 0 on success, or a negative code on error.
|
||||
*
|
||||
* \note If the component uses ltdl for loading its own plugins,
|
||||
* it should load/unload them only in init() and finalize(),
|
||||
* to avoid race conditions with hwloc's use of ltdl.
|
||||
*/
|
||||
int (*init)(unsigned long flags);
|
||||
|
||||
/** \brief Process-wide component termination callback.
|
||||
*
|
||||
* This optional callback is called after unregistering the component
|
||||
* from the hwloc core (before unloading the plugin).
|
||||
*
|
||||
* \p flags is always 0 for now.
|
||||
*
|
||||
* \note If the component uses ltdl for loading its own plugins,
|
||||
* it should load/unload them only in init() and finalize(),
|
||||
* to avoid race conditions with hwloc's use of ltdl.
|
||||
*/
|
||||
void (*finalize)(unsigned long flags);
|
||||
|
||||
/** \brief Component type */
|
||||
hwloc_component_type_t type;
|
||||
|
||||
/** \brief Component flags, unused for now */
|
||||
unsigned long flags;
|
||||
|
||||
/** \brief Component data, pointing to a struct hwloc_disc_component or struct hwloc_xml_component. */
|
||||
void * data;
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_components_core_funcs Components and Plugins: Core functions to be used by components
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Add an object to the topology.
|
||||
*
|
||||
* It is sorted along the tree of other objects according to the inclusion of
|
||||
* cpusets, to eventually be added as a child of the smallest object including
|
||||
* this object.
|
||||
*
|
||||
* If the cpuset is empty, the type of the object (and maybe some attributes)
|
||||
* must be enough to find where to insert the object. This is especially true
|
||||
* for NUMA nodes with memory and no CPUs.
|
||||
*
|
||||
* The given object should not have children.
|
||||
*
|
||||
* This shall only be called before levels are built.
|
||||
*
|
||||
* In case of error, hwloc_report_os_error() is called.
|
||||
*
|
||||
* The caller should check whether the object type is filtered-out before calling this function.
|
||||
*
|
||||
* The topology cpuset/nodesets will be enlarged to include the object sets.
|
||||
*
|
||||
* Returns the object on success.
|
||||
* Returns NULL and frees obj on error.
|
||||
* Returns another object and frees obj if it was merged with an identical pre-existing object.
|
||||
*/
|
||||
HWLOC_DECLSPEC struct hwloc_obj *hwloc_insert_object_by_cpuset(struct hwloc_topology *topology, hwloc_obj_t obj);
|
||||
|
||||
/** \brief Type of error callbacks during object insertion */
|
||||
typedef void (*hwloc_report_error_t)(const char * msg, int line);
|
||||
/** \brief Report an insertion error from a backend */
|
||||
HWLOC_DECLSPEC void hwloc_report_os_error(const char * msg, int line);
|
||||
/** \brief Check whether insertion errors are hidden */
|
||||
HWLOC_DECLSPEC int hwloc_hide_errors(void);
|
||||
|
||||
/** \brief Add an object to the topology and specify which error callback to use.
|
||||
*
|
||||
* Aside from the error callback selection, this function is identical to hwloc_insert_object_by_cpuset()
|
||||
*/
|
||||
HWLOC_DECLSPEC struct hwloc_obj *hwloc__insert_object_by_cpuset(struct hwloc_topology *topology, hwloc_obj_t obj, hwloc_report_error_t report_error);
|
||||
|
||||
/** \brief Insert an object somewhere in the topology.
|
||||
*
|
||||
* It is added as the last child of the given parent.
|
||||
* The cpuset is completely ignored, so strange objects such as I/O devices should
|
||||
* preferably be inserted with this.
|
||||
*
|
||||
* When used for "normal" children with cpusets (when importing from XML
|
||||
* when duplicating a topology), the caller should make sure that:
|
||||
* - children are inserted in order,
|
||||
* - children cpusets do not intersect.
|
||||
*
|
||||
* The given object may have normal, I/O or Misc children, as long as they are in order as well.
|
||||
* These children must have valid parent and next_sibling pointers.
|
||||
*
|
||||
* The caller should check whether the object type is filtered-out before calling this function.
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_insert_object_by_parent(struct hwloc_topology *topology, hwloc_obj_t parent, hwloc_obj_t obj);
|
||||
|
||||
/** \brief Allocate and initialize an object of the given type and physical index */
|
||||
HWLOC_DECLSPEC hwloc_obj_t hwloc_alloc_setup_object(hwloc_topology_t topology, hwloc_obj_type_t type, signed os_index);
|
||||
|
||||
/** \brief Setup object cpusets/nodesets by OR'ing its children.
|
||||
*
|
||||
* Used when adding an object late in the topology.
|
||||
* Will update the new object by OR'ing all its new children sets.
|
||||
*
|
||||
* Used when PCI backend adds a hostbridge parent, when distances
|
||||
* add a new Group, etc.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_obj_add_children_sets(hwloc_obj_t obj);
|
||||
|
||||
/** \brief Request a reconnection of children and levels in the topology.
|
||||
*
|
||||
* May be used by backends during discovery if they need arrays or lists
|
||||
* of object within levels or children to be fully connected.
|
||||
*
|
||||
* \p flags is currently unused, must 0.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_reconnect(hwloc_topology_t topology, unsigned long flags __hwloc_attribute_unused);
|
||||
|
||||
/** \brief Make sure that plugins can lookup core symbols.
|
||||
*
|
||||
* This is a sanity check to avoid lazy-lookup failures when libhwloc
|
||||
* is loaded within a plugin, and later tries to load its own plugins.
|
||||
* This may fail (and abort the program) if libhwloc symbols are in a
|
||||
* private namespace.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return -1 if the plugin cannot be successfully loaded. The caller
|
||||
* plugin init() callback should return a negative error code as well.
|
||||
*
|
||||
* Plugins should call this function in their init() callback to avoid
|
||||
* later crashes if lazy symbol resolution is used by the upper layer that
|
||||
* loaded hwloc (e.g. OpenCL implementations using dlopen with RTLD_LAZY).
|
||||
*
|
||||
* \note The build system must define HWLOC_INSIDE_PLUGIN if and only if
|
||||
* building the caller as a plugin.
|
||||
*
|
||||
* \note This function should remain inline so plugins can call it even
|
||||
* when they cannot find libhwloc symbols.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_plugin_check_namespace(const char *pluginname __hwloc_attribute_unused, const char *symbol __hwloc_attribute_unused)
|
||||
{
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
lt_dlhandle handle;
|
||||
void *sym;
|
||||
handle = lt_dlopen(NULL);
|
||||
if (!handle)
|
||||
/* cannot check, assume things will work */
|
||||
return 0;
|
||||
sym = lt_dlsym(handle, symbol);
|
||||
lt_dlclose(handle);
|
||||
if (!sym) {
|
||||
static int verboseenv_checked = 0;
|
||||
static int verboseenv_value = 0;
|
||||
if (!verboseenv_checked) {
|
||||
const char *verboseenv = getenv("HWLOC_PLUGINS_VERBOSE");
|
||||
verboseenv_value = verboseenv ? atoi(verboseenv) : 0;
|
||||
verboseenv_checked = 1;
|
||||
}
|
||||
if (verboseenv_value)
|
||||
fprintf(stderr, "Plugin `%s' disabling itself because it cannot find the `%s' core symbol.\n",
|
||||
pluginname, symbol);
|
||||
return -1;
|
||||
}
|
||||
#endif /* HWLOC_INSIDE_PLUGIN */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_components_filtering Components and Plugins: Filtering objects
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Check whether the given PCI device classid is important.
|
||||
*
|
||||
* \return 1 if important, 0 otherwise.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_filter_check_pcidev_subtype_important(unsigned classid)
|
||||
{
|
||||
unsigned baseclass = classid >> 8;
|
||||
return (baseclass == 0x03 /* PCI_BASE_CLASS_DISPLAY */
|
||||
|| baseclass == 0x02 /* PCI_BASE_CLASS_NETWORK */
|
||||
|| baseclass == 0x01 /* PCI_BASE_CLASS_STORAGE */
|
||||
|| baseclass == 0x0b /* PCI_BASE_CLASS_PROCESSOR */
|
||||
|| classid == 0x0c04 /* PCI_CLASS_SERIAL_FIBER */
|
||||
|| classid == 0x0c06 /* PCI_CLASS_SERIAL_INFINIBAND */
|
||||
|| baseclass == 0x12 /* Processing Accelerators */);
|
||||
}
|
||||
|
||||
/** \brief Check whether the given OS device subtype is important.
|
||||
*
|
||||
* \return 1 if important, 0 otherwise.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_filter_check_osdev_subtype_important(hwloc_obj_osdev_type_t subtype)
|
||||
{
|
||||
return (subtype != HWLOC_OBJ_OSDEV_DMA);
|
||||
}
|
||||
|
||||
/** \brief Check whether a non-I/O object type should be filtered-out.
|
||||
*
|
||||
* Cannot be used for I/O objects.
|
||||
*
|
||||
* \return 1 if the object type should be kept, 0 otherwise.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_filter_check_keep_object_type(hwloc_topology_t topology, hwloc_obj_type_t type)
|
||||
{
|
||||
enum hwloc_type_filter_e filter = HWLOC_TYPE_FILTER_KEEP_NONE;
|
||||
hwloc_topology_get_type_filter(topology, type, &filter);
|
||||
assert(filter != HWLOC_TYPE_FILTER_KEEP_IMPORTANT); /* IMPORTANT only used for I/O */
|
||||
return filter == HWLOC_TYPE_FILTER_KEEP_NONE ? 0 : 1;
|
||||
}
|
||||
|
||||
/** \brief Check whether the given object should be filtered-out.
|
||||
*
|
||||
* \return 1 if the object type should be kept, 0 otherwise.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_filter_check_keep_object(hwloc_topology_t topology, hwloc_obj_t obj)
|
||||
{
|
||||
hwloc_obj_type_t type = obj->type;
|
||||
enum hwloc_type_filter_e filter = HWLOC_TYPE_FILTER_KEEP_NONE;
|
||||
hwloc_topology_get_type_filter(topology, type, &filter);
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
return 0;
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_IMPORTANT) {
|
||||
if (type == HWLOC_OBJ_PCI_DEVICE)
|
||||
return hwloc_filter_check_pcidev_subtype_important(obj->attr->pcidev.class_id);
|
||||
if (type == HWLOC_OBJ_OS_DEVICE)
|
||||
return hwloc_filter_check_osdev_subtype_important(obj->attr->osdev.type);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_components_pci_funcs Components and Plugins: PCI functions to be used by components
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Return the offset of the given capability in the PCI config space buffer
|
||||
*
|
||||
* This function requires a 256-bytes config space. Unknown/unavailable bytes should be set to 0xff.
|
||||
*/
|
||||
HWLOC_DECLSPEC unsigned hwloc_pci_find_cap(const unsigned char *config, unsigned cap);
|
||||
|
||||
/** \brief Fill linkspeed by reading the PCI config space where PCI_CAP_ID_EXP is at position offset.
|
||||
*
|
||||
* Needs 20 bytes of EXP capability block starting at offset in the config space
|
||||
* for registers up to link status.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_pci_find_linkspeed(const unsigned char *config, unsigned offset, float *linkspeed);
|
||||
|
||||
/** \brief Return the hwloc object type (PCI device or Bridge) for the given class and configuration space.
|
||||
*
|
||||
* This function requires 16 bytes of common configuration header at the beginning of config.
|
||||
*/
|
||||
HWLOC_DECLSPEC hwloc_obj_type_t hwloc_pci_check_bridge_type(unsigned device_class, const unsigned char *config);
|
||||
|
||||
/** \brief Fills the attributes of the given PCI bridge using the given PCI config space.
|
||||
*
|
||||
* This function requires 32 bytes of common configuration header at the beginning of config.
|
||||
*
|
||||
* Returns -1 and destroys /p obj if bridge fields are invalid.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_pci_setup_bridge_attr(hwloc_obj_t obj, const unsigned char *config);
|
||||
|
||||
/** \brief Insert a PCI object in the given PCI tree by looking at PCI bus IDs.
|
||||
*
|
||||
* If \p treep points to \c NULL, the new object is inserted there.
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_pci_tree_insert_by_busid(struct hwloc_obj **treep, struct hwloc_obj *obj);
|
||||
|
||||
/** \brief Add some hostbridges on top of the given tree of PCI objects and attach them to the root of the topology.
|
||||
*
|
||||
* The core will move them to their actual PCI locality using hwloc_pci_belowroot_apply_locality()
|
||||
* at the end of the discovery.
|
||||
* In the meantime, other backends will easily lookup PCI objects (for instance to attach OS devices)
|
||||
* by using hwloc_pci_belowroot_find_by_busid() or by manually looking at the topology root object
|
||||
* io_first_child pointer.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_pci_tree_attach_belowroot(struct hwloc_topology *topology, struct hwloc_obj *tree);
|
||||
|
||||
/** \brief Find the PCI object that matches the bus ID.
|
||||
*
|
||||
* To be used after a PCI backend added PCI devices with hwloc_pci_tree_attach_belowroot()
|
||||
* and before the core moves them to their actual location with hwloc_pci_belowroot_apply_locality().
|
||||
*
|
||||
* If no exactly matching object is found, return the container bridge if any, or NULL.
|
||||
*
|
||||
* On failure, it may be possible to find the PCI locality (instead of the PCI device)
|
||||
* by calling hwloc_pci_find_busid_parent().
|
||||
*
|
||||
* \note This is semantically identical to hwloc_get_pcidev_by_busid() which only works
|
||||
* after the topology is fully loaded.
|
||||
*/
|
||||
HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_belowroot_find_by_busid(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func);
|
||||
|
||||
/** \brief Find the normal parent of a PCI bus ID.
|
||||
*
|
||||
* Look at PCI affinity to find out where the given PCI bus ID should be attached.
|
||||
*
|
||||
* This function should be used to attach an I/O device directly under a normal
|
||||
* (non-I/O) object, instead of below a PCI object.
|
||||
* It is usually used by backends when hwloc_pci_belowroot_find_by_busid() failed
|
||||
* to find the hwloc object corresponding to this bus ID, for instance because
|
||||
* PCI discovery is not supported on this platform.
|
||||
*/
|
||||
HWLOC_DECLSPEC struct hwloc_obj * hwloc_pci_find_busid_parent(struct hwloc_topology *topology, unsigned domain, unsigned bus, unsigned dev, unsigned func);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* HWLOC_PLUGINS_H */
|
707
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/rename.h
Обычный файл
707
opal/mca/hwloc/hwloc2x/hwloc/include/hwloc/rename.h
Обычный файл
@ -0,0 +1,707 @@
|
||||
/*
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright © 2010-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_RENAME_H
|
||||
#define HWLOC_RENAME_H
|
||||
|
||||
#include <hwloc/autogen/config.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Only enact these defines if we're actually renaming the symbols
|
||||
(i.e., avoid trying to have no-op defines if we're *not*
|
||||
renaming). */
|
||||
|
||||
#if HWLOC_SYM_TRANSFORM
|
||||
|
||||
/* Use a preprocessor two-step in order to get the prefixing right.
|
||||
Make 2 macros: HWLOC_NAME and HWLOC_NAME_CAPS for renaming
|
||||
things. */
|
||||
|
||||
#define HWLOC_MUNGE_NAME(a, b) HWLOC_MUNGE_NAME2(a, b)
|
||||
#define HWLOC_MUNGE_NAME2(a, b) a ## b
|
||||
#define HWLOC_NAME(name) HWLOC_MUNGE_NAME(HWLOC_SYM_PREFIX, hwloc_ ## name)
|
||||
#define HWLOC_NAME_CAPS(name) HWLOC_MUNGE_NAME(HWLOC_SYM_PREFIX_CAPS, hwloc_ ## name)
|
||||
|
||||
/* Now define all the "real" names to be the prefixed names. This
|
||||
allows us to use the real names throughout the code base (i.e.,
|
||||
"hwloc_<foo>"); the preprocessor will adjust to have the prefixed
|
||||
name under the covers. */
|
||||
|
||||
/* Names from hwloc.h */
|
||||
|
||||
#define hwloc_get_api_version HWLOC_NAME(get_api_version)
|
||||
|
||||
#define hwloc_topology HWLOC_NAME(topology)
|
||||
#define hwloc_topology_t HWLOC_NAME(topology_t)
|
||||
|
||||
#define hwloc_cpuset_t HWLOC_NAME(cpuset_t)
|
||||
#define hwloc_const_cpuset_t HWLOC_NAME(const_cpuset_t)
|
||||
#define hwloc_nodeset_t HWLOC_NAME(nodeset_t)
|
||||
#define hwloc_const_nodeset_t HWLOC_NAME(const_nodeset_t)
|
||||
|
||||
#define HWLOC_OBJ_SYSTEM HWLOC_NAME_CAPS(OBJ_SYSTEM)
|
||||
#define HWLOC_OBJ_MACHINE HWLOC_NAME_CAPS(OBJ_MACHINE)
|
||||
#define HWLOC_OBJ_NUMANODE HWLOC_NAME_CAPS(OBJ_NUMANODE)
|
||||
#define HWLOC_OBJ_PACKAGE HWLOC_NAME_CAPS(OBJ_PACKAGE)
|
||||
#define HWLOC_OBJ_CORE HWLOC_NAME_CAPS(OBJ_CORE)
|
||||
#define HWLOC_OBJ_PU HWLOC_NAME_CAPS(OBJ_PU)
|
||||
#define HWLOC_OBJ_L1CACHE HWLOC_NAME_CAPS(OBJ_L1CACHE)
|
||||
#define HWLOC_OBJ_L2CACHE HWLOC_NAME_CAPS(OBJ_L2CACHE)
|
||||
#define HWLOC_OBJ_L3CACHE HWLOC_NAME_CAPS(OBJ_L3CACHE)
|
||||
#define HWLOC_OBJ_L4CACHE HWLOC_NAME_CAPS(OBJ_L4CACHE)
|
||||
#define HWLOC_OBJ_L5CACHE HWLOC_NAME_CAPS(OBJ_L5CACHE)
|
||||
#define HWLOC_OBJ_L1ICACHE HWLOC_NAME_CAPS(OBJ_L1ICACHE)
|
||||
#define HWLOC_OBJ_L2ICACHE HWLOC_NAME_CAPS(OBJ_L2ICACHE)
|
||||
#define HWLOC_OBJ_L3ICACHE HWLOC_NAME_CAPS(OBJ_L3ICACHE)
|
||||
#define HWLOC_OBJ_MISC HWLOC_NAME_CAPS(OBJ_MISC)
|
||||
#define HWLOC_OBJ_GROUP HWLOC_NAME_CAPS(OBJ_GROUP)
|
||||
#define HWLOC_OBJ_BRIDGE HWLOC_NAME_CAPS(OBJ_BRIDGE)
|
||||
#define HWLOC_OBJ_PCI_DEVICE HWLOC_NAME_CAPS(OBJ_PCI_DEVICE)
|
||||
#define HWLOC_OBJ_OS_DEVICE HWLOC_NAME_CAPS(OBJ_OS_DEVICE)
|
||||
#define HWLOC_OBJ_TYPE_MAX HWLOC_NAME_CAPS(OBJ_TYPE_MAX)
|
||||
#define hwloc_obj_type_t HWLOC_NAME(obj_type_t)
|
||||
|
||||
#define hwloc_obj_cache_type_e HWLOC_NAME(obj_cache_type_e)
|
||||
#define hwloc_obj_cache_type_t HWLOC_NAME(obj_cache_type_t)
|
||||
#define HWLOC_OBJ_CACHE_UNIFIED HWLOC_NAME_CAPS(OBJ_CACHE_UNIFIED)
|
||||
#define HWLOC_OBJ_CACHE_DATA HWLOC_NAME_CAPS(OBJ_CACHE_DATA)
|
||||
#define HWLOC_OBJ_CACHE_INSTRUCTION HWLOC_NAME_CAPS(OBJ_CACHE_INSTRUCTION)
|
||||
|
||||
#define hwloc_obj_bridge_type_e HWLOC_NAME(obj_bridge_type_e)
|
||||
#define hwloc_obj_bridge_type_t HWLOC_NAME(obj_bridge_type_t)
|
||||
#define HWLOC_OBJ_BRIDGE_HOST HWLOC_NAME_CAPS(OBJ_BRIDGE_HOST)
|
||||
#define HWLOC_OBJ_BRIDGE_PCI HWLOC_NAME_CAPS(OBJ_BRIDGE_PCI)
|
||||
|
||||
#define hwloc_obj_osdev_type_e HWLOC_NAME(obj_osdev_type_e)
|
||||
#define hwloc_obj_osdev_type_t HWLOC_NAME(obj_osdev_type_t)
|
||||
#define HWLOC_OBJ_OSDEV_BLOCK HWLOC_NAME_CAPS(OBJ_OSDEV_BLOCK)
|
||||
#define HWLOC_OBJ_OSDEV_GPU HWLOC_NAME_CAPS(OBJ_OSDEV_GPU)
|
||||
#define HWLOC_OBJ_OSDEV_NETWORK HWLOC_NAME_CAPS(OBJ_OSDEV_NETWORK)
|
||||
#define HWLOC_OBJ_OSDEV_OPENFABRICS HWLOC_NAME_CAPS(OBJ_OSDEV_OPENFABRICS)
|
||||
#define HWLOC_OBJ_OSDEV_DMA HWLOC_NAME_CAPS(OBJ_OSDEV_DMA)
|
||||
#define HWLOC_OBJ_OSDEV_COPROC HWLOC_NAME_CAPS(OBJ_OSDEV_COPROC)
|
||||
|
||||
#define hwloc_compare_types HWLOC_NAME(compare_types)
|
||||
|
||||
#define hwloc_compare_types_e HWLOC_NAME(compare_types_e)
|
||||
#define HWLOC_TYPE_UNORDERED HWLOC_NAME_CAPS(TYPE_UNORDERED)
|
||||
|
||||
#define hwloc_obj_memory_s HWLOC_NAME(obj_memory_s)
|
||||
#define hwloc_obj_memory_page_type_s HWLOC_NAME(obj_memory_page_type_s)
|
||||
|
||||
#define hwloc_obj HWLOC_NAME(obj)
|
||||
#define hwloc_obj_t HWLOC_NAME(obj_t)
|
||||
|
||||
#define hwloc_obj_info_s HWLOC_NAME(obj_info_s)
|
||||
|
||||
#define hwloc_obj_attr_u HWLOC_NAME(obj_attr_u)
|
||||
#define hwloc_cache_attr_s HWLOC_NAME(cache_attr_s)
|
||||
#define hwloc_group_attr_s HWLOC_NAME(group_attr_s)
|
||||
#define hwloc_pcidev_attr_s HWLOC_NAME(pcidev_attr_s)
|
||||
#define hwloc_bridge_attr_s HWLOC_NAME(bridge_attr_s)
|
||||
#define hwloc_osdev_attr_s HWLOC_NAME(osdev_attr_s)
|
||||
|
||||
#define hwloc_topology_init HWLOC_NAME(topology_init)
|
||||
#define hwloc_topology_load HWLOC_NAME(topology_load)
|
||||
#define hwloc_topology_destroy HWLOC_NAME(topology_destroy)
|
||||
#define hwloc_topology_dup HWLOC_NAME(topology_dup)
|
||||
#define hwloc_topology_check HWLOC_NAME(topology_check)
|
||||
|
||||
#define hwloc_topology_flags_e HWLOC_NAME(topology_flags_e)
|
||||
|
||||
#define HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM HWLOC_NAME_CAPS(TOPOLOGY_FLAG_WHOLE_SYSTEM)
|
||||
#define HWLOC_TOPOLOGY_FLAG_IS_THISSYSTEM HWLOC_NAME_CAPS(TOPOLOGY_FLAG_IS_THISSYSTEM)
|
||||
#define HWLOC_TOPOLOGY_FLAG_THISSYSTEM_ALLOWED_RESOURCES HWLOC_NAME_CAPS(TOPOLOGY_FLAG_THISSYSTEM_ALLOWED_RESOURCES)
|
||||
|
||||
#define hwloc_topology_set_pid HWLOC_NAME(topology_set_pid)
|
||||
#define hwloc_topology_set_synthetic HWLOC_NAME(topology_set_synthetic)
|
||||
#define hwloc_topology_set_xml HWLOC_NAME(topology_set_xml)
|
||||
#define hwloc_topology_set_xmlbuffer HWLOC_NAME(topology_set_xmlbuffer)
|
||||
|
||||
#define hwloc_topology_set_flags HWLOC_NAME(topology_set_flags)
|
||||
#define hwloc_topology_is_thissystem HWLOC_NAME(topology_is_thissystem)
|
||||
#define hwloc_topology_get_flags HWLOC_NAME(topology_get_flags)
|
||||
#define hwloc_topology_discovery_support HWLOC_NAME(topology_discovery_support)
|
||||
#define hwloc_topology_cpubind_support HWLOC_NAME(topology_cpubind_support)
|
||||
#define hwloc_topology_membind_support HWLOC_NAME(topology_membind_support)
|
||||
#define hwloc_topology_support HWLOC_NAME(topology_support)
|
||||
#define hwloc_topology_get_support HWLOC_NAME(topology_get_support)
|
||||
|
||||
#define hwloc_type_filter_e HWLOC_NAME(type_filter_e)
|
||||
#define HWLOC_TYPE_FILTER_KEEP_ALL HWLOC_NAME_CAPS(TYPE_FILTER_KEEP_ALL)
|
||||
#define HWLOC_TYPE_FILTER_KEEP_NONE HWLOC_NAME_CAPS(TYPE_FILTER_KEEP_NONE)
|
||||
#define HWLOC_TYPE_FILTER_KEEP_STRUCTURE HWLOC_NAME_CAPS(TYPE_FILTER_KEEP_STRUCTURE)
|
||||
#define HWLOC_TYPE_FILTER_KEEP_IMPORTANT HWLOC_NAME_CAPS(TYPE_FILTER_KEEP_IMPORTANT)
|
||||
#define hwloc_topology_set_type_filter HWLOC_NAME(topology_set_type_filter)
|
||||
#define hwloc_topology_get_type_filter HWLOC_NAME(topology_get_type_filter)
|
||||
#define hwloc_topology_set_all_types_filter HWLOC_NAME(topology_set_all_types_filter)
|
||||
#define hwloc_topology_set_cache_types_filter HWLOC_NAME(topology_set_cache_types_filter)
|
||||
#define hwloc_topology_set_icache_types_filter HWLOC_NAME(topology_set_icache_types_filter)
|
||||
#define hwloc_topology_set_io_types_filter HWLOC_NAME(topology_set_io_types_filter)
|
||||
|
||||
#define hwloc_topology_set_userdata HWLOC_NAME(topology_set_userdata)
|
||||
#define hwloc_topology_get_userdata HWLOC_NAME(topology_get_userdata)
|
||||
|
||||
#define hwloc_restrict_flags_e HWLOC_NAME(restrict_flags_e)
|
||||
#define HWLOC_RESTRICT_FLAG_REMOVE_CPULESS HWLOC_NAME_CAPS(RESTRICT_FLAG_REMOVE_CPULESS)
|
||||
#define HWLOC_RESTRICT_FLAG_ADAPT_MISC HWLOC_NAME_CAPS(RESTRICT_FLAG_ADAPT_MISC)
|
||||
#define HWLOC_RESTRICT_FLAG_ADAPT_IO HWLOC_NAME_CAPS(RESTRICT_FLAG_ADAPT_IO)
|
||||
#define hwloc_topology_restrict HWLOC_NAME(topology_restrict)
|
||||
|
||||
#define hwloc_topology_insert_misc_object HWLOC_NAME(topology_insert_misc_object)
|
||||
#define hwloc_topology_alloc_group_object HWLOC_NAME(topology_alloc_group_object)
|
||||
#define hwloc_topology_insert_group_object HWLOC_NAME(topology_insert_group_object)
|
||||
#define hwloc_obj_add_other_obj_sets HWLOC_NAME(obj_add_other_obj_sets)
|
||||
|
||||
#define hwloc_topology_get_depth HWLOC_NAME(topology_get_depth)
|
||||
#define hwloc_get_type_depth HWLOC_NAME(get_type_depth)
|
||||
|
||||
#define hwloc_get_type_depth_e HWLOC_NAME(get_type_depth_e)
|
||||
#define HWLOC_TYPE_DEPTH_UNKNOWN HWLOC_NAME_CAPS(TYPE_DEPTH_UNKNOWN)
|
||||
#define HWLOC_TYPE_DEPTH_MULTIPLE HWLOC_NAME_CAPS(TYPE_DEPTH_MULTIPLE)
|
||||
#define HWLOC_TYPE_DEPTH_BRIDGE HWLOC_NAME_CAPS(TYPE_DEPTH_BRIDGE)
|
||||
#define HWLOC_TYPE_DEPTH_PCI_DEVICE HWLOC_NAME_CAPS(TYPE_DEPTH_PCI_DEVICE)
|
||||
#define HWLOC_TYPE_DEPTH_OS_DEVICE HWLOC_NAME_CAPS(TYPE_DEPTH_OS_DEVICE)
|
||||
#define HWLOC_TYPE_DEPTH_MISC HWLOC_NAME_CAPS(TYPE_DEPTH_MISC)
|
||||
|
||||
#define hwloc_get_depth_type HWLOC_NAME(get_depth_type)
|
||||
#define hwloc_get_nbobjs_by_depth HWLOC_NAME(get_nbobjs_by_depth)
|
||||
#define hwloc_get_nbobjs_by_type HWLOC_NAME(get_nbobjs_by_type)
|
||||
|
||||
#define hwloc_get_obj_by_depth HWLOC_NAME(get_obj_by_depth )
|
||||
#define hwloc_get_obj_by_type HWLOC_NAME(get_obj_by_type )
|
||||
|
||||
#define hwloc_type_name HWLOC_NAME(type_name)
|
||||
#define hwloc_obj_type_snprintf HWLOC_NAME(obj_type_snprintf )
|
||||
#define hwloc_obj_attr_snprintf HWLOC_NAME(obj_attr_snprintf )
|
||||
#define hwloc_type_sscanf HWLOC_NAME(type_sscanf)
|
||||
#define hwloc_type_sscanf_as_depth HWLOC_NAME(type_sscanf_as_depth)
|
||||
|
||||
#define hwloc_obj_get_info_by_name HWLOC_NAME(obj_get_info_by_name)
|
||||
#define hwloc_obj_add_info HWLOC_NAME(obj_add_info)
|
||||
|
||||
#define HWLOC_CPUBIND_PROCESS HWLOC_NAME_CAPS(CPUBIND_PROCESS)
|
||||
#define HWLOC_CPUBIND_THREAD HWLOC_NAME_CAPS(CPUBIND_THREAD)
|
||||
#define HWLOC_CPUBIND_STRICT HWLOC_NAME_CAPS(CPUBIND_STRICT)
|
||||
#define HWLOC_CPUBIND_NOMEMBIND HWLOC_NAME_CAPS(CPUBIND_NOMEMBIND)
|
||||
|
||||
#define hwloc_cpubind_flags_t HWLOC_NAME(cpubind_flags_t)
|
||||
|
||||
#define hwloc_set_cpubind HWLOC_NAME(set_cpubind)
|
||||
#define hwloc_get_cpubind HWLOC_NAME(get_cpubind)
|
||||
#define hwloc_set_proc_cpubind HWLOC_NAME(set_proc_cpubind)
|
||||
#define hwloc_get_proc_cpubind HWLOC_NAME(get_proc_cpubind)
|
||||
#define hwloc_set_thread_cpubind HWLOC_NAME(set_thread_cpubind)
|
||||
#define hwloc_get_thread_cpubind HWLOC_NAME(get_thread_cpubind)
|
||||
|
||||
#define hwloc_get_last_cpu_location HWLOC_NAME(get_last_cpu_location)
|
||||
#define hwloc_get_proc_last_cpu_location HWLOC_NAME(get_proc_last_cpu_location)
|
||||
|
||||
#define HWLOC_MEMBIND_DEFAULT HWLOC_NAME_CAPS(MEMBIND_DEFAULT)
|
||||
#define HWLOC_MEMBIND_FIRSTTOUCH HWLOC_NAME_CAPS(MEMBIND_FIRSTTOUCH)
|
||||
#define HWLOC_MEMBIND_BIND HWLOC_NAME_CAPS(MEMBIND_BIND)
|
||||
#define HWLOC_MEMBIND_INTERLEAVE HWLOC_NAME_CAPS(MEMBIND_INTERLEAVE)
|
||||
#define HWLOC_MEMBIND_NEXTTOUCH HWLOC_NAME_CAPS(MEMBIND_NEXTTOUCH)
|
||||
#define HWLOC_MEMBIND_MIXED HWLOC_NAME_CAPS(MEMBIND_MIXED)
|
||||
|
||||
#define hwloc_membind_policy_t HWLOC_NAME(membind_policy_t)
|
||||
|
||||
#define HWLOC_MEMBIND_PROCESS HWLOC_NAME_CAPS(MEMBIND_PROCESS)
|
||||
#define HWLOC_MEMBIND_THREAD HWLOC_NAME_CAPS(MEMBIND_THREAD)
|
||||
#define HWLOC_MEMBIND_STRICT HWLOC_NAME_CAPS(MEMBIND_STRICT)
|
||||
#define HWLOC_MEMBIND_MIGRATE HWLOC_NAME_CAPS(MEMBIND_MIGRATE)
|
||||
#define HWLOC_MEMBIND_NOCPUBIND HWLOC_NAME_CAPS(MEMBIND_NOCPUBIND)
|
||||
#define HWLOC_MEMBIND_BYNODESET HWLOC_NAME_CAPS(MEMBIND_BYNODESET)
|
||||
|
||||
#define hwloc_membind_flags_t HWLOC_NAME(membind_flags_t)
|
||||
|
||||
#define hwloc_set_membind HWLOC_NAME(set_membind)
|
||||
#define hwloc_get_membind HWLOC_NAME(get_membind)
|
||||
#define hwloc_set_proc_membind HWLOC_NAME(set_proc_membind)
|
||||
#define hwloc_get_proc_membind HWLOC_NAME(get_proc_membind)
|
||||
#define hwloc_set_area_membind HWLOC_NAME(set_area_membind)
|
||||
#define hwloc_get_area_membind HWLOC_NAME(get_area_membind)
|
||||
#define hwloc_get_area_memlocation HWLOC_NAME(get_area_memlocation)
|
||||
#define hwloc_alloc_membind HWLOC_NAME(alloc_membind)
|
||||
#define hwloc_alloc HWLOC_NAME(alloc)
|
||||
#define hwloc_free HWLOC_NAME(free)
|
||||
|
||||
#define hwloc_get_non_io_ancestor_obj HWLOC_NAME(get_non_io_ancestor_obj)
|
||||
#define hwloc_get_next_pcidev HWLOC_NAME(get_next_pcidev)
|
||||
#define hwloc_get_pcidev_by_busid HWLOC_NAME(get_pcidev_by_busid)
|
||||
#define hwloc_get_pcidev_by_busidstring HWLOC_NAME(get_pcidev_by_busidstring)
|
||||
#define hwloc_get_next_osdev HWLOC_NAME(get_next_osdev)
|
||||
#define hwloc_get_next_bridge HWLOC_NAME(get_next_bridge)
|
||||
#define hwloc_bridge_covers_pcibus HWLOC_NAME(bridge_covers_pcibus)
|
||||
|
||||
/* hwloc/bitmap.h */
|
||||
|
||||
#define hwloc_bitmap_s HWLOC_NAME(bitmap_s)
|
||||
#define hwloc_bitmap_t HWLOC_NAME(bitmap_t)
|
||||
#define hwloc_const_bitmap_t HWLOC_NAME(const_bitmap_t)
|
||||
|
||||
#define hwloc_bitmap_alloc HWLOC_NAME(bitmap_alloc)
|
||||
#define hwloc_bitmap_alloc_full HWLOC_NAME(bitmap_alloc_full)
|
||||
#define hwloc_bitmap_free HWLOC_NAME(bitmap_free)
|
||||
#define hwloc_bitmap_dup HWLOC_NAME(bitmap_dup)
|
||||
#define hwloc_bitmap_copy HWLOC_NAME(bitmap_copy)
|
||||
#define hwloc_bitmap_snprintf HWLOC_NAME(bitmap_snprintf)
|
||||
#define hwloc_bitmap_asprintf HWLOC_NAME(bitmap_asprintf)
|
||||
#define hwloc_bitmap_sscanf HWLOC_NAME(bitmap_sscanf)
|
||||
#define hwloc_bitmap_list_snprintf HWLOC_NAME(bitmap_list_snprintf)
|
||||
#define hwloc_bitmap_list_asprintf HWLOC_NAME(bitmap_list_asprintf)
|
||||
#define hwloc_bitmap_list_sscanf HWLOC_NAME(bitmap_list_sscanf)
|
||||
#define hwloc_bitmap_taskset_snprintf HWLOC_NAME(bitmap_taskset_snprintf)
|
||||
#define hwloc_bitmap_taskset_asprintf HWLOC_NAME(bitmap_taskset_asprintf)
|
||||
#define hwloc_bitmap_taskset_sscanf HWLOC_NAME(bitmap_taskset_sscanf)
|
||||
#define hwloc_bitmap_zero HWLOC_NAME(bitmap_zero)
|
||||
#define hwloc_bitmap_fill HWLOC_NAME(bitmap_fill)
|
||||
#define hwloc_bitmap_from_ulong HWLOC_NAME(bitmap_from_ulong)
|
||||
|
||||
#define hwloc_bitmap_from_ith_ulong HWLOC_NAME(bitmap_from_ith_ulong)
|
||||
#define hwloc_bitmap_to_ulong HWLOC_NAME(bitmap_to_ulong)
|
||||
#define hwloc_bitmap_to_ith_ulong HWLOC_NAME(bitmap_to_ith_ulong)
|
||||
#define hwloc_bitmap_only HWLOC_NAME(bitmap_only)
|
||||
#define hwloc_bitmap_allbut HWLOC_NAME(bitmap_allbut)
|
||||
#define hwloc_bitmap_set HWLOC_NAME(bitmap_set)
|
||||
#define hwloc_bitmap_set_range HWLOC_NAME(bitmap_set_range)
|
||||
#define hwloc_bitmap_set_ith_ulong HWLOC_NAME(bitmap_set_ith_ulong)
|
||||
#define hwloc_bitmap_clr HWLOC_NAME(bitmap_clr)
|
||||
#define hwloc_bitmap_clr_range HWLOC_NAME(bitmap_clr_range)
|
||||
#define hwloc_bitmap_isset HWLOC_NAME(bitmap_isset)
|
||||
#define hwloc_bitmap_iszero HWLOC_NAME(bitmap_iszero)
|
||||
#define hwloc_bitmap_isfull HWLOC_NAME(bitmap_isfull)
|
||||
#define hwloc_bitmap_isequal HWLOC_NAME(bitmap_isequal)
|
||||
#define hwloc_bitmap_intersects HWLOC_NAME(bitmap_intersects)
|
||||
#define hwloc_bitmap_isincluded HWLOC_NAME(bitmap_isincluded)
|
||||
#define hwloc_bitmap_or HWLOC_NAME(bitmap_or)
|
||||
#define hwloc_bitmap_and HWLOC_NAME(bitmap_and)
|
||||
#define hwloc_bitmap_andnot HWLOC_NAME(bitmap_andnot)
|
||||
#define hwloc_bitmap_xor HWLOC_NAME(bitmap_xor)
|
||||
#define hwloc_bitmap_not HWLOC_NAME(bitmap_not)
|
||||
#define hwloc_bitmap_first HWLOC_NAME(bitmap_first)
|
||||
#define hwloc_bitmap_last HWLOC_NAME(bitmap_last)
|
||||
#define hwloc_bitmap_next HWLOC_NAME(bitmap_next)
|
||||
#define hwloc_bitmap_singlify HWLOC_NAME(bitmap_singlify)
|
||||
#define hwloc_bitmap_compare_first HWLOC_NAME(bitmap_compare_first)
|
||||
#define hwloc_bitmap_compare HWLOC_NAME(bitmap_compare)
|
||||
#define hwloc_bitmap_weight HWLOC_NAME(bitmap_weight)
|
||||
|
||||
/* hwloc/helper.h */
|
||||
|
||||
#define hwloc_get_type_or_below_depth HWLOC_NAME(get_type_or_below_depth)
|
||||
#define hwloc_get_type_or_above_depth HWLOC_NAME(get_type_or_above_depth)
|
||||
#define hwloc_get_root_obj HWLOC_NAME(get_root_obj)
|
||||
#define hwloc_get_ancestor_obj_by_depth HWLOC_NAME(get_ancestor_obj_by_depth)
|
||||
#define hwloc_get_ancestor_obj_by_type HWLOC_NAME(get_ancestor_obj_by_type)
|
||||
#define hwloc_get_next_obj_by_depth HWLOC_NAME(get_next_obj_by_depth)
|
||||
#define hwloc_get_next_obj_by_type HWLOC_NAME(get_next_obj_by_type)
|
||||
#define hwloc_get_pu_obj_by_os_index HWLOC_NAME(get_pu_obj_by_os_index)
|
||||
#define hwloc_get_numanode_obj_by_os_index HWLOC_NAME(get_numanode_obj_by_os_index)
|
||||
#define hwloc_get_next_child HWLOC_NAME(get_next_child)
|
||||
#define hwloc_get_common_ancestor_obj HWLOC_NAME(get_common_ancestor_obj)
|
||||
#define hwloc_obj_is_in_subtree HWLOC_NAME(obj_is_in_subtree)
|
||||
#define hwloc_get_first_largest_obj_inside_cpuset HWLOC_NAME(get_first_largest_obj_inside_cpuset)
|
||||
#define hwloc_get_largest_objs_inside_cpuset HWLOC_NAME(get_largest_objs_inside_cpuset)
|
||||
#define hwloc_get_next_obj_inside_cpuset_by_depth HWLOC_NAME(get_next_obj_inside_cpuset_by_depth)
|
||||
#define hwloc_get_next_obj_inside_cpuset_by_type HWLOC_NAME(get_next_obj_inside_cpuset_by_type)
|
||||
#define hwloc_get_obj_inside_cpuset_by_depth HWLOC_NAME(get_obj_inside_cpuset_by_depth)
|
||||
#define hwloc_get_obj_inside_cpuset_by_type HWLOC_NAME(get_obj_inside_cpuset_by_type)
|
||||
#define hwloc_get_nbobjs_inside_cpuset_by_depth HWLOC_NAME(get_nbobjs_inside_cpuset_by_depth)
|
||||
#define hwloc_get_nbobjs_inside_cpuset_by_type HWLOC_NAME(get_nbobjs_inside_cpuset_by_type)
|
||||
#define hwloc_get_obj_index_inside_cpuset HWLOC_NAME(get_obj_index_inside_cpuset)
|
||||
#define hwloc_get_child_covering_cpuset HWLOC_NAME(get_child_covering_cpuset)
|
||||
#define hwloc_get_obj_covering_cpuset HWLOC_NAME(get_obj_covering_cpuset)
|
||||
#define hwloc_get_next_obj_covering_cpuset_by_depth HWLOC_NAME(get_next_obj_covering_cpuset_by_depth)
|
||||
#define hwloc_get_next_obj_covering_cpuset_by_type HWLOC_NAME(get_next_obj_covering_cpuset_by_type)
|
||||
#define hwloc_obj_type_is_cache HWLOC_NAME(obj_type_is_cache)
|
||||
#define hwloc_obj_type_is_dcache HWLOC_NAME(obj_type_is_dcache)
|
||||
#define hwloc_obj_type_is_icache HWLOC_NAME(obj_type_is_icache)
|
||||
#define hwloc_get_cache_type_depth HWLOC_NAME(get_cache_type_depth)
|
||||
#define hwloc_get_cache_covering_cpuset HWLOC_NAME(get_cache_covering_cpuset)
|
||||
#define hwloc_get_shared_cache_covering_obj HWLOC_NAME(get_shared_cache_covering_obj)
|
||||
#define hwloc_get_closest_objs HWLOC_NAME(get_closest_objs)
|
||||
#define hwloc_get_obj_below_by_type HWLOC_NAME(get_obj_below_by_type)
|
||||
#define hwloc_get_obj_below_array_by_type HWLOC_NAME(get_obj_below_array_by_type)
|
||||
#define hwloc_distrib_flags_e HWLOC_NAME(distrib_flags_e)
|
||||
#define HWLOC_DISTRIB_FLAG_REVERSE HWLOC_NAME_CAPS(DISTRIB_FLAG_REVERSE)
|
||||
#define hwloc_distrib HWLOC_NAME(distrib)
|
||||
#define hwloc_alloc_membind_policy HWLOC_NAME(alloc_membind_policy)
|
||||
#define hwloc_alloc_membind_policy_nodeset HWLOC_NAME(alloc_membind_policy_nodeset)
|
||||
#define hwloc_topology_get_complete_cpuset HWLOC_NAME(topology_get_complete_cpuset)
|
||||
#define hwloc_topology_get_topology_cpuset HWLOC_NAME(topology_get_topology_cpuset)
|
||||
#define hwloc_topology_get_allowed_cpuset HWLOC_NAME(topology_get_allowed_cpuset)
|
||||
#define hwloc_topology_get_complete_nodeset HWLOC_NAME(topology_get_complete_nodeset)
|
||||
#define hwloc_topology_get_topology_nodeset HWLOC_NAME(topology_get_topology_nodeset)
|
||||
#define hwloc_topology_get_allowed_nodeset HWLOC_NAME(topology_get_allowed_nodeset)
|
||||
#define hwloc_cpuset_to_nodeset HWLOC_NAME(cpuset_to_nodeset)
|
||||
#define hwloc_cpuset_from_nodeset HWLOC_NAME(cpuset_from_nodeset)
|
||||
|
||||
/* export.h */
|
||||
|
||||
#define hwloc_topology_export_xml_flags_e HWLOC_NAME(topology_export_xml_flags_e)
|
||||
#define HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1 HWLOC_NAME_CAPS(TOPOLOGY_EXPORT_XML_FLAG_V1)
|
||||
#define hwloc_topology_export_xml HWLOC_NAME(topology_export_xml)
|
||||
#define hwloc_topology_export_xmlbuffer HWLOC_NAME(topology_export_xmlbuffer)
|
||||
#define hwloc_free_xmlbuffer HWLOC_NAME(free_xmlbuffer)
|
||||
#define hwloc_topology_set_userdata_export_callback HWLOC_NAME(topology_set_userdata_export_callback)
|
||||
#define hwloc_export_obj_userdata HWLOC_NAME(export_obj_userdata)
|
||||
#define hwloc_export_obj_userdata_base64 HWLOC_NAME(export_obj_userdata_base64)
|
||||
#define hwloc_topology_set_userdata_import_callback HWLOC_NAME(topology_set_userdata_import_callback)
|
||||
|
||||
#define hwloc_topology_export_synthetic_flags_e HWLOC_NAME(topology_export_synthetic_flags_e)
|
||||
#define HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES HWLOC_NAME_CAPS(TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES)
|
||||
#define HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS HWLOC_NAME_CAPS(TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS)
|
||||
#define hwloc_topology_export_synthetic HWLOC_NAME(topology_export_synthetic)
|
||||
|
||||
/* distances.h */
|
||||
|
||||
#define hwloc_distances_s HWLOC_NAME(distances_s)
|
||||
|
||||
#define hwloc_distances_kind_e HWLOC_NAME(distances_kind_e)
|
||||
#define HWLOC_DISTANCES_KIND_FROM_OS HWLOC_NAME_CAPS(DISTANCES_KIND_FROM_OS)
|
||||
#define HWLOC_DISTANCES_KIND_FROM_USER HWLOC_NAME_CAPS(DISTANCES_KIND_FROM_USER)
|
||||
#define HWLOC_DISTANCES_KIND_MEANS_LATENCY HWLOC_NAME_CAPS(DISTANCES_KIND_MEANS_LATENCY)
|
||||
#define HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH HWLOC_NAME_CAPS(DISTANCES_KIND_MEANS_BANDWIDTH)
|
||||
|
||||
#define hwloc_distances_get HWLOC_NAME(distances_get)
|
||||
#define hwloc_distances_get_by_depth HWLOC_NAME(distances_get_by_depth)
|
||||
#define hwloc_distances_get_by_type HWLOC_NAME(distances_get_by_type)
|
||||
#define hwloc_distances_release HWLOC_NAME(distances_release)
|
||||
|
||||
#define hwloc_distances_flag_e HWLOC_NAME(distances_flag_e)
|
||||
#define HWLOC_DISTANCES_FLAG_GROUP HWLOC_NAME_CAPS(DISTANCES_FLAG_GROUP)
|
||||
#define HWLOC_DISTANCES_FLAG_GROUP_INACCURATE HWLOC_NAME_CAPS(DISTANCES_FLAG_GROUP_INACCURATE)
|
||||
|
||||
#define hwloc_distances_add HWLOC_NAME(distances_add)
|
||||
#define hwloc_distances_remove HWLOC_NAME(distances_remove)
|
||||
#define hwloc_distances_remove_by_depth HWLOC_NAME(distances_remove_by_depth)
|
||||
#define hwloc_distances_remove_by_type HWLOC_NAME(distances_remove_by_type)
|
||||
|
||||
/* diff.h */
|
||||
|
||||
#define hwloc_topology_diff_obj_attr_type_e HWLOC_NAME(topology_diff_obj_attr_type_e)
|
||||
#define hwloc_topology_diff_obj_attr_type_t HWLOC_NAME(topology_diff_obj_attr_type_t)
|
||||
#define HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE HWLOC_NAME_CAPS(TOPOLOGY_DIFF_OBJ_ATTR_SIZE)
|
||||
#define HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME HWLOC_NAME_CAPS(TOPOLOGY_DIFF_OBJ_ATTR_NAME)
|
||||
#define HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO HWLOC_NAME_CAPS(TOPOLOGY_DIFF_OBJ_ATTR_INFO)
|
||||
#define hwloc_topology_diff_obj_attr_u HWLOC_NAME(topology_diff_obj_attr_u)
|
||||
#define hwloc_topology_diff_obj_attr_generic_s HWLOC_NAME(topology_diff_obj_attr_generic_s)
|
||||
#define hwloc_topology_diff_obj_attr_uint64_s HWLOC_NAME(topology_diff_obj_attr_uint64_s)
|
||||
#define hwloc_topology_diff_obj_attr_string_s HWLOC_NAME(topology_diff_obj_attr_string_s)
|
||||
#define hwloc_topology_diff_type_e HWLOC_NAME(topology_diff_type_e)
|
||||
#define hwloc_topology_diff_type_t HWLOC_NAME(topology_diff_type_t)
|
||||
#define HWLOC_TOPOLOGY_DIFF_OBJ_ATTR HWLOC_NAME_CAPS(TOPOLOGY_DIFF_OBJ_ATTR)
|
||||
#define HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX HWLOC_NAME_CAPS(TOPOLOGY_DIFF_TOO_COMPLEX)
|
||||
#define hwloc_topology_diff_u HWLOC_NAME(topology_diff_u)
|
||||
#define hwloc_topology_diff_t HWLOC_NAME(topology_diff_t)
|
||||
#define hwloc_topology_diff_generic_s HWLOC_NAME(topology_diff_generic_s)
|
||||
#define hwloc_topology_diff_obj_attr_s HWLOC_NAME(topology_diff_obj_attr_s)
|
||||
#define hwloc_topology_diff_too_complex_s HWLOC_NAME(topology_diff_too_complex_s)
|
||||
#define hwloc_topology_diff_build HWLOC_NAME(topology_diff_build)
|
||||
#define hwloc_topology_diff_apply_flags_e HWLOC_NAME(topology_diff_apply_flags_e)
|
||||
#define HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE HWLOC_NAME_CAPS(TOPOLOGY_DIFF_APPLY_REVERSE)
|
||||
#define hwloc_topology_diff_apply HWLOC_NAME(topology_diff_apply)
|
||||
#define hwloc_topology_diff_destroy HWLOC_NAME(topology_diff_destroy)
|
||||
#define hwloc_topology_diff_load_xml HWLOC_NAME(topology_diff_load_xml)
|
||||
#define hwloc_topology_diff_export_xml HWLOC_NAME(topology_diff_export_xml)
|
||||
#define hwloc_topology_diff_load_xmlbuffer HWLOC_NAME(topology_diff_load_xmlbuffer)
|
||||
#define hwloc_topology_diff_export_xmlbuffer HWLOC_NAME(topology_diff_export_xmlbuffer)
|
||||
|
||||
/* glibc-sched.h */
|
||||
|
||||
#define hwloc_cpuset_to_glibc_sched_affinity HWLOC_NAME(cpuset_to_glibc_sched_affinity)
|
||||
#define hwloc_cpuset_from_glibc_sched_affinity HWLOC_NAME(cpuset_from_glibc_sched_affinity)
|
||||
|
||||
/* linux-libnuma.h */
|
||||
|
||||
#define hwloc_cpuset_to_linux_libnuma_ulongs HWLOC_NAME(cpuset_to_linux_libnuma_ulongs)
|
||||
#define hwloc_nodeset_to_linux_libnuma_ulongs HWLOC_NAME(nodeset_to_linux_libnuma_ulongs)
|
||||
#define hwloc_cpuset_from_linux_libnuma_ulongs HWLOC_NAME(cpuset_from_linux_libnuma_ulongs)
|
||||
#define hwloc_nodeset_from_linux_libnuma_ulongs HWLOC_NAME(nodeset_from_linux_libnuma_ulongs)
|
||||
#define hwloc_cpuset_to_linux_libnuma_bitmask HWLOC_NAME(cpuset_to_linux_libnuma_bitmask)
|
||||
#define hwloc_nodeset_to_linux_libnuma_bitmask HWLOC_NAME(nodeset_to_linux_libnuma_bitmask)
|
||||
#define hwloc_cpuset_from_linux_libnuma_bitmask HWLOC_NAME(cpuset_from_linux_libnuma_bitmask)
|
||||
#define hwloc_nodeset_from_linux_libnuma_bitmask HWLOC_NAME(nodeset_from_linux_libnuma_bitmask)
|
||||
|
||||
/* linux.h */
|
||||
|
||||
#define hwloc_linux_set_tid_cpubind HWLOC_NAME(linux_set_tid_cpubind)
|
||||
#define hwloc_linux_get_tid_cpubind HWLOC_NAME(linux_get_tid_cpubind)
|
||||
#define hwloc_linux_get_tid_last_cpu_location HWLOC_NAME(linux_get_tid_last_cpu_location)
|
||||
#define hwloc_linux_read_path_as_cpumask HWLOC_NAME(linux_read_file_cpumask)
|
||||
|
||||
/* openfabrics-verbs.h */
|
||||
|
||||
#define hwloc_ibv_get_device_cpuset HWLOC_NAME(ibv_get_device_cpuset)
|
||||
#define hwloc_ibv_get_device_osdev HWLOC_NAME(ibv_get_device_osdev)
|
||||
#define hwloc_ibv_get_device_osdev_by_name HWLOC_NAME(ibv_get_device_osdev_by_name)
|
||||
|
||||
/* myriexpress.h */
|
||||
|
||||
#define hwloc_mx_board_get_device_cpuset HWLOC_NAME(mx_board_get_device_cpuset)
|
||||
#define hwloc_mx_endpoint_get_device_cpuset HWLOC_NAME(mx_endpoint_get_device_cpuset)
|
||||
|
||||
/* intel-mic.h */
|
||||
|
||||
#define hwloc_intel_mic_get_device_cpuset HWLOC_NAME(intel_mic_get_device_cpuset)
|
||||
#define hwloc_intel_mic_get_device_osdev_by_index HWLOC_NAME(intel_mic_get_device_osdev_by_index)
|
||||
|
||||
/* opencl.h */
|
||||
|
||||
#define hwloc_opencl_get_device_cpuset HWLOC_NAME(opencl_get_device_cpuset)
|
||||
#define hwloc_opencl_get_device_osdev HWLOC_NAME(opencl_get_device_osdev)
|
||||
#define hwloc_opencl_get_device_osdev_by_index HWLOC_NAME(opencl_get_device_osdev_by_index)
|
||||
|
||||
/* cuda.h */
|
||||
|
||||
#define hwloc_cuda_get_device_pci_ids HWLOC_NAME(cuda_get_device_pci_ids)
|
||||
#define hwloc_cuda_get_device_cpuset HWLOC_NAME(cuda_get_device_cpuset)
|
||||
#define hwloc_cuda_get_device_pcidev HWLOC_NAME(cuda_get_device_pcidev)
|
||||
#define hwloc_cuda_get_device_osdev HWLOC_NAME(cuda_get_device_osdev)
|
||||
#define hwloc_cuda_get_device_osdev_by_index HWLOC_NAME(cuda_get_device_osdev_by_index)
|
||||
|
||||
/* cudart.h */
|
||||
|
||||
#define hwloc_cudart_get_device_pci_ids HWLOC_NAME(cudart_get_device_pci_ids)
|
||||
#define hwloc_cudart_get_device_cpuset HWLOC_NAME(cudart_get_device_cpuset)
|
||||
#define hwloc_cudart_get_device_pcidev HWLOC_NAME(cudart_get_device_pcidev)
|
||||
#define hwloc_cudart_get_device_osdev_by_index HWLOC_NAME(cudart_get_device_osdev_by_index)
|
||||
|
||||
/* nvml.h */
|
||||
|
||||
#define hwloc_nvml_get_device_cpuset HWLOC_NAME(nvml_get_device_cpuset)
|
||||
#define hwloc_nvml_get_device_osdev HWLOC_NAME(nvml_get_device_osdev)
|
||||
#define hwloc_nvml_get_device_osdev_by_index HWLOC_NAME(nvml_get_device_osdev_by_index)
|
||||
|
||||
/* gl.h */
|
||||
|
||||
#define hwloc_gl_get_display_osdev_by_port_device HWLOC_NAME(gl_get_display_osdev_by_port_device)
|
||||
#define hwloc_gl_get_display_osdev_by_name HWLOC_NAME(gl_get_display_osdev_by_name)
|
||||
#define hwloc_gl_get_display_by_osdev HWLOC_NAME(gl_get_display_by_osdev)
|
||||
|
||||
/* hwloc/plugins.h */
|
||||
|
||||
#define hwloc_disc_component_type_e HWLOC_NAME(disc_component_type_e)
|
||||
#define HWLOC_DISC_COMPONENT_TYPE_CPU HWLOC_NAME_CAPS(DISC_COMPONENT_TYPE_CPU)
|
||||
#define HWLOC_DISC_COMPONENT_TYPE_GLOBAL HWLOC_NAME_CAPS(DISC_COMPONENT_TYPE_GLOBAL)
|
||||
#define HWLOC_DISC_COMPONENT_TYPE_MISC HWLOC_NAME_CAPS(DISC_COMPONENT_TYPE_MISC)
|
||||
#define hwloc_disc_component_type_t HWLOC_NAME(disc_component_type_t)
|
||||
#define hwloc_disc_component HWLOC_NAME(disc_component)
|
||||
|
||||
#define hwloc_backend HWLOC_NAME(backend)
|
||||
|
||||
#define hwloc_backend_alloc HWLOC_NAME(backend_alloc)
|
||||
#define hwloc_backend_enable HWLOC_NAME(backend_enable)
|
||||
|
||||
#define hwloc_component_type_e HWLOC_NAME(component_type_e)
|
||||
#define HWLOC_COMPONENT_TYPE_DISC HWLOC_NAME_CAPS(COMPONENT_TYPE_DISC)
|
||||
#define HWLOC_COMPONENT_TYPE_XML HWLOC_NAME_CAPS(COMPONENT_TYPE_XML)
|
||||
#define hwloc_component_type_t HWLOC_NAME(component_type_t)
|
||||
#define hwloc_component HWLOC_NAME(component)
|
||||
|
||||
#define hwloc_plugin_check_namespace HWLOC_NAME(plugin_check_namespace)
|
||||
|
||||
#define hwloc_insert_object_by_cpuset HWLOC_NAME(insert_object_by_cpuset)
|
||||
#define hwloc_report_error_t HWLOC_NAME(report_error_t)
|
||||
#define hwloc_report_os_error HWLOC_NAME(report_os_error)
|
||||
#define hwloc_hide_errors HWLOC_NAME(hide_errors)
|
||||
#define hwloc__insert_object_by_cpuset HWLOC_NAME(_insert_object_by_cpuset)
|
||||
#define hwloc_insert_object_by_parent HWLOC_NAME(insert_object_by_parent)
|
||||
#define hwloc_alloc_setup_object HWLOC_NAME(alloc_setup_object)
|
||||
#define hwloc_obj_add_children_sets HWLOC_NAME(add_children_sets)
|
||||
#define hwloc_topology_reconnect HWLOC_NAME(topology_reconnect)
|
||||
|
||||
#define hwloc_filter_check_pcidev_subtype_important HWLOC_NAME(filter_check_pcidev_subtype_important)
|
||||
#define hwloc_filter_check_osdev_subtype_important HWLOC_NAME(filter_check_osdev_subtype_important)
|
||||
#define hwloc_filter_check_keep_object_type HWLOC_NAME(filter_check_keep_object_type)
|
||||
#define hwloc_filter_check_keep_object HWLOC_NAME(filter_check_keep_object)
|
||||
|
||||
#define hwloc_pci_find_cap HWLOC_NAME(pci_find_cap)
|
||||
#define hwloc_pci_find_linkspeed HWLOC_NAME(pci_find_linkspeed)
|
||||
#define hwloc_pci_check_bridge_type HWLOC_NAME(pci_check_bridge_type)
|
||||
#define hwloc_pci_setup_bridge_attr HWLOC_NAME(pci_setup_bridge_attr)
|
||||
#define hwloc_pci_tree_insert_by_busid HWLOC_NAME(pci_tree_insert_by_busid)
|
||||
#define hwloc_pci_tree_attach_belowroot HWLOC_NAME(pci_tree_attach_belowroot)
|
||||
#define hwloc_pci_belowroot_find_by_busid HWLOC_NAME(pci_belowroot_find_by_busid)
|
||||
#define hwloc_pci_find_busid_parent HWLOC_NAME(pci_find_busid_parent)
|
||||
|
||||
/* hwloc/deprecated.h */
|
||||
|
||||
#define hwloc_topology_insert_misc_object_by_parent HWLOC_NAME(topology_insert_misc_object_by_parent)
|
||||
#define hwloc_obj_cpuset_snprintf HWLOC_NAME(obj_cpuset_snprintf)
|
||||
#define hwloc_obj_type_string HWLOC_NAME(obj_type_string)
|
||||
#define hwloc_obj_type_sscanf HWLOC_NAME(obj_type_sscanf)
|
||||
|
||||
#define hwloc_set_membind_nodeset HWLOC_NAME(set_membind_nodeset)
|
||||
#define hwloc_get_membind_nodeset HWLOC_NAME(get_membind_nodeset)
|
||||
#define hwloc_set_proc_membind_nodeset HWLOC_NAME(set_proc_membind_nodeset)
|
||||
#define hwloc_get_proc_membind_nodeset HWLOC_NAME(get_proc_membind_nodeset)
|
||||
#define hwloc_set_area_membind_nodeset HWLOC_NAME(set_area_membind_nodeset)
|
||||
#define hwloc_get_area_membind_nodeset HWLOC_NAME(get_area_membind_nodeset)
|
||||
#define hwloc_alloc_membind_nodeset HWLOC_NAME(alloc_membind_nodeset)
|
||||
|
||||
#define hwloc_cpuset_to_nodeset_strict HWLOC_NAME(cpuset_to_nodeset_strict)
|
||||
#define hwloc_cpuset_from_nodeset_strict HWLOC_NAME(cpuset_from_nodeset_strict)
|
||||
|
||||
/* private/debug.h */
|
||||
|
||||
#define hwloc_debug_enabled HWLOC_NAME(debug_enabled)
|
||||
#define hwloc_debug HWLOC_NAME(debug)
|
||||
|
||||
/* private/misc.h */
|
||||
|
||||
#define hwloc_snprintf HWLOC_NAME(snprintf)
|
||||
#define hwloc_namecoloncmp HWLOC_NAME(namecoloncmp)
|
||||
#define hwloc_ffsl_manual HWLOC_NAME(ffsl_manual)
|
||||
#define hwloc_ffs32 HWLOC_NAME(ffs32)
|
||||
#define hwloc_ffsl_from_ffs32 HWLOC_NAME(ffsl_from_ffs32)
|
||||
#define hwloc_flsl_manual HWLOC_NAME(flsl_manual)
|
||||
#define hwloc_fls32 HWLOC_NAME(fls32)
|
||||
#define hwloc_flsl_from_fls32 HWLOC_NAME(flsl_from_fls32)
|
||||
#define hwloc_weight_long HWLOC_NAME(weight_long)
|
||||
#define hwloc_strncasecmp HWLOC_NAME(strncasecmp)
|
||||
#define hwloc_cache_type_by_depth_type HWLOC_NAME(cache_type_by_depth_type)
|
||||
#define hwloc_obj_type_is_io HWLOC_NAME(obj_type_is_io)
|
||||
#define hwloc_obj_type_is_special HWLOC_NAME(obj_type_is_special)
|
||||
|
||||
/* private/cpuid-x86.h */
|
||||
|
||||
#define hwloc_have_x86_cpuid HWLOC_NAME(have_x86_cpuid)
|
||||
#define hwloc_x86_cpuid HWLOC_NAME(x86_cpuid)
|
||||
|
||||
/* private/xml.h */
|
||||
|
||||
#define hwloc__xml_verbose HWLOC_NAME(_xml_verbose)
|
||||
|
||||
#define hwloc__xml_import_state_s HWLOC_NAME(_xml_import_state_s)
|
||||
#define hwloc__xml_import_state_t HWLOC_NAME(_xml_import_state_t)
|
||||
#define hwloc__xml_import_diff HWLOC_NAME(_xml_import_diff)
|
||||
#define hwloc_xml_backend_data_s HWLOC_NAME(xml_backend_data_s)
|
||||
#define hwloc__xml_export_state_s HWLOC_NAME(_xml_export_state_s)
|
||||
#define hwloc__xml_export_state_t HWLOC_NAME(_xml_export_state_t)
|
||||
#define hwloc__xml_export_topology HWLOC_NAME(_xml_export_topology)
|
||||
#define hwloc__xml_export_diff HWLOC_NAME(_xml_export_diff)
|
||||
|
||||
#define hwloc_xml_callbacks HWLOC_NAME(xml_callbacks)
|
||||
#define hwloc_xml_component HWLOC_NAME(xml_component)
|
||||
#define hwloc_xml_callbacks_register HWLOC_NAME(xml_callbacks_register)
|
||||
#define hwloc_xml_callbacks_reset HWLOC_NAME(xml_callbacks_reset)
|
||||
|
||||
#define hwloc__xml_imported_v1distances_s HWLOC_NAME(_xml_imported_v1distances_s)
|
||||
|
||||
/* private/components.h */
|
||||
|
||||
#define hwloc_disc_component_force_enable HWLOC_NAME(disc_component_force_enable)
|
||||
#define hwloc_disc_components_enable_others HWLOC_NAME(disc_components_instantiate_others)
|
||||
|
||||
#define hwloc_backends_is_thissystem HWLOC_NAME(backends_is_thissystem)
|
||||
#define hwloc_backends_find_callbacks HWLOC_NAME(backends_find_callbacks)
|
||||
|
||||
#define hwloc_backends_init HWLOC_NAME(backends_init)
|
||||
#define hwloc_backends_disable_all HWLOC_NAME(backends_disable_all)
|
||||
|
||||
#define hwloc_components_init HWLOC_NAME(components_init)
|
||||
#define hwloc_components_fini HWLOC_NAME(components_fini)
|
||||
|
||||
/* private/private.h */
|
||||
|
||||
#define hwloc_special_level_s HWLOC_NAME(special_level_s)
|
||||
|
||||
#define hwloc_pci_forced_locality_s HWLOC_NAME(pci_forced_locality_s)
|
||||
|
||||
#define hwloc_alloc_obj_cpusets HWLOC_NAME(alloc_obj_cpusets)
|
||||
#define hwloc_setup_pu_level HWLOC_NAME(setup_pu_level)
|
||||
#define hwloc_get_sysctlbyname HWLOC_NAME(get_sysctlbyname)
|
||||
#define hwloc_get_sysctl HWLOC_NAME(get_sysctl)
|
||||
#define hwloc_fallback_nbprocessors HWLOC_NAME(fallback_nbprocessors)
|
||||
|
||||
#define hwloc__object_cpusets_compare_first HWLOC_NAME(_object_cpusets_compare_first)
|
||||
#define hwloc__reorder_children HWLOC_NAME(_reorder_children)
|
||||
|
||||
#define hwloc_topology_setup_defaults HWLOC_NAME(topology_setup_defaults)
|
||||
#define hwloc_topology_clear HWLOC_NAME(topology_clear)
|
||||
|
||||
#define hwloc_pci_discovery_init HWLOC_NAME(pci_discovery_init)
|
||||
#define hwloc_pci_discovery_prepare HWLOC_NAME(pci_discovery_prepare)
|
||||
#define hwloc_pci_discovery_exit HWLOC_NAME(pci_discovery_exit)
|
||||
#define hwloc_find_insert_io_parent_by_complete_cpuset HWLOC_NAME(hwloc_find_insert_io_parent_by_complete_cpuset)
|
||||
#define hwloc_pci_belowroot_apply_locality HWLOC_NAME(pci_belowroot_apply_locality)
|
||||
#define hwloc_pci_class_string HWLOC_NAME(pci_class_string)
|
||||
|
||||
#define hwloc__add_info HWLOC_NAME(_add_info)
|
||||
#define hwloc__find_info_slot HWLOC_NAME(_find_info_slot)
|
||||
#define hwloc__move_infos HWLOC_NAME(_move_infos)
|
||||
#define hwloc__free_infos HWLOC_NAME(_free_infos)
|
||||
|
||||
#define hwloc_binding_hooks HWLOC_NAME(binding_hooks)
|
||||
#define hwloc_set_native_binding_hooks HWLOC_NAME(set_native_binding_hooks)
|
||||
#define hwloc_set_binding_hooks HWLOC_NAME(set_binding_hooks)
|
||||
|
||||
#define hwloc_set_linuxfs_hooks HWLOC_NAME(set_linuxfs_hooks)
|
||||
#define hwloc_set_bgq_hooks HWLOC_NAME(set_bgq_hooks)
|
||||
#define hwloc_set_solaris_hooks HWLOC_NAME(set_solaris_hooks)
|
||||
#define hwloc_set_aix_hooks HWLOC_NAME(set_aix_hooks)
|
||||
#define hwloc_set_windows_hooks HWLOC_NAME(set_windows_hooks)
|
||||
#define hwloc_set_darwin_hooks HWLOC_NAME(set_darwin_hooks)
|
||||
#define hwloc_set_freebsd_hooks HWLOC_NAME(set_freebsd_hooks)
|
||||
#define hwloc_set_netbsd_hooks HWLOC_NAME(set_netbsd_hooks)
|
||||
#define hwloc_set_hpux_hooks HWLOC_NAME(set_hpux_hooks)
|
||||
|
||||
#define hwloc_look_hardwired_fujitsu_k HWLOC_NAME(look_hardwired_fujitsu_k)
|
||||
#define hwloc_look_hardwired_fujitsu_fx10 HWLOC_NAME(look_hardwired_fujitsu_fx10)
|
||||
#define hwloc_look_hardwired_fujitsu_fx100 HWLOC_NAME(look_hardwired_fujitsu_fx100)
|
||||
|
||||
#define hwloc_add_uname_info HWLOC_NAME(add_uname_info)
|
||||
#define hwloc_free_unlinked_object HWLOC_NAME(free_unlinked_object)
|
||||
#define hwloc_free_object_and_children HWLOC_NAME(free_object_and_children)
|
||||
#define hwloc_free_object_siblings_and_children HWLOC_NAME(free_object_siblings_and_children)
|
||||
|
||||
#define hwloc_alloc_heap HWLOC_NAME(alloc_heap)
|
||||
#define hwloc_alloc_mmap HWLOC_NAME(alloc_mmap)
|
||||
#define hwloc_free_heap HWLOC_NAME(free_heap)
|
||||
#define hwloc_free_mmap HWLOC_NAME(free_mmap)
|
||||
#define hwloc_alloc_or_fail HWLOC_NAME(alloc_or_fail)
|
||||
|
||||
#define hwloc_internal_distances_s HWLOC_NAME(internal_distances_s)
|
||||
#define hwloc_internal_distances_init HWLOC_NAME(internal_distances_init)
|
||||
#define hwloc_internal_distances_prepare HWLOC_NAME(internal_distances_prepare)
|
||||
#define hwloc_internal_distances_dup HWLOC_NAME(internal_distances_dup)
|
||||
#define hwloc_internal_distances_refresh HWLOC_NAME(internal_distances_refresh)
|
||||
#define hwloc_internal_distances_destroy HWLOC_NAME(internal_distances_destroy)
|
||||
|
||||
#define hwloc_internal_distances_add HWLOC_NAME(internal_distances_add)
|
||||
#define hwloc_internal_distances_add_by_index HWLOC_NAME(internal_distances_add_by_index)
|
||||
#define hwloc_internal_distances_invalidate_cached_objs HWLOC_NAME(hwloc_internal_distances_invalidate_cached_objs)
|
||||
|
||||
#define hwloc_encode_to_base64 HWLOC_NAME(encode_to_base64)
|
||||
#define hwloc_decode_from_base64 HWLOC_NAME(decode_from_base64)
|
||||
|
||||
#define hwloc_obj_add_info_nodup HWLOC_NAME(obj_add_info_nodup)
|
||||
|
||||
#define hwloc_progname HWLOC_NAME(progname)
|
||||
|
||||
#define hwloc_bitmap_compare_inclusion HWLOC_NAME(bitmap_compare_inclusion)
|
||||
|
||||
/* private/solaris-chiptype.h */
|
||||
|
||||
#define hwloc_solaris_get_chip_type HWLOC_NAME(solaris_get_chip_type)
|
||||
#define hwloc_solaris_get_chip_model HWLOC_NAME(solaris_get_chip_model)
|
||||
|
||||
#endif /* HWLOC_SYM_TRANSFORM */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_RENAME_H */
|
56
opal/mca/hwloc/hwloc2x/hwloc/include/netloc.h
Обычный файл
56
opal/mca/hwloc/hwloc2x/hwloc/include/netloc.h
Обычный файл
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright © 2013-2014 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright © 2013-2014 University of Wisconsin-La Crosse.
|
||||
* All rights reserved.
|
||||
* Copyright © 2015-2016 Inria. All rights reserved.
|
||||
*
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
* See COPYING in top-level directory.
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#ifndef _NETLOC_H_
|
||||
#define _NETLOC_H_
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE // for asprintf
|
||||
#endif
|
||||
|
||||
#include <hwloc/autogen/config.h>
|
||||
|
||||
#include <hwloc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup netloc_api Netloc API
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* Return codes
|
||||
*/
|
||||
enum {
|
||||
NETLOC_SUCCESS = 0, /**< Success */
|
||||
NETLOC_ERROR = -1, /**< Error: General condition */
|
||||
NETLOC_ERROR_NOTDIR = -2, /**< Error: URI is not a directory */
|
||||
NETLOC_ERROR_NOENT = -3, /**< Error: URI is invalid, no such entry */
|
||||
NETLOC_ERROR_EMPTY = -4, /**< Error: No networks found */
|
||||
NETLOC_ERROR_MULTIPLE = -5, /**< Error: Multiple matching networks found */
|
||||
NETLOC_ERROR_NOT_IMPL = -6, /**< Error: Interface not implemented */
|
||||
NETLOC_ERROR_EXISTS = -7, /**< Error: If the entry already exists when trying to add to a lookup table */
|
||||
NETLOC_ERROR_NOT_FOUND = -8, /**< Error: No path found */
|
||||
NETLOC_ERROR_MAX = -9 /**< Error: Enum upper bound marker. No errors less than this number Will not be returned externally. */
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif // _NETLOC_H_
|
237
opal/mca/hwloc/hwloc2x/hwloc/include/netloc/utarray.h
Обычный файл
237
opal/mca/hwloc/hwloc2x/hwloc/include/netloc/utarray.h
Обычный файл
@ -0,0 +1,237 @@
|
||||
/*
|
||||
Copyright (c) 2008-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* a dynamic array implementation using macros
|
||||
*/
|
||||
#ifndef UTARRAY_H
|
||||
#define UTARRAY_H
|
||||
|
||||
#define UTARRAY_VERSION 1.9.9
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define _UNUSED_ __attribute__ ((__unused__))
|
||||
#else
|
||||
#define _UNUSED_
|
||||
#endif
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <string.h> /* memset, etc */
|
||||
#include <stdlib.h> /* exit */
|
||||
|
||||
#ifndef oom
|
||||
#define oom() exit(-1)
|
||||
#endif
|
||||
|
||||
typedef void (ctor_f)(void *dst, const void *src);
|
||||
typedef void (dtor_f)(void *elt);
|
||||
typedef void (init_f)(void *elt);
|
||||
typedef struct {
|
||||
size_t sz;
|
||||
init_f *init;
|
||||
ctor_f *copy;
|
||||
dtor_f *dtor;
|
||||
} UT_icd;
|
||||
|
||||
typedef struct {
|
||||
unsigned i,n;/* i: index of next available slot, n: num slots */
|
||||
UT_icd icd; /* initializer, copy and destructor functions */
|
||||
char *d; /* n slots of size icd->sz*/
|
||||
} UT_array;
|
||||
|
||||
#define utarray_init(a,_icd) do { \
|
||||
memset(a,0,sizeof(UT_array)); \
|
||||
(a)->icd=*_icd; \
|
||||
} while(0)
|
||||
|
||||
#define utarray_done(a) do { \
|
||||
if ((a)->n) { \
|
||||
if ((a)->icd.dtor) { \
|
||||
size_t _ut_i; \
|
||||
for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \
|
||||
(a)->icd.dtor(utarray_eltptr(a,_ut_i)); \
|
||||
} \
|
||||
} \
|
||||
free((a)->d); \
|
||||
} \
|
||||
(a)->n=0; \
|
||||
} while(0)
|
||||
|
||||
#define utarray_new(a,_icd) do { \
|
||||
a=(UT_array*)malloc(sizeof(UT_array)); \
|
||||
utarray_init(a,_icd); \
|
||||
} while(0)
|
||||
|
||||
#define utarray_free(a) do { \
|
||||
utarray_done(a); \
|
||||
free(a); \
|
||||
} while(0)
|
||||
|
||||
#define utarray_reserve(a,by) do { \
|
||||
if (((a)->i+(by)) > ((a)->n)) { \
|
||||
char *utarray_tmp; \
|
||||
while(((a)->i+(by)) > ((a)->n)) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \
|
||||
utarray_tmp=(char*)realloc((a)->d, (a)->n*(a)->icd.sz); \
|
||||
if (utarray_tmp == NULL) oom(); \
|
||||
(a)->d=utarray_tmp; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define utarray_push_back(a,p) do { \
|
||||
utarray_reserve(a,1); \
|
||||
if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \
|
||||
else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \
|
||||
} while(0)
|
||||
|
||||
#define utarray_pop_back(a) do { \
|
||||
if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \
|
||||
else { (a)->i--; } \
|
||||
} while(0)
|
||||
|
||||
#define utarray_extend_back(a) do { \
|
||||
utarray_reserve(a,1); \
|
||||
if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \
|
||||
else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \
|
||||
(a)->i++; \
|
||||
} while(0)
|
||||
|
||||
#define utarray_len(a) ((a)->i)
|
||||
|
||||
#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL)
|
||||
#define _utarray_eltptr(a,j) ((char*)((a)->d + ((a)->icd.sz*(j) )))
|
||||
|
||||
#define utarray_insert(a,p,j) do { \
|
||||
if (j > (a)->i) utarray_resize(a,j); \
|
||||
utarray_reserve(a,1); \
|
||||
if ((j) < (a)->i) { \
|
||||
memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \
|
||||
((a)->i - (j))*((a)->icd.sz)); \
|
||||
} \
|
||||
if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \
|
||||
else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \
|
||||
(a)->i++; \
|
||||
} while(0)
|
||||
|
||||
#define utarray_inserta(a,w,j) do { \
|
||||
if (utarray_len(w) == 0) break; \
|
||||
if (j > (a)->i) utarray_resize(a,j); \
|
||||
utarray_reserve(a,utarray_len(w)); \
|
||||
if ((j) < (a)->i) { \
|
||||
memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \
|
||||
_utarray_eltptr(a,j), \
|
||||
((a)->i - (j))*((a)->icd.sz)); \
|
||||
} \
|
||||
if ((a)->icd.copy) { \
|
||||
size_t _ut_i; \
|
||||
for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \
|
||||
(a)->icd.copy(_utarray_eltptr(a,j+_ut_i), _utarray_eltptr(w,_ut_i)); \
|
||||
} \
|
||||
} else { \
|
||||
memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \
|
||||
utarray_len(w)*((a)->icd.sz)); \
|
||||
} \
|
||||
(a)->i += utarray_len(w); \
|
||||
} while(0)
|
||||
|
||||
#define utarray_resize(dst,num) do { \
|
||||
size_t _ut_i; \
|
||||
if (dst->i > (size_t)(num)) { \
|
||||
if ((dst)->icd.dtor) { \
|
||||
for(_ut_i=num; _ut_i < dst->i; _ut_i++) { \
|
||||
(dst)->icd.dtor(utarray_eltptr(dst,_ut_i)); \
|
||||
} \
|
||||
} \
|
||||
} else if (dst->i < (size_t)(num)) { \
|
||||
utarray_reserve(dst,num-dst->i); \
|
||||
if ((dst)->icd.init) { \
|
||||
for(_ut_i=dst->i; _ut_i < num; _ut_i++) { \
|
||||
(dst)->icd.init(utarray_eltptr(dst,_ut_i)); \
|
||||
} \
|
||||
} else { \
|
||||
memset(_utarray_eltptr(dst,dst->i),0,(dst)->icd.sz*(num-dst->i)); \
|
||||
} \
|
||||
} \
|
||||
dst->i = num; \
|
||||
} while(0)
|
||||
|
||||
#define utarray_concat(dst,src) do { \
|
||||
utarray_inserta((dst),(src),utarray_len(dst)); \
|
||||
} while(0)
|
||||
|
||||
#define utarray_erase(a,pos,len) do { \
|
||||
if ((a)->icd.dtor) { \
|
||||
size_t _ut_i; \
|
||||
for(_ut_i=0; _ut_i < len; _ut_i++) { \
|
||||
(a)->icd.dtor(utarray_eltptr((a),pos+_ut_i)); \
|
||||
} \
|
||||
} \
|
||||
if ((a)->i > (pos+len)) { \
|
||||
memmove( _utarray_eltptr((a),pos), _utarray_eltptr((a),pos+len), \
|
||||
(((a)->i)-(pos+len))*((a)->icd.sz)); \
|
||||
} \
|
||||
(a)->i -= (len); \
|
||||
} while(0)
|
||||
|
||||
#define utarray_renew(a,u) do { \
|
||||
if (a) utarray_clear(a); \
|
||||
else utarray_new((a),(u)); \
|
||||
} while(0)
|
||||
|
||||
#define utarray_clear(a) do { \
|
||||
if ((a)->i > 0) { \
|
||||
if ((a)->icd.dtor) { \
|
||||
size_t _ut_i; \
|
||||
for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \
|
||||
(a)->icd.dtor(utarray_eltptr(a,_ut_i)); \
|
||||
} \
|
||||
} \
|
||||
(a)->i = 0; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define utarray_sort(a,cmp) do { \
|
||||
qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \
|
||||
} while(0)
|
||||
|
||||
#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp)
|
||||
|
||||
#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL)
|
||||
#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : ((((a)->i) > (utarray_eltidx(a,e)+1)) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL))
|
||||
#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) > 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL))
|
||||
#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL)
|
||||
#define utarray_eltidx(a,e) (((char*)(e) >= (char*)((a)->d)) ? (((char*)(e) - (char*)((a)->d))/(size_t)(a)->icd.sz) : (unsigned int)-1)
|
||||
|
||||
/* last we pre-define a few icd for common utarrays of ints and strings */
|
||||
static void utarray_str_cpy(void *dst, const void *src) {
|
||||
char **_src = (char**)src, **_dst = (char**)dst;
|
||||
*_dst = (*_src == NULL) ? NULL : strdup(*_src);
|
||||
}
|
||||
static void utarray_str_dtor(void *elt) {
|
||||
char **eltc = (char**)elt;
|
||||
if (*eltc) free(*eltc);
|
||||
}
|
||||
static const UT_icd ut_str_icd _UNUSED_ = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor};
|
||||
static const UT_icd ut_int_icd _UNUSED_ = {sizeof(int),NULL,NULL,NULL};
|
||||
static const UT_icd ut_ptr_icd _UNUSED_ = {sizeof(void*),NULL,NULL,NULL};
|
||||
|
||||
|
||||
#endif /* UTARRAY_H */
|
966
opal/mca/hwloc/hwloc2x/hwloc/include/netloc/uthash.h
Обычный файл
966
opal/mca/hwloc/hwloc2x/hwloc/include/netloc/uthash.h
Обычный файл
@ -0,0 +1,966 @@
|
||||
/*
|
||||
Copyright (c) 2003-2014, Troy D. Hanson http://troydhanson.github.com/uthash/
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef UTHASH_H
|
||||
#define UTHASH_H
|
||||
|
||||
#include <string.h> /* memcmp,strlen */
|
||||
#include <stddef.h> /* ptrdiff_t */
|
||||
#include <stdlib.h> /* exit() */
|
||||
|
||||
/* These macros use decltype or the earlier __typeof GNU extension.
|
||||
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
|
||||
when compiling c++ source) this code uses whatever method is needed
|
||||
or, for VS2008 where neither is available, uses casting workarounds. */
|
||||
#if defined(_MSC_VER) /* MS compiler */
|
||||
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
|
||||
#define DECLTYPE(x) (decltype(x))
|
||||
#else /* VS2008 or older (or VS2010 in C mode) */
|
||||
#define NO_DECLTYPE
|
||||
#define DECLTYPE(x)
|
||||
#endif
|
||||
#elif defined(__BORLANDC__) || defined(__LCC__) || defined(__WATCOMC__)
|
||||
#define NO_DECLTYPE
|
||||
#define DECLTYPE(x)
|
||||
#else /* GNU, Sun and other compilers */
|
||||
#define DECLTYPE(x) (__typeof(x))
|
||||
#endif
|
||||
|
||||
#ifdef NO_DECLTYPE
|
||||
#define DECLTYPE_ASSIGN(dst,src) \
|
||||
do { \
|
||||
char **_da_dst = (char**)(&(dst)); \
|
||||
*_da_dst = (char*)(src); \
|
||||
} while(0)
|
||||
#else
|
||||
#define DECLTYPE_ASSIGN(dst,src) \
|
||||
do { \
|
||||
(dst) = DECLTYPE(dst)(src); \
|
||||
} while(0)
|
||||
#endif
|
||||
|
||||
/* a number of the hash function use uint32_t which isn't defined on Pre VS2010 */
|
||||
#if defined(_WIN32)
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1600
|
||||
#include <stdint.h>
|
||||
#elif defined(__WATCOMC__) || defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#endif
|
||||
#elif defined(__GNUC__) && !defined(__VXWORKS__)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
#endif
|
||||
|
||||
#define UTHASH_VERSION 1.9.9
|
||||
|
||||
#ifndef uthash_fatal
|
||||
#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
|
||||
#endif
|
||||
#ifndef uthash_malloc
|
||||
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
|
||||
#endif
|
||||
#ifndef uthash_free
|
||||
#define uthash_free(ptr,sz) free(ptr) /* free fcn */
|
||||
#endif
|
||||
|
||||
#ifndef uthash_noexpand_fyi
|
||||
#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
|
||||
#endif
|
||||
#ifndef uthash_expand_fyi
|
||||
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
|
||||
#endif
|
||||
|
||||
/* initial number of buckets */
|
||||
#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */
|
||||
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */
|
||||
#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */
|
||||
|
||||
/* calculate the element whose hash handle address is hhe */
|
||||
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
|
||||
|
||||
#define HASH_FIND(hh,head,keyptr,keylen,out) \
|
||||
do { \
|
||||
out=NULL; \
|
||||
if (head != NULL) { \
|
||||
unsigned _hf_bkt,_hf_hashv; \
|
||||
HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
|
||||
if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv) != 0) { \
|
||||
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
|
||||
keyptr,keylen,out); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef HASH_BLOOM
|
||||
#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM)
|
||||
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL)
|
||||
#define HASH_BLOOM_MAKE(tbl) \
|
||||
do { \
|
||||
(tbl)->bloom_nbits = HASH_BLOOM; \
|
||||
(tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
|
||||
if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
|
||||
memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
|
||||
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
|
||||
} while (0)
|
||||
|
||||
#define HASH_BLOOM_FREE(tbl) \
|
||||
do { \
|
||||
uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U)))
|
||||
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U)))
|
||||
|
||||
#define HASH_BLOOM_ADD(tbl,hashv) \
|
||||
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U)))
|
||||
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) \
|
||||
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1U)))
|
||||
|
||||
#else
|
||||
#define HASH_BLOOM_MAKE(tbl)
|
||||
#define HASH_BLOOM_FREE(tbl)
|
||||
#define HASH_BLOOM_ADD(tbl,hashv)
|
||||
#define HASH_BLOOM_TEST(tbl,hashv) (1)
|
||||
#define HASH_BLOOM_BYTELEN 0U
|
||||
#endif
|
||||
|
||||
#define HASH_MAKE_TABLE(hh,head) \
|
||||
do { \
|
||||
(head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
|
||||
sizeof(UT_hash_table)); \
|
||||
if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
|
||||
memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
|
||||
(head)->hh.tbl->tail = &((head)->hh); \
|
||||
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
|
||||
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
|
||||
(head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
|
||||
(head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
|
||||
if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
|
||||
memset((head)->hh.tbl->buckets, 0, \
|
||||
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
|
||||
HASH_BLOOM_MAKE((head)->hh.tbl); \
|
||||
(head)->hh.tbl->signature = HASH_SIGNATURE; \
|
||||
} while(0)
|
||||
|
||||
#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
|
||||
HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add)
|
||||
|
||||
#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \
|
||||
do { \
|
||||
replaced=NULL; \
|
||||
HASH_FIND(hh,head,&((add)->fieldname),keylen_in,replaced); \
|
||||
if (replaced!=NULL) { \
|
||||
HASH_DELETE(hh,head,replaced); \
|
||||
} \
|
||||
HASH_ADD(hh,head,fieldname,keylen_in,add); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
|
||||
do { \
|
||||
unsigned _ha_bkt; \
|
||||
(add)->hh.next = NULL; \
|
||||
(add)->hh.key = (char*)(keyptr); \
|
||||
(add)->hh.keylen = (unsigned)(keylen_in); \
|
||||
if (!(head)) { \
|
||||
head = (add); \
|
||||
(head)->hh.prev = NULL; \
|
||||
HASH_MAKE_TABLE(hh,head); \
|
||||
} else { \
|
||||
(head)->hh.tbl->tail->next = (add); \
|
||||
(add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
|
||||
(head)->hh.tbl->tail = &((add)->hh); \
|
||||
} \
|
||||
(head)->hh.tbl->num_items++; \
|
||||
(add)->hh.tbl = (head)->hh.tbl; \
|
||||
HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
|
||||
(add)->hh.hashv, _ha_bkt); \
|
||||
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
|
||||
HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
|
||||
HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
|
||||
HASH_FSCK(hh,head); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
|
||||
do { \
|
||||
bkt = ((hashv) & ((num_bkts) - 1U)); \
|
||||
} while(0)
|
||||
|
||||
/* delete "delptr" from the hash table.
|
||||
* "the usual" patch-up process for the app-order doubly-linked-list.
|
||||
* The use of _hd_hh_del below deserves special explanation.
|
||||
* These used to be expressed using (delptr) but that led to a bug
|
||||
* if someone used the same symbol for the head and deletee, like
|
||||
* HASH_DELETE(hh,users,users);
|
||||
* We want that to work, but by changing the head (users) below
|
||||
* we were forfeiting our ability to further refer to the deletee (users)
|
||||
* in the patch-up process. Solution: use scratch space to
|
||||
* copy the deletee pointer, then the latter references are via that
|
||||
* scratch pointer rather than through the repointed (users) symbol.
|
||||
*/
|
||||
#define HASH_DELETE(hh,head,delptr) \
|
||||
do { \
|
||||
struct UT_hash_handle *_hd_hh_del; \
|
||||
if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
|
||||
uthash_free((head)->hh.tbl->buckets, \
|
||||
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
|
||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
||||
head = NULL; \
|
||||
} else { \
|
||||
unsigned _hd_bkt; \
|
||||
_hd_hh_del = &((delptr)->hh); \
|
||||
if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
|
||||
(head)->hh.tbl->tail = \
|
||||
(UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
|
||||
(head)->hh.tbl->hho); \
|
||||
} \
|
||||
if ((delptr)->hh.prev != NULL) { \
|
||||
((UT_hash_handle*)((ptrdiff_t)((delptr)->hh.prev) + \
|
||||
(head)->hh.tbl->hho))->next = (delptr)->hh.next; \
|
||||
} else { \
|
||||
DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
|
||||
} \
|
||||
if (_hd_hh_del->next != NULL) { \
|
||||
((UT_hash_handle*)((ptrdiff_t)_hd_hh_del->next + \
|
||||
(head)->hh.tbl->hho))->prev = \
|
||||
_hd_hh_del->prev; \
|
||||
} \
|
||||
HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
|
||||
HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
|
||||
(head)->hh.tbl->num_items--; \
|
||||
} \
|
||||
HASH_FSCK(hh,head); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
|
||||
#define HASH_FIND_STR(head,findstr,out) \
|
||||
HASH_FIND(hh,head,findstr,(unsigned)strlen(findstr),out)
|
||||
#define HASH_ADD_STR(head,strfield,add) \
|
||||
HASH_ADD(hh,head,strfield[0],(unsigned int)strlen(add->strfield),add)
|
||||
#define HASH_REPLACE_STR(head,strfield,add,replaced) \
|
||||
HASH_REPLACE(hh,head,strfield[0],(unsigned)strlen(add->strfield),add,replaced)
|
||||
#define HASH_FIND_INT(head,findint,out) \
|
||||
HASH_FIND(hh,head,findint,sizeof(int),out)
|
||||
#define HASH_ADD_INT(head,intfield,add) \
|
||||
HASH_ADD(hh,head,intfield,sizeof(int),add)
|
||||
#define HASH_REPLACE_INT(head,intfield,add,replaced) \
|
||||
HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced)
|
||||
#define HASH_FIND_PTR(head,findptr,out) \
|
||||
HASH_FIND(hh,head,findptr,sizeof(void *),out)
|
||||
#define HASH_ADD_PTR(head,ptrfield,add) \
|
||||
HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
|
||||
#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \
|
||||
HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced)
|
||||
#define HASH_DEL(head,delptr) \
|
||||
HASH_DELETE(hh,head,delptr)
|
||||
|
||||
/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
|
||||
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
|
||||
*/
|
||||
#ifdef HASH_DEBUG
|
||||
#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
|
||||
#define HASH_FSCK(hh,head) \
|
||||
do { \
|
||||
struct UT_hash_handle *_thh; \
|
||||
if (head) { \
|
||||
unsigned _bkt_i; \
|
||||
unsigned _count; \
|
||||
char *_prev; \
|
||||
_count = 0; \
|
||||
for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
|
||||
unsigned _bkt_count = 0; \
|
||||
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
|
||||
_prev = NULL; \
|
||||
while (_thh) { \
|
||||
if (_prev != (char*)(_thh->hh_prev)) { \
|
||||
HASH_OOPS("invalid hh_prev %p, actual %p\n", \
|
||||
_thh->hh_prev, _prev ); \
|
||||
} \
|
||||
_bkt_count++; \
|
||||
_prev = (char*)(_thh); \
|
||||
_thh = _thh->hh_next; \
|
||||
} \
|
||||
_count += _bkt_count; \
|
||||
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
|
||||
HASH_OOPS("invalid bucket count %u, actual %u\n", \
|
||||
(head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
|
||||
} \
|
||||
} \
|
||||
if (_count != (head)->hh.tbl->num_items) { \
|
||||
HASH_OOPS("invalid hh item count %u, actual %u\n", \
|
||||
(head)->hh.tbl->num_items, _count ); \
|
||||
} \
|
||||
/* traverse hh in app order; check next/prev integrity, count */ \
|
||||
_count = 0; \
|
||||
_prev = NULL; \
|
||||
_thh = &(head)->hh; \
|
||||
while (_thh) { \
|
||||
_count++; \
|
||||
if (_prev !=(char*)(_thh->prev)) { \
|
||||
HASH_OOPS("invalid prev %p, actual %p\n", \
|
||||
_thh->prev, _prev ); \
|
||||
} \
|
||||
_prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
|
||||
_thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
|
||||
(head)->hh.tbl->hho) : NULL ); \
|
||||
} \
|
||||
if (_count != (head)->hh.tbl->num_items) { \
|
||||
HASH_OOPS("invalid app item count %u, actual %u\n", \
|
||||
(head)->hh.tbl->num_items, _count ); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define HASH_FSCK(hh,head)
|
||||
#endif
|
||||
|
||||
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
|
||||
* the descriptor to which this macro is defined for tuning the hash function.
|
||||
* The app can #include <unistd.h> to get the prototype for write(2). */
|
||||
#ifdef HASH_EMIT_KEYS
|
||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
|
||||
do { \
|
||||
unsigned _klen = fieldlen; \
|
||||
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
|
||||
write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \
|
||||
} while (0)
|
||||
#else
|
||||
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
|
||||
#endif
|
||||
|
||||
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
|
||||
#ifdef HASH_FUNCTION
|
||||
#define HASH_FCN HASH_FUNCTION
|
||||
#else
|
||||
#define HASH_FCN HASH_JEN
|
||||
#endif
|
||||
|
||||
/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */
|
||||
#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _hb_keylen=(unsigned)keylen; \
|
||||
const unsigned char *_hb_key=(const unsigned char*)(key); \
|
||||
(hashv) = 0; \
|
||||
while (_hb_keylen-- != 0U) { \
|
||||
(hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \
|
||||
} \
|
||||
bkt = (hashv) & (num_bkts-1U); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
|
||||
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
|
||||
#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _sx_i; \
|
||||
const unsigned char *_hs_key=(const unsigned char*)(key); \
|
||||
hashv = 0; \
|
||||
for(_sx_i=0; _sx_i < keylen; _sx_i++) { \
|
||||
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
|
||||
} \
|
||||
bkt = hashv & (num_bkts-1U); \
|
||||
} while (0)
|
||||
/* FNV-1a variation */
|
||||
#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _fn_i; \
|
||||
const unsigned char *_hf_key=(const unsigned char*)(key); \
|
||||
hashv = 2166136261U; \
|
||||
for(_fn_i=0; _fn_i < keylen; _fn_i++) { \
|
||||
hashv = hashv ^ _hf_key[_fn_i]; \
|
||||
hashv = hashv * 16777619U; \
|
||||
} \
|
||||
bkt = hashv & (num_bkts-1U); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _ho_i; \
|
||||
const unsigned char *_ho_key=(const unsigned char*)(key); \
|
||||
hashv = 0; \
|
||||
for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
|
||||
hashv += _ho_key[_ho_i]; \
|
||||
hashv += (hashv << 10); \
|
||||
hashv ^= (hashv >> 6); \
|
||||
} \
|
||||
hashv += (hashv << 3); \
|
||||
hashv ^= (hashv >> 11); \
|
||||
hashv += (hashv << 15); \
|
||||
bkt = hashv & (num_bkts-1U); \
|
||||
} while(0)
|
||||
|
||||
#define HASH_JEN_MIX(a,b,c) \
|
||||
do { \
|
||||
a -= b; a -= c; a ^= ( c >> 13 ); \
|
||||
b -= c; b -= a; b ^= ( a << 8 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 13 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 12 ); \
|
||||
b -= c; b -= a; b ^= ( a << 16 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 5 ); \
|
||||
a -= b; a -= c; a ^= ( c >> 3 ); \
|
||||
b -= c; b -= a; b ^= ( a << 10 ); \
|
||||
c -= a; c -= b; c ^= ( b >> 15 ); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned _hj_i,_hj_j,_hj_k; \
|
||||
unsigned const char *_hj_key=(unsigned const char*)(key); \
|
||||
hashv = 0xfeedbeefu; \
|
||||
_hj_i = _hj_j = 0x9e3779b9u; \
|
||||
_hj_k = (unsigned)(keylen); \
|
||||
while (_hj_k >= 12U) { \
|
||||
_hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[2] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[3] << 24 ) ); \
|
||||
_hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[6] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[7] << 24 ) ); \
|
||||
hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
|
||||
+ ( (unsigned)_hj_key[10] << 16 ) \
|
||||
+ ( (unsigned)_hj_key[11] << 24 ) ); \
|
||||
\
|
||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||
\
|
||||
_hj_key += 12; \
|
||||
_hj_k -= 12U; \
|
||||
} \
|
||||
hashv += (unsigned)(keylen); \
|
||||
switch ( _hj_k ) { \
|
||||
case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \
|
||||
case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \
|
||||
case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \
|
||||
case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \
|
||||
case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \
|
||||
case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \
|
||||
case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \
|
||||
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \
|
||||
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \
|
||||
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \
|
||||
case 1: _hj_i += _hj_key[0]; \
|
||||
} \
|
||||
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
|
||||
bkt = hashv & (num_bkts-1U); \
|
||||
} while(0)
|
||||
|
||||
/* The Paul Hsieh hash function */
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
||||
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
unsigned const char *_sfh_key=(unsigned const char*)(key); \
|
||||
uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \
|
||||
\
|
||||
unsigned _sfh_rem = _sfh_len & 3U; \
|
||||
_sfh_len >>= 2; \
|
||||
hashv = 0xcafebabeu; \
|
||||
\
|
||||
/* Main loop */ \
|
||||
for (;_sfh_len > 0U; _sfh_len--) { \
|
||||
hashv += get16bits (_sfh_key); \
|
||||
_sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \
|
||||
hashv = (hashv << 16) ^ _sfh_tmp; \
|
||||
_sfh_key += 2U*sizeof (uint16_t); \
|
||||
hashv += hashv >> 11; \
|
||||
} \
|
||||
\
|
||||
/* Handle end cases */ \
|
||||
switch (_sfh_rem) { \
|
||||
case 3: hashv += get16bits (_sfh_key); \
|
||||
hashv ^= hashv << 16; \
|
||||
hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \
|
||||
hashv += hashv >> 11; \
|
||||
break; \
|
||||
case 2: hashv += get16bits (_sfh_key); \
|
||||
hashv ^= hashv << 11; \
|
||||
hashv += hashv >> 17; \
|
||||
break; \
|
||||
case 1: hashv += *_sfh_key; \
|
||||
hashv ^= hashv << 10; \
|
||||
hashv += hashv >> 1; \
|
||||
} \
|
||||
\
|
||||
/* Force "avalanching" of final 127 bits */ \
|
||||
hashv ^= hashv << 3; \
|
||||
hashv += hashv >> 5; \
|
||||
hashv ^= hashv << 4; \
|
||||
hashv += hashv >> 17; \
|
||||
hashv ^= hashv << 25; \
|
||||
hashv += hashv >> 6; \
|
||||
bkt = hashv & (num_bkts-1U); \
|
||||
} while(0)
|
||||
|
||||
#ifdef HASH_USING_NO_STRICT_ALIASING
|
||||
/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
|
||||
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
|
||||
* MurmurHash uses the faster approach only on CPU's where we know it's safe.
|
||||
*
|
||||
* Note the preprocessor built-in defines can be emitted using:
|
||||
*
|
||||
* gcc -m64 -dM -E - < /dev/null (on gcc)
|
||||
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
|
||||
*/
|
||||
#if (defined(__i386__) || defined(__x86_64__) || defined(_M_IX86))
|
||||
#define MUR_GETBLOCK(p,i) p[i]
|
||||
#else /* non intel */
|
||||
#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 3UL) == 0UL)
|
||||
#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 3UL) == 1UL)
|
||||
#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL)
|
||||
#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL)
|
||||
#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
|
||||
#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
|
||||
#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
|
||||
#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
|
||||
#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
|
||||
#else /* assume little endian non-intel */
|
||||
#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
|
||||
#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
|
||||
#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
|
||||
#endif
|
||||
#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
|
||||
(MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
|
||||
(MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
|
||||
MUR_ONE_THREE(p))))
|
||||
#endif
|
||||
#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
|
||||
#define MUR_FMIX(_h) \
|
||||
do { \
|
||||
_h ^= _h >> 16; \
|
||||
_h *= 0x85ebca6bu; \
|
||||
_h ^= _h >> 13; \
|
||||
_h *= 0xc2b2ae35u; \
|
||||
_h ^= _h >> 16; \
|
||||
} while(0)
|
||||
|
||||
#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \
|
||||
do { \
|
||||
const uint8_t *_mur_data = (const uint8_t*)(key); \
|
||||
const int _mur_nblocks = (int)(keylen) / 4; \
|
||||
uint32_t _mur_h1 = 0xf88D5353u; \
|
||||
uint32_t _mur_c1 = 0xcc9e2d51u; \
|
||||
uint32_t _mur_c2 = 0x1b873593u; \
|
||||
uint32_t _mur_k1 = 0; \
|
||||
const uint8_t *_mur_tail; \
|
||||
const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+(_mur_nblocks*4)); \
|
||||
int _mur_i; \
|
||||
for(_mur_i = -_mur_nblocks; _mur_i!=0; _mur_i++) { \
|
||||
_mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
|
||||
_mur_k1 *= _mur_c1; \
|
||||
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
|
||||
_mur_k1 *= _mur_c2; \
|
||||
\
|
||||
_mur_h1 ^= _mur_k1; \
|
||||
_mur_h1 = MUR_ROTL32(_mur_h1,13); \
|
||||
_mur_h1 = (_mur_h1*5U) + 0xe6546b64u; \
|
||||
} \
|
||||
_mur_tail = (const uint8_t*)(_mur_data + (_mur_nblocks*4)); \
|
||||
_mur_k1=0; \
|
||||
switch((keylen) & 3U) { \
|
||||
case 3: _mur_k1 ^= (uint32_t)_mur_tail[2] << 16; /* FALLTHROUGH */ \
|
||||
case 2: _mur_k1 ^= (uint32_t)_mur_tail[1] << 8; /* FALLTHROUGH */ \
|
||||
case 1: _mur_k1 ^= (uint32_t)_mur_tail[0]; \
|
||||
_mur_k1 *= _mur_c1; \
|
||||
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
|
||||
_mur_k1 *= _mur_c2; \
|
||||
_mur_h1 ^= _mur_k1; \
|
||||
} \
|
||||
_mur_h1 ^= (uint32_t)(keylen); \
|
||||
MUR_FMIX(_mur_h1); \
|
||||
hashv = _mur_h1; \
|
||||
bkt = hashv & (num_bkts-1U); \
|
||||
} while(0)
|
||||
#endif /* HASH_USING_NO_STRICT_ALIASING */
|
||||
|
||||
/* key comparison function; return 0 if keys equal */
|
||||
#define HASH_KEYCMP(a,b,len) memcmp(a,b,(unsigned long)(len))
|
||||
|
||||
/* iterate over items in a known bucket to find desired item */
|
||||
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
|
||||
do { \
|
||||
if (head.hh_head != NULL) { DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); } \
|
||||
else { out=NULL; } \
|
||||
while (out != NULL) { \
|
||||
if ((out)->hh.keylen == (keylen_in)) { \
|
||||
if ((HASH_KEYCMP((out)->hh.key,keyptr,keylen_in)) == 0) { break; } \
|
||||
} \
|
||||
if ((out)->hh.hh_next != NULL) { DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,(out)->hh.hh_next)); } \
|
||||
else { out = NULL; } \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* add an item to a bucket */
|
||||
#define HASH_ADD_TO_BKT(head,addhh) \
|
||||
do { \
|
||||
head.count++; \
|
||||
(addhh)->hh_next = head.hh_head; \
|
||||
(addhh)->hh_prev = NULL; \
|
||||
if (head.hh_head != NULL) { (head).hh_head->hh_prev = (addhh); } \
|
||||
(head).hh_head=addhh; \
|
||||
if ((head.count >= ((head.expand_mult+1U) * HASH_BKT_CAPACITY_THRESH)) \
|
||||
&& ((addhh)->tbl->noexpand != 1U)) { \
|
||||
HASH_EXPAND_BUCKETS((addhh)->tbl); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* remove an item from a given bucket */
|
||||
#define HASH_DEL_IN_BKT(hh,head,hh_del) \
|
||||
(head).count--; \
|
||||
if ((head).hh_head == hh_del) { \
|
||||
(head).hh_head = hh_del->hh_next; \
|
||||
} \
|
||||
if (hh_del->hh_prev) { \
|
||||
hh_del->hh_prev->hh_next = hh_del->hh_next; \
|
||||
} \
|
||||
if (hh_del->hh_next) { \
|
||||
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
|
||||
}
|
||||
|
||||
/* Bucket expansion has the effect of doubling the number of buckets
|
||||
* and redistributing the items into the new buckets. Ideally the
|
||||
* items will distribute more or less evenly into the new buckets
|
||||
* (the extent to which this is true is a measure of the quality of
|
||||
* the hash function as it applies to the key domain).
|
||||
*
|
||||
* With the items distributed into more buckets, the chain length
|
||||
* (item count) in each bucket is reduced. Thus by expanding buckets
|
||||
* the hash keeps a bound on the chain length. This bounded chain
|
||||
* length is the essence of how a hash provides constant time lookup.
|
||||
*
|
||||
* The calculation of tbl->ideal_chain_maxlen below deserves some
|
||||
* explanation. First, keep in mind that we're calculating the ideal
|
||||
* maximum chain length based on the *new* (doubled) bucket count.
|
||||
* In fractions this is just n/b (n=number of items,b=new num buckets).
|
||||
* Since the ideal chain length is an integer, we want to calculate
|
||||
* ceil(n/b). We don't depend on floating point arithmetic in this
|
||||
* hash, so to calculate ceil(n/b) with integers we could write
|
||||
*
|
||||
* ceil(n/b) = (n/b) + ((n%b)?1:0)
|
||||
*
|
||||
* and in fact a previous version of this hash did just that.
|
||||
* But now we have improved things a bit by recognizing that b is
|
||||
* always a power of two. We keep its base 2 log handy (call it lb),
|
||||
* so now we can write this with a bit shift and logical AND:
|
||||
*
|
||||
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
|
||||
*
|
||||
*/
|
||||
#define HASH_EXPAND_BUCKETS(tbl) \
|
||||
do { \
|
||||
unsigned _he_bkt; \
|
||||
unsigned _he_bkt_i; \
|
||||
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
|
||||
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
|
||||
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
|
||||
2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
|
||||
memset(_he_new_buckets, 0, \
|
||||
2UL * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
|
||||
tbl->ideal_chain_maxlen = \
|
||||
(tbl->num_items >> (tbl->log2_num_buckets+1U)) + \
|
||||
(((tbl->num_items & ((tbl->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \
|
||||
tbl->nonideal_items = 0; \
|
||||
for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
|
||||
{ \
|
||||
_he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
|
||||
while (_he_thh != NULL) { \
|
||||
_he_hh_nxt = _he_thh->hh_next; \
|
||||
HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2U, _he_bkt); \
|
||||
_he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
|
||||
if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
|
||||
tbl->nonideal_items++; \
|
||||
_he_newbkt->expand_mult = _he_newbkt->count / \
|
||||
tbl->ideal_chain_maxlen; \
|
||||
} \
|
||||
_he_thh->hh_prev = NULL; \
|
||||
_he_thh->hh_next = _he_newbkt->hh_head; \
|
||||
if (_he_newbkt->hh_head != NULL) { _he_newbkt->hh_head->hh_prev = \
|
||||
_he_thh; } \
|
||||
_he_newbkt->hh_head = _he_thh; \
|
||||
_he_thh = _he_hh_nxt; \
|
||||
} \
|
||||
} \
|
||||
uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
|
||||
tbl->num_buckets *= 2U; \
|
||||
tbl->log2_num_buckets++; \
|
||||
tbl->buckets = _he_new_buckets; \
|
||||
tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
|
||||
(tbl->ineff_expands+1U) : 0U; \
|
||||
if (tbl->ineff_expands > 1U) { \
|
||||
tbl->noexpand=1; \
|
||||
uthash_noexpand_fyi(tbl); \
|
||||
} \
|
||||
uthash_expand_fyi(tbl); \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
|
||||
/* Note that HASH_SORT assumes the hash handle name to be hh.
|
||||
* HASH_SRT was added to allow the hash handle name to be passed in. */
|
||||
#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
|
||||
#define HASH_SRT(hh,head,cmpfcn) \
|
||||
do { \
|
||||
unsigned _hs_i; \
|
||||
unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
|
||||
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
|
||||
if (head != NULL) { \
|
||||
_hs_insize = 1; \
|
||||
_hs_looping = 1; \
|
||||
_hs_list = &((head)->hh); \
|
||||
while (_hs_looping != 0U) { \
|
||||
_hs_p = _hs_list; \
|
||||
_hs_list = NULL; \
|
||||
_hs_tail = NULL; \
|
||||
_hs_nmerges = 0; \
|
||||
while (_hs_p != NULL) { \
|
||||
_hs_nmerges++; \
|
||||
_hs_q = _hs_p; \
|
||||
_hs_psize = 0; \
|
||||
for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
|
||||
_hs_psize++; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
if (! (_hs_q) ) { break; } \
|
||||
} \
|
||||
_hs_qsize = _hs_insize; \
|
||||
while ((_hs_psize > 0U) || ((_hs_qsize > 0U) && (_hs_q != NULL))) {\
|
||||
if (_hs_psize == 0U) { \
|
||||
_hs_e = _hs_q; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_qsize--; \
|
||||
} else if ( (_hs_qsize == 0U) || (_hs_q == NULL) ) { \
|
||||
_hs_e = _hs_p; \
|
||||
if (_hs_p != NULL){ \
|
||||
_hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \
|
||||
((void*)((char*)(_hs_p->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
} \
|
||||
_hs_psize--; \
|
||||
} else if (( \
|
||||
cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
|
||||
DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
|
||||
) <= 0) { \
|
||||
_hs_e = _hs_p; \
|
||||
if (_hs_p != NULL){ \
|
||||
_hs_p = (UT_hash_handle*)((_hs_p->next != NULL) ? \
|
||||
((void*)((char*)(_hs_p->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
} \
|
||||
_hs_psize--; \
|
||||
} else { \
|
||||
_hs_e = _hs_q; \
|
||||
_hs_q = (UT_hash_handle*)((_hs_q->next != NULL) ? \
|
||||
((void*)((char*)(_hs_q->next) + \
|
||||
(head)->hh.tbl->hho)) : NULL); \
|
||||
_hs_qsize--; \
|
||||
} \
|
||||
if ( _hs_tail != NULL ) { \
|
||||
_hs_tail->next = ((_hs_e != NULL) ? \
|
||||
ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
|
||||
} else { \
|
||||
_hs_list = _hs_e; \
|
||||
} \
|
||||
if (_hs_e != NULL) { \
|
||||
_hs_e->prev = ((_hs_tail != NULL) ? \
|
||||
ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
|
||||
} \
|
||||
_hs_tail = _hs_e; \
|
||||
} \
|
||||
_hs_p = _hs_q; \
|
||||
} \
|
||||
if (_hs_tail != NULL){ \
|
||||
_hs_tail->next = NULL; \
|
||||
} \
|
||||
if ( _hs_nmerges <= 1U ) { \
|
||||
_hs_looping=0; \
|
||||
(head)->hh.tbl->tail = _hs_tail; \
|
||||
DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
|
||||
} \
|
||||
_hs_insize *= 2U; \
|
||||
} \
|
||||
HASH_FSCK(hh,head); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* This function selects items from one hash into another hash.
|
||||
* The end result is that the selected items have dual presence
|
||||
* in both hashes. There is no copy of the items made; rather
|
||||
* they are added into the new hash through a secondary hash
|
||||
* hash handle that must be present in the structure. */
|
||||
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
|
||||
do { \
|
||||
unsigned _src_bkt, _dst_bkt; \
|
||||
void *_last_elt=NULL, *_elt; \
|
||||
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
|
||||
ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
|
||||
if (src != NULL) { \
|
||||
for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
|
||||
for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
|
||||
_src_hh != NULL; \
|
||||
_src_hh = _src_hh->hh_next) { \
|
||||
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
|
||||
if (cond(_elt)) { \
|
||||
_dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
|
||||
_dst_hh->key = _src_hh->key; \
|
||||
_dst_hh->keylen = _src_hh->keylen; \
|
||||
_dst_hh->hashv = _src_hh->hashv; \
|
||||
_dst_hh->prev = _last_elt; \
|
||||
_dst_hh->next = NULL; \
|
||||
if (_last_elt_hh != NULL) { _last_elt_hh->next = _elt; } \
|
||||
if (dst == NULL) { \
|
||||
DECLTYPE_ASSIGN(dst,_elt); \
|
||||
HASH_MAKE_TABLE(hh_dst,dst); \
|
||||
} else { \
|
||||
_dst_hh->tbl = (dst)->hh_dst.tbl; \
|
||||
} \
|
||||
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
|
||||
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
|
||||
(dst)->hh_dst.tbl->num_items++; \
|
||||
_last_elt = _elt; \
|
||||
_last_elt_hh = _dst_hh; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
HASH_FSCK(hh_dst,dst); \
|
||||
} while (0)
|
||||
|
||||
#define HASH_CLEAR(hh,head) \
|
||||
do { \
|
||||
if (head != NULL) { \
|
||||
uthash_free((head)->hh.tbl->buckets, \
|
||||
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
|
||||
HASH_BLOOM_FREE((head)->hh.tbl); \
|
||||
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
|
||||
(head)=NULL; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define HASH_OVERHEAD(hh,head) \
|
||||
((head != NULL) ? ( \
|
||||
(size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \
|
||||
((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \
|
||||
sizeof(UT_hash_table) + \
|
||||
(HASH_BLOOM_BYTELEN))) : 0U)
|
||||
|
||||
#ifdef NO_DECLTYPE
|
||||
#define HASH_ITER(hh,head,el,tmp) \
|
||||
for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \
|
||||
(el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL)))
|
||||
#else
|
||||
#define HASH_ITER(hh,head,el,tmp) \
|
||||
for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \
|
||||
(el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL)))
|
||||
#endif
|
||||
|
||||
/* obtain a count of items in the hash */
|
||||
#define HASH_COUNT(head) HASH_CNT(hh,head)
|
||||
#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U)
|
||||
|
||||
typedef struct UT_hash_bucket {
|
||||
struct UT_hash_handle *hh_head;
|
||||
unsigned count;
|
||||
|
||||
/* expand_mult is normally set to 0. In this situation, the max chain length
|
||||
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
|
||||
* the bucket's chain exceeds this length, bucket expansion is triggered).
|
||||
* However, setting expand_mult to a non-zero value delays bucket expansion
|
||||
* (that would be triggered by additions to this particular bucket)
|
||||
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
|
||||
* (The multiplier is simply expand_mult+1). The whole idea of this
|
||||
* multiplier is to reduce bucket expansions, since they are expensive, in
|
||||
* situations where we know that a particular bucket tends to be overused.
|
||||
* It is better to let its chain length grow to a longer yet-still-bounded
|
||||
* value, than to do an O(n) bucket expansion too often.
|
||||
*/
|
||||
unsigned expand_mult;
|
||||
|
||||
} UT_hash_bucket;
|
||||
|
||||
/* random signature used only to find hash tables in external analysis */
|
||||
#define HASH_SIGNATURE 0xa0111fe1u
|
||||
#define HASH_BLOOM_SIGNATURE 0xb12220f2u
|
||||
|
||||
typedef struct UT_hash_table {
|
||||
UT_hash_bucket *buckets;
|
||||
unsigned num_buckets, log2_num_buckets;
|
||||
unsigned num_items;
|
||||
struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
|
||||
ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
|
||||
|
||||
/* in an ideal situation (all buckets used equally), no bucket would have
|
||||
* more than ceil(#items/#buckets) items. that's the ideal chain length. */
|
||||
unsigned ideal_chain_maxlen;
|
||||
|
||||
/* nonideal_items is the number of items in the hash whose chain position
|
||||
* exceeds the ideal chain maxlen. these items pay the penalty for an uneven
|
||||
* hash distribution; reaching them in a chain traversal takes >ideal steps */
|
||||
unsigned nonideal_items;
|
||||
|
||||
/* ineffective expands occur when a bucket doubling was performed, but
|
||||
* afterward, more than half the items in the hash had nonideal chain
|
||||
* positions. If this happens on two consecutive expansions we inhibit any
|
||||
* further expansion, as it's not helping; this happens when the hash
|
||||
* function isn't a good fit for the key domain. When expansion is inhibited
|
||||
* the hash will still work, albeit no longer in constant time. */
|
||||
unsigned ineff_expands, noexpand;
|
||||
|
||||
uint32_t signature; /* used only to find hash tables in external analysis */
|
||||
#ifdef HASH_BLOOM
|
||||
uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
|
||||
uint8_t *bloom_bv;
|
||||
uint8_t bloom_nbits;
|
||||
#endif
|
||||
|
||||
} UT_hash_table;
|
||||
|
||||
typedef struct UT_hash_handle {
|
||||
struct UT_hash_table *tbl;
|
||||
void *prev; /* prev element in app order */
|
||||
void *next; /* next element in app order */
|
||||
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
|
||||
struct UT_hash_handle *hh_next; /* next hh in bucket order */
|
||||
void *key; /* ptr to enclosing struct's key */
|
||||
unsigned keylen; /* enclosing struct's key len */
|
||||
unsigned hashv; /* result of hash-fcn(key) */
|
||||
} UT_hash_handle;
|
||||
|
||||
#endif /* UTHASH_H */
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
x
Ссылка в новой задаче
Block a user