/* * 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. */ #include #include #include #include #include #include #ifdef HAVE_PTHREAD_NP_H #include #endif #ifdef HAVE_SYS_CPUSET_H #include #endif #include #include #include #ifdef HAVE_SYS_CPUSET_H static void hwloc_freebsd_bsd2hwloc(hwloc_bitmap_t hwloc_cpuset, const cpuset_t *cpuset) { unsigned cpu; hwloc_bitmap_zero(hwloc_cpuset); for (cpu = 0; cpu < CPU_SETSIZE; cpu++) if (CPU_ISSET(cpu, cpuset)) hwloc_bitmap_set(hwloc_cpuset, cpu); } static void hwloc_freebsd_hwloc2bsd(hwloc_const_bitmap_t hwloc_cpuset, cpuset_t *cpuset) { unsigned cpu; CPU_ZERO(cpuset); for (cpu = 0; cpu < CPU_SETSIZE; cpu++) if (hwloc_bitmap_isset(hwloc_cpuset, cpu)) CPU_SET(cpu, cpuset); } static int hwloc_freebsd_set_sth_affinity(hwloc_topology_t topology __hwloc_attribute_unused, cpulevel_t level, cpuwhich_t which, id_t id, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) { cpuset_t cpuset; hwloc_freebsd_hwloc2bsd(hwloc_cpuset, &cpuset); if (cpuset_setaffinity(level, which, id, sizeof(cpuset), &cpuset)) return -1; return 0; } static int hwloc_freebsd_get_sth_affinity(hwloc_topology_t topology __hwloc_attribute_unused, cpulevel_t level, cpuwhich_t which, id_t id, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) { cpuset_t cpuset; if (cpuset_getaffinity(level, which, id, sizeof(cpuset), &cpuset)) return -1; hwloc_freebsd_bsd2hwloc(hwloc_cpuset, &cpuset); return 0; } static int hwloc_freebsd_set_thisproc_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags) { return hwloc_freebsd_set_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, hwloc_cpuset, flags); } static int hwloc_freebsd_get_thisproc_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags) { return hwloc_freebsd_get_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, hwloc_cpuset, flags); } static int hwloc_freebsd_set_thisthread_cpubind(hwloc_topology_t topology, hwloc_const_bitmap_t hwloc_cpuset, int flags) { return hwloc_freebsd_set_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, hwloc_cpuset, flags); } static int hwloc_freebsd_get_thisthread_cpubind(hwloc_topology_t topology, hwloc_bitmap_t hwloc_cpuset, int flags) { return hwloc_freebsd_get_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, hwloc_cpuset, flags); } static int hwloc_freebsd_set_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_const_bitmap_t hwloc_cpuset, int flags) { return hwloc_freebsd_set_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, hwloc_cpuset, flags); } static int hwloc_freebsd_get_proc_cpubind(hwloc_topology_t topology, hwloc_pid_t pid, hwloc_bitmap_t hwloc_cpuset, int flags) { return hwloc_freebsd_get_sth_affinity(topology, CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, hwloc_cpuset, flags); } #ifdef hwloc_thread_t #if HAVE_DECL_PTHREAD_SETAFFINITY_NP #pragma weak pthread_setaffinity_np static int hwloc_freebsd_set_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_const_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) { int err; cpuset_t cpuset; if (!pthread_setaffinity_np) { errno = ENOSYS; return -1; } hwloc_freebsd_hwloc2bsd(hwloc_cpuset, &cpuset); err = pthread_setaffinity_np(tid, sizeof(cpuset), &cpuset); if (err) { errno = err; return -1; } return 0; } #endif #if HAVE_DECL_PTHREAD_GETAFFINITY_NP #pragma weak pthread_getaffinity_np static int hwloc_freebsd_get_thread_cpubind(hwloc_topology_t topology __hwloc_attribute_unused, hwloc_thread_t tid, hwloc_bitmap_t hwloc_cpuset, int flags __hwloc_attribute_unused) { int err; cpuset_t cpuset; if (!pthread_getaffinity_np) { errno = ENOSYS; return -1; } err = pthread_getaffinity_np(tid, sizeof(cpuset), &cpuset); if (err) { errno = err; return -1; } hwloc_freebsd_bsd2hwloc(hwloc_cpuset, &cpuset); return 0; } #endif #endif #endif void hwloc_look_freebsd(struct hwloc_topology *topology) { unsigned nbprocs = hwloc_fallback_nbprocessors(topology); #ifdef HAVE__SC_LARGE_PAGESIZE topology->levels[0][0]->attr->machine.huge_page_size_kB = sysconf(_SC_LARGE_PAGESIZE); #endif hwloc_set_freebsd_hooks(topology); hwloc_look_x86(topology, nbprocs); hwloc_setup_pu_level(topology, nbprocs); hwloc_add_object_info(topology->levels[0][0], "Backend", "FreeBSD"); } void hwloc_set_freebsd_hooks(struct hwloc_topology *topology) { #ifdef HAVE_SYS_CPUSET_H topology->set_thisproc_cpubind = hwloc_freebsd_set_thisproc_cpubind; topology->get_thisproc_cpubind = hwloc_freebsd_get_thisproc_cpubind; topology->set_thisthread_cpubind = hwloc_freebsd_set_thisthread_cpubind; topology->get_thisthread_cpubind = hwloc_freebsd_get_thisthread_cpubind; topology->set_proc_cpubind = hwloc_freebsd_set_proc_cpubind; topology->get_proc_cpubind = hwloc_freebsd_get_proc_cpubind; #ifdef hwloc_thread_t #if HAVE_DECL_PTHREAD_SETAFFINITY_NP topology->set_thread_cpubind = hwloc_freebsd_set_thread_cpubind; #endif #if HAVE_DECL_PTHREAD_GETAFFINITY_NP topology->get_thread_cpubind = hwloc_freebsd_get_thread_cpubind; #endif #endif #endif /* TODO: get_last_cpu_location: find out ki_lastcpu */ }