blob: 90faf96aab08cfff39ffa8858c885aac00a8443c [file] [log] [blame] [raw]
/*
* 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 <private/autogen/config.h>
#include <sys/types.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/param.h>
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
#ifdef HAVE_SYS_CPUSET_H
#include <sys/cpuset.h>
#endif
#include <hwloc.h>
#include <private/private.h>
#include <private/debug.h>
#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 */
}