639 changes: 517 additions & 122 deletions openmp/runtime/src/kmp_affinity.cpp

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions openmp/runtime/src/kmp_affinity.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ class Address {
bool operator!=(const Address &b) const {
return !operator==(b);
}
void print() const {
unsigned i;
printf("Depth: %u --- ", depth);
for(i=0;i<depth;i++) {
printf("%u ", labels[i]);
}
}
};

class AddrUnsPair {
Expand All @@ -72,6 +79,18 @@ class AddrUnsPair {
second = b.second;
return *this;
}
void print() const {
printf("first = "); first.print();
printf(" --- second = %u", second);
}
bool operator==(const AddrUnsPair &b) const {
if(first != b.first) return false;
if(second != b.second) return false;
return true;
}
bool operator!=(const AddrUnsPair &b) const {
return !operator==(b);
}
};


Expand Down
2 changes: 2 additions & 0 deletions openmp/runtime/src/kmp_config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#cmakedefine01 LIBOMP_ENABLE_ASSERTIONS
#define KMP_USE_ASSERT LIBOMP_ENABLE_ASSERTIONS
#cmakedefine01 STUBS_LIBRARY
#cmakedefine01 LIBOMP_USE_HWLOC
#define KMP_USE_HWLOC LIBOMP_USE_HWLOC
#define KMP_ARCH_STR "@LIBOMP_LEGAL_ARCH@"
#define KMP_LIBRARY_FILE "@LIBOMP_LIB_FILE@"
#define KMP_VERSION_MAJOR @LIBOMP_VERSION_MAJOR@
Expand Down
10 changes: 9 additions & 1 deletion openmp/runtime/src/kmp_ftn_entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ FTN_GET_AFFINITY_MAX_PROC( void )
return 0;
}

#if KMP_GROUP_AFFINITY
#if KMP_GROUP_AFFINITY && !KMP_USE_HWLOC
if ( __kmp_num_proc_groups > 1 ) {
return (int)KMP_CPU_SETSIZE;
}
Expand All @@ -278,7 +278,11 @@ FTN_CREATE_AFFINITY_MASK( void **mask )
if ( ! TCR_4(__kmp_init_middle) ) {
__kmp_middle_initialize();
}
# if KMP_USE_HWLOC
*mask = (hwloc_cpuset_t)hwloc_bitmap_alloc();
# else
*mask = kmpc_malloc( __kmp_affin_mask_size );
# endif
KMP_CPU_ZERO( (kmp_affin_mask_t *)(*mask) );
#endif
}
Expand All @@ -300,7 +304,11 @@ FTN_DESTROY_AFFINITY_MASK( void **mask )
KMP_FATAL( AffinityInvalidMask, "kmp_destroy_affinity_mask" );
}
}
# if KMP_USE_HWLOC
hwloc_bitmap_free((hwloc_cpuset_t)(*mask));
# else
kmpc_free( *mask );
# endif
*mask = NULL;
#endif
}
Expand Down
4 changes: 4 additions & 0 deletions openmp/runtime/src/kmp_global.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ __thread kmp_stats_list* __kmp_stats_thread_ptr = &__kmp_stats_list;
// gives reference tick for all events (considered the 0 tick)
tsc_tick_count __kmp_stats_start_time;
#endif
#if KMP_USE_HWLOC
int __kmp_hwloc_error = FALSE;
hwloc_topology_t __kmp_hwloc_topology = NULL;
#endif

/* ----------------------------------------------------- */
/* INITIALIZATION VARIABLES */
Expand Down
37 changes: 37 additions & 0 deletions openmp/runtime/src/kmp_settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -3009,6 +3009,11 @@ __kmp_stg_parse_topology_method( char const * name, char const * value,
else if ( __kmp_str_match( "flat", 1, value ) ) {
__kmp_affinity_top_method = affinity_top_method_flat;
}
# if KMP_USE_HWLOC
else if ( __kmp_str_match( "hwloc", 1, value) ) {
__kmp_affinity_top_method = affinity_top_method_hwloc;
}
# endif
else {
KMP_WARNING( StgInvalidValue, name, value );
}
Expand Down Expand Up @@ -5119,11 +5124,43 @@ __kmp_env_initialize( char const * string ) {
// affinity.
//
const char *var = "KMP_AFFINITY";
# if KMP_USE_HWLOC
if(hwloc_topology_init(&__kmp_hwloc_topology) < 0) {
__kmp_hwloc_error = TRUE;
if(__kmp_affinity_verbose)
KMP_WARNING(AffHwlocErrorOccurred, var, "hwloc_topology_init()");
}
hwloc_topology_ignore_type(__kmp_hwloc_topology, HWLOC_OBJ_CACHE);
# endif
if ( __kmp_affinity_type == affinity_disabled ) {
KMP_AFFINITY_DISABLE();
}
else if ( ! KMP_AFFINITY_CAPABLE() ) {
# if KMP_USE_HWLOC
const hwloc_topology_support* topology_support = hwloc_topology_get_support(__kmp_hwloc_topology);
if(hwloc_topology_load(__kmp_hwloc_topology) < 0) {
__kmp_hwloc_error = TRUE;
if(__kmp_affinity_verbose)
KMP_WARNING(AffHwlocErrorOccurred, var, "hwloc_topology_load()");
}
// Is the system capable of setting/getting this thread's affinity?
// also, is topology discovery possible? (pu indicates ability to discover processing units)
// and finally, were there no errors when calling any hwloc_* API functions?
if(topology_support->cpubind->set_thisthread_cpubind &&
topology_support->cpubind->get_thisthread_cpubind &&
topology_support->discovery->pu &&
!__kmp_hwloc_error)
{
// enables affinity according to KMP_AFFINITY_CAPABLE() macro
KMP_AFFINITY_ENABLE(TRUE);
} else {
// indicate that hwloc didn't work and disable affinity
__kmp_hwloc_error = TRUE;
KMP_AFFINITY_DISABLE();
}
# else
__kmp_affinity_determine_capable( var );
# endif // KMP_USE_HWLOC
if ( ! KMP_AFFINITY_CAPABLE() ) {
if ( __kmp_affinity_verbose || ( __kmp_affinity_warnings
&& ( __kmp_affinity_type != affinity_default )
Expand Down
13 changes: 11 additions & 2 deletions openmp/runtime/src/z_Linux_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,11 @@ __kmp_set_system_affinity( kmp_affin_mask_t const *mask, int abort_on_error )
{
KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
"Illegal set affinity operation when not capable");

#if KMP_USE_HWLOC
int retval = hwloc_set_cpubind(__kmp_hwloc_topology, (hwloc_cpuset_t)mask, HWLOC_CPUBIND_THREAD);
#else
int retval = syscall( __NR_sched_setaffinity, 0, __kmp_affin_mask_size, mask );
#endif
if (retval >= 0) {
return 0;
}
Expand All @@ -198,7 +201,11 @@ __kmp_get_system_affinity( kmp_affin_mask_t *mask, int abort_on_error )
KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
"Illegal get affinity operation when not capable");

#if KMP_USE_HWLOC
int retval = hwloc_get_cpubind(__kmp_hwloc_topology, (hwloc_cpuset_t)mask, HWLOC_CPUBIND_THREAD);
#else
int retval = syscall( __NR_sched_getaffinity, 0, __kmp_affin_mask_size, mask );
#endif
if (retval >= 0) {
return 0;
}
Expand All @@ -220,10 +227,12 @@ __kmp_affinity_bind_thread( int which )
KMP_ASSERT2(KMP_AFFINITY_CAPABLE(),
"Illegal set affinity operation when not capable");

kmp_affin_mask_t *mask = (kmp_affin_mask_t *)KMP_ALLOCA(__kmp_affin_mask_size);
kmp_affin_mask_t *mask;
KMP_CPU_ALLOC_ON_STACK(mask);
KMP_CPU_ZERO(mask);
KMP_CPU_SET(which, mask);
__kmp_set_system_affinity(mask, TRUE);
KMP_CPU_FREE_FROM_STACK(mask);
}

/*
Expand Down
11 changes: 11 additions & 0 deletions openmp/runtime/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
# CMakeLists.txt file for unit testing OpenMP Library
include(FindPythonInterp)
include(CheckTypeSize)

if(NOT PYTHONINTERP_FOUND)
libomp_warning_say("Could not find Python.")
libomp_warning_say("The check-libomp target will not be available!")
return()
endif()

macro(pythonize_bool var)
if (${var})
set(${var} True)
else()
set(${var} False)
endif()
endmacro()

pythonize_bool(LIBOMP_USE_HWLOC)

set(LIBOMP_TEST_CFLAGS "" CACHE STRING
"Extra compiler flags to send to the test compiler")

Expand Down
29 changes: 20 additions & 9 deletions openmp/runtime/test/lit.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,20 @@ if 'PYLINT_IMPORT' in os.environ:
config = object()
lit_config = object()

def append_dynamic_library_path(name, value, sep):
def append_dynamic_library_path(path):
if config.operating_system == 'Windows':
name = 'PATH'
sep = ';'
elif config.operating_system == 'Darwin':
name = 'DYLD_LIBRARY_PATH'
sep = ':'
else:
name = 'LD_LIBRARY_PATH'
sep = ':'
if name in config.environment:
config.environment[name] = value + sep + config.environment[name]
config.environment[name] = path + sep + config.environment[name]
else:
config.environment[name] = value
config.environment[name] = path

# name: The name of this test suite.
config.name = 'libomp'
Expand All @@ -38,13 +47,15 @@ config.test_cflags = config.test_openmp_flag + \
" " + config.test_extra_cflags

# Setup environment to find dynamic library at runtime
if config.operating_system == 'Windows':
append_dynamic_library_path('PATH', config.library_dir, ";")
elif config.operating_system == 'Darwin':
append_dynamic_library_path('DYLD_LIBRARY_PATH', config.library_dir, ":")
append_dynamic_library_path(config.library_dir)
if config.using_hwloc:
append_dynamic_library_path(config.hwloc_library_dir)

# Rpath modifications for Darwin
if config.operating_system == 'Darwin':
config.test_cflags += " -Wl,-rpath," + config.library_dir
else: # Unices
append_dynamic_library_path('LD_LIBRARY_PATH', config.library_dir, ":")
if config.using_hwloc:
config.test_cflags += " -Wl,-rpath," + config.hwloc_library_dir

# substitutions
config.substitutions.append(("%libomp-compile-and-run", \
Expand Down
2 changes: 2 additions & 0 deletions openmp/runtime/test/lit.site.cfg.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ config.libomp_obj_root = "@CMAKE_CURRENT_BINARY_DIR@"
config.library_dir = "@LIBOMP_LIBRARY_DIR@"
config.omp_header_directory = "@LIBOMP_BINARY_DIR@/src"
config.operating_system = "@CMAKE_SYSTEM_NAME@"
config.hwloc_library_dir = "@LIBOMP_HWLOC_LIBRARY_DIR@"
config.using_hwloc = @LIBOMP_USE_HWLOC@

# Let the main config do the real work.
lit_config.load_config(config, "@LIBOMP_BASE_DIR@/test/lit.cfg")
Expand Down