From f61f13d4e7e08b44629a1411ace53c5c6aeaf32b Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 8 Oct 2019 21:25:30 +0000 Subject: [PATCH] [OpenMP] Enable thread affinity on FreeBSD Reviewers: chandlerc, jlpeyton, jdoerfert, dim Reviewed-By: dim Differential Revision: https://reviews.llvm.org/D68580 llvm-svn: 374118 --- openmp/runtime/src/kmp.h | 2 +- openmp/runtime/src/kmp_affinity.cpp | 4 ++-- openmp/runtime/src/kmp_affinity.h | 17 ++++++++++++++++- openmp/runtime/src/kmp_os.h | 2 +- openmp/runtime/src/kmp_runtime.cpp | 8 ++++---- openmp/runtime/src/z_Linux_util.cpp | 32 +++++++++++++++++++++++++++----- 6 files changed, 51 insertions(+), 14 deletions(-) diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index a0b4202..23eebe67 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -3341,7 +3341,7 @@ extern int __kmp_aux_set_affinity_mask_proc(int proc, void **mask); extern int __kmp_aux_unset_affinity_mask_proc(int proc, void **mask); extern int __kmp_aux_get_affinity_mask_proc(int proc, void **mask); extern void __kmp_balanced_affinity(kmp_info_t *th, int team_size); -#if KMP_OS_LINUX +#if KMP_OS_LINUX || KMP_OS_FREEBSD extern int kmp_set_thread_affinity_mask_initial(void); #endif #endif /* KMP_AFFINITY_SUPPORTED */ diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp index 372c300..4c7ed31 100644 --- a/openmp/runtime/src/kmp_affinity.cpp +++ b/openmp/runtime/src/kmp_affinity.cpp @@ -1968,7 +1968,7 @@ static void __kmp_dispatch_set_hierarchy_values() { __kmp_hier_max_units[kmp_hier_layer_e::LAYER_THREAD + 1] = nPackages * nCoresPerPkg * __kmp_nThreadsPerCore; __kmp_hier_max_units[kmp_hier_layer_e::LAYER_L1 + 1] = __kmp_ncores; -#if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_WINDOWS) +#if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_WINDOWS) if (__kmp_mic_type >= mic3) __kmp_hier_max_units[kmp_hier_layer_e::LAYER_L2 + 1] = __kmp_ncores / 2; else @@ -1982,7 +1982,7 @@ static void __kmp_dispatch_set_hierarchy_values() { __kmp_hier_threads_per[kmp_hier_layer_e::LAYER_THREAD + 1] = 1; __kmp_hier_threads_per[kmp_hier_layer_e::LAYER_L1 + 1] = __kmp_nThreadsPerCore; -#if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_WINDOWS) +#if KMP_ARCH_X86_64 && (KMP_OS_LINUX || KMP_OS_FREEBSD || KMP_OS_WINDOWS) if (__kmp_mic_type >= mic3) __kmp_hier_threads_per[kmp_hier_layer_e::LAYER_L2 + 1] = 2 * __kmp_nThreadsPerCore; diff --git a/openmp/runtime/src/kmp_affinity.h b/openmp/runtime/src/kmp_affinity.h index c00ad36..f270bb6 100644 --- a/openmp/runtime/src/kmp_affinity.h +++ b/openmp/runtime/src/kmp_affinity.h @@ -160,6 +160,7 @@ public: }; #endif /* KMP_USE_HWLOC */ +#if KMP_OS_LINUX || KMP_OS_FREEBSD #if KMP_OS_LINUX /* On some of the older OS's that we build on, these constants aren't present in #included from . They must be the same on @@ -234,6 +235,10 @@ public: #endif /* __NR_sched_getaffinity */ #error Unknown or unsupported architecture #endif /* KMP_ARCH_* */ +#elif KMP_OS_FREEBSD +#include +#include +#endif class KMPNativeAffinity : public KMPAffinity { class Mask : public KMPAffinity::Mask { typedef unsigned char mask_t; @@ -294,8 +299,13 @@ class KMPNativeAffinity : public KMPAffinity { int get_system_affinity(bool abort_on_error) override { KMP_ASSERT2(KMP_AFFINITY_CAPABLE(), "Illegal get affinity operation when not capable"); +#if KMP_OS_LINUX int retval = syscall(__NR_sched_getaffinity, 0, __kmp_affin_mask_size, mask); +#elif KMP_OS_FREEBSD + int retval = + pthread_getaffinity_np(pthread_self(), __kmp_affin_mask_size, reinterpret_cast(mask)); +#endif if (retval >= 0) { return 0; } @@ -308,8 +318,13 @@ class KMPNativeAffinity : public KMPAffinity { int set_system_affinity(bool abort_on_error) const override { KMP_ASSERT2(KMP_AFFINITY_CAPABLE(), "Illegal get affinity operation when not capable"); +#if KMP_OS_LINUX int retval = syscall(__NR_sched_setaffinity, 0, __kmp_affin_mask_size, mask); +#elif KMP_OS_FREEBSD + int retval = + pthread_setaffinity_np(pthread_self(), __kmp_affin_mask_size, reinterpret_cast(mask)); +#endif if (retval >= 0) { return 0; } @@ -347,7 +362,7 @@ class KMPNativeAffinity : public KMPAffinity { } api_type get_api_type() const override { return NATIVE_OS; } }; -#endif /* KMP_OS_LINUX */ +#endif /* KMP_OS_LINUX || KMP_OS_FREEBSD */ #if KMP_OS_WINDOWS class KMPNativeAffinity : public KMPAffinity { diff --git a/openmp/runtime/src/kmp_os.h b/openmp/runtime/src/kmp_os.h index ca3af3a..cd942a9 100644 --- a/openmp/runtime/src/kmp_os.h +++ b/openmp/runtime/src/kmp_os.h @@ -69,7 +69,7 @@ #error Unknown compiler #endif -#if (KMP_OS_LINUX || KMP_OS_WINDOWS) && !KMP_OS_CNK +#if (KMP_OS_LINUX || KMP_OS_WINDOWS || KMP_OS_FREEBSD) && !KMP_OS_CNK #define KMP_AFFINITY_SUPPORTED 1 #if KMP_OS_WINDOWS && KMP_ARCH_X86_64 #define KMP_GROUP_AFFINITY 1 diff --git a/openmp/runtime/src/kmp_runtime.cpp b/openmp/runtime/src/kmp_runtime.cpp index 82d4c26..dd6e0ff 100644 --- a/openmp/runtime/src/kmp_runtime.cpp +++ b/openmp/runtime/src/kmp_runtime.cpp @@ -4493,7 +4493,7 @@ static void __kmp_initialize_team(kmp_team_t *team, int new_nproc, KF_TRACE(10, ("__kmp_initialize_team: exit: team=%p\n", team)); } -#if KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED +#if (KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED /* Sets full mask for thread and returns old mask, no changes to structures. */ static void __kmp_set_thread_affinity_mask_full_tmp(kmp_affin_mask_t *old_mask) { @@ -5041,7 +5041,7 @@ __kmp_allocate_team(kmp_root_t *root, int new_nproc, int max_nproc, __kmp_partition_places(team); #endif } else { // team->t.t_nproc < new_nproc -#if KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED +#if (KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED kmp_affin_mask_t *old_mask; if (KMP_AFFINITY_CAPABLE()) { KMP_CPU_ALLOC(old_mask); @@ -5090,7 +5090,7 @@ __kmp_allocate_team(kmp_root_t *root, int new_nproc, int max_nproc, __kmp_reinitialize_team(team, new_icvs, NULL); } -#if KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED +#if (KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED /* Temporarily set full mask for master thread before creation of workers. The reason is that workers inherit the affinity from master, so if a lot of workers are created on the single core quickly, they @@ -5125,7 +5125,7 @@ __kmp_allocate_team(kmp_root_t *root, int new_nproc, int max_nproc, } } -#if KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED +#if (KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED if (KMP_AFFINITY_CAPABLE()) { /* Restore initial master thread's affinity mask */ __kmp_set_system_affinity(old_mask, TRUE); diff --git a/openmp/runtime/src/z_Linux_util.cpp b/openmp/runtime/src/z_Linux_util.cpp index 871be62..0ee1292 100644 --- a/openmp/runtime/src/z_Linux_util.cpp +++ b/openmp/runtime/src/z_Linux_util.cpp @@ -100,7 +100,7 @@ static void __kmp_print_cond(char *buffer, kmp_cond_align_t *cond) { } #endif -#if (KMP_OS_LINUX && KMP_AFFINITY_SUPPORTED) +#if ((KMP_OS_LINUX || KMP_OS_FREEBSD) && KMP_AFFINITY_SUPPORTED) /* Affinity support */ @@ -122,16 +122,21 @@ void __kmp_affinity_bind_thread(int which) { void __kmp_affinity_determine_capable(const char *env_var) { // Check and see if the OS supports thread affinity. +#if KMP_OS_LINUX #define KMP_CPU_SET_SIZE_LIMIT (1024 * 1024) +#elif KMP_OS_FREEBSD +#define KMP_CPU_SET_SIZE_LIMIT (sizeof(cpuset_t)) +#endif - int gCode; - int sCode; - unsigned char *buf; - buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT); +#if KMP_OS_LINUX // If Linux* OS: // If the syscall fails or returns a suggestion for the size, // then we don't have to search for an appropriate size. + int gCode; + int sCode; + unsigned char *buf; + buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT); gCode = syscall(__NR_sched_getaffinity, 0, KMP_CPU_SET_SIZE_LIMIT, buf); KA_TRACE(30, ("__kmp_affinity_determine_capable: " "initial getaffinity call returned %d errno = %d\n", @@ -270,6 +275,23 @@ void __kmp_affinity_determine_capable(const char *env_var) { } } } +#elif KMP_OS_FREEBSD + int gCode; + unsigned char *buf; + buf = (unsigned char *)KMP_INTERNAL_MALLOC(KMP_CPU_SET_SIZE_LIMIT); + gCode = pthread_getaffinity_np(pthread_self(), KMP_CPU_SET_SIZE_LIMIT, reinterpret_cast(buf)); + KA_TRACE(30, ("__kmp_affinity_determine_capable: " + "initial getaffinity call returned %d errno = %d\n", + gCode, errno)); + if (gCode == 0) { + KMP_AFFINITY_ENABLE(KMP_CPU_SET_SIZE_LIMIT); + KA_TRACE(10, ("__kmp_affinity_determine_capable: " + "affinity supported (mask size %d)\n"< + (int)__kmp_affin_mask_size)); + KMP_INTERNAL_FREE(buf); + return; + } +#endif // save uncaught error code // int error = errno; KMP_INTERNAL_FREE(buf); -- 2.7.4