diff options
Diffstat (limited to 'hwloc-1.2.1/src/topology-hpux.c')
-rw-r--r-- | hwloc-1.2.1/src/topology-hpux.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/hwloc-1.2.1/src/topology-hpux.c b/hwloc-1.2.1/src/topology-hpux.c new file mode 100644 index 00000000..2ca58c66 --- /dev/null +++ b/hwloc-1.2.1/src/topology-hpux.c @@ -0,0 +1,262 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2010 INRIA. All rights reserved. + * Copyright © 2009-2010 Université Bordeaux 1 + * Copyright © 2011 Cisco Systems, Inc. All rights reserved. + * See COPYING in top-level directory. + */ + +/* TODO: psets? (Only for root) + * since 11i 1.6: + _SC_PSET_SUPPORT + pset_create/destroy/assign/setattr + pset_ctl/getattr + pset_bind() + pthread_pset_bind_np() + */ + +#include <private/autogen/config.h> + +#include <sys/types.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +#include <hwloc.h> +#include <private/private.h> +#include <private/debug.h> + +#include <sys/mpctl.h> +#include <sys/mman.h> +#include <pthread.h> + +static ldom_t +hwloc_hpux_find_ldom(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set) +{ + int has_numa = sysconf(_SC_CCNUMA_SUPPORT) == 1; + hwloc_obj_t obj; + + if (!has_numa) + return -1; + + obj = hwloc_get_first_largest_obj_inside_cpuset(topology, hwloc_set); + if (!hwloc_bitmap_isequal(obj->cpuset, hwloc_set) || obj->type != HWLOC_OBJ_NODE) { + /* Does not correspond to exactly one node */ + return -1; + } + + return obj->os_index; +} + +static spu_t +hwloc_hpux_find_spu(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t hwloc_set) +{ + spu_t cpu; + + cpu = hwloc_bitmap_first(hwloc_set); + if (cpu != -1 && hwloc_bitmap_weight(hwloc_set) == 1) + return cpu; + return -1; +} + +/* Note: get_cpubind not available on HP-UX */ +static int +hwloc_hpux_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags) +{ + ldom_t ldom; + spu_t cpu; + + /* Drop previous binding */ + mpctl(MPC_SETLDOM, MPC_LDOMFLOAT, pid); + mpctl(MPC_SETPROCESS, MPC_SPUFLOAT, pid); + + if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) + return 0; + + ldom = hwloc_hpux_find_ldom(topology, hwloc_set); + if (ldom != -1) + return mpctl(MPC_SETLDOM, ldom, pid); + + cpu = hwloc_hpux_find_spu(topology, hwloc_set); + if (cpu != -1) + return mpctl(flags & HWLOC_CPUBIND_STRICT ? MPC_SETPROCESS_FORCE : MPC_SETPROCESS, cpu, pid); + + errno = EXDEV; + return -1; +} + +static int +hwloc_hpux_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + return hwloc_hpux_set_proc_cpubind(topology, MPC_SELFPID, hwloc_set, flags); +} + +#ifdef hwloc_thread_t +static int +hwloc_hpux_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_const_bitmap_t hwloc_set, int flags) +{ + ldom_t ldom, ldom2; + spu_t cpu, cpu2; + + /* Drop previous binding */ + pthread_ldom_bind_np(&ldom2, PTHREAD_LDOMFLOAT_NP, pthread); + pthread_processor_bind_np(PTHREAD_BIND_ADVISORY_NP, &cpu2, PTHREAD_SPUFLOAT_NP, pthread); + + if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology))) + return 0; + + ldom = hwloc_hpux_find_ldom(topology, hwloc_set); + if (ldom != -1) + return pthread_ldom_bind_np(&ldom2, ldom, pthread); + + cpu = hwloc_hpux_find_spu(topology, hwloc_set); + if (cpu != -1) + return pthread_processor_bind_np(flags & HWLOC_CPUBIND_STRICT ? PTHREAD_BIND_FORCED_NP : PTHREAD_BIND_ADVISORY_NP, &cpu2, cpu, pthread); + + errno = EXDEV; + return -1; +} + +static int +hwloc_hpux_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags) +{ + return hwloc_hpux_set_thread_cpubind(topology, PTHREAD_SELFTID_NP, hwloc_set, flags); +} +#endif + +/* According to HP docs, HP-UX up to 11iv2 don't support migration */ + +#ifdef MAP_MEM_FIRST_TOUCH +static void* +hwloc_hpux_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + int mmap_flags; + + /* Can not give a set of nodes. */ + if (!hwloc_bitmap_isequal(nodeset, hwloc_topology_get_complete_nodeset(topology))) { + errno = EXDEV; + return hwloc_alloc_or_fail(topology, len, flags); + } + + switch (policy) { + case HWLOC_MEMBIND_DEFAULT: + case HWLOC_MEMBIND_BIND: + mmap_flags = 0; + break; + case HWLOC_MEMBIND_FIRSTTOUCH: + mmap_flags = MAP_MEM_FIRST_TOUCH; + break; + case HWLOC_MEMBIND_INTERLEAVE: + mmap_flags = MAP_MEM_INTERLEAVED; + break; + default: + errno = ENOSYS; + return NULL; + } + + return mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | mmap_flags, -1, 0); +} +#endif /* MAP_MEM_FIRST_TOUCH */ + +void +hwloc_look_hpux(struct hwloc_topology *topology) +{ + int has_numa = sysconf(_SC_CCNUMA_SUPPORT) == 1; + hwloc_obj_t *nodes = NULL, obj; + spu_t currentcpu; + ldom_t currentnode; + int i, nbnodes = 0; + +#ifdef HAVE__SC_LARGE_PAGESIZE + topology->levels[0][0]->attr->machine.huge_page_size_kB = sysconf(_SC_LARGE_PAGESIZE); +#endif + + if (has_numa) { + nbnodes = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ? + MPC_GETNUMLDOMS_SYS : MPC_GETNUMLDOMS, 0, 0); + + hwloc_debug("%d nodes\n", nbnodes); + + nodes = malloc(nbnodes * sizeof(*nodes)); + + i = 0; + currentnode = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ? + MPC_GETFIRSTLDOM_SYS : MPC_GETFIRSTLDOM, 0, 0); + while (currentnode != -1 && i < nbnodes) { + hwloc_debug("node %d is %d\n", i, currentnode); + nodes[i] = obj = hwloc_alloc_setup_object(HWLOC_OBJ_NODE, currentnode); + obj->cpuset = hwloc_bitmap_alloc(); + obj->nodeset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(obj->nodeset, currentnode); + /* TODO: obj->attr->node.memory_kB */ + /* TODO: obj->attr->node.huge_page_free */ + + currentnode = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ? + MPC_GETNEXTLDOM_SYS : MPC_GETNEXTLDOM, currentnode, 0); + i++; + } + } + + i = 0; + currentcpu = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ? + MPC_GETFIRSTSPU_SYS : MPC_GETFIRSTSPU, 0,0); + while (currentcpu != -1) { + obj = hwloc_alloc_setup_object(HWLOC_OBJ_PU, currentcpu); + obj->cpuset = hwloc_bitmap_alloc(); + hwloc_bitmap_set(obj->cpuset, currentcpu); + + hwloc_debug("cpu %d\n", currentcpu); + + if (nodes) { + /* Add this cpu to its node */ + currentnode = mpctl(MPC_SPUTOLDOM, currentcpu, 0); + if ((ldom_t) nodes[i]->os_index != currentnode) + for (i = 0; i < nbnodes; i++) + if ((ldom_t) nodes[i]->os_index == currentnode) + break; + if (i < nbnodes) { + hwloc_bitmap_set(nodes[i]->cpuset, currentcpu); + hwloc_debug("is in node %d\n", i); + } else { + hwloc_debug("%s", "is in no node?!\n"); + } + } + + /* Add cpu */ + hwloc_insert_object_by_cpuset(topology, obj); + + currentcpu = mpctl(topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM ? + MPC_GETNEXTSPU_SYS : MPC_GETNEXTSPU, currentcpu, 0); + } + + if (nodes) { + /* Add nodes */ + for (i = 0 ; i < nbnodes ; i++) + hwloc_insert_object_by_cpuset(topology, nodes[i]); + free(nodes); + } + + topology->support.discovery->pu = 1; + + hwloc_add_object_info(topology->levels[0][0], "Backend", "HP-UX"); +} + +void +hwloc_set_hpux_hooks(struct hwloc_topology *topology) +{ + topology->set_proc_cpubind = hwloc_hpux_set_proc_cpubind; + topology->set_thisproc_cpubind = hwloc_hpux_set_thisproc_cpubind; +#ifdef hwloc_thread_t + topology->set_thread_cpubind = hwloc_hpux_set_thread_cpubind; + topology->set_thisthread_cpubind = hwloc_hpux_set_thisthread_cpubind; +#endif +#ifdef MAP_MEM_FIRST_TOUCH + topology->alloc_membind = hwloc_hpux_alloc_membind; + topology->alloc = hwloc_alloc_mmap; + topology->free_membind = hwloc_free_mmap; + topology->support.membind->firsttouch_membind = 1; + topology->support.membind->bind_membind = 1; + topology->support.membind->interleave_membind = 1; +#endif /* MAP_MEM_FIRST_TOUCH */ +} |