root/opal/mca/hwloc/hwloc201/hwloc/hwloc/bind.c

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

DEFINITIONS

This source file includes following definitions.
  1. hwloc_fix_cpubind
  2. hwloc_set_cpubind
  3. hwloc_get_cpubind
  4. hwloc_set_proc_cpubind
  5. hwloc_get_proc_cpubind
  6. hwloc_set_thread_cpubind
  7. hwloc_get_thread_cpubind
  8. hwloc_get_last_cpu_location
  9. hwloc_get_proc_last_cpu_location
  10. hwloc_fix_membind
  11. hwloc_fix_membind_cpuset
  12. hwloc__check_membind_policy
  13. hwloc_set_membind_by_nodeset
  14. hwloc_set_membind
  15. hwloc_get_membind_by_nodeset
  16. hwloc_get_membind
  17. hwloc_set_proc_membind_by_nodeset
  18. hwloc_set_proc_membind
  19. hwloc_get_proc_membind_by_nodeset
  20. hwloc_get_proc_membind
  21. hwloc_set_area_membind_by_nodeset
  22. hwloc_set_area_membind
  23. hwloc_get_area_membind_by_nodeset
  24. hwloc_get_area_membind
  25. hwloc_get_area_memlocation_by_nodeset
  26. hwloc_get_area_memlocation
  27. hwloc_alloc_heap
  28. hwloc_alloc_mmap
  29. hwloc_free_heap
  30. hwloc_free_mmap
  31. hwloc_alloc
  32. hwloc_alloc_membind_by_nodeset
  33. hwloc_alloc_membind
  34. hwloc_free
  35. dontset_return_complete_cpuset
  36. dontset_thisthread_cpubind
  37. dontget_thisthread_cpubind
  38. dontset_thisproc_cpubind
  39. dontget_thisproc_cpubind
  40. dontset_proc_cpubind
  41. dontget_proc_cpubind
  42. dontset_thread_cpubind
  43. dontget_thread_cpubind
  44. dontset_return_complete_nodeset
  45. dontset_thisproc_membind
  46. dontget_thisproc_membind
  47. dontset_thisthread_membind
  48. dontget_thisthread_membind
  49. dontset_proc_membind
  50. dontget_proc_membind
  51. dontset_area_membind
  52. dontget_area_membind
  53. dontget_area_memlocation
  54. dontalloc_membind
  55. dontfree_membind
  56. hwloc_set_dummy_hooks
  57. hwloc_set_native_binding_hooks
  58. hwloc_set_binding_hooks

   1 /*
   2  * Copyright © 2009 CNRS
   3  * Copyright © 2009-2018 Inria.  All rights reserved.
   4  * Copyright © 2009-2010, 2012 Université Bordeaux
   5  * Copyright © 2011-2015 Cisco Systems, Inc.  All rights reserved.
   6  * See COPYING in top-level directory.
   7  */
   8 
   9 #include <private/autogen/config.h>
  10 #include <hwloc.h>
  11 #include <private/private.h>
  12 #include <hwloc/helper.h>
  13 #ifdef HAVE_SYS_MMAN_H
  14 #  include <sys/mman.h>
  15 #endif
  16 /* <malloc.h> is only needed if we don't have posix_memalign() */
  17 #if defined(hwloc_getpagesize) && !defined(HAVE_POSIX_MEMALIGN) && defined(HAVE_MEMALIGN) && defined(HAVE_MALLOC_H)
  18 #include <malloc.h>
  19 #endif
  20 #ifdef HAVE_UNISTD_H
  21 #include <unistd.h>
  22 #endif
  23 #include <stdlib.h>
  24 #include <errno.h>
  25 
  26 /* TODO: HWLOC_GNU_SYS,
  27  *
  28  * We could use glibc's sched_setaffinity generically when it is available
  29  *
  30  * Darwin and OpenBSD don't seem to have binding facilities.
  31  */
  32 
  33 #define HWLOC_CPUBIND_ALLFLAGS (HWLOC_CPUBIND_PROCESS|HWLOC_CPUBIND_THREAD|HWLOC_CPUBIND_STRICT|HWLOC_CPUBIND_NOMEMBIND)
  34 
  35 static hwloc_const_bitmap_t
  36 hwloc_fix_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t set)
  37 {
  38   hwloc_const_bitmap_t topology_set = hwloc_topology_get_topology_cpuset(topology);
  39   hwloc_const_bitmap_t complete_set = hwloc_topology_get_complete_cpuset(topology);
  40 
  41   if (hwloc_bitmap_iszero(set)) {
  42     errno = EINVAL;
  43     return NULL;
  44   }
  45 
  46   if (!hwloc_bitmap_isincluded(set, complete_set)) {
  47     errno = EINVAL;
  48     return NULL;
  49   }
  50 
  51   if (hwloc_bitmap_isincluded(topology_set, set))
  52     set = complete_set;
  53 
  54   return set;
  55 }
  56 
  57 int
  58 hwloc_set_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t set, int flags)
  59 {
  60   if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
  61     errno = EINVAL;
  62     return -1;
  63   }
  64 
  65   set = hwloc_fix_cpubind(topology, set);
  66   if (!set)
  67     return -1;
  68 
  69   if (flags & HWLOC_CPUBIND_PROCESS) {
  70     if (topology->binding_hooks.set_thisproc_cpubind)
  71       return topology->binding_hooks.set_thisproc_cpubind(topology, set, flags);
  72   } else if (flags & HWLOC_CPUBIND_THREAD) {
  73     if (topology->binding_hooks.set_thisthread_cpubind)
  74       return topology->binding_hooks.set_thisthread_cpubind(topology, set, flags);
  75   } else {
  76     if (topology->binding_hooks.set_thisproc_cpubind) {
  77       int err = topology->binding_hooks.set_thisproc_cpubind(topology, set, flags);
  78       if (err >= 0 || errno != ENOSYS)
  79         return err;
  80       /* ENOSYS, fallback */
  81     }
  82     if (topology->binding_hooks.set_thisthread_cpubind)
  83       return topology->binding_hooks.set_thisthread_cpubind(topology, set, flags);
  84   }
  85 
  86   errno = ENOSYS;
  87   return -1;
  88 }
  89 
  90 int
  91 hwloc_get_cpubind(hwloc_topology_t topology, hwloc_bitmap_t set, int flags)
  92 {
  93   if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
  94     errno = EINVAL;
  95     return -1;
  96   }
  97 
  98   if (flags & HWLOC_CPUBIND_PROCESS) {
  99     if (topology->binding_hooks.get_thisproc_cpubind)
 100       return topology->binding_hooks.get_thisproc_cpubind(topology, set, flags);
 101   } else if (flags & HWLOC_CPUBIND_THREAD) {
 102     if (topology->binding_hooks.get_thisthread_cpubind)
 103       return topology->binding_hooks.get_thisthread_cpubind(topology, set, flags);
 104   } else {
 105     if (topology->binding_hooks.get_thisproc_cpubind) {
 106       int err = topology->binding_hooks.get_thisproc_cpubind(topology, set, flags);
 107       if (err >= 0 || errno != ENOSYS)
 108         return err;
 109       /* ENOSYS, fallback */
 110     }
 111     if (topology->binding_hooks.get_thisthread_cpubind)
 112       return topology->binding_hooks.get_thisthread_cpubind(topology, set, flags);
 113   }
 114 
 115   errno = ENOSYS;
 116   return -1;
 117 }
 118 
 119 int
 120 hwloc_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t set, int flags)
 121 {
 122   if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
 123     errno = EINVAL;
 124     return -1;
 125   }
 126 
 127   set = hwloc_fix_cpubind(topology, set);
 128   if (!set)
 129     return -1;
 130 
 131   if (topology->binding_hooks.set_proc_cpubind)
 132     return topology->binding_hooks.set_proc_cpubind(topology, pid, set, flags);
 133 
 134   errno = ENOSYS;
 135   return -1;
 136 }
 137 
 138 int
 139 hwloc_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t set, int flags)
 140 {
 141   if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
 142     errno = EINVAL;
 143     return -1;
 144   }
 145 
 146   if (topology->binding_hooks.get_proc_cpubind)
 147     return topology->binding_hooks.get_proc_cpubind(topology, pid, set, flags);
 148 
 149   errno = ENOSYS;
 150   return -1;
 151 }
 152 
 153 #ifdef hwloc_thread_t
 154 int
 155 hwloc_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_const_bitmap_t set, int flags)
 156 {
 157   if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
 158     errno = EINVAL;
 159     return -1;
 160   }
 161 
 162   set = hwloc_fix_cpubind(topology, set);
 163   if (!set)
 164     return -1;
 165 
 166   if (topology->binding_hooks.set_thread_cpubind)
 167     return topology->binding_hooks.set_thread_cpubind(topology, tid, set, flags);
 168 
 169   errno = ENOSYS;
 170   return -1;
 171 }
 172 
 173 int
 174 hwloc_get_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_bitmap_t set, int flags)
 175 {
 176   if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
 177     errno = EINVAL;
 178     return -1;
 179   }
 180 
 181   if (topology->binding_hooks.get_thread_cpubind)
 182     return topology->binding_hooks.get_thread_cpubind(topology, tid, set, flags);
 183 
 184   errno = ENOSYS;
 185   return -1;
 186 }
 187 #endif
 188 
 189 int
 190 hwloc_get_last_cpu_location(hwloc_topology_t topology, hwloc_bitmap_t set, int flags)
 191 {
 192   if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
 193     errno = EINVAL;
 194     return -1;
 195   }
 196 
 197   if (flags & HWLOC_CPUBIND_PROCESS) {
 198     if (topology->binding_hooks.get_thisproc_last_cpu_location)
 199       return topology->binding_hooks.get_thisproc_last_cpu_location(topology, set, flags);
 200   } else if (flags & HWLOC_CPUBIND_THREAD) {
 201     if (topology->binding_hooks.get_thisthread_last_cpu_location)
 202       return topology->binding_hooks.get_thisthread_last_cpu_location(topology, set, flags);
 203   } else {
 204     if (topology->binding_hooks.get_thisproc_last_cpu_location) {
 205       int err = topology->binding_hooks.get_thisproc_last_cpu_location(topology, set, flags);
 206       if (err >= 0 || errno != ENOSYS)
 207         return err;
 208       /* ENOSYS, fallback */
 209     }
 210     if (topology->binding_hooks.get_thisthread_last_cpu_location)
 211       return topology->binding_hooks.get_thisthread_last_cpu_location(topology, set, flags);
 212   }
 213 
 214   errno = ENOSYS;
 215   return -1;
 216 }
 217 
 218 int
 219 hwloc_get_proc_last_cpu_location(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t set, int flags)
 220 {
 221   if (flags & ~HWLOC_CPUBIND_ALLFLAGS) {
 222     errno = EINVAL;
 223     return -1;
 224   }
 225 
 226   if (topology->binding_hooks.get_proc_last_cpu_location)
 227     return topology->binding_hooks.get_proc_last_cpu_location(topology, pid, set, flags);
 228 
 229   errno = ENOSYS;
 230   return -1;
 231 }
 232 
 233 #define HWLOC_MEMBIND_ALLFLAGS (HWLOC_MEMBIND_PROCESS|HWLOC_MEMBIND_THREAD|HWLOC_MEMBIND_STRICT|HWLOC_MEMBIND_MIGRATE|HWLOC_MEMBIND_NOCPUBIND|HWLOC_MEMBIND_BYNODESET)
 234 
 235 static hwloc_const_nodeset_t
 236 hwloc_fix_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset)
 237 {
 238   hwloc_const_bitmap_t topology_nodeset = hwloc_topology_get_topology_nodeset(topology);
 239   hwloc_const_bitmap_t complete_nodeset = hwloc_topology_get_complete_nodeset(topology);
 240 
 241   if (hwloc_bitmap_iszero(nodeset)) {
 242     errno = EINVAL;
 243     return NULL;
 244   }
 245 
 246   if (!hwloc_bitmap_isincluded(nodeset, complete_nodeset)) {
 247     errno = EINVAL;
 248     return NULL;
 249   }
 250 
 251   if (hwloc_bitmap_isincluded(topology_nodeset, nodeset))
 252     return complete_nodeset;
 253 
 254   return nodeset;
 255 }
 256 
 257 static int
 258 hwloc_fix_membind_cpuset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_const_cpuset_t cpuset)
 259 {
 260   hwloc_const_bitmap_t topology_set = hwloc_topology_get_topology_cpuset(topology);
 261   hwloc_const_bitmap_t complete_set = hwloc_topology_get_complete_cpuset(topology);
 262   hwloc_const_bitmap_t complete_nodeset = hwloc_topology_get_complete_nodeset(topology);
 263 
 264   if (hwloc_bitmap_iszero(cpuset)) {
 265     errno = EINVAL;
 266     return -1;
 267   }
 268 
 269   if (!hwloc_bitmap_isincluded(cpuset, complete_set)) {
 270     errno = EINVAL;
 271     return -1;
 272   }
 273 
 274   if (hwloc_bitmap_isincluded(topology_set, cpuset)) {
 275     hwloc_bitmap_copy(nodeset, complete_nodeset);
 276     return 0;
 277   }
 278 
 279   hwloc_cpuset_to_nodeset(topology, cpuset, nodeset);
 280   return 0;
 281 }
 282 
 283 static __hwloc_inline int hwloc__check_membind_policy(hwloc_membind_policy_t policy)
 284 {
 285   if (policy == HWLOC_MEMBIND_DEFAULT
 286       || policy == HWLOC_MEMBIND_FIRSTTOUCH
 287       || policy == HWLOC_MEMBIND_BIND
 288       || policy == HWLOC_MEMBIND_INTERLEAVE
 289       || policy == HWLOC_MEMBIND_NEXTTOUCH)
 290     return 0;
 291   return -1;
 292 }
 293 
 294 static int
 295 hwloc_set_membind_by_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
 296 {
 297   if ((flags & ~HWLOC_MEMBIND_ALLFLAGS) || hwloc__check_membind_policy(policy) < 0) {
 298     errno = EINVAL;
 299     return -1;
 300   }
 301 
 302   nodeset = hwloc_fix_membind(topology, nodeset);
 303   if (!nodeset)
 304     return -1;
 305 
 306   if (flags & HWLOC_MEMBIND_PROCESS) {
 307     if (topology->binding_hooks.set_thisproc_membind)
 308       return topology->binding_hooks.set_thisproc_membind(topology, nodeset, policy, flags);
 309   } else if (flags & HWLOC_MEMBIND_THREAD) {
 310     if (topology->binding_hooks.set_thisthread_membind)
 311       return topology->binding_hooks.set_thisthread_membind(topology, nodeset, policy, flags);
 312   } else {
 313     if (topology->binding_hooks.set_thisproc_membind) {
 314       int err = topology->binding_hooks.set_thisproc_membind(topology, nodeset, policy, flags);
 315       if (err >= 0 || errno != ENOSYS)
 316         return err;
 317       /* ENOSYS, fallback */
 318     }
 319     if (topology->binding_hooks.set_thisthread_membind)
 320       return topology->binding_hooks.set_thisthread_membind(topology, nodeset, policy, flags);
 321   }
 322 
 323   errno = ENOSYS;
 324   return -1;
 325 }
 326 
 327 int
 328 hwloc_set_membind(hwloc_topology_t topology, hwloc_const_bitmap_t set, hwloc_membind_policy_t policy, int flags)
 329 {
 330   int ret;
 331 
 332   if (flags & HWLOC_MEMBIND_BYNODESET) {
 333     ret = hwloc_set_membind_by_nodeset(topology, set, policy, flags);
 334   } else {
 335     hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
 336     if (hwloc_fix_membind_cpuset(topology, nodeset, set))
 337       ret = -1;
 338     else
 339       ret = hwloc_set_membind_by_nodeset(topology, nodeset, policy, flags);
 340     hwloc_bitmap_free(nodeset);
 341   }
 342   return ret;
 343 }
 344 
 345 static int
 346 hwloc_get_membind_by_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags)
 347 {
 348   if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
 349     errno = EINVAL;
 350     return -1;
 351   }
 352 
 353   if (flags & HWLOC_MEMBIND_PROCESS) {
 354     if (topology->binding_hooks.get_thisproc_membind)
 355       return topology->binding_hooks.get_thisproc_membind(topology, nodeset, policy, flags);
 356   } else if (flags & HWLOC_MEMBIND_THREAD) {
 357     if (topology->binding_hooks.get_thisthread_membind)
 358       return topology->binding_hooks.get_thisthread_membind(topology, nodeset, policy, flags);
 359   } else {
 360     if (topology->binding_hooks.get_thisproc_membind) {
 361       int err = topology->binding_hooks.get_thisproc_membind(topology, nodeset, policy, flags);
 362       if (err >= 0 || errno != ENOSYS)
 363         return err;
 364       /* ENOSYS, fallback */
 365     }
 366     if (topology->binding_hooks.get_thisthread_membind)
 367       return topology->binding_hooks.get_thisthread_membind(topology, nodeset, policy, flags);
 368   }
 369 
 370   errno = ENOSYS;
 371   return -1;
 372 }
 373 
 374 int
 375 hwloc_get_membind(hwloc_topology_t topology, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags)
 376 {
 377   int ret;
 378 
 379   if (flags & HWLOC_MEMBIND_BYNODESET) {
 380     ret = hwloc_get_membind_by_nodeset(topology, set, policy, flags);
 381   } else {
 382     hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
 383     ret = hwloc_get_membind_by_nodeset(topology, nodeset, policy, flags);
 384     if (!ret)
 385       hwloc_cpuset_from_nodeset(topology, set, nodeset);
 386     hwloc_bitmap_free(nodeset);
 387   }
 388 
 389   return ret;
 390 }
 391 
 392 static int
 393 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)
 394 {
 395   if ((flags & ~HWLOC_MEMBIND_ALLFLAGS) || hwloc__check_membind_policy(policy) < 0) {
 396     errno = EINVAL;
 397     return -1;
 398   }
 399 
 400   nodeset = hwloc_fix_membind(topology, nodeset);
 401   if (!nodeset)
 402     return -1;
 403 
 404   if (topology->binding_hooks.set_proc_membind)
 405     return topology->binding_hooks.set_proc_membind(topology, pid, nodeset, policy, flags);
 406 
 407   errno = ENOSYS;
 408   return -1;
 409 }
 410 
 411 
 412 int
 413 hwloc_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t set, hwloc_membind_policy_t policy, int flags)
 414 {
 415   int ret;
 416 
 417   if (flags & HWLOC_MEMBIND_BYNODESET) {
 418     ret = hwloc_set_proc_membind_by_nodeset(topology, pid, set, policy, flags);
 419   } else {
 420     hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
 421     if (hwloc_fix_membind_cpuset(topology, nodeset, set))
 422       ret = -1;
 423     else
 424       ret = hwloc_set_proc_membind_by_nodeset(topology, pid, nodeset, policy, flags);
 425     hwloc_bitmap_free(nodeset);
 426   }
 427 
 428   return ret;
 429 }
 430 
 431 static int
 432 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)
 433 {
 434   if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
 435     errno = EINVAL;
 436     return -1;
 437   }
 438 
 439   if (topology->binding_hooks.get_proc_membind)
 440     return topology->binding_hooks.get_proc_membind(topology, pid, nodeset, policy, flags);
 441 
 442   errno = ENOSYS;
 443   return -1;
 444 }
 445 
 446 int
 447 hwloc_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags)
 448 {
 449   int ret;
 450 
 451   if (flags & HWLOC_MEMBIND_BYNODESET) {
 452     ret = hwloc_get_proc_membind_by_nodeset(topology, pid, set, policy, flags);
 453   } else {
 454     hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
 455     ret = hwloc_get_proc_membind_by_nodeset(topology, pid, nodeset, policy, flags);
 456     if (!ret)
 457       hwloc_cpuset_from_nodeset(topology, set, nodeset);
 458     hwloc_bitmap_free(nodeset);
 459   }
 460 
 461   return ret;
 462 }
 463 
 464 static int
 465 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)
 466 {
 467   if ((flags & ~HWLOC_MEMBIND_ALLFLAGS) || hwloc__check_membind_policy(policy) < 0) {
 468     errno = EINVAL;
 469     return -1;
 470   }
 471 
 472   if (!len)
 473     /* nothing to do */
 474     return 0;
 475 
 476   nodeset = hwloc_fix_membind(topology, nodeset);
 477   if (!nodeset)
 478     return -1;
 479 
 480   if (topology->binding_hooks.set_area_membind)
 481     return topology->binding_hooks.set_area_membind(topology, addr, len, nodeset, policy, flags);
 482 
 483   errno = ENOSYS;
 484   return -1;
 485 }
 486 
 487 int
 488 hwloc_set_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_bitmap_t set, hwloc_membind_policy_t policy, int flags)
 489 {
 490   int ret;
 491 
 492   if (flags & HWLOC_MEMBIND_BYNODESET) {
 493     ret = hwloc_set_area_membind_by_nodeset(topology, addr, len, set, policy, flags);
 494   } else {
 495     hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
 496     if (hwloc_fix_membind_cpuset(topology, nodeset, set))
 497       ret = -1;
 498     else
 499       ret = hwloc_set_area_membind_by_nodeset(topology, addr, len, nodeset, policy, flags);
 500     hwloc_bitmap_free(nodeset);
 501   }
 502 
 503   return ret;
 504 }
 505 
 506 static int
 507 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)
 508 {
 509   if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
 510     errno = EINVAL;
 511     return -1;
 512   }
 513 
 514   if (!len) {
 515     /* nothing to query */
 516     errno = EINVAL;
 517     return -1;
 518   }
 519 
 520   if (topology->binding_hooks.get_area_membind)
 521     return topology->binding_hooks.get_area_membind(topology, addr, len, nodeset, policy, flags);
 522 
 523   errno = ENOSYS;
 524   return -1;
 525 }
 526 
 527 int
 528 hwloc_get_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags)
 529 {
 530   int ret;
 531 
 532   if (flags & HWLOC_MEMBIND_BYNODESET) {
 533     ret = hwloc_get_area_membind_by_nodeset(topology, addr, len, set, policy, flags);
 534   } else {
 535     hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
 536     ret = hwloc_get_area_membind_by_nodeset(topology, addr, len, nodeset, policy, flags);
 537     if (!ret)
 538       hwloc_cpuset_from_nodeset(topology, set, nodeset);
 539     hwloc_bitmap_free(nodeset);
 540   }
 541 
 542   return ret;
 543 }
 544 
 545 static int
 546 hwloc_get_area_memlocation_by_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, int flags)
 547 {
 548   if (flags & ~HWLOC_MEMBIND_ALLFLAGS) {
 549     errno = EINVAL;
 550     return -1;
 551   }
 552 
 553   if (!len)
 554     /* nothing to do */
 555     return 0;
 556 
 557   if (topology->binding_hooks.get_area_memlocation)
 558     return topology->binding_hooks.get_area_memlocation(topology, addr, len, nodeset, flags);
 559 
 560   errno = ENOSYS;
 561   return -1;
 562 }
 563 
 564 int
 565 hwloc_get_area_memlocation(hwloc_topology_t topology, const void *addr, size_t len, hwloc_cpuset_t set, int flags)
 566 {
 567   int ret;
 568 
 569   if (flags & HWLOC_MEMBIND_BYNODESET) {
 570     ret = hwloc_get_area_memlocation_by_nodeset(topology, addr, len, set, flags);
 571   } else {
 572     hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
 573     ret = hwloc_get_area_memlocation_by_nodeset(topology, addr, len, nodeset, flags);
 574     if (!ret)
 575       hwloc_cpuset_from_nodeset(topology, set, nodeset);
 576     hwloc_bitmap_free(nodeset);
 577   }
 578 
 579   return ret;
 580 }
 581 
 582 void *
 583 hwloc_alloc_heap(hwloc_topology_t topology __hwloc_attribute_unused, size_t len)
 584 {
 585   void *p = NULL;
 586 #if defined(hwloc_getpagesize) && defined(HAVE_POSIX_MEMALIGN)
 587   errno = posix_memalign(&p, hwloc_getpagesize(), len);
 588   if (errno)
 589     p = NULL;
 590 #elif defined(hwloc_getpagesize) && defined(HAVE_MEMALIGN)
 591   p = memalign(hwloc_getpagesize(), len);
 592 #else
 593   p = malloc(len);
 594 #endif
 595   return p;
 596 }
 597 
 598 #ifdef MAP_ANONYMOUS
 599 void *
 600 hwloc_alloc_mmap(hwloc_topology_t topology __hwloc_attribute_unused, size_t len)
 601 {
 602   void * buffer = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
 603   return buffer == MAP_FAILED ? NULL : buffer;
 604 }
 605 #endif
 606 
 607 int
 608 hwloc_free_heap(hwloc_topology_t topology __hwloc_attribute_unused, void *addr, size_t len __hwloc_attribute_unused)
 609 {
 610   free(addr);
 611   return 0;
 612 }
 613 
 614 #ifdef MAP_ANONYMOUS
 615 int
 616 hwloc_free_mmap(hwloc_topology_t topology __hwloc_attribute_unused, void *addr, size_t len)
 617 {
 618   if (!addr)
 619     return 0;
 620   return munmap(addr, len);
 621 }
 622 #endif
 623 
 624 void *
 625 hwloc_alloc(hwloc_topology_t topology, size_t len)
 626 {
 627   if (topology->binding_hooks.alloc)
 628     return topology->binding_hooks.alloc(topology, len);
 629   return hwloc_alloc_heap(topology, len);
 630 }
 631 
 632 static void *
 633 hwloc_alloc_membind_by_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags)
 634 {
 635   void *p;
 636 
 637   if ((flags & ~HWLOC_MEMBIND_ALLFLAGS) || hwloc__check_membind_policy(policy) < 0) {
 638     errno = EINVAL;
 639     return NULL;
 640   }
 641 
 642   nodeset = hwloc_fix_membind(topology, nodeset);
 643   if (!nodeset)
 644     goto fallback;
 645   if (flags & HWLOC_MEMBIND_MIGRATE) {
 646     errno = EINVAL;
 647     goto fallback;
 648   }
 649 
 650   if (topology->binding_hooks.alloc_membind)
 651     return topology->binding_hooks.alloc_membind(topology, len, nodeset, policy, flags);
 652   else if (topology->binding_hooks.set_area_membind) {
 653     p = hwloc_alloc(topology, len);
 654     if (!p)
 655       return NULL;
 656     if (topology->binding_hooks.set_area_membind(topology, p, len, nodeset, policy, flags) && flags & HWLOC_MEMBIND_STRICT) {
 657       int error = errno;
 658       free(p);
 659       errno = error;
 660       return NULL;
 661     }
 662     return p;
 663   } else {
 664     errno = ENOSYS;
 665   }
 666 
 667 fallback:
 668   if (flags & HWLOC_MEMBIND_STRICT)
 669     /* Report error */
 670     return NULL;
 671   /* Never mind, allocate anyway */
 672   return hwloc_alloc(topology, len);
 673 }
 674 
 675 void *
 676 hwloc_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_bitmap_t set, hwloc_membind_policy_t policy, int flags)
 677 {
 678   void *ret;
 679 
 680   if (flags & HWLOC_MEMBIND_BYNODESET) {
 681     ret = hwloc_alloc_membind_by_nodeset(topology, len, set, policy, flags);
 682   } else {
 683     hwloc_nodeset_t nodeset = hwloc_bitmap_alloc();
 684     if (hwloc_fix_membind_cpuset(topology, nodeset, set)) {
 685       if (flags & HWLOC_MEMBIND_STRICT)
 686         ret = NULL;
 687       else
 688         ret = hwloc_alloc(topology, len);
 689     } else
 690       ret = hwloc_alloc_membind_by_nodeset(topology, len, nodeset, policy, flags);
 691     hwloc_bitmap_free(nodeset);
 692   }
 693 
 694   return ret;
 695 }
 696 
 697 int
 698 hwloc_free(hwloc_topology_t topology, void *addr, size_t len)
 699 {
 700   if (topology->binding_hooks.free_membind)
 701     return topology->binding_hooks.free_membind(topology, addr, len);
 702   return hwloc_free_heap(topology, addr, len);
 703 }
 704 
 705 /*
 706  * Empty binding hooks always returning success
 707  */
 708 
 709 static int dontset_return_complete_cpuset(hwloc_topology_t topology, hwloc_cpuset_t set)
 710 {
 711   hwloc_bitmap_copy(set, hwloc_topology_get_complete_cpuset(topology));
 712   return 0;
 713 }
 714 
 715 static int dontset_thisthread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
 716 {
 717   return 0;
 718 }
 719 static int dontget_thisthread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, int flags __hwloc_attribute_unused)
 720 {
 721   return dontset_return_complete_cpuset(topology, set);
 722 }
 723 static int dontset_thisproc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
 724 {
 725   return 0;
 726 }
 727 static int dontget_thisproc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, int flags __hwloc_attribute_unused)
 728 {
 729   return dontset_return_complete_cpuset(topology, set);
 730 }
 731 static int dontset_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
 732 {
 733   return 0;
 734 }
 735 static int dontget_proc_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_bitmap_t cpuset, int flags __hwloc_attribute_unused)
 736 {
 737   return dontset_return_complete_cpuset(topology, cpuset);
 738 }
 739 #ifdef hwloc_thread_t
 740 static int dontset_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
 741 {
 742   return 0;
 743 }
 744 static int dontget_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid __hwloc_attribute_unused, hwloc_bitmap_t cpuset, int flags __hwloc_attribute_unused)
 745 {
 746   return dontset_return_complete_cpuset(topology, cpuset);
 747 }
 748 #endif
 749 
 750 static int dontset_return_complete_nodeset(hwloc_topology_t topology, hwloc_nodeset_t set, hwloc_membind_policy_t *policy)
 751 {
 752   hwloc_bitmap_copy(set, hwloc_topology_get_complete_nodeset(topology));
 753   *policy = HWLOC_MEMBIND_MIXED;
 754   return 0;
 755 }
 756 
 757 static int dontset_thisproc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
 758 {
 759   return 0;
 760 }
 761 static int dontget_thisproc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused)
 762 {
 763   return dontset_return_complete_nodeset(topology, set, policy);
 764 }
 765 
 766 static int dontset_thisthread_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
 767 {
 768   return 0;
 769 }
 770 static int dontget_thisthread_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused)
 771 {
 772   return dontset_return_complete_nodeset(topology, set, policy);
 773 }
 774 
 775 static int dontset_proc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
 776 {
 777   return 0;
 778 }
 779 static int dontget_proc_membind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_pid_t pid __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused)
 780 {
 781   return dontset_return_complete_nodeset(topology, set, policy);
 782 }
 783 
 784 static int dontset_area_membind(hwloc_topology_t topology __hwloc_attribute_unused, const void *addr __hwloc_attribute_unused, size_t size __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
 785 {
 786   return 0;
 787 }
 788 static int dontget_area_membind(hwloc_topology_t topology __hwloc_attribute_unused, const void *addr __hwloc_attribute_unused, size_t size __hwloc_attribute_unused, hwloc_bitmap_t set, hwloc_membind_policy_t * policy, int flags __hwloc_attribute_unused)
 789 {
 790   return dontset_return_complete_nodeset(topology, set, policy);
 791 }
 792 static int dontget_area_memlocation(hwloc_topology_t topology __hwloc_attribute_unused, const void *addr __hwloc_attribute_unused, size_t size __hwloc_attribute_unused, hwloc_bitmap_t set, int flags __hwloc_attribute_unused)
 793 {
 794   hwloc_membind_policy_t policy;
 795   return dontset_return_complete_nodeset(topology, set, &policy);
 796 }
 797 
 798 static void * dontalloc_membind(hwloc_topology_t topology __hwloc_attribute_unused, size_t size __hwloc_attribute_unused, hwloc_const_bitmap_t set __hwloc_attribute_unused, hwloc_membind_policy_t policy __hwloc_attribute_unused, int flags __hwloc_attribute_unused)
 799 {
 800   return malloc(size);
 801 }
 802 static int dontfree_membind(hwloc_topology_t topology __hwloc_attribute_unused, void *addr __hwloc_attribute_unused, size_t size __hwloc_attribute_unused)
 803 {
 804   free(addr);
 805   return 0;
 806 }
 807 
 808 static void hwloc_set_dummy_hooks(struct hwloc_binding_hooks *hooks,
 809                                   struct hwloc_topology_support *support __hwloc_attribute_unused)
 810 {
 811   hooks->set_thisproc_cpubind = dontset_thisproc_cpubind;
 812   hooks->get_thisproc_cpubind = dontget_thisproc_cpubind;
 813   hooks->set_thisthread_cpubind = dontset_thisthread_cpubind;
 814   hooks->get_thisthread_cpubind = dontget_thisthread_cpubind;
 815   hooks->set_proc_cpubind = dontset_proc_cpubind;
 816   hooks->get_proc_cpubind = dontget_proc_cpubind;
 817 #ifdef hwloc_thread_t
 818   hooks->set_thread_cpubind = dontset_thread_cpubind;
 819   hooks->get_thread_cpubind = dontget_thread_cpubind;
 820 #endif
 821   hooks->get_thisproc_last_cpu_location = dontget_thisproc_cpubind; /* cpubind instead of last_cpu_location is ok */
 822   hooks->get_thisthread_last_cpu_location = dontget_thisthread_cpubind; /* cpubind instead of last_cpu_location is ok */
 823   hooks->get_proc_last_cpu_location = dontget_proc_cpubind; /* cpubind instead of last_cpu_location is ok */
 824   /* TODO: get_thread_last_cpu_location */
 825   hooks->set_thisproc_membind = dontset_thisproc_membind;
 826   hooks->get_thisproc_membind = dontget_thisproc_membind;
 827   hooks->set_thisthread_membind = dontset_thisthread_membind;
 828   hooks->get_thisthread_membind = dontget_thisthread_membind;
 829   hooks->set_proc_membind = dontset_proc_membind;
 830   hooks->get_proc_membind = dontget_proc_membind;
 831   hooks->set_area_membind = dontset_area_membind;
 832   hooks->get_area_membind = dontget_area_membind;
 833   hooks->get_area_memlocation = dontget_area_memlocation;
 834   hooks->alloc_membind = dontalloc_membind;
 835   hooks->free_membind = dontfree_membind;
 836 }
 837 
 838 void
 839 hwloc_set_native_binding_hooks(struct hwloc_binding_hooks *hooks, struct hwloc_topology_support *support)
 840 {
 841 #    ifdef HWLOC_LINUX_SYS
 842     hwloc_set_linuxfs_hooks(hooks, support);
 843 #    endif /* HWLOC_LINUX_SYS */
 844 
 845 #    ifdef HWLOC_BGQ_SYS
 846     hwloc_set_bgq_hooks(hooks, support);
 847 #    endif /* HWLOC_BGQ_SYS */
 848 
 849 #    ifdef HWLOC_AIX_SYS
 850     hwloc_set_aix_hooks(hooks, support);
 851 #    endif /* HWLOC_AIX_SYS */
 852 
 853 #    ifdef HWLOC_SOLARIS_SYS
 854     hwloc_set_solaris_hooks(hooks, support);
 855 #    endif /* HWLOC_SOLARIS_SYS */
 856 
 857 #    ifdef HWLOC_WIN_SYS
 858     hwloc_set_windows_hooks(hooks, support);
 859 #    endif /* HWLOC_WIN_SYS */
 860 
 861 #    ifdef HWLOC_DARWIN_SYS
 862     hwloc_set_darwin_hooks(hooks, support);
 863 #    endif /* HWLOC_DARWIN_SYS */
 864 
 865 #    ifdef HWLOC_FREEBSD_SYS
 866     hwloc_set_freebsd_hooks(hooks, support);
 867 #    endif /* HWLOC_FREEBSD_SYS */
 868 
 869 #    ifdef HWLOC_NETBSD_SYS
 870     hwloc_set_netbsd_hooks(hooks, support);
 871 #    endif /* HWLOC_NETBSD_SYS */
 872 
 873 #    ifdef HWLOC_HPUX_SYS
 874     hwloc_set_hpux_hooks(hooks, support);
 875 #    endif /* HWLOC_HPUX_SYS */
 876 }
 877 
 878 /* If the represented system is actually not this system, use dummy binding hooks. */
 879 void
 880 hwloc_set_binding_hooks(struct hwloc_topology *topology)
 881 {
 882   if (topology->is_thissystem) {
 883     hwloc_set_native_binding_hooks(&topology->binding_hooks, &topology->support);
 884     /* every hook not set above will return ENOSYS */
 885   } else {
 886     /* not this system, use dummy binding hooks that do nothing (but don't return ENOSYS) */
 887     hwloc_set_dummy_hooks(&topology->binding_hooks, &topology->support);
 888   }
 889 
 890   /* if not is_thissystem, set_cpubind is fake
 891    * and get_cpubind returns the whole system cpuset,
 892    * so don't report that set/get_cpubind as supported
 893    */
 894   if (topology->is_thissystem) {
 895 #define DO(which,kind) \
 896     if (topology->binding_hooks.kind) \
 897       topology->support.which##bind->kind = 1;
 898     DO(cpu,set_thisproc_cpubind);
 899     DO(cpu,get_thisproc_cpubind);
 900     DO(cpu,set_proc_cpubind);
 901     DO(cpu,get_proc_cpubind);
 902     DO(cpu,set_thisthread_cpubind);
 903     DO(cpu,get_thisthread_cpubind);
 904 #ifdef hwloc_thread_t
 905     DO(cpu,set_thread_cpubind);
 906     DO(cpu,get_thread_cpubind);
 907 #endif
 908     DO(cpu,get_thisproc_last_cpu_location);
 909     DO(cpu,get_proc_last_cpu_location);
 910     DO(cpu,get_thisthread_last_cpu_location);
 911     DO(mem,set_thisproc_membind);
 912     DO(mem,get_thisproc_membind);
 913     DO(mem,set_thisthread_membind);
 914     DO(mem,get_thisthread_membind);
 915     DO(mem,set_proc_membind);
 916     DO(mem,get_proc_membind);
 917     DO(mem,set_area_membind);
 918     DO(mem,get_area_membind);
 919     DO(mem,get_area_memlocation);
 920     DO(mem,alloc_membind);
 921   }
 922 }

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