1
1

Merge pull request #3302 from ggouaillardet/poc/hwloc2

POC: add support for hwloc v2
Этот коммит содержится в:
Ralph Castain 2017-07-20 07:57:13 -05:00 коммит произвёл GitHub
родитель fca68b070b 593e4ce63f
Коммит 7c6bd7d48d
174 изменённых файлов: 50250 добавлений и 391 удалений

Просмотреть файл

@ -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 поставляемый
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -0,0 +1 @@
hwloc

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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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 Обычный файл
Просмотреть файл

@ -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 Исполняемый файл
Просмотреть файл

@ -0,0 +1,2 @@
:
autoreconf ${autoreconf_args:-"-ivf"}

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

Просмотреть файл

@ -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 Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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])
])

Просмотреть файл

@ -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
])

Просмотреть файл

@ -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])
])

Просмотреть файл

@ -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
])

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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

Просмотреть файл

@ -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
}

Просмотреть файл

@ -0,0 +1,2 @@
# This is a dummy file that is not needed in embedded mode,
# but sadly, automake *requires* it

Просмотреть файл

@ -0,0 +1,2 @@
# This is a dummy file that is not needed in embedded mode,
# but sadly, automake *requires* it

Просмотреть файл

@ -0,0 +1,2 @@
# This is a dummy file that is not needed in embedded mode,
# but sadly, automake *requires* it

Просмотреть файл

@ -0,0 +1,2 @@
# This is a dummy file that is not needed in embedded mode,
# but sadly, automake *requires* it

Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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@

Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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 */
}

Просмотреть файл

@ -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 Обычный файл
Просмотреть файл

@ -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", &current, &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 Обычный файл
Просмотреть файл

@ -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 */
}

Просмотреть файл

@ -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";
}

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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

Просмотреть файл

@ -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
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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
};

Просмотреть файл

@ -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, "&#10;"); replen=5; break;
case '\r': strcpy(dst, "&#13;"); replen=5; break;
case '\t': strcpy(dst, "&#9;"); replen=4; break;
case '\"': strcpy(dst, "&quot;"); replen=6; break;
case '<': strcpy(dst, "&lt;"); replen=4; break;
case '>': strcpy(dst, "&gt;"); replen=4; break;
case '&': strcpy(dst, "&amp;"); 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
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

3684
opal/mca/hwloc/hwloc2x/hwloc/hwloc/topology.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;
}

Просмотреть файл

@ -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 Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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_

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше