summaryrefslogtreecommitdiffstats
path: root/hwloc-1.2.1/src/topology-synthetic.c
diff options
context:
space:
mode:
Diffstat (limited to 'hwloc-1.2.1/src/topology-synthetic.c')
-rw-r--r--hwloc-1.2.1/src/topology-synthetic.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/hwloc-1.2.1/src/topology-synthetic.c b/hwloc-1.2.1/src/topology-synthetic.c
new file mode 100644
index 00000000..d716ea0b
--- /dev/null
+++ b/hwloc-1.2.1/src/topology-synthetic.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright © 2009 CNRS
+ * Copyright © 2009-2011 INRIA. All rights reserved.
+ * Copyright © 2009-2010 Université Bordeaux 1
+ * 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>
+
+#include <limits.h>
+#include <assert.h>
+#include <strings.h>
+
+/* Read from DESCRIPTION a series of integers describing a symmetrical
+ topology and update `topology->synthetic_description' accordingly. On
+ success, return zero. */
+int
+hwloc_backend_synthetic_init(struct hwloc_topology *topology, const char *description)
+{
+ 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;
+
+ assert(topology->backend_type == HWLOC_BACKEND_NONE);
+
+ 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;
+
+ while (*pos == ' ')
+ pos++;
+
+ if (!*pos)
+ break;
+
+ if (*pos < '0' || *pos > '9') {
+ if (!hwloc_namecoloncmp(pos, "machines", 2)) {
+ type = HWLOC_OBJ_MACHINE;
+ } else if (!hwloc_namecoloncmp(pos, "nodes", 1))
+ type = HWLOC_OBJ_NODE;
+ else if (!hwloc_namecoloncmp(pos, "sockets", 1))
+ type = HWLOC_OBJ_SOCKET;
+ else if (!hwloc_namecoloncmp(pos, "cores", 2))
+ type = HWLOC_OBJ_CORE;
+ else if (!hwloc_namecoloncmp(pos, "caches", 2))
+ type = HWLOC_OBJ_CACHE;
+ else if (!hwloc_namecoloncmp(pos, "pus", 1) || !hwloc_namecoloncmp(pos, "procs", 1) /* backward compatiblity with 0.9 */)
+ type = HWLOC_OBJ_PU;
+ else if (!hwloc_namecoloncmp(pos, "misc", 2))
+ type = HWLOC_OBJ_MISC;
+ else if (!hwloc_namecoloncmp(pos, "group", 2))
+ type = HWLOC_OBJ_GROUP;
+ else
+ fprintf(stderr, "Unknown object type `%s'\n", pos);
+
+ next_pos = strchr(pos, ':');
+ if (!next_pos) {
+ fprintf(stderr,"synthetic string doesn't have a `:' after object type at '%s'\n", pos);
+ errno = EINVAL;
+ return -1;
+ }
+ pos = next_pos + 1;
+ }
+ item = strtoul(pos, (char **)&next_pos, 0);
+ if (next_pos == pos) {
+ fprintf(stderr,"synthetic string doesn't have a number of objects at '%s'\n", pos);
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (count + 1 >= HWLOC_SYNTHETIC_MAX_DEPTH) {
+ fprintf(stderr,"Too many synthetic levels, max %d\n", HWLOC_SYNTHETIC_MAX_DEPTH);
+ errno = EINVAL;
+ return -1;
+ }
+ if (item > UINT_MAX) {
+ fprintf(stderr,"Too big arity, max %u\n", UINT_MAX);
+ errno = EINVAL;
+ return -1;
+ }
+
+ topology->backend_params.synthetic.arity[count-1] = (unsigned)item;
+ topology->backend_params.synthetic.type[count] = type;
+ count++;
+ }
+
+ if (count <= 0) {
+ fprintf(stderr,"synthetic string doesn't contain any object\n");
+ errno = EINVAL;
+ return -1;
+ }
+
+ for(i=count-1; i>0; i--) {
+ hwloc_obj_type_t type;
+
+ type = topology->backend_params.synthetic.type[i];
+
+ if (type == HWLOC_OBJ_TYPE_UNKNOWN) {
+ if (i == count-1)
+ type = HWLOC_OBJ_PU;
+ else {
+ switch (topology->backend_params.synthetic.type[i+1]) {
+ 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_SOCKET; break;
+ case HWLOC_OBJ_SOCKET: type = HWLOC_OBJ_NODE; break;
+ case HWLOC_OBJ_NODE:
+ case HWLOC_OBJ_GROUP: type = HWLOC_OBJ_GROUP; break;
+ case HWLOC_OBJ_MACHINE:
+ case HWLOC_OBJ_MISC: type = HWLOC_OBJ_MISC; break;
+ default:
+ assert(0);
+ }
+ }
+ topology->backend_params.synthetic.type[i] = type;
+ }
+ switch (type) {
+ case HWLOC_OBJ_PU:
+ if (nb_pu_levels) {
+ fprintf(stderr,"synthetic string can not have several PU levels\n");
+ errno = EINVAL;
+ return -1;
+ }
+ nb_pu_levels++;
+ break;
+ case HWLOC_OBJ_CACHE:
+ cache_depth++;
+ break;
+ case HWLOC_OBJ_GROUP:
+ group_depth++;
+ break;
+ case HWLOC_OBJ_NODE:
+ nb_node_levels++;
+ break;
+ case HWLOC_OBJ_MACHINE:
+ nb_machine_levels++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (nb_pu_levels > 1) {
+ fprintf(stderr,"synthetic string can not have several PU levels\n");
+ errno = EINVAL;
+ return -1;
+ }
+ if (nb_node_levels > 1) {
+ fprintf(stderr,"synthetic string can not have several NUMA node levels\n");
+ errno = EINVAL;
+ return -1;
+ }
+ if (nb_machine_levels > 1) {
+ fprintf(stderr,"synthetic string can not have several machine levels\n");
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (nb_machine_levels)
+ topology->backend_params.synthetic.type[0] = HWLOC_OBJ_SYSTEM;
+ else {
+ topology->backend_params.synthetic.type[0] = HWLOC_OBJ_MACHINE;
+ nb_machine_levels++;
+ }
+
+ if (cache_depth == 1)
+ /* if there is a single cache level, make it L2 */
+ cache_depth = 2;
+
+ for (i=0; i<count; i++) {
+ hwloc_obj_type_t type = topology->backend_params.synthetic.type[i];
+
+ if (type == HWLOC_OBJ_GROUP)
+ topology->backend_params.synthetic.depth[i] = group_depth--;
+ else if (type == HWLOC_OBJ_CACHE)
+ topology->backend_params.synthetic.depth[i] = cache_depth--;
+ }
+
+ topology->backend_type = HWLOC_BACKEND_SYNTHETIC;
+ topology->backend_params.synthetic.arity[count-1] = 0;
+ topology->is_thissystem = 0;
+
+ return 0;
+}
+
+void
+hwloc_backend_synthetic_exit(struct hwloc_topology *topology)
+{
+ assert(topology->backend_type == HWLOC_BACKEND_SYNTHETIC);
+ topology->backend_type = HWLOC_BACKEND_NONE;
+}
+
+/*
+ * Recursively build objects whose cpu start at first_cpu
+ * - level gives where to look in the type, arity and id arrays
+ * - the id array is used as a variable to get unique IDs for a given level.
+ * - generated memory should be added to *memory_kB.
+ * - generated cpus should be added to parent_cpuset.
+ * - next cpu number to be used should be returned.
+ */
+static unsigned
+hwloc__look_synthetic(struct hwloc_topology *topology,
+ int level, unsigned first_cpu,
+ hwloc_bitmap_t parent_cpuset)
+{
+ hwloc_obj_t obj;
+ unsigned i;
+ hwloc_obj_type_t type = topology->backend_params.synthetic.type[level];
+
+ /* pre-hooks */
+ switch (type) {
+ case HWLOC_OBJ_MISC:
+ break;
+ case HWLOC_OBJ_GROUP:
+ break;
+ case HWLOC_OBJ_SYSTEM:
+ /* Shouldn't happen. */
+ abort();
+ break;
+ case HWLOC_OBJ_MACHINE:
+ break;
+ case HWLOC_OBJ_NODE:
+ break;
+ case HWLOC_OBJ_SOCKET:
+ break;
+ case HWLOC_OBJ_CACHE:
+ break;
+ case HWLOC_OBJ_CORE:
+ break;
+ case HWLOC_OBJ_PU:
+ break;
+ case HWLOC_OBJ_TYPE_MAX:
+ /* Should never happen */
+ assert(0);
+ break;
+ }
+
+ obj = hwloc_alloc_setup_object(type, topology->backend_params.synthetic.id[level]++);
+ obj->cpuset = hwloc_bitmap_alloc();
+
+ if (!topology->backend_params.synthetic.arity[level]) {
+ hwloc_bitmap_set(obj->cpuset, first_cpu++);
+ } else {
+ for (i = 0; i < topology->backend_params.synthetic.arity[level]; i++)
+ first_cpu = hwloc__look_synthetic(topology, level + 1, first_cpu, obj->cpuset);
+ }
+
+ if (type == HWLOC_OBJ_NODE) {
+ obj->nodeset = hwloc_bitmap_alloc();
+ hwloc_bitmap_set(obj->nodeset, obj->os_index);
+ }
+
+ hwloc_bitmap_or(parent_cpuset, parent_cpuset, obj->cpuset);
+
+ /* post-hooks */
+ switch (type) {
+ case HWLOC_OBJ_MISC:
+ break;
+ case HWLOC_OBJ_GROUP:
+ obj->attr->group.depth = topology->backend_params.synthetic.depth[level];
+ break;
+ case HWLOC_OBJ_SYSTEM:
+ abort();
+ break;
+ case HWLOC_OBJ_MACHINE:
+ break;
+ case HWLOC_OBJ_NODE:
+ /* 1GB in memory nodes, 256k 4k-pages. */
+ obj->memory.local_memory = 1024*1024*1024;
+ obj->memory.page_types_len = 1;
+ obj->memory.page_types = malloc(sizeof(*obj->memory.page_types));
+ memset(obj->memory.page_types, 0, sizeof(*obj->memory.page_types));
+ obj->memory.page_types[0].size = 4096;
+ obj->memory.page_types[0].count = 256*1024;
+ break;
+ case HWLOC_OBJ_SOCKET:
+ break;
+ case HWLOC_OBJ_CACHE:
+ obj->attr->cache.depth = topology->backend_params.synthetic.depth[level];
+ obj->attr->cache.linesize = 64;
+ if (obj->attr->cache.depth == 1)
+ /* 32Kb in L1 */
+ obj->attr->cache.size = 32*1024;
+ else
+ /* *4 at each level, starting from 1MB for L2 */
+ obj->attr->cache.size = 256*1024 << (2*obj->attr->cache.depth);
+ break;
+ case HWLOC_OBJ_CORE:
+ break;
+ case HWLOC_OBJ_PU:
+ break;
+ case HWLOC_OBJ_TYPE_MAX:
+ /* Should never happen */
+ assert(0);
+ break;
+ }
+
+ hwloc_insert_object_by_cpuset(topology, obj);
+
+ return first_cpu;
+}
+
+void
+hwloc_look_synthetic(struct hwloc_topology *topology)
+{
+ hwloc_bitmap_t cpuset = hwloc_bitmap_alloc();
+ unsigned first_cpu = 0, i;
+
+ topology->support.discovery->pu = 1;
+
+ /* start with id=0 for each level */
+ for (i = 0; topology->backend_params.synthetic.arity[i] > 0; i++)
+ topology->backend_params.synthetic.id[i] = 0;
+ /* ... including the last one */
+ topology->backend_params.synthetic.id[i] = 0;
+
+ /* update first level type according to the synthetic type array */
+ topology->levels[0][0]->type = topology->backend_params.synthetic.type[0];
+
+ for (i = 0; i < topology->backend_params.synthetic.arity[0]; i++)
+ first_cpu = hwloc__look_synthetic(topology, 1, first_cpu, cpuset);
+
+ hwloc_bitmap_free(cpuset);
+
+ hwloc_add_object_info(topology->levels[0][0], "Backend", "Synthetic");
+}
+