/* * 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 #include #include #include #include #include #include #include #include #include #include #include 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 */ }