diff options
Diffstat (limited to 'hwloc-1.2.1/src/bind.c')
-rw-r--r-- | hwloc-1.2.1/src/bind.c | 552 |
1 files changed, 552 insertions, 0 deletions
diff --git a/hwloc-1.2.1/src/bind.c b/hwloc-1.2.1/src/bind.c new file mode 100644 index 00000000..745cdade --- /dev/null +++ b/hwloc-1.2.1/src/bind.c @@ -0,0 +1,552 @@ +/* + * Copyright © 2009 CNRS + * Copyright © 2009-2011 INRIA. All rights reserved. + * Copyright © 2009-2010 Université Bordeaux 1 + * Copyright © 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 <hwloc/helper.h> +#ifdef HAVE_SYS_MMAN_H +# include <sys/mman.h> +#endif +#ifdef HAVE_MALLOC_H +# include <malloc.h> +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <errno.h> + +/* TODO: HWLOC_GNU_SYS, HWLOC_IRIX_SYS, + * + * IRIX: see MP_MUSTRUN / _DSM_MUSTRUN, pthread_setrunon_np, /hw, procss_cpulink, numa_create + * + * We could use glibc's sched_setaffinity generically when it is available + * + * Darwin and OpenBSD don't seem to have binding facilities. + */ + +static hwloc_const_bitmap_t +hwloc_fix_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t set) +{ + hwloc_const_bitmap_t topology_set = hwloc_topology_get_topology_cpuset(topology); + hwloc_const_bitmap_t complete_set = hwloc_topology_get_complete_cpuset(topology); + + if (!topology_set) { + /* The topology is composed of several systems, the cpuset is ambiguous. */ + errno = EXDEV; + return NULL; + } + + if (hwloc_bitmap_iszero(set)) { + errno = EINVAL; + return NULL; + } + + if (!hwloc_bitmap_isincluded(set, complete_set)) { + errno = EINVAL; + return NULL; + } + + if (hwloc_bitmap_isincluded(topology_set, set)) + set = complete_set; + + return set; +} + +int +hwloc_set_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t set, int flags) +{ + set = hwloc_fix_cpubind(topology, set); + if (!set) + return -1; + + if (flags & HWLOC_CPUBIND_PROCESS) { + if (topology->set_thisproc_cpubind) + return topology->set_thisproc_cpubind(topology, set, flags); + } else if (flags & HWLOC_CPUBIND_THREAD) { + if (topology->set_thisthread_cpubind) + return topology->set_thisthread_cpubind(topology, set, flags); + } else { + if (topology->set_thisproc_cpubind) + return topology->set_thisproc_cpubind(topology, set, flags); + else if (topology->set_thisthread_cpubind) + return topology->set_thisthread_cpubind(topology, set, flags); + } + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_cpubind(hwloc_topology_t topology, hwloc_bitmap_t set, int flags) +{ + if (flags & HWLOC_CPUBIND_PROCESS) { + if (topology->get_thisproc_cpubind) + return topology->get_thisproc_cpubind(topology, set, flags); + } else if (flags & HWLOC_CPUBIND_THREAD) { + if (topology->get_thisthread_cpubind) + return topology->get_thisthread_cpubind(topology, set, flags); + } else { + if (topology->get_thisproc_cpubind) + return topology->get_thisproc_cpubind(topology, set, flags); + else if (topology->get_thisthread_cpubind) + return topology->get_thisthread_cpubind(topology, set, flags); + } + + errno = ENOSYS; + return -1; +} + +int +hwloc_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t set, int flags) +{ + set = hwloc_fix_cpubind(topology, set); + if (!set) + return -1; + + if (topology->set_proc_cpubind) + return topology->set_proc_cpubind(topology, pid, set, flags); + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t set, int flags) +{ + if (topology->get_proc_cpubind) + return topology->get_proc_cpubind(topology, pid, set, flags); + + errno = ENOSYS; + return -1; +} + +#ifdef hwloc_thread_t +int +hwloc_set_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_const_bitmap_t set, int flags) +{ + set = hwloc_fix_cpubind(topology, set); + if (!set) + return -1; + + if (topology->set_thread_cpubind) + return topology->set_thread_cpubind(topology, tid, set, flags); + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_thread_cpubind(hwloc_topology_t topology, hwloc_thread_t tid, hwloc_bitmap_t set, int flags) +{ + if (topology->get_thread_cpubind) + return topology->get_thread_cpubind(topology, tid, set, flags); + + errno = ENOSYS; + return -1; +} +#endif + +int +hwloc_get_last_cpu_location(hwloc_topology_t topology, hwloc_bitmap_t set, int flags) +{ + if (flags & HWLOC_CPUBIND_PROCESS) { + if (topology->get_thisproc_last_cpu_location) + return topology->get_thisproc_last_cpu_location(topology, set, flags); + } else if (flags & HWLOC_CPUBIND_THREAD) { + if (topology->get_thisthread_last_cpu_location) + return topology->get_thisthread_last_cpu_location(topology, set, flags); + } else { + if (topology->get_thisproc_last_cpu_location) + return topology->get_thisproc_last_cpu_location(topology, set, flags); + else if (topology->get_thisthread_last_cpu_location) + return topology->get_thisthread_last_cpu_location(topology, set, flags); + } + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_proc_last_cpu_location(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t set, int flags) +{ + if (topology->get_proc_last_cpu_location) + return topology->get_proc_last_cpu_location(topology, pid, set, flags); + + errno = ENOSYS; + return -1; +} + +static hwloc_const_nodeset_t +hwloc_fix_membind(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset) +{ + hwloc_const_bitmap_t topology_nodeset = hwloc_topology_get_topology_nodeset(topology); + hwloc_const_bitmap_t complete_nodeset = hwloc_topology_get_complete_nodeset(topology); + + if (!hwloc_topology_get_topology_cpuset(topology)) { + /* The topology is composed of several systems, the nodeset is thus + * ambiguous. */ + errno = EXDEV; + return NULL; + } + + if (!complete_nodeset) { + /* There is no NUMA node */ + errno = ENODEV; + return NULL; + } + + if (hwloc_bitmap_iszero(nodeset)) { + errno = EINVAL; + return NULL; + } + + if (!hwloc_bitmap_isincluded(nodeset, complete_nodeset)) { + errno = EINVAL; + return NULL; + } + + if (hwloc_bitmap_isincluded(topology_nodeset, nodeset)) + return complete_nodeset; + + return nodeset; +} + +static int +hwloc_fix_membind_cpuset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_const_cpuset_t cpuset) +{ + hwloc_const_bitmap_t topology_set = hwloc_topology_get_topology_cpuset(topology); + hwloc_const_bitmap_t complete_set = hwloc_topology_get_complete_cpuset(topology); + hwloc_const_bitmap_t complete_nodeset = hwloc_topology_get_complete_nodeset(topology); + + if (!topology_set) { + /* The topology is composed of several systems, the cpuset is thus + * ambiguous. */ + errno = EXDEV; + return -1; + } + + if (!complete_nodeset) { + /* There is no NUMA node */ + errno = ENODEV; + return -1; + } + + if (hwloc_bitmap_iszero(cpuset)) { + errno = EINVAL; + return -1; + } + + if (!hwloc_bitmap_isincluded(cpuset, complete_set)) { + errno = EINVAL; + return -1; + } + + if (hwloc_bitmap_isincluded(topology_set, cpuset)) { + hwloc_bitmap_copy(nodeset, complete_nodeset); + return 0; + } + + hwloc_cpuset_to_nodeset(topology, cpuset, nodeset); + return 0; +} + +int +hwloc_set_membind_nodeset(hwloc_topology_t topology, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + nodeset = hwloc_fix_membind(topology, nodeset); + if (!nodeset) + return -1; + + if (flags & HWLOC_MEMBIND_PROCESS) { + if (topology->set_thisproc_membind) + return topology->set_thisproc_membind(topology, nodeset, policy, flags); + } else if (flags & HWLOC_MEMBIND_THREAD) { + if (topology->set_thisthread_membind) + return topology->set_thisthread_membind(topology, nodeset, policy, flags); + } else { + if (topology->set_thisproc_membind) + return topology->set_thisproc_membind(topology, nodeset, policy, flags); + else if (topology->set_thisthread_membind) + return topology->set_thisthread_membind(topology, nodeset, policy, flags); + } + + errno = ENOSYS; + return -1; +} + +int +hwloc_set_membind(hwloc_topology_t topology, hwloc_const_cpuset_t set, hwloc_membind_policy_t policy, int flags) +{ + hwloc_nodeset_t nodeset = hwloc_bitmap_alloc(); + int ret; + + if (hwloc_fix_membind_cpuset(topology, nodeset, set)) + ret = -1; + else + ret = hwloc_set_membind_nodeset(topology, nodeset, policy, flags); + + hwloc_bitmap_free(nodeset); + return ret; +} + +int +hwloc_get_membind_nodeset(hwloc_topology_t topology, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) +{ + if (flags & HWLOC_MEMBIND_PROCESS) { + if (topology->get_thisproc_membind) + return topology->get_thisproc_membind(topology, nodeset, policy, flags); + } else if (flags & HWLOC_MEMBIND_THREAD) { + if (topology->get_thisthread_membind) + return topology->get_thisthread_membind(topology, nodeset, policy, flags); + } else { + if (topology->get_thisproc_membind) + return topology->get_thisproc_membind(topology, nodeset, policy, flags); + else if (topology->get_thisthread_membind) + return topology->get_thisthread_membind(topology, nodeset, policy, flags); + } + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_membind(hwloc_topology_t topology, hwloc_cpuset_t set, hwloc_membind_policy_t * policy, int flags) +{ + hwloc_nodeset_t nodeset; + int ret; + + nodeset = hwloc_bitmap_alloc(); + ret = hwloc_get_membind_nodeset(topology, nodeset, policy, flags); + + if (!ret) + hwloc_cpuset_from_nodeset(topology, set, nodeset); + + return ret; +} + +int +hwloc_set_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + nodeset = hwloc_fix_membind(topology, nodeset); + if (!nodeset) + return -1; + + if (topology->set_proc_membind) + return topology->set_proc_membind(topology, pid, nodeset, policy, flags); + + errno = ENOSYS; + return -1; +} + + +int +hwloc_set_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_cpuset_t set, hwloc_membind_policy_t policy, int flags) +{ + hwloc_nodeset_t nodeset = hwloc_bitmap_alloc(); + int ret; + + if (hwloc_fix_membind_cpuset(topology, nodeset, set)) + ret = -1; + else + ret = hwloc_set_proc_membind_nodeset(topology, pid, nodeset, policy, flags); + + hwloc_bitmap_free(nodeset); + return ret; +} + +int +hwloc_get_proc_membind_nodeset(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) +{ + if (topology->get_proc_membind) + return topology->get_proc_membind(topology, pid, nodeset, policy, flags); + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_proc_membind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_cpuset_t set, hwloc_membind_policy_t * policy, int flags) +{ + hwloc_nodeset_t nodeset; + int ret; + + nodeset = hwloc_bitmap_alloc(); + ret = hwloc_get_proc_membind_nodeset(topology, pid, nodeset, policy, flags); + + if (!ret) + hwloc_cpuset_from_nodeset(topology, set, nodeset); + + return ret; +} + +int +hwloc_set_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + nodeset = hwloc_fix_membind(topology, nodeset); + if (!nodeset) + return -1; + + if (topology->set_area_membind) + return topology->set_area_membind(topology, addr, len, nodeset, policy, flags); + + errno = ENOSYS; + return -1; +} + +int +hwloc_set_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_const_cpuset_t set, hwloc_membind_policy_t policy, int flags) +{ + hwloc_nodeset_t nodeset = hwloc_bitmap_alloc(); + int ret; + + if (hwloc_fix_membind_cpuset(topology, nodeset, set)) + ret = -1; + else + ret = hwloc_set_area_membind_nodeset(topology, addr, len, nodeset, policy, flags); + + hwloc_bitmap_free(nodeset); + return ret; +} + +int +hwloc_get_area_membind_nodeset(hwloc_topology_t topology, const void *addr, size_t len, hwloc_nodeset_t nodeset, hwloc_membind_policy_t * policy, int flags) +{ + if (topology->get_area_membind) + return topology->get_area_membind(topology, addr, len, nodeset, policy, flags); + + errno = ENOSYS; + return -1; +} + +int +hwloc_get_area_membind(hwloc_topology_t topology, const void *addr, size_t len, hwloc_cpuset_t set, hwloc_membind_policy_t * policy, int flags) +{ + hwloc_nodeset_t nodeset; + int ret; + + nodeset = hwloc_bitmap_alloc(); + ret = hwloc_get_area_membind_nodeset(topology, addr, len, nodeset, policy, flags); + + if (!ret) + hwloc_cpuset_from_nodeset(topology, set, nodeset); + + return ret; +} + +void * +hwloc_alloc_heap(hwloc_topology_t topology __hwloc_attribute_unused, size_t len) +{ + void *p; +#if defined(HAVE_GETPAGESIZE) && defined(HAVE_POSIX_MEMALIGN) + errno = posix_memalign(&p, getpagesize(), len); + if (errno) + p = NULL; +#elif defined(HAVE_GETPAGESIZE) && defined(HAVE_MEMALIGN) + p = memalign(getpagesize(), len); +#else + p = malloc(len); +#endif + return p; +} + +#ifdef MAP_ANONYMOUS +void * +hwloc_alloc_mmap(hwloc_topology_t topology __hwloc_attribute_unused, size_t len) +{ + return mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); +} +#endif + +int +hwloc_free_heap(hwloc_topology_t topology __hwloc_attribute_unused, void *addr, size_t len __hwloc_attribute_unused) +{ + free(addr); + return 0; +} + +#ifdef MAP_ANONYMOUS +int +hwloc_free_mmap(hwloc_topology_t topology __hwloc_attribute_unused, void *addr, size_t len) +{ + if (!addr) + return 0; + return munmap(addr, len); +} +#endif + +void * +hwloc_alloc(hwloc_topology_t topology, size_t len) +{ + if (topology->alloc) + return topology->alloc(topology, len); + return hwloc_alloc_heap(topology, len); +} + +void * +hwloc_alloc_membind_nodeset(hwloc_topology_t topology, size_t len, hwloc_const_nodeset_t nodeset, hwloc_membind_policy_t policy, int flags) +{ + void *p; + nodeset = hwloc_fix_membind(topology, nodeset); + if (!nodeset) + goto fallback; + if (flags & HWLOC_MEMBIND_MIGRATE) { + errno = EINVAL; + goto fallback; + } + + if (topology->alloc_membind) + return topology->alloc_membind(topology, len, nodeset, policy, flags); + else if (topology->set_area_membind) { + p = hwloc_alloc(topology, len); + if (!p) + return NULL; + if (topology->set_area_membind(topology, p, len, nodeset, policy, flags) && flags & HWLOC_MEMBIND_STRICT) { + int error = errno; + free(p); + errno = error; + return NULL; + } + return p; + } else { + errno = ENOSYS; + } + +fallback: + if (flags & HWLOC_MEMBIND_STRICT) + /* Report error */ + return NULL; + /* Never mind, allocate anyway */ + return hwloc_alloc(topology, len); +} + +void * +hwloc_alloc_membind(hwloc_topology_t topology, size_t len, hwloc_const_cpuset_t set, hwloc_membind_policy_t policy, int flags) +{ + hwloc_nodeset_t nodeset = hwloc_bitmap_alloc(); + void *ret; + + if (!hwloc_fix_membind_cpuset(topology, nodeset, set)) { + if (flags & HWLOC_MEMBIND_STRICT) + ret = NULL; + else + ret = hwloc_alloc(topology, len); + } else + ret = hwloc_alloc_membind_nodeset(topology, len, nodeset, policy, flags); + + hwloc_bitmap_free(nodeset); + return ret; +} + +int +hwloc_free(hwloc_topology_t topology, void *addr, size_t len) +{ + if (topology->free_membind) + return topology->free_membind(topology, addr, len); + return hwloc_free_heap(topology, addr, len); +} |