root/opal/mca/hwloc/hwloc201/hwloc/hwloc/topology-hpux.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hwloc_hpux_find_ldom
  2. hwloc_hpux_find_spu
  3. hwloc_hpux_set_proc_cpubind
  4. hwloc_hpux_set_thisproc_cpubind
  5. hwloc_hpux_set_thread_cpubind
  6. hwloc_hpux_set_thisthread_cpubind
  7. hwloc_hpux_alloc_membind
  8. hwloc_look_hpux
  9. hwloc_set_hpux_hooks
  10. hwloc_hpux_component_instantiate

   1 /*
   2  * Copyright © 2009 CNRS
   3  * Copyright © 2009-2018 Inria.  All rights reserved.
   4  * Copyright © 2009-2010, 2013 Université Bordeaux
   5  * Copyright © 2011 Cisco Systems, Inc.  All rights reserved.
   6  * See COPYING in top-level directory.
   7  */
   8 
   9 /* TODO: psets? (Only for root)
  10  * since 11i 1.6:
  11    _SC_PSET_SUPPORT
  12    pset_create/destroy/assign/setattr
  13    pset_ctl/getattr
  14    pset_bind()
  15    pthread_pset_bind_np()
  16  */
  17 
  18 #include <private/autogen/config.h>
  19 
  20 #include <sys/types.h>
  21 #ifdef HAVE_UNISTD_H
  22 #include <unistd.h>
  23 #endif
  24 #include <string.h>
  25 #include <errno.h>
  26 #include <stdio.h>
  27 
  28 #include <hwloc.h>
  29 #include <private/private.h>
  30 #include <private/debug.h>
  31 
  32 #include <sys/mpctl.h>
  33 #include <sys/mman.h>
  34 #include <pthread.h>
  35 
  36 static ldom_t
  37 hwloc_hpux_find_ldom(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set)
  38 {
  39   int has_numa = sysconf(_SC_CCNUMA_SUPPORT) == 1;
  40   hwloc_obj_t obj;
  41 
  42   if (!has_numa)
  43     return -1;
  44 
  45   obj = hwloc_get_first_largest_obj_inside_cpuset(topology, hwloc_set);
  46   if (!hwloc_bitmap_isequal(obj->cpuset, hwloc_set))
  47     /* Does not correspond to exactly one node */
  48     return -1;
  49   /* obj is the highest possibly matching object, but some (single) child (with same cpuset) could match too */
  50   while (obj->type != HWLOC_OBJ_NUMANODE) {
  51     /* try the first child, in case it has the same cpuset */
  52     if (!obj->first_child
  53         || !obj->first_child->cpuset
  54         || !hwloc_bitmap_isequal(obj->cpuset, obj->first_child->cpuset))
  55       return -1;
  56     obj = obj->first_child;
  57   }
  58 
  59   return obj->os_index;
  60 }
  61 
  62 static spu_t
  63 hwloc_hpux_find_spu(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t hwloc_set)
  64 {
  65   spu_t cpu;
  66 
  67   cpu = hwloc_bitmap_first(hwloc_set);
  68   if (cpu != -1 && hwloc_bitmap_weight(hwloc_set) == 1)
  69     return cpu;
  70   return -1;
  71 }
  72 
  73 /* Note: get_cpubind not available on HP-UX */
  74 static int
  75 hwloc_hpux_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_set, int flags)
  76 {
  77   ldom_t ldom;
  78   spu_t cpu;
  79 
  80   /* Drop previous binding */
  81   mpctl(MPC_SETLDOM, MPC_LDOMFLOAT, pid);
  82   mpctl(MPC_SETPROCESS, MPC_SPUFLOAT, pid);
  83 
  84   if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology)))
  85     return 0;
  86 
  87   ldom = hwloc_hpux_find_ldom(topology, hwloc_set);
  88   if (ldom != -1)
  89     return mpctl(MPC_SETLDOM, ldom, pid);
  90 
  91   cpu = hwloc_hpux_find_spu(topology, hwloc_set);
  92   if (cpu != -1)
  93     return mpctl((flags & HWLOC_CPUBIND_STRICT) ? MPC_SETPROCESS_FORCE : MPC_SETPROCESS, cpu, pid);
  94 
  95   errno = EXDEV;
  96   return -1;
  97 }
  98 
  99 static int
 100 hwloc_hpux_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
 101 {
 102   return hwloc_hpux_set_proc_cpubind(topology, MPC_SELFPID, hwloc_set, flags);
 103 }
 104 
 105 #ifdef hwloc_thread_t
 106 static int
 107 hwloc_hpux_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t pthread, hwloc_const_bitmap_t hwloc_set, int flags)
 108 {
 109   ldom_t ldom, ldom2;
 110   spu_t cpu, cpu2;
 111 
 112   /* Drop previous binding */
 113   pthread_ldom_bind_np(&ldom2, PTHREAD_LDOMFLOAT_NP, pthread);
 114   pthread_processor_bind_np(PTHREAD_BIND_ADVISORY_NP, &cpu2, PTHREAD_SPUFLOAT_NP, pthread);
 115 
 116   if (hwloc_bitmap_isequal(hwloc_set, hwloc_topology_get_complete_cpuset(topology)))
 117     return 0;
 118 
 119   ldom = hwloc_hpux_find_ldom(topology, hwloc_set);
 120   if (ldom != -1)
 121     return pthread_ldom_bind_np(&ldom2, ldom, pthread);
 122 
 123   cpu = hwloc_hpux_find_spu(topology, hwloc_set);
 124   if (cpu != -1)
 125     return pthread_processor_bind_np((flags & HWLOC_CPUBIND_STRICT) ? PTHREAD_BIND_FORCED_NP : PTHREAD_BIND_ADVISORY_NP, &cpu2, cpu, pthread);
 126 
 127   errno = EXDEV;
 128   return -1;
 129 }
 130 
 131 static int
 132 hwloc_hpux_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_set, int flags)
 133 {
 134   return hwloc_hpux_set_thread_cpubind(topology, PTHREAD_SELFTID_NP, hwloc_set, flags);
 135 }
 136 #endif
 137 
 138 /* According to HP docs, HP-UX up to 11iv2 don't support migration */
 139 
 140 #ifdef MAP_MEM_FIRST_TOUCH
 141 static void*
 142 hwloc_hpux_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t _nodeset, hwloc_membind_policy_t policy, int flags)
 143 {
 144   hwloc_const_nodeset_t nodeset;
 145   int mmap_flags;
 146   void *p;
 147 
 148   /* Can not give a set of nodes.  */
 149   nodeset = hwloc_topology_get_complete_nodeset(topology);
 150   if (policy != HWLOC_MEMBIND_DEFAULT
 151       && !hwloc_bitmap_isequal(nodeset, _nodeset)) {
 152     errno = EXDEV;
 153     return hwloc_alloc_or_fail(topology, len, flags);
 154   }
 155 
 156   switch (policy) {
 157     case HWLOC_MEMBIND_DEFAULT:
 158     case HWLOC_MEMBIND_BIND:
 159       mmap_flags = 0;
 160       break;
 161     case HWLOC_MEMBIND_FIRSTTOUCH:
 162       mmap_flags = MAP_MEM_FIRST_TOUCH;
 163       break;
 164     case HWLOC_MEMBIND_INTERLEAVE:
 165       mmap_flags = MAP_MEM_INTERLEAVED;
 166       break;
 167     default:
 168       errno = ENOSYS;
 169       return NULL;
 170   }
 171 
 172   p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | mmap_flags, -1, 0);
 173   return p == MAP_FAILED ? NULL : p;
 174 }
 175 #endif /* MAP_MEM_FIRST_TOUCH */
 176 
 177 static int
 178 hwloc_look_hpux(struct hwloc_backend *backend)
 179 {
 180   struct hwloc_topology *topology = backend->topology;
 181   int has_numa = sysconf(_SC_CCNUMA_SUPPORT) == 1;
 182   spu_t currentcpu;
 183   ldom_t currentnode;
 184   int i, nbnodes = 0;
 185 
 186   if (topology->levels[0][0]->cpuset)
 187     /* somebody discovered things */
 188     return -1;
 189 
 190   hwloc_alloc_root_sets(topology->levels[0][0]);
 191 
 192   if (has_numa) {
 193     nbnodes = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
 194       MPC_GETNUMLDOMS_SYS : MPC_GETNUMLDOMS, 0, 0);
 195   }
 196   hwloc_debug("%d nodes\n", nbnodes);
 197 
 198   hwloc_obj_t nodes[nbnodes], obj;
 199 
 200   if (has_numa) {
 201     i = 0;
 202     currentnode = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
 203       MPC_GETFIRSTLDOM_SYS : MPC_GETFIRSTLDOM, 0, 0);
 204     while (currentnode != -1 && i < nbnodes) {
 205       hwloc_debug("node %d is %d\n", i, currentnode);
 206       nodes[i] = obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_NUMANODE, (unsigned) currentnode);
 207       obj->cpuset = hwloc_bitmap_alloc();
 208       obj->nodeset = hwloc_bitmap_alloc();
 209       hwloc_bitmap_set(obj->nodeset, currentnode);
 210       /* TODO: obj->attr->node.memory_kB */
 211       /* TODO: obj->attr->node.huge_page_free */
 212 
 213       currentnode = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
 214         MPC_GETNEXTLDOM_SYS : MPC_GETNEXTLDOM, currentnode, 0);
 215       i++;
 216     }
 217   }
 218 
 219   i = 0;
 220   currentcpu = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
 221       MPC_GETFIRSTSPU_SYS : MPC_GETFIRSTSPU, 0,0);
 222   while (currentcpu != -1) {
 223     obj = hwloc_alloc_setup_object(topology, HWLOC_OBJ_PU, (unsigned) currentcpu);
 224     obj->cpuset = hwloc_bitmap_alloc();
 225     hwloc_bitmap_set(obj->cpuset, currentcpu);
 226 
 227     hwloc_debug("cpu %d\n", currentcpu);
 228 
 229     if (has_numa) {
 230       /* Add this cpu to its node */
 231       currentnode = mpctl(MPC_SPUTOLDOM, currentcpu, 0);
 232       /* Hopefully it's just the same as previous cpu */
 233       if (i >= nbnodes || (ldom_t) nodes[i]->os_index != currentnode)
 234         for (i = 0; i < nbnodes; i++)
 235           if ((ldom_t) nodes[i]->os_index == currentnode)
 236             break;
 237       if (i < nbnodes) {
 238         hwloc_bitmap_set(nodes[i]->cpuset, currentcpu);
 239         hwloc_debug("is in node %d\n", i);
 240       } else {
 241         hwloc_debug("%s", "is in no node?!\n");
 242       }
 243     }
 244 
 245     /* Add cpu */
 246     hwloc_insert_object_by_cpuset(topology, obj);
 247 
 248     currentcpu = mpctl((topology->flags & HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM) ?
 249       MPC_GETNEXTSPU_SYS : MPC_GETNEXTSPU, currentcpu, 0);
 250   }
 251 
 252   if (has_numa) {
 253     /* Add nodes */
 254     for (i = 0 ; i < nbnodes ; i++)
 255       hwloc_insert_object_by_cpuset(topology, nodes[i]);
 256   }
 257 
 258   topology->support.discovery->pu = 1;
 259   if (has_numa)
 260     topology->support.discovery->numa = 1;
 261 
 262   hwloc_obj_add_info(topology->levels[0][0], "Backend", "HP-UX");
 263   hwloc_add_uname_info(topology, NULL);
 264   return 0;
 265 }
 266 
 267 void
 268 hwloc_set_hpux_hooks(struct hwloc_binding_hooks *hooks,
 269                      struct hwloc_topology_support *support __hwloc_attribute_unused)
 270 {
 271   hooks->set_proc_cpubind = hwloc_hpux_set_proc_cpubind;
 272   hooks->set_thisproc_cpubind = hwloc_hpux_set_thisproc_cpubind;
 273 #ifdef hwloc_thread_t
 274   hooks->set_thread_cpubind = hwloc_hpux_set_thread_cpubind;
 275   hooks->set_thisthread_cpubind = hwloc_hpux_set_thisthread_cpubind;
 276 #endif
 277 #ifdef MAP_MEM_FIRST_TOUCH
 278   hooks->alloc_membind = hwloc_hpux_alloc_membind;
 279   hooks->alloc = hwloc_alloc_mmap;
 280   hooks->free_membind = hwloc_free_mmap;
 281   support->membind->firsttouch_membind = 1;
 282   support->membind->bind_membind = 1;
 283   support->membind->interleave_membind = 1;
 284 #endif /* MAP_MEM_FIRST_TOUCH */
 285 }
 286 
 287 static struct hwloc_backend *
 288 hwloc_hpux_component_instantiate(struct hwloc_disc_component *component,
 289                                  const void *_data1 __hwloc_attribute_unused,
 290                                  const void *_data2 __hwloc_attribute_unused,
 291                                  const void *_data3 __hwloc_attribute_unused)
 292 {
 293   struct hwloc_backend *backend;
 294   backend = hwloc_backend_alloc(component);
 295   if (!backend)
 296     return NULL;
 297   backend->discover = hwloc_look_hpux;
 298   return backend;
 299 }
 300 
 301 static struct hwloc_disc_component hwloc_hpux_disc_component = {
 302   HWLOC_DISC_COMPONENT_TYPE_CPU,
 303   "hpux",
 304   HWLOC_DISC_COMPONENT_TYPE_GLOBAL,
 305   hwloc_hpux_component_instantiate,
 306   50,
 307   1,
 308   NULL
 309 };
 310 
 311 const struct hwloc_component hwloc_hpux_component = {
 312   HWLOC_COMPONENT_ABI,
 313   NULL, NULL,
 314   HWLOC_COMPONENT_TYPE_DISC,
 315   0,
 316   &hwloc_hpux_disc_component
 317 };

/* [<][>][^][v][top][bottom][index][help] */