1
1

Merge pull request #3951 from rhc54/topic/hwloc2

Update to hwloc 2.0.0a
Этот коммит содержится в:
Ralph Castain 2017-08-01 15:18:31 -06:00 коммит произвёл GitHub
родитель 69612b3e2a 6ebaed8c01
Коммит f39ce67982
148 изменённых файлов: 23234 добавлений и 18835 удалений

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

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

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

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

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

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

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

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

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

@ -0,0 +1,468 @@
/*
* Copyright © 2013-2017 Inria. All rights reserved.
* See COPYING in top-level directory.
*/
#include <private/autogen/config.h>
#include <private/private.h>
#include <private/misc.h>
int hwloc_topology_diff_destroy(hwloc_topology_diff_t diff)
{
hwloc_topology_diff_t next;
while (diff) {
next = diff->generic.next;
switch (diff->generic.type) {
default:
break;
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR:
switch (diff->obj_attr.diff.generic.type) {
default:
break;
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME:
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO:
free(diff->obj_attr.diff.string.name);
free(diff->obj_attr.diff.string.oldvalue);
free(diff->obj_attr.diff.string.newvalue);
break;
}
break;
}
free(diff);
diff = next;
}
return 0;
}
/************************
* Computing diffs
*/
static void hwloc_append_diff(hwloc_topology_diff_t newdiff,
hwloc_topology_diff_t *firstdiffp,
hwloc_topology_diff_t *lastdiffp)
{
if (*firstdiffp)
(*lastdiffp)->generic.next = newdiff;
else
*firstdiffp = newdiff;
*lastdiffp = newdiff;
newdiff->generic.next = NULL;
}
static int hwloc_append_diff_too_complex(hwloc_obj_t obj1,
hwloc_topology_diff_t *firstdiffp,
hwloc_topology_diff_t *lastdiffp)
{
hwloc_topology_diff_t newdiff;
newdiff = malloc(sizeof(*newdiff));
if (!newdiff)
return -1;
newdiff->too_complex.type = HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX;
newdiff->too_complex.obj_depth = obj1->depth;
newdiff->too_complex.obj_index = obj1->logical_index;
hwloc_append_diff(newdiff, firstdiffp, lastdiffp);
return 0;
}
static int hwloc_append_diff_obj_attr_string(hwloc_obj_t obj,
hwloc_topology_diff_obj_attr_type_t type,
const char *name,
const char *oldvalue,
const char *newvalue,
hwloc_topology_diff_t *firstdiffp,
hwloc_topology_diff_t *lastdiffp)
{
hwloc_topology_diff_t newdiff;
newdiff = malloc(sizeof(*newdiff));
if (!newdiff)
return -1;
newdiff->obj_attr.type = HWLOC_TOPOLOGY_DIFF_OBJ_ATTR;
newdiff->obj_attr.obj_depth = obj->depth;
newdiff->obj_attr.obj_index = obj->logical_index;
newdiff->obj_attr.diff.string.type = type;
newdiff->obj_attr.diff.string.name = name ? strdup(name) : NULL;
newdiff->obj_attr.diff.string.oldvalue = oldvalue ? strdup(oldvalue) : NULL;
newdiff->obj_attr.diff.string.newvalue = newvalue ? strdup(newvalue) : NULL;
hwloc_append_diff(newdiff, firstdiffp, lastdiffp);
return 0;
}
static int hwloc_append_diff_obj_attr_uint64(hwloc_obj_t obj,
hwloc_topology_diff_obj_attr_type_t type,
hwloc_uint64_t idx,
hwloc_uint64_t oldvalue,
hwloc_uint64_t newvalue,
hwloc_topology_diff_t *firstdiffp,
hwloc_topology_diff_t *lastdiffp)
{
hwloc_topology_diff_t newdiff;
newdiff = malloc(sizeof(*newdiff));
if (!newdiff)
return -1;
newdiff->obj_attr.type = HWLOC_TOPOLOGY_DIFF_OBJ_ATTR;
newdiff->obj_attr.obj_depth = obj->depth;
newdiff->obj_attr.obj_index = obj->logical_index;
newdiff->obj_attr.diff.uint64.type = type;
newdiff->obj_attr.diff.uint64.index = idx;
newdiff->obj_attr.diff.uint64.oldvalue = oldvalue;
newdiff->obj_attr.diff.uint64.newvalue = newvalue;
hwloc_append_diff(newdiff, firstdiffp, lastdiffp);
return 0;
}
static int
hwloc_diff_trees(hwloc_topology_t topo1, hwloc_obj_t obj1,
hwloc_topology_t topo2, hwloc_obj_t obj2,
unsigned flags,
hwloc_topology_diff_t *firstdiffp, hwloc_topology_diff_t *lastdiffp)
{
unsigned i;
int err;
hwloc_obj_t child1, child2;
if (obj1->depth != obj2->depth)
goto out_too_complex;
if (obj1->type != obj2->type)
goto out_too_complex;
if ((!obj1->subtype) != (!obj2->subtype)
|| (obj1->subtype && strcmp(obj1->subtype, obj2->subtype)))
goto out_too_complex;
if (obj1->os_index != obj2->os_index)
/* we could allow different os_index for non-PU non-NUMAnode objects
* but it's likely useless anyway */
goto out_too_complex;
#define _SETS_DIFFERENT(_set1, _set2) \
( ( !(_set1) != !(_set2) ) \
|| ( (_set1) && !hwloc_bitmap_isequal(_set1, _set2) ) )
#define SETS_DIFFERENT(_set, _obj1, _obj2) _SETS_DIFFERENT((_obj1)->_set, (_obj2)->_set)
if (SETS_DIFFERENT(cpuset, obj1, obj2)
|| SETS_DIFFERENT(complete_cpuset, obj1, obj2)
|| SETS_DIFFERENT(allowed_cpuset, obj1, obj2)
|| SETS_DIFFERENT(nodeset, obj1, obj2)
|| SETS_DIFFERENT(complete_nodeset, obj1, obj2)
|| SETS_DIFFERENT(allowed_nodeset, obj1, obj2))
goto out_too_complex;
/* no need to check logical_index, sibling_rank, symmetric_subtree,
* the parents did it */
/* gp_index don't have to be strictly identical */
if ((!obj1->name) != (!obj2->name)
|| (obj1->name && strcmp(obj1->name, obj2->name))) {
err = hwloc_append_diff_obj_attr_string(obj1,
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME,
NULL,
obj1->name,
obj2->name,
firstdiffp, lastdiffp);
if (err < 0)
return err;
}
/* memory */
if (obj1->memory.local_memory != obj2->memory.local_memory) {
err = hwloc_append_diff_obj_attr_uint64(obj1,
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE,
0,
obj1->memory.local_memory,
obj2->memory.local_memory,
firstdiffp, lastdiffp);
if (err < 0)
return err;
}
/* ignore memory page_types */
/* type-specific attrs */
switch (obj1->type) {
default:
break;
case HWLOC_OBJ_L1CACHE:
case HWLOC_OBJ_L2CACHE:
case HWLOC_OBJ_L3CACHE:
case HWLOC_OBJ_L4CACHE:
case HWLOC_OBJ_L5CACHE:
case HWLOC_OBJ_L1ICACHE:
case HWLOC_OBJ_L2ICACHE:
case HWLOC_OBJ_L3ICACHE:
if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->cache)))
goto out_too_complex;
break;
case HWLOC_OBJ_GROUP:
if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->group)))
goto out_too_complex;
break;
case HWLOC_OBJ_PCI_DEVICE:
if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->pcidev)))
goto out_too_complex;
break;
case HWLOC_OBJ_BRIDGE:
if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->bridge)))
goto out_too_complex;
break;
case HWLOC_OBJ_OS_DEVICE:
if (memcmp(obj1->attr, obj2->attr, sizeof(obj1->attr->osdev)))
goto out_too_complex;
break;
}
/* infos */
if (obj1->infos_count != obj2->infos_count)
goto out_too_complex;
for(i=0; i<obj1->infos_count; i++) {
if (strcmp(obj1->infos[i].name, obj2->infos[i].name))
goto out_too_complex;
if (strcmp(obj1->infos[i].value, obj2->infos[i].value)) {
err = hwloc_append_diff_obj_attr_string(obj1,
HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO,
obj1->infos[i].name,
obj1->infos[i].value,
obj2->infos[i].value,
firstdiffp, lastdiffp);
if (err < 0)
return err;
}
}
/* ignore userdata */
/* children */
for(child1 = obj1->first_child, child2 = obj2->first_child;
child1 != NULL && child2 != NULL;
child1 = child1->next_sibling, child2 = child2->next_sibling) {
err = hwloc_diff_trees(topo1, child1,
topo2, child2,
flags,
firstdiffp, lastdiffp);
if (err < 0)
return err;
}
if (child1 || child2)
goto out_too_complex;
/* I/O children */
for(child1 = obj1->io_first_child, child2 = obj2->io_first_child;
child1 != NULL && child2 != NULL;
child1 = child1->next_sibling, child2 = child2->next_sibling) {
err = hwloc_diff_trees(topo1, child1,
topo2, child2,
flags,
firstdiffp, lastdiffp);
if (err < 0)
return err;
}
if (child1 || child2)
goto out_too_complex;
/* misc children */
for(child1 = obj1->misc_first_child, child2 = obj2->misc_first_child;
child1 != NULL && child2 != NULL;
child1 = child1->next_sibling, child2 = child2->next_sibling) {
err = hwloc_diff_trees(topo1, child1,
topo2, child2,
flags,
firstdiffp, lastdiffp);
if (err < 0)
return err;
}
if (child1 || child2)
goto out_too_complex;
return 0;
out_too_complex:
hwloc_append_diff_too_complex(obj1, firstdiffp, lastdiffp);
return 0;
}
int hwloc_topology_diff_build(hwloc_topology_t topo1,
hwloc_topology_t topo2,
unsigned long flags,
hwloc_topology_diff_t *diffp)
{
hwloc_topology_diff_t lastdiff, tmpdiff;
struct hwloc_internal_distances_s *dist1, *dist2;
unsigned i;
int err;
if (!topo1->is_loaded || !topo2->is_loaded) {
errno = EINVAL;
return -1;
}
if (flags != 0) {
errno = EINVAL;
return -1;
}
*diffp = NULL;
err = hwloc_diff_trees(topo1, hwloc_get_root_obj(topo1),
topo2, hwloc_get_root_obj(topo2),
flags,
diffp, &lastdiff);
if (!err) {
tmpdiff = *diffp;
while (tmpdiff) {
if (tmpdiff->generic.type == HWLOC_TOPOLOGY_DIFF_TOO_COMPLEX) {
err = 1;
break;
}
tmpdiff = tmpdiff->generic.next;
}
}
if (!err) {
/* distances */
hwloc_internal_distances_refresh(topo1);
hwloc_internal_distances_refresh(topo2);
dist1 = topo1->first_dist;
dist2 = topo2->first_dist;
while (dist1 || dist2) {
if (!!dist1 != !!dist2) {
hwloc_append_diff_too_complex(hwloc_get_root_obj(topo1), diffp, &lastdiff);
err = 1;
break;
}
if (dist1->type != dist2->type
|| dist1->nbobjs != dist2->nbobjs
|| dist1->kind != dist2->kind
|| memcmp(dist1->values, dist2->values, dist1->nbobjs * dist1->nbobjs * sizeof(*dist1->values))) {
hwloc_append_diff_too_complex(hwloc_get_root_obj(topo1), diffp, &lastdiff);
err = 1;
break;
}
for(i=0; i<dist1->nbobjs; i++)
/* gp_index isn't enforced above. so compare logical_index instead, which is enforced. requires distances refresh() above */
if (dist1->objs[i]->logical_index != dist2->objs[i]->logical_index) {
hwloc_append_diff_too_complex(hwloc_get_root_obj(topo1), diffp, &lastdiff);
err = 1;
break;
}
dist1 = dist1->next;
dist2 = dist2->next;
}
}
return err;
}
/********************
* Applying diffs
*/
static int
hwloc_apply_diff_one(hwloc_topology_t topology,
hwloc_topology_diff_t diff,
unsigned long flags)
{
int reverse = !!(flags & HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE);
switch (diff->generic.type) {
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR: {
struct hwloc_topology_diff_obj_attr_s *obj_attr = &diff->obj_attr;
hwloc_obj_t obj = hwloc_get_obj_by_depth(topology, obj_attr->obj_depth, obj_attr->obj_index);
if (!obj)
return -1;
switch (obj_attr->diff.generic.type) {
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_SIZE: {
hwloc_obj_t tmpobj;
hwloc_uint64_t oldvalue = reverse ? obj_attr->diff.uint64.newvalue : obj_attr->diff.uint64.oldvalue;
hwloc_uint64_t newvalue = reverse ? obj_attr->diff.uint64.oldvalue : obj_attr->diff.uint64.newvalue;
hwloc_uint64_t valuediff = newvalue - oldvalue;
if (obj->memory.local_memory != oldvalue)
return -1;
obj->memory.local_memory = newvalue;
tmpobj = obj;
while (tmpobj) {
tmpobj->memory.total_memory += valuediff;
tmpobj = tmpobj->parent;
}
break;
}
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_NAME: {
const char *oldvalue = reverse ? obj_attr->diff.string.newvalue : obj_attr->diff.string.oldvalue;
const char *newvalue = reverse ? obj_attr->diff.string.oldvalue : obj_attr->diff.string.newvalue;
if (!obj->name || strcmp(obj->name, oldvalue))
return -1;
free(obj->name);
obj->name = strdup(newvalue);
break;
}
case HWLOC_TOPOLOGY_DIFF_OBJ_ATTR_INFO: {
const char *name = obj_attr->diff.string.name;
const char *oldvalue = reverse ? obj_attr->diff.string.newvalue : obj_attr->diff.string.oldvalue;
const char *newvalue = reverse ? obj_attr->diff.string.oldvalue : obj_attr->diff.string.newvalue;
unsigned i;
int found = 0;
for(i=0; i<obj->infos_count; i++) {
if (!strcmp(obj->infos[i].name, name)
&& !strcmp(obj->infos[i].value, oldvalue)) {
free(obj->infos[i].value);
obj->infos[i].value = strdup(newvalue);
found = 1;
break;
}
}
if (!found)
return -1;
break;
}
default:
return -1;
}
break;
}
default:
return -1;
}
return 0;
}
int hwloc_topology_diff_apply(hwloc_topology_t topology,
hwloc_topology_diff_t diff,
unsigned long flags)
{
hwloc_topology_diff_t tmpdiff, tmpdiff2;
int err, nr;
if (!topology->is_loaded) {
errno = EINVAL;
return -1;
}
if (flags & ~HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE) {
errno = EINVAL;
return -1;
}
tmpdiff = diff;
nr = 0;
while (tmpdiff) {
nr++;
err = hwloc_apply_diff_one(topology, tmpdiff, flags);
if (err < 0)
goto cancel;
tmpdiff = tmpdiff->generic.next;
}
return 0;
cancel:
tmpdiff2 = tmpdiff;
tmpdiff = diff;
while (tmpdiff != tmpdiff2) {
hwloc_apply_diff_one(topology, tmpdiff, flags ^ HWLOC_TOPOLOGY_DIFF_APPLY_REVERSE);
tmpdiff = tmpdiff->generic.next;
}
errno = EINVAL;
return -nr; /* return the index (starting at 1) of the first element that couldn't be applied */
}

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

@ -0,0 +1,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)

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

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

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

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

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

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

@ -0,0 +1,146 @@
/*
* Copyright © 2012-2017 Inria. All rights reserved.
* See COPYING in top-level directory.
*/
#include <private/autogen/config.h>
#include <hwloc.h>
#include <hwloc/plugins.h>
/* private headers allowed for convenience because this plugin is built within hwloc */
#include <private/misc.h>
#include <private/debug.h>
#include <nvml.h>
static int
hwloc_nvml_discover(struct hwloc_backend *backend)
{
struct hwloc_topology *topology = backend->topology;
enum hwloc_type_filter_e filter;
nvmlReturn_t ret;
unsigned nb, i;
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_OS_DEVICE, &filter);
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
return 0;
ret = nvmlInit();
if (NVML_SUCCESS != ret)
return -1;
ret = nvmlDeviceGetCount(&nb);
if (NVML_SUCCESS != ret || !nb) {
nvmlShutdown();
return 0;
}
for(i=0; i<nb; i++) {
nvmlPciInfo_t pci;
nvmlDevice_t device;
hwloc_obj_t osdev, parent;
char buffer[64];
ret = nvmlDeviceGetHandleByIndex(i, &device);
assert(ret == NVML_SUCCESS);
osdev = hwloc_alloc_setup_object(topology, HWLOC_OBJ_OS_DEVICE, -1);
snprintf(buffer, sizeof(buffer), "nvml%u", i);
osdev->name = strdup(buffer);
osdev->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN;
osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_GPU;
hwloc_obj_add_info(osdev, "Backend", "NVML");
hwloc_obj_add_info(osdev, "GPUVendor", "NVIDIA Corporation");
buffer[0] = '\0';
ret = nvmlDeviceGetName(device, buffer, sizeof(buffer));
hwloc_obj_add_info(osdev, "GPUModel", buffer);
/* these may fail with NVML_ERROR_NOT_SUPPORTED on old devices */
buffer[0] = '\0';
ret = nvmlDeviceGetSerial(device, buffer, sizeof(buffer));
if (buffer[0] != '\0')
hwloc_obj_add_info(osdev, "NVIDIASerial", buffer);
buffer[0] = '\0';
ret = nvmlDeviceGetUUID(device, buffer, sizeof(buffer));
if (buffer[0] != '\0')
hwloc_obj_add_info(osdev, "NVIDIAUUID", buffer);
parent = NULL;
if (NVML_SUCCESS == nvmlDeviceGetPciInfo(device, &pci)) {
parent = hwloc_pci_belowroot_find_by_busid(topology, pci.domain, pci.bus, pci.device, 0);
if (!parent)
parent = hwloc_pci_find_busid_parent(topology, pci.domain, pci.bus, pci.device, 0);
#if HAVE_DECL_NVMLDEVICEGETMAXPCIELINKGENERATION
if (parent && parent->type == HWLOC_OBJ_PCI_DEVICE) {
unsigned maxwidth = 0, maxgen = 0;
float lanespeed;
nvmlDeviceGetMaxPcieLinkWidth(device, &maxwidth);
nvmlDeviceGetMaxPcieLinkGeneration(device, &maxgen);
/* PCIe Gen1 = 2.5GT/s signal-rate per lane with 8/10 encoding = 0.25GB/s data-rate per lane
* PCIe Gen2 = 5 GT/s signal-rate per lane with 8/10 encoding = 0.5 GB/s data-rate per lane
* PCIe Gen3 = 8 GT/s signal-rate per lane with 128/130 encoding = 1 GB/s data-rate per lane
*/
lanespeed = maxgen <= 2 ? 2.5 * maxgen * 0.8 : 8.0 * 128/130; /* Gbit/s per lane */
if (lanespeed * maxwidth != 0.)
/* we found the max link speed, replace the current link speed found by pci (or none) */
parent->attr->pcidev.linkspeed = lanespeed * maxwidth / 8; /* GB/s */
}
#endif
}
if (!parent)
parent = hwloc_get_root_obj(topology);
hwloc_insert_object_by_parent(topology, parent, osdev);
}
nvmlShutdown();
return 0;
}
static struct hwloc_backend *
hwloc_nvml_component_instantiate(struct hwloc_disc_component *component,
const void *_data1 __hwloc_attribute_unused,
const void *_data2 __hwloc_attribute_unused,
const void *_data3 __hwloc_attribute_unused)
{
struct hwloc_backend *backend;
backend = hwloc_backend_alloc(component);
if (!backend)
return NULL;
backend->discover = hwloc_nvml_discover;
return backend;
}
static struct hwloc_disc_component hwloc_nvml_disc_component = {
HWLOC_DISC_COMPONENT_TYPE_MISC,
"nvml",
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
hwloc_nvml_component_instantiate,
5, /* after pci, and after cuda since likely less useful */
NULL
};
static int
hwloc_nvml_component_init(unsigned long flags)
{
if (flags)
return -1;
if (hwloc_plugin_check_namespace("nvml", "hwloc_backend_alloc") < 0)
return -1;
return 0;
}
#ifdef HWLOC_INSIDE_PLUGIN
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_nvml_component;
#endif
const struct hwloc_component hwloc_nvml_component = {
HWLOC_COMPONENT_ABI,
hwloc_nvml_component_init, NULL,
HWLOC_COMPONENT_TYPE_DISC,
0,
&hwloc_nvml_disc_component
};

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

@ -0,0 +1,203 @@
/*
* Copyright © 2012-2017 Inria. All rights reserved.
* Copyright © 2013 Université Bordeaux. All right reserved.
* See COPYING in top-level directory.
*/
#include <private/autogen/config.h>
#include <hwloc.h>
#include <hwloc/plugins.h>
/* private headers allowed for convenience because this plugin is built within hwloc */
#include <private/misc.h>
#include <private/debug.h>
#include <CL/cl_ext.h>
static int
hwloc_opencl_discover(struct hwloc_backend *backend)
{
struct hwloc_topology *topology = backend->topology;
enum hwloc_type_filter_e filter;
cl_platform_id *platform_ids = NULL;
cl_uint nr_platforms;
cl_int clret;
unsigned j;
hwloc_topology_get_type_filter(topology, HWLOC_OBJ_OS_DEVICE, &filter);
if (filter == HWLOC_TYPE_FILTER_KEEP_NONE)
return 0;
clret = clGetPlatformIDs(0, NULL, &nr_platforms);
if (CL_SUCCESS != clret || !nr_platforms)
return -1;
hwloc_debug("%u OpenCL platforms\n", nr_platforms);
platform_ids = malloc(nr_platforms * sizeof(*platform_ids));
if (!platform_ids)
return -1;
clret = clGetPlatformIDs(nr_platforms, platform_ids, &nr_platforms);
if (CL_SUCCESS != clret || !nr_platforms) {
free(platform_ids);
return -1;
}
for(j=0; j<nr_platforms; j++) {
cl_device_id *device_ids = NULL;
cl_uint nr_devices;
unsigned i;
clret = clGetDeviceIDs(platform_ids[j], CL_DEVICE_TYPE_ALL, 0, NULL, &nr_devices);
if (CL_SUCCESS != clret)
continue;
device_ids = malloc(nr_devices * sizeof(*device_ids));
clret = clGetDeviceIDs(platform_ids[j], CL_DEVICE_TYPE_ALL, nr_devices, device_ids, &nr_devices);
if (CL_SUCCESS != clret) {
free(device_ids);
continue;
}
for(i=0; i<nr_devices; i++) {
cl_platform_id platform_id = 0;
cl_device_type type;
#ifdef CL_DEVICE_TOPOLOGY_AMD
cl_device_topology_amd amdtopo;
#endif
cl_ulong globalmemsize;
cl_uint computeunits;
hwloc_obj_t osdev, parent;
char buffer[64];
hwloc_debug("This is opencl%ud%u\n", j, i);
#ifdef CL_DEVICE_TOPOLOGY_AMD
clret = clGetDeviceInfo(device_ids[i], CL_DEVICE_TOPOLOGY_AMD, sizeof(amdtopo), &amdtopo, NULL);
if (CL_SUCCESS != clret) {
hwloc_debug("no AMD-specific device information: %d\n", clret);
continue;
} else if (CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD != amdtopo.raw.type) {
hwloc_debug("AMD-specific device topology reports non-PCIe device type: %u\n", amdtopo.raw.type);
continue;
}
#else
continue;
#endif
osdev = hwloc_alloc_setup_object(topology, HWLOC_OBJ_OS_DEVICE, -1);
snprintf(buffer, sizeof(buffer), "opencl%ud%u", j, i);
osdev->name = strdup(buffer);
osdev->depth = (unsigned) HWLOC_TYPE_DEPTH_UNKNOWN;
osdev->attr->osdev.type = HWLOC_OBJ_OSDEV_COPROC;
osdev->subtype = strdup("OpenCL");
hwloc_obj_add_info(osdev, "Backend", "OpenCL");
clGetDeviceInfo(device_ids[i], CL_DEVICE_TYPE, sizeof(type), &type, NULL);
if (type == CL_DEVICE_TYPE_GPU)
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "GPU");
else if (type == CL_DEVICE_TYPE_ACCELERATOR)
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "Accelerator");
else if (type == CL_DEVICE_TYPE_CPU)
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "CPU");
else if (type == CL_DEVICE_TYPE_CUSTOM)
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "Custom");
else
hwloc_obj_add_info(osdev, "OpenCLDeviceType", "Unknown");
buffer[0] = '\0';
clGetDeviceInfo(device_ids[i], CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL);
if (buffer[0] != '\0')
hwloc_obj_add_info(osdev, "GPUVendor", buffer);
buffer[0] = '\0';
#ifdef CL_DEVICE_BOARD_NAME_AMD
clGetDeviceInfo(device_ids[i], CL_DEVICE_BOARD_NAME_AMD, sizeof(buffer), buffer, NULL);
#else
clGetDeviceInfo(device_ids[i], CL_DEVICE_NAME, sizeof(buffer), buffer, NULL);
#endif
if (buffer[0] != '\0')
hwloc_obj_add_info(osdev, "GPUModel", buffer);
snprintf(buffer, sizeof(buffer), "%u", j);
hwloc_obj_add_info(osdev, "OpenCLPlatformIndex", buffer);
buffer[0] = '\0';
clret = clGetDeviceInfo(device_ids[i], CL_DEVICE_PLATFORM, sizeof(platform_id), &platform_id, NULL);
if (CL_SUCCESS == clret) {
clGetPlatformInfo(platform_id, CL_PLATFORM_NAME, sizeof(buffer), buffer, NULL);
if (buffer[0] != '\0')
hwloc_obj_add_info(osdev, "OpenCLPlatformName", buffer);
}
snprintf(buffer, sizeof(buffer), "%u", i);
hwloc_obj_add_info(osdev, "OpenCLPlatformDeviceIndex", buffer);
clGetDeviceInfo(device_ids[i], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(computeunits), &computeunits, NULL);
snprintf(buffer, sizeof(buffer), "%u", computeunits);
hwloc_obj_add_info(osdev, "OpenCLComputeUnits", buffer);
clGetDeviceInfo(device_ids[i], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(globalmemsize), &globalmemsize, NULL);
snprintf(buffer, sizeof(buffer), "%llu", (unsigned long long) globalmemsize / 1024);
hwloc_obj_add_info(osdev, "OpenCLGlobalMemorySize", buffer);
parent = NULL;
#ifdef CL_DEVICE_TOPOLOGY_AMD
parent = hwloc_pci_belowroot_find_by_busid(topology, 0, amdtopo.pcie.bus, amdtopo.pcie.device, amdtopo.pcie.function);
if (!parent)
parent = hwloc_pci_find_busid_parent(topology, 0, amdtopo.pcie.bus, amdtopo.pcie.device, amdtopo.pcie.function);
#endif
if (!parent)
parent = hwloc_get_root_obj(topology);
hwloc_insert_object_by_parent(topology, parent, osdev);
}
free(device_ids);
}
free(platform_ids);
return 0;
}
static struct hwloc_backend *
hwloc_opencl_component_instantiate(struct hwloc_disc_component *component,
const void *_data1 __hwloc_attribute_unused,
const void *_data2 __hwloc_attribute_unused,
const void *_data3 __hwloc_attribute_unused)
{
struct hwloc_backend *backend;
backend = hwloc_backend_alloc(component);
if (!backend)
return NULL;
backend->discover = hwloc_opencl_discover;
return backend;
}
static struct hwloc_disc_component hwloc_opencl_disc_component = {
HWLOC_DISC_COMPONENT_TYPE_MISC,
"opencl",
HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
hwloc_opencl_component_instantiate,
10, /* after pci */
NULL
};
static int
hwloc_opencl_component_init(unsigned long flags)
{
if (flags)
return -1;
if (hwloc_plugin_check_namespace("opencl", "hwloc_backend_alloc") < 0)
return -1;
return 0;
}
#ifdef HWLOC_INSIDE_PLUGIN
HWLOC_DECLSPEC extern const struct hwloc_component hwloc_opencl_component;
#endif
const struct hwloc_component hwloc_opencl_component = {
HWLOC_COMPONENT_ABI,
hwloc_opencl_component_init, NULL,
HWLOC_COMPONENT_TYPE_DISC,
0,
&hwloc_opencl_disc_component
};

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

@ -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 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 cannot have several package levels\n");
errno = EINVAL;
return -1;
}
if (type_count[HWLOC_OBJ_NUMANODE] > 1) {
if (verbose)
fprintf(stderr, "Synthetic string cannot have several NUMA node levels\n");
errno = EINVAL;
return -1;
}
if (nb_machine_levels > 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;
}
@ -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

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

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

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

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

3808
opal/mca/hwloc/hwloc2a/hwloc/hwloc/topology.c Обычный файл

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

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

@ -0,0 +1,553 @@
/*
* Copyright © 2009 CNRS
* Copyright © 2009-2017 Inria. All rights reserved.
* Copyright © 2009-2010 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
#include <private/autogen/config.h>
#include <hwloc.h>
#include <private/private.h>
#include <private/misc.h>
#include <private/debug.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif /* HAVE_STRINGS_H */
int
hwloc_get_type_depth (struct hwloc_topology *topology, hwloc_obj_type_t type)
{
return topology->type_depth[type];
}
hwloc_obj_type_t
hwloc_get_depth_type (hwloc_topology_t topology, unsigned depth)
{
if (depth >= topology->nb_levels)
switch (depth) {
case HWLOC_TYPE_DEPTH_BRIDGE:
return HWLOC_OBJ_BRIDGE;
case HWLOC_TYPE_DEPTH_PCI_DEVICE:
return HWLOC_OBJ_PCI_DEVICE;
case HWLOC_TYPE_DEPTH_OS_DEVICE:
return HWLOC_OBJ_OS_DEVICE;
case HWLOC_TYPE_DEPTH_MISC:
return HWLOC_OBJ_MISC;
default:
return HWLOC_OBJ_TYPE_NONE;
}
return topology->levels[depth][0]->type;
}
unsigned
hwloc_get_nbobjs_by_depth (struct hwloc_topology *topology, unsigned depth)
{
if (depth >= topology->nb_levels) {
unsigned l = HWLOC_SLEVEL_FROM_DEPTH(depth);
if (l < HWLOC_NR_SLEVELS)
return topology->slevels[l].nbobjs;
else
return 0;
}
return topology->level_nbobjects[depth];
}
struct hwloc_obj *
hwloc_get_obj_by_depth (struct hwloc_topology *topology, unsigned depth, unsigned idx)
{
if (depth >= topology->nb_levels) {
unsigned l = HWLOC_SLEVEL_FROM_DEPTH(depth);
if (l < HWLOC_NR_SLEVELS)
return idx < topology->slevels[l].nbobjs ? topology->slevels[l].objs[idx] : NULL;
else
return NULL;
}
if (idx >= topology->level_nbobjects[depth])
return NULL;
return topology->levels[depth][idx];
}
unsigned hwloc_get_closest_objs (struct hwloc_topology *topology, struct hwloc_obj *src, struct hwloc_obj **objs, unsigned max)
{
struct hwloc_obj *parent, *nextparent, **src_objs;
int i,src_nbobjects;
unsigned stored = 0;
if (!src->cpuset)
return 0;
src_nbobjects = topology->level_nbobjects[src->depth];
src_objs = topology->levels[src->depth];
parent = src;
while (stored < max) {
while (1) {
nextparent = parent->parent;
if (!nextparent)
goto out;
if (!hwloc_bitmap_isequal(parent->cpuset, nextparent->cpuset))
break;
parent = nextparent;
}
/* traverse src's objects and find those that are in nextparent and were not in parent */
for(i=0; i<src_nbobjects; i++) {
if (hwloc_bitmap_isincluded(src_objs[i]->cpuset, nextparent->cpuset)
&& !hwloc_bitmap_isincluded(src_objs[i]->cpuset, parent->cpuset)) {
objs[stored++] = src_objs[i];
if (stored == max)
goto out;
}
}
parent = nextparent;
}
out:
return stored;
}
static int
hwloc__get_largest_objs_inside_cpuset (struct hwloc_obj *current, hwloc_const_bitmap_t set,
struct hwloc_obj ***res, int *max)
{
int gotten = 0;
unsigned i;
/* the caller must ensure this */
if (*max <= 0)
return 0;
if (hwloc_bitmap_isequal(current->cpuset, set)) {
**res = current;
(*res)++;
(*max)--;
return 1;
}
for (i=0; i<current->arity; i++) {
hwloc_bitmap_t subset;
int ret;
/* split out the cpuset part corresponding to this child and see if there's anything to do */
if (!hwloc_bitmap_intersects(set,current->children[i]->cpuset))
continue;
subset = hwloc_bitmap_dup(set);
hwloc_bitmap_and(subset, subset, current->children[i]->cpuset);
ret = hwloc__get_largest_objs_inside_cpuset (current->children[i], subset, res, max);
gotten += ret;
hwloc_bitmap_free(subset);
/* if no more room to store remaining objects, return what we got so far */
if (!*max)
break;
}
return gotten;
}
int
hwloc_get_largest_objs_inside_cpuset (struct hwloc_topology *topology, hwloc_const_bitmap_t set,
struct hwloc_obj **objs, int max)
{
struct hwloc_obj *current = topology->levels[0][0];
if (!hwloc_bitmap_isincluded(set, current->cpuset))
return -1;
if (max <= 0)
return 0;
return hwloc__get_largest_objs_inside_cpuset (current, set, &objs, &max);
}
const char *
hwloc_type_name (hwloc_obj_type_t obj)
{
switch (obj)
{
case HWLOC_OBJ_SYSTEM: return "System";
case HWLOC_OBJ_MACHINE: return "Machine";
case HWLOC_OBJ_MISC: return "Misc";
case HWLOC_OBJ_GROUP: return "Group";
case HWLOC_OBJ_NUMANODE: return "NUMANode";
case HWLOC_OBJ_PACKAGE: return "Package";
case HWLOC_OBJ_L1CACHE: return "L1Cache";
case HWLOC_OBJ_L2CACHE: return "L2Cache";
case HWLOC_OBJ_L3CACHE: return "L3Cache";
case HWLOC_OBJ_L4CACHE: return "L4Cache";
case HWLOC_OBJ_L5CACHE: return "L5Cache";
case HWLOC_OBJ_L1ICACHE: return "L1iCache";
case HWLOC_OBJ_L2ICACHE: return "L2iCache";
case HWLOC_OBJ_L3ICACHE: return "L3iCache";
case HWLOC_OBJ_CORE: return "Core";
case HWLOC_OBJ_BRIDGE: return "Bridge";
case HWLOC_OBJ_PCI_DEVICE: return "PCIDev";
case HWLOC_OBJ_OS_DEVICE: return "OSDev";
case HWLOC_OBJ_PU: return "PU";
default: return "Unknown";
}
}
int
hwloc_type_sscanf(const char *string, hwloc_obj_type_t *typep,
union hwloc_obj_attr_u *attrp, size_t attrsize)
{
hwloc_obj_type_t type = (hwloc_obj_type_t) -1;
unsigned depthattr = (unsigned) -1;
hwloc_obj_cache_type_t cachetypeattr = (hwloc_obj_cache_type_t) -1; /* unspecified */
hwloc_obj_bridge_type_t ubtype = (hwloc_obj_bridge_type_t) -1;
hwloc_obj_osdev_type_t ostype = (hwloc_obj_osdev_type_t) -1;
char *end;
/* never match the ending \0 since we want to match things like core:2 too.
* just use hwloc_strncasecmp() everywhere.
*/
/* types without a custom depth */
if (!hwloc_strncasecmp(string, "system", 2)) {
type = HWLOC_OBJ_SYSTEM;
} else if (!hwloc_strncasecmp(string, "machine", 2)) {
type = HWLOC_OBJ_MACHINE;
} else if (!hwloc_strncasecmp(string, "node", 2)
|| !hwloc_strncasecmp(string, "numa", 2)) { /* matches node and numanode */
type = HWLOC_OBJ_NUMANODE;
} else if (!hwloc_strncasecmp(string, "package", 2)
|| !hwloc_strncasecmp(string, "socket", 2)) { /* backward compat with v1.10 */
type = HWLOC_OBJ_PACKAGE;
} else if (!hwloc_strncasecmp(string, "core", 2)) {
type = HWLOC_OBJ_CORE;
} else if (!hwloc_strncasecmp(string, "pu", 2)) {
type = HWLOC_OBJ_PU;
} else if (!hwloc_strncasecmp(string, "misc", 4)) {
type = HWLOC_OBJ_MISC;
} else if (!hwloc_strncasecmp(string, "bridge", 4)) {
type = HWLOC_OBJ_BRIDGE;
} else if (!hwloc_strncasecmp(string, "hostbridge", 6)) {
type = HWLOC_OBJ_BRIDGE;
ubtype = HWLOC_OBJ_BRIDGE_HOST;
} else if (!hwloc_strncasecmp(string, "pcibridge", 5)) {
type = HWLOC_OBJ_BRIDGE;
ubtype = HWLOC_OBJ_BRIDGE_PCI;
} else if (!hwloc_strncasecmp(string, "pci", 3)) {
type = HWLOC_OBJ_PCI_DEVICE;
} else if (!hwloc_strncasecmp(string, "os", 2)) {
type = HWLOC_OBJ_OS_DEVICE;
} else if (!hwloc_strncasecmp(string, "bloc", 4)) {
type = HWLOC_OBJ_OS_DEVICE;
ostype = HWLOC_OBJ_OSDEV_BLOCK;
} else if (!hwloc_strncasecmp(string, "net", 3)) {
type = HWLOC_OBJ_OS_DEVICE;
ostype = HWLOC_OBJ_OSDEV_NETWORK;
} else if (!hwloc_strncasecmp(string, "openfab", 7)) {
type = HWLOC_OBJ_OS_DEVICE;
ostype = HWLOC_OBJ_OSDEV_OPENFABRICS;
} else if (!hwloc_strncasecmp(string, "dma", 3)) {
type = HWLOC_OBJ_OS_DEVICE;
ostype = HWLOC_OBJ_OSDEV_DMA;
} else if (!hwloc_strncasecmp(string, "gpu", 3)) {
type = HWLOC_OBJ_OS_DEVICE;
ostype = HWLOC_OBJ_OSDEV_GPU;
} else if (!hwloc_strncasecmp(string, "copro", 5)
|| !hwloc_strncasecmp(string, "co-pro", 6)) {
type = HWLOC_OBJ_OS_DEVICE;
ostype = HWLOC_OBJ_OSDEV_COPROC;
/* types with depthattr */
} else if ((string[0] == 'l' || string[0] == 'L') && string[1] >= '0' && string[1] <= '9') {
depthattr = strtol(string+1, &end, 10);
if (*end == 'i') {
if (depthattr >= 1 && depthattr <= 3) {
type = HWLOC_OBJ_L1ICACHE + depthattr-1;
cachetypeattr = HWLOC_OBJ_CACHE_INSTRUCTION;
} else
return -1;
} else {
if (depthattr >= 1 && depthattr <= 5) {
type = HWLOC_OBJ_L1CACHE + depthattr-1;
cachetypeattr = *end == 'd' ? HWLOC_OBJ_CACHE_DATA : HWLOC_OBJ_CACHE_UNIFIED;
} else
return -1;
}
} else if (!hwloc_strncasecmp(string, "group", 2)) {
size_t length;
type = HWLOC_OBJ_GROUP;
length = strcspn(string, "0123456789");
if (length <= 5 && !hwloc_strncasecmp(string, "group", length)
&& string[length] >= '0' && string[length] <= '9') {
depthattr = strtol(string+length, &end, 10);
}
} else
return -1;
*typep = type;
if (attrp) {
if (hwloc_obj_type_is_cache(type) && attrsize >= sizeof(attrp->cache)) {
attrp->cache.depth = depthattr;
attrp->cache.type = cachetypeattr;
} else if (type == HWLOC_OBJ_GROUP && attrsize >= sizeof(attrp->group)) {
attrp->group.depth = depthattr;
} else if (type == HWLOC_OBJ_BRIDGE && attrsize >= sizeof(attrp->bridge)) {
attrp->bridge.upstream_type = ubtype;
attrp->bridge.downstream_type = HWLOC_OBJ_BRIDGE_PCI; /* nothing else so far */
} else if (type == HWLOC_OBJ_OS_DEVICE && attrsize >= sizeof(attrp->osdev)) {
attrp->osdev.type = ostype;
}
}
return 0;
}
int
hwloc_type_sscanf_as_depth(const char *string, hwloc_obj_type_t *typep,
hwloc_topology_t topology, int *depthp)
{
union hwloc_obj_attr_u attr;
hwloc_obj_type_t type;
int depth;
int err;
err = hwloc_type_sscanf(string, &type, &attr, sizeof(attr));
if (err < 0)
return err;
depth = hwloc_get_type_depth(topology, type);
if (type == HWLOC_OBJ_GROUP
&& depth == HWLOC_TYPE_DEPTH_MULTIPLE
&& attr.group.depth != (unsigned)-1) {
unsigned l;
depth = HWLOC_TYPE_DEPTH_UNKNOWN;
for(l=0; l<topology->nb_levels; l++) {
if (topology->levels[l][0]->type == HWLOC_OBJ_GROUP
&& topology->levels[l][0]->attr->group.depth == attr.group.depth) {
depth = l;
break;
}
}
}
if (typep)
*typep = type;
*depthp = (unsigned) depth;
return 0;
}
static const char* hwloc_obj_cache_type_letter(hwloc_obj_cache_type_t type)
{
switch (type) {
case HWLOC_OBJ_CACHE_UNIFIED: return "";
case HWLOC_OBJ_CACHE_DATA: return "d";
case HWLOC_OBJ_CACHE_INSTRUCTION: return "i";
default: return "unknown";
}
}
int
hwloc_obj_type_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, int verbose)
{
hwloc_obj_type_t type = obj->type;
switch (type) {
case HWLOC_OBJ_MISC:
case HWLOC_OBJ_SYSTEM:
case HWLOC_OBJ_MACHINE:
case HWLOC_OBJ_NUMANODE:
case HWLOC_OBJ_PACKAGE:
case HWLOC_OBJ_CORE:
case HWLOC_OBJ_PU:
return hwloc_snprintf(string, size, "%s", hwloc_type_name(type));
case HWLOC_OBJ_L1CACHE:
case HWLOC_OBJ_L2CACHE:
case HWLOC_OBJ_L3CACHE:
case HWLOC_OBJ_L4CACHE:
case HWLOC_OBJ_L5CACHE:
case HWLOC_OBJ_L1ICACHE:
case HWLOC_OBJ_L2ICACHE:
case HWLOC_OBJ_L3ICACHE:
return hwloc_snprintf(string, size, "L%u%s%s", obj->attr->cache.depth,
hwloc_obj_cache_type_letter(obj->attr->cache.type),
verbose ? "Cache" : "");
case HWLOC_OBJ_GROUP:
if (obj->attr->group.depth != (unsigned) -1)
return hwloc_snprintf(string, size, "%s%u", hwloc_type_name(type), obj->attr->group.depth);
else
return hwloc_snprintf(string, size, "%s", hwloc_type_name(type));
case HWLOC_OBJ_BRIDGE:
return snprintf(string, size, obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI ? "PCIBridge" : "HostBridge");
case HWLOC_OBJ_PCI_DEVICE:
return hwloc_snprintf(string, size, "PCI");
case HWLOC_OBJ_OS_DEVICE:
switch (obj->attr->osdev.type) {
case HWLOC_OBJ_OSDEV_BLOCK: return hwloc_snprintf(string, size, "Block");
case HWLOC_OBJ_OSDEV_NETWORK: return hwloc_snprintf(string, size, verbose ? "Network" : "Net");
case HWLOC_OBJ_OSDEV_OPENFABRICS: return hwloc_snprintf(string, size, "OpenFabrics");
case HWLOC_OBJ_OSDEV_DMA: return hwloc_snprintf(string, size, "DMA");
case HWLOC_OBJ_OSDEV_GPU: return hwloc_snprintf(string, size, "GPU");
case HWLOC_OBJ_OSDEV_COPROC: return hwloc_snprintf(string, size, verbose ? "Co-Processor" : "CoProc");
default:
if (size > 0)
*string = '\0';
return 0;
}
break;
default:
if (size > 0)
*string = '\0';
return 0;
}
}
int
hwloc_obj_attr_snprintf(char * __hwloc_restrict string, size_t size, hwloc_obj_t obj, const char * separator, int verbose)
{
const char *prefix = "";
char *tmp = string;
ssize_t tmplen = size;
int ret = 0;
int res;
/* make sure we output at least an empty string */
if (size)
*string = '\0';
/* print memory attributes */
res = 0;
if (verbose) {
if (obj->memory.local_memory)
res = hwloc_snprintf(tmp, tmplen, "%slocal=%lu%s%stotal=%lu%s",
prefix,
(unsigned long) hwloc_memory_size_printf_value(obj->memory.local_memory, verbose),
hwloc_memory_size_printf_unit(obj->memory.total_memory, verbose),
separator,
(unsigned long) hwloc_memory_size_printf_value(obj->memory.total_memory, verbose),
hwloc_memory_size_printf_unit(obj->memory.local_memory, verbose));
else if (obj->memory.total_memory)
res = hwloc_snprintf(tmp, tmplen, "%stotal=%lu%s",
prefix,
(unsigned long) hwloc_memory_size_printf_value(obj->memory.total_memory, verbose),
hwloc_memory_size_printf_unit(obj->memory.total_memory, verbose));
} else {
if (obj->memory.local_memory)
res = hwloc_snprintf(tmp, tmplen, "%s%lu%s",
prefix,
(unsigned long) hwloc_memory_size_printf_value(obj->memory.local_memory, verbose),
hwloc_memory_size_printf_unit(obj->memory.local_memory, verbose));
}
if (res < 0)
return -1;
ret += res;
if (ret > 0)
prefix = separator;
if (res >= tmplen)
res = tmplen>0 ? (int)tmplen - 1 : 0;
tmp += res;
tmplen -= res;
/* printf type-specific attributes */
res = 0;
switch (obj->type) {
case HWLOC_OBJ_L1CACHE:
case HWLOC_OBJ_L2CACHE:
case HWLOC_OBJ_L3CACHE:
case HWLOC_OBJ_L4CACHE:
case HWLOC_OBJ_L5CACHE:
case HWLOC_OBJ_L1ICACHE:
case HWLOC_OBJ_L2ICACHE:
case HWLOC_OBJ_L3ICACHE:
if (verbose) {
char assoc[32];
if (obj->attr->cache.associativity == -1)
snprintf(assoc, sizeof(assoc), "%sfully-associative", separator);
else if (obj->attr->cache.associativity == 0)
*assoc = '\0';
else
snprintf(assoc, sizeof(assoc), "%sways=%d", separator, obj->attr->cache.associativity);
res = hwloc_snprintf(tmp, tmplen, "%ssize=%lu%s%slinesize=%u%s",
prefix,
(unsigned long) hwloc_memory_size_printf_value(obj->attr->cache.size, verbose),
hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose),
separator, obj->attr->cache.linesize,
assoc);
} else
res = hwloc_snprintf(tmp, tmplen, "%s%lu%s",
prefix,
(unsigned long) hwloc_memory_size_printf_value(obj->attr->cache.size, verbose),
hwloc_memory_size_printf_unit(obj->attr->cache.size, verbose));
break;
case HWLOC_OBJ_BRIDGE:
if (verbose) {
char up[128], down[64];
/* upstream is PCI or HOST */
if (obj->attr->bridge.upstream_type == HWLOC_OBJ_BRIDGE_PCI) {
char linkspeed[64]= "";
if (obj->attr->pcidev.linkspeed)
snprintf(linkspeed, sizeof(linkspeed), "%slink=%.2fGB/s", separator, obj->attr->pcidev.linkspeed);
snprintf(up, sizeof(up), "busid=%04x:%02x:%02x.%01x%sid=%04x:%04x%sclass=%04x(%s)%s",
obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func, separator,
obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id, separator,
obj->attr->pcidev.class_id, hwloc_pci_class_string(obj->attr->pcidev.class_id), linkspeed);
} else
*up = '\0';
/* downstream is_PCI */
snprintf(down, sizeof(down), "buses=%04x:[%02x-%02x]",
obj->attr->bridge.downstream.pci.domain, obj->attr->bridge.downstream.pci.secondary_bus, obj->attr->bridge.downstream.pci.subordinate_bus);
if (*up)
res = snprintf(string, size, "%s%s%s", up, separator, down);
else
res = snprintf(string, size, "%s", down);
}
break;
case HWLOC_OBJ_PCI_DEVICE:
if (verbose) {
char linkspeed[64]= "";
if (obj->attr->pcidev.linkspeed)
snprintf(linkspeed, sizeof(linkspeed), "%slink=%.2fGB/s", separator, obj->attr->pcidev.linkspeed);
res = snprintf(string, size, "busid=%04x:%02x:%02x.%01x%sid=%04x:%04x%sclass=%04x(%s)%s",
obj->attr->pcidev.domain, obj->attr->pcidev.bus, obj->attr->pcidev.dev, obj->attr->pcidev.func, separator,
obj->attr->pcidev.vendor_id, obj->attr->pcidev.device_id, separator,
obj->attr->pcidev.class_id, hwloc_pci_class_string(obj->attr->pcidev.class_id), linkspeed);
}
break;
default:
break;
}
if (res < 0)
return -1;
ret += res;
if (ret > 0)
prefix = separator;
if (res >= tmplen)
res = tmplen>0 ? (int)tmplen - 1 : 0;
tmp += res;
tmplen -= res;
/* printf infos */
if (verbose) {
unsigned i;
for(i=0; i<obj->infos_count; i++) {
if (strchr(obj->infos[i].value, ' '))
res = hwloc_snprintf(tmp, tmplen, "%s%s=\"%s\"",
prefix,
obj->infos[i].name, obj->infos[i].value);
else
res = hwloc_snprintf(tmp, tmplen, "%s%s=%s",
prefix,
obj->infos[i].name, obj->infos[i].value);
if (res < 0)
return -1;
ret += res;
if (res >= tmplen)
res = tmplen>0 ? (int)tmplen - 1 : 0;
tmp += res;
tmplen -= res;
if (ret > 0)
prefix = separator;
}
}
return ret;
}

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

@ -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().
*/

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

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

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

@ -0,0 +1,223 @@
/*
* Copyright © 2010-2017 Inria. All rights reserved.
* See COPYING in top-level directory.
*/
/** \file
* \brief Object distances.
*/
#ifndef HWLOC_DISTANCES_H
#define HWLOC_DISTANCES_H
#ifndef HWLOC_H
#error Please include the main hwloc.h instead
#endif
#ifdef __cplusplus
extern "C" {
#elif 0
}
#endif
/** \defgroup hwlocality_distances_get Retrieve distances between objects
* @{
*/
/** \brief Matrix of distances between a set of objects.
*
* This matrix often contains latencies between NUMA nodes
* (as reported in the System Locality Distance Information Table (SLIT)
* in the ACPI specification), which may or may not be physically accurate.
* It corresponds to the latency for accessing the memory of one node
* from a core in another node.
* The corresponding kind is ::HWLOC_DISTANCES_KIND_FROM_OS | ::HWLOC_DISTANCES_KIND_FROM_USER.
*
* The matrix may also contain bandwidths between random sets of objects,
* possibly provided by the user, as specified in the \p kind attribute.
*/
struct hwloc_distances_s {
unsigned nbobjs; /**< \brief Number of objects described by the distance matrix. */
hwloc_obj_t *objs; /**< \brief Array of objects described by the distance matrix. */
unsigned long kind; /**< \brief OR'ed set of ::hwloc_distances_kind_e. */
hwloc_uint64_t *values; /**< \brief Matrix of distances between objects, stored as a one-dimension array.
*
* Distance from i-th to j-th object is stored in slot i*nbobjs+j.
* The meaning of the value depends on the \p kind attribute.
*/
};
/** \brief Kinds of distance matrices.
*
* The \p kind attribute of struct hwloc_distances_s is a OR'ed set
* of kinds.
*
* A kind of format HWLOC_DISTANCES_KIND_FROM_* specifies where the
* distance information comes from, if known.
*
* A kind of format HWLOC_DISTANCES_KIND_MEANS_* specifies whether
* values are latencies or bandwidths, if applicable.
*/
enum hwloc_distances_kind_e {
/** \brief These distances were obtained from the operating system or hardware.
* \hideinitializer
*/
HWLOC_DISTANCES_KIND_FROM_OS = (1UL<<0),
/** \brief These distances were provided by the user.
* \hideinitializer
*/
HWLOC_DISTANCES_KIND_FROM_USER = (1UL<<1),
/** \brief Distance values are similar to latencies between objects.
* Values are smaller for closer objects, hence minimal on the diagonal
* of the matrix (distance between an object and itself).
* It could also be the number of network hops between objects, etc.
* \hideinitializer
*/
HWLOC_DISTANCES_KIND_MEANS_LATENCY = (1UL<<2),
/** \brief Distance values are similar to bandwidths between objects.
* Values are higher for closer objects, hence maximal on the diagonal
* of the matrix (distance between an object and itself).
* Such values are currently ignored for distance-based grouping.
* \hideinitializer
*/
HWLOC_DISTANCES_KIND_MEANS_BANDWIDTH = (1UL<<3)
};
/** \brief Retrieve distance matrices.
*
* Retrieve distance matrices from the topology into the \p distances array.
*
* \p flags is currently unused, should be \c 0.
*
* \p kind serves as a filter. If \c 0, all distance matrices are returned.
* If it contains some HWLOC_DISTANCES_KIND_FROM_*, only distances whose kind
* matches one of these are returned.
* If it contains some HWLOC_DISTANCES_KIND_MEANS_*, only distances whose kind
* matches one of these are returned.
*
* On input, \p nr points to the number of distances that may be stored in \p distances.
* On output, \p nr points to the number of distances that were actually found,
* even if some of them couldn't be stored in \p distances.
* Distances that couldn't be stored are ignored, but the function still returns
* success (\c 0). The caller may find out by comparing the value pointed by \p nr
* before and after the function call.
*
* Each distance structure returned in the \p distances array should be released
* by the caller using hwloc_distances_release().
*/
HWLOC_DECLSPEC int
hwloc_distances_get(hwloc_topology_t topology,
unsigned *nr, struct hwloc_distances_s **distances,
unsigned long kind, unsigned long flags);
/** \brief Retrieve distance matrices for object at a specific depth in the topology.
*
* Identical to hwloc_distances_get() with the additional \p depth filter.
*/
HWLOC_DECLSPEC int
hwloc_distances_get_by_depth(hwloc_topology_t topology, unsigned depth,
unsigned *nr, struct hwloc_distances_s **distances,
unsigned long kind, unsigned long flags);
/** \brief Retrieve distance matrices for object of a specific type.
*
* Identical to hwloc_distances_get() with the additional \p type filter.
*/
static __hwloc_inline int
hwloc_distances_get_by_type(hwloc_topology_t topology, hwloc_obj_type_t type,
unsigned *nr, struct hwloc_distances_s **distances,
unsigned long kind, unsigned long flags)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth < 0) {
*nr = 0;
return 0;
}
return hwloc_distances_get_by_depth(topology, depth, nr, distances, kind, flags);
}
/** \brief Release a distance structure previously returned by hwloc_distances_get(). */
HWLOC_DECLSPEC void
hwloc_distances_release(hwloc_topology_t topology, struct hwloc_distances_s *distances);
/** @} */
/** \defgroup hwlocality_distances_add Add or remove distances between objects
* @{
*/
/** \brief Flags for adding a new distances to a topology. */
enum hwloc_distances_flag_e {
/** \brief Try to group objects based on the newly provided distance information.
* \hideinitializer
*/
HWLOC_DISTANCES_FLAG_GROUP = (1UL<<0),
/** \brief If grouping, consider the distance values as inaccurate and relax the
* comparisons during the grouping algorithms. The actual accuracy may be modified
* through the HWLOC_GROUPING_ACCURACY environment variable (see \ref envvar).
* \hideinitializer
*/
HWLOC_DISTANCES_FLAG_GROUP_INACCURATE = (1UL<<1)
};
/** \brief Provide a distance matrix.
*
* Provide the matrix of distances between a set of objects given by \p nbobjs
* and the \p objs array. \p nbobjs must be at least 2.
* The distances are stored as a one-dimension array in \p values.
* The distance from object i to object j is in slot i*nbobjs+j.
*
* \p kind specifies the kind of distance as a OR'ed set of ::hwloc_distances_kind_e.
*
* \p flags configures the behavior of the function using an optional OR'ed set of
* ::hwloc_distances_flag_e.
*
* Objects must be of the same type. They cannot be of type Group.
*/
HWLOC_DECLSPEC int hwloc_distances_add(hwloc_topology_t topology,
unsigned nbobjs, hwloc_obj_t *objs, hwloc_uint64_t *values,
unsigned long kind, unsigned long flags);
/** \brief Remove all distance matrices from a topology.
*
* Remove all distance matrices, either provided by the user or
* gathered through the OS.
*
* If these distances were used to group objects, these additional
*Group objects are not removed from the topology.
*/
HWLOC_DECLSPEC int hwloc_distances_remove(hwloc_topology_t topology);
/** \brief Remove distance matrices for objects at a specific depth in the topology.
*
* Identical to hwloc_distances_remove() but only applies to one level of the topology.
*/
HWLOC_DECLSPEC int hwloc_distances_remove_by_depth(hwloc_topology_t topology, unsigned depth);
/** \brief Remove distance matrices for objects of a specific type in the topology.
*
* Identical to hwloc_distances_remove() but only applies to one level of the topology.
*/
static __hwloc_inline int
hwloc_distances_remove_by_type(hwloc_topology_t topology, hwloc_obj_type_t type)
{
int depth = hwloc_get_type_depth(topology, type);
if (depth < 0)
return 0;
return hwloc_distances_remove_by_depth(topology, depth);
}
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* HWLOC_DISTANCES_H */

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

@ -0,0 +1,236 @@
/*
* Copyright © 2009-2016 Inria. All rights reserved.
* Copyright © 2009-2012 Université Bordeaux
* Copyright © 2009-2011 Cisco Systems, Inc. All rights reserved.
* See COPYING in top-level directory.
*/
/** \file
* \brief Exporting Topologies to XML or to Synthetic strings.
*/
#ifndef HWLOC_EXPORT_H
#define HWLOC_EXPORT_H
#ifndef HWLOC_H
#error Please include the main hwloc.h instead
#endif
#ifdef __cplusplus
extern "C" {
#elif 0
}
#endif
/** \defgroup hwlocality_xmlexport Exporting Topologies to XML
* @{
*/
/** \brief Flags for exporting XML topologies.
*
* Flags to be given as a OR'ed set to hwloc_topology_export_xml().
*/
enum hwloc_topology_export_xml_flags_e {
/** \brief Export XML that is loadable by hwloc v1.x.
* \hideinitializer
*/
HWLOC_TOPOLOGY_EXPORT_XML_FLAG_V1 = (1UL<<0)
};
/** \brief Export the topology into an XML file.
*
* This file may be loaded later through hwloc_topology_set_xml().
*
* \p flags is a OR'ed set of ::hwloc_topology_export_xml_flags_e.
*
* \return -1 if a failure occured.
*
* \note See also hwloc_topology_set_userdata_export_callback()
* for exporting application-specific object userdata.
*
* \note The topology-specific userdata pointer is ignored when exporting to XML.
*
* \note Only printable characters may be exported to XML string attributes.
* Any other character, especially any non-ASCII character, will be silently
* dropped.
*
* \note If \p name is "-", the XML output is sent to the standard output.
*/
HWLOC_DECLSPEC int hwloc_topology_export_xml(hwloc_topology_t topology, const char *xmlpath, unsigned long flags);
/** \brief Export the topology into a newly-allocated XML memory buffer.
*
* \p xmlbuffer is allocated by the callee and should be freed with
* hwloc_free_xmlbuffer() later in the caller.
*
* This memory buffer may be loaded later through hwloc_topology_set_xmlbuffer().
*
* \p flags is a OR'ed set of ::hwloc_topology_export_xml_flags_e.
*
* \return -1 if a failure occured.
*
* \note See also hwloc_topology_set_userdata_export_callback()
* for exporting application-specific object userdata.
*
* \note The topology-specific userdata pointer is ignored when exporting to XML.
*
* \note Only printable characters may be exported to XML string attributes.
* Any other character, especially any non-ASCII character, will be silently
* dropped.
*/
HWLOC_DECLSPEC int hwloc_topology_export_xmlbuffer(hwloc_topology_t topology, char **xmlbuffer, int *buflen, unsigned long flags);
/** \brief Free a buffer allocated by hwloc_topology_export_xmlbuffer() */
HWLOC_DECLSPEC void hwloc_free_xmlbuffer(hwloc_topology_t topology, char *xmlbuffer);
/** \brief Set the application-specific callback for exporting object userdata
*
* The object userdata pointer is not exported to XML by default because hwloc
* does not know what it contains.
*
* This function lets applications set \p export_cb to a callback function
* that converts this opaque userdata into an exportable string.
*
* \p export_cb is invoked during XML export for each object whose
* \p userdata pointer is not \c NULL.
* The callback should use hwloc_export_obj_userdata() or
* hwloc_export_obj_userdata_base64() to actually export
* something to XML (possibly multiple times per object).
*
* \p export_cb may be set to \c NULL if userdata should not be exported to XML.
*
* \note The topology-specific userdata pointer is ignored when exporting to XML.
*/
HWLOC_DECLSPEC void hwloc_topology_set_userdata_export_callback(hwloc_topology_t topology,
void (*export_cb)(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj));
/** \brief Export some object userdata to XML
*
* This function may only be called from within the export() callback passed
* to hwloc_topology_set_userdata_export_callback().
* It may be invoked one of multiple times to export some userdata to XML.
* The \p buffer content of length \p length is stored with optional name
* \p name.
*
* When importing this XML file, the import() callback (if set) will be
* called exactly as many times as hwloc_export_obj_userdata() was called
* during export(). It will receive the corresponding \p name, \p buffer
* and \p length arguments.
*
* \p reserved, \p topology and \p obj must be the first three parameters
* that were given to the export callback.
*
* Only printable characters may be exported to XML string attributes.
* If a non-printable character is passed in \p name or \p buffer,
* the function returns -1 with errno set to EINVAL.
*
* If exporting binary data, the application should first encode into
* printable characters only (or use hwloc_export_obj_userdata_base64()).
* It should also take care of portability issues if the export may
* be reimported on a different architecture.
*/
HWLOC_DECLSPEC int hwloc_export_obj_userdata(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length);
/** \brief Encode and export some object userdata to XML
*
* This function is similar to hwloc_export_obj_userdata() but it encodes
* the input buffer into printable characters before exporting.
* On import, decoding is automatically performed before the data is given
* to the import() callback if any.
*
* This function may only be called from within the export() callback passed
* to hwloc_topology_set_userdata_export_callback().
*
* The function does not take care of portability issues if the export
* may be reimported on a different architecture.
*/
HWLOC_DECLSPEC int hwloc_export_obj_userdata_base64(void *reserved, hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length);
/** \brief Set the application-specific callback for importing userdata
*
* On XML import, userdata is ignored by default because hwloc does not know
* how to store it in memory.
*
* This function lets applications set \p import_cb to a callback function
* that will get the XML-stored userdata and store it in the object as expected
* by the application.
*
* \p import_cb is called during hwloc_topology_load() as many times as
* hwloc_export_obj_userdata() was called during export. The topology
* is not entirely setup yet. Object attributes are ready to consult,
* but links between objects are not.
*
* \p import_cb may be \c NULL if userdata should be ignored during import.
*
* \note \p buffer contains \p length characters followed by a null byte ('\0').
*
* \note This function should be called before hwloc_topology_load().
*
* \note The topology-specific userdata pointer is ignored when importing from XML.
*/
HWLOC_DECLSPEC void hwloc_topology_set_userdata_import_callback(hwloc_topology_t topology,
void (*import_cb)(hwloc_topology_t topology, hwloc_obj_t obj, const char *name, const void *buffer, size_t length));
/** @} */
/** \defgroup hwlocality_syntheticexport Exporting Topologies to Synthetic
* @{
*/
/** \brief Flags for exporting synthetic topologies.
*
* Flags to be given as a OR'ed set to hwloc_topology_export_synthetic().
*/
enum hwloc_topology_export_synthetic_flags_e {
/** \brief Export extended types such as L2dcache as basic types such as Cache.
*
* This is required if loading the synthetic description with hwloc < 1.9.
* \hideinitializer
*/
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_EXTENDED_TYPES = (1UL<<0),
/** \brief Do not export level attributes.
*
* Ignore level attributes such as memory/cache sizes or PU indexes.
* This is required if loading the synthetic description with hwloc < 1.10.
* \hideinitializer
*/
HWLOC_TOPOLOGY_EXPORT_SYNTHETIC_FLAG_NO_ATTRS = (1UL<<1)
};
/** \brief Export the topology as a synthetic string.
*
* At most \p buflen characters will be written in \p buffer,
* including the terminating \0.
*
* This exported string may be given back to hwloc_topology_set_synthetic().
*
* \p flags is a OR'ed set of ::hwloc_topology_export_synthetic_flags_e.
*
* \return The number of characters that were written,
* not including the terminating \0.
*
* \return -1 if the topology could not be exported,
* for instance if it is not symmetric.
*
* \note I/O and Misc children are ignored, the synthetic string only
* describes normal children.
*
* \note A 1024-byte buffer should be large enough for exporting
* topologies in the vast majority of cases.
*/
HWLOC_DECLSPEC int hwloc_topology_export_synthetic(hwloc_topology_t topology, char *buffer, size_t buflen, unsigned long flags);
/** @} */
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* HWLOC_EXPORT_H */

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

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

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