Коммит
f39ce67982
3
.gitignore
поставляемый
3
.gitignore
поставляемый
@ -303,9 +303,7 @@ opal/mca/event/libevent*/libevent/libevent_pthreads.pc
|
||||
opal/mca/event/libevent*/libevent/include/event2/event-config.h
|
||||
|
||||
opal/mca/hwloc/hwloc*/hwloc/include/hwloc/autogen/config.h
|
||||
opal/mca/hwloc/hwloc*/hwloc/include/hwloc/autogen/config.h.in
|
||||
opal/mca/hwloc/hwloc*/hwloc/include/private/autogen/config.h
|
||||
opal/mca/hwloc/hwloc*/hwloc/include/private/autogen/config.h.in
|
||||
opal/mca/hwloc/base/static-components.h.new.extern
|
||||
opal/mca/hwloc/base/static-components.h.new.struct
|
||||
|
||||
@ -362,6 +360,7 @@ orte/test/mpi/accept
|
||||
orte/test/mpi/attach
|
||||
orte/test/mpi/bad_exit
|
||||
orte/test/mpi/bcast_loop
|
||||
orte/test/mpi/binding
|
||||
orte/test/mpi/concurrent_spawn
|
||||
orte/test/mpi/connect
|
||||
orte/test/mpi/crisscross
|
||||
|
@ -16,6 +16,7 @@
|
||||
* Copyright (c) 2017 The University of Tennessee and The University
|
||||
* of Tennessee Research Foundation. All rights
|
||||
* reserved.
|
||||
* Copyright (c) 2017 Intel, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -242,10 +243,6 @@ int ompi_osc_rdma_post_atomic (ompi_group_t *group, int assert, ompi_win_t *win)
|
||||
return OMPI_SUCCESS;
|
||||
}
|
||||
|
||||
if (OPAL_UNLIKELY(OMPI_SUCCESS != ret)) {
|
||||
return OMPI_ERR_OUT_OF_RESOURCE;
|
||||
}
|
||||
|
||||
/* translate group ranks into the communicator */
|
||||
peers = ompi_osc_rdma_get_peers (module, module->pw_group);
|
||||
if (OPAL_UNLIKELY(NULL == peers)) {
|
||||
@ -281,7 +278,7 @@ int ompi_osc_rdma_post_atomic (ompi_group_t *group, int assert, ompi_win_t *win)
|
||||
do {
|
||||
ompi_osc_rdma_lock_t result;
|
||||
|
||||
OSC_RDMA_VERBOSE(MCA_BASE_VERBOSE_TRACE, "attempting to post to index %d @ rank %d", post_index, peer->rank);
|
||||
OSC_RDMA_VERBOSE(MCA_BASE_VERBOSE_TRACE, "attempting to post to index %d @ rank %d", (int)post_index, peer->rank);
|
||||
|
||||
/* try to post. if the value isn't 0 then another rank is occupying this index */
|
||||
if (!ompi_osc_rdma_peer_local_state (peer)) {
|
||||
|
@ -18,7 +18,7 @@
|
||||
* Copyright (c) 2009-2012 Oracle and/or its affiliates. All rights reserved.
|
||||
* 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) 2013-2017 Intel, Inc. All rights reserved.
|
||||
* Copyright (c) 2014-2017 Research Organization for Information Science
|
||||
* and Technology (RIST). All rights reserved.
|
||||
* Copyright (c) 2014 Bull SAS. All rights reserved.
|
||||
@ -2330,34 +2330,43 @@ static float get_ib_dev_distance(struct ibv_device *dev)
|
||||
/* If we don't have hwloc, we'll default to a distance of 0,
|
||||
because we have no way of measuring. */
|
||||
float distance = 0;
|
||||
float a, b;
|
||||
int i;
|
||||
hwloc_cpuset_t my_cpuset = NULL, ibv_cpuset = NULL;
|
||||
hwloc_obj_t my_obj, ibv_obj, node_obj;
|
||||
struct hwloc_distances_s *hwloc_distances = NULL;
|
||||
|
||||
#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()) {
|
||||
return distance;
|
||||
}
|
||||
|
||||
float a, b;
|
||||
int i;
|
||||
hwloc_cpuset_t my_cpuset = NULL, ibv_cpuset = NULL;
|
||||
hwloc_obj_t my_obj, ibv_obj, node_obj;
|
||||
|
||||
/* Note that this struct is owned by hwloc; there's no need to
|
||||
free it at the end of time */
|
||||
static const struct hwloc_distances_s *hwloc_distances = NULL;
|
||||
#if HWLOC_API_VERSION >= 0x20000
|
||||
unsigned int j, distances_nr = 1;
|
||||
int ibvindex, myindex;
|
||||
#endif
|
||||
|
||||
if (NULL == hwloc_distances) {
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
hwloc_distances =
|
||||
hwloc_get_whole_distance_matrix_by_type(opal_hwloc_topology,
|
||||
HWLOC_OBJ_NODE);
|
||||
}
|
||||
|
||||
/* If we got no info, just return 0 */
|
||||
if (NULL == hwloc_distances || NULL == hwloc_distances->latency) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
#else
|
||||
if (0 != hwloc_distances_get_by_type(opal_hwloc_topology, HWLOC_OBJ_NODE,
|
||||
&distances_nr, &hwloc_distances,
|
||||
HWLOC_DISTANCES_KIND_MEANS_LATENCY, 0) || 0 == distances_nr) {
|
||||
hwloc_distances = NULL;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Next, find the NUMA node where this IBV device is located */
|
||||
ibv_cpuset = hwloc_bitmap_alloc();
|
||||
if (NULL == ibv_cpuset) {
|
||||
@ -2373,16 +2382,31 @@ static float get_ib_dev_distance(struct ibv_device *dev)
|
||||
|
||||
opal_output_verbose(5, opal_btl_base_framework.framework_output,
|
||||
"hwloc_distances->nbobjs=%d", hwloc_distances->nbobjs);
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
for (i = 0; i < (int)(2 * hwloc_distances->nbobjs); i++) {
|
||||
opal_output_verbose(5, opal_btl_base_framework.framework_output,
|
||||
"hwloc_distances->latency[%d]=%f", i, hwloc_distances->latency[i]);
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < (int)hwloc_distances->nbobjs; i++) {
|
||||
opal_output_verbose(5, opal_btl_base_framework.framework_output,
|
||||
"hwloc_distances->values[%d]=%"PRIu64, i, hwloc_distances->values[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If ibv_obj is a NUMA node or below, we're good. */
|
||||
switch (ibv_obj->type) {
|
||||
case HWLOC_OBJ_NODE:
|
||||
case HWLOC_OBJ_SOCKET:
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
case HWLOC_OBJ_CACHE:
|
||||
#else
|
||||
case HWLOC_OBJ_L1CACHE:
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
case HWLOC_OBJ_L3CACHE:
|
||||
case HWLOC_OBJ_L4CACHE:
|
||||
case HWLOC_OBJ_L5CACHE:
|
||||
#endif
|
||||
case HWLOC_OBJ_CORE:
|
||||
case HWLOC_OBJ_PU:
|
||||
while (NULL != ibv_obj && ibv_obj->type != HWLOC_OBJ_NODE) {
|
||||
@ -2402,6 +2426,22 @@ static float get_ib_dev_distance(struct ibv_device *dev)
|
||||
if (NULL == ibv_obj) {
|
||||
goto out;
|
||||
}
|
||||
#if HWLOC_API_VERSION >= 0x20000
|
||||
/* the new matrix format isn't quite as friendly, so we have to
|
||||
* do an exhaustive search to find the index of this object
|
||||
* in that array */
|
||||
ibvindex = -1;
|
||||
for (j=0; j < distances_nr; j++) {
|
||||
if (ibv_obj == hwloc_distances->objs[j]) {
|
||||
ibvindex = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (-1 == ibvindex) {
|
||||
OPAL_ERROR_LOG(OPAL_ERR_NOT_FOUND);
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
opal_output_verbose(5, opal_btl_base_framework.framework_output,
|
||||
"ibv_obj->logical_index=%d", ibv_obj->logical_index);
|
||||
@ -2424,7 +2464,15 @@ static float get_ib_dev_distance(struct ibv_device *dev)
|
||||
switch (my_obj->type) {
|
||||
case HWLOC_OBJ_NODE:
|
||||
case HWLOC_OBJ_SOCKET:
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
case HWLOC_OBJ_CACHE:
|
||||
#else
|
||||
case HWLOC_OBJ_L1CACHE:
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
case HWLOC_OBJ_L3CACHE:
|
||||
case HWLOC_OBJ_L4CACHE:
|
||||
case HWLOC_OBJ_L5CACHE:
|
||||
#endif
|
||||
case HWLOC_OBJ_CORE:
|
||||
case HWLOC_OBJ_PU:
|
||||
while (NULL != my_obj && my_obj->type != HWLOC_OBJ_NODE) {
|
||||
@ -2435,12 +2483,31 @@ static float get_ib_dev_distance(struct ibv_device *dev)
|
||||
"my_obj->logical_index=%d", my_obj->logical_index);
|
||||
/* Distance may be asymetrical, so calculate both of them
|
||||
and take the max */
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
a = hwloc_distances->latency[my_obj->logical_index +
|
||||
(ibv_obj->logical_index *
|
||||
hwloc_distances->nbobjs)];
|
||||
b = hwloc_distances->latency[ibv_obj->logical_index +
|
||||
(my_obj->logical_index *
|
||||
hwloc_distances->nbobjs)];
|
||||
#else
|
||||
/* the new matrix format isn't quite as friendly, so we have to
|
||||
* do an exhaustive search to find the index of this object
|
||||
* in that array */
|
||||
myindex = -1;
|
||||
for (j=0; j < distances_nr; j++) {
|
||||
if (my_obj == hwloc_distances->objs[j]) {
|
||||
myindex = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (-1 == myindex) {
|
||||
OPAL_ERROR_LOG(OPAL_ERR_NOT_FOUND);
|
||||
goto out;
|
||||
}
|
||||
a = (float)hwloc_distances->values[myindex + (ibvindex * hwloc_distances->nbobjs)];
|
||||
b = (float)hwloc_distances->values[ibvindex + (myindex * hwloc_distances->nbobjs)];
|
||||
#endif
|
||||
distance = (a > b) ? a : b;
|
||||
}
|
||||
break;
|
||||
@ -2456,13 +2523,28 @@ static float get_ib_dev_distance(struct ibv_device *dev)
|
||||
node_obj = hwloc_get_obj_inside_cpuset_by_type(opal_hwloc_topology,
|
||||
ibv_obj->cpuset,
|
||||
HWLOC_OBJ_NODE, ++i)) {
|
||||
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
a = hwloc_distances->latency[node_obj->logical_index +
|
||||
(ibv_obj->logical_index *
|
||||
hwloc_distances->nbobjs)];
|
||||
b = hwloc_distances->latency[ibv_obj->logical_index +
|
||||
(node_obj->logical_index *
|
||||
hwloc_distances->nbobjs)];
|
||||
#else
|
||||
unsigned int j;
|
||||
j = node_obj->logical_index + (ibv_obj->logical_index * hwloc_distances->nbobjs);
|
||||
if (j < distances_nr) {
|
||||
a = (float)hwloc_distances->values[j];
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
j = ibv_obj->logical_index + (node_obj->logical_index * hwloc_distances->nbobjs);
|
||||
if (j < distances_nr) {
|
||||
b = (float)hwloc_distances->values[j];
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
a = (a > b) ? a : b;
|
||||
distance = (a > distance) ? a : distance;
|
||||
}
|
||||
@ -2476,10 +2558,12 @@ 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
|
||||
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
if (NULL != hwloc_distances) {
|
||||
hwloc_distances_release(opal_hwloc_topology, hwloc_distances);
|
||||
}
|
||||
#endif
|
||||
return distance;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
* All rights reserved.
|
||||
* Copyright (c) 2007-2015 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2006-2007 Voltaire All rights reserved.
|
||||
* Copyright (c) 2014 Intel, Inc. All rights reserved.
|
||||
* Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
|
||||
* Copyright (c) 2015-2016 Research Organization for Information Science
|
||||
* and Technology (RIST). All rights reserved.
|
||||
* Copyright (c) 2015 Mellanox Technologies. All rights reserved.
|
||||
@ -77,8 +77,6 @@ void mca_btl_openib_proc_construct(mca_btl_openib_proc_t* ib_proc)
|
||||
|
||||
void mca_btl_openib_proc_destruct(mca_btl_openib_proc_t* ib_proc)
|
||||
{
|
||||
mca_btl_openib_proc_btlptr_t* elem;
|
||||
|
||||
/* release resources */
|
||||
if(NULL != ib_proc->proc_endpoints) {
|
||||
free(ib_proc->proc_endpoints);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2016 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2016 Intel, Inc. All rights reserved.
|
||||
* Copyright (c) 2016-2017 Intel, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -26,22 +26,34 @@
|
||||
*/
|
||||
static hwloc_obj_t my_numa_node = NULL;
|
||||
static int num_numa_nodes = 0;
|
||||
static const struct hwloc_distances_s *matrix = NULL;
|
||||
static struct hwloc_distances_s *matrix = NULL;
|
||||
#if HWLOC_API_VERSION >= 0x20000
|
||||
static unsigned int matrix_nr = 1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Get the hwloc distance matrix (if we don't already have it).
|
||||
*
|
||||
* Note that the matrix data structure belongs to hwloc; we are not
|
||||
* responsibile for freeing it.
|
||||
*/
|
||||
static int get_distance_matrix(void)
|
||||
{
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
/* Note that the matrix data structure belongs to hwloc; we are not
|
||||
* responsible for freeing it. */
|
||||
|
||||
if (NULL == matrix) {
|
||||
matrix = hwloc_get_whole_distance_matrix_by_type(opal_hwloc_topology,
|
||||
HWLOC_OBJ_NODE);
|
||||
}
|
||||
|
||||
return (NULL == matrix) ? OPAL_ERROR : OPAL_SUCCESS;
|
||||
#else
|
||||
if (0 != hwloc_distances_get_by_type(opal_hwloc_topology, HWLOC_OBJ_NODE,
|
||||
&matrix_nr, &matrix,
|
||||
HWLOC_DISTANCES_KIND_MEANS_LATENCY, 0) || 0 == matrix_nr) {
|
||||
return OPAL_ERROR;
|
||||
}
|
||||
return OPAL_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -219,6 +231,7 @@ int opal_btl_usnic_hwloc_distance(opal_btl_usnic_module_t *module)
|
||||
|
||||
/* Lookup the distance between my NUMA node and the NUMA node of
|
||||
the device */
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
if (NULL != dev_numa) {
|
||||
module->numa_distance =
|
||||
matrix->latency[dev_numa->logical_index * num_numa_nodes +
|
||||
@ -229,6 +242,40 @@ int opal_btl_usnic_hwloc_distance(opal_btl_usnic_module_t *module)
|
||||
module->linux_device_name,
|
||||
module->numa_distance);
|
||||
}
|
||||
#else
|
||||
if (NULL != dev_numa) {
|
||||
int myindex, devindex;
|
||||
unsigned int j;
|
||||
myindex = -1;
|
||||
for (j=0; j < matrix_nr; j++) {
|
||||
if (my_numa_node == matrix->objs[j]) {
|
||||
myindex = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (-1 == myindex) {
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
devindex = -1;
|
||||
for (j=0; j < matrix_nr; j++) {
|
||||
if (dev_numa == matrix->objs[j]) {
|
||||
devindex = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (-1 == devindex) {
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
module->numa_distance =
|
||||
matrix->values[(devindex * num_numa_nodes) + myindex];
|
||||
|
||||
opal_output_verbose(5, USNIC_OUT,
|
||||
"btl:usnic:filter_numa: %s is distance %d from me",
|
||||
module->linux_device_name,
|
||||
module->numa_distance);
|
||||
}
|
||||
#endif
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
@ -35,6 +35,12 @@
|
||||
#ifdef HAVE_ENDIAN_H
|
||||
#include <endian.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#if HAVE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "opal/runtime/opal.h"
|
||||
#include "opal/constants.h"
|
||||
@ -48,6 +54,8 @@
|
||||
#include "opal/mca/hwloc/hwloc-internal.h"
|
||||
#include "opal/mca/hwloc/base/base.h"
|
||||
|
||||
static bool topo_in_shmem = false;
|
||||
|
||||
/*
|
||||
* Provide the hwloc object that corresponds to the given
|
||||
* processor id of the given type. Remember: "processor" here [usually] means "core" --
|
||||
@ -110,7 +118,6 @@ hwloc_obj_t opal_hwloc_base_get_pu(hwloc_topology_t topo,
|
||||
return obj;
|
||||
}
|
||||
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
/* determine the node-level available cpuset based on
|
||||
* online vs allowed vs user-specified cpus
|
||||
*/
|
||||
@ -138,8 +145,12 @@ int opal_hwloc_base_filter_cpus(hwloc_topology_t topo)
|
||||
/* process any specified default cpu set against this topology */
|
||||
if (NULL == opal_hwloc_base_cpu_list) {
|
||||
/* get the root available cpuset */
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
avail = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_and(avail, root->online_cpuset, root->allowed_cpuset);
|
||||
#else
|
||||
avail = hwloc_bitmap_dup(root->allowed_cpuset);
|
||||
#endif
|
||||
OPAL_OUTPUT_VERBOSE((5, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base: no cpus specified - using root available cpuset"));
|
||||
} else {
|
||||
@ -158,7 +169,12 @@ int opal_hwloc_base_filter_cpus(hwloc_topology_t topo)
|
||||
/* 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))) {
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
hwloc_bitmap_and(pucpus, pu->online_cpuset, pu->allowed_cpuset);
|
||||
#else
|
||||
hwloc_bitmap_free(pucpus);
|
||||
pucpus = hwloc_bitmap_dup(pu->allowed_cpuset);
|
||||
#endif
|
||||
hwloc_bitmap_or(res, avail, pucpus);
|
||||
hwloc_bitmap_copy(avail, res);
|
||||
data = (opal_hwloc_obj_data_t*)pu->userdata;
|
||||
@ -175,7 +191,12 @@ int opal_hwloc_base_filter_cpus(hwloc_topology_t topo)
|
||||
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))) {
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
hwloc_bitmap_and(pucpus, pu->online_cpuset, pu->allowed_cpuset);
|
||||
#else
|
||||
hwloc_bitmap_free(pucpus);
|
||||
pucpus = hwloc_bitmap_dup(pu->allowed_cpuset);
|
||||
#endif
|
||||
hwloc_bitmap_or(res, avail, pucpus);
|
||||
hwloc_bitmap_copy(avail, res);
|
||||
data = (opal_hwloc_obj_data_t*)pu->userdata;
|
||||
@ -204,7 +225,6 @@ int opal_hwloc_base_filter_cpus(hwloc_topology_t topo)
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void fill_cache_line_size(void)
|
||||
{
|
||||
@ -251,21 +271,58 @@ int opal_hwloc_base_get_topology(void)
|
||||
int rc;
|
||||
opal_process_name_t wildcard_rank;
|
||||
char *val = NULL;
|
||||
#if HWLOC_API_VERSION >= 0x20000
|
||||
int rc2, rc3, fd;
|
||||
uint64_t addr, *aptr, size, *sptr;
|
||||
char *shmemfile;
|
||||
hwloc_obj_t root;
|
||||
opal_hwloc_topo_data_t *sum;
|
||||
#endif
|
||||
|
||||
OPAL_OUTPUT_VERBOSE((2, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base:get_topology"));
|
||||
|
||||
/* see if we already got it */
|
||||
/* see if we already have it */
|
||||
if (NULL != opal_hwloc_topology) {
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
if (NULL != opal_pmix.get) {
|
||||
/* try to retrieve it from the PMIx store */
|
||||
opal_output_verbose(1, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base instantiating topology");
|
||||
wildcard_rank.jobid = OPAL_PROC_MY_NAME.jobid;
|
||||
wildcard_rank.vpid = OPAL_VPID_WILDCARD;
|
||||
|
||||
if (NULL != opal_pmix.get) {
|
||||
#if HWLOC_API_VERSION >= 0x20000
|
||||
OPAL_OUTPUT_VERBOSE((2, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base: looking for topology in shared memory"));
|
||||
|
||||
/* first try to get the shmem link, if available */
|
||||
aptr = &addr;
|
||||
sptr = &size;
|
||||
OPAL_MODEX_RECV_VALUE_OPTIONAL(rc, OPAL_PMIX_HWLOC_SHMEM_FILE,
|
||||
&wildcard_rank, (void**)&shmemfile, OPAL_STRING);
|
||||
OPAL_MODEX_RECV_VALUE_OPTIONAL(rc2, OPAL_PMIX_HWLOC_SHMEM_ADDR,
|
||||
&wildcard_rank, (void**)&aptr, OPAL_SIZE);
|
||||
OPAL_MODEX_RECV_VALUE_OPTIONAL(rc3, OPAL_PMIX_HWLOC_SHMEM_SIZE,
|
||||
&wildcard_rank, (void**)&sptr, OPAL_SIZE);
|
||||
if (OPAL_SUCCESS == rc && OPAL_SUCCESS == rc2 && OPAL_SUCCESS == rc3) {
|
||||
if (0 > (fd = open(shmemfile, O_RDONLY))) {
|
||||
free(shmemfile);
|
||||
return OPAL_ERROR;
|
||||
}
|
||||
free(shmemfile);
|
||||
if (0 != hwloc_shmem_topology_adopt(&opal_hwloc_topology, fd,
|
||||
0, (void*)addr, size, 0)) {
|
||||
return OPAL_ERROR;
|
||||
}
|
||||
OPAL_OUTPUT_VERBOSE((2, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base: topology in shared memory"));
|
||||
topo_in_shmem = true;
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
/* if that isn't available, then try to retrieve
|
||||
* the xml representation from the PMIx data store */
|
||||
opal_output_verbose(1, opal_hwloc_base_framework.framework_output,
|
||||
"hwloc:base instantiating topology");
|
||||
OPAL_MODEX_RECV_VALUE_OPTIONAL(rc, OPAL_PMIX_LOCAL_TOPO,
|
||||
&wildcard_rank, &val, OPAL_STRING);
|
||||
} else {
|
||||
@ -300,26 +357,22 @@ int opal_hwloc_base_get_topology(void)
|
||||
return OPAL_ERROR;
|
||||
}
|
||||
free(val);
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
/* 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;
|
||||
}
|
||||
#endif
|
||||
} else if (NULL == opal_hwloc_base_topo_file) {
|
||||
if (0 != hwloc_topology_init(&opal_hwloc_topology) ||
|
||||
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 HWLOC_API_VERSION < 0x20000
|
||||
/* 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;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if (OPAL_SUCCESS != (rc = opal_hwloc_base_set_topology(opal_hwloc_base_topo_file))) {
|
||||
return rc;
|
||||
@ -414,6 +467,7 @@ void opal_hwloc_base_free_topology(hwloc_topology_t topo)
|
||||
opal_hwloc_topo_data_t *rdata;
|
||||
unsigned k;
|
||||
|
||||
if (!topo_in_shmem) {
|
||||
obj = hwloc_get_root_obj(topo);
|
||||
/* release the root-level userdata */
|
||||
if (NULL != obj->userdata) {
|
||||
@ -427,6 +481,7 @@ void opal_hwloc_base_free_topology(hwloc_topology_t topo)
|
||||
for (k=0; k < obj->arity; k++) {
|
||||
free_object(obj->children[k]);
|
||||
}
|
||||
}
|
||||
hwloc_topology_destroy(topo);
|
||||
}
|
||||
|
||||
@ -744,7 +799,9 @@ static hwloc_obj_t df_search(hwloc_topology_t topo,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
notfound:
|
||||
#endif
|
||||
for (k=0; k < start->arity; k++) {
|
||||
obj = df_search(topo, start->children[k], target, cache_level, nobj, rtype, idx, num_objs);
|
||||
if (NULL != obj) {
|
||||
@ -923,7 +980,9 @@ hwloc_obj_t opal_hwloc_base_find_min_bound_target_under_obj(hwloc_topology_t top
|
||||
return obj;
|
||||
}
|
||||
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
moveon:
|
||||
#endif
|
||||
/* the hwloc accessors all report at the topo level,
|
||||
* so we have to do some work
|
||||
*/
|
||||
@ -1876,7 +1935,6 @@ 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 HWLOC_API_VERSION < 0x20000
|
||||
if (NULL != root->userdata) {
|
||||
sum = (opal_hwloc_topo_data_t*)root->userdata;
|
||||
if (NULL == sum->available) {
|
||||
@ -1886,11 +1944,6 @@ int opal_hwloc_base_cset2mapstr(char *str, int len,
|
||||
return OPAL_ERR_NOT_BOUND;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (0 != hwloc_bitmap_isincluded(root->cpuset, cpuset)) {
|
||||
return OPAL_ERR_NOT_BOUND;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Iterate over all existing sockets */
|
||||
for (socket = hwloc_get_obj_by_type(topo, HWLOC_OBJ_SOCKET, 0);
|
||||
@ -1952,14 +2005,17 @@ static int dist_cmp_fn (opal_list_item_t **a, opal_list_item_t **b)
|
||||
static void sort_by_dist(hwloc_topology_t topo, char* device_name, opal_list_t *sorted_list)
|
||||
{
|
||||
hwloc_obj_t device_obj = NULL;
|
||||
hwloc_obj_t obj = NULL, root = NULL;
|
||||
hwloc_obj_t obj = NULL;
|
||||
struct hwloc_distances_s* distances;
|
||||
opal_rmaps_numa_node_t *numa_node;
|
||||
int close_node_index;
|
||||
float latency;
|
||||
unsigned int j;
|
||||
#if HWLOC_API_VERSION < 0x20000
|
||||
hwloc_obj_t root = NULL;
|
||||
int depth;
|
||||
unsigned i;
|
||||
#endif
|
||||
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)) {
|
||||
@ -2019,7 +2075,9 @@ static void sort_by_dist(hwloc_topology_t topo, char* device_name, opal_list_t *
|
||||
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) {
|
||||
distances_nr = 1;
|
||||
if (0 != hwloc_distances_get_by_type(topo, HWLOC_OBJ_NODE, &distances_nr, &distances,
|
||||
HWLOC_DISTANCES_KIND_MEANS_LATENCY, 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;
|
||||
|
@ -1,6 +0,0 @@
|
||||
Cherry-picked commits after 1.11.3:
|
||||
|
||||
open-mpi/hwloc@9549fd59af04dca2e2340e17f0e685f8c552d818
|
||||
open-mpi/hwloc@0ab7af5e90fc2b58be30b2126cc2a73f9f7ecfe9
|
||||
open-mpi/hwloc@8b44fb1c812d01582887548c2fc28ee78255619
|
||||
open-mpi/hwloc@d4565c351e5f01e27d3e106e3a4c2f971a37c9dd
|
@ -1,10 +0,0 @@
|
||||
Cédric Augonnet <Cedric.Augonnet@labri.fr>
|
||||
Guillaume Beauchamp <Guillaume.Beauchamp@inria.fr>
|
||||
Jérôme Clet-Ortega <Jerome.Clet-Ortega@labri.fr>
|
||||
Ludovic Courtès <Ludovic.Courtes@inria.fr>
|
||||
Nathalie Furmento <Nathalie.Furmento@labri.fr>
|
||||
Brice Goglin <Brice.Goglin@inria.fr>
|
||||
Alexey Kardashevskiy <aik@au1.ibm.com>
|
||||
Antoine Rougier (University of Bordeaux intern)
|
||||
Jeff Squyres <jsquyres@cisco.com>
|
||||
Samuel Thibault <Samuel.Thibault@labri.fr>
|
@ -1,75 +0,0 @@
|
||||
Introduction
|
||||
|
||||
hwloc provides command line tools and a C API to obtain the hierarchical map of
|
||||
key computing elements, such as: NUMA memory nodes, shared caches, processor
|
||||
packages, processor cores, processing units (logical processors or "threads")
|
||||
and even I/O devices. hwloc also gathers various attributes such as cache and
|
||||
memory information, and is portable across a variety of different operating
|
||||
systems and platforms. Additionally it may assemble the topologies of multiple
|
||||
machines into a single one so as to let applications consult the topology of an
|
||||
entire fabric or cluster at once.
|
||||
|
||||
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 supports the following operating systems:
|
||||
|
||||
* Linux (including old kernels not having sysfs topology information, with
|
||||
knowledge of cpusets, ScaleMP vSMP and Kerrighed support, etc.) on all
|
||||
supported hardware, including Intel Xeon Phi (KNL and KNC, either
|
||||
standalone or as a coprocessor) and NumaScale NumaConnect.
|
||||
* Solaris
|
||||
* AIX
|
||||
* Darwin / OS X
|
||||
* FreeBSD and its variants (such as kFreeBSD/GNU)
|
||||
* NetBSD
|
||||
* OSF/1 (a.k.a., Tru64)
|
||||
* HP-UX
|
||||
* Microsoft Windows
|
||||
* IBM BlueGene/Q Compute Node Kernel (CNK)
|
||||
|
||||
Since it uses standard Operating System information, hwloc's support is mostly
|
||||
independant from the processor type (x86, powerpc, ...) and just relies on the
|
||||
Operating System support. The only exception to this is kFreeBSD, which does
|
||||
not support topology information, and hwloc thus uses an x86-only CPUID-based
|
||||
backend (which can be used for other OSes too, see the Components and plugins
|
||||
section).
|
||||
|
||||
To check whether hwloc works on a particular machine, just try to build it and
|
||||
run lstopo or lstopo-no-graphics. If some things do not look right (e.g. bogus
|
||||
or missing cache information), see Questions and Bugs below.
|
||||
|
||||
hwloc only reports the number of processors on unsupported operating systems;
|
||||
no topology information is available.
|
||||
|
||||
For development and debugging purposes, hwloc also offers the ability to work
|
||||
on "fake" topologies:
|
||||
|
||||
* Symmetrical tree of resources generated from a list of level arities, see
|
||||
Synthetic topologies.
|
||||
* Remote machine simulation through the gathering of topology as XML files,
|
||||
see Importing and exporting topologies from/to XML files.
|
||||
|
||||
hwloc can display the topology in a human-readable format, either in graphical
|
||||
mode (X11), or by exporting in one of several different formats, including:
|
||||
plain text, PDF, PNG, and FIG (see Command-line Examples below). Note that some
|
||||
of the export formats require additional support libraries.
|
||||
|
||||
hwloc offers a programming interface for manipulating topologies and objects.
|
||||
It also brings a powerful CPU bitmap API that is used to describe topology
|
||||
objects location on physical/logical processors. See the Programming Interface
|
||||
below. It may also be used to binding applications onto certain cores or memory
|
||||
nodes. Several utility programs are also provided to ease command-line
|
||||
manipulation of topology objects, binding of processes, and so on.
|
||||
|
||||
Perl bindings are available from Bernd Kallies on CPAN.
|
||||
|
||||
Python bindings are available from Guy Streeter:
|
||||
|
||||
* Fedora RPM and tarball.
|
||||
* git tree (html).
|
||||
|
||||
|
||||
|
||||
See https://www.open-mpi.org/projects/hwloc/doc/ for more hwloc documentation.
|
@ -1,102 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2014 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 Return an object type from the string
|
||||
*
|
||||
* \return -1 if unrecognized.
|
||||
*/
|
||||
HWLOC_DECLSPEC hwloc_obj_type_t hwloc_obj_type_of_string (const char * string) __hwloc_attribute_pure __hwloc_attribute_deprecated;
|
||||
|
||||
/** \brief Stringify a given topology object into a human-readable form.
|
||||
*
|
||||
* \note This function is deprecated in favor of hwloc_obj_type_snprintf()
|
||||
* and hwloc_obj_attr_snprintf() since it is not very flexible and
|
||||
* only prints physical/OS indexes.
|
||||
*
|
||||
* Fill string \p string up to \p size characters with the description
|
||||
* of topology object \p obj in topology \p topology.
|
||||
*
|
||||
* If \p verbose is set, a longer description is used. Otherwise a
|
||||
* short description is used.
|
||||
*
|
||||
* \p indexprefix is used to prefix the \p os_index attribute number of
|
||||
* the object in the description. If \c NULL, the \c # character is used.
|
||||
*
|
||||
* 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).
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_obj_snprintf(char * __hwloc_restrict string, size_t size,
|
||||
hwloc_topology_t topology, hwloc_obj_t obj,
|
||||
const char * __hwloc_restrict indexprefix, int verbose) __hwloc_attribute_deprecated;
|
||||
|
||||
/** \brief Distribute \p n items over the topology under \p root
|
||||
*
|
||||
* Array \p cpuset will be filled with \p n cpusets recursively distributed
|
||||
* linearly over the topology under \p root, down to depth \p until (which can
|
||||
* be INT_MAX to distribute down to the finest level).
|
||||
*
|
||||
* This is typically useful when an application wants to distribute \p n
|
||||
* threads over a machine, giving each of them as much private cache as
|
||||
* possible and keeping them locally in number order.
|
||||
*
|
||||
* The caller may typically want to also call hwloc_bitmap_singlify()
|
||||
* before binding a thread so that it does not move at all.
|
||||
*
|
||||
* \note This function requires the \p root object to have a CPU set.
|
||||
*/
|
||||
static __hwloc_inline void
|
||||
hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *set, unsigned n, unsigned until) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline void
|
||||
hwloc_distribute(hwloc_topology_t topology, hwloc_obj_t root, hwloc_cpuset_t *set, unsigned n, unsigned until)
|
||||
{
|
||||
hwloc_distrib(topology, &root, 1, set, n, until, 0);
|
||||
}
|
||||
|
||||
/** \brief Distribute \p n items over the topology under \p roots
|
||||
*
|
||||
* This is the same as hwloc_distribute(), but takes an array of roots instead of
|
||||
* just one root.
|
||||
*
|
||||
* \note This function requires the \p roots objects to have a CPU set.
|
||||
*/
|
||||
static __hwloc_inline void
|
||||
hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *set, unsigned n, unsigned until) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline void
|
||||
hwloc_distributev(hwloc_topology_t topology, hwloc_obj_t *roots, unsigned n_roots, hwloc_cpuset_t *set, unsigned n, unsigned until)
|
||||
{
|
||||
hwloc_distrib(topology, roots, n_roots, set, n, until, 0);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_DEPRECATED_H */
|
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2012 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
/*
|
||||
* these declarations are internal only, they are not available to plugins
|
||||
* (many functions below are internal static symbols).
|
||||
*/
|
||||
#error This file should not be used in plugins
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef PRIVATE_COMPONENTS_H
|
||||
#define PRIVATE_COMPONENTS_H 1
|
||||
|
||||
#include <hwloc/plugins.h>
|
||||
|
||||
struct hwloc_topology;
|
||||
|
||||
extern int hwloc_disc_component_force_enable(struct hwloc_topology *topology,
|
||||
int envvar_forced, /* 1 if forced through envvar, 0 if forced through API */
|
||||
int type, const char *name,
|
||||
const void *data1, const void *data2, const void *data3);
|
||||
extern void hwloc_disc_components_enable_others(struct hwloc_topology *topology);
|
||||
|
||||
/* Compute the topology is_thissystem flag based on enabled backends */
|
||||
extern void hwloc_backends_is_thissystem(struct hwloc_topology *topology);
|
||||
|
||||
/* Disable and destroy all backends used by a topology */
|
||||
extern void hwloc_backends_disable_all(struct hwloc_topology *topology);
|
||||
|
||||
/* Used by the core to setup/destroy the list of components */
|
||||
extern void hwloc_components_init(struct hwloc_topology *topology); /* increases components refcount, should be called exactly once per topology (during init) */
|
||||
extern void hwloc_components_destroy_all(struct hwloc_topology *topology); /* decreases components refcount, should be called exactly once per topology (during destroy) */
|
||||
|
||||
#endif /* PRIVATE_COMPONENTS_H */
|
||||
|
@ -1,306 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@ -1,408 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2013-2014 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_t topology __hwloc_attribute_unused,
|
||||
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;
|
||||
|
||||
if (obj->type == HWLOC_OBJ_MISC)
|
||||
/* TODO: add a custom level/depth for Misc */
|
||||
return hwloc_append_diff_too_complex(obj, firstdiffp, lastdiffp);
|
||||
|
||||
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;
|
||||
|
||||
if (obj->type == HWLOC_OBJ_MISC)
|
||||
/* TODO: add a custom level/depth for Misc */
|
||||
return hwloc_append_diff_too_complex(obj, firstdiffp, lastdiffp);
|
||||
|
||||
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;
|
||||
|
||||
if (obj1->depth != obj2->depth)
|
||||
goto out_too_complex;
|
||||
if (obj1->type != obj2->type)
|
||||
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(online_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 */
|
||||
|
||||
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 */
|
||||
|
||||
/* ignore os_level */
|
||||
|
||||
/* type-specific attrs */
|
||||
switch (obj1->type) {
|
||||
default:
|
||||
break;
|
||||
case HWLOC_OBJ_CACHE:
|
||||
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;
|
||||
}
|
||||
|
||||
/* distances */
|
||||
if (obj1->distances_count != obj2->distances_count)
|
||||
goto out_too_complex;
|
||||
for(i=0; i<obj1->distances_count; i++) {
|
||||
struct hwloc_distances_s *d1 = obj1->distances[i], *d2 = obj2->distances[i];
|
||||
if (d1->relative_depth != d2->relative_depth
|
||||
|| d1->nbobjs != d2->nbobjs
|
||||
|| d1->latency_max != d2->latency_max
|
||||
|| d1->latency_base != d2->latency_base
|
||||
|| memcmp(d1->latency, d2->latency, d1->nbobjs * d1->nbobjs * sizeof(*d1->latency)))
|
||||
goto out_too_complex;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
if (obj1->arity != obj2->arity)
|
||||
goto out_too_complex;
|
||||
for(i=0; i<obj1->arity; i++) {
|
||||
err = hwloc_diff_trees(topo1, obj1->children[i],
|
||||
topo2, obj2->children[i],
|
||||
flags,
|
||||
firstdiffp, lastdiffp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
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;
|
||||
int err;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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 (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 */
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@ -1,545 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#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("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);
|
||||
}
|
||||
#endif /* HWLOC_DEBUG */
|
||||
|
||||
static void
|
||||
hwloc_pci_traverse_lookuposdevices_cb(void * cbdata,
|
||||
struct hwloc_obj *pcidev)
|
||||
{
|
||||
struct hwloc_backend *backend = cbdata;
|
||||
|
||||
if (pcidev->type == HWLOC_OBJ_BRIDGE)
|
||||
return;
|
||||
|
||||
hwloc_backends_notify_new_object(backend, pcidev);
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci__traverse(void * cbdata, struct hwloc_obj *root,
|
||||
void (*cb)(void * cbdata, struct hwloc_obj *))
|
||||
{
|
||||
struct hwloc_obj *child = root->first_child;
|
||||
while (child) {
|
||||
cb(cbdata, child);
|
||||
if (child->type == HWLOC_OBJ_BRIDGE)
|
||||
hwloc_pci__traverse(cbdata, child, cb);
|
||||
child = child->next_sibling;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci_traverse(void * cbdata, struct hwloc_obj *root,
|
||||
void (*cb)(void * cbdata, struct hwloc_obj *))
|
||||
{
|
||||
hwloc_pci__traverse(cbdata, root, cb);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
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_child_before(struct hwloc_obj *root, struct hwloc_obj *child, struct hwloc_obj *new)
|
||||
{
|
||||
if (child) {
|
||||
new->prev_sibling = child->prev_sibling;
|
||||
child->prev_sibling = new;
|
||||
} else {
|
||||
new->prev_sibling = root->last_child;
|
||||
root->last_child = new;
|
||||
}
|
||||
|
||||
if (new->prev_sibling)
|
||||
new->prev_sibling->next_sibling = new;
|
||||
else
|
||||
root->first_child = new;
|
||||
new->next_sibling = child;
|
||||
|
||||
new->parent = root; /* so that hwloc_pci_traverse_print_cb() can indent by depth */
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci_remove_child(struct hwloc_obj *root, struct hwloc_obj *child)
|
||||
{
|
||||
if (child->next_sibling)
|
||||
child->next_sibling->prev_sibling = child->prev_sibling;
|
||||
else
|
||||
root->last_child = child->prev_sibling;
|
||||
if (child->prev_sibling)
|
||||
child->prev_sibling->next_sibling = child->next_sibling;
|
||||
else
|
||||
root->first_child = child->next_sibling;
|
||||
child->prev_sibling = NULL;
|
||||
child->next_sibling = NULL;
|
||||
}
|
||||
|
||||
static void hwloc_pci_add_object(struct hwloc_obj *root, struct hwloc_obj *new);
|
||||
|
||||
static void
|
||||
hwloc_pci_try_insert_siblings_below_new_bridge(struct hwloc_obj *root, struct hwloc_obj *new)
|
||||
{
|
||||
enum hwloc_pci_busid_comparison_e comp;
|
||||
struct hwloc_obj *current, *next;
|
||||
|
||||
next = new->next_sibling;
|
||||
while (next) {
|
||||
current = next;
|
||||
next = current->next_sibling;
|
||||
|
||||
comp = hwloc_pci_compare_busids(current, new);
|
||||
assert(comp != HWLOC_PCI_BUSID_SUPERSET);
|
||||
if (comp == HWLOC_PCI_BUSID_HIGHER)
|
||||
continue;
|
||||
assert(comp == HWLOC_PCI_BUSID_INCLUDED);
|
||||
|
||||
/* move this object below the new bridge */
|
||||
hwloc_pci_remove_child(root, current);
|
||||
hwloc_pci_add_object(new, current);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci_add_object(struct hwloc_obj *root, struct hwloc_obj *new)
|
||||
{
|
||||
struct hwloc_obj *current;
|
||||
|
||||
current = root->first_child;
|
||||
while (current) {
|
||||
enum hwloc_pci_busid_comparison_e comp = hwloc_pci_compare_busids(new, current);
|
||||
switch (comp) {
|
||||
case HWLOC_PCI_BUSID_HIGHER:
|
||||
/* go further */
|
||||
current = current->next_sibling;
|
||||
continue;
|
||||
case HWLOC_PCI_BUSID_INCLUDED:
|
||||
/* insert below current bridge */
|
||||
hwloc_pci_add_object(current, new);
|
||||
return;
|
||||
case HWLOC_PCI_BUSID_LOWER:
|
||||
case HWLOC_PCI_BUSID_SUPERSET:
|
||||
/* insert before current object */
|
||||
hwloc_pci_add_child_before(root, current, new);
|
||||
/* walk next siblings and move them below new bridge if needed */
|
||||
hwloc_pci_try_insert_siblings_below_new_bridge(root, new);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* add to the end of the list if higher than everybody */
|
||||
hwloc_pci_add_child_before(root, NULL, new);
|
||||
}
|
||||
|
||||
static struct hwloc_obj *
|
||||
hwloc_pci_fixup_hostbridge_parent(struct hwloc_topology *topology __hwloc_attribute_unused,
|
||||
struct hwloc_obj *hostbridge,
|
||||
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",
|
||||
hostbridge->first_child->attr->pcidev.domain, hostbridge->first_child->attr->pcidev.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",
|
||||
hostbridge->first_child->attr->pcidev.domain, hostbridge->first_child->attr->pcidev.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_hostbridge_parent(struct hwloc_topology *topology, struct hwloc_backend *backend,
|
||||
struct hwloc_obj *hostbridge)
|
||||
{
|
||||
hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();
|
||||
struct hwloc_obj *parent;
|
||||
const char *env;
|
||||
int err;
|
||||
|
||||
/* override the cpuset with the environment if given */
|
||||
int forced = 0;
|
||||
char envname[256];
|
||||
snprintf(envname, sizeof(envname), "HWLOC_PCI_%04x_%02x_LOCALCPUS",
|
||||
hostbridge->first_child->attr->pcidev.domain, hostbridge->first_child->attr->pcidev.bus);
|
||||
env = getenv(envname);
|
||||
if (env)
|
||||
/* if env exists but is empty, don't let quirks change what the OS reports */
|
||||
forced = 1;
|
||||
if (env && *env) {
|
||||
/* force the hostbridge cpuset */
|
||||
hwloc_debug("Overriding localcpus using %s in the environment\n", envname);
|
||||
hwloc_bitmap_sscanf(cpuset, env);
|
||||
} else {
|
||||
/* get the hostbridge cpuset by acking the OS backend.
|
||||
* it's not a PCI device, so we use its first child locality info.
|
||||
*/
|
||||
err = hwloc_backends_get_obj_cpuset(backend, hostbridge->first_child, cpuset);
|
||||
if (err < 0)
|
||||
/* if we got nothing, assume the hostbridge is attached to the top of hierarchy */
|
||||
hwloc_bitmap_copy(cpuset, hwloc_topology_get_topology_cpuset(topology));
|
||||
}
|
||||
|
||||
hwloc_debug_bitmap("Attaching hostbridge to cpuset %s\n", cpuset);
|
||||
|
||||
/* restrict to the existing topology cpuset to avoid errors later */
|
||||
hwloc_bitmap_and(cpuset, cpuset, hwloc_topology_get_topology_cpuset(topology));
|
||||
|
||||
/* if the remaining cpuset is empty, take the root */
|
||||
if (hwloc_bitmap_iszero(cpuset))
|
||||
hwloc_bitmap_copy(cpuset, hwloc_topology_get_topology_cpuset(topology));
|
||||
|
||||
/* attach the hostbridge now that it contains the right objects */
|
||||
parent = hwloc_get_obj_covering_cpuset(topology, cpuset);
|
||||
/* in the worst case, we got the root object */
|
||||
|
||||
if (hwloc_bitmap_isequal(cpuset, parent->cpuset)) {
|
||||
/* this object has the right cpuset, but it could be a cache or so,
|
||||
* go up as long as the cpuset is the same
|
||||
*/
|
||||
while (parent->parent && hwloc_bitmap_isequal(parent->cpuset, parent->parent->cpuset))
|
||||
parent = parent->parent;
|
||||
|
||||
if (!forced)
|
||||
parent = hwloc_pci_fixup_hostbridge_parent(topology, hostbridge, parent);
|
||||
|
||||
} else {
|
||||
/* the object we found is too large, insert an intermediate group */
|
||||
hwloc_obj_t group_obj = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, -1);
|
||||
if (group_obj) {
|
||||
group_obj->cpuset = hwloc_bitmap_dup(cpuset);
|
||||
group_obj->complete_cpuset = hwloc_bitmap_dup(cpuset);
|
||||
group_obj->attr->group.depth = (unsigned) -1;
|
||||
parent = hwloc__insert_object_by_cpuset(topology, group_obj, hwloc_report_os_error);
|
||||
if (parent == group_obj)
|
||||
/* if didn't get merged, setup its sets */
|
||||
hwloc_fill_object_sets(group_obj);
|
||||
if (!parent)
|
||||
/* Failed to insert the parent, maybe a conflicting cpuset, attach to the root object instead */
|
||||
parent = hwloc_get_root_obj(topology);
|
||||
}
|
||||
}
|
||||
|
||||
hwloc_bitmap_free(cpuset);
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_insert_pci_device_list(struct hwloc_backend *backend,
|
||||
struct hwloc_obj *first_obj)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
struct hwloc_obj fakeparent;
|
||||
struct hwloc_obj *obj;
|
||||
unsigned current_hostbridge;
|
||||
|
||||
if (!first_obj)
|
||||
/* found nothing, exit */
|
||||
return 0;
|
||||
|
||||
/* first, organise object as tree under a fake parent object */
|
||||
fakeparent.parent = NULL;
|
||||
fakeparent.first_child = NULL;
|
||||
fakeparent.last_child = NULL;
|
||||
while (first_obj) {
|
||||
obj = first_obj;
|
||||
first_obj = obj->next_sibling;
|
||||
hwloc_pci_add_object(&fakeparent, obj);
|
||||
}
|
||||
|
||||
#ifdef HWLOC_DEBUG
|
||||
hwloc_debug("%s", "\nPCI hierarchy under fake parent:\n");
|
||||
hwloc_pci_traverse(NULL, &fakeparent, hwloc_pci_traverse_print_cb);
|
||||
hwloc_debug("%s", "\n");
|
||||
#endif
|
||||
|
||||
/* walk the hierarchy, and lookup OS devices */
|
||||
hwloc_pci_traverse(backend, &fakeparent, hwloc_pci_traverse_lookuposdevices_cb);
|
||||
|
||||
/*
|
||||
* fakeparent lists 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.
|
||||
*/
|
||||
current_hostbridge = 0;
|
||||
while (fakeparent.first_child) {
|
||||
/* start a new host bridge */
|
||||
struct hwloc_obj *hostbridge = hwloc_alloc_setup_object(HWLOC_OBJ_BRIDGE, current_hostbridge++);
|
||||
struct hwloc_obj *child = fakeparent.first_child;
|
||||
struct hwloc_obj *next_child;
|
||||
struct hwloc_obj *parent;
|
||||
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);
|
||||
|
||||
/*
|
||||
* attach all objects from the same upstream domain/bus
|
||||
*/
|
||||
next_child:
|
||||
next_child = child->next_sibling;
|
||||
hwloc_pci_remove_child(&fakeparent, child);
|
||||
hwloc_pci_add_child_before(hostbridge, NULL, child);
|
||||
|
||||
/* 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 = next_child;
|
||||
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);
|
||||
|
||||
/* attach the hostbridge where it belongs */
|
||||
parent = hwloc_pci_find_hostbridge_parent(topology, backend, hostbridge);
|
||||
hwloc_insert_object_by_parent(topology, parent, hostbridge);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#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
|
||||
#define HWLOC_PCI_PRIMARY_BUS 0x18
|
||||
#define HWLOC_PCI_SECONDARY_BUS 0x19
|
||||
#define HWLOC_PCI_SUBORDINATE_BUS 0x1a
|
||||
|
||||
int
|
||||
hwloc_pci_prepare_bridge(hwloc_obj_t obj,
|
||||
const unsigned char *config)
|
||||
{
|
||||
unsigned char headertype;
|
||||
unsigned isbridge;
|
||||
struct hwloc_pcidev_attr_s *pattr = &obj->attr->pcidev;
|
||||
struct hwloc_bridge_attr_s *battr;
|
||||
|
||||
headertype = config[HWLOC_PCI_HEADER_TYPE] & 0x7f;
|
||||
isbridge = (pattr->class_id == HWLOC_PCI_CLASS_BRIDGE_PCI
|
||||
&& headertype == HWLOC_PCI_HEADER_TYPE_BRIDGE);
|
||||
|
||||
if (!isbridge)
|
||||
return 0;
|
||||
|
||||
battr = &obj->attr->bridge;
|
||||
|
||||
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;
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2011-2014 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
|
||||
hwloc_obj_t
|
||||
hwloc_custom_insert_group_object_by_parent(struct hwloc_topology *topology, hwloc_obj_t parent, int groupdepth)
|
||||
{
|
||||
hwloc_obj_t obj;
|
||||
|
||||
/* must be called between set_custom() and load(), so there's a single backend, the custom one */
|
||||
if (topology->is_loaded || !topology->backends || !topology->backends->is_custom) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, -1);
|
||||
obj->attr->group.depth = groupdepth;
|
||||
hwloc_obj_add_info(obj, "Backend", "Custom");
|
||||
hwloc_insert_object_by_parent(topology, parent, obj);
|
||||
/* insert_object_by_parent() doesn't merge during insert, so obj is still valid */
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_custom_insert_topology(struct hwloc_topology *newtopology,
|
||||
struct hwloc_obj *newparent,
|
||||
struct hwloc_topology *oldtopology,
|
||||
struct hwloc_obj *oldroot)
|
||||
{
|
||||
/* must be called between set_custom() and load(), so there's a single backend, the custom one */
|
||||
if (newtopology->is_loaded || !newtopology->backends || !newtopology->backends->is_custom) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!oldtopology->is_loaded) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
hwloc__duplicate_objects(newtopology, newparent, oldroot ? oldroot : oldtopology->levels[0][0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_look_custom(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
hwloc_obj_t root = topology->levels[0][0];
|
||||
|
||||
assert(!root->cpuset);
|
||||
|
||||
if (!root->first_child) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
root->type = HWLOC_OBJ_SYSTEM;
|
||||
hwloc_obj_add_info(root, "Backend", "Custom");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_custom_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_custom;
|
||||
backend->is_custom = 1;
|
||||
backend->is_thissystem = 0;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_custom_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
"custom",
|
||||
~0,
|
||||
hwloc_custom_component_instantiate,
|
||||
30,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct hwloc_component hwloc_custom_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
NULL, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_custom_disc_component
|
||||
};
|
@ -1,197 +0,0 @@
|
||||
/*
|
||||
* 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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, i);
|
||||
obj->cpuset = set;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(set, 0, 7);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(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);
|
||||
|
||||
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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, i);
|
||||
obj->cpuset = set;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(set, 0, 15);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(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);
|
||||
|
||||
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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, i);
|
||||
obj->cpuset = set;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -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(HWLOC_OBJ_CACHE, -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);
|
||||
|
||||
obj = hwloc_alloc_setup_object(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;
|
||||
}
|
@ -1,239 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2012-2014 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>
|
||||
|
||||
struct hwloc_nvml_backend_data_s {
|
||||
unsigned nr_devices; /* -1 when unknown yet, first callback will setup */
|
||||
struct hwloc_nvml_device_info_s {
|
||||
char name[64];
|
||||
char serial[64];
|
||||
char uuid[64];
|
||||
unsigned pcidomain, pcibus, pcidev, pcifunc;
|
||||
float maxlinkspeed;
|
||||
} * devices;
|
||||
};
|
||||
|
||||
static void
|
||||
hwloc_nvml_query_devices(struct hwloc_nvml_backend_data_s *data)
|
||||
{
|
||||
nvmlReturn_t ret;
|
||||
unsigned nb, i;
|
||||
|
||||
/* mark the number of devices as 0 in case we fail below,
|
||||
* so that we don't try again later.
|
||||
*/
|
||||
data->nr_devices = 0;
|
||||
|
||||
ret = nvmlInit();
|
||||
if (NVML_SUCCESS != ret)
|
||||
goto out;
|
||||
ret = nvmlDeviceGetCount(&nb);
|
||||
if (NVML_SUCCESS != ret)
|
||||
goto out_with_init;
|
||||
|
||||
/* allocate structs */
|
||||
data->devices = malloc(nb * sizeof(*data->devices));
|
||||
if (!data->devices)
|
||||
goto out_with_init;
|
||||
|
||||
for(i=0; i<nb; i++) {
|
||||
struct hwloc_nvml_device_info_s *info = &data->devices[data->nr_devices];
|
||||
nvmlPciInfo_t pci;
|
||||
nvmlDevice_t device;
|
||||
|
||||
ret = nvmlDeviceGetHandleByIndex(i, &device);
|
||||
assert(ret == NVML_SUCCESS);
|
||||
|
||||
ret = nvmlDeviceGetPciInfo(device, &pci);
|
||||
if (NVML_SUCCESS != ret)
|
||||
continue;
|
||||
|
||||
info->pcidomain = pci.domain;
|
||||
info->pcibus = pci.bus;
|
||||
info->pcidev = pci.device;
|
||||
info->pcifunc = 0;
|
||||
|
||||
info->name[0] = '\0';
|
||||
ret = nvmlDeviceGetName(device, info->name, sizeof(info->name));
|
||||
/* these may fail with NVML_ERROR_NOT_SUPPORTED on old devices */
|
||||
info->serial[0] = '\0';
|
||||
ret = nvmlDeviceGetSerial(device, info->serial, sizeof(info->serial));
|
||||
info->uuid[0] = '\0';
|
||||
ret = nvmlDeviceGetUUID(device, info->uuid, sizeof(info->uuid));
|
||||
|
||||
info->maxlinkspeed = 0.0f;
|
||||
#if HAVE_DECL_NVMLDEVICEGETMAXPCIELINKGENERATION
|
||||
{
|
||||
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 */
|
||||
info->maxlinkspeed = lanespeed * maxwidth / 8; /* GB/s */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* validate this device */
|
||||
data->nr_devices++;
|
||||
}
|
||||
|
||||
out_with_init:
|
||||
nvmlShutdown();
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_nvml_backend_notify_new_object(struct hwloc_backend *backend, struct hwloc_backend *caller __hwloc_attribute_unused,
|
||||
struct hwloc_obj *pcidev)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
struct hwloc_nvml_backend_data_s *data = backend->private_data;
|
||||
unsigned i;
|
||||
|
||||
if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO)))
|
||||
return 0;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
hwloc_debug("%s", "\nno NVML detection (not thissystem)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HWLOC_OBJ_PCI_DEVICE != pcidev->type)
|
||||
return 0;
|
||||
|
||||
if (data->nr_devices == (unsigned) -1) {
|
||||
/* first call, lookup all devices */
|
||||
hwloc_nvml_query_devices(data);
|
||||
/* if it fails, data->nr_devices = 0 so we won't do anything below and in next callbacks */
|
||||
}
|
||||
|
||||
if (!data->nr_devices)
|
||||
/* found no devices */
|
||||
return 0;
|
||||
|
||||
/* now the devices array is ready to use */
|
||||
for(i=0; i<data->nr_devices; i++) {
|
||||
struct hwloc_nvml_device_info_s *info = &data->devices[i];
|
||||
hwloc_obj_t osdev;
|
||||
char buffer[64];
|
||||
|
||||
if (info->pcidomain != pcidev->attr->pcidev.domain)
|
||||
continue;
|
||||
if (info->pcibus != pcidev->attr->pcidev.bus)
|
||||
continue;
|
||||
if (info->pcidev != pcidev->attr->pcidev.dev)
|
||||
continue;
|
||||
if (info->pcifunc != pcidev->attr->pcidev.func)
|
||||
continue;
|
||||
|
||||
osdev = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1);
|
||||
snprintf(buffer, sizeof(buffer), "nvml%d", 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");
|
||||
hwloc_obj_add_info(osdev, "GPUModel", info->name);
|
||||
if (info->serial[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "NVIDIASerial", info->serial);
|
||||
if (info->uuid[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "NVIDIAUUID", info->uuid);
|
||||
|
||||
hwloc_insert_object_by_parent(topology, pcidev, osdev);
|
||||
|
||||
if (info->maxlinkspeed != 0.0f)
|
||||
/* we found the max link speed, replace the current link speed found by pci (or none) */
|
||||
pcidev->attr->pcidev.linkspeed = info->maxlinkspeed;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_nvml_backend_disable(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_nvml_backend_data_s *data = backend->private_data;
|
||||
free(data->devices);
|
||||
free(data);
|
||||
}
|
||||
|
||||
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;
|
||||
struct hwloc_nvml_backend_data_s *data;
|
||||
|
||||
/* thissystem may not be fully initialized yet, we'll check flags in discover() */
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (!data) {
|
||||
free(backend);
|
||||
return NULL;
|
||||
}
|
||||
/* the first callback will initialize those */
|
||||
data->nr_devices = (unsigned) -1; /* unknown yet */
|
||||
data->devices = NULL;
|
||||
|
||||
backend->private_data = data;
|
||||
backend->disable = hwloc_nvml_backend_disable;
|
||||
|
||||
backend->notify_new_object = hwloc_nvml_backend_notify_new_object;
|
||||
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
|
||||
};
|
@ -1,346 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2012-2014 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>
|
||||
|
||||
typedef enum hwloc_opencl_device_type_e {
|
||||
HWLOC_OPENCL_DEVICE_AMD
|
||||
} hwloc_opencl_device_type_t;
|
||||
|
||||
struct hwloc_opencl_backend_data_s {
|
||||
unsigned nr_devices; /* -1 when unknown yet, first callback will setup */
|
||||
struct hwloc_opencl_device_info_s {
|
||||
hwloc_opencl_device_type_t type;
|
||||
|
||||
unsigned platformidx;
|
||||
char platformname[64];
|
||||
unsigned platformdeviceidx;
|
||||
char devicename[64];
|
||||
char devicevendor[64];
|
||||
char devicetype[64];
|
||||
|
||||
unsigned computeunits;
|
||||
unsigned long long globalmemsize;
|
||||
|
||||
union hwloc_opencl_device_info_u {
|
||||
struct hwloc_opencl_device_info_amd_s {
|
||||
unsigned pcidomain, pcibus, pcidev, pcifunc;
|
||||
} amd;
|
||||
} specific;
|
||||
} * devices;
|
||||
};
|
||||
|
||||
static void
|
||||
hwloc_opencl_query_devices(struct hwloc_opencl_backend_data_s *data)
|
||||
{
|
||||
cl_platform_id *platform_ids = NULL;
|
||||
cl_uint nr_platforms;
|
||||
cl_device_id *device_ids = NULL;
|
||||
cl_uint nr_devices, nr_total_devices, tmp;
|
||||
cl_int clret;
|
||||
unsigned curpfidx, curpfdvidx, i;
|
||||
|
||||
/* mark the number of devices as 0 in case we fail below,
|
||||
* so that we don't try again later.
|
||||
*/
|
||||
data->nr_devices = 0;
|
||||
|
||||
/* count platforms, allocate and get them */
|
||||
clret = clGetPlatformIDs(0, NULL, &nr_platforms);
|
||||
if (CL_SUCCESS != clret || !nr_platforms)
|
||||
goto out;
|
||||
hwloc_debug("%u OpenCL platforms\n", nr_platforms);
|
||||
platform_ids = malloc(nr_platforms * sizeof(*platform_ids));
|
||||
if (!platform_ids)
|
||||
goto out;
|
||||
clret = clGetPlatformIDs(nr_platforms, platform_ids, &nr_platforms);
|
||||
if (CL_SUCCESS != clret || !nr_platforms)
|
||||
goto out_with_platform_ids;
|
||||
|
||||
/* how many devices, total? */
|
||||
tmp = 0;
|
||||
for(i=0; i<nr_platforms; i++) {
|
||||
clret = clGetDeviceIDs(platform_ids[i], CL_DEVICE_TYPE_ALL, 0, NULL, &nr_devices);
|
||||
if (CL_SUCCESS != clret)
|
||||
goto out_with_platform_ids;
|
||||
tmp += nr_devices;
|
||||
}
|
||||
nr_total_devices = tmp;
|
||||
hwloc_debug("%u OpenCL devices total\n", nr_total_devices);
|
||||
/* allocate structs */
|
||||
device_ids = malloc(nr_total_devices * sizeof(*device_ids));
|
||||
data->devices = malloc(nr_total_devices * sizeof(*data->devices));
|
||||
if (!data->devices || !device_ids)
|
||||
goto out_with_device_ids;
|
||||
/* actually query device ids */
|
||||
tmp = 0;
|
||||
for(i=0; i<nr_platforms; i++) {
|
||||
clret = clGetDeviceIDs(platform_ids[i], CL_DEVICE_TYPE_ALL, nr_total_devices - tmp, device_ids + tmp, &nr_devices);
|
||||
if (CL_SUCCESS != clret)
|
||||
goto out_with_device_ids;
|
||||
tmp += nr_devices;
|
||||
}
|
||||
|
||||
/* query individual devices */
|
||||
curpfidx = 0;
|
||||
curpfdvidx = 0;
|
||||
for(i=0; i<nr_total_devices; i++) {
|
||||
struct hwloc_opencl_device_info_s *info = &data->devices[data->nr_devices];
|
||||
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_debug("Looking device %p\n", device_ids[i]);
|
||||
|
||||
info->platformname[0] = '\0';
|
||||
clret = clGetDeviceInfo(device_ids[i], CL_DEVICE_PLATFORM, sizeof(platform_id), &platform_id, NULL);
|
||||
if (CL_SUCCESS != clret)
|
||||
continue;
|
||||
clGetPlatformInfo(platform_id, CL_PLATFORM_NAME, sizeof(info->platformname), info->platformname, NULL);
|
||||
|
||||
info->devicename[0] = '\0';
|
||||
#ifdef CL_DEVICE_BOARD_NAME_AMD
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_BOARD_NAME_AMD, sizeof(info->devicename), info->devicename, NULL);
|
||||
#else
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_NAME, sizeof(info->devicename), info->devicename, NULL);
|
||||
#endif
|
||||
info->devicevendor[0] = '\0';
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_VENDOR, sizeof(info->devicevendor), info->devicevendor, NULL);
|
||||
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL);
|
||||
switch (type) {
|
||||
case CL_DEVICE_TYPE_CPU: /* FIXME: cannot happen in PCI devices? */
|
||||
strcpy(info->devicetype, "CPU");
|
||||
break;
|
||||
case CL_DEVICE_TYPE_GPU:
|
||||
strcpy(info->devicetype, "GPU");
|
||||
break;
|
||||
case CL_DEVICE_TYPE_ACCELERATOR:
|
||||
strcpy(info->devicetype, "Accelerator");
|
||||
break;
|
||||
default:
|
||||
strcpy(info->devicetype, "Unknown");
|
||||
break;
|
||||
}
|
||||
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(globalmemsize), &globalmemsize, NULL);
|
||||
info->globalmemsize = globalmemsize / 1024;
|
||||
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(computeunits), &computeunits, NULL);
|
||||
info->computeunits = computeunits;
|
||||
|
||||
hwloc_debug("platform %s device %s vendor %s type %s\n", info->platformname, info->devicename, info->devicevendor, info->devicetype);
|
||||
|
||||
/* find our indexes */
|
||||
while (platform_id != platform_ids[curpfidx]) {
|
||||
curpfidx++;
|
||||
curpfdvidx = 0;
|
||||
}
|
||||
info->platformidx = curpfidx;
|
||||
info->platformdeviceidx = curpfdvidx;
|
||||
curpfdvidx++;
|
||||
|
||||
hwloc_debug("This is opencl%dd%d\n", info->platformidx, info->platformdeviceidx);
|
||||
|
||||
#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;
|
||||
}
|
||||
if (CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD != amdtopo.raw.type) {
|
||||
hwloc_debug("not a PCIe device: %u\n", amdtopo.raw.type);
|
||||
continue;
|
||||
}
|
||||
|
||||
info->type = HWLOC_OPENCL_DEVICE_AMD;
|
||||
info->specific.amd.pcidomain = 0;
|
||||
info->specific.amd.pcibus = amdtopo.pcie.bus;
|
||||
info->specific.amd.pcidev = amdtopo.pcie.device;
|
||||
info->specific.amd.pcifunc = amdtopo.pcie.function;
|
||||
|
||||
hwloc_debug("OpenCL device on PCI 0000:%02x:%02x.%u\n", amdtopo.pcie.bus, amdtopo.pcie.device, amdtopo.pcie.function);
|
||||
|
||||
/* validate this device */
|
||||
data->nr_devices++;
|
||||
#endif /* HAVE_DECL_CL_DEVICE_TOPOLOGY_AMD */
|
||||
}
|
||||
free(device_ids);
|
||||
free(platform_ids);
|
||||
return;
|
||||
|
||||
out_with_device_ids:
|
||||
free(device_ids);
|
||||
free(data->devices);
|
||||
data->devices = NULL;
|
||||
out_with_platform_ids:
|
||||
free(platform_ids);
|
||||
out:
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_opencl_backend_notify_new_object(struct hwloc_backend *backend, struct hwloc_backend *caller __hwloc_attribute_unused,
|
||||
struct hwloc_obj *pcidev)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
struct hwloc_opencl_backend_data_s *data = backend->private_data;
|
||||
unsigned i;
|
||||
|
||||
if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO)))
|
||||
return 0;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
hwloc_debug("%s", "\nno OpenCL detection (not thissystem)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HWLOC_OBJ_PCI_DEVICE != pcidev->type)
|
||||
return 0;
|
||||
|
||||
if (data->nr_devices == (unsigned) -1) {
|
||||
/* first call, lookup all devices */
|
||||
hwloc_opencl_query_devices(data);
|
||||
/* if it fails, data->nr_devices = 0 so we won't do anything below and in next callbacks */
|
||||
}
|
||||
|
||||
if (!data->nr_devices)
|
||||
/* found no devices */
|
||||
return 0;
|
||||
|
||||
/* now the devices array is ready to use */
|
||||
for(i=0; i<data->nr_devices; i++) {
|
||||
struct hwloc_opencl_device_info_s *info = &data->devices[i];
|
||||
hwloc_obj_t osdev;
|
||||
char buffer[64];
|
||||
|
||||
assert(info->type == HWLOC_OPENCL_DEVICE_AMD);
|
||||
if (info->specific.amd.pcidomain != pcidev->attr->pcidev.domain)
|
||||
continue;
|
||||
if (info->specific.amd.pcibus != pcidev->attr->pcidev.bus)
|
||||
continue;
|
||||
if (info->specific.amd.pcidev != pcidev->attr->pcidev.dev)
|
||||
continue;
|
||||
if (info->specific.amd.pcifunc != pcidev->attr->pcidev.func)
|
||||
continue;
|
||||
|
||||
osdev = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1);
|
||||
snprintf(buffer, sizeof(buffer), "opencl%dd%d", info->platformidx, info->platformdeviceidx);
|
||||
osdev->name = strdup(buffer);
|
||||
osdev->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN;
|
||||
osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_COPROC;
|
||||
|
||||
hwloc_obj_add_info(osdev, "CoProcType", "OpenCL");
|
||||
hwloc_obj_add_info(osdev, "Backend", "OpenCL");
|
||||
hwloc_obj_add_info(osdev, "OpenCLDeviceType", info->devicetype);
|
||||
|
||||
if (info->devicevendor[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "GPUVendor", info->devicevendor);
|
||||
if (info->devicename[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "GPUModel", info->devicename);
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%u", info->platformidx);
|
||||
hwloc_obj_add_info(osdev, "OpenCLPlatformIndex", buffer);
|
||||
if (info->platformname[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "OpenCLPlatformName", info->platformname);
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%u", info->platformdeviceidx);
|
||||
hwloc_obj_add_info(osdev, "OpenCLPlatformDeviceIndex", buffer);
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%u", info->computeunits);
|
||||
hwloc_obj_add_info(osdev, "OpenCLComputeUnits", buffer);
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%llu", info->globalmemsize);
|
||||
hwloc_obj_add_info(osdev, "OpenCLGlobalMemorySize", buffer);
|
||||
|
||||
hwloc_insert_object_by_parent(topology, pcidev, osdev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_opencl_backend_disable(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_opencl_backend_data_s *data = backend->private_data;
|
||||
free(data->devices);
|
||||
free(data);
|
||||
}
|
||||
|
||||
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;
|
||||
struct hwloc_opencl_backend_data_s *data;
|
||||
|
||||
/* thissystem may not be fully initialized yet, we'll check flags in discover() */
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (!data) {
|
||||
free(backend);
|
||||
return NULL;
|
||||
}
|
||||
/* the first callback will initialize those */
|
||||
data->nr_devices = (unsigned) -1; /* unknown yet */
|
||||
data->devices = NULL;
|
||||
|
||||
backend->private_data = data;
|
||||
backend->disable = hwloc_opencl_backend_disable;
|
||||
|
||||
backend->notify_new_object = hwloc_opencl_backend_notify_new_object;
|
||||
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
|
||||
};
|
@ -1,392 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2011 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>
|
||||
#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 <pthread.h>
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#include <numa.h>
|
||||
#include <radset.h>
|
||||
#include <cpuset.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
/*
|
||||
* TODO
|
||||
*
|
||||
* nsg_init(), nsg_attach_pid(), RAD_MIGRATE/RAD_WAIT
|
||||
* assign_pid_to_pset()
|
||||
*
|
||||
* pthread_use_only_cpu too?
|
||||
*/
|
||||
|
||||
static int
|
||||
prepare_radset(hwloc_topology_t topology __hwloc_attribute_unused, radset_t *radset, hwloc_const_bitmap_t hwloc_set)
|
||||
{
|
||||
unsigned cpu;
|
||||
cpuset_t target_cpuset;
|
||||
cpuset_t cpuset, xor_cpuset;
|
||||
radid_t radid;
|
||||
int ret = 0;
|
||||
int ret_errno = 0;
|
||||
int nbnodes = rad_get_num();
|
||||
|
||||
cpusetcreate(&target_cpuset);
|
||||
cpuemptyset(target_cpuset);
|
||||
hwloc_bitmap_foreach_begin(cpu, hwloc_set)
|
||||
cpuaddset(target_cpuset, cpu);
|
||||
hwloc_bitmap_foreach_end();
|
||||
|
||||
cpusetcreate(&cpuset);
|
||||
cpusetcreate(&xor_cpuset);
|
||||
for (radid = 0; radid < nbnodes; radid++) {
|
||||
cpuemptyset(cpuset);
|
||||
if (rad_get_cpus(radid, cpuset)==-1) {
|
||||
fprintf(stderr,"rad_get_cpus(%d) failed: %s\n",radid,strerror(errno));
|
||||
continue;
|
||||
}
|
||||
cpuxorset(target_cpuset, cpuset, xor_cpuset);
|
||||
if (cpucountset(xor_cpuset) == 0) {
|
||||
/* Found it */
|
||||
radsetcreate(radset);
|
||||
rademptyset(*radset);
|
||||
radaddset(*radset, radid);
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* radset containing exactly this set of CPUs not found */
|
||||
ret_errno = EXDEV;
|
||||
|
||||
out:
|
||||
cpusetdestroy(&target_cpuset);
|
||||
cpusetdestroy(&cpuset);
|
||||
cpusetdestroy(&xor_cpuset);
|
||||
errno = ret_errno;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Note: get_cpubind not available on OSF */
|
||||
|
||||
static int
|
||||
hwloc_osf_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t thread, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
radset_t radset;
|
||||
|
||||
if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) {
|
||||
if ((errno = pthread_rad_detach(thread)))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Apparently OSF migrates pages */
|
||||
if (flags & HWLOC_CPUBIND_NOMEMBIND) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!prepare_radset(topology, &radset, hwloc_set))
|
||||
return -1;
|
||||
|
||||
if (flags & HWLOC_CPUBIND_STRICT) {
|
||||
if ((errno = pthread_rad_bind(thread, radset, RAD_INSIST | RAD_WAIT)))
|
||||
return -1;
|
||||
} else {
|
||||
if ((errno = pthread_rad_attach(thread, radset, RAD_WAIT)))
|
||||
return -1;
|
||||
}
|
||||
radsetdestroy(&radset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_osf_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
radset_t radset;
|
||||
|
||||
if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) {
|
||||
if (rad_detach_pid(pid))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Apparently OSF migrates pages */
|
||||
if (flags & HWLOC_CPUBIND_NOMEMBIND) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!prepare_radset(topology, &radset, hwloc_set))
|
||||
return -1;
|
||||
|
||||
if (flags & HWLOC_CPUBIND_STRICT) {
|
||||
if (rad_bind_pid(pid, radset, RAD_INSIST | RAD_WAIT))
|
||||
return -1;
|
||||
} else {
|
||||
if (rad_attach_pid(pid, radset, RAD_WAIT))
|
||||
return -1;
|
||||
}
|
||||
radsetdestroy(&radset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_osf_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
return hwloc_osf_set_thread_cpubind(topology, pthread_self(), hwloc_set, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_osf_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
return hwloc_osf_set_proc_cpubind(topology, getpid(), hwloc_set, flags);
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_osf_prepare_mattr(hwloc_topology_t topology __hwloc_attribute_unused, memalloc_attr_t *mattr, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
unsigned long osf_policy;
|
||||
int node;
|
||||
|
||||
switch (policy) {
|
||||
case HWLOC_MEMBIND_FIRSTTOUCH:
|
||||
osf_policy = MPOL_THREAD;
|
||||
break;
|
||||
case HWLOC_MEMBIND_DEFAULT:
|
||||
case HWLOC_MEMBIND_BIND:
|
||||
osf_policy = MPOL_DIRECTED;
|
||||
break;
|
||||
case HWLOC_MEMBIND_INTERLEAVE:
|
||||
osf_policy = MPOL_STRIPPED;
|
||||
break;
|
||||
case HWLOC_MEMBIND_REPLICATE:
|
||||
osf_policy = MPOL_REPLICATED;
|
||||
break;
|
||||
default:
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(mattr, 0, sizeof(*mattr));
|
||||
mattr->mattr_policy = osf_policy;
|
||||
mattr->mattr_rad = RAD_NONE;
|
||||
radsetcreate(&mattr->mattr_radset);
|
||||
rademptyset(mattr->mattr_radset);
|
||||
|
||||
hwloc_bitmap_foreach_begin(node, nodeset)
|
||||
radaddset(mattr->mattr_radset, node);
|
||||
hwloc_bitmap_foreach_end();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_osf_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)
|
||||
{
|
||||
memalloc_attr_t mattr;
|
||||
int behavior = 0;
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_MIGRATE)
|
||||
behavior |= MADV_CURRENT;
|
||||
if (flags & HWLOC_MEMBIND_STRICT)
|
||||
behavior |= MADV_INSIST;
|
||||
|
||||
if (hwloc_osf_prepare_mattr(topology, &mattr, nodeset, policy, flags))
|
||||
return -1;
|
||||
|
||||
ret = nmadvise(addr, len, MADV_CURRENT, &mattr);
|
||||
radsetdestroy(&mattr.mattr_radset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *
|
||||
hwloc_osf_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
memalloc_attr_t mattr;
|
||||
void *ptr;
|
||||
|
||||
if (hwloc_osf_prepare_mattr(topology, &mattr, nodeset, policy, flags))
|
||||
return hwloc_alloc_or_fail(topology, len, flags);
|
||||
|
||||
/* TODO: rather use acreate/amalloc ? */
|
||||
ptr = nmmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1,
|
||||
0, &mattr);
|
||||
radsetdestroy(&mattr.mattr_radset);
|
||||
return ptr == MAP_FAILED ? NULL : ptr;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_look_osf(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
cpu_cursor_t cursor;
|
||||
unsigned nbnodes;
|
||||
radid_t radid, radid2;
|
||||
radset_t radset, radset2;
|
||||
cpuid_t cpuid;
|
||||
cpuset_t cpuset;
|
||||
struct hwloc_obj *obj;
|
||||
unsigned distance;
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return 0;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
|
||||
nbnodes = rad_get_num();
|
||||
|
||||
cpusetcreate(&cpuset);
|
||||
radsetcreate(&radset);
|
||||
radsetcreate(&radset2);
|
||||
{
|
||||
hwloc_obj_t *nodes = calloc(nbnodes, sizeof(hwloc_obj_t));
|
||||
unsigned *indexes = calloc(nbnodes, sizeof(unsigned));
|
||||
float *distances = calloc(nbnodes*nbnodes, sizeof(float));
|
||||
unsigned nfound;
|
||||
numa_attr_t attr;
|
||||
|
||||
attr.nattr_type = R_RAD;
|
||||
attr.nattr_descr.rd_radset = radset;
|
||||
attr.nattr_flags = 0;
|
||||
|
||||
for (radid = 0; radid < (radid_t) nbnodes; radid++) {
|
||||
rademptyset(radset);
|
||||
radaddset(radset, radid);
|
||||
cpuemptyset(cpuset);
|
||||
if (rad_get_cpus(radid, cpuset)==-1) {
|
||||
fprintf(stderr,"rad_get_cpus(%d) failed: %s\n",radid,strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
indexes[radid] = radid;
|
||||
nodes[radid] = obj = hwloc_alloc_setup_object(HWLOC_OBJ_NUMANODE, radid);
|
||||
obj->nodeset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(obj->nodeset, radid);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
obj->memory.local_memory = rad_get_physmem(radid) * hwloc_getpagesize();
|
||||
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
|
||||
|
||||
cursor = SET_CURSOR_INIT;
|
||||
while((cpuid = cpu_foreach(cpuset, 0, &cursor)) != CPU_NONE)
|
||||
hwloc_bitmap_set(obj->cpuset, cpuid);
|
||||
|
||||
hwloc_debug_1arg_bitmap("node %d has cpuset %s\n",
|
||||
radid, obj->cpuset);
|
||||
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
|
||||
nfound = 0;
|
||||
for (radid2 = 0; radid2 < (radid_t) nbnodes; radid2++)
|
||||
distances[radid*nbnodes+radid2] = RAD_DIST_REMOTE;
|
||||
for (distance = RAD_DIST_LOCAL; distance < RAD_DIST_REMOTE; distance++) {
|
||||
attr.nattr_distance = distance;
|
||||
/* get set of NUMA nodes at distance <= DISTANCE */
|
||||
if (nloc(&attr, radset2)) {
|
||||
fprintf(stderr,"nloc failed: %s\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
cursor = SET_CURSOR_INIT;
|
||||
while ((radid2 = rad_foreach(radset2, 0, &cursor)) != RAD_NONE) {
|
||||
if (distances[radid*nbnodes+radid2] == RAD_DIST_REMOTE) {
|
||||
distances[radid*nbnodes+radid2] = (float) distance;
|
||||
nfound++;
|
||||
}
|
||||
}
|
||||
if (nfound == nbnodes)
|
||||
/* Finished finding distances, no need to go up to RAD_DIST_REMOTE */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hwloc_distances_set(topology, HWLOC_OBJ_NUMANODE, nbnodes, indexes, nodes, distances, 0 /* OS cannot force */);
|
||||
}
|
||||
radsetdestroy(&radset2);
|
||||
radsetdestroy(&radset);
|
||||
cpusetdestroy(&cpuset);
|
||||
|
||||
/* add PU objects */
|
||||
hwloc_setup_pu_level(topology, hwloc_fallback_nbprocessors(topology));
|
||||
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "OSF");
|
||||
if (topology->is_thissystem)
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_set_osf_hooks(struct hwloc_binding_hooks *hooks,
|
||||
struct hwloc_topology_support *support)
|
||||
{
|
||||
hooks->set_thread_cpubind = hwloc_osf_set_thread_cpubind;
|
||||
hooks->set_thisthread_cpubind = hwloc_osf_set_thisthread_cpubind;
|
||||
hooks->set_proc_cpubind = hwloc_osf_set_proc_cpubind;
|
||||
hooks->set_thisproc_cpubind = hwloc_osf_set_thisproc_cpubind;
|
||||
hooks->set_area_membind = hwloc_osf_set_area_membind;
|
||||
hooks->alloc_membind = hwloc_osf_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;
|
||||
support->membind->replicate_membind = 1;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_osf_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_osf;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_osf_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_CPU,
|
||||
"osf",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_osf_component_instantiate,
|
||||
50,
|
||||
NULL
|
||||
};
|
||||
|
||||
const struct hwloc_component hwloc_osf_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
NULL, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_osf_disc_component
|
||||
};
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@ -1,715 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#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;
|
||||
default:
|
||||
return (hwloc_obj_type_t) -1;
|
||||
}
|
||||
return topology->levels[depth][0]->type;
|
||||
}
|
||||
|
||||
unsigned
|
||||
hwloc_get_nbobjs_by_depth (struct hwloc_topology *topology, unsigned depth)
|
||||
{
|
||||
if (depth >= topology->nb_levels)
|
||||
switch (depth) {
|
||||
case HWLOC_TYPE_DEPTH_BRIDGE:
|
||||
return topology->bridge_nbobjects;
|
||||
case HWLOC_TYPE_DEPTH_PCI_DEVICE:
|
||||
return topology->pcidev_nbobjects;
|
||||
case HWLOC_TYPE_DEPTH_OS_DEVICE:
|
||||
return topology->osdev_nbobjects;
|
||||
default:
|
||||
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)
|
||||
switch (depth) {
|
||||
case HWLOC_TYPE_DEPTH_BRIDGE:
|
||||
return idx < topology->bridge_nbobjects ? topology->bridge_level[idx] : NULL;
|
||||
case HWLOC_TYPE_DEPTH_PCI_DEVICE:
|
||||
return idx < topology->pcidev_nbobjects ? topology->pcidev_level[idx] : NULL;
|
||||
case HWLOC_TYPE_DEPTH_OS_DEVICE:
|
||||
return idx < topology->osdev_nbobjects ? topology->osdev_level[idx] : NULL;
|
||||
default:
|
||||
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 (!nextparent->cpuset || !hwloc_bitmap_isequal(parent->cpuset, nextparent->cpuset))
|
||||
break;
|
||||
parent = nextparent;
|
||||
}
|
||||
|
||||
if (!nextparent->cpuset)
|
||||
break;
|
||||
|
||||
/* 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 = hwloc_bitmap_dup(set);
|
||||
int ret;
|
||||
|
||||
/* split out the cpuset part corresponding to this child and see if there's anything to do */
|
||||
if (current->children[i]->cpuset) {
|
||||
hwloc_bitmap_and(subset, subset, current->children[i]->cpuset);
|
||||
if (hwloc_bitmap_iszero(subset)) {
|
||||
hwloc_bitmap_free(subset);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
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 (!current->cpuset || !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_obj_type_string (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_CACHE: return "Cache";
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
hwloc_obj_type_t
|
||||
hwloc_obj_type_of_string (const char * string)
|
||||
{
|
||||
if (!strcasecmp(string, "System")) return HWLOC_OBJ_SYSTEM;
|
||||
if (!strcasecmp(string, "Machine")) return HWLOC_OBJ_MACHINE;
|
||||
if (!strcasecmp(string, "Misc")) return HWLOC_OBJ_MISC;
|
||||
if (!strcasecmp(string, "Group")) return HWLOC_OBJ_GROUP;
|
||||
if (!strcasecmp(string, "NUMANode") || !strcasecmp(string, "Node")) return HWLOC_OBJ_NUMANODE;
|
||||
if (!strcasecmp(string, "Package") || !strcasecmp(string, "Socket") /* backward compat with v1.10 */) return HWLOC_OBJ_PACKAGE;
|
||||
if (!strcasecmp(string, "Cache")) return HWLOC_OBJ_CACHE;
|
||||
if (!strcasecmp(string, "Core")) return HWLOC_OBJ_CORE;
|
||||
if (!strcasecmp(string, "PU")) return HWLOC_OBJ_PU;
|
||||
if (!strcasecmp(string, "Bridge") || !strcasecmp(string, "HostBridge") || !strcasecmp(string, "PCIBridge")) return HWLOC_OBJ_BRIDGE;
|
||||
if (!strcasecmp(string, "PCIDev")) return HWLOC_OBJ_PCI_DEVICE;
|
||||
if (!strcasecmp(string, "OSDev")) return HWLOC_OBJ_OS_DEVICE;
|
||||
return (hwloc_obj_type_t) -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, void *typeattrp, size_t typeattrsize)
|
||||
{
|
||||
hwloc_obj_type_t type = (hwloc_obj_type_t) -1;
|
||||
int depthattr = -1;
|
||||
hwloc_obj_cache_type_t cachetypeattr = (hwloc_obj_cache_type_t) -1; /* unspecified */
|
||||
char *end;
|
||||
|
||||
/* never match the ending \0 since we want to match things like core:2 too.
|
||||
* just use hwloc_strncasecmp() everywhere.
|
||||
*/
|
||||
|
||||
/* types without depthattr */
|
||||
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)
|
||||
|| !hwloc_strncasecmp(string, "hostbridge", 6)
|
||||
|| !hwloc_strncasecmp(string, "pcibridge", 5)) {
|
||||
type = HWLOC_OBJ_BRIDGE;
|
||||
} else if (!hwloc_strncasecmp(string, "pci", 3)) {
|
||||
type = HWLOC_OBJ_PCI_DEVICE;
|
||||
} else if (!hwloc_strncasecmp(string, "os", 2)
|
||||
|| !hwloc_strncasecmp(string, "bloc", 4)
|
||||
|| !hwloc_strncasecmp(string, "net", 3)
|
||||
|| !hwloc_strncasecmp(string, "openfab", 7)
|
||||
|| !hwloc_strncasecmp(string, "dma", 3)
|
||||
|| !hwloc_strncasecmp(string, "gpu", 3)
|
||||
|| !hwloc_strncasecmp(string, "copro", 5)
|
||||
|| !hwloc_strncasecmp(string, "co-pro", 6)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
|
||||
/* types with depthattr */
|
||||
} else if (!hwloc_strncasecmp(string, "cache", 2)) {
|
||||
type = HWLOC_OBJ_CACHE;
|
||||
|
||||
} else if ((string[0] == 'l' || string[0] == 'L') && string[1] >= '0' && string[1] <= '9') {
|
||||
type = HWLOC_OBJ_CACHE;
|
||||
depthattr = strtol(string+1, &end, 10);
|
||||
if (*end == 'd') {
|
||||
cachetypeattr = HWLOC_OBJ_CACHE_DATA;
|
||||
} else if (*end == 'i') {
|
||||
cachetypeattr = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
} else if (*end == 'u') {
|
||||
cachetypeattr = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
}
|
||||
|
||||
} 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 (depthattrp)
|
||||
*depthattrp = depthattr;
|
||||
if (typeattrp) {
|
||||
if (type == HWLOC_OBJ_CACHE && sizeof(hwloc_obj_cache_type_t) <= typeattrsize)
|
||||
memcpy(typeattrp, &cachetypeattr, sizeof(hwloc_obj_cache_type_t));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *
|
||||
hwloc_pci_class_string(unsigned short class_id)
|
||||
{
|
||||
switch ((class_id & 0xff00) >> 8) {
|
||||
case 0x00:
|
||||
switch (class_id) {
|
||||
case 0x0001: return "VGA";
|
||||
}
|
||||
return "PCI";
|
||||
case 0x01:
|
||||
switch (class_id) {
|
||||
case 0x0100: return "SCSI";
|
||||
case 0x0101: return "IDE";
|
||||
case 0x0102: return "Flop";
|
||||
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 "Stor";
|
||||
case 0x02:
|
||||
switch (class_id) {
|
||||
case 0x0200: return "Ether";
|
||||
case 0x0201: return "TokRn";
|
||||
case 0x0202: return "FDDI";
|
||||
case 0x0203: return "ATM";
|
||||
case 0x0204: return "ISDN";
|
||||
case 0x0205: return "WrdFip";
|
||||
case 0x0206: return "PICMG";
|
||||
case 0x0207: return "IB";
|
||||
case 0x0208: return "FI";
|
||||
}
|
||||
return "Net";
|
||||
case 0x03:
|
||||
switch (class_id) {
|
||||
case 0x0300: return "VGA";
|
||||
case 0x0301: return "XGA";
|
||||
case 0x0302: return "3D";
|
||||
}
|
||||
return "Disp";
|
||||
case 0x04:
|
||||
switch (class_id) {
|
||||
case 0x0400: return "Video";
|
||||
case 0x0401: return "Audio";
|
||||
case 0x0402: return "Phone";
|
||||
case 0x0403: return "Auddv";
|
||||
}
|
||||
return "MM";
|
||||
case 0x05:
|
||||
switch (class_id) {
|
||||
case 0x0500: return "RAM";
|
||||
case 0x0501: return "Flash";
|
||||
}
|
||||
return "Mem";
|
||||
case 0x06:
|
||||
switch (class_id) {
|
||||
case 0x0600: return "Host";
|
||||
case 0x0601: return "ISA";
|
||||
case 0x0602: return "EISA";
|
||||
case 0x0603: return "MC";
|
||||
case 0x0604: return "PCI_B";
|
||||
case 0x0605: return "PCMCIA";
|
||||
case 0x0606: return "Nubus";
|
||||
case 0x0607: return "CardBus";
|
||||
case 0x0608: return "RACEway";
|
||||
case 0x0609: return "PCI_SB";
|
||||
case 0x060a: return "IB_B";
|
||||
}
|
||||
return "Bridg";
|
||||
case 0x07:
|
||||
switch (class_id) {
|
||||
case 0x0700: return "Ser";
|
||||
case 0x0701: return "Para";
|
||||
case 0x0702: return "MSer";
|
||||
case 0x0703: return "Modm";
|
||||
case 0x0704: return "GPIB";
|
||||
case 0x0705: return "SmrtCrd";
|
||||
}
|
||||
return "Comm";
|
||||
case 0x08:
|
||||
switch (class_id) {
|
||||
case 0x0800: return "PIC";
|
||||
case 0x0801: return "DMA";
|
||||
case 0x0802: return "Time";
|
||||
case 0x0803: return "RTC";
|
||||
case 0x0804: return "HtPl";
|
||||
case 0x0805: return "SD-HtPl";
|
||||
case 0x0806: return "IOMMU";
|
||||
}
|
||||
return "Syst";
|
||||
case 0x09:
|
||||
switch (class_id) {
|
||||
case 0x0900: return "Kbd";
|
||||
case 0x0901: return "Pen";
|
||||
case 0x0902: return "Mouse";
|
||||
case 0x0903: return "Scan";
|
||||
case 0x0904: return "Game";
|
||||
}
|
||||
return "In";
|
||||
case 0x0a:
|
||||
return "Dock";
|
||||
case 0x0b:
|
||||
switch (class_id) {
|
||||
case 0x0b00: return "386";
|
||||
case 0x0b01: return "486";
|
||||
case 0x0b02: return "Pent";
|
||||
case 0x0b10: return "Alpha";
|
||||
case 0x0b20: return "PPC";
|
||||
case 0x0b30: return "MIPS";
|
||||
case 0x0b40: return "CoProc";
|
||||
}
|
||||
return "Proc";
|
||||
case 0x0c:
|
||||
switch (class_id) {
|
||||
case 0x0c00: return "Firw";
|
||||
case 0x0c01: return "ACCES";
|
||||
case 0x0c02: return "SSA";
|
||||
case 0x0c03: return "USB";
|
||||
case 0x0c04: return "Fibre";
|
||||
case 0x0c05: return "SMBus";
|
||||
case 0x0c06: return "IB";
|
||||
case 0x0c07: return "IPMI";
|
||||
case 0x0c08: return "SERCOS";
|
||||
case 0x0c09: return "CANBUS";
|
||||
}
|
||||
return "Ser";
|
||||
case 0x0d:
|
||||
switch (class_id) {
|
||||
case 0x0d00: return "IRDA";
|
||||
case 0x0d01: return "IR";
|
||||
case 0x0d10: return "RF";
|
||||
case 0x0d11: return "Blueth";
|
||||
case 0x0d12: return "BroadB";
|
||||
case 0x0d20: return "802.1a";
|
||||
case 0x0d21: return "802.1b";
|
||||
}
|
||||
return "Wifi";
|
||||
case 0x0e:
|
||||
switch (class_id) {
|
||||
case 0x0e00: return "I2O";
|
||||
}
|
||||
return "Intll";
|
||||
case 0x0f:
|
||||
switch (class_id) {
|
||||
case 0x0f00: return "S-TV";
|
||||
case 0x0f01: return "S-Aud";
|
||||
case 0x0f02: return "S-Voice";
|
||||
case 0x0f03: return "S-Data";
|
||||
}
|
||||
return "Satel";
|
||||
case 0x10:
|
||||
return "Crypt";
|
||||
case 0x11:
|
||||
return "Signl";
|
||||
case 0x12:
|
||||
return "Accel";
|
||||
case 0x13:
|
||||
return "Instr";
|
||||
case 0xff:
|
||||
return "Oth";
|
||||
}
|
||||
return "PCI";
|
||||
}
|
||||
|
||||
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_obj_type_string(type));
|
||||
case HWLOC_OBJ_CACHE:
|
||||
return hwloc_snprintf(string, size, "L%u%s%s", obj->attr->cache.depth,
|
||||
hwloc_obj_cache_type_letter(obj->attr->cache.type),
|
||||
verbose ? hwloc_obj_type_string(type): "");
|
||||
case HWLOC_OBJ_GROUP:
|
||||
/* TODO: more pretty presentation? */
|
||||
if (obj->attr->group.depth != (unsigned) -1)
|
||||
return hwloc_snprintf(string, size, "%s%u", hwloc_obj_type_string(type), obj->attr->group.depth);
|
||||
else
|
||||
return hwloc_snprintf(string, size, "%s", hwloc_obj_type_string(type));
|
||||
case HWLOC_OBJ_BRIDGE:
|
||||
if (verbose)
|
||||
return snprintf(string, size, "Bridge %s->%s",
|
||||
obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI ? "PCI" : "Host",
|
||||
"PCI");
|
||||
else
|
||||
return snprintf(string, size, obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI ? "PCIBridge" : "HostBridge");
|
||||
case HWLOC_OBJ_PCI_DEVICE:
|
||||
return snprintf(string, size, "PCI %04x:%04x",
|
||||
obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id);
|
||||
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_CACHE:
|
||||
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]= "";
|
||||
char busid[16] = "[collapsed]";
|
||||
if (obj->attr->pcidev.linkspeed)
|
||||
snprintf(linkspeed, sizeof(linkspeed), "%slink=%.2fGB/s", separator, obj->attr->pcidev.linkspeed);
|
||||
if (!hwloc_obj_get_info_by_name(obj, "lstopoCollapse"))
|
||||
snprintf(busid, sizeof(busid), "%04x:%02x:%02x.%01x",
|
||||
obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func);
|
||||
res = snprintf(string, size, "busid=%s%sclass=%04x(%s)%s",
|
||||
busid, 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 (!strcmp(obj->infos[i].name, "lstopoCollapse"))
|
||||
continue;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
hwloc_obj_snprintf(char *string, size_t size,
|
||||
struct hwloc_topology *topology __hwloc_attribute_unused, struct hwloc_obj *l, const char *_indexprefix, int verbose)
|
||||
{
|
||||
const char *indexprefix = _indexprefix ? _indexprefix : "#";
|
||||
char os_index[12] = "";
|
||||
char type[64];
|
||||
char attr[128];
|
||||
int attrlen;
|
||||
|
||||
if (l->os_index != (unsigned) -1) {
|
||||
hwloc_snprintf(os_index, 12, "%s%u", indexprefix, l->os_index);
|
||||
}
|
||||
|
||||
hwloc_obj_type_snprintf(type, sizeof(type), l, verbose);
|
||||
attrlen = hwloc_obj_attr_snprintf(attr, sizeof(attr), l, " ", verbose);
|
||||
|
||||
if (attrlen > 0)
|
||||
return hwloc_snprintf(string, size, "%s%s(%s)", type, os_index, attr);
|
||||
else
|
||||
return hwloc_snprintf(string, size, "%s%s", type, os_index);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
#
|
||||
# Copyright (c) 2011-2016 Cisco Systems, Inc. All rights reserved.
|
||||
# Copyright (c) 2014-2015 Intel, Inc. All right reserved.
|
||||
# Copyright (c) 2014-2017 Intel, Inc. All rights reserved.
|
||||
# Copyright (c) 2016 Los Alamos National Security, LLC. All rights
|
||||
# reserved.
|
||||
# Copyright (c) 2017 Research Organization for Information Science
|
||||
@ -30,17 +30,17 @@ EXTRA_DIST = \
|
||||
SUBDIRS = hwloc
|
||||
|
||||
# Headers and sources
|
||||
headers = hwloc1116.h
|
||||
sources = hwloc1116_component.c
|
||||
headers = hwloc2a.h
|
||||
sources = hwloc2a_component.c
|
||||
|
||||
# We only ever build this component statically
|
||||
noinst_LTLIBRARIES = libmca_hwloc_hwloc1116.la
|
||||
libmca_hwloc_hwloc1116_la_SOURCES = $(headers) $(sources)
|
||||
nodist_libmca_hwloc_hwloc1116_la_SOURCES = $(nodist_headers)
|
||||
libmca_hwloc_hwloc1116_la_LDFLAGS = -module -avoid-version $(opal_hwloc_hwloc1116_LDFLAGS)
|
||||
libmca_hwloc_hwloc1116_la_LIBADD = $(opal_hwloc_hwloc1116_LIBS)
|
||||
libmca_hwloc_hwloc1116_la_DEPENDENCIES = \
|
||||
$(HWLOC_top_builddir)/src/libhwloc_embedded.la
|
||||
noinst_LTLIBRARIES = libmca_hwloc_hwloc2a.la
|
||||
libmca_hwloc_hwloc2a_la_SOURCES = $(headers) $(sources)
|
||||
nodist_libmca_hwloc_hwloc2a_la_SOURCES = $(nodist_headers)
|
||||
libmca_hwloc_hwloc2a_la_LDFLAGS = -module -avoid-version $(opal_hwloc_hwloc2a_LDFLAGS)
|
||||
libmca_hwloc_hwloc2a_la_LIBADD = $(opal_hwloc_hwloc2a_LIBS)
|
||||
libmca_hwloc_hwloc2a_la_DEPENDENCIES = \
|
||||
$(HWLOC_top_builddir)/hwloc/libhwloc_embedded.la
|
||||
|
||||
# Since the rest of the code base includes the underlying hwloc.h, we
|
||||
# also have to install the underlying header files when
|
||||
@ -54,6 +54,8 @@ headers += \
|
||||
hwloc/include/hwloc/cudart.h \
|
||||
hwloc/include/hwloc/deprecated.h \
|
||||
hwloc/include/hwloc/diff.h \
|
||||
hwloc/include/hwloc/distances.h \
|
||||
hwloc/include/hwloc/export.h \
|
||||
hwloc/include/hwloc/gl.h \
|
||||
hwloc/include/hwloc/helper.h \
|
||||
hwloc/include/hwloc/inlines.h \
|
||||
@ -64,6 +66,7 @@ headers += \
|
||||
hwloc/include/hwloc/openfabrics-verbs.h \
|
||||
hwloc/include/hwloc/plugins.h \
|
||||
hwloc/include/hwloc/rename.h \
|
||||
hwloc/include/hwloc/shmem.h \
|
||||
hwloc/include/private/private.h \
|
||||
hwloc/include/private/debug.h \
|
||||
hwloc/include/private/misc.h \
|
||||
@ -76,6 +79,11 @@ headers += \
|
||||
hwloc/include/hwloc/linux-libnuma.h
|
||||
endif HWLOC_HAVE_LINUX
|
||||
|
||||
if HWLOC_HAVE_SOLARIS
|
||||
headers += \
|
||||
hwloc/include/private/solaris-chiptype.h
|
||||
endif HWLOC_HAVE_SOLARIS
|
||||
|
||||
if HWLOC_HAVE_SCHED_SETAFFINITY
|
||||
headers += hwloc/include/hwloc/glibc-sched.h
|
||||
endif HWLOC_HAVE_SCHED_SETAFFINITY
|
1
opal/mca/hwloc/hwloc2a/README-ompi.txt
Обычный файл
1
opal/mca/hwloc/hwloc2a/README-ompi.txt
Обычный файл
@ -0,0 +1 @@
|
||||
Cherry-picked commits after 2.0.0:
|
@ -1,7 +1,7 @@
|
||||
# -*- shell-script -*-
|
||||
#
|
||||
# Copyright (c) 2009-2017 Cisco Systems, Inc. All rights reserved
|
||||
# Copyright (c) 2014-2015 Intel, Inc. All rights reserved.
|
||||
# Copyright (c) 2014-2017 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
|
||||
@ -17,41 +17,43 @@
|
||||
#
|
||||
# Priority
|
||||
#
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc1116_PRIORITY], [90])
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc2a_PRIORITY], [90])
|
||||
|
||||
#
|
||||
# Force this component to compile in static-only mode
|
||||
#
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc1116_COMPILE_MODE], [
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc2a_COMPILE_MODE], [
|
||||
AC_MSG_CHECKING([for MCA component $2:$3 compile mode])
|
||||
$4="static"
|
||||
AC_MSG_RESULT([$$4])
|
||||
])
|
||||
|
||||
# Include hwloc m4 files
|
||||
m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_pkg.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_attributes.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_visibility.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_check_vendor.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc1116/hwloc/config/hwloc_components.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_pkg.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_attributes.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_visibility.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_check_vendor.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_components.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/hwloc_internal.m4)
|
||||
m4_include(opal/mca/hwloc/hwloc2a/hwloc/config/netloc.m4)
|
||||
|
||||
# MCA_hwloc_hwloc1116_POST_CONFIG()
|
||||
# MCA_hwloc_hwloc2a_POST_CONFIG()
|
||||
# ---------------------------------
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc1116_POST_CONFIG],[
|
||||
OPAL_VAR_SCOPE_PUSH([opal_hwloc_hwloc1116_basedir])
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc2a_POST_CONFIG],[
|
||||
OPAL_VAR_SCOPE_PUSH([opal_hwloc_hwloc2a_basedir])
|
||||
|
||||
# If we won, then do all the rest of the setup
|
||||
AS_IF([test "$1" = "1" && test "$opal_hwloc_hwloc1116_support" = "yes"],
|
||||
AS_IF([test "$1" = "1" && test "$opal_hwloc_hwloc2a_support" = "yes"],
|
||||
[
|
||||
# Set this variable so that the framework m4 knows what
|
||||
# file to include in opal/mca/hwloc/hwloc-internal.h
|
||||
opal_hwloc_hwloc1116_basedir=opal/mca/hwloc/hwloc1116
|
||||
opal_hwloc_base_include="$opal_hwloc_hwloc1116_basedir/hwloc1116.h"
|
||||
opal_hwloc_hwloc2a_basedir=opal/mca/hwloc/hwloc2a
|
||||
opal_hwloc_base_include="$opal_hwloc_hwloc2a_basedir/hwloc2a.h"
|
||||
|
||||
# Add some stuff to CPPFLAGS so that the rest of the source
|
||||
# tree can be built
|
||||
file=$opal_hwloc_hwloc1116_basedir/hwloc
|
||||
file=$opal_hwloc_hwloc2a_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"])
|
||||
@ -64,40 +66,41 @@ AC_DEFUN([MCA_opal_hwloc_hwloc1116_POST_CONFIG],[
|
||||
])dnl
|
||||
|
||||
|
||||
# MCA_hwloc_hwloc1116_CONFIG([action-if-found], [action-if-not-found])
|
||||
# MCA_hwloc_hwloc2a_CONFIG([action-if-found], [action-if-not-found])
|
||||
# --------------------------------------------------------------------
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc1116_CONFIG],[
|
||||
AC_DEFUN([MCA_opal_hwloc_hwloc2a_CONFIG],[
|
||||
# Hwloc needs to know if we have Verbs support
|
||||
AC_REQUIRE([OPAL_CHECK_VERBS_DIR])
|
||||
|
||||
AC_CONFIG_FILES([opal/mca/hwloc/hwloc1116/Makefile])
|
||||
AC_CONFIG_FILES([opal/mca/hwloc/hwloc2a/Makefile])
|
||||
|
||||
OPAL_VAR_SCOPE_PUSH([HWLOC_VERSION opal_hwloc_hwloc1116_save_CPPFLAGS opal_hwloc_hwloc1116_save_LDFLAGS opal_hwloc_hwloc1116_save_LIBS opal_hwloc_hwloc1116_save_cairo opal_hwloc_hwloc1116_save_xml opal_hwloc_hwloc1116_basedir opal_hwloc_hwloc1116_file opal_hwloc_hwloc1116_save_cflags CPPFLAGS_save LIBS_save opal_hwloc_external])
|
||||
OPAL_VAR_SCOPE_PUSH([HWLOC_VERSION opal_hwloc_hwloc2a_save_CPPFLAGS opal_hwloc_hwloc2a_save_LDFLAGS opal_hwloc_hwloc2a_save_LIBS opal_hwloc_hwloc2a_save_cairo opal_hwloc_hwloc2a_save_xml opal_hwloc_hwloc2a_save_mode opal_hwloc_hwloc2a_basedir opal_hwloc_hwloc2a_file opal_hwloc_hwloc2a_save_cflags CPPFLAGS_save LIBS_save opal_hwloc_external])
|
||||
|
||||
# default to this component not providing support
|
||||
opal_hwloc_hwloc1116_basedir=opal/mca/hwloc/hwloc1116
|
||||
opal_hwloc_hwloc1116_support=no
|
||||
opal_hwloc_hwloc2a_basedir=opal/mca/hwloc/hwloc2a
|
||||
opal_hwloc_hwloc2a_support=no
|
||||
|
||||
AS_IF([test "$with_hwloc" = "internal" || test -z "$with_hwloc" || test "$with_hwloc" = "yes"],
|
||||
[opal_hwloc_external="no"],
|
||||
[opal_hwloc_external="yes"])
|
||||
|
||||
opal_hwloc_hwloc1116_save_CPPFLAGS=$CPPFLAGS
|
||||
opal_hwloc_hwloc1116_save_LDFLAGS=$LDFLAGS
|
||||
opal_hwloc_hwloc1116_save_LIBS=$LIBS
|
||||
opal_hwloc_hwloc2a_save_CPPFLAGS=$CPPFLAGS
|
||||
opal_hwloc_hwloc2a_save_LDFLAGS=$LDFLAGS
|
||||
opal_hwloc_hwloc2a_save_LIBS=$LIBS
|
||||
|
||||
# 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" &&
|
||||
test "$with_hwloc" != "future"],
|
||||
[HWLOC_SET_SYMBOL_PREFIX([opal_hwloc1116_])])
|
||||
[HWLOC_SET_SYMBOL_PREFIX([opal_hwloc2a_])])
|
||||
|
||||
# save XML or graphical options
|
||||
opal_hwloc_hwloc1116_save_cairo=$enable_cairo
|
||||
opal_hwloc_hwloc1116_save_xml=$enable_xml
|
||||
opal_hwloc_hwloc1116_save_static=$enable_static
|
||||
opal_hwloc_hwloc1116_save_shared=$enable_shared
|
||||
opal_hwloc_hwloc1116_save_plugins=$enable_plugins
|
||||
opal_hwloc_hwloc2a_save_cairo=$enable_cairo
|
||||
opal_hwloc_hwloc2a_save_xml=$enable_xml
|
||||
opal_hwloc_hwloc2a_save_static=$enable_static
|
||||
opal_hwloc_hwloc2a_save_shared=$enable_shared
|
||||
opal_hwloc_hwloc2a_save_plugins=$enable_plugins
|
||||
opal_hwloc_hwloc2a_save_mode=$hwloc_mode
|
||||
|
||||
# never enable hwloc's graphical option
|
||||
enable_cairo=no
|
||||
@ -112,28 +115,31 @@ AC_DEFUN([MCA_opal_hwloc_hwloc1116_CONFIG],[
|
||||
enable_libxml2=no
|
||||
enable_xml=yes
|
||||
|
||||
# ensure we are in "embedded" mode
|
||||
hwloc_mode=embedded
|
||||
|
||||
# Disable NVML support if CUDA support is not built
|
||||
AS_IF([test "$opal_check_cuda_happy" != "yes"],
|
||||
[enable_nvml=no])
|
||||
|
||||
# hwloc checks for compiler visibility, and its needs to do
|
||||
# this without "picky" flags.
|
||||
opal_hwloc_hwloc1116_save_cflags=$CFLAGS
|
||||
opal_hwloc_hwloc2a_save_cflags=$CFLAGS
|
||||
CFLAGS=$OPAL_CFLAGS_BEFORE_PICKY
|
||||
AS_IF([test -n "$opal_datatype_cuda_CPPFLAGS"],
|
||||
[CPPFLAGS="$CPPFLAGS $opal_datatype_cuda_CPPFLAGS"])
|
||||
|
||||
HWLOC_SETUP_CORE([opal/mca/hwloc/hwloc1116/hwloc],
|
||||
HWLOC_SETUP_CORE([opal/mca/hwloc/hwloc2a/hwloc],
|
||||
[AC_MSG_CHECKING([whether hwloc configure succeeded])
|
||||
AC_MSG_RESULT([yes])
|
||||
HWLOC_VERSION="internal v`$srcdir/$opal_hwloc_hwloc1116_basedir/hwloc/config/hwloc_get_version.sh $srcdir/$opal_hwloc_hwloc1116_basedir/hwloc/VERSION`"
|
||||
HWLOC_VERSION="internal v`$srcdir/$opal_hwloc_hwloc2a_basedir/hwloc/config/hwloc_get_version.sh $srcdir/$opal_hwloc_hwloc2a_basedir/hwloc/VERSION`"
|
||||
|
||||
# Build flags for our Makefile.am
|
||||
opal_hwloc_hwloc1116_LDFLAGS='$(HWLOC_EMBEDDED_LDFLAGS)'
|
||||
opal_hwloc_hwloc1116_LIBS='$(OPAL_TOP_BUILDDIR)/'"$opal_hwloc_hwloc1116_basedir"'/hwloc/src/libhwloc_embedded.la $(HWLOC_EMBEDDED_LIBS)'
|
||||
opal_hwloc_hwloc1116_support=yes
|
||||
opal_hwloc_hwloc2a_LDFLAGS='$(HWLOC_EMBEDDED_LDFLAGS)'
|
||||
opal_hwloc_hwloc2a_LIBS='$(OPAL_TOP_BUILDDIR)/'"$opal_hwloc_hwloc2a_basedir"'/hwloc/hwloc/libhwloc_embedded.la $(HWLOC_EMBEDDED_LIBS)'
|
||||
opal_hwloc_hwloc2a_support=yes
|
||||
|
||||
AC_DEFINE_UNQUOTED([HWLOC_HWLOC1116_HWLOC_VERSION],
|
||||
AC_DEFINE_UNQUOTED([HWLOC_HWLOC2a_HWLOC_VERSION],
|
||||
["$HWLOC_VERSION"],
|
||||
[Version of hwloc])
|
||||
|
||||
@ -146,35 +152,35 @@ AC_DEFUN([MCA_opal_hwloc_hwloc1116_CONFIG],[
|
||||
],
|
||||
[AC_MSG_CHECKING([whether hwloc configure succeeded])
|
||||
AC_MSG_RESULT([no])
|
||||
opal_hwloc_hwloc1116_support=no])
|
||||
CFLAGS=$opal_hwloc_hwloc1116_save_cflags
|
||||
opal_hwloc_hwloc2a_support=no])
|
||||
CFLAGS=$opal_hwloc_hwloc2a_save_cflags
|
||||
|
||||
# Restore some env variables, if necessary
|
||||
AS_IF([test -n "$opal_hwloc_hwloc1116_save_cairo"],
|
||||
[enable_cairo=$opal_hwloc_hwloc1116_save_cairo])
|
||||
AS_IF([test -n "$opal_hwloc_hwloc1116_save_xml"],
|
||||
[enable_xml=$opal_hwloc_hwloc1116_save_xml])
|
||||
AS_IF([test -n "$opal_hwloc_hwloc1116_save_static"],
|
||||
[enable_static=$opal_hwloc_hwloc1116_save_static])
|
||||
AS_IF([test -n "$opal_hwloc_hwloc1116_save_shared"],
|
||||
[enable_shared=$opal_hwloc_hwloc1116_save_shared])
|
||||
AS_IF([test -n "$opal_hwloc_hwloc1116_save_plugins"],
|
||||
[enable_plugins=$opal_hwloc_hwloc1116_save_shared])
|
||||
AS_IF([test -n "$opal_hwloc_hwloc2a_save_cairo"],
|
||||
[enable_cairo=$opal_hwloc_hwloc2a_save_cairo])
|
||||
AS_IF([test -n "$opal_hwloc_hwloc2a_save_xml"],
|
||||
[enable_xml=$opal_hwloc_hwloc2a_save_xml])
|
||||
AS_IF([test -n "$opal_hwloc_hwloc2a_save_static"],
|
||||
[enable_static=$opal_hwloc_hwloc2a_save_static])
|
||||
AS_IF([test -n "$opal_hwloc_hwloc2a_save_shared"],
|
||||
[enable_shared=$opal_hwloc_hwloc2a_save_shared])
|
||||
AS_IF([test -n "$opal_hwloc_hwloc2a_save_plugins"],
|
||||
[enable_plugins=$opal_hwloc_hwloc2a_save_shared])
|
||||
|
||||
CPPFLAGS=$opal_hwloc_hwloc1116_save_CPPFLAGS
|
||||
LDFLAGS=$opal_hwloc_hwloc1116_save_LDFLAGS
|
||||
LIBS=$opal_hwloc_hwloc1116_save_LIBS
|
||||
CPPFLAGS=$opal_hwloc_hwloc2a_save_CPPFLAGS
|
||||
LDFLAGS=$opal_hwloc_hwloc2a_save_LDFLAGS
|
||||
LIBS=$opal_hwloc_hwloc2a_save_LIBS
|
||||
|
||||
AC_SUBST([opal_hwloc_hwloc1116_CFLAGS])
|
||||
AC_SUBST([opal_hwloc_hwloc1116_CPPFLAGS])
|
||||
AC_SUBST([opal_hwloc_hwloc1116_LDFLAGS])
|
||||
AC_SUBST([opal_hwloc_hwloc1116_LIBS])
|
||||
AC_SUBST([opal_hwloc_hwloc2a_CFLAGS])
|
||||
AC_SUBST([opal_hwloc_hwloc2a_CPPFLAGS])
|
||||
AC_SUBST([opal_hwloc_hwloc2a_LDFLAGS])
|
||||
AC_SUBST([opal_hwloc_hwloc2a_LIBS])
|
||||
|
||||
# Finally, add some flags to the wrapper compiler so that our
|
||||
# headers can be found.
|
||||
hwloc_hwloc1116_WRAPPER_EXTRA_LDFLAGS="$HWLOC_EMBEDDED_LDFLAGS"
|
||||
hwloc_hwloc1116_WRAPPER_EXTRA_LIBS="$HWLOC_EMBEDDED_LIBS"
|
||||
hwloc_hwloc1116_WRAPPER_EXTRA_CPPFLAGS='-I${pkgincludedir}/'"$opal_hwloc_hwloc1116_basedir/hwloc/include"
|
||||
hwloc_hwloc2a_WRAPPER_EXTRA_LDFLAGS="$HWLOC_EMBEDDED_LDFLAGS"
|
||||
hwloc_hwloc2a_WRAPPER_EXTRA_LIBS="$HWLOC_EMBEDDED_LIBS"
|
||||
hwloc_hwloc2a_WRAPPER_EXTRA_CPPFLAGS='-I${pkgincludedir}/'"$opal_hwloc_hwloc2a_basedir/hwloc/include"
|
||||
|
||||
# If we are not building the internal hwloc, then indicate that
|
||||
# this component should not be built. NOTE: we still did all the
|
||||
@ -184,12 +190,12 @@ AC_DEFUN([MCA_opal_hwloc_hwloc1116_CONFIG],[
|
||||
# distclean" infrastructure to work properly).
|
||||
AS_IF([test "$opal_hwloc_external" = "yes"],
|
||||
[AC_MSG_WARN([using an external hwloc; disqualifying this component])
|
||||
opal_hwloc_hwloc1116_support=no],
|
||||
opal_hwloc_hwloc2a_support=no],
|
||||
[AC_DEFINE([HAVE_DECL_HWLOC_OBJ_OSDEV_COPROC], [1])
|
||||
AC_DEFINE([HAVE_HWLOC_TOPOLOGY_DUP], [1])])
|
||||
|
||||
# Done!
|
||||
AS_IF([test "$opal_hwloc_hwloc1116_support" = "yes"],
|
||||
AS_IF([test "$opal_hwloc_hwloc2a_support" = "yes"],
|
||||
[$1],
|
||||
[$2])
|
||||
|
29
opal/mca/hwloc/hwloc2a/hwloc/AUTHORS
Обычный файл
29
opal/mca/hwloc/hwloc2a/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
|
@ -11,6 +11,7 @@ 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.
|
@ -7,9 +7,23 @@
|
||||
# via AC_CONFIG_MACRO_DIR in configure.ac.
|
||||
ACLOCAL_AMFLAGS = -I ./config
|
||||
|
||||
SUBDIRS = src include
|
||||
#
|
||||
# "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
|
||||
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
|
||||
@ -23,23 +37,25 @@ DIST_SUBDIRS = $(SUBDIRS)
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = hwloc.pc
|
||||
endif
|
||||
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
|
||||
# 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
|
||||
|
||||
#
|
||||
# "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
|
||||
|
||||
# Only install entire visual studio subdirectory if we're building in standalone mode
|
||||
# Only install entire visual studio subdirectory if we're building in
|
||||
# standalone mode
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
EXTRA_DIST += contrib/windows
|
||||
endif
|
||||
@ -49,15 +65,6 @@ dist-hook:
|
||||
sh "$(top_srcdir)/config/distscript.sh" "$(top_srcdir)" "$(distdir)" "$(HWLOC_VERSION)"
|
||||
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
|
||||
|
||||
if HWLOC_BUILD_STANDALONE
|
||||
if HWLOC_HAVE_WINDOWS
|
||||
#
|
||||
@ -71,3 +78,12 @@ 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
|
@ -3,6 +3,7 @@ Copyright © 2009-2017 Inria. All rights reserved.
|
||||
Copyright © 2009-2013 Université Bordeaux
|
||||
Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
|
||||
Copyright (c) 2017 Intel, Inc. All rights reserved.
|
||||
$COPYRIGHT$
|
||||
|
||||
Additional copyrights may follow
|
||||
@ -17,6 +18,138 @@ bug fixes (and other actions) for each version of hwloc since version
|
||||
in v0.9.1).
|
||||
|
||||
|
||||
Version 2.0.0
|
||||
-------------
|
||||
* The ABI of the library has changed. For instance some hwloc_obj fields
|
||||
were reordered.
|
||||
- HWLOC_API_VERSION and hwloc_get_api_version() now give 0x00020000.
|
||||
- See "How do I handle ABI breaks and API upgrades ?" in the FAQ
|
||||
and https://github.com/open-mpi/hwloc/wiki/Upgrading-to-v2.0-API
|
||||
* Major changes
|
||||
+ Topologies always have at least one NUMA object. On non-NUMA machines,
|
||||
a single NUMA object is added to describe the entire machine memory.
|
||||
The NUMA level cannot be ignored anymore.
|
||||
+ The HWLOC_OBJ_CACHE type is replaced with 8 types HWLOC_OBJ_L[1-5]CACHE
|
||||
and HWLOC_OBJ_L[1-3]ICACHE that remove the need to disambiguate levels
|
||||
when looking for caches with _by_type() functions.
|
||||
- New hwloc_obj_type_is_{,d,i}cache() functions may be used to check whether
|
||||
a given type is a cache.
|
||||
+ Replace hwloc_topology_ignore*() functions with hwloc_topology_set_type_filter()
|
||||
and hwloc_topology_set_all_types_filter().
|
||||
- Contrary to hwloc_topology_ignore_{type,all}_keep_structure() which
|
||||
removed individual objects, HWLOC_TYPE_FILTER_KEEP_STRUCTURE only removes
|
||||
entire levels (so that topology do not become too asymmetric).
|
||||
+ Remove HWLOC_TOPOLOGY_FLAG_ICACHES in favor of hwloc_topology_set_icache_types_filter()
|
||||
with HWLOC_TYPE_FILTER_KEEP_ALL.
|
||||
+ Remove HWLOC_TOPOLOGY_FLAG_IO_DEVICES, _IO_BRIDGES and _WHOLE_IO in favor of
|
||||
hwloc_topology_set_io_types_filter() with HWLOC_TYPE_FILTER_KEEP_ALL or
|
||||
HWLOC_TYPE_FILTER_KEEP_IMPORTANT.
|
||||
+ hwloc_topology_restrict() doesn't remove objects that contain memory
|
||||
by default anymore.
|
||||
- The list of existing restrict flags was modified.
|
||||
+ XML export functions take an additional flags argument,
|
||||
for instance for exporting XMLs that are compatible with hwloc 1.x.
|
||||
+ The distance API has been completely reworked. It is now described
|
||||
in hwloc/distances.h.
|
||||
+ Add the experimental netloc subproject. It is enabled by default when
|
||||
supported and can be disabled with --disable-netloc.
|
||||
It currently brings command-line tools to gather and visualize the
|
||||
topology of InfiniBand fabrics, and an API to convert such topologies
|
||||
into Scotch architectures for process mapping.
|
||||
See the documentation for details.
|
||||
+ Remove the online_cpuset from struct hwloc_obj. Offline PUs get unknown
|
||||
topologies on Linux nowadays, and wrong topology on Solaris. Other OS
|
||||
do not support them. And one cannot do much about them anyway. Just keep
|
||||
them in complete_cpuset.
|
||||
+ Remove the custom interface for assembling the topologies of different
|
||||
nodes as well as the hwloc-assembler tools.
|
||||
+ Remove Kerrighed support from the Linux backend.
|
||||
+ Remove Tru64 (OSF/1) support.
|
||||
- Remove HWLOC_MEMBIND_REPLICATE which wasn't available anywhere else.
|
||||
* API
|
||||
+ Objects now have a "subtype" field that supersedes former "Type" and
|
||||
"CoProcType" info attributes.
|
||||
+ The almost-unused "os_level" attribute has been removed from the
|
||||
hwloc_obj structure.
|
||||
+ I/O and Misc objects are now stored in a dedicated children list, only
|
||||
normal children with non-NULL cpusets and nodesets are in the main
|
||||
children list.
|
||||
- hwloc_get_next_child() may still be used to iterate over these 3 lists
|
||||
of children at once.
|
||||
+ Replace hwloc_topology_insert_misc_object_by_cpuset() with
|
||||
hwloc_topology_insert_group_object() to precisely specify the location
|
||||
of an additional hierarchy level in the topology.
|
||||
+ Misc objects have their own level and depth to iterate over all of them.
|
||||
+ Misc objects may now only be inserted as a leaf object with
|
||||
hwloc_topology_insert_misc_object() which deprecates
|
||||
hwloc_topology_insert_misc_object_by_parent().
|
||||
+ hwloc_topology_set_fsroot() is removed, the environment variable
|
||||
HWLOC_FSROOT may be used for the same remote testing/debugging purpose.
|
||||
+ hwloc_type_sscanf() deprecates the old hwloc_obj_type_sscanf().
|
||||
+ hwloc_type_sscanf_as_depth() is added to convert a type name into
|
||||
a level depth.
|
||||
+ hwloc_type_name() deprecates the old hwloc_obj_type_string().
|
||||
+ Remove the deprecated hwloc_obj_snprintf(), hwloc_obj_type_of_string(),
|
||||
hwloc_distribute[v]().
|
||||
+ hwloc_obj_cpuset_snprintf() is deprecated in favor of hwloc_bitmap_snprintf().
|
||||
+ Functions diff_load_xml*(), diff_export_xml*() and diff_destroy() in
|
||||
hwloc/diff.h do not need a topology as first parameter anymore.
|
||||
+ hwloc_parse_cpumap_file () superseded by hwloc_linux_read_path_as_cpumask()
|
||||
in hwloc/linux.h.
|
||||
* Tools
|
||||
- lstopo and hwloc-info have a new --filter option matching the new filtering API.
|
||||
- hwloc-distances was removed and replaced with lstopo --distances.
|
||||
* Plugin API
|
||||
+ hwloc_fill_object_sets() is renamed into hwloc_obj_add_children_sets().
|
||||
* Misc
|
||||
+ Linux OS devices do not have to be attached through PCI anymore,
|
||||
for instance enabling the discovery of NVDIMM block devices.
|
||||
+ Add a SectorSize attribute to block OS devices on Linux.
|
||||
+ Misc MemoryModule objects are only added when full I/O discovery is enabled
|
||||
(WHOLE_IO topology flag).
|
||||
+ Do not set PCI devices and bridges name automatically. Vendor and device
|
||||
names are already in info attributes.
|
||||
+ Exporting to synthetic now ignores I/O and Misc objects.
|
||||
+ XML and Synthetic export functions have moved to hwloc/export.h,
|
||||
automatically included from hwloc.h.
|
||||
+ Separate OS device discovery from PCI discovery. Only the latter is disabled
|
||||
with --disable-pci at configure time. Both may be disabled with --disable-io.
|
||||
+ The old `libpci' component name from hwloc 1.6 is not supported anymore,
|
||||
only the `pci' name from hwloc 1.7 is now recognized.
|
||||
+ The `linuxpci' component is now renamed into `linuxio'.
|
||||
+ The HWLOC_PCI_<domain>_<bus>_LOCALCPUS environment variables are superseded
|
||||
with a single HWLOC_PCI_LOCALITY where bus ranges may be specified.
|
||||
+ Add HWLOC_SYNTHETIC environment variable to enforce a synthetic topology
|
||||
as if hwloc_topology_set_synthetic() had been called.
|
||||
+ HWLOC_COMPONENTS doesn't support xml or synthetic component attributes
|
||||
anymore, they should be passed in HWLOC_XMLFILE or HWLOC_SYNTHETIC instead.
|
||||
+ HWLOC_COMPONENTS takes precedence over other environment variables
|
||||
for selecting components.
|
||||
+ Remove the dependency on libnuma on Linux.
|
||||
|
||||
|
||||
Version 1.11.7
|
||||
--------------
|
||||
* Fix hwloc-bind --membind for CPU-less NUMA nodes (again).
|
||||
Thanks to Gilles Gouaillardet for reporting the issue.
|
||||
* Fix a memory leak on IBM S/390 platforms running Linux.
|
||||
* Fix a memory leak when forcing the x86 backend first on amd64/topoext
|
||||
platforms running Linux.
|
||||
* Command-line tools now support "hbm" instead "numanode" for filtering
|
||||
only high-bandwidth memory nodes when selecting locations.
|
||||
+ hwloc-bind also support --hbm and --no-hbm for filtering only or
|
||||
no HBM nodes.
|
||||
Thanks to Nicolas Denoyelle for the suggestion.
|
||||
* Add --children and --descendants to hwloc-info for listing object
|
||||
children or object descendants of a specific type.
|
||||
* Add --no-index, --index, --no-attrs, --attrs to disable/enable display
|
||||
of index numbers or attributes in the graphical lstopo output.
|
||||
* Try to gather hwloc-dump-hwdata output from all possible locations
|
||||
in hwloc-gather-topology.
|
||||
* Updates to the documentation of locations in hwloc(7) and
|
||||
command-line tools manpages.
|
||||
|
||||
|
||||
Version 1.11.6
|
||||
--------------
|
||||
* Make the Linux discovery about twice faster, especially on the CPU side,
|
65
opal/mca/hwloc/hwloc2a/hwloc/README
Обычный файл
65
opal/mca/hwloc/hwloc2a/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.
|
@ -7,9 +7,9 @@
|
||||
|
||||
# Please update HWLOC_VERSION in contrib/windows/private_config.h too.
|
||||
|
||||
major=1
|
||||
minor=11
|
||||
release=6
|
||||
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
|
||||
@ -22,7 +22,7 @@ greek=
|
||||
|
||||
# The date when this release was created
|
||||
|
||||
date="Feb 23, 2017"
|
||||
date="Jul 21, 2017"
|
||||
|
||||
# If snapshot=1, then use the value from snapshot_version as the
|
||||
# entire hwloc version (i.e., ignore major, minor, release, and
|
||||
@ -41,6 +41,7 @@ snapshot_version=${major}.${minor}.${release}${greek}-git
|
||||
# 2. Version numbers are described in the Libtool current:revision:age
|
||||
# format.
|
||||
|
||||
libhwloc_so_version=12:3:7
|
||||
libhwloc_so_version=0:0:0
|
||||
libnetloc_so_version=0:0:0
|
||||
|
||||
# Please also update the <TargetName> lines in contrib/windows/libhwloc.vcxproj
|
@ -12,6 +12,7 @@
|
||||
# All rights reserved.
|
||||
# Copyright © 2010-2014 Inria. All rights reserved.
|
||||
# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved.
|
||||
# Copyright (c) 2017 Intel, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
@ -179,7 +179,7 @@ EOF])
|
||||
# List of components to be built, either statically or dynamically.
|
||||
# To be enlarged below.
|
||||
#
|
||||
hwloc_components="noos xml synthetic custom xml_nolibxml"
|
||||
hwloc_components="noos xml synthetic xml_nolibxml"
|
||||
|
||||
#
|
||||
# Check OS support
|
||||
@ -197,11 +197,15 @@ EOF])
|
||||
hwloc_linux=yes
|
||||
AC_MSG_RESULT([Linux])
|
||||
hwloc_components="$hwloc_components linux"
|
||||
if test "x$enable_io" != xno; then
|
||||
hwloc_components="$hwloc_components linuxio"
|
||||
AC_DEFINE(HWLOC_HAVE_LINUXIO, 1, [Define to 1 if building the Linux I/O component])
|
||||
hwloc_linuxio_happy=yes
|
||||
if test x$enable_pci != xno; then
|
||||
hwloc_components="$hwloc_components linuxpci"
|
||||
AC_DEFINE(HWLOC_HAVE_LINUXPCI, 1, [Define to 1 if building the Linux PCI component])
|
||||
AC_DEFINE(HWLOC_HAVE_LINUXPCI, 1, [Define to 1 if enabling Linux-specific PCI discovery in the Linux I/O component])
|
||||
hwloc_linuxpci_happy=yes
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*-*-irix*)
|
||||
AC_DEFINE(HWLOC_IRIX_SYS, 1, [Define to 1 on Irix])
|
||||
@ -227,12 +231,6 @@ EOF])
|
||||
AC_MSG_RESULT([AIX])
|
||||
hwloc_components="$hwloc_components aix"
|
||||
;;
|
||||
*-*-osf*)
|
||||
AC_DEFINE(HWLOC_OSF_SYS, 1, [Define to 1 on OSF])
|
||||
hwloc_osf=yes
|
||||
AC_MSG_RESULT([OSF])
|
||||
hwloc_components="$hwloc_components osf"
|
||||
;;
|
||||
*-*-hpux*)
|
||||
AC_DEFINE(HWLOC_HPUX_SYS, 1, [Define to 1 on HP-UX])
|
||||
hwloc_hpux=yes
|
||||
@ -264,7 +262,7 @@ EOF])
|
||||
AC_MSG_WARN([*** hwloc does not support this system.])
|
||||
AC_MSG_WARN([*** hwloc will *attempt* to build (but it may not work).])
|
||||
AC_MSG_WARN([*** hwloc run-time results may be reduced to showing just one processor,])
|
||||
AC_MSG_WARN([*** and binding will likely not be supported.])
|
||||
AC_MSG_WARN([*** and binding will not be supported.])
|
||||
AC_MSG_WARN([*** You have been warned.])
|
||||
AC_MSG_WARN([*** Pausing to give you time to read this message...])
|
||||
AC_MSG_WARN([***********************************************************])
|
||||
@ -593,22 +591,16 @@ EOF])
|
||||
AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([no])])
|
||||
|
||||
AC_MSG_CHECKING([for working syscall])
|
||||
AC_MSG_CHECKING([for working syscall with 6 parameters])
|
||||
AC_LINK_IFELSE([
|
||||
AC_LANG_PROGRAM([[
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
]], [[syscall(1, 2, 3);]])],
|
||||
[AC_DEFINE([HWLOC_HAVE_SYSCALL], [1], [Define to 1 if function `syscall' is available])
|
||||
]], [[syscall(0, 1, 2, 3, 4, 5, 6);]])],
|
||||
[AC_DEFINE([HWLOC_HAVE_SYSCALL], [1], [Define to 1 if function `syscall' is available with 6 parameters])
|
||||
AC_MSG_RESULT([yes])],
|
||||
[AC_MSG_RESULT([no])])
|
||||
|
||||
# Check for kerrighed, but don't abort if not found. It's illegal
|
||||
# to pass in an empty 3rd argument, but we trust the output of
|
||||
# pkg-config, so just give it a value that will always work:
|
||||
# printf.
|
||||
HWLOC_PKG_CHECK_MODULES([KERRIGHED], [kerrighed >= 2.0], [printf], [stdio.h], [], [:])
|
||||
|
||||
AC_PATH_PROGS([HWLOC_MS_LIB], [lib])
|
||||
AC_ARG_VAR([HWLOC_MS_LIB], [Path to Microsoft's Visual Studio `lib' tool])
|
||||
|
||||
@ -710,44 +702,6 @@ EOF])
|
||||
)
|
||||
AC_CHECK_FUNCS([cpuset_setid])
|
||||
|
||||
# Linux libnuma support
|
||||
hwloc_linux_libnuma_happy=no
|
||||
if test "x$enable_libnuma" != "xno"; then
|
||||
hwloc_linux_libnuma_happy=yes
|
||||
AC_CHECK_HEADERS([numaif.h], [
|
||||
AC_CHECK_LIB([numa], [numa_available], [HWLOC_LINUX_LIBNUMA_LIBS="-lnuma"], [hwloc_linux_libnuma_happy=no])
|
||||
], [hwloc_linux_libnuma_happy=no])
|
||||
fi
|
||||
AC_SUBST(HWLOC_LINUX_LIBNUMA_LIBS)
|
||||
# If we asked for Linux libnuma support but couldn't deliver, fail
|
||||
HWLOC_LIBS="$HWLOC_LIBS $HWLOC_LINUX_LIBNUMA_LIBS"
|
||||
AS_IF([test "$enable_libnuma" = "yes" -a "$hwloc_linux_libnuma_happy" = "no"],
|
||||
[AC_MSG_WARN([Specified --enable-libnuma switch, but could not])
|
||||
AC_MSG_WARN([find appropriate support])
|
||||
AC_MSG_ERROR([Cannot continue])])
|
||||
if test "x$hwloc_linux_libnuma_happy" = "xyes"; then
|
||||
tmp_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS $HWLOC_LINUX_LIBNUMA_LIBS"
|
||||
|
||||
AC_CHECK_LIB([numa], [set_mempolicy], [
|
||||
enable_set_mempolicy=yes
|
||||
AC_DEFINE([HWLOC_HAVE_SET_MEMPOLICY], [1], [Define to 1 if set_mempolicy is available.])
|
||||
])
|
||||
AC_CHECK_LIB([numa], [mbind], [
|
||||
enable_mbind=yes
|
||||
AC_DEFINE([HWLOC_HAVE_MBIND], [1], [Define to 1 if mbind is available.])
|
||||
])
|
||||
AC_CHECK_LIB([numa], [migrate_pages], [
|
||||
enable_migrate_pages=yes
|
||||
AC_DEFINE([HWLOC_HAVE_MIGRATE_PAGES], [1], [Define to 1 if migrate_pages is available.])
|
||||
])
|
||||
AC_CHECK_LIB([numa], [move_pages], [
|
||||
AC_DEFINE([HWLOC_HAVE_MOVE_PAGES], [1], [Define to 1 if move_pages is available.])
|
||||
])
|
||||
|
||||
LIBS="$tmp_save_LIBS"
|
||||
fi
|
||||
|
||||
# Linux libudev support
|
||||
if test "x$enable_libudev" != xno; then
|
||||
AC_CHECK_HEADERS([libudev.h], [
|
||||
@ -761,32 +715,31 @@ EOF])
|
||||
# PCI support via libpciaccess. NOTE: we do not support
|
||||
# libpci/pciutils because that library is GPL and is incompatible
|
||||
# with our BSD license.
|
||||
hwloc_pci_happy=no
|
||||
if test "x$enable_pci" != xno; then
|
||||
hwloc_pci_happy=yes
|
||||
HWLOC_PKG_CHECK_MODULES([PCIACCESS], [pciaccess], [pci_slot_match_iterator_create], [pciaccess.h], [:], [hwloc_pci_happy=no])
|
||||
hwloc_pciaccess_happy=no
|
||||
if test "x$enable_io" != xno && test "x$enable_pci" != xno; then
|
||||
hwloc_pciaccess_happy=yes
|
||||
HWLOC_PKG_CHECK_MODULES([PCIACCESS], [pciaccess], [pci_slot_match_iterator_create], [pciaccess.h], [:], [hwloc_pciaccess_happy=no])
|
||||
|
||||
# Only add the REQUIRES if we got pciaccess through pkg-config.
|
||||
# Otherwise we don't know if pciaccess.pc is installed
|
||||
AS_IF([test "$hwloc_pci_happy" = "yes"], [HWLOC_PCIACCESS_REQUIRES=pciaccess])
|
||||
AS_IF([test "$hwloc_pciaccess_happy" = "yes"], [HWLOC_PCIACCESS_REQUIRES=pciaccess])
|
||||
|
||||
# Just for giggles, if we didn't find a pciaccess pkg-config,
|
||||
# just try looking for its header file and library.
|
||||
AS_IF([test "$hwloc_pci_happy" != "yes"],
|
||||
AS_IF([test "$hwloc_pciaccess_happy" != "yes"],
|
||||
[AC_CHECK_HEADER([pciaccess.h],
|
||||
[AC_CHECK_LIB([pciaccess], [pci_slot_match_iterator_create],
|
||||
[hwloc_pci_happy=yes
|
||||
[hwloc_pciaccess_happy=yes
|
||||
HWLOC_PCIACCESS_LIBS="-lpciaccess"])
|
||||
])
|
||||
])
|
||||
|
||||
AS_IF([test "$hwloc_pci_happy" = "yes"],
|
||||
[hwloc_pci_lib=pciaccess
|
||||
hwloc_components="$hwloc_components pci"
|
||||
AS_IF([test "$hwloc_pciaccess_happy" = "yes"],
|
||||
[hwloc_components="$hwloc_components pci"
|
||||
hwloc_pci_component_maybeplugin=1])
|
||||
fi
|
||||
# If we asked for pci support but couldn't deliver, fail
|
||||
AS_IF([test "$enable_pci" = "yes" -a "$hwloc_pci_happy" = "no"],
|
||||
AS_IF([test "$enable_pci" = "yes" -a "$hwloc_pciaccess_happy" = "no"],
|
||||
[AC_MSG_WARN([Specified --enable-pci switch, but could not])
|
||||
AC_MSG_WARN([find appropriate support])
|
||||
AC_MSG_ERROR([Cannot continue])])
|
||||
@ -794,7 +747,7 @@ EOF])
|
||||
|
||||
# OpenCL support
|
||||
hwloc_opencl_happy=no
|
||||
if test "x$enable_opencl" != "xno"; then
|
||||
if test "x$enable_io" != xno && test "x$enable_opencl" != "xno"; then
|
||||
hwloc_opencl_happy=yes
|
||||
AC_CHECK_HEADERS([CL/cl_ext.h], [
|
||||
AC_CHECK_LIB([OpenCL], [clGetDeviceIDs], [HWLOC_OPENCL_LIBS="-lOpenCL"], [hwloc_opencl_happy=no])
|
||||
@ -831,7 +784,7 @@ EOF])
|
||||
# CUDA support
|
||||
hwloc_have_cuda=no
|
||||
hwloc_have_cudart=no
|
||||
if test "x$enable_cuda" != "xno"; then
|
||||
if test "x$enable_io" != xno && test "x$enable_cuda" != "xno"; then
|
||||
AC_CHECK_HEADERS([cuda.h], [
|
||||
AC_MSG_CHECKING(if CUDA_VERSION >= 3020)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||
@ -880,7 +833,7 @@ EOF])
|
||||
|
||||
# NVML support
|
||||
hwloc_nvml_happy=no
|
||||
if test "x$enable_nvml" != "xno"; then
|
||||
if test "x$enable_io" != xno && test "x$enable_nvml" != "xno"; then
|
||||
hwloc_nvml_happy=yes
|
||||
AC_CHECK_HEADERS([nvml.h], [
|
||||
AC_CHECK_LIB([nvidia-ml], [nvmlInit], [HWLOC_NVML_LIBS="-lnvidia-ml"], [hwloc_nvml_happy=no])
|
||||
@ -940,7 +893,7 @@ EOF])
|
||||
|
||||
# GL Support
|
||||
hwloc_gl_happy=no
|
||||
if test "x$enable_gl" != "xno"; then
|
||||
if test "x$enable_io" != xno && test "x$enable_gl" != "xno"; then
|
||||
hwloc_gl_happy=yes
|
||||
|
||||
AS_IF([test "$hwloc_enable_X11" != "yes"],
|
||||
@ -998,7 +951,7 @@ EOF])
|
||||
AC_MSG_CHECKING([for x86 cpuid])
|
||||
old_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS -I$HWLOC_top_srcdir/include"
|
||||
# We need hwloc_uint64_t but we can't use hwloc/autogen/config.h before configure ends.
|
||||
# We need hwloc_uint64_t but we can't use autogen/config.h before configure ends.
|
||||
# So pass #include/#define manually here for now.
|
||||
CPUID_CHECK_HEADERS=
|
||||
CPUID_CHECK_DEFINE=
|
||||
@ -1107,7 +1060,7 @@ EOF])
|
||||
AC_SUBST(HWLOC_PLUGINS_DIR)
|
||||
|
||||
# Static components output file
|
||||
hwloc_static_components_dir=${HWLOC_top_builddir}/src
|
||||
hwloc_static_components_dir=${HWLOC_top_builddir}/hwloc
|
||||
mkdir -p ${hwloc_static_components_dir}
|
||||
hwloc_static_components_file=${hwloc_static_components_dir}/static-components.h
|
||||
rm -f ${hwloc_static_components_file}
|
||||
@ -1173,7 +1126,7 @@ EOF])
|
||||
AS_IF([test "$hwloc_mode" = "embedded"],
|
||||
[HWLOC_EMBEDDED_CFLAGS=$HWLOC_CFLAGS
|
||||
HWLOC_EMBEDDED_CPPFLAGS=$HWLOC_CPPFLAGS
|
||||
HWLOC_EMBEDDED_LDADD='$(HWLOC_top_builddir)/src/libhwloc_embedded.la'
|
||||
HWLOC_EMBEDDED_LDADD='$(HWLOC_top_builddir)/hwloc/libhwloc_embedded.la'
|
||||
HWLOC_EMBEDDED_LIBS=$HWLOC_LIBS
|
||||
HWLOC_LIBS=])
|
||||
AC_SUBST(HWLOC_EMBEDDED_CFLAGS)
|
||||
@ -1185,7 +1138,7 @@ EOF])
|
||||
AC_CONFIG_FILES(
|
||||
hwloc_config_prefix[Makefile]
|
||||
hwloc_config_prefix[include/Makefile]
|
||||
hwloc_config_prefix[src/Makefile ]
|
||||
hwloc_config_prefix[hwloc/Makefile ]
|
||||
)
|
||||
|
||||
# Cleanup
|
||||
@ -1213,12 +1166,12 @@ AC_DEFUN([HWLOC_DO_AM_CONDITIONALS],[
|
||||
AM_CONDITIONAL([HWLOC_HAVE_GCC], [test "x$GCC" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_MS_LIB], [test "x$HWLOC_MS_LIB" != "x"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_OPENAT], [test "x$hwloc_have_openat" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_LINUX_LIBNUMA],
|
||||
[test "x$hwloc_have_linux_libnuma" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_SCHED_SETAFFINITY],
|
||||
[test "x$hwloc_have_sched_setaffinity" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_PTHREAD],
|
||||
[test "x$hwloc_have_pthread" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_LINUX_LIBNUMA],
|
||||
[test "x$hwloc_have_linux_libnuma" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_LIBIBVERBS],
|
||||
[test "x$hwloc_have_libibverbs" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_CUDA],
|
||||
@ -1231,11 +1184,9 @@ AC_DEFUN([HWLOC_DO_AM_CONDITIONALS],[
|
||||
[test "x$hwloc_have_cudart" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_LIBXML2], [test "$hwloc_libxml2_happy" = "yes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_CAIRO], [test "$hwloc_cairo_happy" = "yes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_PCI], [test "$hwloc_pci_happy" = "yes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_PCIACCESS], [test "$hwloc_pciaccess_happy" = "yes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_OPENCL], [test "$hwloc_opencl_happy" = "yes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_NVML], [test "$hwloc_nvml_happy" = "yes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_SET_MEMPOLICY], [test "x$enable_set_mempolicy" != "xno"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_MBIND], [test "x$enable_mbind" != "xno"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_BUNZIPP], [test "x$BUNZIPP" != "xfalse"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_USER32], [test "x$hwloc_have_user32" = "xyes"])
|
||||
|
||||
@ -1254,7 +1205,6 @@ AC_DEFUN([HWLOC_DO_AM_CONDITIONALS],[
|
||||
AM_CONDITIONAL([HWLOC_HAVE_NETBSD], [test "x$hwloc_netbsd" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_SOLARIS], [test "x$hwloc_solaris" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_AIX], [test "x$hwloc_aix" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_OSF], [test "x$hwloc_osf" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_HPUX], [test "x$hwloc_hpux" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_WINDOWS], [test "x$hwloc_windows" = "xyes"])
|
||||
AM_CONDITIONAL([HWLOC_HAVE_MINGW32], [test "x$target_os" = "xmingw32"])
|
||||
@ -1275,6 +1225,11 @@ AC_DEFUN([HWLOC_DO_AM_CONDITIONALS],[
|
||||
AM_CONDITIONAL([HWLOC_HAVE_CXX], [test "x$hwloc_have_cxx" = "xyes"])
|
||||
])
|
||||
hwloc_did_am_conditionals=yes
|
||||
|
||||
# For backwards compatibility (i.e., packages that only call
|
||||
# HWLOC_DO_AM_CONDITIONS, not NETLOC DO_AM_CONDITIONALS), we also have to
|
||||
# do the netloc AM conditionals here
|
||||
NETLOC_DO_AM_CONDITIONALS
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
@ -531,4 +531,3 @@ AC_DEFUN([_HWLOC_CHECK_ATTRIBUTES], [
|
||||
AC_DEFINE_UNQUOTED(HWLOC_HAVE_ATTRIBUTE_WEAK_ALIAS, [$hwloc_cv___attribute__weak_alias],
|
||||
[Whether your compiler has __attribute__ weak alias or not])
|
||||
])
|
||||
|
@ -11,6 +11,8 @@ 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 (c) 2017 Intel, Inc. All rights reserved.
|
||||
dnl $COPYRIGHT$
|
||||
dnl
|
||||
dnl Additional copyrights may follow
|
||||
@ -120,6 +122,7 @@ AC_DEFUN([_HWLOC_CHECK_COMPILER_VENDOR], [
|
||||
[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"],
|
@ -12,6 +12,7 @@
|
||||
# All rights reserved.
|
||||
# Copyright © 2008-2014 Cisco Systems, Inc. All rights reserved.
|
||||
# Copyright © 2014 Inria. All rights reserved.
|
||||
# Copyright (c) 2017 Intel, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
@ -64,6 +64,11 @@ AC_DEFUN([HWLOC_DEFINE_ARGS],[
|
||||
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],
|
||||
@ -89,11 +94,6 @@ AC_DEFUN([HWLOC_DEFINE_ARGS],[
|
||||
AS_HELP_STRING([--disable-gl],
|
||||
[Disable the GL display device discovery]))
|
||||
|
||||
# Linux libnuma
|
||||
AC_ARG_ENABLE([libnuma],
|
||||
AS_HELP_STRING([--disable-libnuma],
|
||||
[Disable the Linux libnuma]))
|
||||
|
||||
# LibUdev
|
||||
AC_ARG_ENABLE([libudev],
|
||||
AS_HELP_STRING([--disable-libudev],
|
||||
@ -221,7 +221,7 @@ EOF
|
||||
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"
|
||||
add="$add -Wcomment -pedantic -Wshadow"
|
||||
|
||||
HWLOC_CFLAGS="$HWLOC_CFLAGS $add"
|
||||
fi
|
||||
@ -326,7 +326,15 @@ EOF
|
||||
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[hwloc.pc]
|
||||
|
||||
hwloc_config_prefix[utils/netloc/infiniband/Makefile]
|
||||
hwloc_config_prefix[utils/netloc/draw/Makefile]
|
||||
hwloc_config_prefix[utils/netloc/scotch/Makefile]
|
||||
hwloc_config_prefix[utils/netloc/mpi/Makefile]
|
||||
hwloc_config_prefix[netloc.pc]
|
||||
hwloc_config_prefix[netlocscotch.pc]
|
||||
)
|
||||
])dnl
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
@ -336,7 +344,7 @@ AC_DEFUN([HWLOC_SETUP_TESTS],[
|
||||
cat <<EOF
|
||||
|
||||
###
|
||||
### Configuring hwloc tests
|
||||
### Configuring tests
|
||||
###
|
||||
EOF
|
||||
|
||||
@ -386,33 +394,57 @@ int foo(void) {
|
||||
# Only generate these files if we're making the tests
|
||||
AC_CONFIG_FILES(
|
||||
hwloc_config_prefix[tests/Makefile]
|
||||
hwloc_config_prefix[tests/linux/Makefile]
|
||||
hwloc_config_prefix[tests/linux/allowed/Makefile]
|
||||
hwloc_config_prefix[tests/linux/gather/Makefile]
|
||||
hwloc_config_prefix[tests/xml/Makefile]
|
||||
hwloc_config_prefix[tests/ports/Makefile]
|
||||
hwloc_config_prefix[tests/rename/Makefile]
|
||||
hwloc_config_prefix[tests/linux/allowed/test-topology.sh]
|
||||
hwloc_config_prefix[tests/linux/gather/test-gather-topology.sh]
|
||||
hwloc_config_prefix[tests/linux/test-topology.sh]
|
||||
hwloc_config_prefix[tests/xml/test-topology.sh]
|
||||
hwloc_config_prefix[tests/wrapper.sh]
|
||||
hwloc_config_prefix[utils/hwloc/hwloc-assembler-remote]
|
||||
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-assembler.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-distances.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/lstopo/test-hwloc-ls.sh]
|
||||
hwloc_config_prefix[contrib/systemd/Makefile])
|
||||
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/linux/test-topology.sh ]hwloc_config_prefix[tests/xml/test-topology.sh ]hwloc_config_prefix[tests/linux/allowed/test-topology.sh ]hwloc_config_prefix[tests/linux/gather/test-gather-topology.sh ]hwloc_config_prefix[tests/wrapper.sh ]hwloc_config_prefix[utils/hwloc/hwloc-assembler-remote ]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-assembler.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-distances.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/lstopo/test-hwloc-ls.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
|
||||
@ -421,19 +453,19 @@ int foo(void) {
|
||||
# built in standalone mode, only generate them in
|
||||
# standalone mode.
|
||||
AC_CONFIG_LINKS(
|
||||
hwloc_config_prefix[tests/ports/topology-solaris.c]:hwloc_config_prefix[src/topology-solaris.c]
|
||||
hwloc_config_prefix[tests/ports/topology-solaris-chiptype.c]:hwloc_config_prefix[src/topology-solaris-chiptype.c]
|
||||
hwloc_config_prefix[tests/ports/topology-aix.c]:hwloc_config_prefix[src/topology-aix.c]
|
||||
hwloc_config_prefix[tests/ports/topology-osf.c]:hwloc_config_prefix[src/topology-osf.c]
|
||||
hwloc_config_prefix[tests/ports/topology-windows.c]:hwloc_config_prefix[src/topology-windows.c]
|
||||
hwloc_config_prefix[tests/ports/topology-darwin.c]:hwloc_config_prefix[src/topology-darwin.c]
|
||||
hwloc_config_prefix[tests/ports/topology-freebsd.c]:hwloc_config_prefix[src/topology-freebsd.c]
|
||||
hwloc_config_prefix[tests/ports/topology-netbsd.c]:hwloc_config_prefix[src/topology-netbsd.c]
|
||||
hwloc_config_prefix[tests/ports/topology-hpux.c]:hwloc_config_prefix[src/topology-hpux.c]
|
||||
hwloc_config_prefix[tests/ports/topology-bgq.c]:hwloc_config_prefix[src/topology-bgq.c]
|
||||
hwloc_config_prefix[tests/ports/topology-opencl.c]:hwloc_config_prefix[src/topology-opencl.c]
|
||||
hwloc_config_prefix[tests/ports/topology-cuda.c]:hwloc_config_prefix[src/topology-cuda.c]
|
||||
hwloc_config_prefix[tests/ports/topology-nvml.c]:hwloc_config_prefix[src/topology-nvml.c]
|
||||
hwloc_config_prefix[tests/ports/topology-gl.c]:hwloc_config_prefix[src/topology-gl.c])
|
||||
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
|
116
opal/mca/hwloc/hwloc2a/hwloc/config/netloc.m4
Обычный файл
116
opal/mca/hwloc/hwloc2a/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
|
@ -1,7 +1,7 @@
|
||||
# -*- shell-script -*-
|
||||
#
|
||||
# Copyright © 2009 CNRS
|
||||
# Copyright © 2009-2015 Inria. All rights reserved.
|
||||
# Copyright © 2009-2016 Inria. All rights reserved.
|
||||
# Copyright © 2009, 2011-2012 Université Bordeaux
|
||||
# Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved.
|
||||
#
|
||||
@ -40,11 +40,6 @@ AC_CANONICAL_TARGET
|
||||
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])])
|
||||
|
||||
# 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])
|
||||
|
||||
AC_LANG([C])
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
@ -55,7 +50,8 @@ AC_USE_SYSTEM_EXTENSIONS
|
||||
AH_TOP([/* -*- c -*-
|
||||
*
|
||||
* Copyright © 2009, 2011, 2012 CNRS, inria., Université Bordeaux All rights reserved.
|
||||
* Copyright © 2009 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright © 2009-2014 Cisco Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2017 Intel, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
@ -74,18 +70,37 @@ AH_BOTTOM([
|
||||
])
|
||||
|
||||
####################################################################
|
||||
# Setup C compiler
|
||||
# Setup Libtool
|
||||
####################################################################
|
||||
|
||||
CFLAGS_save="$CFLAGS"
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AM_PROG_CC_C_O
|
||||
CFLAGS="$CFLAGS_save"
|
||||
# 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])
|
||||
@ -116,24 +131,29 @@ AS_IF([test "$enable_embedded_mode" != "yes"],
|
||||
# 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 hwloc's docs, utils, and tests
|
||||
AS_IF([test "$hwloc_mode" = "standalone"],
|
||||
[HWLOC_SETUP_DOCS
|
||||
HWLOC_SETUP_UTILS
|
||||
HWLOC_SETUP_TESTS])
|
||||
####################################################################
|
||||
# Setup the netloc API
|
||||
####################################################################
|
||||
|
||||
cat <<EOF
|
||||
AC_SUBST([libnetloc_so_version])
|
||||
|
||||
###
|
||||
### Performing final hwloc configuration
|
||||
###
|
||||
EOF
|
||||
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.])
|
||||
])
|
||||
|
||||
# Run the AM_CONDITIONALs
|
||||
HWLOC_DO_AM_CONDITIONALS
|
||||
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
|
||||
@ -150,7 +170,6 @@ AC_SUBST([CONFIGURE_DEPENDENCIES], ['$(top_srcdir)/VERSION'])
|
||||
# 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}"
|
||||
@ -158,7 +177,27 @@ VERSION="${PACKAGE_VERSION}"
|
||||
# For standalone configurations, we also include a .so version number.
|
||||
|
||||
. $srcdir/VERSION
|
||||
AC_SUBST([libhwloc_so_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
|
||||
@ -169,13 +208,6 @@ CFLAGS="$HWLOC_EMBEDDED_CFLAGS $CFLAGS"
|
||||
CPPFLAGS="$HWLOC_EMBEDDED_CPPFLAGS $CPPFLAGS"
|
||||
LIBS="$HWLOC_EMBEDDED_LIBS $LIBS"
|
||||
|
||||
# Setup libtool, but disable C++, F77, Java and Windows Resource
|
||||
# Compiler support -- we don't need that stuff.
|
||||
AM_ENABLE_SHARED
|
||||
AM_DISABLE_STATIC
|
||||
AM_PROG_LIBTOOL([dlopen win32-dll])
|
||||
LT_LANG([C])
|
||||
|
||||
# Party on
|
||||
AC_OUTPUT
|
||||
|
||||
@ -193,22 +225,24 @@ 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_pci_happy" = "xyes" -o "x$hwloc_linuxpci_happy" = "xyes"; then
|
||||
test "x$hwloc_pci_happy" = "xyes" && hwloc_probepci_list="$hwloc_pci_lib"
|
||||
test "x$hwloc_pci_happy$hwloc_linuxpci_happy" = "xyesyes" && hwloc_probepci_list="${hwloc_probepci_list}+"
|
||||
test "x$hwloc_linuxpci_happy" = "xyes" && hwloc_probepci_list="${hwloc_probepci_list}linux"
|
||||
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 anything but PCI, that anything will be useless
|
||||
test "x$hwloc_pci_happy" != "xyes" && test "x$hwloc_linuxpci_happy" != "xyes" \
|
||||
&& test "x$hwloc_probeio_list" != "x" && hwloc_probeio_list="$hwloc_probeio_list (cannot work without PCI)"
|
||||
# if nothing, say "no"
|
||||
test "x$hwloc_probeio_list" = "x" && hwloc_probeio_list=" no"
|
||||
|
||||
@ -221,13 +255,9 @@ 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
|
||||
|
||||
# Linux specific support
|
||||
AS_IF([test "$hwloc_linux" = "yes"], [cat <<EOF
|
||||
libnuma memory support: $hwloc_linux_libnuma_happy
|
||||
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
|
@ -1,4 +1,4 @@
|
||||
# Copyright © 2012 Inria. All rights reserved.
|
||||
# Copyright © 2012-2015 Inria. All rights reserved.
|
||||
# See COPYING in top-level directory.
|
||||
|
||||
# suppressions file to be passed to valgrind with
|
||||
@ -143,3 +143,18 @@
|
||||
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
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
# Copyright © 2009-2016 Inria. All rights reserved.
|
||||
# Copyright © 2009-2017 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.
|
||||
@ -36,11 +36,11 @@ sources = \
|
||||
bitmap.c \
|
||||
pci-common.c \
|
||||
diff.c \
|
||||
shmem.c \
|
||||
misc.c \
|
||||
base64.c \
|
||||
topology-noos.c \
|
||||
topology-synthetic.c \
|
||||
topology-custom.c \
|
||||
topology-xml.c \
|
||||
topology-xml-nolibxml.c
|
||||
ldflags =
|
||||
@ -58,7 +58,7 @@ hwloc_xml_libxml_la_LDFLAGS = $(plugins_ldflags) $(HWLOC_LIBXML2_LIBS)
|
||||
endif
|
||||
endif HWLOC_HAVE_LIBXML2
|
||||
|
||||
if HWLOC_HAVE_PCI
|
||||
if HWLOC_HAVE_PCIACCESS
|
||||
if HWLOC_PCI_BUILD_STATIC
|
||||
sources += topology-pci.c
|
||||
else
|
||||
@ -67,7 +67,7 @@ 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_PCI
|
||||
endif HWLOC_HAVE_PCIACCESS
|
||||
|
||||
if HWLOC_HAVE_OPENCL
|
||||
if HWLOC_OPENCL_BUILD_STATIC
|
||||
@ -131,11 +131,6 @@ sources += topology-aix.c
|
||||
ldflags += -lpthread
|
||||
endif HWLOC_HAVE_AIX
|
||||
|
||||
if HWLOC_HAVE_OSF
|
||||
sources += topology-osf.c
|
||||
ldflags += -lnuma -lpthread
|
||||
endif HWLOC_HAVE_OSF
|
||||
|
||||
if HWLOC_HAVE_HPUX
|
||||
sources += topology-hpux.c
|
||||
ldflags += -lpthread
|
306
opal/mca/hwloc/hwloc2a/hwloc/hwloc/base64.c
Обычный файл
306
opal/mca/hwloc/hwloc2a/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);
|
||||
}
|
@ -23,15 +23,15 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* TODO: HWLOC_GNU_SYS, HWLOC_IRIX_SYS,
|
||||
*
|
||||
* IRIX: see MP_MUSTRUN / _DSM_MUSTRUN, pthread_setrunon_np, /hw, procss_cpulink, numa_create
|
||||
/* 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)
|
||||
{
|
||||
@ -63,6 +63,11 @@ hwloc_fix_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t 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;
|
||||
@ -91,6 +96,11 @@ hwloc_set_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t set, int flags
|
||||
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);
|
||||
@ -115,6 +125,11 @@ hwloc_get_cpubind(hwloc_topology_t topology, hwloc_bitmap_t set, int flags)
|
||||
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;
|
||||
@ -129,6 +144,11 @@ hwloc_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_b
|
||||
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);
|
||||
|
||||
@ -140,6 +160,11 @@ hwloc_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_
|
||||
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;
|
||||
@ -154,6 +179,11 @@ hwloc_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_co
|
||||
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);
|
||||
|
||||
@ -165,6 +195,11 @@ hwloc_get_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_bi
|
||||
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);
|
||||
@ -189,6 +224,11 @@ hwloc_get_last_cpu_location(hwloc_topology_t topology, hwloc_bitmap_t set, int f
|
||||
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);
|
||||
|
||||
@ -272,9 +312,14 @@ hwloc_fix_membind_cpuset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwl
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
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;
|
||||
@ -306,21 +351,26 @@ hwloc_set_membind(hwloc_topology_t topology, hwloc_const_bitmap_t set, hwloc_mem
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_set_membind_nodeset(topology, set, policy, flags);
|
||||
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_nodeset(topology, nodeset, policy, flags);
|
||||
ret = hwloc_set_membind_by_nodeset(topology, nodeset, policy, flags);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
||||
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);
|
||||
@ -348,10 +398,10 @@ hwloc_get_membind(hwloc_topology_t topology, hwloc_bitmap_t set, hwloc_membind_p
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_get_membind_nodeset(topology, set, policy, flags);
|
||||
ret = hwloc_get_membind_by_nodeset(topology, set, policy, flags);
|
||||
} else {
|
||||
hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
|
||||
ret = hwloc_get_membind_nodeset(topology, nodeset, policy, flags);
|
||||
ret = hwloc_get_membind_by_nodeset(topology, nodeset, policy, flags);
|
||||
if (!ret)
|
||||
hwloc_cpuset_from_nodeset(topology, set, nodeset);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
@ -360,9 +410,14 @@ hwloc_get_membind(hwloc_topology_t topology, hwloc_bitmap_t set, hwloc_membind_p
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
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;
|
||||
@ -381,22 +436,27 @@ hwloc_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_b
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_set_proc_membind_nodeset(topology, pid, set, policy, flags);
|
||||
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_nodeset(topology, pid, nodeset, policy, flags);
|
||||
ret = hwloc_set_proc_membind_by_nodeset(topology, pid, nodeset, policy, flags);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
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);
|
||||
|
||||
@ -410,10 +470,10 @@ hwloc_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_get_proc_membind_nodeset(topology, pid, set, policy, flags);
|
||||
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_nodeset(topology, pid, nodeset, policy, flags);
|
||||
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);
|
||||
@ -422,9 +482,14 @@ hwloc_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
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;
|
||||
@ -446,22 +511,27 @@ hwloc_set_area_membind(hwloc_topology_t topology, const void *addr, size_t len,
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_set_area_membind_nodeset(topology, addr, len, set, policy, flags);
|
||||
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_nodeset(topology, addr, len, nodeset, policy, flags);
|
||||
ret = hwloc_set_area_membind_by_nodeset(topology, addr, len, nodeset, policy, flags);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)
|
||||
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;
|
||||
@ -481,10 +551,10 @@ hwloc_get_area_membind(hwloc_topology_t topology, const void *addr, size_t len,
|
||||
int ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_get_area_membind_nodeset(topology, addr, len, set, policy, flags);
|
||||
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_nodeset(topology, addr, len, nodeset, policy, flags);
|
||||
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);
|
||||
@ -580,10 +650,16 @@ hwloc_alloc(hwloc_topology_t topology, size_t len)
|
||||
return hwloc_alloc_heap(topology, len);
|
||||
}
|
||||
|
||||
void *
|
||||
hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
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;
|
||||
@ -623,7 +699,7 @@ hwloc_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_bitmap_t
|
||||
void *ret;
|
||||
|
||||
if (flags & HWLOC_MEMBIND_BYNODESET) {
|
||||
ret = hwloc_alloc_membind_nodeset(topology, len, set, policy, flags);
|
||||
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)) {
|
||||
@ -632,7 +708,7 @@ hwloc_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_bitmap_t
|
||||
else
|
||||
ret = hwloc_alloc(topology, len);
|
||||
} else
|
||||
ret = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags);
|
||||
ret = hwloc_alloc_membind_by_nodeset(topology, len, nodeset, policy, flags);
|
||||
hwloc_bitmap_free(nodeset);
|
||||
}
|
||||
|
||||
@ -803,10 +879,6 @@ hwloc_set_native_binding_hooks(struct hwloc_binding_hooks *hooks, struct hwloc_t
|
||||
hwloc_set_aix_hooks(hooks, support);
|
||||
# endif /* HWLOC_AIX_SYS */
|
||||
|
||||
# ifdef HWLOC_OSF_SYS
|
||||
hwloc_set_osf_hooks(hooks, support);
|
||||
# endif /* HWLOC_OSF_SYS */
|
||||
|
||||
# ifdef HWLOC_SOLARIS_SYS
|
||||
hwloc_set_solaris_hooks(hooks, support);
|
||||
# endif /* HWLOC_SOLARIS_SYS */
|
1527
opal/mca/hwloc/hwloc2a/hwloc/hwloc/bitmap.c
Обычный файл
1527
opal/mca/hwloc/hwloc2a/hwloc/hwloc/bitmap.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* Copyright © 2012 Université Bordeaux
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
@ -115,7 +115,7 @@ hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
|
||||
}
|
||||
if (component->abi != HWLOC_COMPONENT_ABI) {
|
||||
if (hwloc_plugins_verbose)
|
||||
fprintf(stderr, "Plugin symbol ABI %u instead of %u\n",
|
||||
fprintf(stderr, "Plugin symbol ABI %u instead of %d\n",
|
||||
component->abi, HWLOC_COMPONENT_ABI);
|
||||
goto out_with_handle;
|
||||
}
|
||||
@ -198,7 +198,7 @@ static int
|
||||
hwloc_plugins_init(void)
|
||||
{
|
||||
const char *verboseenv;
|
||||
char *path = HWLOC_PLUGINS_PATH;
|
||||
const char *path = HWLOC_PLUGINS_PATH;
|
||||
const char *env;
|
||||
int err;
|
||||
|
||||
@ -317,7 +317,7 @@ static void (**hwloc_component_finalize_cbs)(unsigned long);
|
||||
static unsigned hwloc_component_finalize_cb_count;
|
||||
|
||||
void
|
||||
hwloc_components_init(struct hwloc_topology *topology __hwloc_attribute_unused)
|
||||
hwloc_components_init(void)
|
||||
{
|
||||
#ifdef HWLOC_HAVE_PLUGINS
|
||||
struct hwloc__plugin_desc *desc;
|
||||
@ -329,7 +329,7 @@ hwloc_components_init(struct hwloc_topology *topology __hwloc_attribute_unused)
|
||||
assert((unsigned) -1 != hwloc_components_users);
|
||||
if (0 != hwloc_components_users++) {
|
||||
HWLOC_COMPONENTS_UNLOCK();
|
||||
goto ok;
|
||||
return;
|
||||
}
|
||||
|
||||
verboseenv = getenv("HWLOC_COMPONENTS_VERBOSE");
|
||||
@ -413,9 +413,13 @@ hwloc_components_init(struct hwloc_topology *topology __hwloc_attribute_unused)
|
||||
#endif
|
||||
|
||||
HWLOC_COMPONENTS_UNLOCK();
|
||||
}
|
||||
|
||||
ok:
|
||||
void
|
||||
hwloc_backends_init(struct hwloc_topology *topology)
|
||||
{
|
||||
topology->backends = NULL;
|
||||
topology->backend_excludes = 0;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component *
|
||||
@ -467,18 +471,16 @@ static int
|
||||
hwloc_disc_component_try_enable(struct hwloc_topology *topology,
|
||||
struct hwloc_disc_component *comp,
|
||||
const char *comparg,
|
||||
unsigned *excludes,
|
||||
int envvar_forced)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
int err;
|
||||
|
||||
if ((*excludes) & comp->type) {
|
||||
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, *excludes);
|
||||
hwloc_disc_component_type_string(comp->type), comp->name, topology->backend_excludes);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -490,13 +492,7 @@ hwloc_disc_component_try_enable(struct hwloc_topology *topology,
|
||||
}
|
||||
|
||||
backend->envvar_forced = envvar_forced;
|
||||
err = hwloc_backend_enable(topology, backend);
|
||||
if (err < 0)
|
||||
return -1;
|
||||
|
||||
*excludes |= comp->excludes;
|
||||
|
||||
return 0;
|
||||
return hwloc_backend_enable(topology, backend);
|
||||
}
|
||||
|
||||
void
|
||||
@ -504,7 +500,6 @@ hwloc_disc_components_enable_others(struct hwloc_topology *topology)
|
||||
{
|
||||
struct hwloc_disc_component *comp;
|
||||
struct hwloc_backend *backend;
|
||||
unsigned excludes = 0;
|
||||
int tryall = 1;
|
||||
const char *_env;
|
||||
char *env; /* we'll to modify the env value, so duplicate it */
|
||||
@ -512,13 +507,6 @@ hwloc_disc_components_enable_others(struct hwloc_topology *topology)
|
||||
_env = getenv("HWLOC_COMPONENTS");
|
||||
env = _env ? strdup(_env) : NULL;
|
||||
|
||||
/* compute current excludes */
|
||||
backend = topology->backends;
|
||||
while (backend) {
|
||||
excludes |= backend->component->excludes;
|
||||
backend = backend->next;
|
||||
}
|
||||
|
||||
/* enable explicitly listed components */
|
||||
if (env) {
|
||||
char *curenv = env;
|
||||
@ -527,19 +515,17 @@ hwloc_disc_components_enable_others(struct hwloc_topology *topology)
|
||||
while (*curenv) {
|
||||
s = strcspn(curenv, HWLOC_COMPONENT_SEPS);
|
||||
if (s) {
|
||||
char *arg;
|
||||
char c, d;
|
||||
char c;
|
||||
|
||||
/* replace libpci with pci for backward compatibility with v1.6 */
|
||||
if (!strncmp(curenv, "libpci", 6) && s == 6) {
|
||||
curenv[0] = curenv[1] = curenv[2] = *HWLOC_COMPONENT_SEPS;
|
||||
curenv += 3;
|
||||
s -= 3;
|
||||
} else if (curenv[0] == HWLOC_COMPONENT_EXCLUDE_CHAR && !strncmp(curenv+1, "libpci", 6) && s == 7 ) {
|
||||
curenv[3] = curenv[0];
|
||||
curenv[0] = curenv[1] = curenv[2] = *HWLOC_COMPONENT_SEPS;
|
||||
curenv += 3;
|
||||
s -= 3;
|
||||
/* 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;
|
||||
}
|
||||
@ -556,23 +542,15 @@ hwloc_disc_components_enable_others(struct hwloc_topology *topology)
|
||||
c = curenv[s];
|
||||
curenv[s] = '\0';
|
||||
|
||||
arg = strchr(curenv, '=');
|
||||
if (arg) {
|
||||
d = *arg;
|
||||
*arg = '\0';
|
||||
}
|
||||
|
||||
comp = hwloc_disc_component_find(-1, curenv);
|
||||
if (comp) {
|
||||
hwloc_disc_component_try_enable(topology, comp, arg ? arg+1 : NULL, &excludes, 1 /* envvar forced */);
|
||||
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;
|
||||
if (arg)
|
||||
*arg = d;
|
||||
}
|
||||
|
||||
nextname:
|
||||
@ -606,7 +584,7 @@ nextname:
|
||||
curenv++;
|
||||
}
|
||||
}
|
||||
hwloc_disc_component_try_enable(topology, comp, NULL, &excludes, 0 /* defaults, not envvar forced */);
|
||||
hwloc_disc_component_try_enable(topology, comp, NULL, 0 /* defaults, not envvar forced */);
|
||||
nextcomp:
|
||||
comp = comp->next;
|
||||
}
|
||||
@ -625,12 +603,11 @@ nextcomp:
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
if (env)
|
||||
free(env);
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_components_destroy_all(struct hwloc_topology *topology __hwloc_attribute_unused)
|
||||
hwloc_components_fini(void)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
@ -670,10 +647,8 @@ hwloc_backend_alloc(struct hwloc_disc_component *component)
|
||||
backend->component = component;
|
||||
backend->flags = 0;
|
||||
backend->discover = NULL;
|
||||
backend->get_obj_cpuset = NULL;
|
||||
backend->notify_new_object = NULL;
|
||||
backend->get_pci_busid_cpuset = NULL;
|
||||
backend->disable = NULL;
|
||||
backend->is_custom = 0;
|
||||
backend->is_thissystem = -1;
|
||||
backend->next = NULL;
|
||||
backend->envvar_forced = 0;
|
||||
@ -694,7 +669,7 @@ hwloc_backend_enable(struct hwloc_topology *topology, struct hwloc_backend *back
|
||||
struct hwloc_backend **pprev;
|
||||
|
||||
/* check backend flags */
|
||||
if (backend->flags & (~(HWLOC_BACKEND_FLAG_NEED_LEVELS))) {
|
||||
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;
|
||||
@ -726,7 +701,7 @@ hwloc_backend_enable(struct hwloc_topology *topology, struct hwloc_backend *back
|
||||
*pprev = backend;
|
||||
|
||||
backend->topology = topology;
|
||||
|
||||
topology->backend_excludes |= backend->component->excludes;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -775,34 +750,20 @@ hwloc_backends_is_thissystem(struct hwloc_topology *topology)
|
||||
topology->is_thissystem = atoi(local_env);
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_backends_get_obj_cpuset(struct hwloc_backend *caller, struct hwloc_obj *obj, hwloc_bitmap_t cpuset)
|
||||
void
|
||||
hwloc_backends_find_callbacks(struct hwloc_topology *topology)
|
||||
{
|
||||
struct hwloc_topology *topology = caller->topology;
|
||||
struct hwloc_backend *backend = topology->backends;
|
||||
/* use the first backend's get_obj_cpuset callback */
|
||||
/* use the first backend's get_pci_busid_cpuset callback */
|
||||
topology->get_pci_busid_cpuset_backend = NULL;
|
||||
while (backend != NULL) {
|
||||
if (backend->get_obj_cpuset)
|
||||
return backend->get_obj_cpuset(backend, caller, obj, cpuset);
|
||||
if (backend->get_pci_busid_cpuset) {
|
||||
topology->get_pci_busid_cpuset_backend = backend;
|
||||
return;
|
||||
}
|
||||
backend = backend->next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_backends_notify_new_object(struct hwloc_backend *caller, struct hwloc_obj *obj)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
int res = 0;
|
||||
|
||||
backend = caller->topology->backends;
|
||||
while (NULL != backend) {
|
||||
if (backend != caller && backend->notify_new_object)
|
||||
res += backend->notify_new_object(backend, caller, obj);
|
||||
backend = backend->next;
|
||||
}
|
||||
|
||||
return res;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
@ -819,4 +780,5 @@ hwloc_backends_disable_all(struct hwloc_topology *topology)
|
||||
topology->backends = next;
|
||||
}
|
||||
topology->backends = NULL;
|
||||
topology->backend_excludes = 0;
|
||||
}
|
468
opal/mca/hwloc/hwloc2a/hwloc/hwloc/diff.c
Обычный файл
468
opal/mca/hwloc/hwloc2a/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 */
|
||||
}
|
931
opal/mca/hwloc/hwloc2a/hwloc/hwloc/distances.c
Обычный файл
931
opal/mca/hwloc/hwloc2a/hwloc/hwloc/distances.c
Обычный файл
@ -0,0 +1,931 @@
|
||||
/*
|
||||
* 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_tma *tma = new->tma;
|
||||
struct hwloc_internal_distances_s *newdist;
|
||||
unsigned nbobjs = olddist->nbobjs;
|
||||
|
||||
newdist = hwloc_tma_malloc(tma, sizeof(*newdist));
|
||||
if (!newdist)
|
||||
return -1;
|
||||
|
||||
newdist->type = olddist->type;
|
||||
newdist->nbobjs = nbobjs;
|
||||
newdist->kind = olddist->kind;
|
||||
|
||||
newdist->indexes = hwloc_tma_malloc(tma, nbobjs * sizeof(*newdist->indexes));
|
||||
newdist->objs = hwloc_tma_calloc(tma, nbobjs * sizeof(*newdist->objs));
|
||||
newdist->objs_are_valid = 0;
|
||||
newdist->values = hwloc_tma_malloc(tma, nbobjs*nbobjs * sizeof(*newdist->values));
|
||||
if (!newdist->indexes || !newdist->objs || !newdist->values) {
|
||||
assert(!tma || !tma->dontfree); /* this tma cannot fail to allocate */
|
||||
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;
|
||||
}
|
||||
|
||||
/* This function may be called with topology->tma set, it cannot free() or realloc() */
|
||||
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;
|
||||
}
|
||||
|
||||
/* This function may be called with topology->tma set, it cannot free() or realloc() */
|
||||
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) {
|
||||
assert(!topology->tma || !topology->tma->dontfree); /* this tma cannot fail to allocate */
|
||||
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);
|
||||
}
|
@ -1,17 +1,18 @@
|
||||
<!--
|
||||
Copyright © 2009 CNRS
|
||||
Copyright © 2009-2014 Inria. All rights reserved.
|
||||
Copyright © 2009-2016 Inria. All rights reserved.
|
||||
Copyright © 2009-2011 Université Bordeaux.
|
||||
See COPYING in top-level directory.
|
||||
-->
|
||||
|
||||
<!ELEMENT topology (object)+>
|
||||
<!ELEMENT topology (object+,distances2*)>
|
||||
<!ELEMENT root (object)+>
|
||||
|
||||
<!ELEMENT object (page_type*,info*,distances*,userdata*,object*)>
|
||||
<!ATTLIST object type (System | Machine | Misc | Group | NUMANode | Package | Cache | Core | PU | Bridge | PCIDev | OSDev) #REQUIRED>
|
||||
<!ATTLIST object os_level CDATA "-1" >
|
||||
<!ELEMENT object (page_type*,info*,userdata*,object*,distances*)>
|
||||
<!ATTLIST object type (System | Machine | Misc | Group | NUMANode | Package | L1Cache | L2Cache | L3Cache | L4Cache | L5Cache | L1iCache | L2iCache | L3iCache | Core | PU | Bridge | PCIDev | OSDev) #REQUIRED>
|
||||
<!ATTLIST object subtype CDATA "" >
|
||||
<!ATTLIST object os_index CDATA "-1" >
|
||||
<!ATTLIST object gp_index CDATA "-1" >
|
||||
<!ATTLIST object name CDATA "" >
|
||||
<!ATTLIST object local_memory CDATA "0" >
|
||||
<!ATTLIST object cache_size CDATA "0" >
|
||||
@ -20,14 +21,15 @@
|
||||
<!ATTLIST object cache_type CDATA "0" >
|
||||
<!ATTLIST object huge_page_size_kB CDATA "0" >
|
||||
<!ATTLIST object huge_page_free CDATA "0" >
|
||||
<!ATTLIST object depth CDATA "-1" >
|
||||
<!ATTLIST object cpuset CDATA "0" >
|
||||
<!ATTLIST object complete_cpuset CDATA "" >
|
||||
<!ATTLIST object online_cpuset CDATA "" >
|
||||
<!ATTLIST object allowed_cpuset CDATA "" >
|
||||
<!ATTLIST object nodeset CDATA "" >
|
||||
<!ATTLIST object complete_nodeset CDATA "" >
|
||||
<!ATTLIST object allowed_nodeset CDATA "" >
|
||||
<!ATTLIST object depth CDATA "-1" >
|
||||
<!ATTLIST object kind CDATA "0" >
|
||||
<!ATTLIST object subkind CDATA "0" >
|
||||
<!ATTLIST object bridge_type CDATA "" >
|
||||
<!ATTLIST object bridge_pci CDATA "" >
|
||||
<!ATTLIST object pci_busid CDATA "" >
|
||||
@ -43,13 +45,17 @@
|
||||
<!ATTLIST info name CDATA #REQUIRED>
|
||||
<!ATTLIST info value CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT distances (latency*)>
|
||||
<!ATTLIST distances nbobjs CDATA #REQUIRED>
|
||||
<!ATTLIST distances relative_depth CDATA #REQUIRED>
|
||||
<!ATTLIST distances latency_base CDATA #REQUIRED>
|
||||
<!ELEMENT distances2 (indexes+,u64values+)>
|
||||
<!ATTLIST distances2 type CDATA #REQUIRED>
|
||||
<!ATTLIST distances2 nbobjs CDATA #REQUIRED>
|
||||
<!ATTLIST distances2 indexing CDATA #REQUIRED>
|
||||
<!ATTLIST distances2 kind CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT latency EMPTY>
|
||||
<!ATTLIST latency value CDATA #REQUIRED>
|
||||
<!ELEMENT indexes (#PCDATA)>
|
||||
<!ATTLIST indexes length CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT u64values (#PCDATA)>
|
||||
<!ATTLIST u64values length CDATA #REQUIRED>
|
||||
|
||||
<!ELEMENT userdata (#PCDATA)>
|
||||
<!ATTLIST userdata name CDATA "" >
|
||||
@ -69,3 +75,13 @@
|
||||
<!ATTLIST diff obj_attr_name CDATA "" >
|
||||
<!ATTLIST diff obj_attr_newvalue CDATA "" >
|
||||
<!ATTLIST diff obj_attr_oldvalue CDATA "" >
|
||||
|
||||
|
||||
<!-- Deprecated in 2.0+ -->
|
||||
|
||||
<!ELEMENT distances (latency*)>
|
||||
<!ATTLIST distances nbobjs CDATA #REQUIRED>
|
||||
<!ATTLIST distances relative_depth CDATA #REQUIRED>
|
||||
<!ATTLIST distances latency_base CDATA #REQUIRED>
|
||||
<!ELEMENT latency EMPTY>
|
||||
<!ATTLIST latency value CDATA #REQUIRED>
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2014 Inria. All rights reserved.
|
||||
* 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.
|
||||
@ -151,7 +151,7 @@ hwloc_progname(struct hwloc_topology *topology __hwloc_attribute_unused)
|
||||
name = __progname; /* fallback for most unix, used for OpenBSD */
|
||||
#else
|
||||
/* TODO: _NSGetExecutablePath(path, &size) on Darwin */
|
||||
/* TODO: AIX, HPUX, OSF */
|
||||
/* TODO: AIX, HPUX */
|
||||
name = NULL;
|
||||
#endif
|
||||
if (!name)
|
954
opal/mca/hwloc/hwloc2a/hwloc/hwloc/pci-common.c
Обычный файл
954
opal/mca/hwloc/hwloc2a/hwloc/hwloc/pci-common.c
Обычный файл
@ -0,0 +1,954 @@
|
||||
/*
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/plugins.h>
|
||||
#include <private/private.h>
|
||||
#include <private/debug.h>
|
||||
#include <private/misc.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HWLOC_WIN_SYS
|
||||
#include <io.h>
|
||||
#define open _open
|
||||
#define read _read
|
||||
#define close _close
|
||||
#endif
|
||||
|
||||
static void
|
||||
hwloc_pci_forced_locality_parse_one(struct hwloc_topology *topology,
|
||||
const char *string /* must contain a ' ' */,
|
||||
unsigned *allocated)
|
||||
{
|
||||
unsigned nr = topology->pci_forced_locality_nr;
|
||||
unsigned domain, bus_first, bus_last, dummy;
|
||||
hwloc_bitmap_t set;
|
||||
char *tmp;
|
||||
|
||||
if (sscanf(string, "%x:%x-%x %x", &domain, &bus_first, &bus_last, &dummy) == 4) {
|
||||
/* fine */
|
||||
} else if (sscanf(string, "%x:%x %x", &domain, &bus_first, &dummy) == 3) {
|
||||
bus_last = bus_first;
|
||||
} else if (sscanf(string, "%x %x", &domain, &dummy) == 2) {
|
||||
bus_first = 0;
|
||||
bus_last = 255;
|
||||
} else
|
||||
return;
|
||||
|
||||
tmp = strchr(string, ' ');
|
||||
if (!tmp)
|
||||
return;
|
||||
tmp++;
|
||||
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_sscanf(set, tmp);
|
||||
|
||||
if (!*allocated) {
|
||||
topology->pci_forced_locality = malloc(sizeof(*topology->pci_forced_locality));
|
||||
if (!topology->pci_forced_locality)
|
||||
goto out_with_set; /* failed to allocate, ignore this forced locality */
|
||||
*allocated = 1;
|
||||
} else if (nr >= *allocated) {
|
||||
struct hwloc_pci_forced_locality_s *tmplocs;
|
||||
tmplocs = realloc(topology->pci_forced_locality,
|
||||
2 * *allocated * sizeof(*topology->pci_forced_locality));
|
||||
if (!tmplocs)
|
||||
goto out_with_set; /* failed to allocate, ignore this forced locality */
|
||||
topology->pci_forced_locality = tmplocs;
|
||||
*allocated *= 2;
|
||||
}
|
||||
|
||||
topology->pci_forced_locality[nr].domain = domain;
|
||||
topology->pci_forced_locality[nr].bus_first = bus_first;
|
||||
topology->pci_forced_locality[nr].bus_last = bus_last;
|
||||
topology->pci_forced_locality[nr].cpuset = set;
|
||||
topology->pci_forced_locality_nr++;
|
||||
return;
|
||||
|
||||
out_with_set:
|
||||
hwloc_bitmap_free(set);
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci_forced_locality_parse(struct hwloc_topology *topology, const char *_env)
|
||||
{
|
||||
char *env = strdup(_env);
|
||||
unsigned allocated = 0;
|
||||
char *tmp = env;
|
||||
|
||||
while (1) {
|
||||
size_t len = strcspn(tmp, ";\r\n");
|
||||
char *next = NULL;
|
||||
|
||||
if (tmp[len] != '\0') {
|
||||
tmp[len] = '\0';
|
||||
if (tmp[len+1] != '\0')
|
||||
next = &tmp[len]+1;
|
||||
}
|
||||
|
||||
hwloc_pci_forced_locality_parse_one(topology, tmp, &allocated);
|
||||
|
||||
if (next)
|
||||
tmp = next;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
free(env);
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_pci_discovery_init(struct hwloc_topology *topology)
|
||||
{
|
||||
topology->pci_nonzero_domains = 0;
|
||||
topology->need_pci_belowroot_apply_locality = 0;
|
||||
|
||||
topology->pci_has_forced_locality = 0;
|
||||
topology->pci_forced_locality_nr = 0;
|
||||
topology->pci_forced_locality = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_pci_discovery_prepare(struct hwloc_topology *topology)
|
||||
{
|
||||
char *env;
|
||||
|
||||
env = getenv("HWLOC_PCI_LOCALITY");
|
||||
if (env) {
|
||||
int fd;
|
||||
|
||||
topology->pci_has_forced_locality = 1;
|
||||
|
||||
fd = open(env, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
struct stat st;
|
||||
char *buffer;
|
||||
int err = fstat(fd, &st);
|
||||
if (!err) {
|
||||
if (st.st_size <= 64*1024) { /* random limit large enough to store multiple cpusets for thousands of PUs */
|
||||
buffer = malloc(st.st_size+1);
|
||||
if (read(fd, buffer, st.st_size) == st.st_size) {
|
||||
buffer[st.st_size] = '\0';
|
||||
hwloc_pci_forced_locality_parse(topology, buffer);
|
||||
}
|
||||
free(buffer);
|
||||
} else {
|
||||
fprintf(stderr, "Ignoring HWLOC_PCI_LOCALITY file `%s' too large (%lu bytes)\n",
|
||||
env, (unsigned long) st.st_size);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
} else
|
||||
hwloc_pci_forced_locality_parse(topology, env);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_pci_discovery_exit(struct hwloc_topology *topology __hwloc_attribute_unused)
|
||||
{
|
||||
unsigned i;
|
||||
for(i=0; i<topology->pci_forced_locality_nr; i++)
|
||||
hwloc_bitmap_free(topology->pci_forced_locality[i].cpuset);
|
||||
free(topology->pci_forced_locality);
|
||||
|
||||
hwloc_pci_discovery_init(topology);
|
||||
}
|
||||
|
||||
#ifdef HWLOC_DEBUG
|
||||
static void
|
||||
hwloc_pci_traverse_print_cb(void * cbdata __hwloc_attribute_unused,
|
||||
struct hwloc_obj *pcidev)
|
||||
{
|
||||
char busid[14];
|
||||
hwloc_obj_t parent;
|
||||
|
||||
/* indent */
|
||||
parent = pcidev->parent;
|
||||
while (parent) {
|
||||
hwloc_debug("%s", " ");
|
||||
parent = parent->parent;
|
||||
}
|
||||
|
||||
snprintf(busid, sizeof(busid), "%04x:%02x:%02x.%01x",
|
||||
pcidev->attr->pcidev.domain, pcidev->attr->pcidev.bus, pcidev->attr->pcidev.dev, pcidev->attr->pcidev.func);
|
||||
|
||||
if (pcidev->type == HWLOC_OBJ_BRIDGE) {
|
||||
if (pcidev->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_HOST)
|
||||
hwloc_debug("HostBridge");
|
||||
else
|
||||
hwloc_debug("%s Bridge [%04x:%04x]", busid,
|
||||
pcidev->attr->pcidev.vendor_id, pcidev->attr->pcidev.device_id);
|
||||
hwloc_debug(" to %04x:[%02x:%02x]\n",
|
||||
pcidev->attr->bridge.downstream.pci.domain, pcidev->attr->bridge.downstream.pci.secondary_bus, pcidev->attr->bridge.downstream.pci.subordinate_bus);
|
||||
} else
|
||||
hwloc_debug("%s Device [%04x:%04x (%04x:%04x) rev=%02x class=%04x]\n", busid,
|
||||
pcidev->attr->pcidev.vendor_id, pcidev->attr->pcidev.device_id,
|
||||
pcidev->attr->pcidev.subvendor_id, pcidev->attr->pcidev.subdevice_id,
|
||||
pcidev->attr->pcidev.revision, pcidev->attr->pcidev.class_id);
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci__traverse(void * cbdata, struct hwloc_obj *tree,
|
||||
void (*cb)(void * cbdata, struct hwloc_obj *))
|
||||
{
|
||||
struct hwloc_obj *child = tree;
|
||||
while (child) {
|
||||
cb(cbdata, child);
|
||||
if (child->type == HWLOC_OBJ_BRIDGE && child->io_first_child)
|
||||
hwloc_pci__traverse(cbdata, child->io_first_child, cb);
|
||||
child = child->next_sibling;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci_traverse(void * cbdata, struct hwloc_obj *tree,
|
||||
void (*cb)(void * cbdata, struct hwloc_obj *))
|
||||
{
|
||||
hwloc_pci__traverse(cbdata, tree, cb);
|
||||
}
|
||||
#endif /* HWLOC_DEBUG */
|
||||
|
||||
enum hwloc_pci_busid_comparison_e {
|
||||
HWLOC_PCI_BUSID_LOWER,
|
||||
HWLOC_PCI_BUSID_HIGHER,
|
||||
HWLOC_PCI_BUSID_INCLUDED,
|
||||
HWLOC_PCI_BUSID_SUPERSET
|
||||
};
|
||||
|
||||
static enum hwloc_pci_busid_comparison_e
|
||||
hwloc_pci_compare_busids(struct hwloc_obj *a, struct hwloc_obj *b)
|
||||
{
|
||||
#ifdef HWLOC_DEBUG
|
||||
if (a->type == HWLOC_OBJ_BRIDGE)
|
||||
assert(a->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI);
|
||||
if (b->type == HWLOC_OBJ_BRIDGE)
|
||||
assert(b->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI);
|
||||
#endif
|
||||
|
||||
if (a->attr->pcidev.domain < b->attr->pcidev.domain)
|
||||
return HWLOC_PCI_BUSID_LOWER;
|
||||
if (a->attr->pcidev.domain > b->attr->pcidev.domain)
|
||||
return HWLOC_PCI_BUSID_HIGHER;
|
||||
|
||||
if (a->type == HWLOC_OBJ_BRIDGE
|
||||
&& b->attr->pcidev.bus >= a->attr->bridge.downstream.pci.secondary_bus
|
||||
&& b->attr->pcidev.bus <= a->attr->bridge.downstream.pci.subordinate_bus)
|
||||
return HWLOC_PCI_BUSID_SUPERSET;
|
||||
if (b->type == HWLOC_OBJ_BRIDGE
|
||||
&& a->attr->pcidev.bus >= b->attr->bridge.downstream.pci.secondary_bus
|
||||
&& a->attr->pcidev.bus <= b->attr->bridge.downstream.pci.subordinate_bus)
|
||||
return HWLOC_PCI_BUSID_INCLUDED;
|
||||
|
||||
if (a->attr->pcidev.bus < b->attr->pcidev.bus)
|
||||
return HWLOC_PCI_BUSID_LOWER;
|
||||
if (a->attr->pcidev.bus > b->attr->pcidev.bus)
|
||||
return HWLOC_PCI_BUSID_HIGHER;
|
||||
|
||||
if (a->attr->pcidev.dev < b->attr->pcidev.dev)
|
||||
return HWLOC_PCI_BUSID_LOWER;
|
||||
if (a->attr->pcidev.dev > b->attr->pcidev.dev)
|
||||
return HWLOC_PCI_BUSID_HIGHER;
|
||||
|
||||
if (a->attr->pcidev.func < b->attr->pcidev.func)
|
||||
return HWLOC_PCI_BUSID_LOWER;
|
||||
if (a->attr->pcidev.func > b->attr->pcidev.func)
|
||||
return HWLOC_PCI_BUSID_HIGHER;
|
||||
|
||||
/* Should never reach here. Abort on both debug builds and
|
||||
non-debug builds */
|
||||
assert(0);
|
||||
fprintf(stderr, "Bad assertion in hwloc %s:%d (aborting)\n", __FILE__, __LINE__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_pci_add_object(struct hwloc_obj *parent, struct hwloc_obj **parent_io_first_child_p, struct hwloc_obj *new)
|
||||
{
|
||||
struct hwloc_obj **curp, **childp;
|
||||
|
||||
curp = parent_io_first_child_p;
|
||||
while (*curp) {
|
||||
enum hwloc_pci_busid_comparison_e comp = hwloc_pci_compare_busids(new, *curp);
|
||||
switch (comp) {
|
||||
case HWLOC_PCI_BUSID_HIGHER:
|
||||
/* go further */
|
||||
curp = &(*curp)->next_sibling;
|
||||
continue;
|
||||
case HWLOC_PCI_BUSID_INCLUDED:
|
||||
/* insert new below current bridge */
|
||||
hwloc_pci_add_object(*curp, &(*curp)->io_first_child, new);
|
||||
return;
|
||||
case HWLOC_PCI_BUSID_LOWER:
|
||||
case HWLOC_PCI_BUSID_SUPERSET: {
|
||||
/* insert new before current */
|
||||
new->next_sibling = *curp;
|
||||
*curp = new;
|
||||
new->parent = parent;
|
||||
if (new->type == HWLOC_OBJ_BRIDGE) {
|
||||
/* look at remaining siblings and move some below new */
|
||||
childp = &new->io_first_child;
|
||||
curp = &new->next_sibling;
|
||||
while (*curp) {
|
||||
hwloc_obj_t cur = *curp;
|
||||
if (hwloc_pci_compare_busids(new, cur) == HWLOC_PCI_BUSID_LOWER) {
|
||||
/* this sibling remains under root, after new. */
|
||||
if (cur->attr->pcidev.domain > new->attr->pcidev.domain
|
||||
|| cur->attr->pcidev.bus > new->attr->bridge.downstream.pci.subordinate_bus)
|
||||
/* this sibling is even above new's subordinate bus, no other sibling could go below new */
|
||||
return;
|
||||
curp = &cur->next_sibling;
|
||||
} else {
|
||||
/* this sibling goes under new */
|
||||
*childp = cur;
|
||||
*curp = cur->next_sibling;
|
||||
(*childp)->parent = new;
|
||||
(*childp)->next_sibling = NULL;
|
||||
childp = &(*childp)->next_sibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* add to the end of the list if higher than everybody */
|
||||
new->parent = parent;
|
||||
new->next_sibling = NULL;
|
||||
*curp = new;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc_pci_tree_insert_by_busid(struct hwloc_obj **treep,
|
||||
struct hwloc_obj *obj)
|
||||
{
|
||||
hwloc_pci_add_object(NULL /* no parent on top of tree */, treep, obj);
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_pci_tree_attach_belowroot(struct hwloc_topology *topology, struct hwloc_obj *old_tree)
|
||||
{
|
||||
struct hwloc_obj **next_hb_p;
|
||||
enum hwloc_type_filter_e bfilter;
|
||||
|
||||
if (!old_tree)
|
||||
/* found nothing, exit */
|
||||
return 0;
|
||||
|
||||
#ifdef HWLOC_DEBUG
|
||||
hwloc_debug("%s", "\nPCI hierarchy:\n");
|
||||
hwloc_pci_traverse(NULL, old_tree, hwloc_pci_traverse_print_cb);
|
||||
hwloc_debug("%s", "\n");
|
||||
#endif
|
||||
|
||||
next_hb_p = &hwloc_get_root_obj(topology)->io_first_child;
|
||||
while (*next_hb_p)
|
||||
next_hb_p = &((*next_hb_p)->next_sibling);
|
||||
|
||||
bfilter = topology->type_filter[HWLOC_OBJ_BRIDGE];
|
||||
if (bfilter == HWLOC_TYPE_FILTER_KEEP_NONE) {
|
||||
*next_hb_p = old_tree;
|
||||
topology->modified = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* tree points to all objects connected to any upstream bus in the machine.
|
||||
* We now create one real hostbridge object per upstream bus.
|
||||
* It's not actually a PCI device so we have to create it.
|
||||
*/
|
||||
while (old_tree) {
|
||||
/* start a new host bridge */
|
||||
struct hwloc_obj *hostbridge = hwloc_alloc_setup_object(topology, HWLOC_OBJ_BRIDGE, -1);
|
||||
struct hwloc_obj **dstnextp = &hostbridge->io_first_child;
|
||||
struct hwloc_obj **srcnextp = &old_tree;
|
||||
struct hwloc_obj *child = *srcnextp;
|
||||
unsigned short current_domain = child->attr->pcidev.domain;
|
||||
unsigned char current_bus = child->attr->pcidev.bus;
|
||||
unsigned char current_subordinate = current_bus;
|
||||
|
||||
hwloc_debug("Starting new PCI hostbridge %04x:%02x\n", current_domain, current_bus);
|
||||
|
||||
next_child:
|
||||
/* remove next child from tree */
|
||||
*srcnextp = child->next_sibling;
|
||||
/* append it to hostbridge */
|
||||
*dstnextp = child;
|
||||
child->parent = hostbridge;
|
||||
child->next_sibling = NULL;
|
||||
dstnextp = &child->next_sibling;
|
||||
|
||||
/* compute hostbridge secondary/subordinate buses */
|
||||
if (child->type == HWLOC_OBJ_BRIDGE
|
||||
&& child->attr->bridge.downstream.pci.subordinate_bus > current_subordinate)
|
||||
current_subordinate = child->attr->bridge.downstream.pci.subordinate_bus;
|
||||
|
||||
/* use next child if it has the same domains/bus */
|
||||
child = *srcnextp;
|
||||
if (child
|
||||
&& child->attr->pcidev.domain == current_domain
|
||||
&& child->attr->pcidev.bus == current_bus)
|
||||
goto next_child;
|
||||
|
||||
/* finish setting up this hostbridge */
|
||||
hostbridge->attr->bridge.upstream_type = HWLOC_OBJ_BRIDGE_HOST;
|
||||
hostbridge->attr->bridge.downstream_type = HWLOC_OBJ_BRIDGE_PCI;
|
||||
hostbridge->attr->bridge.downstream.pci.domain = current_domain;
|
||||
hostbridge->attr->bridge.downstream.pci.secondary_bus = current_bus;
|
||||
hostbridge->attr->bridge.downstream.pci.subordinate_bus = current_subordinate;
|
||||
hwloc_debug("New PCI hostbridge %04x:[%02x-%02x]\n",
|
||||
current_domain, current_bus, current_subordinate);
|
||||
|
||||
if (current_domain)
|
||||
topology->pci_nonzero_domains = 1;
|
||||
|
||||
*next_hb_p = hostbridge;
|
||||
next_hb_p = &hostbridge->next_sibling;
|
||||
topology->modified = 1; /* needed in case somebody reconnects levels before the core calls hwloc_pci_belowroot_apply_locality()
|
||||
* or if hwloc_pci_belowroot_apply_locality() keeps hostbridges below root.
|
||||
*/
|
||||
}
|
||||
|
||||
done:
|
||||
topology->need_pci_belowroot_apply_locality = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_obj *
|
||||
hwloc_pci_fixup_busid_parent(struct hwloc_topology *topology __hwloc_attribute_unused,
|
||||
struct hwloc_pcidev_attr_s *busid,
|
||||
struct hwloc_obj *parent)
|
||||
{
|
||||
/* Xeon E5v3 in cluster-on-die mode only have PCI on the first NUMA node of each package.
|
||||
* but many dual-processor host report the second PCI hierarchy on 2nd NUMA of first package.
|
||||
*/
|
||||
if (parent->depth >= 2
|
||||
&& parent->type == HWLOC_OBJ_NUMANODE
|
||||
&& parent->sibling_rank == 1 && parent->parent->arity == 2
|
||||
&& parent->parent->type == HWLOC_OBJ_PACKAGE
|
||||
&& parent->parent->sibling_rank == 0 && parent->parent->parent->arity == 2) {
|
||||
const char *cpumodel = hwloc_obj_get_info_by_name(parent->parent, "CPUModel");
|
||||
if (cpumodel && strstr(cpumodel, "Xeon")) {
|
||||
if (!hwloc_hide_errors()) {
|
||||
fprintf(stderr, "****************************************************************************\n");
|
||||
fprintf(stderr, "* hwloc %s has encountered an incorrect PCI locality information.\n", HWLOC_VERSION);
|
||||
fprintf(stderr, "* PCI bus %04x:%02x is supposedly close to 2nd NUMA node of 1st package,\n",
|
||||
busid->domain, busid->bus);
|
||||
fprintf(stderr, "* however hwloc believes this is impossible on this architecture.\n");
|
||||
fprintf(stderr, "* Therefore the PCI bus will be moved to 1st NUMA node of 2nd package.\n");
|
||||
fprintf(stderr, "*\n");
|
||||
fprintf(stderr, "* If you feel this fixup is wrong, disable it by setting in your environment\n");
|
||||
fprintf(stderr, "* HWLOC_PCI_%04x_%02x_LOCALCPUS= (empty value), and report the problem\n",
|
||||
busid->domain, busid->bus);
|
||||
fprintf(stderr, "* to the hwloc's user mailing list together with the XML output of lstopo.\n");
|
||||
fprintf(stderr, "*\n");
|
||||
fprintf(stderr, "* You may silence this message by setting HWLOC_HIDE_ERRORS=1 in your environment.\n");
|
||||
fprintf(stderr, "****************************************************************************\n");
|
||||
}
|
||||
return parent->parent->next_sibling->first_child;
|
||||
}
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
static struct hwloc_obj *
|
||||
hwloc__pci_find_busid_parent(struct hwloc_topology *topology, struct hwloc_pcidev_attr_s *busid)
|
||||
{
|
||||
hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_obj_t parent;
|
||||
int forced = 0;
|
||||
int noquirks = 0;
|
||||
unsigned i;
|
||||
int err;
|
||||
|
||||
/* try to match a forced locality */
|
||||
if (topology->pci_has_forced_locality) {
|
||||
for(i=0; i<topology->pci_forced_locality_nr; i++) {
|
||||
if (busid->domain == topology->pci_forced_locality[i].domain
|
||||
&& busid->bus >= topology->pci_forced_locality[i].bus_first
|
||||
&& busid->bus <= topology->pci_forced_locality[i].bus_last) {
|
||||
hwloc_bitmap_copy(cpuset, topology->pci_forced_locality[i].cpuset);
|
||||
forced = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* if pci locality was forced, even empty, don't let quirks change what the OS reports */
|
||||
noquirks = 1;
|
||||
}
|
||||
|
||||
/* deprecated force locality variables */
|
||||
if (!forced) {
|
||||
const char *env;
|
||||
char envname[256];
|
||||
/* override the cpuset with the environment if given */
|
||||
snprintf(envname, sizeof(envname), "HWLOC_PCI_%04x_%02x_LOCALCPUS",
|
||||
busid->domain, busid->bus);
|
||||
env = getenv(envname);
|
||||
if (env) {
|
||||
static int reported = 0;
|
||||
if (!topology->pci_has_forced_locality && !reported) {
|
||||
fprintf(stderr, "Environment variable %s is deprecated, please use HWLOC_PCI_LOCALITY instead.\n", env);
|
||||
reported = 1;
|
||||
}
|
||||
if (*env) {
|
||||
/* force the cpuset */
|
||||
hwloc_debug("Overriding localcpus using %s in the environment\n", envname);
|
||||
hwloc_bitmap_sscanf(cpuset, env);
|
||||
forced = 1;
|
||||
}
|
||||
/* if env exists, even empty, don't let quirks change what the OS reports */
|
||||
noquirks = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!forced) {
|
||||
/* get the cpuset by asking the OS backend. */
|
||||
struct hwloc_backend *backend = topology->get_pci_busid_cpuset_backend;
|
||||
if (backend)
|
||||
err = backend->get_pci_busid_cpuset(backend, busid, cpuset);
|
||||
else
|
||||
err = -1;
|
||||
if (err < 0)
|
||||
/* if we got nothing, assume this PCI bus is attached to the top of hierarchy */
|
||||
hwloc_bitmap_copy(cpuset, hwloc_topology_get_topology_cpuset(topology));
|
||||
}
|
||||
|
||||
hwloc_debug_bitmap("Attaching PCI tree to cpuset %s\n", cpuset);
|
||||
|
||||
parent = hwloc_find_insert_io_parent_by_complete_cpuset(topology, cpuset);
|
||||
if (parent) {
|
||||
if (!noquirks)
|
||||
/* We found a valid parent. Check that the OS didn't report invalid locality */
|
||||
parent = hwloc_pci_fixup_busid_parent(topology, busid, parent);
|
||||
} else {
|
||||
/* Fallback to root */
|
||||
parent = hwloc_get_root_obj(topology);
|
||||
}
|
||||
|
||||
hwloc_bitmap_free(cpuset);
|
||||
return parent;
|
||||
}
|
||||
|
||||
struct hwloc_obj *
|
||||
hwloc_pci_find_busid_parent(struct hwloc_topology *topology,
|
||||
unsigned domain, unsigned bus, unsigned dev, unsigned func)
|
||||
{
|
||||
struct hwloc_pcidev_attr_s busid;
|
||||
busid.domain = domain;
|
||||
busid.bus = bus;
|
||||
busid.dev = dev;
|
||||
busid.func = func;
|
||||
return hwloc__pci_find_busid_parent(topology, &busid);
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_pci_belowroot_apply_locality(struct hwloc_topology *topology)
|
||||
{
|
||||
struct hwloc_obj *root = hwloc_get_root_obj(topology);
|
||||
struct hwloc_obj **listp, *obj;
|
||||
|
||||
if (!topology->need_pci_belowroot_apply_locality)
|
||||
return 0;
|
||||
topology->need_pci_belowroot_apply_locality = 0;
|
||||
|
||||
/* root->io_first_child contains some PCI hierarchies, any maybe some non-PCI things.
|
||||
* insert the PCI trees according to their PCI-locality.
|
||||
*/
|
||||
listp = &root->io_first_child;
|
||||
while ((obj = *listp) != NULL) {
|
||||
struct hwloc_pcidev_attr_s *busid;
|
||||
struct hwloc_obj *parent;
|
||||
|
||||
/* skip non-PCI objects */
|
||||
if (obj->type != HWLOC_OBJ_PCI_DEVICE
|
||||
&& !(obj->type == HWLOC_OBJ_BRIDGE && obj->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI)
|
||||
&& !(obj->type == HWLOC_OBJ_BRIDGE && obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI)) {
|
||||
listp = &obj->next_sibling;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (obj->type == HWLOC_OBJ_PCI_DEVICE
|
||||
|| (obj->type == HWLOC_OBJ_BRIDGE
|
||||
&& obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI))
|
||||
busid = &obj->attr->pcidev;
|
||||
else {
|
||||
/* hostbridges don't have a PCI busid for looking up locality, use their first child if PCI */
|
||||
hwloc_obj_t child = obj->io_first_child;
|
||||
if (child && (child->type == HWLOC_OBJ_PCI_DEVICE
|
||||
|| (child->type == HWLOC_OBJ_BRIDGE
|
||||
&& child->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI)))
|
||||
busid = &obj->io_first_child->attr->pcidev;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
/* attach the object (and children) where it belongs */
|
||||
parent = hwloc__pci_find_busid_parent(topology, busid);
|
||||
if (parent == root) {
|
||||
/* keep this object here */
|
||||
listp = &obj->next_sibling;
|
||||
} else {
|
||||
/* dequeue this object */
|
||||
*listp = obj->next_sibling;
|
||||
obj->next_sibling = NULL;
|
||||
hwloc_insert_object_by_parent(topology, parent, obj);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_obj *
|
||||
hwloc__pci_belowroot_find_by_busid(hwloc_obj_t parent,
|
||||
unsigned domain, unsigned bus, unsigned dev, unsigned func)
|
||||
{
|
||||
hwloc_obj_t child = parent->io_first_child;
|
||||
|
||||
for ( ; child; child = child->next_sibling) {
|
||||
if (child->type == HWLOC_OBJ_PCI_DEVICE
|
||||
|| (child->type == HWLOC_OBJ_BRIDGE
|
||||
&& child->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI)) {
|
||||
if (child->attr->pcidev.domain == domain
|
||||
&& child->attr->pcidev.bus == bus
|
||||
&& child->attr->pcidev.dev == dev
|
||||
&& child->attr->pcidev.func == func)
|
||||
/* that's the right bus id */
|
||||
return child;
|
||||
if (child->attr->pcidev.domain > domain
|
||||
|| (child->attr->pcidev.domain == domain
|
||||
&& child->attr->pcidev.bus > bus))
|
||||
/* bus id too high, won't find anything later, return parent */
|
||||
return parent;
|
||||
if (child->type == HWLOC_OBJ_BRIDGE
|
||||
&& child->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI
|
||||
&& child->attr->bridge.downstream.pci.domain == domain
|
||||
&& child->attr->bridge.downstream.pci.secondary_bus <= bus
|
||||
&& child->attr->bridge.downstream.pci.subordinate_bus >= bus)
|
||||
/* not the right bus id, but it's included in the bus below that bridge */
|
||||
return hwloc__pci_belowroot_find_by_busid(child, domain, bus, dev, func);
|
||||
|
||||
} else if (child->type == HWLOC_OBJ_BRIDGE
|
||||
&& child->attr->bridge.upstream_type != HWLOC_OBJ_BRIDGE_PCI
|
||||
&& child->attr->bridge.downstream_type == HWLOC_OBJ_BRIDGE_PCI
|
||||
/* non-PCI to PCI bridge, just look at the subordinate bus */
|
||||
&& child->attr->bridge.downstream.pci.domain == domain
|
||||
&& child->attr->bridge.downstream.pci.secondary_bus <= bus
|
||||
&& child->attr->bridge.downstream.pci.subordinate_bus >= bus) {
|
||||
/* contains our bus, recurse */
|
||||
return hwloc__pci_belowroot_find_by_busid(child, domain, bus, dev, func);
|
||||
}
|
||||
}
|
||||
/* didn't find anything, return parent */
|
||||
return parent;
|
||||
}
|
||||
|
||||
struct hwloc_obj *
|
||||
hwloc_pci_belowroot_find_by_busid(struct hwloc_topology *topology,
|
||||
unsigned domain, unsigned bus, unsigned dev, unsigned func)
|
||||
{
|
||||
hwloc_obj_t root = hwloc_get_root_obj(topology);
|
||||
hwloc_obj_t parent = hwloc__pci_belowroot_find_by_busid(root, domain, bus, dev, func);
|
||||
if (parent == root)
|
||||
return NULL;
|
||||
else
|
||||
return parent;
|
||||
}
|
||||
|
||||
#define HWLOC_PCI_STATUS 0x06
|
||||
#define HWLOC_PCI_STATUS_CAP_LIST 0x10
|
||||
#define HWLOC_PCI_CAPABILITY_LIST 0x34
|
||||
#define HWLOC_PCI_CAP_LIST_ID 0
|
||||
#define HWLOC_PCI_CAP_LIST_NEXT 1
|
||||
|
||||
unsigned
|
||||
hwloc_pci_find_cap(const unsigned char *config, unsigned cap)
|
||||
{
|
||||
unsigned char seen[256] = { 0 };
|
||||
unsigned char ptr; /* unsigned char to make sure we stay within the 256-byte config space */
|
||||
|
||||
if (!(config[HWLOC_PCI_STATUS] & HWLOC_PCI_STATUS_CAP_LIST))
|
||||
return 0;
|
||||
|
||||
for (ptr = config[HWLOC_PCI_CAPABILITY_LIST] & ~3;
|
||||
ptr; /* exit if next is 0 */
|
||||
ptr = config[ptr + HWLOC_PCI_CAP_LIST_NEXT] & ~3) {
|
||||
unsigned char id;
|
||||
|
||||
/* Looped around! */
|
||||
if (seen[ptr])
|
||||
break;
|
||||
seen[ptr] = 1;
|
||||
|
||||
id = config[ptr + HWLOC_PCI_CAP_LIST_ID];
|
||||
if (id == cap)
|
||||
return ptr;
|
||||
if (id == 0xff) /* exit if id is 0 or 0xff */
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define HWLOC_PCI_EXP_LNKSTA 0x12
|
||||
#define HWLOC_PCI_EXP_LNKSTA_SPEED 0x000f
|
||||
#define HWLOC_PCI_EXP_LNKSTA_WIDTH 0x03f0
|
||||
|
||||
int
|
||||
hwloc_pci_find_linkspeed(const unsigned char *config,
|
||||
unsigned offset, float *linkspeed)
|
||||
{
|
||||
unsigned linksta, speed, width;
|
||||
float lanespeed;
|
||||
|
||||
memcpy(&linksta, &config[offset + HWLOC_PCI_EXP_LNKSTA], 4);
|
||||
speed = linksta & HWLOC_PCI_EXP_LNKSTA_SPEED; /* PCIe generation */
|
||||
width = (linksta & HWLOC_PCI_EXP_LNKSTA_WIDTH) >> 4; /* how many lanes */
|
||||
/* PCIe Gen1 = 2.5GT/s signal-rate per lane with 8/10 encoding = 0.25GB/s data-rate per lane
|
||||
* PCIe Gen2 = 5 GT/s signal-rate per lane with 8/10 encoding = 0.5 GB/s data-rate per lane
|
||||
* PCIe Gen3 = 8 GT/s signal-rate per lane with 128/130 encoding = 1 GB/s data-rate per lane
|
||||
* PCIe Gen4 = 16 GT/s signal-rate per lane with 128/130 encoding = 2 GB/s data-rate per lane
|
||||
*/
|
||||
|
||||
/* lanespeed in Gbit/s */
|
||||
if (speed <= 2)
|
||||
lanespeed = 2.5f * speed * 0.8f;
|
||||
else
|
||||
lanespeed = 8.0f * (1<<(speed-3)) * 128/130; /* assume Gen5 will be 32 GT/s and so on */
|
||||
|
||||
/* linkspeed in GB/s */
|
||||
*linkspeed = lanespeed * width / 8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define HWLOC_PCI_HEADER_TYPE 0x0e
|
||||
#define HWLOC_PCI_HEADER_TYPE_BRIDGE 1
|
||||
#define HWLOC_PCI_CLASS_BRIDGE_PCI 0x0604
|
||||
|
||||
hwloc_obj_type_t
|
||||
hwloc_pci_check_bridge_type(unsigned device_class, const unsigned char *config)
|
||||
{
|
||||
unsigned char headertype;
|
||||
|
||||
if (device_class != HWLOC_PCI_CLASS_BRIDGE_PCI)
|
||||
return HWLOC_OBJ_PCI_DEVICE;
|
||||
|
||||
headertype = config[HWLOC_PCI_HEADER_TYPE] & 0x7f;
|
||||
return (headertype == HWLOC_PCI_HEADER_TYPE_BRIDGE)
|
||||
? HWLOC_OBJ_BRIDGE : HWLOC_OBJ_PCI_DEVICE;
|
||||
}
|
||||
|
||||
#define HWLOC_PCI_PRIMARY_BUS 0x18
|
||||
#define HWLOC_PCI_SECONDARY_BUS 0x19
|
||||
#define HWLOC_PCI_SUBORDINATE_BUS 0x1a
|
||||
|
||||
int
|
||||
hwloc_pci_setup_bridge_attr(hwloc_obj_t obj,
|
||||
const unsigned char *config)
|
||||
{
|
||||
struct hwloc_bridge_attr_s *battr = &obj->attr->bridge;
|
||||
struct hwloc_pcidev_attr_s *pattr = &battr->upstream.pci;
|
||||
|
||||
if (config[HWLOC_PCI_PRIMARY_BUS] != pattr->bus) {
|
||||
/* Sometimes the config space contains 00 instead of the actual primary bus number.
|
||||
* Always trust the bus ID because it was built by the system which has more information
|
||||
* to workaround such problems (e.g. ACPI information about PCI parent/children).
|
||||
*/
|
||||
hwloc_debug(" %04x:%02x:%02x.%01x bridge with (ignored) invalid PCI_PRIMARY_BUS %02x\n",
|
||||
pattr->domain, pattr->bus, pattr->dev, pattr->func, config[HWLOC_PCI_PRIMARY_BUS]);
|
||||
}
|
||||
|
||||
obj->type = HWLOC_OBJ_BRIDGE;
|
||||
battr->upstream_type = HWLOC_OBJ_BRIDGE_PCI;
|
||||
battr->downstream_type = HWLOC_OBJ_BRIDGE_PCI;
|
||||
battr->downstream.pci.domain = pattr->domain;
|
||||
battr->downstream.pci.secondary_bus = config[HWLOC_PCI_SECONDARY_BUS];
|
||||
battr->downstream.pci.subordinate_bus = config[HWLOC_PCI_SUBORDINATE_BUS];
|
||||
|
||||
if (battr->downstream.pci.secondary_bus <= pattr->bus
|
||||
|| battr->downstream.pci.subordinate_bus <= pattr->bus
|
||||
|| battr->downstream.pci.secondary_bus > battr->downstream.pci.subordinate_bus) {
|
||||
/* This should catch most cases of invalid bridge information
|
||||
* (e.g. 00 for secondary and subordinate).
|
||||
* Ideally we would also check that [secondary-subordinate] is included
|
||||
* in the parent bridge [secondary+1:subordinate]. But that's hard to do
|
||||
* because objects may be discovered out of order (especially in the fsroot case).
|
||||
*/
|
||||
hwloc_debug(" %04x:%02x:%02x.%01x bridge has invalid secondary-subordinate buses [%02x-%02x]\n",
|
||||
pattr->domain, pattr->bus, pattr->dev, pattr->func,
|
||||
battr->downstream.pci.secondary_bus, battr->downstream.pci.subordinate_bus);
|
||||
hwloc_free_unlinked_object(obj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *
|
||||
hwloc_pci_class_string(unsigned short class_id)
|
||||
{
|
||||
/* See https://pci-ids.ucw.cz/read/PD/ */
|
||||
switch ((class_id & 0xff00) >> 8) {
|
||||
case 0x00:
|
||||
switch (class_id) {
|
||||
case 0x0001: return "VGA";
|
||||
}
|
||||
break;
|
||||
case 0x01:
|
||||
switch (class_id) {
|
||||
case 0x0100: return "SCSI";
|
||||
case 0x0101: return "IDE";
|
||||
case 0x0102: return "Floppy";
|
||||
case 0x0103: return "IPI";
|
||||
case 0x0104: return "RAID";
|
||||
case 0x0105: return "ATA";
|
||||
case 0x0106: return "SATA";
|
||||
case 0x0107: return "SAS";
|
||||
case 0x0108: return "NVMExp";
|
||||
}
|
||||
return "Storage";
|
||||
case 0x02:
|
||||
switch (class_id) {
|
||||
case 0x0200: return "Ethernet";
|
||||
case 0x0201: return "TokenRing";
|
||||
case 0x0202: return "FDDI";
|
||||
case 0x0203: return "ATM";
|
||||
case 0x0204: return "ISDN";
|
||||
case 0x0205: return "WorldFip";
|
||||
case 0x0206: return "PICMG";
|
||||
case 0x0207: return "InfiniBand";
|
||||
case 0x0208: return "Fabric";
|
||||
}
|
||||
return "Network";
|
||||
case 0x03:
|
||||
switch (class_id) {
|
||||
case 0x0300: return "VGA";
|
||||
case 0x0301: return "XGA";
|
||||
case 0x0302: return "3D";
|
||||
}
|
||||
return "Display";
|
||||
case 0x04:
|
||||
switch (class_id) {
|
||||
case 0x0400: return "MultimediaVideo";
|
||||
case 0x0401: return "MultimediaAudio";
|
||||
case 0x0402: return "Telephony";
|
||||
case 0x0403: return "AudioDevice";
|
||||
}
|
||||
return "Multimedia";
|
||||
case 0x05:
|
||||
switch (class_id) {
|
||||
case 0x0500: return "RAM";
|
||||
case 0x0501: return "Flash";
|
||||
}
|
||||
return "Memory";
|
||||
case 0x06:
|
||||
switch (class_id) {
|
||||
case 0x0600: return "HostBridge";
|
||||
case 0x0601: return "ISABridge";
|
||||
case 0x0602: return "EISABridge";
|
||||
case 0x0603: return "MicroChannelBridge";
|
||||
case 0x0604: return "PCIBridge";
|
||||
case 0x0605: return "PCMCIABridge";
|
||||
case 0x0606: return "NubusBridge";
|
||||
case 0x0607: return "CardBusBridge";
|
||||
case 0x0608: return "RACEwayBridge";
|
||||
case 0x0609: return "SemiTransparentPCIBridge";
|
||||
case 0x060a: return "InfiniBandPCIHostBridge";
|
||||
}
|
||||
return "Bridge";
|
||||
case 0x07:
|
||||
switch (class_id) {
|
||||
case 0x0700: return "Serial";
|
||||
case 0x0701: return "Parallel";
|
||||
case 0x0702: return "MultiportSerial";
|
||||
case 0x0703: return "Model";
|
||||
case 0x0704: return "GPIB";
|
||||
case 0x0705: return "SmartCard";
|
||||
}
|
||||
return "Communication";
|
||||
case 0x08:
|
||||
switch (class_id) {
|
||||
case 0x0800: return "PIC";
|
||||
case 0x0801: return "DMA";
|
||||
case 0x0802: return "Timer";
|
||||
case 0x0803: return "RTC";
|
||||
case 0x0804: return "PCIHotPlug";
|
||||
case 0x0805: return "SDHost";
|
||||
case 0x0806: return "IOMMU";
|
||||
}
|
||||
return "SystemPeripheral";
|
||||
case 0x09:
|
||||
switch (class_id) {
|
||||
case 0x0900: return "Keyboard";
|
||||
case 0x0901: return "DigitizerPen";
|
||||
case 0x0902: return "Mouse";
|
||||
case 0x0903: return "Scanern";
|
||||
case 0x0904: return "Gameport";
|
||||
}
|
||||
return "Input";
|
||||
case 0x0a:
|
||||
return "DockingStation";
|
||||
case 0x0b:
|
||||
switch (class_id) {
|
||||
case 0x0b00: return "386";
|
||||
case 0x0b01: return "486";
|
||||
case 0x0b02: return "Pentium";
|
||||
/* 0x0b03 and 0x0b04 might be Pentium and P6 ? */
|
||||
case 0x0b10: return "Alpha";
|
||||
case 0x0b20: return "PowerPC";
|
||||
case 0x0b30: return "MIPS";
|
||||
case 0x0b40: return "Co-Processor";
|
||||
}
|
||||
return "Processor";
|
||||
case 0x0c:
|
||||
switch (class_id) {
|
||||
case 0x0c00: return "FireWire";
|
||||
case 0x0c01: return "ACCESS";
|
||||
case 0x0c02: return "SSA";
|
||||
case 0x0c03: return "USB";
|
||||
case 0x0c04: return "FibreChannel";
|
||||
case 0x0c05: return "SMBus";
|
||||
case 0x0c06: return "InfiniBand";
|
||||
case 0x0c07: return "IPMI-SMIC";
|
||||
case 0x0c08: return "SERCOS";
|
||||
case 0x0c09: return "CANBUS";
|
||||
}
|
||||
return "SerialBus";
|
||||
case 0x0d:
|
||||
switch (class_id) {
|
||||
case 0x0d00: return "IRDA";
|
||||
case 0x0d01: return "ConsumerIR";
|
||||
case 0x0d10: return "RF";
|
||||
case 0x0d11: return "Bluetooth";
|
||||
case 0x0d12: return "Broadband";
|
||||
case 0x0d20: return "802.1a";
|
||||
case 0x0d21: return "802.1b";
|
||||
}
|
||||
return "Wireless";
|
||||
case 0x0e:
|
||||
switch (class_id) {
|
||||
case 0x0e00: return "I2O";
|
||||
}
|
||||
return "Intelligent";
|
||||
case 0x0f:
|
||||
return "Satellite";
|
||||
case 0x10:
|
||||
return "Encryption";
|
||||
case 0x11:
|
||||
return "SignalProcessing";
|
||||
case 0x12:
|
||||
return "ProcessingAccelerator";
|
||||
case 0x13:
|
||||
return "Instrumentation";
|
||||
case 0x40:
|
||||
return "Co-Processor";
|
||||
}
|
||||
return "Other";
|
||||
}
|
275
opal/mca/hwloc/hwloc2a/hwloc/hwloc/shmem.c
Обычный файл
275
opal/mca/hwloc/hwloc2a/hwloc/hwloc/shmem.c
Обычный файл
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright © 2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/shmem.h>
|
||||
#include <private/private.h>
|
||||
|
||||
#ifndef HWLOC_WIN_SYS
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define HWLOC_SHMEM_HEADER_VERSION 1
|
||||
|
||||
struct hwloc_shmem_header {
|
||||
uint32_t header_version; /* sanity check */
|
||||
uint32_t header_length; /* where the actual topology starts in the file/mapping */
|
||||
uint64_t mmap_address; /* virtual address to pass to mmap */
|
||||
uint64_t mmap_length; /* length to pass to mmap (includes the header) */
|
||||
};
|
||||
|
||||
#define HWLOC_SHMEM_MALLOC_ALIGN 8UL
|
||||
|
||||
static void *
|
||||
tma_shmem_malloc(struct hwloc_tma * tma,
|
||||
size_t length)
|
||||
{
|
||||
void *current = tma->data;
|
||||
tma->data = (char*)tma->data + ((length + HWLOC_SHMEM_MALLOC_ALIGN - 1) & ~(HWLOC_SHMEM_MALLOC_ALIGN - 1));
|
||||
return current;
|
||||
|
||||
}
|
||||
|
||||
static void *
|
||||
tma_get_length_malloc(struct hwloc_tma * tma,
|
||||
size_t length)
|
||||
{
|
||||
size_t *tma_length = tma->data;
|
||||
*tma_length += (length + HWLOC_SHMEM_MALLOC_ALIGN - 1) & ~(HWLOC_SHMEM_MALLOC_ALIGN - 1);
|
||||
return malloc(length);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_shmem_topology_get_length(hwloc_topology_t topology,
|
||||
size_t *lengthp,
|
||||
unsigned long flags)
|
||||
{
|
||||
hwloc_topology_t new;
|
||||
struct hwloc_tma tma;
|
||||
size_t length = 0;
|
||||
unsigned long pagesize = hwloc_getpagesize(); /* round-up to full page for mmap() */
|
||||
int err;
|
||||
|
||||
if (flags) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
tma.malloc = tma_get_length_malloc;
|
||||
tma.dontfree = 0;
|
||||
tma.data = &length;
|
||||
|
||||
err = hwloc__topology_dup(&new, topology, &tma);
|
||||
if (err < 0)
|
||||
return err;
|
||||
hwloc_topology_destroy(new);
|
||||
|
||||
*lengthp = (sizeof(struct hwloc_shmem_header) + length + pagesize - 1) & ~(pagesize - 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_shmem_topology_write(hwloc_topology_t topology,
|
||||
int fd, uint64_t fileoffset,
|
||||
void *mmap_address, size_t length,
|
||||
unsigned long flags)
|
||||
{
|
||||
hwloc_topology_t new;
|
||||
struct hwloc_tma tma;
|
||||
struct hwloc_shmem_header header;
|
||||
void *mmap_res;
|
||||
int err;
|
||||
|
||||
if (flags) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* refresh old topology distances so that we don't uselessly duplicate invalid distances
|
||||
* without being able to free() them.
|
||||
*/
|
||||
hwloc_internal_distances_refresh(topology);
|
||||
|
||||
header.header_version = HWLOC_SHMEM_HEADER_VERSION;
|
||||
header.header_length = sizeof(header);
|
||||
header.mmap_address = (uintptr_t) mmap_address;
|
||||
header.mmap_length = length;
|
||||
|
||||
err = lseek(fd, fileoffset, SEEK_SET);
|
||||
if (err < 0)
|
||||
return -1;
|
||||
|
||||
err = write(fd, &header, sizeof(header));
|
||||
if (err != sizeof(header))
|
||||
return -2;
|
||||
|
||||
err = ftruncate(fd, fileoffset + length);
|
||||
if (err < 0)
|
||||
return -3;
|
||||
|
||||
mmap_res = mmap(mmap_address, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, fileoffset);
|
||||
if (mmap_res == MAP_FAILED)
|
||||
return -4;
|
||||
if (mmap_res != mmap_address) {
|
||||
munmap(mmap_res, length);
|
||||
errno = EBUSY;
|
||||
return -5;
|
||||
}
|
||||
|
||||
tma.malloc = tma_shmem_malloc;
|
||||
tma.dontfree = 1;
|
||||
tma.data = (char *)mmap_res + sizeof(header);
|
||||
err = hwloc__topology_dup(&new, topology, &tma);
|
||||
if (err < 0)
|
||||
return err;
|
||||
assert((char*)new == (char*)mmap_address + sizeof(header));
|
||||
|
||||
assert((char *)mmap_res <= (char *)mmap_address + length);
|
||||
|
||||
/* now refresh the new distances so that adopters can use them without refreshing the R/O shmem mapping */
|
||||
hwloc_internal_distances_refresh(new);
|
||||
|
||||
/* topology is saved, release resources now */
|
||||
munmap(mmap_address, length);
|
||||
hwloc_components_fini();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_shmem_topology_adopt(hwloc_topology_t *topologyp,
|
||||
int fd, uint64_t fileoffset,
|
||||
void *mmap_address, size_t length,
|
||||
unsigned long flags)
|
||||
{
|
||||
hwloc_topology_t new, old;
|
||||
struct hwloc_shmem_header header;
|
||||
void *mmap_res;
|
||||
int err;
|
||||
|
||||
if (flags) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = lseek(fd, fileoffset, SEEK_SET);
|
||||
if (err < 0)
|
||||
return -1;
|
||||
|
||||
err = read(fd, &header, sizeof(header));
|
||||
if (err != sizeof(header))
|
||||
return -1;
|
||||
|
||||
if (header.header_version != HWLOC_SHMEM_HEADER_VERSION
|
||||
|| header.header_length != sizeof(header)
|
||||
|| header.mmap_address != (uintptr_t) mmap_address
|
||||
|| header.mmap_length != length) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmap_res = mmap(mmap_address, length, PROT_READ, MAP_SHARED, fd, fileoffset);
|
||||
if (mmap_res == MAP_FAILED)
|
||||
return -1;
|
||||
if (mmap_res != mmap_address) {
|
||||
munmap(mmap_res, length);
|
||||
errno = EBUSY;
|
||||
return -1;
|
||||
}
|
||||
|
||||
old = (hwloc_topology_t)((char*)mmap_address + sizeof(header));
|
||||
assert(old->is_loaded);
|
||||
assert(old->backends == NULL);
|
||||
assert(old->get_pci_busid_cpuset_backend == NULL);
|
||||
|
||||
hwloc_components_init();
|
||||
|
||||
/* duplicate the topology object so that we ca change use local binding_hooks
|
||||
* (those are likely not mapped at the same location in both processes).
|
||||
*/
|
||||
new = malloc(sizeof(struct hwloc_topology));
|
||||
if (!new)
|
||||
goto out_with_components;
|
||||
memcpy(new, old, sizeof(*old));
|
||||
new->tma = NULL;
|
||||
new->adopted_shmem_addr = mmap_address;
|
||||
new->adopted_shmem_length = length;
|
||||
/* setting binding hooks will touch support arrays, so duplicate them too.
|
||||
* could avoid that by requesting a R/W mmap
|
||||
*/
|
||||
new->support.discovery = malloc(sizeof(*new->support.discovery));
|
||||
new->support.cpubind = malloc(sizeof(*new->support.cpubind));
|
||||
new->support.membind = malloc(sizeof(*new->support.membind));
|
||||
memcpy(new->support.discovery, old->support.discovery, sizeof(*new->support.discovery));
|
||||
memcpy(new->support.cpubind, old->support.cpubind, sizeof(*new->support.cpubind));
|
||||
memcpy(new->support.membind, old->support.membind, sizeof(*new->support.membind));
|
||||
hwloc_set_binding_hooks(new);
|
||||
|
||||
#ifndef HWLOC_DEBUG
|
||||
if (getenv("HWLOC_DEBUG_CHECK"))
|
||||
#endif
|
||||
hwloc_topology_check(new);
|
||||
|
||||
*topologyp = new;
|
||||
return 0;
|
||||
|
||||
out_with_components:
|
||||
hwloc_components_fini();
|
||||
munmap(mmap_address, length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc__topology_disadopt(hwloc_topology_t topology)
|
||||
{
|
||||
hwloc_components_fini();
|
||||
munmap(topology->adopted_shmem_addr, topology->adopted_shmem_length);
|
||||
free(topology->support.discovery);
|
||||
free(topology->support.cpubind);
|
||||
free(topology->support.membind);
|
||||
free(topology);
|
||||
}
|
||||
|
||||
#else /* HWLOC_WIN_SYS */
|
||||
|
||||
int
|
||||
hwloc_shmem_topology_get_length(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
size_t *lengthp __hwloc_attribute_unused,
|
||||
unsigned long flags __hwloc_attribute_unused)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_shmem_topology_write(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
int fd __hwloc_attribute_unused, uint64_t fileoffset __hwloc_attribute_unused,
|
||||
void *mmap_address __hwloc_attribute_unused, size_t length __hwloc_attribute_unused,
|
||||
unsigned long flags __hwloc_attribute_unused)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_shmem_topology_adopt(hwloc_topology_t *topologyp __hwloc_attribute_unused,
|
||||
int fd __hwloc_attribute_unused, uint64_t fileoffset __hwloc_attribute_unused,
|
||||
void *mmap_address __hwloc_attribute_unused, size_t length __hwloc_attribute_unused,
|
||||
unsigned long flags __hwloc_attribute_unused)
|
||||
{
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
hwloc__topology_disadopt(hwloc_topology_t topology __hwloc_attribute_unused)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* HWLOC_WIN_SYS */
|
@ -405,10 +405,7 @@ hwloc_aix_get_sth_membind(hwloc_topology_t topology, rstype_t what, rsid_t who,
|
||||
int depth, n, i;
|
||||
|
||||
depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
if (depth < 0) {
|
||||
errno = EXDEV;
|
||||
return -1;
|
||||
}
|
||||
assert(depth >= 0);
|
||||
n = hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
|
||||
rset = rs_alloc(RS_EMPTY);
|
||||
@ -637,9 +634,8 @@ look_rset(int sdl, hwloc_obj_type_t type, struct hwloc_topology *topology, int l
|
||||
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(type, os_index);
|
||||
obj = hwloc_alloc_setup_object(topology, type, os_index);
|
||||
obj->cpuset = cpuset;
|
||||
obj->os_level = sdl;
|
||||
|
||||
switch(type) {
|
||||
case HWLOC_OBJ_NUMANODE:
|
||||
@ -655,7 +651,7 @@ look_rset(int sdl, hwloc_obj_type_t type, struct hwloc_topology *topology, int l
|
||||
#endif
|
||||
/* TODO: obj->memory.page_types[1].count = rs_getinfo(rset, R_LGPGFREE, 0) / hugepagesize */
|
||||
break;
|
||||
case HWLOC_OBJ_CACHE:
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
obj->attr->cache.size = _system_configuration.L2_cache_size;
|
||||
obj->attr->cache.associativity = _system_configuration.L2_cache_asc;
|
||||
|
||||
@ -668,12 +664,13 @@ look_rset(int sdl, hwloc_obj_type_t type, struct hwloc_topology *topology, int l
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED; /* OK for power[4567], unknown for others */
|
||||
break;
|
||||
case HWLOC_OBJ_GROUP:
|
||||
obj->attr->group.depth = level;
|
||||
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(HWLOC_OBJ_CACHE, i);
|
||||
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;
|
||||
@ -683,14 +680,13 @@ look_rset(int sdl, hwloc_obj_type_t type, struct hwloc_topology *topology, int l
|
||||
/* Unified cache */
|
||||
obj2->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
hwloc_debug("Adding an L1u cache for core %d\n", i);
|
||||
hwloc_insert_object_by_cpuset(topology, obj2);
|
||||
} 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);
|
||||
hwloc_insert_object_by_cpuset(topology, obj2);
|
||||
|
||||
obj3 = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, 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;
|
||||
@ -700,15 +696,23 @@ look_rset(int sdl, hwloc_obj_type_t type, struct hwloc_topology *topology, int l
|
||||
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_obj_type_string(type),
|
||||
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);
|
||||
@ -723,7 +727,7 @@ hwloc_look_aix(struct hwloc_backend *backend)
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
|
||||
@ -759,7 +763,7 @@ hwloc_look_aix(struct hwloc_backend *backend)
|
||||
if (i == rs_getinfo(NULL, R_L2CSDL, 0))
|
||||
{
|
||||
hwloc_debug("looking AIX L2 sdl %d\n", i);
|
||||
look_rset(i, HWLOC_OBJ_CACHE, topology, i);
|
||||
look_rset(i, HWLOC_OBJ_L2CACHE, topology, i);
|
||||
known = 1;
|
||||
}
|
||||
# endif
|
||||
@ -788,9 +792,8 @@ hwloc_look_aix(struct hwloc_backend *backend)
|
||||
}
|
||||
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "AIX");
|
||||
if (topology->is_thissystem)
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
@ -46,33 +46,35 @@ static int
|
||||
hwloc_look_bgq(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
unsigned i;
|
||||
|
||||
if (!topology->levels[0][0]->cpuset) {
|
||||
/* Nobody created objects yet, setup everything */
|
||||
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 */
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(set, 0);
|
||||
topology->levels[0][0]->nodeset = set;
|
||||
topology->levels[0][0]->memory.local_memory = 16ULL*1024*1024*1024ULL;
|
||||
|
||||
/* package */
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_PACKAGE, 0);
|
||||
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;
|
||||
hwloc_obj_add_info(obj, "CPUModel", "IBM PowerPC A2");
|
||||
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 */
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1);
|
||||
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;
|
||||
@ -80,17 +82,25 @@ hwloc_look_bgq(struct hwloc_backend *backend)
|
||||
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++) {
|
||||
/* Core */
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, i);
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(set, i*4, i*4+3);
|
||||
obj->cpuset = set;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
|
||||
/* L1d */
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1);
|
||||
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;
|
||||
@ -98,8 +108,10 @@ hwloc_look_bgq(struct hwloc_backend *backend)
|
||||
obj->attr->cache.linesize = 64;
|
||||
obj->attr->cache.associativity = 8;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
/* L1i */
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CACHE, -1);
|
||||
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;
|
||||
@ -107,19 +119,26 @@ hwloc_look_bgq(struct hwloc_backend *backend)
|
||||
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");
|
||||
if (topology->is_thissystem)
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2011 Université Bordeaux
|
||||
* Copyright © 2012-2014 Inria. All rights reserved.
|
||||
* Copyright © 2012-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@ -15,58 +15,9 @@
|
||||
|
||||
#include <cuda_runtime_api.h>
|
||||
|
||||
struct hwloc_cuda_backend_data_s {
|
||||
unsigned nr_devices; /* -1 when unknown yet, first callback will setup */
|
||||
struct hwloc_cuda_device_info_s {
|
||||
int idx;
|
||||
unsigned pcidomain, pcibus, pcidev, pcifunc;
|
||||
} * devices;
|
||||
};
|
||||
|
||||
/* query all PCI bus ids for later */
|
||||
static void
|
||||
hwloc_cuda_query_devices(struct hwloc_cuda_backend_data_s *data)
|
||||
{
|
||||
cudaError_t cures;
|
||||
int nb, i;
|
||||
|
||||
/* mark the number of devices as 0 in case we fail below,
|
||||
* so that we don't try again later.
|
||||
*/
|
||||
data->nr_devices = 0;
|
||||
|
||||
cures = cudaGetDeviceCount(&nb);
|
||||
if (cures)
|
||||
return;
|
||||
|
||||
/* allocate structs */
|
||||
data->devices = malloc(nb * sizeof(*data->devices));
|
||||
if (!data->devices)
|
||||
return;
|
||||
|
||||
for (i = 0; i < nb; i++) {
|
||||
struct hwloc_cuda_device_info_s *info = &data->devices[data->nr_devices];
|
||||
int domain, bus, dev;
|
||||
|
||||
if (hwloc_cudart_get_device_pci_ids(NULL /* topology unused */, i, &domain, &bus, &dev))
|
||||
continue;
|
||||
|
||||
info->idx = i;
|
||||
info->pcidomain = (unsigned) domain;
|
||||
info->pcibus = (unsigned) bus;
|
||||
info->pcidev = (unsigned) dev;
|
||||
info->pcifunc = 0;
|
||||
|
||||
/* validate this device */
|
||||
data->nr_devices++;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned hwloc_cuda_cores_per_MP(int major, int minor)
|
||||
{
|
||||
/* based on CUDA C Programming Guide, Annex G */
|
||||
/* FP32 cores per MP, based on CUDA C Programming Guide, Annex G */
|
||||
switch (major) {
|
||||
case 1:
|
||||
switch (minor) {
|
||||
@ -87,70 +38,54 @@ static unsigned hwloc_cuda_cores_per_MP(int major, int minor)
|
||||
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 %u.%u, disabling core display.\n", major, minor);
|
||||
hwloc_debug("unknown compute capability %d.%d, disabling core display.\n", major, minor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_cuda_backend_notify_new_object(struct hwloc_backend *backend, struct hwloc_backend *caller __hwloc_attribute_unused,
|
||||
struct hwloc_obj *pcidev)
|
||||
hwloc_cuda_discover(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
struct hwloc_cuda_backend_data_s *data = backend->private_data;
|
||||
unsigned i;
|
||||
enum hwloc_type_filter_e filter;
|
||||
cudaError_t cures;
|
||||
int nb, i;
|
||||
|
||||
if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO)))
|
||||
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_OS_DEVICE, &filter);
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
return 0;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
hwloc_debug("%s", "\nno CUDA detection (not thissystem)\n");
|
||||
return 0;
|
||||
}
|
||||
cures = cudaGetDeviceCount(&nb);
|
||||
if (cures)
|
||||
return -1;
|
||||
|
||||
if (HWLOC_OBJ_PCI_DEVICE != pcidev->type)
|
||||
return 0;
|
||||
|
||||
if (data->nr_devices == (unsigned) -1) {
|
||||
/* first call, lookup all devices */
|
||||
hwloc_cuda_query_devices(data);
|
||||
/* if it fails, data->nr_devices = 0 so we won't do anything below and in next callbacks */
|
||||
}
|
||||
|
||||
if (!data->nr_devices)
|
||||
/* found no devices */
|
||||
return 0;
|
||||
|
||||
for(i=0; i<data->nr_devices; i++) {
|
||||
struct hwloc_cuda_device_info_s *info = &data->devices[i];
|
||||
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;
|
||||
cudaError_t cures;
|
||||
hwloc_obj_t cuda_device, parent;
|
||||
unsigned cores;
|
||||
|
||||
if (info->pcidomain != pcidev->attr->pcidev.domain)
|
||||
continue;
|
||||
if (info->pcibus != pcidev->attr->pcidev.bus)
|
||||
continue;
|
||||
if (info->pcidev != pcidev->attr->pcidev.dev)
|
||||
continue;
|
||||
if (info->pcifunc != pcidev->attr->pcidev.func)
|
||||
continue;
|
||||
|
||||
cuda_device = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1);
|
||||
snprintf(cuda_name, sizeof(cuda_name), "cuda%d", info->idx);
|
||||
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;
|
||||
|
||||
hwloc_obj_add_info(cuda_device, "CoProcType", "CUDA");
|
||||
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, info->idx);
|
||||
cures = cudaGetDeviceProperties(&prop, i);
|
||||
if (!cures)
|
||||
hwloc_obj_add_info(cuda_device, "GPUModel", prop.name);
|
||||
|
||||
@ -172,21 +107,21 @@ hwloc_cuda_backend_notify_new_object(struct hwloc_backend *backend, struct hwloc
|
||||
snprintf(number, sizeof(number), "%llu", ((unsigned long long) prop.sharedMemPerBlock) >> 10);
|
||||
hwloc_obj_add_info(cuda_device, "CUDASharedMemorySizePerMP", number);
|
||||
|
||||
hwloc_insert_object_by_parent(topology, pcidev, cuda_device);
|
||||
return 1;
|
||||
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 void
|
||||
hwloc_cuda_backend_disable(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_cuda_backend_data_s *data = backend->private_data;
|
||||
free(data->devices);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_cuda_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
@ -194,27 +129,12 @@ hwloc_cuda_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
struct hwloc_cuda_backend_data_s *data;
|
||||
|
||||
/* thissystem may not be fully initialized yet, we'll check flags in discover() */
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (!data) {
|
||||
free(backend);
|
||||
return NULL;
|
||||
}
|
||||
/* the first callback will initialize those */
|
||||
data->nr_devices = (unsigned) -1; /* unknown yet */
|
||||
data->devices = NULL;
|
||||
|
||||
backend->private_data = data;
|
||||
backend->disable = hwloc_cuda_backend_disable;
|
||||
|
||||
backend->notify_new_object = hwloc_cuda_backend_notify_new_object;
|
||||
backend->discover = hwloc_cuda_discover;
|
||||
return backend;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ hwloc_look_darwin(struct hwloc_backend *backend)
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
|
||||
@ -72,10 +72,10 @@ hwloc_look_darwin(struct hwloc_backend *backend)
|
||||
|
||||
hwloc_debug("%u threads per package\n", logical_per_package);
|
||||
|
||||
|
||||
if (nprocs == npackages * 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(HWLOC_OBJ_PACKAGE, 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);
|
||||
@ -91,13 +91,14 @@ hwloc_look_darwin(struct hwloc_backend *backend)
|
||||
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) {
|
||||
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(HWLOC_OBJ_CORE, 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);
|
||||
@ -190,10 +191,12 @@ hwloc_look_darwin(struct hwloc_backend *backend)
|
||||
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++) {
|
||||
obj = hwloc_alloc_setup_object(i?HWLOC_OBJ_CACHE:HWLOC_OBJ_NUMANODE, 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];
|
||||
@ -201,10 +204,11 @@ hwloc_look_darwin(struct hwloc_backend *backend)
|
||||
cpu++)
|
||||
hwloc_bitmap_set(obj->cpuset, cpu);
|
||||
|
||||
if (i == 1 && l1icachesize) {
|
||||
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(HWLOC_OBJ_CACHE, j);
|
||||
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);
|
||||
@ -243,30 +247,26 @@ hwloc_look_darwin(struct hwloc_backend *backend)
|
||||
#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:
|
||||
if (NULL != cacheconfig) {
|
||||
free(cacheconfig);
|
||||
}
|
||||
if (NULL != cachesize) {
|
||||
free(cachesize);
|
||||
}
|
||||
if (NULL != cacheconfig32) {
|
||||
free(cacheconfig32);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* add PU objects */
|
||||
hwloc_setup_pu_level(topology, nprocs);
|
||||
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "Darwin");
|
||||
if (topology->is_thissystem)
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2014 Inria. All rights reserved.
|
||||
* 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.
|
||||
@ -173,6 +173,8 @@ hwloc_freebsd_node_meminfo_info(struct hwloc_topology *topology)
|
||||
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
|
||||
|
||||
@ -193,9 +195,8 @@ hwloc_look_freebsd(struct hwloc_backend *backend)
|
||||
hwloc_freebsd_node_meminfo_info(topology);
|
||||
#endif
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "FreeBSD");
|
||||
if (topology->is_thissystem)
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2012-2013 Blue Brain Project, BBP/EPFL. All rights reserved.
|
||||
* Copyright © 2012-2014 Inria. All rights reserved.
|
||||
* Copyright © 2012-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
@ -20,31 +20,24 @@
|
||||
|
||||
#define HWLOC_GL_SERVER_MAX 10
|
||||
#define HWLOC_GL_SCREEN_MAX 10
|
||||
struct hwloc_gl_backend_data_s {
|
||||
unsigned nr_display;
|
||||
struct hwloc_gl_display_info_s {
|
||||
char name[10];
|
||||
unsigned port, device;
|
||||
unsigned pcidomain, pcibus, pcidevice, pcifunc;
|
||||
char *productname;
|
||||
} display[HWLOC_GL_SERVER_MAX*HWLOC_GL_SCREEN_MAX];
|
||||
};
|
||||
|
||||
static void
|
||||
hwloc_gl_query_devices(struct hwloc_gl_backend_data_s *data)
|
||||
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;
|
||||
unsigned i,j;
|
||||
|
||||
/* mark the number of display as 0 in case we fail below,
|
||||
* so that we don't try again later.
|
||||
*/
|
||||
data->nr_display = 0;
|
||||
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);
|
||||
@ -59,7 +52,7 @@ hwloc_gl_query_devices(struct hwloc_gl_backend_data_s *data)
|
||||
}
|
||||
|
||||
for (j = 0; j < (unsigned) ScreenCount(display) && j < HWLOC_GL_SCREEN_MAX; j++) {
|
||||
struct hwloc_gl_display_info_s *info = &data->display[data->nr_display];
|
||||
hwloc_obj_t osdev, parent;
|
||||
const int screen = j;
|
||||
unsigned int *ptr_binary_data;
|
||||
int data_length;
|
||||
@ -69,6 +62,7 @@ hwloc_gl_query_devices(struct hwloc_gl_backend_data_s *data)
|
||||
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))
|
||||
@ -115,98 +109,33 @@ hwloc_gl_query_devices(struct hwloc_gl_backend_data_s *data)
|
||||
err = XNVCTRLQueryTargetStringAttribute(display, NV_CTRL_TARGET_TYPE_GPU, gpu_number, 0,
|
||||
NV_CTRL_STRING_PRODUCT_NAME, &productname);
|
||||
|
||||
snprintf(info->name, sizeof(info->name), ":%u.%u", i, j);
|
||||
info->port = i;
|
||||
info->device = j;
|
||||
info->pcidomain = nv_ctrl_pci_domain;
|
||||
info->pcibus = nv_ctrl_pci_bus;
|
||||
info->pcidevice = nv_ctrl_pci_device;
|
||||
info->pcifunc = nv_ctrl_pci_func;
|
||||
info->productname = productname;
|
||||
snprintf(name, sizeof(name), ":%u.%u", i, j);
|
||||
|
||||
hwloc_debug("GL device %s (product %s) on PCI 0000:%02x:%02x.%u\n", info->name, productname,
|
||||
nv_ctrl_pci_domain, nv_ctrl_pci_bus, nv_ctrl_pci_device, nv_ctrl_pci_func);
|
||||
|
||||
/* validate this device */
|
||||
data->nr_display++;
|
||||
}
|
||||
XCloseDisplay(display);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_gl_backend_notify_new_object(struct hwloc_backend *backend, struct hwloc_backend *caller __hwloc_attribute_unused,
|
||||
struct hwloc_obj *pcidev)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
struct hwloc_gl_backend_data_s *data = backend->private_data;
|
||||
unsigned i, res;
|
||||
|
||||
if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO)))
|
||||
return 0;
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
hwloc_debug("%s", "\nno GL detection (not thissystem)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (HWLOC_OBJ_PCI_DEVICE != pcidev->type)
|
||||
return 0;
|
||||
|
||||
if (data->nr_display == (unsigned) -1) {
|
||||
/* first call, lookup all display */
|
||||
hwloc_gl_query_devices(data);
|
||||
/* if it fails, data->nr_display = 0 so we won't do anything below and in next callbacks */
|
||||
}
|
||||
|
||||
if (!data->nr_display)
|
||||
/* found no display */
|
||||
return 0;
|
||||
|
||||
/* now the display array is ready to use */
|
||||
res = 0;
|
||||
for(i=0; i<data->nr_display; i++) {
|
||||
struct hwloc_gl_display_info_s *info = &data->display[i];
|
||||
hwloc_obj_t osdev;
|
||||
|
||||
if (info->pcidomain != pcidev->attr->pcidev.domain)
|
||||
continue;
|
||||
if (info->pcibus != pcidev->attr->pcidev.bus)
|
||||
continue;
|
||||
if (info->pcidevice != pcidev->attr->pcidev.dev)
|
||||
continue;
|
||||
if (info->pcifunc != pcidev->attr->pcidev.func)
|
||||
continue;
|
||||
|
||||
osdev = hwloc_alloc_setup_object(HWLOC_OBJ_OS_DEVICE, -1);
|
||||
osdev->name = strdup(info->name);
|
||||
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 (info->productname)
|
||||
hwloc_obj_add_info(osdev, "GPUModel", info->productname);
|
||||
hwloc_insert_object_by_parent(topology, pcidev, osdev);
|
||||
if (productname)
|
||||
hwloc_obj_add_info(osdev, "GPUModel", productname);
|
||||
|
||||
res++;
|
||||
/* there may be others */
|
||||
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 res;
|
||||
}
|
||||
|
||||
static void
|
||||
hwloc_gl_backend_disable(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_gl_backend_data_s *data = backend->private_data;
|
||||
unsigned i;
|
||||
if (data->nr_display != (unsigned) -1) { /* could be -1 if --no-io */
|
||||
for(i=0; i<data->nr_display; i++) {
|
||||
struct hwloc_gl_display_info_s *info = &data->display[i];
|
||||
free(info->productname);
|
||||
}
|
||||
}
|
||||
free(backend->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
@ -216,26 +145,11 @@ hwloc_gl_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
struct hwloc_gl_backend_data_s *data;
|
||||
|
||||
/* thissystem may not be fully initialized yet, we'll check flags in discover() */
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
|
||||
data = malloc(sizeof(*data));
|
||||
if (!data) {
|
||||
free(backend);
|
||||
return NULL;
|
||||
}
|
||||
/* the first callback will initialize those */
|
||||
data->nr_display = (unsigned) -1; /* unknown yet */
|
||||
|
||||
backend->private_data = data;
|
||||
backend->disable = hwloc_gl_backend_disable;
|
||||
|
||||
backend->notify_new_object = hwloc_gl_backend_notify_new_object;
|
||||
backend->discover = hwloc_gl_discover;
|
||||
return backend;
|
||||
}
|
||||
|
223
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-hardwired.c
Обычный файл
223
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-hardwired.c
Обычный файл
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright © 2015-2016 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
|
||||
int hwloc_look_hardwired_fujitsu_k(struct hwloc_topology *topology)
|
||||
{
|
||||
/* If a broken core gets disabled, its bit disappears and other core bits are NOT shifted towards 0.
|
||||
* Node is not given to user job, not need to handle that case properly.
|
||||
*/
|
||||
unsigned i;
|
||||
hwloc_obj_t obj;
|
||||
hwloc_bitmap_t set;
|
||||
|
||||
for(i=0; i<8; i++) {
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(set, i);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1ICACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1ICACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 32*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 2;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 32*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 2;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_CORE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_CORE, i);
|
||||
obj->cpuset = set;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
}
|
||||
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(set, 0, 7);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L2CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L2CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
obj->attr->cache.depth = 2;
|
||||
obj->attr->cache.size = 6*1024*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 12;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_PACKAGE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PACKAGE, 0);
|
||||
obj->cpuset = set;
|
||||
hwloc_obj_add_info(obj, "CPUVendor", "Fujitsu");
|
||||
hwloc_obj_add_info(obj, "CPUModel", "SPARC64 VIIIfx");
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
|
||||
hwloc_setup_pu_level(topology, 8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hwloc_look_hardwired_fujitsu_fx10(struct hwloc_topology *topology)
|
||||
{
|
||||
/* If a broken core gets disabled, its bit disappears and other core bits are NOT shifted towards 0.
|
||||
* Node is not given to user job, not need to handle that case properly.
|
||||
*/
|
||||
unsigned i;
|
||||
hwloc_obj_t obj;
|
||||
hwloc_bitmap_t set;
|
||||
|
||||
for(i=0; i<16; i++) {
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(set, i);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1ICACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1ICACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 32*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 2;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 32*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 2;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_CORE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_CORE, i);
|
||||
obj->cpuset = set;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
}
|
||||
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(set, 0, 15);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L2CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L2CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
obj->attr->cache.depth = 2;
|
||||
obj->attr->cache.size = 12*1024*1024;
|
||||
obj->attr->cache.linesize = 128;
|
||||
obj->attr->cache.associativity = 24;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_PACKAGE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PACKAGE, 0);
|
||||
obj->cpuset = set;
|
||||
hwloc_obj_add_info(obj, "CPUVendor", "Fujitsu");
|
||||
hwloc_obj_add_info(obj, "CPUModel", "SPARC64 IXfx");
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
|
||||
hwloc_setup_pu_level(topology, 16);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hwloc_look_hardwired_fujitsu_fx100(struct hwloc_topology *topology)
|
||||
{
|
||||
/* If a broken core gets disabled, its bit disappears and other core bits are NOT shifted towards 0.
|
||||
* Node is not given to user job, not need to handle that case properly.
|
||||
*/
|
||||
unsigned i;
|
||||
hwloc_obj_t obj;
|
||||
hwloc_bitmap_t set;
|
||||
|
||||
for(i=0; i<34; i++) {
|
||||
set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(set, i);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1ICACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1ICACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 64*1024;
|
||||
obj->attr->cache.linesize = 256;
|
||||
obj->attr->cache.associativity = 4;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L1CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L1CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_dup(set);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_DATA;
|
||||
obj->attr->cache.depth = 1;
|
||||
obj->attr->cache.size = 64*1024;
|
||||
obj->attr->cache.linesize = 256;
|
||||
obj->attr->cache.associativity = 4;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_CORE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_CORE, i);
|
||||
obj->cpuset = set;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
}
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_L2CACHE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L2CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(obj->cpuset, 0, 15);
|
||||
hwloc_bitmap_set(obj->cpuset, 32);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
obj->attr->cache.depth = 2;
|
||||
obj->attr->cache.size = 12*1024*1024;
|
||||
obj->attr->cache.linesize = 256;
|
||||
obj->attr->cache.associativity = 24;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_L2CACHE, -1);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(obj->cpuset, 16, 31);
|
||||
hwloc_bitmap_set(obj->cpuset, 33);
|
||||
obj->attr->cache.type = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
obj->attr->cache.depth = 2;
|
||||
obj->attr->cache.size = 12*1024*1024;
|
||||
obj->attr->cache.linesize = 256;
|
||||
obj->attr->cache.associativity = 24;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_PACKAGE)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PACKAGE, 0);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set_range(obj->cpuset, 0, 33);
|
||||
hwloc_obj_add_info(obj, "CPUVendor", "Fujitsu");
|
||||
hwloc_obj_add_info(obj, "CPUModel", "SPARC64 XIfx");
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
|
||||
hwloc_setup_pu_level(topology, 34);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2014 Inria. All rights reserved.
|
||||
* 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.
|
||||
@ -90,7 +90,7 @@ hwloc_hpux_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_co
|
||||
|
||||
cpu = hwloc_hpux_find_spu(topology, hwloc_set);
|
||||
if (cpu != -1)
|
||||
return mpctl(flags & HWLOC_CPUBIND_STRICT ? MPC_SETPROCESS_FORCE : MPC_SETPROCESS, cpu, pid);
|
||||
return mpctl((flags & HWLOC_CPUBIND_STRICT) ? MPC_SETPROCESS_FORCE : MPC_SETPROCESS, cpu, pid);
|
||||
|
||||
errno = EXDEV;
|
||||
return -1;
|
||||
@ -122,7 +122,7 @@ hwloc_hpux_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t 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);
|
||||
return pthread_processor_bind_np((flags & HWLOC_CPUBIND_STRICT) ? PTHREAD_BIND_FORCED_NP : PTHREAD_BIND_ADVISORY_NP, &cpu2, cpu, pthread);
|
||||
|
||||
errno = EXDEV;
|
||||
return -1;
|
||||
@ -183,12 +183,12 @@ hwloc_look_hpux(struct hwloc_backend *backend)
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
|
||||
if (has_numa) {
|
||||
nbnodes = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ?
|
||||
nbnodes = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
|
||||
MPC_GETNUMLDOMS_SYS : MPC_GETNUMLDOMS, 0, 0);
|
||||
|
||||
hwloc_debug("%d nodes\n", nbnodes);
|
||||
@ -196,28 +196,28 @@ hwloc_look_hpux(struct hwloc_backend *backend)
|
||||
nodes = malloc(nbnodes * sizeof(*nodes));
|
||||
|
||||
i = 0;
|
||||
currentnode = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ?
|
||||
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(HWLOC_OBJ_NUMANODE, 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 ?
|
||||
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 ?
|
||||
currentcpu = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
|
||||
MPC_GETFIRSTSPU_SYS : MPC_GETFIRSTSPU, 0,0);
|
||||
while (currentcpu != -1) {
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_PU, currentcpu);
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PU, currentcpu);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(obj->cpuset, currentcpu);
|
||||
|
||||
@ -242,7 +242,7 @@ hwloc_look_hpux(struct hwloc_backend *backend)
|
||||
/* Add cpu */
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
|
||||
currentcpu = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ?
|
||||
currentcpu = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
|
||||
MPC_GETNEXTSPU_SYS : MPC_GETNEXTSPU, currentcpu, 0);
|
||||
}
|
||||
|
||||
@ -256,9 +256,8 @@ hwloc_look_hpux(struct hwloc_backend *backend)
|
||||
topology->support.discovery->pu = 1;
|
||||
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "HP-UX");
|
||||
if (topology->is_thissystem)
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2012 Aleksej Saushev, The NetBSD Foundation
|
||||
* Copyright © 2009-2014 Inria. All rights reserved.
|
||||
* 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.
|
||||
@ -162,9 +162,8 @@ hwloc_look_netbsd(struct hwloc_backend *backend)
|
||||
hwloc_netbsd_node_meminfo_info(topology);
|
||||
#endif
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "NetBSD");
|
||||
if (topology->is_thissystem)
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2014 Inria. All rights reserved.
|
||||
* 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.
|
||||
@ -17,13 +17,12 @@ hwloc_look_noos(struct hwloc_backend *backend)
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
hwloc_setup_pu_level(topology, hwloc_fallback_nbprocessors(topology));
|
||||
if (topology->is_thissystem)
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
146
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-nvml.c
Обычный файл
146
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-nvml.c
Обычный файл
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright © 2012-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/plugins.h>
|
||||
|
||||
/* private headers allowed for convenience because this plugin is built within hwloc */
|
||||
#include <private/misc.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#include <nvml.h>
|
||||
|
||||
static int
|
||||
hwloc_nvml_discover(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
enum hwloc_type_filter_e filter;
|
||||
nvmlReturn_t ret;
|
||||
unsigned nb, i;
|
||||
|
||||
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_OS_DEVICE, &filter);
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
return 0;
|
||||
|
||||
ret = nvmlInit();
|
||||
if (NVML_SUCCESS != ret)
|
||||
return -1;
|
||||
ret = nvmlDeviceGetCount(&nb);
|
||||
if (NVML_SUCCESS != ret || !nb) {
|
||||
nvmlShutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(i=0; i<nb; i++) {
|
||||
nvmlPciInfo_t pci;
|
||||
nvmlDevice_t device;
|
||||
hwloc_obj_t osdev, parent;
|
||||
char buffer[64];
|
||||
|
||||
ret = nvmlDeviceGetHandleByIndex(i, &device);
|
||||
assert(ret == NVML_SUCCESS);
|
||||
|
||||
osdev = hwloc_alloc_setup_object(topology, HWLOC_OBJ_OS_DEVICE, -1);
|
||||
snprintf(buffer, sizeof(buffer), "nvml%u", i);
|
||||
osdev->name = strdup(buffer);
|
||||
osdev->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN;
|
||||
osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_GPU;
|
||||
|
||||
hwloc_obj_add_info(osdev, "Backend", "NVML");
|
||||
hwloc_obj_add_info(osdev, "GPUVendor", "NVIDIA Corporation");
|
||||
|
||||
buffer[0] = '\0';
|
||||
ret = nvmlDeviceGetName(device, buffer, sizeof(buffer));
|
||||
hwloc_obj_add_info(osdev, "GPUModel", buffer);
|
||||
|
||||
/* these may fail with NVML_ERROR_NOT_SUPPORTED on old devices */
|
||||
buffer[0] = '\0';
|
||||
ret = nvmlDeviceGetSerial(device, buffer, sizeof(buffer));
|
||||
if (buffer[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "NVIDIASerial", buffer);
|
||||
|
||||
buffer[0] = '\0';
|
||||
ret = nvmlDeviceGetUUID(device, buffer, sizeof(buffer));
|
||||
if (buffer[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "NVIDIAUUID", buffer);
|
||||
|
||||
parent = NULL;
|
||||
if (NVML_SUCCESS == nvmlDeviceGetPciInfo(device, &pci)) {
|
||||
parent = hwloc_pci_belowroot_find_by_busid(topology, pci.domain, pci.bus, pci.device, 0);
|
||||
if (!parent)
|
||||
parent = hwloc_pci_find_busid_parent(topology, pci.domain, pci.bus, pci.device, 0);
|
||||
#if HAVE_DECL_NVMLDEVICEGETMAXPCIELINKGENERATION
|
||||
if (parent && parent->type == HWLOC_OBJ_PCI_DEVICE) {
|
||||
unsigned maxwidth = 0, maxgen = 0;
|
||||
float lanespeed;
|
||||
nvmlDeviceGetMaxPcieLinkWidth(device, &maxwidth);
|
||||
nvmlDeviceGetMaxPcieLinkGeneration(device, &maxgen);
|
||||
/* PCIe Gen1 = 2.5GT/s signal-rate per lane with 8/10 encoding = 0.25GB/s data-rate per lane
|
||||
* PCIe Gen2 = 5 GT/s signal-rate per lane with 8/10 encoding = 0.5 GB/s data-rate per lane
|
||||
* PCIe Gen3 = 8 GT/s signal-rate per lane with 128/130 encoding = 1 GB/s data-rate per lane
|
||||
*/
|
||||
lanespeed = maxgen <= 2 ? 2.5 * maxgen * 0.8 : 8.0 * 128/130; /* Gbit/s per lane */
|
||||
if (lanespeed * maxwidth != 0.)
|
||||
/* we found the max link speed, replace the current link speed found by pci (or none) */
|
||||
parent->attr->pcidev.linkspeed = lanespeed * maxwidth / 8; /* GB/s */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (!parent)
|
||||
parent = hwloc_get_root_obj(topology);
|
||||
|
||||
hwloc_insert_object_by_parent(topology, parent, osdev);
|
||||
}
|
||||
|
||||
nvmlShutdown();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_nvml_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_nvml_discover;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_nvml_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_MISC,
|
||||
"nvml",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_nvml_component_instantiate,
|
||||
5, /* after pci, and after cuda since likely less useful */
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
hwloc_nvml_component_init(unsigned long flags)
|
||||
{
|
||||
if (flags)
|
||||
return -1;
|
||||
if (hwloc_plugin_check_namespace("nvml", "hwloc_backend_alloc") < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_nvml_component;
|
||||
#endif
|
||||
|
||||
const struct hwloc_component hwloc_nvml_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
hwloc_nvml_component_init, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_nvml_disc_component
|
||||
};
|
203
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-opencl.c
Обычный файл
203
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-opencl.c
Обычный файл
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* Copyright © 2012-2017 Inria. All rights reserved.
|
||||
* Copyright © 2013 Université Bordeaux. All right reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <hwloc/plugins.h>
|
||||
|
||||
/* private headers allowed for convenience because this plugin is built within hwloc */
|
||||
#include <private/misc.h>
|
||||
#include <private/debug.h>
|
||||
|
||||
#include <CL/cl_ext.h>
|
||||
|
||||
static int
|
||||
hwloc_opencl_discover(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
enum hwloc_type_filter_e filter;
|
||||
cl_platform_id *platform_ids = NULL;
|
||||
cl_uint nr_platforms;
|
||||
cl_int clret;
|
||||
unsigned j;
|
||||
|
||||
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_OS_DEVICE, &filter);
|
||||
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
|
||||
return 0;
|
||||
|
||||
clret = clGetPlatformIDs(0, NULL, &nr_platforms);
|
||||
if (CL_SUCCESS != clret || !nr_platforms)
|
||||
return -1;
|
||||
hwloc_debug("%u OpenCL platforms\n", nr_platforms);
|
||||
platform_ids = malloc(nr_platforms * sizeof(*platform_ids));
|
||||
if (!platform_ids)
|
||||
return -1;
|
||||
clret = clGetPlatformIDs(nr_platforms, platform_ids, &nr_platforms);
|
||||
if (CL_SUCCESS != clret || !nr_platforms) {
|
||||
free(platform_ids);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(j=0; j<nr_platforms; j++) {
|
||||
cl_device_id *device_ids = NULL;
|
||||
cl_uint nr_devices;
|
||||
unsigned i;
|
||||
|
||||
clret = clGetDeviceIDs(platform_ids[j], CL_DEVICE_TYPE_ALL, 0, NULL, &nr_devices);
|
||||
if (CL_SUCCESS != clret)
|
||||
continue;
|
||||
device_ids = malloc(nr_devices * sizeof(*device_ids));
|
||||
clret = clGetDeviceIDs(platform_ids[j], CL_DEVICE_TYPE_ALL, nr_devices, device_ids, &nr_devices);
|
||||
if (CL_SUCCESS != clret) {
|
||||
free(device_ids);
|
||||
continue;
|
||||
}
|
||||
|
||||
for(i=0; i<nr_devices; i++) {
|
||||
cl_platform_id platform_id = 0;
|
||||
cl_device_type type;
|
||||
#ifdef CL_DEVICE_TOPOLOGY_AMD
|
||||
cl_device_topology_amd amdtopo;
|
||||
#endif
|
||||
cl_ulong globalmemsize;
|
||||
cl_uint computeunits;
|
||||
hwloc_obj_t osdev, parent;
|
||||
char buffer[64];
|
||||
|
||||
hwloc_debug("This is opencl%ud%u\n", j, i);
|
||||
|
||||
#ifdef CL_DEVICE_TOPOLOGY_AMD
|
||||
clret = clGetDeviceInfo(device_ids[i], CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
|
||||
if (CL_SUCCESS != clret) {
|
||||
hwloc_debug("no AMD-specific device information: %d\n", clret);
|
||||
continue;
|
||||
} else if (CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD != amdtopo.raw.type) {
|
||||
hwloc_debug("AMD-specific device topology reports non-PCIe device type: %u\n", amdtopo.raw.type);
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
continue;
|
||||
#endif
|
||||
|
||||
osdev = hwloc_alloc_setup_object(topology, HWLOC_OBJ_OS_DEVICE, -1);
|
||||
snprintf(buffer, sizeof(buffer), "opencl%ud%u", j, i);
|
||||
osdev->name = strdup(buffer);
|
||||
osdev->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN;
|
||||
osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_COPROC;
|
||||
|
||||
osdev->subtype = strdup("OpenCL");
|
||||
hwloc_obj_add_info(osdev, "Backend", "OpenCL");
|
||||
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL);
|
||||
if (type == CL_DEVICE_TYPE_GPU)
|
||||
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "GPU");
|
||||
else if (type == CL_DEVICE_TYPE_ACCELERATOR)
|
||||
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "Accelerator");
|
||||
else if (type == CL_DEVICE_TYPE_CPU)
|
||||
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "CPU");
|
||||
else if (type == CL_DEVICE_TYPE_CUSTOM)
|
||||
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "Custom");
|
||||
else
|
||||
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "Unknown");
|
||||
|
||||
buffer[0] = '\0';
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL);
|
||||
if (buffer[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "GPUVendor", buffer);
|
||||
|
||||
buffer[0] = '\0';
|
||||
#ifdef CL_DEVICE_BOARD_NAME_AMD
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_BOARD_NAME_AMD, sizeof(buffer), buffer, NULL);
|
||||
#else
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_NAME, sizeof(buffer), buffer, NULL);
|
||||
#endif
|
||||
if (buffer[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "GPUModel", buffer);
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%u", j);
|
||||
hwloc_obj_add_info(osdev, "OpenCLPlatformIndex", buffer);
|
||||
|
||||
buffer[0] = '\0';
|
||||
clret = clGetDeviceInfo(device_ids[i], CL_DEVICE_PLATFORM, sizeof(platform_id), &platform_id, NULL);
|
||||
if (CL_SUCCESS == clret) {
|
||||
clGetPlatformInfo(platform_id, CL_PLATFORM_NAME, sizeof(buffer), buffer, NULL);
|
||||
if (buffer[0] != '\0')
|
||||
hwloc_obj_add_info(osdev, "OpenCLPlatformName", buffer);
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%u", i);
|
||||
hwloc_obj_add_info(osdev, "OpenCLPlatformDeviceIndex", buffer);
|
||||
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(computeunits), &computeunits, NULL);
|
||||
snprintf(buffer, sizeof(buffer), "%u", computeunits);
|
||||
hwloc_obj_add_info(osdev, "OpenCLComputeUnits", buffer);
|
||||
|
||||
clGetDeviceInfo(device_ids[i], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(globalmemsize), &globalmemsize, NULL);
|
||||
snprintf(buffer, sizeof(buffer), "%llu", (unsigned long long) globalmemsize / 1024);
|
||||
hwloc_obj_add_info(osdev, "OpenCLGlobalMemorySize", buffer);
|
||||
|
||||
parent = NULL;
|
||||
#ifdef CL_DEVICE_TOPOLOGY_AMD
|
||||
parent = hwloc_pci_belowroot_find_by_busid(topology, 0, amdtopo.pcie.bus, amdtopo.pcie.device, amdtopo.pcie.function);
|
||||
if (!parent)
|
||||
parent = hwloc_pci_find_busid_parent(topology, 0, amdtopo.pcie.bus, amdtopo.pcie.device, amdtopo.pcie.function);
|
||||
#endif
|
||||
if (!parent)
|
||||
parent = hwloc_get_root_obj(topology);
|
||||
|
||||
hwloc_insert_object_by_parent(topology, parent, osdev);
|
||||
}
|
||||
free(device_ids);
|
||||
}
|
||||
free(platform_ids);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
hwloc_opencl_component_instantiate(struct hwloc_disc_component *component,
|
||||
const void *_data1 __hwloc_attribute_unused,
|
||||
const void *_data2 __hwloc_attribute_unused,
|
||||
const void *_data3 __hwloc_attribute_unused)
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->discover = hwloc_opencl_discover;
|
||||
return backend;
|
||||
}
|
||||
|
||||
static struct hwloc_disc_component hwloc_opencl_disc_component = {
|
||||
HWLOC_DISC_COMPONENT_TYPE_MISC,
|
||||
"opencl",
|
||||
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
|
||||
hwloc_opencl_component_instantiate,
|
||||
10, /* after pci */
|
||||
NULL
|
||||
};
|
||||
|
||||
static int
|
||||
hwloc_opencl_component_init(unsigned long flags)
|
||||
{
|
||||
if (flags)
|
||||
return -1;
|
||||
if (hwloc_plugin_check_namespace("opencl", "hwloc_backend_alloc") < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HWLOC_INSIDE_PLUGIN
|
||||
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_opencl_component;
|
||||
#endif
|
||||
|
||||
const struct hwloc_component hwloc_opencl_component = {
|
||||
HWLOC_COMPONENT_ABI,
|
||||
hwloc_opencl_component_init, NULL,
|
||||
HWLOC_COMPONENT_TYPE_DISC,
|
||||
0,
|
||||
&hwloc_opencl_disc_component
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* 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
|
||||
@ -78,25 +78,29 @@ static int
|
||||
hwloc_look_pci(struct hwloc_backend *backend)
|
||||
{
|
||||
struct hwloc_topology *topology = backend->topology;
|
||||
struct hwloc_obj *first_obj = NULL, *last_obj = NULL;
|
||||
enum hwloc_type_filter_e pfilter, bfilter;
|
||||
struct hwloc_obj *tree = NULL, *tmp;
|
||||
int ret;
|
||||
struct pci_device_iterator *iter;
|
||||
struct pci_device *pcidev;
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
DIR *dir;
|
||||
#endif
|
||||
|
||||
if (!(hwloc_topology_get_flags(topology) & (HWLOC_TOPOLOGY_FLAG_IO_DEVICES|HWLOC_TOPOLOGY_FLAG_WHOLE_IO)))
|
||||
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;
|
||||
|
||||
if (hwloc_get_next_pcidev(topology, NULL)) {
|
||||
hwloc_debug("%s", "PCI objects already added, ignoring pci backend.\n");
|
||||
/* 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;
|
||||
}
|
||||
|
||||
if (!hwloc_topology_is_thissystem(topology)) {
|
||||
hwloc_debug("%s", "\nno PCI detection (not thissystem)\n");
|
||||
return 0;
|
||||
tmp = tmp->next_sibling;
|
||||
}
|
||||
|
||||
hwloc_debug("%s", "\nScanning PCI buses...\n");
|
||||
@ -115,14 +119,13 @@ hwloc_look_pci(struct hwloc_backend *backend)
|
||||
pcidev;
|
||||
pcidev = pci_device_next(iter))
|
||||
{
|
||||
const char *vendorname, *devicename, *fullname;
|
||||
const char *vendorname, *devicename;
|
||||
unsigned char config_space_cache[CONFIG_SPACE_CACHESIZE];
|
||||
hwloc_obj_type_t type;
|
||||
struct hwloc_obj *obj;
|
||||
unsigned os_index;
|
||||
unsigned domain;
|
||||
unsigned device_class;
|
||||
unsigned short tmp16;
|
||||
char name[128];
|
||||
unsigned offset;
|
||||
|
||||
/* initialize the config space in case we fail to read it (missing permissions, etc). */
|
||||
@ -136,6 +139,26 @@ hwloc_look_pci(struct hwloc_backend *backend)
|
||||
/* 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.
|
||||
@ -143,7 +166,7 @@ hwloc_look_pci(struct hwloc_backend *backend)
|
||||
* 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 the kernel.
|
||||
* 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,
|
||||
@ -188,10 +211,7 @@ hwloc_look_pci(struct hwloc_backend *backend)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* might be useful for debugging (note that domain might be truncated) */
|
||||
os_index = (domain << 20) + (pcidev->bus << 12) + (pcidev->dev << 4) + pcidev->func;
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_PCI_DEVICE, os_index);
|
||||
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;
|
||||
@ -207,8 +227,10 @@ hwloc_look_pci(struct hwloc_backend *backend)
|
||||
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 (hwloc_pci_prepare_bridge(obj, config_space_cache) < 0)
|
||||
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));
|
||||
@ -232,63 +254,21 @@ hwloc_look_pci(struct hwloc_backend *backend)
|
||||
if (devicename && *devicename)
|
||||
hwloc_obj_add_info(obj, "PCIDevice", devicename);
|
||||
|
||||
/* generate or get the fullname */
|
||||
snprintf(name, sizeof(name), "%s%s%s",
|
||||
vendorname ? vendorname : "",
|
||||
vendorname && devicename ? " " : "",
|
||||
devicename ? devicename : "");
|
||||
fullname = name;
|
||||
if (*name)
|
||||
obj->name = strdup(name);
|
||||
hwloc_debug(" %04x:%02x:%02x.%01x %04x %04x:%04x %s\n",
|
||||
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,
|
||||
fullname && *fullname ? fullname : "??");
|
||||
vendorname && *vendorname ? vendorname : "??",
|
||||
devicename && *devicename ? devicename : "??");
|
||||
|
||||
/* queue the object for now */
|
||||
if (first_obj)
|
||||
last_obj->next_sibling = obj;
|
||||
else
|
||||
first_obj = obj;
|
||||
last_obj = obj;
|
||||
hwloc_pci_tree_insert_by_busid(&tree, obj);
|
||||
}
|
||||
|
||||
/* finalize device scanning */
|
||||
pci_iterator_destroy(iter);
|
||||
pci_system_cleanup();
|
||||
|
||||
#ifdef HWLOC_LINUX_SYS
|
||||
dir = opendir("/sys/bus/pci/slots/");
|
||||
if (dir) {
|
||||
struct dirent *dirent;
|
||||
while ((dirent = readdir(dir)) != NULL) {
|
||||
char path[64];
|
||||
FILE *file;
|
||||
if (dirent->d_name[0] == '.')
|
||||
continue;
|
||||
snprintf(path, sizeof(path), "/sys/bus/pci/slots/%s/address", dirent->d_name);
|
||||
file = fopen(path, "r");
|
||||
if (file) {
|
||||
unsigned domain, bus, dev;
|
||||
if (fscanf(file, "%x:%x:%x", &domain, &bus, &dev) == 3) {
|
||||
hwloc_obj_t obj = first_obj;
|
||||
while (obj) {
|
||||
if (obj->attr->pcidev.domain == domain
|
||||
&& obj->attr->pcidev.bus == bus
|
||||
&& obj->attr->pcidev.dev == dev) {
|
||||
hwloc_obj_add_info(obj, "PCISlot", dirent->d_name);
|
||||
}
|
||||
obj = obj->next_sibling;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
return hwloc_insert_pci_device_list(backend, first_obj);
|
||||
hwloc_pci_tree_attach_belowroot(topology, tree);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct hwloc_backend *
|
||||
@ -299,17 +279,14 @@ hwloc_pci_component_instantiate(struct hwloc_disc_component *component,
|
||||
{
|
||||
struct hwloc_backend *backend;
|
||||
|
||||
/* thissystem may not be fully initialized yet, we'll check flags in discover() */
|
||||
#ifdef HWLOC_SOLARIS_SYS
|
||||
if ((uid_t)0 != geteuid())
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
return NULL;
|
||||
backend->flags = HWLOC_BACKEND_FLAG_NEED_LEVELS;
|
||||
#ifdef HWLOC_SOLARIS_SYS
|
||||
if ((uid_t)0 != geteuid())
|
||||
backend->discover = NULL;
|
||||
else
|
||||
#endif
|
||||
backend->discover = hwloc_look_pci;
|
||||
return backend;
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
* Copyright © 2013 Université Bordeaux. All rights reserved.
|
||||
* Copyright © 2016 Inria. All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2017 Intel, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* 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.
|
||||
@ -50,16 +50,14 @@ hwloc_solaris_set_sth_cpubind(hwloc_topology_t topology, idtype_t idtype, id_t i
|
||||
#ifdef HAVE_LIBLGRP
|
||||
if (!(flags & HWLOC_CPUBIND_NOMEMBIND)) {
|
||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
if (depth >= 0) {
|
||||
int n = hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
int i;
|
||||
|
||||
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;
|
||||
}
|
||||
@ -67,12 +65,10 @@ hwloc_solaris_set_sth_cpubind(hwloc_topology_t topology, idtype_t idtype, id_t i
|
||||
#ifdef HAVE_LIBLGRP
|
||||
if (!(flags & HWLOC_CPUBIND_NOMEMBIND)) {
|
||||
int depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
if (depth >= 0) {
|
||||
int n = hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
int i;
|
||||
int ok;
|
||||
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))
|
||||
@ -101,7 +97,6 @@ hwloc_solaris_set_sth_cpubind(hwloc_topology_t topology, idtype_t idtype, id_t i
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_LIBLGRP */
|
||||
|
||||
if (hwloc_bitmap_weight(hwloc_set) != 1) {
|
||||
@ -145,10 +140,7 @@ hwloc_solaris_get_sth_cpubind(hwloc_topology_t topology, idtype_t idtype, id_t i
|
||||
int n;
|
||||
int i;
|
||||
|
||||
if (depth < 0) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
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 ) {
|
||||
@ -215,10 +207,7 @@ hwloc_solaris_set_sth_membind(hwloc_topology_t topology, idtype_t idtype, id_t i
|
||||
}
|
||||
|
||||
depth = hwloc_get_type_depth(topology, HWLOC_OBJ_NUMANODE);
|
||||
if (depth < 0) {
|
||||
errno = EXDEV;
|
||||
return -1;
|
||||
}
|
||||
assert(depth >= 0);
|
||||
n = hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
@ -261,10 +250,7 @@ hwloc_solaris_get_sth_membind(hwloc_topology_t topology, idtype_t idtype, id_t i
|
||||
int n;
|
||||
int i;
|
||||
|
||||
if (depth < 0) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
assert(depth >= 0);
|
||||
|
||||
hwloc_bitmap_zero(nodeset);
|
||||
n = hwloc_get_nbobjs_by_depth(topology, depth);
|
||||
@ -361,7 +347,7 @@ browse(struct hwloc_topology *topology, lgrp_cookie_t cookie, lgrp_id_t lgrp, hw
|
||||
cpuids = malloc(sizeof(processorid_t) * n);
|
||||
assert(cpuids != NULL);
|
||||
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_NUMANODE, lgrp);
|
||||
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();
|
||||
@ -431,15 +417,15 @@ hwloc_look_lgrp(struct hwloc_topology *topology)
|
||||
browse(topology, cookie, root, glob_lgrps, &curlgrp);
|
||||
#if HAVE_DECL_LGRP_LATENCY_COOKIE
|
||||
if (nlgrps > 1) {
|
||||
float *distances = calloc(curlgrp*curlgrp, sizeof(float));
|
||||
unsigned *indexes = calloc(curlgrp,sizeof(unsigned));
|
||||
uint64_t *distances = calloc(curlgrp*curlgrp, sizeof(uint64_t));
|
||||
unsigned i, j;
|
||||
for (i = 0; i < curlgrp; i++) {
|
||||
indexes[i] = glob_lgrps[i]->os_index;
|
||||
for (j = 0; j < curlgrp; j++)
|
||||
distances[i*curlgrp+j] = (float) lgrp_latency_cookie(cookie, glob_lgrps[i]->os_index, glob_lgrps[j]->os_index, LGRP_LAT_CPU_TO_MEM);
|
||||
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_distances_set(topology, HWLOC_OBJ_NUMANODE, curlgrp, indexes, glob_lgrps, distances, 0 /* OS cannot force */);
|
||||
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);
|
||||
@ -519,6 +505,24 @@ hwloc_look_kstat(struct hwloc_topology *topology)
|
||||
}
|
||||
|
||||
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));
|
||||
@ -548,19 +552,6 @@ hwloc_look_kstat(struct hwloc_topology *topology)
|
||||
if (cpuid >= Pproc_max)
|
||||
Pproc_max = cpuid + 1;
|
||||
|
||||
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 */
|
||||
hwloc_bitmap_clr(topology->levels[0][0]->online_cpuset, cpuid);
|
||||
}
|
||||
|
||||
if (look_chips) do {
|
||||
/* Get Chip ID */
|
||||
stat = (kstat_named_t *) kstat_data_lookup(ksp, "chip_id");
|
||||
@ -666,12 +657,13 @@ hwloc_look_kstat(struct hwloc_topology *topology)
|
||||
* however. */
|
||||
}
|
||||
|
||||
if (look_chips) {
|
||||
if (look_chips
|
||||
&& hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_PACKAGE)) {
|
||||
struct hwloc_obj *obj;
|
||||
unsigned j,k;
|
||||
hwloc_debug("%d Packages\n", Lpkg_num);
|
||||
hwloc_debug("%u Packages\n", Lpkg_num);
|
||||
for (j = 0; j < Lpkg_num; j++) {
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_PACKAGE, Lpkg[j].Ppkg);
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PACKAGE, Lpkg[j].Ppkg);
|
||||
if (CPUType)
|
||||
hwloc_obj_add_info(obj, "CPUType", CPUType);
|
||||
if (CPUModel)
|
||||
@ -680,38 +672,40 @@ hwloc_look_kstat(struct hwloc_topology *topology)
|
||||
for(k=0; k<Pproc_max; k++)
|
||||
if (Pproc[k].Lpkg == j)
|
||||
hwloc_bitmap_set(obj->cpuset, k);
|
||||
hwloc_debug_1arg_bitmap("Package %d has cpuset %s\n", j, obj->cpuset);
|
||||
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) {
|
||||
if (look_cores
|
||||
&& hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_CORE)) {
|
||||
struct hwloc_obj *obj;
|
||||
unsigned j,k;
|
||||
hwloc_debug("%d Cores\n", Lcore_num);
|
||||
hwloc_debug("%u Cores\n", Lcore_num);
|
||||
for (j = 0; j < Lcore_num; j++) {
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_CORE, Lcore[j].Pcore);
|
||||
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 %d has cpuset %s\n", j, obj->cpuset);
|
||||
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("%d PUs\n", Lproc_num);
|
||||
hwloc_debug("%u PUs\n", Lproc_num);
|
||||
for (j = 0; j < Lproc_num; j++) {
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_PU, Lproc[j].Pproc);
|
||||
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 %d has cpuset %s\n", j, obj->cpuset);
|
||||
hwloc_debug_1arg_bitmap("PU %u has cpuset %s\n", j, obj->cpuset);
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
}
|
||||
hwloc_debug("%s", "\n");
|
||||
@ -745,7 +739,7 @@ hwloc_look_solaris(struct hwloc_backend *backend)
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
|
||||
@ -760,9 +754,8 @@ hwloc_look_solaris(struct hwloc_backend *backend)
|
||||
hwloc_setup_pu_level(topology, nbprocs);
|
||||
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "Solaris");
|
||||
if (topology->is_thissystem)
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2015 Inria. All rights reserved.
|
||||
* 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.
|
||||
@ -168,15 +168,14 @@ hwloc_synthetic_process_level_indexes(struct hwloc_synthetic_backend_data_s *dat
|
||||
} else {
|
||||
/* interleaving as type1:type2:... */
|
||||
hwloc_obj_type_t type;
|
||||
hwloc_obj_cache_type_t cachetypeattr;
|
||||
int depthattr;
|
||||
union hwloc_obj_attr_u attrs;
|
||||
int err;
|
||||
|
||||
/* find level depths for each interleaving loop */
|
||||
tmp = attr;
|
||||
cur_loop = 0;
|
||||
while (tmp) {
|
||||
err = hwloc_obj_type_sscanf(tmp, &type, &depthattr, &cachetypeattr, sizeof(cachetypeattr));
|
||||
err = hwloc_type_sscanf(tmp, &type, &attrs, sizeof(attrs));
|
||||
if (err < 0) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Failed to read synthetic index interleaving loop type '%s'\n", tmp);
|
||||
@ -190,13 +189,9 @@ hwloc_synthetic_process_level_indexes(struct hwloc_synthetic_backend_data_s *dat
|
||||
for(i=0; i<curleveldepth; i++) {
|
||||
if (type != data->level[i].type)
|
||||
continue;
|
||||
if ((type == HWLOC_OBJ_GROUP || type == HWLOC_OBJ_CACHE)
|
||||
&& depthattr != -1
|
||||
&& (unsigned) depthattr != data->level[i].depth)
|
||||
continue;
|
||||
if (type == HWLOC_OBJ_CACHE
|
||||
&& cachetypeattr != (hwloc_obj_cache_type_t) -1
|
||||
&& cachetypeattr != data->level[i].cachetype)
|
||||
if (type == HWLOC_OBJ_GROUP
|
||||
&& attrs.group.depth != (unsigned) -1
|
||||
&& attrs.group.depth != data->level[i].depth)
|
||||
continue;
|
||||
loops[cur_loop].level_depth = (unsigned)i;
|
||||
break;
|
||||
@ -204,7 +199,7 @@ hwloc_synthetic_process_level_indexes(struct hwloc_synthetic_backend_data_s *dat
|
||||
if (i == curleveldepth) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Failed to find level for synthetic index interleaving loop type '%s' above '%s'\n",
|
||||
tmp, hwloc_obj_type_string(curlevel->type));
|
||||
tmp, hwloc_type_name(curlevel->type));
|
||||
goto out_with_loops;
|
||||
}
|
||||
tmp = strchr(tmp, ':');
|
||||
@ -337,10 +332,12 @@ hwloc_synthetic_parse_level_attrs(const char *attrs, const char **next_posp,
|
||||
}
|
||||
|
||||
while (')' != *attrs) {
|
||||
if (HWLOC_OBJ_CACHE == type && !strncmp("size=", attrs, 5)) {
|
||||
int iscache = hwloc_obj_type_is_cache(type);
|
||||
|
||||
if (iscache && !strncmp("size=", attrs, 5)) {
|
||||
memorysize = hwloc_synthetic_parse_memory_attr(attrs+5, &attrs);
|
||||
|
||||
} else if (HWLOC_OBJ_CACHE != type && !strncmp("memory=", attrs, 7)) {
|
||||
} else if (!iscache && !strncmp("memory=", attrs, 7)) {
|
||||
memorysize = hwloc_synthetic_parse_memory_attr(attrs+7, &attrs);
|
||||
|
||||
} else if (!strncmp("indexes=", attrs, 8)) {
|
||||
@ -383,9 +380,8 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
const char *pos, *next_pos;
|
||||
unsigned long item, count;
|
||||
unsigned i;
|
||||
int cache_depth = 0, group_depth = 0;
|
||||
int nb_machine_levels = 0, nb_node_levels = 0;
|
||||
int nb_pu_levels = 0;
|
||||
int type_count[HWLOC_OBJ_TYPE_MAX];
|
||||
unsigned unset;
|
||||
int verbose = 0;
|
||||
const char *env = getenv("HWLOC_SYNTHETIC_VERBOSE");
|
||||
int err;
|
||||
@ -407,10 +403,8 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
}
|
||||
|
||||
for (pos = description, count = 1; *pos; pos = next_pos) {
|
||||
#define HWLOC_OBJ_TYPE_UNKNOWN ((hwloc_obj_type_t) -1)
|
||||
hwloc_obj_type_t type = HWLOC_OBJ_TYPE_UNKNOWN;
|
||||
int typedepth = -1;
|
||||
hwloc_obj_cache_type_t cachetype = (hwloc_obj_cache_type_t) -1;
|
||||
hwloc_obj_type_t type = HWLOC_OBJ_TYPE_NONE;
|
||||
union hwloc_obj_attr_u attrs;
|
||||
|
||||
/* initialize parent arity to 0 so that the levels are not infinite */
|
||||
data->level[count-1].arity = 0;
|
||||
@ -422,7 +416,8 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
break;
|
||||
|
||||
if (*pos < '0' || *pos > '9') {
|
||||
if (hwloc_obj_type_sscanf(pos, &type, &typedepth, &cachetype, sizeof(cachetype)) < 0) {
|
||||
if (hwloc_type_sscanf(pos, &type, &attrs, sizeof(attrs)) < 0) {
|
||||
/* FIXME: allow generic "Cache" string? would require to deal with possibly duplicate cache levels */
|
||||
if (verbose)
|
||||
fprintf(stderr, "Synthetic string with unknown object type at '%s'\n", pos);
|
||||
errno = EINVAL;
|
||||
@ -445,8 +440,16 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
pos = next_pos + 1;
|
||||
}
|
||||
data->level[count].type = type;
|
||||
data->level[count].depth = (unsigned) typedepth;
|
||||
data->level[count].cachetype = cachetype;
|
||||
data->level[count].depth = (unsigned) -1;
|
||||
data->level[count].cachetype = (hwloc_obj_cache_type_t) -1;
|
||||
if (hwloc_obj_type_is_cache(type)) {
|
||||
/* these are always initialized */
|
||||
data->level[count].depth = attrs.cache.depth;
|
||||
data->level[count].cachetype = attrs.cache.type;
|
||||
} else if (type == HWLOC_OBJ_GROUP) {
|
||||
/* could be -1 but will be set below */
|
||||
data->level[count].depth = attrs.group.depth;
|
||||
}
|
||||
|
||||
item = strtoul(pos, (char **)&next_pos, 0);
|
||||
if (next_pos == pos) {
|
||||
@ -497,99 +500,165 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
goto error;
|
||||
}
|
||||
|
||||
for(i=count-1; i>0; i--) {
|
||||
struct hwloc_synthetic_level_data_s *curlevel = &data->level[i];
|
||||
hwloc_obj_type_t type;
|
||||
|
||||
type = curlevel->type;
|
||||
|
||||
if (i == count-1 && type != HWLOC_OBJ_TYPE_UNKNOWN && type != HWLOC_OBJ_PU) {
|
||||
if (data->level[count-1].type != HWLOC_OBJ_TYPE_NONE && data->level[count-1].type != HWLOC_OBJ_PU) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Synthetic string cannot use non-PU type for last level\n");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (i != count-1 && type == HWLOC_OBJ_PU) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Synthetic string cannot use PU type for non-last level\n");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
data->level[count-1].type = HWLOC_OBJ_PU;
|
||||
|
||||
if (type == HWLOC_OBJ_TYPE_UNKNOWN) {
|
||||
if (i == count-1)
|
||||
type = HWLOC_OBJ_PU;
|
||||
else {
|
||||
switch (data->level[i+1].type) {
|
||||
case HWLOC_OBJ_PU: type = HWLOC_OBJ_CORE; break;
|
||||
case HWLOC_OBJ_CORE: type = HWLOC_OBJ_CACHE; break;
|
||||
case HWLOC_OBJ_CACHE: type = HWLOC_OBJ_PACKAGE; break;
|
||||
case HWLOC_OBJ_PACKAGE: type = HWLOC_OBJ_NUMANODE; break;
|
||||
case HWLOC_OBJ_NUMANODE:
|
||||
case HWLOC_OBJ_MACHINE:
|
||||
case HWLOC_OBJ_GROUP: type = HWLOC_OBJ_GROUP; break;
|
||||
default:
|
||||
assert(0);
|
||||
for(i=0; i<HWLOC_OBJ_TYPE_MAX; i++) {
|
||||
type_count[i] = 0;
|
||||
}
|
||||
}
|
||||
curlevel->type = type;
|
||||
}
|
||||
switch (type) {
|
||||
case HWLOC_OBJ_PU:
|
||||
nb_pu_levels++;
|
||||
break;
|
||||
case HWLOC_OBJ_CACHE:
|
||||
cache_depth++;
|
||||
break;
|
||||
case HWLOC_OBJ_GROUP:
|
||||
group_depth++;
|
||||
break;
|
||||
case HWLOC_OBJ_NUMANODE:
|
||||
nb_node_levels++;
|
||||
break;
|
||||
case HWLOC_OBJ_MACHINE:
|
||||
nb_machine_levels++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
for(i=count-1; i>0; i--) {
|
||||
hwloc_obj_type_t type = data->level[i].type;
|
||||
if (type != HWLOC_OBJ_TYPE_NONE) {
|
||||
type_count[type]++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nb_pu_levels) {
|
||||
/* sanity checks */
|
||||
if (!type_count[HWLOC_OBJ_PU]) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Synthetic string missing ending number of PUs\n");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (nb_pu_levels > 1) {
|
||||
} else if (type_count[HWLOC_OBJ_PU] > 1) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Synthetic string can not have several PU levels\n");
|
||||
fprintf(stderr, "Synthetic string cannot have several PU levels\n");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (nb_node_levels > 1) {
|
||||
if (type_count[HWLOC_OBJ_PACKAGE] > 1) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Synthetic string can not have several NUMA node levels\n");
|
||||
fprintf(stderr, "Synthetic string cannot have several package levels\n");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (nb_machine_levels > 1) {
|
||||
if (type_count[HWLOC_OBJ_NUMANODE] > 1) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Synthetic string can not have several machine levels\n");
|
||||
fprintf(stderr, "Synthetic string cannot have several NUMA node levels\n");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (type_count[HWLOC_OBJ_CORE] > 1) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Synthetic string cannot have several core levels\n");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (type_count[HWLOC_OBJ_MACHINE] > 1) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Synthetic string cannot have several machine levels\n");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nb_machine_levels)
|
||||
/* initialize the top level (not specified in the string) */
|
||||
if (type_count[HWLOC_OBJ_MACHINE] == 1) {
|
||||
data->level[0].type = HWLOC_OBJ_SYSTEM;
|
||||
else {
|
||||
type_count[HWLOC_OBJ_SYSTEM] = 1;
|
||||
} else {
|
||||
data->level[0].type = HWLOC_OBJ_MACHINE;
|
||||
nb_machine_levels++;
|
||||
type_count[HWLOC_OBJ_MACHINE] = 1;
|
||||
}
|
||||
|
||||
if (cache_depth == 1)
|
||||
/* if there is a single cache level, make it L2 */
|
||||
cache_depth = 2;
|
||||
/* deal with missing intermediate levels */
|
||||
unset = 0;
|
||||
for(i=1; i<count-1; i++) {
|
||||
if (data->level[i].type == HWLOC_OBJ_TYPE_NONE)
|
||||
unset++;
|
||||
}
|
||||
if (unset && unset != count-2) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Synthetic string cannot mix unspecified and specified types for levels\n");
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (unset) {
|
||||
/* we want in priority: numa, package, core, up to 3 caches, groups */
|
||||
unsigned neednuma = count >= 3;
|
||||
unsigned needpack = count >= 4;
|
||||
unsigned needcore = count >= 5;
|
||||
unsigned needcaches = count <= 5 ? 0 : count >= 9 ? 4 : count-5;
|
||||
unsigned needgroups = count-2-neednuma-needpack-needcore-needcaches;
|
||||
/* we place them in order: groups, package, numa, caches, core */
|
||||
for(i = 0; i < needgroups; i++) {
|
||||
unsigned depth = 1 + i;
|
||||
data->level[depth].type = HWLOC_OBJ_GROUP;
|
||||
type_count[HWLOC_OBJ_GROUP]++;
|
||||
}
|
||||
if (needpack) {
|
||||
unsigned depth = 1 + needgroups;
|
||||
data->level[depth].type = HWLOC_OBJ_PACKAGE;
|
||||
type_count[HWLOC_OBJ_PACKAGE] = 1;
|
||||
}
|
||||
if (neednuma) {
|
||||
unsigned depth = 1 + needgroups + needpack;
|
||||
data->level[depth].type = HWLOC_OBJ_NUMANODE;
|
||||
type_count[HWLOC_OBJ_NUMANODE] = 1;
|
||||
}
|
||||
if (needcaches) {
|
||||
/* priority: l2, l1, l3, l1i */
|
||||
/* order: l3, l2, l1, l1i */
|
||||
unsigned l3depth = 1 + needgroups + needpack + neednuma;
|
||||
unsigned l2depth = l3depth + (needcaches >= 3);
|
||||
unsigned l1depth = l2depth + 1;
|
||||
unsigned l1idepth = l1depth + 1;
|
||||
if (needcaches >= 3) {
|
||||
data->level[l3depth].type = HWLOC_OBJ_L3CACHE;
|
||||
data->level[l3depth].depth = 3;
|
||||
data->level[l3depth].cachetype = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
type_count[HWLOC_OBJ_L3CACHE] = 1;
|
||||
}
|
||||
data->level[l2depth].type = HWLOC_OBJ_L2CACHE;
|
||||
data->level[l2depth].depth = 2;
|
||||
data->level[l2depth].cachetype = HWLOC_OBJ_CACHE_UNIFIED;
|
||||
type_count[HWLOC_OBJ_L2CACHE] = 1;
|
||||
if (needcaches >= 2) {
|
||||
data->level[l1depth].type = HWLOC_OBJ_L1CACHE;
|
||||
data->level[l1depth].depth = 1;
|
||||
data->level[l1depth].cachetype = HWLOC_OBJ_CACHE_DATA;
|
||||
type_count[HWLOC_OBJ_L1CACHE] = 1;
|
||||
}
|
||||
if (needcaches >= 4) {
|
||||
data->level[l1idepth].type = HWLOC_OBJ_L1ICACHE;
|
||||
data->level[l1idepth].depth = 1;
|
||||
data->level[l1idepth].cachetype = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
type_count[HWLOC_OBJ_L1ICACHE] = 1;
|
||||
}
|
||||
}
|
||||
if (needcore) {
|
||||
unsigned depth = 1 + needgroups + needpack + neednuma + needcaches;
|
||||
data->level[depth].type = HWLOC_OBJ_CORE;
|
||||
type_count[HWLOC_OBJ_CORE] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* enforce a NUMA level */
|
||||
if (!type_count[HWLOC_OBJ_NUMANODE]) {
|
||||
/* insert a NUMA level and the machine level */
|
||||
if (data->level[1].type == HWLOC_OBJ_MACHINE)
|
||||
/* there's an explicit machine level after the automatic system root, insert below both */
|
||||
i = 2;
|
||||
else
|
||||
/* insert below the automatic machine root */
|
||||
i = 1;
|
||||
if (verbose)
|
||||
fprintf(stderr, "Inserting a NUMA level with a single object at depth %u\n", i);
|
||||
/* move existing levels by one */
|
||||
memmove(&data->level[i+1], &data->level[i], (count*i)*sizeof(struct hwloc_synthetic_level_data_s));
|
||||
data->level[i].type = HWLOC_OBJ_NUMANODE;
|
||||
data->level[i].index_string = NULL;
|
||||
data->level[i].index_array = NULL;
|
||||
data->level[i].memorysize = 0;
|
||||
data->level[i].totalwidth = data->level[i-1].totalwidth;
|
||||
/* update arity to insert a single NUMA node per parent */
|
||||
data->level[i].arity = data->level[i-1].arity;
|
||||
data->level[i-1].arity = 1;
|
||||
count++;
|
||||
}
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
struct hwloc_synthetic_level_data_s *curlevel = &data->level[i];
|
||||
@ -597,13 +666,9 @@ hwloc_backend_synthetic_init(struct hwloc_synthetic_backend_data_s *data,
|
||||
|
||||
if (type == HWLOC_OBJ_GROUP) {
|
||||
if (curlevel->depth == (unsigned)-1)
|
||||
curlevel->depth = group_depth--;
|
||||
curlevel->depth = type_count[HWLOC_OBJ_GROUP]--;
|
||||
|
||||
} else if (type == HWLOC_OBJ_CACHE) {
|
||||
if (curlevel->depth == (unsigned)-1)
|
||||
curlevel->depth = cache_depth--;
|
||||
if (curlevel->cachetype == (hwloc_obj_cache_type_t) -1)
|
||||
curlevel->cachetype = curlevel->depth == 1 ? HWLOC_OBJ_CACHE_DATA : HWLOC_OBJ_CACHE_UNIFIED;
|
||||
} else if (hwloc_obj_type_is_cache(type)) {
|
||||
if (!curlevel->memorysize) {
|
||||
if (1 == curlevel->depth)
|
||||
/* 32Kb in L1 */
|
||||
@ -641,7 +706,8 @@ hwloc_synthetic__post_look_hooks(struct hwloc_synthetic_level_data_s *curlevel,
|
||||
{
|
||||
switch (obj->type) {
|
||||
case HWLOC_OBJ_GROUP:
|
||||
obj->attr->group.depth = curlevel->depth;
|
||||
obj->attr->group.kind = HWLOC_GROUP_KIND_SYNTHETIC;
|
||||
obj->attr->group.subkind = curlevel->depth-1;
|
||||
break;
|
||||
case HWLOC_OBJ_SYSTEM:
|
||||
break;
|
||||
@ -651,7 +717,14 @@ hwloc_synthetic__post_look_hooks(struct hwloc_synthetic_level_data_s *curlevel,
|
||||
break;
|
||||
case HWLOC_OBJ_PACKAGE:
|
||||
break;
|
||||
case HWLOC_OBJ_CACHE:
|
||||
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:
|
||||
obj->attr->cache.depth = curlevel->depth;
|
||||
obj->attr->cache.linesize = 64;
|
||||
obj->attr->cache.type = curlevel->cachetype;
|
||||
@ -670,7 +743,7 @@ hwloc_synthetic__post_look_hooks(struct hwloc_synthetic_level_data_s *curlevel,
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
if (curlevel->memorysize && HWLOC_OBJ_CACHE != obj->type) {
|
||||
if (curlevel->memorysize && !hwloc_obj_type_is_cache(obj->type)) {
|
||||
obj->memory.local_memory = curlevel->memorysize;
|
||||
obj->memory.page_types_len = 1;
|
||||
obj->memory.page_types = malloc(sizeof(*obj->memory.page_types));
|
||||
@ -698,6 +771,7 @@ hwloc__look_synthetic(struct hwloc_topology *topology,
|
||||
unsigned i;
|
||||
struct hwloc_synthetic_level_data_s *curlevel = &data->level[level];
|
||||
hwloc_obj_type_t type = curlevel->type;
|
||||
hwloc_bitmap_t set;
|
||||
unsigned os_index;
|
||||
|
||||
/* pre-hooks */
|
||||
@ -710,7 +784,14 @@ hwloc__look_synthetic(struct hwloc_topology *topology,
|
||||
break;
|
||||
case HWLOC_OBJ_PACKAGE:
|
||||
break;
|
||||
case HWLOC_OBJ_CACHE:
|
||||
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:
|
||||
break;
|
||||
case HWLOC_OBJ_CORE:
|
||||
break;
|
||||
@ -730,26 +811,34 @@ hwloc__look_synthetic(struct hwloc_topology *topology,
|
||||
os_index = curlevel->next_os_index++;
|
||||
if (curlevel->index_array)
|
||||
os_index = curlevel->index_array[os_index];
|
||||
obj = hwloc_alloc_setup_object(type, os_index);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
else if (hwloc_obj_type_is_cache(type) || type == HWLOC_OBJ_GROUP)
|
||||
/* don't enforce useless os_indexes for Caches and Groups */
|
||||
os_index = -1;
|
||||
|
||||
set = hwloc_bitmap_alloc();
|
||||
if (!curlevel->arity) {
|
||||
hwloc_bitmap_set(obj->cpuset, os_index);
|
||||
hwloc_bitmap_set(set, os_index);
|
||||
} else {
|
||||
for (i = 0; i < curlevel->arity; i++)
|
||||
hwloc__look_synthetic(topology, data, level + 1, obj->cpuset);
|
||||
hwloc__look_synthetic(topology, data, level + 1, set);
|
||||
}
|
||||
|
||||
hwloc_bitmap_or(parent_cpuset, parent_cpuset, set);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, type)) {
|
||||
obj = hwloc_alloc_setup_object(topology, type, os_index);
|
||||
obj->cpuset = set;
|
||||
|
||||
if (type == HWLOC_OBJ_NUMANODE) {
|
||||
obj->nodeset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_set(obj->nodeset, os_index);
|
||||
}
|
||||
|
||||
hwloc_bitmap_or(parent_cpuset, parent_cpuset, obj->cpuset);
|
||||
|
||||
hwloc_synthetic__post_look_hooks(curlevel, obj);
|
||||
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -783,7 +872,7 @@ hwloc_look_synthetic(struct hwloc_backend *backend)
|
||||
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "Synthetic");
|
||||
hwloc_obj_add_info(topology->levels[0][0], "SyntheticDescription", data->string);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -812,9 +901,15 @@ hwloc_synthetic_component_instantiate(struct hwloc_disc_component *component,
|
||||
int err;
|
||||
|
||||
if (!_data1) {
|
||||
const char *env = getenv("HWLOC_SYNTHETIC");
|
||||
if (env) {
|
||||
/* 'synthetic' was given in HWLOC_COMPONENTS without a description */
|
||||
_data1 = env;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
backend = hwloc_backend_alloc(component);
|
||||
if (!backend)
|
||||
@ -933,13 +1028,10 @@ static int hwloc_topology_export_synthetic_indexes(struct hwloc_topology * topol
|
||||
tmplen -= res;
|
||||
}
|
||||
|
||||
if (loops)
|
||||
free(loops);
|
||||
|
||||
return ret;
|
||||
|
||||
exportall:
|
||||
if (loops)
|
||||
free(loops);
|
||||
|
||||
/* dump all indexes */
|
||||
@ -969,7 +1061,7 @@ static int hwloc_topology_export_synthetic_obj_attr(struct hwloc_topology * topo
|
||||
char memsize[64] = "";
|
||||
int needindexes = 0;
|
||||
|
||||
if (HWLOC_OBJ_CACHE == obj->type && obj->attr->cache.size) {
|
||||
if (hwloc_obj_type_is_cache(obj->type) && obj->attr->cache.size) {
|
||||
snprintf(cachesize, sizeof(cachesize), "%ssize=%llu",
|
||||
prefix, (unsigned long long) obj->attr->cache.size);
|
||||
prefix = separator;
|
||||
@ -1037,10 +1129,15 @@ hwloc_topology_export_synthetic(struct hwloc_topology * topology,
|
||||
ssize_t tmplen = buflen;
|
||||
char *tmp = buffer;
|
||||
int res, ret = 0;
|
||||
int arity;
|
||||
unsigned arity;
|
||||
const char * separator = " ";
|
||||
const char * prefix = "";
|
||||
|
||||
if (!topology->is_loaded) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & ~(HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES|HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
@ -1083,7 +1180,7 @@ hwloc_topology_export_synthetic(struct hwloc_topology * topology,
|
||||
/* for each level */
|
||||
obj = obj->first_child;
|
||||
if (flags & HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES) {
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%s:%u", prefix, hwloc_obj_type_string(obj->type), arity);
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%s:%u", prefix, hwloc_type_name(obj->type), arity);
|
||||
} else {
|
||||
char types[64];
|
||||
hwloc_obj_type_snprintf(types, sizeof(types), obj, 1);
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
@ -427,8 +427,6 @@ hwloc_win_set_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: SetThreadGroupAffinity to get affinity */
|
||||
|
||||
static int
|
||||
hwloc_win_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
|
||||
{
|
||||
@ -449,7 +447,8 @@ hwloc_win_set_thisthread_membind(hwloc_topology_t topology, hwloc_const_nodeset_
|
||||
|
||||
cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_cpuset_from_nodeset(topology, cpuset, nodeset);
|
||||
ret = hwloc_win_set_thisthread_cpubind(topology, cpuset, flags & HWLOC_MEMBIND_STRICT?HWLOC_CPUBIND_STRICT:0);
|
||||
ret = hwloc_win_set_thisthread_cpubind(topology, cpuset,
|
||||
(flags & HWLOC_MEMBIND_STRICT) ? HWLOC_CPUBIND_STRICT : 0);
|
||||
hwloc_bitmap_free(cpuset);
|
||||
return ret;
|
||||
}
|
||||
@ -459,7 +458,7 @@ hwloc_win_set_thisthread_membind(hwloc_topology_t topology, hwloc_const_nodeset_
|
||||
* get cpu/membind for threads
|
||||
*/
|
||||
|
||||
static int
|
||||
static int
|
||||
hwloc_win_get_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t thread, hwloc_cpuset_t set, int flags __hwloc_attribute_unused)
|
||||
{
|
||||
GROUP_AFFINITY aff;
|
||||
@ -546,7 +545,8 @@ hwloc_win_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_con
|
||||
|
||||
cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_cpuset_from_nodeset(topology, cpuset, nodeset);
|
||||
ret = hwloc_win_set_proc_cpubind(topology, pid, cpuset, flags & HWLOC_MEMBIND_STRICT?HWLOC_CPUBIND_STRICT:0);
|
||||
ret = hwloc_win_set_proc_cpubind(topology, pid, cpuset,
|
||||
(flags & HWLOC_MEMBIND_STRICT) ? HWLOC_CPUBIND_STRICT : 0);
|
||||
hwloc_bitmap_free(cpuset);
|
||||
return ret;
|
||||
}
|
||||
@ -595,7 +595,8 @@ hwloc_win_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nod
|
||||
{
|
||||
int ret;
|
||||
hwloc_cpuset_t cpuset = hwloc_bitmap_alloc();
|
||||
ret = hwloc_win_get_proc_cpubind(topology, pid, cpuset, flags & HWLOC_MEMBIND_STRICT?HWLOC_CPUBIND_STRICT:0);
|
||||
ret = hwloc_win_get_proc_cpubind(topology, pid, cpuset,
|
||||
(flags & HWLOC_MEMBIND_STRICT) ? HWLOC_CPUBIND_STRICT : 0);
|
||||
if (!ret) {
|
||||
*policy = HWLOC_MEMBIND_BIND;
|
||||
hwloc_cpuset_to_nodeset(topology, cpuset, nodeset);
|
||||
@ -734,7 +735,7 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
|
||||
if (topology->levels[0][0]->cpuset)
|
||||
/* somebody discovered things */
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
hwloc_alloc_obj_cpusets(topology->levels[0][0]);
|
||||
|
||||
@ -784,7 +785,7 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
type = HWLOC_OBJ_PACKAGE;
|
||||
break;
|
||||
case RelationCache:
|
||||
type = HWLOC_OBJ_CACHE;
|
||||
type = (procInfo[i].Cache.Type == CacheInstruction ? HWLOC_OBJ_L1ICACHE : HWLOC_OBJ_L1CACHE) + procInfo[i].Cache.Level - 1;
|
||||
break;
|
||||
case RelationProcessorCore:
|
||||
type = HWLOC_OBJ_CORE;
|
||||
@ -795,12 +796,15 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
break;
|
||||
}
|
||||
|
||||
obj = hwloc_alloc_setup_object(type, id);
|
||||
if (!hwloc_filter_check_keep_object_type(topology, type))
|
||||
continue;
|
||||
|
||||
obj = hwloc_alloc_setup_object(topology, type, id);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_debug("%s#%u mask %lx\n", hwloc_obj_type_string(type), id, procInfo[i].ProcessorMask);
|
||||
hwloc_debug("%s#%u mask %lx\n", hwloc_type_name(type), id, procInfo[i].ProcessorMask);
|
||||
/* ProcessorMask is a ULONG_PTR */
|
||||
hwloc_bitmap_set_ith_ULONG_PTR(obj->cpuset, 0, procInfo[i].ProcessorMask);
|
||||
hwloc_debug_2args_bitmap("%s#%u bitmap %s\n", hwloc_obj_type_string(type), id, obj->cpuset);
|
||||
hwloc_debug_2args_bitmap("%s#%u bitmap %s\n", hwloc_type_name(type), id, obj->cpuset);
|
||||
|
||||
switch (type) {
|
||||
case HWLOC_OBJ_NUMANODE:
|
||||
@ -822,7 +826,14 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case HWLOC_OBJ_CACHE:
|
||||
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:
|
||||
obj->attr->cache.size = procInfo[i].Cache.Size;
|
||||
obj->attr->cache.associativity = procInfo[i].Cache.Associativity == CACHE_FULLY_ASSOCIATIVE ? -1 : procInfo[i].Cache.Associativity ;
|
||||
obj->attr->cache.linesize = procInfo[i].Cache.LineSize;
|
||||
@ -843,7 +854,7 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
}
|
||||
break;
|
||||
case HWLOC_OBJ_GROUP:
|
||||
obj->attr->group.depth = procInfo[i].Relationship == RelationGroup;
|
||||
obj->attr->group.kind = procInfo[i].Relationship == RelationGroup ? HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP : HWLOC_GROUP_KIND_WINDOWS_RELATIONSHIP_UNKNOWN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -903,7 +914,7 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
GroupMask = procInfo->Processor.GroupMask;
|
||||
break;
|
||||
case RelationCache:
|
||||
type = HWLOC_OBJ_CACHE;
|
||||
type = (procInfo->Cache.Type == CacheInstruction ? HWLOC_OBJ_L1ICACHE : HWLOC_OBJ_L1CACHE) + procInfo->Cache.Level - 1;
|
||||
num = 1;
|
||||
GroupMask = &procInfo->Cache.GroupMask;
|
||||
break;
|
||||
@ -916,21 +927,32 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
/* So strange an interface... */
|
||||
for (id = 0; id < procInfo->Group.ActiveGroupCount; id++) {
|
||||
KAFFINITY mask;
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_GROUP, id);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_t set;
|
||||
|
||||
set = hwloc_bitmap_alloc();
|
||||
mask = procInfo->Group.GroupInfo[id].ActiveProcessorMask;
|
||||
hwloc_debug("group %u %d cpus mask %lx\n", id,
|
||||
procInfo->Group.GroupInfo[id].ActiveProcessorCount, mask);
|
||||
/* KAFFINITY is ULONG_PTR */
|
||||
hwloc_bitmap_set_ith_ULONG_PTR(obj->cpuset, id, mask);
|
||||
hwloc_debug_2args_bitmap("group %u %d bitmap %s\n", id, procInfo->Group.GroupInfo[id].ActiveProcessorCount, obj->cpuset);
|
||||
hwloc_bitmap_set_ith_ULONG_PTR(set, id, mask);
|
||||
/* FIXME: what if running 32bits on a 64bits windows with 64-processor groups?
|
||||
* ULONG_PTR is 32bits, so half the group is invisible?
|
||||
* maybe scale id to id*8/sizeof(ULONG_PTR) so that groups are 64-PU aligned?
|
||||
*/
|
||||
hwloc_debug_2args_bitmap("group %u %d bitmap %s\n", id, procInfo->Group.GroupInfo[id].ActiveProcessorCount, set);
|
||||
|
||||
/* save the set of PUs so that we can create them at the end */
|
||||
if (!groups_pu_set)
|
||||
groups_pu_set = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_or(groups_pu_set, groups_pu_set, obj->cpuset);
|
||||
hwloc_bitmap_or(groups_pu_set, groups_pu_set, set);
|
||||
|
||||
if (hwloc_filter_check_keep_object_type(topology, HWLOC_OBJ_GROUP)) {
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_GROUP, id);
|
||||
obj->cpuset = set;
|
||||
obj->attr->group.kind = HWLOC_GROUP_KIND_WINDOWS_PROCESSOR_GROUP;
|
||||
hwloc_insert_object_by_cpuset(topology, obj);
|
||||
} else
|
||||
hwloc_bitmap_free(set);
|
||||
}
|
||||
continue;
|
||||
default:
|
||||
@ -939,15 +961,18 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
continue;
|
||||
}
|
||||
|
||||
obj = hwloc_alloc_setup_object(type, id);
|
||||
if (!hwloc_filter_check_keep_object_type(topology, type))
|
||||
continue;
|
||||
|
||||
obj = hwloc_alloc_setup_object(topology, type, id);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
for (i = 0; i < num; i++) {
|
||||
hwloc_debug("%s#%u %d: mask %d:%lx\n", hwloc_obj_type_string(type), id, i, GroupMask[i].Group, GroupMask[i].Mask);
|
||||
hwloc_debug("%s#%u %d: mask %d:%lx\n", hwloc_type_name(type), id, i, GroupMask[i].Group, GroupMask[i].Mask);
|
||||
/* GROUP_AFFINITY.Mask is KAFFINITY, which is ULONG_PTR */
|
||||
hwloc_bitmap_set_ith_ULONG_PTR(obj->cpuset, GroupMask[i].Group, GroupMask[i].Mask);
|
||||
/* FIXME: scale id to id*8/sizeof(ULONG_PTR) as above? */
|
||||
}
|
||||
hwloc_debug_2args_bitmap("%s#%u bitmap %s\n", hwloc_obj_type_string(type), id, obj->cpuset);
|
||||
|
||||
hwloc_debug_2args_bitmap("%s#%u bitmap %s\n", hwloc_type_name(type), id, obj->cpuset);
|
||||
switch (type) {
|
||||
case HWLOC_OBJ_NUMANODE:
|
||||
{
|
||||
@ -967,7 +992,14 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case HWLOC_OBJ_CACHE:
|
||||
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:
|
||||
obj->attr->cache.size = procInfo->Cache.CacheSize;
|
||||
obj->attr->cache.associativity = procInfo->Cache.Associativity == CACHE_FULLY_ASSOCIATIVE ? -1 : procInfo->Cache.Associativity ;
|
||||
obj->attr->cache.linesize = procInfo->Cache.LineSize;
|
||||
@ -1002,7 +1034,7 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
hwloc_obj_t obj;
|
||||
unsigned idx;
|
||||
hwloc_bitmap_foreach_begin(idx, groups_pu_set) {
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_PU, idx);
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PU, idx);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_only(obj->cpuset, idx);
|
||||
hwloc_debug_1arg_bitmap("cpu %u has cpuset %s\n",
|
||||
@ -1018,7 +1050,7 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
GetSystemInfo(&sysinfo);
|
||||
for(idx=0; idx<32; idx++)
|
||||
if (sysinfo.dwActiveProcessorMask & (((DWORD_PTR)1)<<idx)) {
|
||||
obj = hwloc_alloc_setup_object(HWLOC_OBJ_PU, idx);
|
||||
obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PU, idx);
|
||||
obj->cpuset = hwloc_bitmap_alloc();
|
||||
hwloc_bitmap_only(obj->cpuset, idx);
|
||||
hwloc_debug_1arg_bitmap("cpu %u has cpuset %s\n",
|
||||
@ -1029,9 +1061,8 @@ hwloc_look_windows(struct hwloc_backend *backend)
|
||||
|
||||
out:
|
||||
hwloc_obj_add_info(topology->levels[0][0], "Backend", "Windows");
|
||||
if (topology->is_thissystem)
|
||||
hwloc_add_uname_info(topology, NULL);
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
1437
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-x86.c
Обычный файл
1437
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-x86.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@ -24,13 +24,28 @@
|
||||
|
||||
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_disable_stderrwarnings(void)
|
||||
hwloc_libxml2_init_once(void)
|
||||
{
|
||||
static int first = 1;
|
||||
if (first) {
|
||||
static int checked = 0;
|
||||
if (!checked) {
|
||||
/* disable stderr warnings */
|
||||
xmlSetGenericErrorFunc(NULL, hwloc__xml_verbose() ? xmlGenericError : hwloc_libxml2_error_callback);
|
||||
first = 0;
|
||||
/* 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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,7 +224,7 @@ hwloc_libxml_import_diff(struct hwloc__xml_import_state_s *state, const char *xm
|
||||
assert(sizeof(*lstate) <= sizeof(state->data));
|
||||
|
||||
LIBXML_TEST_VERSION;
|
||||
hwloc_libxml2_disable_stderrwarnings();
|
||||
hwloc_libxml2_init_once();
|
||||
|
||||
errno = 0; /* set to 0 so that we know if libxml2 changed it */
|
||||
|
||||
@ -260,7 +275,6 @@ hwloc_libxml_import_diff(struct hwloc__xml_import_state_s *state, const char *xm
|
||||
if (state->global->next_attr(state, &attrname, &attrvalue) < 0)
|
||||
break;
|
||||
if (!strcmp(attrname, "refname")) {
|
||||
if (refname)
|
||||
free(refname);
|
||||
refname = strdup(attrvalue);
|
||||
} else
|
||||
@ -270,16 +284,17 @@ hwloc_libxml_import_diff(struct hwloc__xml_import_state_s *state, const char *xm
|
||||
ret = hwloc__xml_import_diff(state, firstdiffp);
|
||||
if (refnamep && !ret)
|
||||
*refnamep = refname;
|
||||
else if (refname)
|
||||
else
|
||||
free(refname);
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
hwloc_libxml2_cleanup();
|
||||
return ret;
|
||||
|
||||
out_with_doc:
|
||||
if (refname)
|
||||
free(refname);
|
||||
xmlFreeDoc(doc);
|
||||
hwloc_libxml2_cleanup();
|
||||
out:
|
||||
return -1; /* failed */
|
||||
}
|
||||
@ -292,6 +307,7 @@ static void
|
||||
hwloc_libxml_backend_exit(struct hwloc_xml_backend_data_s *bdata)
|
||||
{
|
||||
xmlFreeDoc((xmlDoc*)bdata->data);
|
||||
hwloc_libxml2_cleanup();
|
||||
}
|
||||
|
||||
static int
|
||||
@ -301,7 +317,7 @@ hwloc_libxml_backend_init(struct hwloc_xml_backend_data_s *bdata,
|
||||
xmlDoc *doc = NULL;
|
||||
|
||||
LIBXML_TEST_VERSION;
|
||||
hwloc_libxml2_disable_stderrwarnings();
|
||||
hwloc_libxml2_init_once();
|
||||
|
||||
errno = 0; /* set to 0 so that we know if libxml2 changed it */
|
||||
|
||||
@ -370,7 +386,7 @@ hwloc__libxml_export_add_content(hwloc__xml_export_state_t state, const char *bu
|
||||
}
|
||||
|
||||
static xmlDocPtr
|
||||
hwloc__libxml2_prepare_export(hwloc_topology_t topology)
|
||||
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;
|
||||
@ -380,7 +396,7 @@ hwloc__libxml2_prepare_export(hwloc_topology_t topology)
|
||||
assert(sizeof(*data) <= sizeof(state.data));
|
||||
|
||||
LIBXML_TEST_VERSION;
|
||||
hwloc_libxml2_disable_stderrwarnings();
|
||||
hwloc_libxml2_init_once();
|
||||
|
||||
/* Creates a new document, a node and set it as a root node. */
|
||||
doc = xmlNewDoc(BAD_CAST "1.0");
|
||||
@ -397,22 +413,23 @@ hwloc__libxml2_prepare_export(hwloc_topology_t topology)
|
||||
|
||||
data->current_node = root_node;
|
||||
|
||||
hwloc__xml_export_object (&state, topology, hwloc_get_root_obj(topology));
|
||||
hwloc__xml_export_topology (&state, topology, flags);
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_libxml_export_file(hwloc_topology_t topology, const char *filename)
|
||||
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);
|
||||
doc = hwloc__libxml2_prepare_export(topology, flags);
|
||||
ret = xmlSaveFormatFileEnc(filename, doc, "UTF-8", 1);
|
||||
xmlFreeDoc(doc);
|
||||
hwloc_libxml2_cleanup();
|
||||
|
||||
if (ret < 0) {
|
||||
if (!errno)
|
||||
@ -424,13 +441,14 @@ hwloc_libxml_export_file(hwloc_topology_t topology, const char *filename)
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_libxml_export_buffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen)
|
||||
hwloc_libxml_export_buffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen, unsigned long flags)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
|
||||
doc = hwloc__libxml2_prepare_export(topology);
|
||||
doc = hwloc__libxml2_prepare_export(topology, flags);
|
||||
xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)xmlbuffer, buflen, "UTF-8", 1);
|
||||
xmlFreeDoc(doc);
|
||||
hwloc_libxml2_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -445,7 +463,7 @@ hwloc__libxml2_prepare_export_diff(hwloc_topology_diff_t diff, const char *refna
|
||||
assert(sizeof(*data) <= sizeof(state.data));
|
||||
|
||||
LIBXML_TEST_VERSION;
|
||||
hwloc_libxml2_disable_stderrwarnings();
|
||||
hwloc_libxml2_init_once();
|
||||
|
||||
/* Creates a new document, a node and set it as a root node. */
|
||||
doc = xmlNewDoc(BAD_CAST "1.0");
|
||||
@ -480,6 +498,7 @@ hwloc_libxml_export_diff_file(hwloc_topology_diff_t diff, const char *refname, c
|
||||
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)
|
||||
@ -498,6 +517,7 @@ hwloc_libxml_export_diff_buffer(hwloc_topology_diff_t diff, const char *refname,
|
||||
doc = hwloc__libxml2_prepare_export_diff(diff, refname);
|
||||
xmlDocDumpFormatMemoryEnc(doc, (xmlChar **)xmlbuffer, buflen, "UTF-8", 1);
|
||||
xmlFreeDoc(doc);
|
||||
hwloc_libxml2_cleanup();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* 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.
|
||||
@ -154,7 +154,7 @@ hwloc__nolibxml_import_find_child(hwloc__xml_import_state_t state,
|
||||
nchildstate->closed = 0;
|
||||
|
||||
/* find attributes */
|
||||
namelen = strspn(buffer, "abcdefghijklmnopqrstuvwxyz_");
|
||||
namelen = strspn(buffer, "abcdefghijklmnopqrstuvwxyz1234567890_");
|
||||
|
||||
if (buffer[namelen] == '\0') {
|
||||
/* no attributes */
|
||||
@ -590,7 +590,7 @@ hwloc__nolibxml_export_new_child(hwloc__xml_export_state_t parentstate,
|
||||
ndata->nr_children = 0;
|
||||
ndata->has_content = 0;
|
||||
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining, "%*s<%s", npdata->indent, "", name);
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining, "%*s<%s", (int) npdata->indent, "", name);
|
||||
hwloc__nolibxml_export_update_buffer(ndata, res);
|
||||
}
|
||||
|
||||
@ -615,7 +615,7 @@ hwloc__nolibxml_export_end_object(hwloc__xml_export_state_t state, const char *n
|
||||
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", npdata->indent, "", name);
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining, "%*s</%s>\n", (int) npdata->indent, "", name);
|
||||
} else {
|
||||
res = hwloc_snprintf(ndata->buffer, ndata->remaining, "/>\n");
|
||||
}
|
||||
@ -644,7 +644,7 @@ hwloc__nolibxml_export_add_content(hwloc__xml_export_state_t state, const char *
|
||||
}
|
||||
|
||||
static size_t
|
||||
hwloc___nolibxml_prepare_export(hwloc_topology_t topology, char *xmlbuffer, int buflen)
|
||||
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;
|
||||
@ -670,14 +670,14 @@ hwloc___nolibxml_prepare_export(hwloc_topology_t topology, char *xmlbuffer, int
|
||||
"<!DOCTYPE topology SYSTEM \"hwloc.dtd\">\n");
|
||||
hwloc__nolibxml_export_update_buffer(ndata, res);
|
||||
hwloc__nolibxml_export_new_child(&state, &childstate, "topology");
|
||||
hwloc__xml_export_object (&childstate, topology, hwloc_get_root_obj(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)
|
||||
hwloc_nolibxml_export_buffer(hwloc_topology_t topology, char **bufferp, int *buflenp, unsigned long flags)
|
||||
{
|
||||
char *buffer;
|
||||
size_t bufferlen, res;
|
||||
@ -686,7 +686,7 @@ hwloc_nolibxml_export_buffer(hwloc_topology_t topology, char **bufferp, int *buf
|
||||
buffer = malloc(bufferlen);
|
||||
if (!buffer)
|
||||
return -1;
|
||||
res = hwloc___nolibxml_prepare_export(topology, buffer, (int)bufferlen);
|
||||
res = hwloc___nolibxml_prepare_export(topology, buffer, (int)bufferlen, flags);
|
||||
|
||||
if (res > bufferlen) {
|
||||
char *tmp = realloc(buffer, res);
|
||||
@ -695,7 +695,7 @@ hwloc_nolibxml_export_buffer(hwloc_topology_t topology, char **bufferp, int *buf
|
||||
return -1;
|
||||
}
|
||||
buffer = tmp;
|
||||
hwloc___nolibxml_prepare_export(topology, buffer, (int)res);
|
||||
hwloc___nolibxml_prepare_export(topology, buffer, (int)res, flags);
|
||||
}
|
||||
|
||||
*bufferp = buffer;
|
||||
@ -704,14 +704,14 @@ hwloc_nolibxml_export_buffer(hwloc_topology_t topology, char **bufferp, int *buf
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc_nolibxml_export_file(hwloc_topology_t topology, const char *filename)
|
||||
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);
|
||||
ret = hwloc_nolibxml_export_buffer(topology, &buffer, &bufferlen, flags);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
2398
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-xml.c
Обычный файл
2398
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology-xml.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
3808
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology.c
Обычный файл
3808
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology.c
Обычный файл
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
553
opal/mca/hwloc/hwloc2a/hwloc/hwloc/traversal.c
Обычный файл
553
opal/mca/hwloc/hwloc2a/hwloc/hwloc/traversal.c
Обычный файл
@ -0,0 +1,553 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2017 Inria. All rights reserved.
|
||||
* Copyright © 2009-2010 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
#include <private/autogen/config.h>
|
||||
#include <hwloc.h>
|
||||
#include <private/private.h>
|
||||
#include <private/misc.h>
|
||||
#include <private/debug.h>
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif /* HAVE_STRINGS_H */
|
||||
|
||||
int
|
||||
hwloc_get_type_depth (struct hwloc_topology *topology, hwloc_obj_type_t type)
|
||||
{
|
||||
return topology->type_depth[type];
|
||||
}
|
||||
|
||||
hwloc_obj_type_t
|
||||
hwloc_get_depth_type (hwloc_topology_t topology, unsigned depth)
|
||||
{
|
||||
if (depth >= topology->nb_levels)
|
||||
switch (depth) {
|
||||
case HWLOC_TYPE_DEPTH_BRIDGE:
|
||||
return HWLOC_OBJ_BRIDGE;
|
||||
case HWLOC_TYPE_DEPTH_PCI_DEVICE:
|
||||
return HWLOC_OBJ_PCI_DEVICE;
|
||||
case HWLOC_TYPE_DEPTH_OS_DEVICE:
|
||||
return HWLOC_OBJ_OS_DEVICE;
|
||||
case HWLOC_TYPE_DEPTH_MISC:
|
||||
return HWLOC_OBJ_MISC;
|
||||
default:
|
||||
return HWLOC_OBJ_TYPE_NONE;
|
||||
}
|
||||
return topology->levels[depth][0]->type;
|
||||
}
|
||||
|
||||
unsigned
|
||||
hwloc_get_nbobjs_by_depth (struct hwloc_topology *topology, unsigned depth)
|
||||
{
|
||||
if (depth >= topology->nb_levels) {
|
||||
unsigned l = HWLOC_SLEVEL_FROM_DEPTH(depth);
|
||||
if (l < HWLOC_NR_SLEVELS)
|
||||
return topology->slevels[l].nbobjs;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
return topology->level_nbobjects[depth];
|
||||
}
|
||||
|
||||
struct hwloc_obj *
|
||||
hwloc_get_obj_by_depth (struct hwloc_topology *topology, unsigned depth, unsigned idx)
|
||||
{
|
||||
if (depth >= topology->nb_levels) {
|
||||
unsigned l = HWLOC_SLEVEL_FROM_DEPTH(depth);
|
||||
if (l < HWLOC_NR_SLEVELS)
|
||||
return idx < topology->slevels[l].nbobjs ? topology->slevels[l].objs[idx] : NULL;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
if (idx >= topology->level_nbobjects[depth])
|
||||
return NULL;
|
||||
return topology->levels[depth][idx];
|
||||
}
|
||||
|
||||
unsigned hwloc_get_closest_objs (struct hwloc_topology *topology, struct hwloc_obj *src, struct hwloc_obj **objs, unsigned max)
|
||||
{
|
||||
struct hwloc_obj *parent, *nextparent, **src_objs;
|
||||
int i,src_nbobjects;
|
||||
unsigned stored = 0;
|
||||
|
||||
if (!src->cpuset)
|
||||
return 0;
|
||||
|
||||
src_nbobjects = topology->level_nbobjects[src->depth];
|
||||
src_objs = topology->levels[src->depth];
|
||||
|
||||
parent = src;
|
||||
while (stored < max) {
|
||||
while (1) {
|
||||
nextparent = parent->parent;
|
||||
if (!nextparent)
|
||||
goto out;
|
||||
if (!hwloc_bitmap_isequal(parent->cpuset, nextparent->cpuset))
|
||||
break;
|
||||
parent = nextparent;
|
||||
}
|
||||
|
||||
/* traverse src's objects and find those that are in nextparent and were not in parent */
|
||||
for(i=0; i<src_nbobjects; i++) {
|
||||
if (hwloc_bitmap_isincluded(src_objs[i]->cpuset, nextparent->cpuset)
|
||||
&& !hwloc_bitmap_isincluded(src_objs[i]->cpuset, parent->cpuset)) {
|
||||
objs[stored++] = src_objs[i];
|
||||
if (stored == max)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
parent = nextparent;
|
||||
}
|
||||
|
||||
out:
|
||||
return stored;
|
||||
}
|
||||
|
||||
static int
|
||||
hwloc__get_largest_objs_inside_cpuset (struct hwloc_obj *current, hwloc_const_bitmap_t set,
|
||||
struct hwloc_obj ***res, int *max)
|
||||
{
|
||||
int gotten = 0;
|
||||
unsigned i;
|
||||
|
||||
/* the caller must ensure this */
|
||||
if (*max <= 0)
|
||||
return 0;
|
||||
|
||||
if (hwloc_bitmap_isequal(current->cpuset, set)) {
|
||||
**res = current;
|
||||
(*res)++;
|
||||
(*max)--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i=0; i<current->arity; i++) {
|
||||
hwloc_bitmap_t subset;
|
||||
int ret;
|
||||
|
||||
/* split out the cpuset part corresponding to this child and see if there's anything to do */
|
||||
if (!hwloc_bitmap_intersects(set,current->children[i]->cpuset))
|
||||
continue;
|
||||
|
||||
subset = hwloc_bitmap_dup(set);
|
||||
hwloc_bitmap_and(subset, subset, current->children[i]->cpuset);
|
||||
ret = hwloc__get_largest_objs_inside_cpuset (current->children[i], subset, res, max);
|
||||
gotten += ret;
|
||||
hwloc_bitmap_free(subset);
|
||||
|
||||
/* if no more room to store remaining objects, return what we got so far */
|
||||
if (!*max)
|
||||
break;
|
||||
}
|
||||
|
||||
return gotten;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_get_largest_objs_inside_cpuset (struct hwloc_topology *topology, hwloc_const_bitmap_t set,
|
||||
struct hwloc_obj **objs, int max)
|
||||
{
|
||||
struct hwloc_obj *current = topology->levels[0][0];
|
||||
|
||||
if (!hwloc_bitmap_isincluded(set, current->cpuset))
|
||||
return -1;
|
||||
|
||||
if (max <= 0)
|
||||
return 0;
|
||||
|
||||
return hwloc__get_largest_objs_inside_cpuset (current, set, &objs, &max);
|
||||
}
|
||||
|
||||
const char *
|
||||
hwloc_type_name (hwloc_obj_type_t obj)
|
||||
{
|
||||
switch (obj)
|
||||
{
|
||||
case HWLOC_OBJ_SYSTEM: return "System";
|
||||
case HWLOC_OBJ_MACHINE: return "Machine";
|
||||
case HWLOC_OBJ_MISC: return "Misc";
|
||||
case HWLOC_OBJ_GROUP: return "Group";
|
||||
case HWLOC_OBJ_NUMANODE: return "NUMANode";
|
||||
case HWLOC_OBJ_PACKAGE: return "Package";
|
||||
case HWLOC_OBJ_L1CACHE: return "L1Cache";
|
||||
case HWLOC_OBJ_L2CACHE: return "L2Cache";
|
||||
case HWLOC_OBJ_L3CACHE: return "L3Cache";
|
||||
case HWLOC_OBJ_L4CACHE: return "L4Cache";
|
||||
case HWLOC_OBJ_L5CACHE: return "L5Cache";
|
||||
case HWLOC_OBJ_L1ICACHE: return "L1iCache";
|
||||
case HWLOC_OBJ_L2ICACHE: return "L2iCache";
|
||||
case HWLOC_OBJ_L3ICACHE: return "L3iCache";
|
||||
case HWLOC_OBJ_CORE: return "Core";
|
||||
case HWLOC_OBJ_BRIDGE: return "Bridge";
|
||||
case HWLOC_OBJ_PCI_DEVICE: return "PCIDev";
|
||||
case HWLOC_OBJ_OS_DEVICE: return "OSDev";
|
||||
case HWLOC_OBJ_PU: return "PU";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_type_sscanf(const char *string, hwloc_obj_type_t *typep,
|
||||
union hwloc_obj_attr_u *attrp, size_t attrsize)
|
||||
{
|
||||
hwloc_obj_type_t type = (hwloc_obj_type_t) -1;
|
||||
unsigned depthattr = (unsigned) -1;
|
||||
hwloc_obj_cache_type_t cachetypeattr = (hwloc_obj_cache_type_t) -1; /* unspecified */
|
||||
hwloc_obj_bridge_type_t ubtype = (hwloc_obj_bridge_type_t) -1;
|
||||
hwloc_obj_osdev_type_t ostype = (hwloc_obj_osdev_type_t) -1;
|
||||
char *end;
|
||||
|
||||
/* never match the ending \0 since we want to match things like core:2 too.
|
||||
* just use hwloc_strncasecmp() everywhere.
|
||||
*/
|
||||
|
||||
/* types without a custom depth */
|
||||
if (!hwloc_strncasecmp(string, "system", 2)) {
|
||||
type = HWLOC_OBJ_SYSTEM;
|
||||
} else if (!hwloc_strncasecmp(string, "machine", 2)) {
|
||||
type = HWLOC_OBJ_MACHINE;
|
||||
} else if (!hwloc_strncasecmp(string, "node", 2)
|
||||
|| !hwloc_strncasecmp(string, "numa", 2)) { /* matches node and numanode */
|
||||
type = HWLOC_OBJ_NUMANODE;
|
||||
} else if (!hwloc_strncasecmp(string, "package", 2)
|
||||
|| !hwloc_strncasecmp(string, "socket", 2)) { /* backward compat with v1.10 */
|
||||
type = HWLOC_OBJ_PACKAGE;
|
||||
} else if (!hwloc_strncasecmp(string, "core", 2)) {
|
||||
type = HWLOC_OBJ_CORE;
|
||||
} else if (!hwloc_strncasecmp(string, "pu", 2)) {
|
||||
type = HWLOC_OBJ_PU;
|
||||
} else if (!hwloc_strncasecmp(string, "misc", 4)) {
|
||||
type = HWLOC_OBJ_MISC;
|
||||
|
||||
} else if (!hwloc_strncasecmp(string, "bridge", 4)) {
|
||||
type = HWLOC_OBJ_BRIDGE;
|
||||
} else if (!hwloc_strncasecmp(string, "hostbridge", 6)) {
|
||||
type = HWLOC_OBJ_BRIDGE;
|
||||
ubtype = HWLOC_OBJ_BRIDGE_HOST;
|
||||
} else if (!hwloc_strncasecmp(string, "pcibridge", 5)) {
|
||||
type = HWLOC_OBJ_BRIDGE;
|
||||
ubtype = HWLOC_OBJ_BRIDGE_PCI;
|
||||
|
||||
} else if (!hwloc_strncasecmp(string, "pci", 3)) {
|
||||
type = HWLOC_OBJ_PCI_DEVICE;
|
||||
|
||||
} else if (!hwloc_strncasecmp(string, "os", 2)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
} else if (!hwloc_strncasecmp(string, "bloc", 4)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_BLOCK;
|
||||
} else if (!hwloc_strncasecmp(string, "net", 3)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_NETWORK;
|
||||
} else if (!hwloc_strncasecmp(string, "openfab", 7)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_OPENFABRICS;
|
||||
} else if (!hwloc_strncasecmp(string, "dma", 3)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_DMA;
|
||||
} else if (!hwloc_strncasecmp(string, "gpu", 3)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_GPU;
|
||||
} else if (!hwloc_strncasecmp(string, "copro", 5)
|
||||
|| !hwloc_strncasecmp(string, "co-pro", 6)) {
|
||||
type = HWLOC_OBJ_OS_DEVICE;
|
||||
ostype = HWLOC_OBJ_OSDEV_COPROC;
|
||||
|
||||
/* types with depthattr */
|
||||
} else if ((string[0] == 'l' || string[0] == 'L') && string[1] >= '0' && string[1] <= '9') {
|
||||
depthattr = strtol(string+1, &end, 10);
|
||||
if (*end == 'i') {
|
||||
if (depthattr >= 1 && depthattr <= 3) {
|
||||
type = HWLOC_OBJ_L1ICACHE + depthattr-1;
|
||||
cachetypeattr = HWLOC_OBJ_CACHE_INSTRUCTION;
|
||||
} else
|
||||
return -1;
|
||||
} else {
|
||||
if (depthattr >= 1 && depthattr <= 5) {
|
||||
type = HWLOC_OBJ_L1CACHE + depthattr-1;
|
||||
cachetypeattr = *end == 'd' ? HWLOC_OBJ_CACHE_DATA : HWLOC_OBJ_CACHE_UNIFIED;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else if (!hwloc_strncasecmp(string, "group", 2)) {
|
||||
size_t length;
|
||||
type = HWLOC_OBJ_GROUP;
|
||||
length = strcspn(string, "0123456789");
|
||||
if (length <= 5 && !hwloc_strncasecmp(string, "group", length)
|
||||
&& string[length] >= '0' && string[length] <= '9') {
|
||||
depthattr = strtol(string+length, &end, 10);
|
||||
}
|
||||
|
||||
} else
|
||||
return -1;
|
||||
|
||||
*typep = type;
|
||||
if (attrp) {
|
||||
if (hwloc_obj_type_is_cache(type) && attrsize >= sizeof(attrp->cache)) {
|
||||
attrp->cache.depth = depthattr;
|
||||
attrp->cache.type = cachetypeattr;
|
||||
} else if (type == HWLOC_OBJ_GROUP && attrsize >= sizeof(attrp->group)) {
|
||||
attrp->group.depth = depthattr;
|
||||
} else if (type == HWLOC_OBJ_BRIDGE && attrsize >= sizeof(attrp->bridge)) {
|
||||
attrp->bridge.upstream_type = ubtype;
|
||||
attrp->bridge.downstream_type = HWLOC_OBJ_BRIDGE_PCI; /* nothing else so far */
|
||||
} else if (type == HWLOC_OBJ_OS_DEVICE && attrsize >= sizeof(attrp->osdev)) {
|
||||
attrp->osdev.type = ostype;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_type_sscanf_as_depth(const char *string, hwloc_obj_type_t *typep,
|
||||
hwloc_topology_t topology, int *depthp)
|
||||
{
|
||||
union hwloc_obj_attr_u attr;
|
||||
hwloc_obj_type_t type;
|
||||
int depth;
|
||||
int err;
|
||||
|
||||
err = hwloc_type_sscanf(string, &type, &attr, sizeof(attr));
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
depth = hwloc_get_type_depth(topology, type);
|
||||
if (type == HWLOC_OBJ_GROUP
|
||||
&& depth == HWLOC_TYPE_DEPTH_MULTIPLE
|
||||
&& attr.group.depth != (unsigned)-1) {
|
||||
unsigned l;
|
||||
depth = HWLOC_TYPE_DEPTH_UNKNOWN;
|
||||
for(l=0; l<topology->nb_levels; l++) {
|
||||
if (topology->levels[l][0]->type == HWLOC_OBJ_GROUP
|
||||
&& topology->levels[l][0]->attr->group.depth == attr.group.depth) {
|
||||
depth = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typep)
|
||||
*typep = type;
|
||||
*depthp = (unsigned) depth;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* hwloc_obj_cache_type_letter(hwloc_obj_cache_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case HWLOC_OBJ_CACHE_UNIFIED: return "";
|
||||
case HWLOC_OBJ_CACHE_DATA: return "d";
|
||||
case HWLOC_OBJ_CACHE_INSTRUCTION: return "i";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, int verbose)
|
||||
{
|
||||
hwloc_obj_type_t type = obj->type;
|
||||
switch (type) {
|
||||
case HWLOC_OBJ_MISC:
|
||||
case HWLOC_OBJ_SYSTEM:
|
||||
case HWLOC_OBJ_MACHINE:
|
||||
case HWLOC_OBJ_NUMANODE:
|
||||
case HWLOC_OBJ_PACKAGE:
|
||||
case HWLOC_OBJ_CORE:
|
||||
case HWLOC_OBJ_PU:
|
||||
return hwloc_snprintf(string, size, "%s", hwloc_type_name(type));
|
||||
case HWLOC_OBJ_L1CACHE:
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
case HWLOC_OBJ_L3CACHE:
|
||||
case HWLOC_OBJ_L4CACHE:
|
||||
case HWLOC_OBJ_L5CACHE:
|
||||
case HWLOC_OBJ_L1ICACHE:
|
||||
case HWLOC_OBJ_L2ICACHE:
|
||||
case HWLOC_OBJ_L3ICACHE:
|
||||
return hwloc_snprintf(string, size, "L%u%s%s", obj->attr->cache.depth,
|
||||
hwloc_obj_cache_type_letter(obj->attr->cache.type),
|
||||
verbose ? "Cache" : "");
|
||||
case HWLOC_OBJ_GROUP:
|
||||
if (obj->attr->group.depth != (unsigned) -1)
|
||||
return hwloc_snprintf(string, size, "%s%u", hwloc_type_name(type), obj->attr->group.depth);
|
||||
else
|
||||
return hwloc_snprintf(string, size, "%s", hwloc_type_name(type));
|
||||
case HWLOC_OBJ_BRIDGE:
|
||||
return snprintf(string, size, obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI ? "PCIBridge" : "HostBridge");
|
||||
case HWLOC_OBJ_PCI_DEVICE:
|
||||
return hwloc_snprintf(string, size, "PCI");
|
||||
case HWLOC_OBJ_OS_DEVICE:
|
||||
switch (obj->attr->osdev.type) {
|
||||
case HWLOC_OBJ_OSDEV_BLOCK: return hwloc_snprintf(string, size, "Block");
|
||||
case HWLOC_OBJ_OSDEV_NETWORK: return hwloc_snprintf(string, size, verbose ? "Network" : "Net");
|
||||
case HWLOC_OBJ_OSDEV_OPENFABRICS: return hwloc_snprintf(string, size, "OpenFabrics");
|
||||
case HWLOC_OBJ_OSDEV_DMA: return hwloc_snprintf(string, size, "DMA");
|
||||
case HWLOC_OBJ_OSDEV_GPU: return hwloc_snprintf(string, size, "GPU");
|
||||
case HWLOC_OBJ_OSDEV_COPROC: return hwloc_snprintf(string, size, verbose ? "Co-Processor" : "CoProc");
|
||||
default:
|
||||
if (size > 0)
|
||||
*string = '\0';
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (size > 0)
|
||||
*string = '\0';
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
hwloc_obj_attr_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, const char * separator, int verbose)
|
||||
{
|
||||
const char *prefix = "";
|
||||
char *tmp = string;
|
||||
ssize_t tmplen = size;
|
||||
int ret = 0;
|
||||
int res;
|
||||
|
||||
/* make sure we output at least an empty string */
|
||||
if (size)
|
||||
*string = '\0';
|
||||
|
||||
/* print memory attributes */
|
||||
res = 0;
|
||||
if (verbose) {
|
||||
if (obj->memory.local_memory)
|
||||
res = hwloc_snprintf(tmp, tmplen, "%slocal=%lu%s%stotal=%lu%s",
|
||||
prefix,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->memory.local_memory, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->memory.total_memory, verbose),
|
||||
separator,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->memory.total_memory, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->memory.local_memory, verbose));
|
||||
else if (obj->memory.total_memory)
|
||||
res = hwloc_snprintf(tmp, tmplen, "%stotal=%lu%s",
|
||||
prefix,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->memory.total_memory, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->memory.total_memory, verbose));
|
||||
} else {
|
||||
if (obj->memory.local_memory)
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%lu%s",
|
||||
prefix,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->memory.local_memory, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->memory.local_memory, verbose));
|
||||
}
|
||||
if (res < 0)
|
||||
return -1;
|
||||
ret += res;
|
||||
if (ret > 0)
|
||||
prefix = separator;
|
||||
if (res >= tmplen)
|
||||
res = tmplen>0 ? (int)tmplen - 1 : 0;
|
||||
tmp += res;
|
||||
tmplen -= res;
|
||||
|
||||
/* printf type-specific attributes */
|
||||
res = 0;
|
||||
switch (obj->type) {
|
||||
case HWLOC_OBJ_L1CACHE:
|
||||
case HWLOC_OBJ_L2CACHE:
|
||||
case HWLOC_OBJ_L3CACHE:
|
||||
case HWLOC_OBJ_L4CACHE:
|
||||
case HWLOC_OBJ_L5CACHE:
|
||||
case HWLOC_OBJ_L1ICACHE:
|
||||
case HWLOC_OBJ_L2ICACHE:
|
||||
case HWLOC_OBJ_L3ICACHE:
|
||||
if (verbose) {
|
||||
char assoc[32];
|
||||
if (obj->attr->cache.associativity == -1)
|
||||
snprintf(assoc, sizeof(assoc), "%sfully-associative", separator);
|
||||
else if (obj->attr->cache.associativity == 0)
|
||||
*assoc = '\0';
|
||||
else
|
||||
snprintf(assoc, sizeof(assoc), "%sways=%d", separator, obj->attr->cache.associativity);
|
||||
res = hwloc_snprintf(tmp, tmplen, "%ssize=%lu%s%slinesize=%u%s",
|
||||
prefix,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->attr->cache.size, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose),
|
||||
separator, obj->attr->cache.linesize,
|
||||
assoc);
|
||||
} else
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%lu%s",
|
||||
prefix,
|
||||
(unsigned long) hwloc_memory_size_printf_value(obj->attr->cache.size, verbose),
|
||||
hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose));
|
||||
break;
|
||||
case HWLOC_OBJ_BRIDGE:
|
||||
if (verbose) {
|
||||
char up[128], down[64];
|
||||
/* upstream is PCI or HOST */
|
||||
if (obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI) {
|
||||
char linkspeed[64]= "";
|
||||
if (obj->attr->pcidev.linkspeed)
|
||||
snprintf(linkspeed, sizeof(linkspeed), "%slink=%.2fGB/s", separator, obj->attr->pcidev.linkspeed);
|
||||
snprintf(up, sizeof(up), "busid=%04x:%02x:%02x.%01x%sid=%04x:%04x%sclass=%04x(%s)%s",
|
||||
obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func, separator,
|
||||
obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id, separator,
|
||||
obj->attr->pcidev.class_id, hwloc_pci_class_string(obj->attr->pcidev.class_id), linkspeed);
|
||||
} else
|
||||
*up = '\0';
|
||||
/* downstream is_PCI */
|
||||
snprintf(down, sizeof(down), "buses=%04x:[%02x-%02x]",
|
||||
obj->attr->bridge.downstream.pci.domain, obj->attr->bridge.downstream.pci.secondary_bus, obj->attr->bridge.downstream.pci.subordinate_bus);
|
||||
if (*up)
|
||||
res = snprintf(string, size, "%s%s%s", up, separator, down);
|
||||
else
|
||||
res = snprintf(string, size, "%s", down);
|
||||
}
|
||||
break;
|
||||
case HWLOC_OBJ_PCI_DEVICE:
|
||||
if (verbose) {
|
||||
char linkspeed[64]= "";
|
||||
if (obj->attr->pcidev.linkspeed)
|
||||
snprintf(linkspeed, sizeof(linkspeed), "%slink=%.2fGB/s", separator, obj->attr->pcidev.linkspeed);
|
||||
res = snprintf(string, size, "busid=%04x:%02x:%02x.%01x%sid=%04x:%04x%sclass=%04x(%s)%s",
|
||||
obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func, separator,
|
||||
obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id, separator,
|
||||
obj->attr->pcidev.class_id, hwloc_pci_class_string(obj->attr->pcidev.class_id), linkspeed);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (res < 0)
|
||||
return -1;
|
||||
ret += res;
|
||||
if (ret > 0)
|
||||
prefix = separator;
|
||||
if (res >= tmplen)
|
||||
res = tmplen>0 ? (int)tmplen - 1 : 0;
|
||||
tmp += res;
|
||||
tmplen -= res;
|
||||
|
||||
/* printf infos */
|
||||
if (verbose) {
|
||||
unsigned i;
|
||||
for(i=0; i<obj->infos_count; i++) {
|
||||
if (strchr(obj->infos[i].value, ' '))
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%s=\"%s\"",
|
||||
prefix,
|
||||
obj->infos[i].name, obj->infos[i].value);
|
||||
else
|
||||
res = hwloc_snprintf(tmp, tmplen, "%s%s=%s",
|
||||
prefix,
|
||||
obj->infos[i].name, obj->infos[i].value);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
ret += res;
|
||||
if (res >= tmplen)
|
||||
res = tmplen>0 ? (int)tmplen - 1 : 0;
|
||||
tmp += res;
|
||||
tmplen -= res;
|
||||
if (ret > 0)
|
||||
prefix = separator;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
# Copyright © 2009-2014 Inria. All rights reserved.
|
||||
# Copyright © 2009-2017 Inria. All rights reserved.
|
||||
# Copyright © 2009-2010 Université Bordeaux
|
||||
# Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
# 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.
|
||||
|
||||
@ -9,12 +9,20 @@
|
||||
|
||||
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/shmem.h \
|
||||
hwloc/distances.h \
|
||||
hwloc/export.h \
|
||||
hwloc/myriexpress.h \
|
||||
hwloc/openfabrics-verbs.h \
|
||||
hwloc/opencl.h \
|
||||
@ -35,7 +43,10 @@ noinst_HEADERS = \
|
||||
private/misc.h \
|
||||
private/xml.h \
|
||||
private/components.h \
|
||||
private/cpuid-x86.h
|
||||
private/cpuid-x86.h \
|
||||
private/netloc.h \
|
||||
netloc/utarray.h \
|
||||
netloc/uthash.h
|
||||
|
||||
if HWLOC_HAVE_LINUX
|
||||
include_hwloc_HEADERS += \
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
@ -96,7 +96,6 @@ hwloc_cuda_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
/* 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];
|
||||
FILE *sysfile = NULL;
|
||||
int domainid, busid, deviceid;
|
||||
|
||||
if (hwloc_cuda_get_device_pci_ids(topology, cudevice, &domainid, &busid, &deviceid))
|
||||
@ -108,15 +107,9 @@ hwloc_cuda_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unused,
|
||||
}
|
||||
|
||||
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.0/local_cpus", domainid, busid, deviceid);
|
||||
sysfile = fopen(path, "r");
|
||||
if (!sysfile)
|
||||
return -1;
|
||||
|
||||
if (hwloc_linux_parse_cpumap_file(sysfile, set) < 0
|
||||
if (hwloc_linux_read_path_as_cpumask(path, set) < 0
|
||||
|| hwloc_bitmap_iszero(set))
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
|
||||
fclose(sysfile);
|
||||
#else
|
||||
/* Non-Linux systems simply get a full cpuset */
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
@ -155,8 +148,10 @@ hwloc_cuda_get_device_pcidev(hwloc_topology_t topology, CUdevice cudevice)
|
||||
* 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.
|
||||
* 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)
|
||||
@ -179,6 +174,7 @@ hwloc_cuda_get_device_osdev(hwloc_topology_t topology, CUdevice cudevice)
|
||||
&& (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;
|
||||
@ -195,7 +191,7 @@ hwloc_cuda_get_device_osdev(hwloc_topology_t topology, CUdevice cudevice)
|
||||
* 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.
|
||||
* 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().
|
||||
*/
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2010-2016 Inria. All rights reserved.
|
||||
* 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.
|
||||
@ -93,7 +93,6 @@ hwloc_cudart_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unuse
|
||||
/* 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];
|
||||
FILE *sysfile = NULL;
|
||||
int domain, bus, dev;
|
||||
|
||||
if (hwloc_cudart_get_device_pci_ids(topology, idx, &domain, &bus, &dev))
|
||||
@ -104,16 +103,10 @@ hwloc_cudart_get_device_cpuset(hwloc_topology_t topology __hwloc_attribute_unuse
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.0/local_cpus", domain, bus, dev);
|
||||
sysfile = fopen(path, "r");
|
||||
if (!sysfile)
|
||||
return -1;
|
||||
|
||||
if (hwloc_linux_parse_cpumap_file(sysfile, set) < 0
|
||||
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));
|
||||
|
||||
fclose(sysfile);
|
||||
#else
|
||||
/* Non-Linux systems simply get a full cpuset */
|
||||
hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
|
||||
@ -155,7 +148,7 @@ hwloc_cudart_get_device_pcidev(hwloc_topology_t topology, int idx)
|
||||
* hwloc_cudart_get_device_cpuset().
|
||||
*
|
||||
* \note The corresponding PCI device object can be obtained by looking
|
||||
* at the OS device parent object.
|
||||
* 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().
|
||||
*/
|
216
opal/mca/hwloc/hwloc2a/hwloc/include/hwloc/deprecated.h
Обычный файл
216
opal/mca/hwloc/hwloc2a/hwloc/include/hwloc/deprecated.h
Обычный файл
@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright © 2009 CNRS
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2009-2010 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file contains the inline code of functions declared in hwloc.h
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_DEPRECATED_H
|
||||
#define HWLOC_DEPRECATED_H
|
||||
|
||||
#ifndef HWLOC_H
|
||||
#error Please include the main hwloc.h instead
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* backward compat with v1.10 before Socket->Package renaming */
|
||||
#define HWLOC_OBJ_SOCKET HWLOC_OBJ_PACKAGE
|
||||
/* backward compat with v1.10 before Node->NUMANode clarification */
|
||||
#define HWLOC_OBJ_NODE HWLOC_OBJ_NUMANODE
|
||||
|
||||
/** \brief Insert a misc object by parent.
|
||||
*
|
||||
* Identical to hwloc_topology_insert_misc_object().
|
||||
*/
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_topology_insert_misc_object_by_parent(hwloc_topology_t topology, hwloc_obj_t parent, const char *name) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline hwloc_obj_t
|
||||
hwloc_topology_insert_misc_object_by_parent(hwloc_topology_t topology, hwloc_obj_t parent, const char *name)
|
||||
{
|
||||
return hwloc_topology_insert_misc_object(topology, parent, name);
|
||||
}
|
||||
|
||||
/** \brief Stringify the cpuset containing a set of objects.
|
||||
*
|
||||
* If \p size is 0, \p string may safely be \c NULL.
|
||||
*
|
||||
* \return the number of character that were actually written if not truncating,
|
||||
* or that would have been written (not including the ending \\0).
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_obj_cpuset_snprintf(char *str, size_t size, size_t nobj, struct hwloc_obj * const *objs) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_obj_cpuset_snprintf(char *str, size_t size, size_t nobj, struct hwloc_obj * const *objs)
|
||||
{
|
||||
hwloc_bitmap_t set = hwloc_bitmap_alloc();
|
||||
int res;
|
||||
unsigned i;
|
||||
|
||||
hwloc_bitmap_zero(set);
|
||||
for(i=0; i<nobj; i++)
|
||||
if (objs[i]->cpuset)
|
||||
hwloc_bitmap_or(set, set, objs[i]->cpuset);
|
||||
|
||||
res = hwloc_bitmap_snprintf(str, size, set);
|
||||
hwloc_bitmap_free(set);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** \brief Return a stringified topology object type.
|
||||
*
|
||||
* Deprecated by the identical hwloc_type_name()
|
||||
*/
|
||||
static __hwloc_inline const char *
|
||||
hwloc_obj_type_string (hwloc_obj_type_t type) __hwloc_attribute_const; /* not deprecated in early 2.x releases because widely used and prototype unchanged */
|
||||
static __hwloc_inline const char *
|
||||
hwloc_obj_type_string (hwloc_obj_type_t type)
|
||||
{
|
||||
return hwloc_type_name(type);
|
||||
}
|
||||
|
||||
/** \brief Convert a type string into a type and some attributes.
|
||||
*
|
||||
* Deprecated by hwloc_type_sscanf()
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, void *typeattrp, size_t typeattrsize) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, void *typeattrp, size_t typeattrsize)
|
||||
{
|
||||
union hwloc_obj_attr_u attr;
|
||||
int err = hwloc_type_sscanf(string, typep, &attr, sizeof(attr));
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (hwloc_obj_type_is_cache(*typep)) {
|
||||
if (depthattrp)
|
||||
*depthattrp = attr.cache.depth;
|
||||
if (typeattrp && typeattrsize >= sizeof(hwloc_obj_cache_type_t))
|
||||
memcpy(typeattrp, &attr.cache.type, sizeof(hwloc_obj_cache_type_t));
|
||||
} else if (*typep == HWLOC_OBJ_GROUP) {
|
||||
if (depthattrp)
|
||||
*depthattrp = attr.group.depth;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** \brief Set the default memory binding policy of the current
|
||||
* process or thread to prefer the NUMA node(s) specified by physical \p nodeset
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_set_membind(topology, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Query the default memory binding policy and physical locality of the
|
||||
* current process or thread.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
return hwloc_get_membind(topology, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Set the default memory binding policy of the specified
|
||||
* process to prefer the NUMA node(s) specified by physical \p nodeset
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_set_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_set_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_set_proc_membind(topology, pid, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Query the default memory binding policy and physical locality of the
|
||||
* specified process.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_get_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_get_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
return hwloc_get_proc_membind(topology, pid, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Bind the already-allocated memory identified by (addr, len)
|
||||
* to the NUMA node(s) in physical \p nodeset.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_set_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_set_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_set_area_membind(topology, addr, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Query the physical NUMA node(s) and binding policy of the memory
|
||||
* identified by (\p addr, \p len ).
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_get_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline int
|
||||
hwloc_get_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
|
||||
{
|
||||
return hwloc_get_area_membind(topology, addr, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Allocate some memory on the given physical nodeset \p nodeset
|
||||
*/
|
||||
static __hwloc_inline void *
|
||||
hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_malloc __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline void *
|
||||
hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_alloc_membind(topology, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Allocate some memory on the given nodeset \p nodeset.
|
||||
*/
|
||||
static __hwloc_inline void *
|
||||
hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) __hwloc_attribute_malloc __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline void *
|
||||
hwloc_alloc_membind_policy_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
|
||||
{
|
||||
return hwloc_alloc_membind_policy(topology, len, nodeset, policy, flags | HWLOC_MEMBIND_BYNODESET);
|
||||
}
|
||||
|
||||
/** \brief Convert a CPU set into a NUMA node set and handle non-NUMA cases
|
||||
*/
|
||||
static __hwloc_inline void
|
||||
hwloc_cpuset_to_nodeset_strict(hwloc_topology_t topology, hwloc_const_cpuset_t _cpuset, hwloc_nodeset_t nodeset) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline void
|
||||
hwloc_cpuset_to_nodeset_strict(hwloc_topology_t topology, hwloc_const_cpuset_t _cpuset, hwloc_nodeset_t nodeset)
|
||||
{
|
||||
hwloc_cpuset_to_nodeset(topology, _cpuset, nodeset);
|
||||
}
|
||||
|
||||
/** \brief Convert a NUMA node set into a CPU set and handle non-NUMA cases
|
||||
*/
|
||||
static __hwloc_inline void
|
||||
hwloc_cpuset_from_nodeset_strict(hwloc_topology_t topology, hwloc_cpuset_t _cpuset, hwloc_const_nodeset_t nodeset) __hwloc_attribute_deprecated;
|
||||
static __hwloc_inline void
|
||||
hwloc_cpuset_from_nodeset_strict(hwloc_topology_t topology, hwloc_cpuset_t _cpuset, hwloc_const_nodeset_t nodeset)
|
||||
{
|
||||
hwloc_cpuset_from_nodeset(topology, _cpuset, nodeset);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_DEPRECATED_H */
|
@ -220,11 +220,8 @@ enum hwloc_topology_diff_apply_flags_e {
|
||||
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.
|
||||
*
|
||||
* \note The \p topology parameter must be a valid topology
|
||||
* but it is not required that it is related to \p diff.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_destroy(hwloc_topology_t topology, hwloc_topology_diff_t diff);
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_destroy(hwloc_topology_diff_t diff);
|
||||
|
||||
/** \brief Load a list of topology differences from a XML file.
|
||||
*
|
||||
@ -234,13 +231,10 @@ HWLOC_DECLSPEC int hwloc_topology_diff_destroy(hwloc_topology_t topology, hwloc_
|
||||
* This identifier is usually the name of the other XML file
|
||||
* that contains the reference topology.
|
||||
*
|
||||
* \note The \p topology parameter must be a valid topology
|
||||
* but it is not required that it is related to \p diff.
|
||||
*
|
||||
* \note the pointer returned in refname should later be freed
|
||||
* by the caller.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_load_xml(hwloc_topology_t topology, const char *xmlpath, hwloc_topology_diff_t *diff, char **refname);
|
||||
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.
|
||||
*
|
||||
@ -250,11 +244,8 @@ HWLOC_DECLSPEC int hwloc_topology_diff_load_xml(hwloc_topology_t topology, const
|
||||
* 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 \p topology parameter must be a valid topology
|
||||
* but it is not required that it is related to \p diff.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_export_xml(hwloc_topology_t topology, hwloc_topology_diff_t diff, const char *refname, const char *xmlpath);
|
||||
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.
|
||||
*
|
||||
@ -264,13 +255,10 @@ HWLOC_DECLSPEC int hwloc_topology_diff_export_xml(hwloc_topology_t topology, hwl
|
||||
* This identifier is usually the name of the other XML file
|
||||
* that contains the reference topology.
|
||||
*
|
||||
* \note The \p topology parameter must be a valid topology
|
||||
* but it is not required that it is related to \p diff.
|
||||
*
|
||||
* \note the pointer returned in refname should later be freed
|
||||
* by the caller.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_load_xmlbuffer(hwloc_topology_t topology, const char *xmlbuffer, int buflen, hwloc_topology_diff_t *diff, char **refname);
|
||||
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.
|
||||
*
|
||||
@ -282,11 +270,8 @@ HWLOC_DECLSPEC int hwloc_topology_diff_load_xmlbuffer(hwloc_topology_t topology,
|
||||
* This attribute is given back when reading the diff from XML.
|
||||
*
|
||||
* \note The XML buffer should later be freed with hwloc_free_xmlbuffer().
|
||||
*
|
||||
* \note The \p topology parameter must be a valid topology
|
||||
* but it is not required that it is related to \p diff.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_export_xmlbuffer(hwloc_topology_t topology, hwloc_topology_diff_t diff, const char *refname, char **xmlbuffer, int *buflen);
|
||||
HWLOC_DECLSPEC int hwloc_topology_diff_export_xmlbuffer(hwloc_topology_diff_t diff, const char *refname, char **xmlbuffer, int *buflen);
|
||||
|
||||
/** @} */
|
||||
|
223
opal/mca/hwloc/hwloc2a/hwloc/include/hwloc/distances.h
Обычный файл
223
opal/mca/hwloc/hwloc2a/hwloc/include/hwloc/distances.h
Обычный файл
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* Copyright © 2010-2017 Inria. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Object distances.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_DISTANCES_H
|
||||
#define HWLOC_DISTANCES_H
|
||||
|
||||
#ifndef HWLOC_H
|
||||
#error Please include the main hwloc.h instead
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#elif 0
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_distances_get Retrieve distances between objects
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Matrix of distances between a set of objects.
|
||||
*
|
||||
* This matrix often contains latencies between NUMA nodes
|
||||
* (as reported in the System Locality Distance Information Table (SLIT)
|
||||
* in the ACPI specification), which may or may not be physically accurate.
|
||||
* It corresponds to the latency for accessing the memory of one node
|
||||
* from a core in another node.
|
||||
* The corresponding kind is ::HWLOC_DISTANCES_KIND_FROM_OS | ::HWLOC_DISTANCES_KIND_FROM_USER.
|
||||
*
|
||||
* The matrix may also contain bandwidths between random sets of objects,
|
||||
* possibly provided by the user, as specified in the \p kind attribute.
|
||||
*/
|
||||
struct hwloc_distances_s {
|
||||
unsigned nbobjs; /**< \brief Number of objects described by the distance matrix. */
|
||||
hwloc_obj_t *objs; /**< \brief Array of objects described by the distance matrix. */
|
||||
unsigned long kind; /**< \brief OR'ed set of ::hwloc_distances_kind_e. */
|
||||
hwloc_uint64_t *values; /**< \brief Matrix of distances between objects, stored as a one-dimension array.
|
||||
*
|
||||
* Distance from i-th to j-th object is stored in slot i*nbobjs+j.
|
||||
* The meaning of the value depends on the \p kind attribute.
|
||||
*/
|
||||
};
|
||||
|
||||
/** \brief Kinds of distance matrices.
|
||||
*
|
||||
* The \p kind attribute of struct hwloc_distances_s is a OR'ed set
|
||||
* of kinds.
|
||||
*
|
||||
* A kind of format HWLOC_DISTANCES_KIND_FROM_* specifies where the
|
||||
* distance information comes from, if known.
|
||||
*
|
||||
* A kind of format HWLOC_DISTANCES_KIND_MEANS_* specifies whether
|
||||
* values are latencies or bandwidths, if applicable.
|
||||
*/
|
||||
enum hwloc_distances_kind_e {
|
||||
/** \brief These distances were obtained from the operating system or hardware.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_KIND_FROM_OS = (1UL<<0),
|
||||
/** \brief These distances were provided by the user.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_KIND_FROM_USER = (1UL<<1),
|
||||
|
||||
/** \brief Distance values are similar to latencies between objects.
|
||||
* Values are smaller for closer objects, hence minimal on the diagonal
|
||||
* of the matrix (distance between an object and itself).
|
||||
* It could also be the number of network hops between objects, etc.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_KIND_MEANS_LATENCY = (1UL<<2),
|
||||
/** \brief Distance values are similar to bandwidths between objects.
|
||||
* Values are higher for closer objects, hence maximal on the diagonal
|
||||
* of the matrix (distance between an object and itself).
|
||||
* Such values are currently ignored for distance-based grouping.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH = (1UL<<3)
|
||||
};
|
||||
|
||||
/** \brief Retrieve distance matrices.
|
||||
*
|
||||
* Retrieve distance matrices from the topology into the \p distances array.
|
||||
*
|
||||
* \p flags is currently unused, should be \c 0.
|
||||
*
|
||||
* \p kind serves as a filter. If \c 0, all distance matrices are returned.
|
||||
* If it contains some HWLOC_DISTANCES_KIND_FROM_*, only distances whose kind
|
||||
* matches one of these are returned.
|
||||
* If it contains some HWLOC_DISTANCES_KIND_MEANS_*, only distances whose kind
|
||||
* matches one of these are returned.
|
||||
*
|
||||
* On input, \p nr points to the number of distances that may be stored in \p distances.
|
||||
* On output, \p nr points to the number of distances that were actually found,
|
||||
* even if some of them couldn't be stored in \p distances.
|
||||
* Distances that couldn't be stored are ignored, but the function still returns
|
||||
* success (\c 0). The caller may find out by comparing the value pointed by \p nr
|
||||
* before and after the function call.
|
||||
*
|
||||
* Each distance structure returned in the \p distances array should be released
|
||||
* by the caller using hwloc_distances_release().
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_distances_get(hwloc_topology_t topology,
|
||||
unsigned *nr, struct hwloc_distances_s **distances,
|
||||
unsigned long kind, unsigned long flags);
|
||||
|
||||
/** \brief Retrieve distance matrices for object at a specific depth in the topology.
|
||||
*
|
||||
* Identical to hwloc_distances_get() with the additional \p depth filter.
|
||||
*/
|
||||
HWLOC_DECLSPEC int
|
||||
hwloc_distances_get_by_depth(hwloc_topology_t topology, unsigned depth,
|
||||
unsigned *nr, struct hwloc_distances_s **distances,
|
||||
unsigned long kind, unsigned long flags);
|
||||
|
||||
/** \brief Retrieve distance matrices for object of a specific type.
|
||||
*
|
||||
* Identical to hwloc_distances_get() with the additional \p type filter.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_distances_get_by_type(hwloc_topology_t topology, hwloc_obj_type_t type,
|
||||
unsigned *nr, struct hwloc_distances_s **distances,
|
||||
unsigned long kind, unsigned long flags)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, type);
|
||||
if (depth < 0) {
|
||||
*nr = 0;
|
||||
return 0;
|
||||
}
|
||||
return hwloc_distances_get_by_depth(topology, depth, nr, distances, kind, flags);
|
||||
}
|
||||
|
||||
/** \brief Release a distance structure previously returned by hwloc_distances_get(). */
|
||||
HWLOC_DECLSPEC void
|
||||
hwloc_distances_release(hwloc_topology_t topology, struct hwloc_distances_s *distances);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
/** \defgroup hwlocality_distances_add Add or remove distances between objects
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Flags for adding a new distances to a topology. */
|
||||
enum hwloc_distances_flag_e {
|
||||
/** \brief Try to group objects based on the newly provided distance information.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_FLAG_GROUP = (1UL<<0),
|
||||
/** \brief If grouping, consider the distance values as inaccurate and relax the
|
||||
* comparisons during the grouping algorithms. The actual accuracy may be modified
|
||||
* through the HWLOC_GROUPING_ACCURACY environment variable (see \ref envvar).
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_DISTANCES_FLAG_GROUP_INACCURATE = (1UL<<1)
|
||||
};
|
||||
|
||||
/** \brief Provide a distance matrix.
|
||||
*
|
||||
* Provide the matrix of distances between a set of objects given by \p nbobjs
|
||||
* and the \p objs array. \p nbobjs must be at least 2.
|
||||
* The distances are stored as a one-dimension array in \p values.
|
||||
* The distance from object i to object j is in slot i*nbobjs+j.
|
||||
*
|
||||
* \p kind specifies the kind of distance as a OR'ed set of ::hwloc_distances_kind_e.
|
||||
*
|
||||
* \p flags configures the behavior of the function using an optional OR'ed set of
|
||||
* ::hwloc_distances_flag_e.
|
||||
*
|
||||
* Objects must be of the same type. They cannot be of type Group.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_distances_add(hwloc_topology_t topology,
|
||||
unsigned nbobjs, hwloc_obj_t *objs, hwloc_uint64_t *values,
|
||||
unsigned long kind, unsigned long flags);
|
||||
|
||||
/** \brief Remove all distance matrices from a topology.
|
||||
*
|
||||
* Remove all distance matrices, either provided by the user or
|
||||
* gathered through the OS.
|
||||
*
|
||||
* If these distances were used to group objects, these additional
|
||||
*Group objects are not removed from the topology.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_distances_remove(hwloc_topology_t topology);
|
||||
|
||||
/** \brief Remove distance matrices for objects at a specific depth in the topology.
|
||||
*
|
||||
* Identical to hwloc_distances_remove() but only applies to one level of the topology.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_distances_remove_by_depth(hwloc_topology_t topology, unsigned depth);
|
||||
|
||||
/** \brief Remove distance matrices for objects of a specific type in the topology.
|
||||
*
|
||||
* Identical to hwloc_distances_remove() but only applies to one level of the topology.
|
||||
*/
|
||||
static __hwloc_inline int
|
||||
hwloc_distances_remove_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
|
||||
{
|
||||
int depth = hwloc_get_type_depth(topology, type);
|
||||
if (depth < 0)
|
||||
return 0;
|
||||
return hwloc_distances_remove_by_depth(topology, depth);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_DISTANCES_H */
|
236
opal/mca/hwloc/hwloc2a/hwloc/include/hwloc/export.h
Обычный файл
236
opal/mca/hwloc/hwloc2a/hwloc/include/hwloc/export.h
Обычный файл
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright © 2009-2016 Inria. All rights reserved.
|
||||
* Copyright © 2009-2012 Université Bordeaux
|
||||
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
|
||||
* See COPYING in top-level directory.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \brief Exporting Topologies to XML or to Synthetic strings.
|
||||
*/
|
||||
|
||||
#ifndef HWLOC_EXPORT_H
|
||||
#define HWLOC_EXPORT_H
|
||||
|
||||
#ifndef HWLOC_H
|
||||
#error Please include the main hwloc.h instead
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#elif 0
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup hwlocality_xmlexport Exporting Topologies to XML
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Flags for exporting XML topologies.
|
||||
*
|
||||
* Flags to be given as a OR'ed set to hwloc_topology_export_xml().
|
||||
*/
|
||||
enum hwloc_topology_export_xml_flags_e {
|
||||
/** \brief Export XML that is loadable by hwloc v1.x.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1 = (1UL<<0)
|
||||
};
|
||||
|
||||
/** \brief Export the topology into an XML file.
|
||||
*
|
||||
* This file may be loaded later through hwloc_topology_set_xml().
|
||||
*
|
||||
* \p flags is a OR'ed set of ::hwloc_topology_export_xml_flags_e.
|
||||
*
|
||||
* \return -1 if a failure occured.
|
||||
*
|
||||
* \note See also hwloc_topology_set_userdata_export_callback()
|
||||
* for exporting application-specific object userdata.
|
||||
*
|
||||
* \note The topology-specific userdata pointer is ignored when exporting to XML.
|
||||
*
|
||||
* \note Only printable characters may be exported to XML string attributes.
|
||||
* Any other character, especially any non-ASCII character, will be silently
|
||||
* dropped.
|
||||
*
|
||||
* \note If \p name is "-", the XML output is sent to the standard output.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_export_xml(hwloc_topology_t topology, const char *xmlpath, unsigned long flags);
|
||||
|
||||
/** \brief Export the topology into a newly-allocated XML memory buffer.
|
||||
*
|
||||
* \p xmlbuffer is allocated by the callee and should be freed with
|
||||
* hwloc_free_xmlbuffer() later in the caller.
|
||||
*
|
||||
* This memory buffer may be loaded later through hwloc_topology_set_xmlbuffer().
|
||||
*
|
||||
* \p flags is a OR'ed set of ::hwloc_topology_export_xml_flags_e.
|
||||
*
|
||||
* \return -1 if a failure occured.
|
||||
*
|
||||
* \note See also hwloc_topology_set_userdata_export_callback()
|
||||
* for exporting application-specific object userdata.
|
||||
*
|
||||
* \note The topology-specific userdata pointer is ignored when exporting to XML.
|
||||
*
|
||||
* \note Only printable characters may be exported to XML string attributes.
|
||||
* Any other character, especially any non-ASCII character, will be silently
|
||||
* dropped.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_export_xmlbuffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen, unsigned long flags);
|
||||
|
||||
/** \brief Free a buffer allocated by hwloc_topology_export_xmlbuffer() */
|
||||
HWLOC_DECLSPEC void hwloc_free_xmlbuffer(hwloc_topology_t topology, char *xmlbuffer);
|
||||
|
||||
/** \brief Set the application-specific callback for exporting object userdata
|
||||
*
|
||||
* The object userdata pointer is not exported to XML by default because hwloc
|
||||
* does not know what it contains.
|
||||
*
|
||||
* This function lets applications set \p export_cb to a callback function
|
||||
* that converts this opaque userdata into an exportable string.
|
||||
*
|
||||
* \p export_cb is invoked during XML export for each object whose
|
||||
* \p userdata pointer is not \c NULL.
|
||||
* The callback should use hwloc_export_obj_userdata() or
|
||||
* hwloc_export_obj_userdata_base64() to actually export
|
||||
* something to XML (possibly multiple times per object).
|
||||
*
|
||||
* \p export_cb may be set to \c NULL if userdata should not be exported to XML.
|
||||
*
|
||||
* \note The topology-specific userdata pointer is ignored when exporting to XML.
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_topology_set_userdata_export_callback(hwloc_topology_t topology,
|
||||
void (*export_cb)(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj));
|
||||
|
||||
/** \brief Export some object userdata to XML
|
||||
*
|
||||
* This function may only be called from within the export() callback passed
|
||||
* to hwloc_topology_set_userdata_export_callback().
|
||||
* It may be invoked one of multiple times to export some userdata to XML.
|
||||
* The \p buffer content of length \p length is stored with optional name
|
||||
* \p name.
|
||||
*
|
||||
* When importing this XML file, the import() callback (if set) will be
|
||||
* called exactly as many times as hwloc_export_obj_userdata() was called
|
||||
* during export(). It will receive the corresponding \p name, \p buffer
|
||||
* and \p length arguments.
|
||||
*
|
||||
* \p reserved, \p topology and \p obj must be the first three parameters
|
||||
* that were given to the export callback.
|
||||
*
|
||||
* Only printable characters may be exported to XML string attributes.
|
||||
* If a non-printable character is passed in \p name or \p buffer,
|
||||
* the function returns -1 with errno set to EINVAL.
|
||||
*
|
||||
* If exporting binary data, the application should first encode into
|
||||
* printable characters only (or use hwloc_export_obj_userdata_base64()).
|
||||
* It should also take care of portability issues if the export may
|
||||
* be reimported on a different architecture.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_export_obj_userdata(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length);
|
||||
|
||||
/** \brief Encode and export some object userdata to XML
|
||||
*
|
||||
* This function is similar to hwloc_export_obj_userdata() but it encodes
|
||||
* the input buffer into printable characters before exporting.
|
||||
* On import, decoding is automatically performed before the data is given
|
||||
* to the import() callback if any.
|
||||
*
|
||||
* This function may only be called from within the export() callback passed
|
||||
* to hwloc_topology_set_userdata_export_callback().
|
||||
*
|
||||
* The function does not take care of portability issues if the export
|
||||
* may be reimported on a different architecture.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_export_obj_userdata_base64(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length);
|
||||
|
||||
/** \brief Set the application-specific callback for importing userdata
|
||||
*
|
||||
* On XML import, userdata is ignored by default because hwloc does not know
|
||||
* how to store it in memory.
|
||||
*
|
||||
* This function lets applications set \p import_cb to a callback function
|
||||
* that will get the XML-stored userdata and store it in the object as expected
|
||||
* by the application.
|
||||
*
|
||||
* \p import_cb is called during hwloc_topology_load() as many times as
|
||||
* hwloc_export_obj_userdata() was called during export. The topology
|
||||
* is not entirely setup yet. Object attributes are ready to consult,
|
||||
* but links between objects are not.
|
||||
*
|
||||
* \p import_cb may be \c NULL if userdata should be ignored during import.
|
||||
*
|
||||
* \note \p buffer contains \p length characters followed by a null byte ('\0').
|
||||
*
|
||||
* \note This function should be called before hwloc_topology_load().
|
||||
*
|
||||
* \note The topology-specific userdata pointer is ignored when importing from XML.
|
||||
*/
|
||||
HWLOC_DECLSPEC void hwloc_topology_set_userdata_import_callback(hwloc_topology_t topology,
|
||||
void (*import_cb)(hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length));
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
/** \defgroup hwlocality_syntheticexport Exporting Topologies to Synthetic
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Flags for exporting synthetic topologies.
|
||||
*
|
||||
* Flags to be given as a OR'ed set to hwloc_topology_export_synthetic().
|
||||
*/
|
||||
enum hwloc_topology_export_synthetic_flags_e {
|
||||
/** \brief Export extended types such as L2dcache as basic types such as Cache.
|
||||
*
|
||||
* This is required if loading the synthetic description with hwloc < 1.9.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES = (1UL<<0),
|
||||
|
||||
/** \brief Do not export level attributes.
|
||||
*
|
||||
* Ignore level attributes such as memory/cache sizes or PU indexes.
|
||||
* This is required if loading the synthetic description with hwloc < 1.10.
|
||||
* \hideinitializer
|
||||
*/
|
||||
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS = (1UL<<1)
|
||||
};
|
||||
|
||||
/** \brief Export the topology as a synthetic string.
|
||||
*
|
||||
* At most \p buflen characters will be written in \p buffer,
|
||||
* including the terminating \0.
|
||||
*
|
||||
* This exported string may be given back to hwloc_topology_set_synthetic().
|
||||
*
|
||||
* \p flags is a OR'ed set of ::hwloc_topology_export_synthetic_flags_e.
|
||||
*
|
||||
* \return The number of characters that were written,
|
||||
* not including the terminating \0.
|
||||
*
|
||||
* \return -1 if the topology could not be exported,
|
||||
* for instance if it is not symmetric.
|
||||
*
|
||||
* \note I/O and Misc children are ignored, the synthetic string only
|
||||
* describes normal children.
|
||||
*
|
||||
* \note A 1024-byte buffer should be large enough for exporting
|
||||
* topologies in the vast majority of cases.
|
||||
*/
|
||||
HWLOC_DECLSPEC int hwloc_topology_export_synthetic(hwloc_topology_t topology, char *buffer, size_t buflen, unsigned long flags);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* HWLOC_EXPORT_H */
|
@ -48,7 +48,7 @@ extern "C" {
|
||||
* 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.
|
||||
* 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,
|
||||
@ -79,7 +79,7 @@ hwloc_gl_get_display_osdev_by_port_device(hwloc_topology_t topology,
|
||||
* 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.
|
||||
* 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,
|
||||
@ -132,4 +132,3 @@ hwloc_gl_get_display_by_osdev(hwloc_topology_t topology __hwloc_attribute_unused
|
||||
|
||||
|
||||
#endif /* HWLOC_GL_H */
|
||||
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче
Block a user