summaryrefslogtreecommitdiffstats
path: root/hwloc-1.2.1/src/bind.c
diff options
context:
space:
mode:
Diffstat (limited to 'hwloc-1.2.1/src/bind.c')
-rw-r--r--hwloc-1.2.1/src/bind.c552
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);
+}