[OpenMP] Enable omp_get_num_devices() on Windows

This patch enables omp_get_num_devices() and omp_get_initial_device() on
Windows by providing an alternative to dlsym on Windows, and proposes to
add a new libomptarget entry, __tgt_get_num_devices().

Differential Revision: https://reviews.llvm.org/D96182
This commit is contained in:
Hansang Bae 2021-02-05 08:53:40 -06:00
parent 8f3518e69b
commit ffb21e7f05
4 changed files with 54 additions and 25 deletions

View File

@ -126,6 +126,9 @@ function(libomp_get_libflags libflags)
if(${IA32})
libomp_append(libflags_local -lirc_pic LIBOMP_HAVE_IRC_PIC_LIBRARY)
endif()
if(MINGW)
libomp_append(libflags_local -lpsapi LIBOMP_HAVE_LIBPSAPI)
endif()
if(LIBOMP_HAVE_SHM_OPEN_WITH_LRT)
libomp_append(libflags_local -lrt)
endif()

View File

@ -941,13 +941,15 @@ void FTN_STDCALL KMP_EXPAND_NAME(FTN_SET_DEFAULT_DEVICE)(int KMP_DEREF arg) {
// libomptarget, if loaded, provides this function in api.cpp.
int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NUM_DEVICES)(void) KMP_WEAK_ATTRIBUTE_EXTERNAL;
int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_NUM_DEVICES)(void) {
#if KMP_MIC || KMP_OS_DARWIN || KMP_OS_WINDOWS || defined(KMP_STUB)
#if KMP_MIC || KMP_OS_DARWIN || defined(KMP_STUB)
return 0;
#else
int (*fptr)();
if ((*(void **)(&fptr) = dlsym(RTLD_DEFAULT, "_Offload_number_of_devices"))) {
if ((*(void **)(&fptr) = KMP_DLSYM("__tgt_get_num_devices"))) {
return (*fptr)();
} else if ((*(void **)(&fptr) = dlsym(RTLD_NEXT, "omp_get_num_devices"))) {
} else if ((*(void **)(&fptr) = KMP_DLSYM_NEXT("omp_get_num_devices"))) {
return (*fptr)();
} else if ((*(void **)(&fptr) = KMP_DLSYM("_Offload_number_of_devices"))) {
return (*fptr)();
} else { // liboffload & libomptarget don't exist
return 0;
@ -963,20 +965,11 @@ int FTN_STDCALL KMP_EXPAND_NAME(FTN_IS_INITIAL_DEVICE)(void) {
}
// libomptarget, if loaded, provides this function
int FTN_STDCALL FTN_GET_INITIAL_DEVICE(void) KMP_WEAK_ATTRIBUTE_EXTERNAL;
int FTN_STDCALL FTN_GET_INITIAL_DEVICE(void) {
#if KMP_MIC || KMP_OS_DARWIN || KMP_OS_WINDOWS || defined(KMP_STUB)
int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE)(void)
KMP_WEAK_ATTRIBUTE_EXTERNAL;
int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE)(void) {
// same as omp_get_num_devices()
return 0;
#else
int (*fptr)();
if ((*(void **)(&fptr) = dlsym(RTLD_NEXT, "omp_get_initial_device"))) {
return (*fptr)();
} else { // liboffload & libomptarget don't exist
// same as omp_get_num_devices()
return 0;
}
#endif
return KMP_EXPAND_NAME(FTN_GET_NUM_DEVICES)();
}
#if defined(KMP_STUB)
@ -1321,22 +1314,22 @@ int FTN_STDCALL KMP_EXPAND_NAME(FTN_GET_MAX_TASK_PRIORITY)(void) {
// loaded, we assume we are on the host and return KMP_HOST_DEVICE.
// Compiler/libomptarget will handle this if called inside target.
int FTN_STDCALL FTN_GET_DEVICE_NUM(void) KMP_WEAK_ATTRIBUTE_EXTERNAL;
int FTN_STDCALL FTN_GET_DEVICE_NUM(void) { return FTN_GET_INITIAL_DEVICE(); }
int FTN_STDCALL FTN_GET_DEVICE_NUM(void) {
return KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE)();
}
// Compiler will ensure that this is only called from host in sequential region
int FTN_STDCALL FTN_PAUSE_RESOURCE(kmp_pause_status_t kind, int device_num) {
#ifdef KMP_STUB
return 1; // just fail
#else
if (device_num == FTN_GET_INITIAL_DEVICE())
if (device_num == KMP_EXPAND_NAME(FTN_GET_INITIAL_DEVICE)())
return __kmpc_pause_resource(kind);
else {
#if !KMP_OS_WINDOWS
int (*fptr)(kmp_pause_status_t, int);
if ((*(void **)(&fptr) = dlsym(RTLD_DEFAULT, "tgt_pause_resource")))
if ((*(void **)(&fptr) = KMP_DLSYM("tgt_pause_resource")))
return (*fptr)(kind, device_num);
else
#endif
return 1; // just fail if there is no libomptarget
}
#endif
@ -1348,11 +1341,9 @@ int FTN_STDCALL FTN_PAUSE_RESOURCE_ALL(kmp_pause_status_t kind) {
return 1; // just fail
#else
int fails = 0;
#if !KMP_OS_WINDOWS
int (*fptr)(kmp_pause_status_t, int);
if ((*(void **)(&fptr) = dlsym(RTLD_DEFAULT, "tgt_pause_resource")))
if ((*(void **)(&fptr) = KMP_DLSYM("tgt_pause_resource")))
fails = (*fptr)(kind, KMP_DEVICE_ALL); // pause devices
#endif
fails += __kmpc_pause_resource(kind); // pause host
return fails;
#endif
@ -1515,7 +1506,7 @@ KMP_VERSION_SYMBOL(FTN_GET_PLACE_PROC_IDS, 45, "OMP_4.5");
KMP_VERSION_SYMBOL(FTN_GET_PLACE_NUM, 45, "OMP_4.5");
KMP_VERSION_SYMBOL(FTN_GET_PARTITION_NUM_PLACES, 45, "OMP_4.5");
KMP_VERSION_SYMBOL(FTN_GET_PARTITION_PLACE_NUMS, 45, "OMP_4.5");
// KMP_VERSION_SYMBOL(FTN_GET_INITIAL_DEVICE, 45, "OMP_4.5");
KMP_VERSION_SYMBOL(FTN_GET_INITIAL_DEVICE, 45, "OMP_4.5");
// OMP_5.0 versioned symbols
// KMP_VERSION_SYMBOL(FTN_GET_DEVICE_NUM, 50, "OMP_5.0");

View File

@ -1077,6 +1077,16 @@ bool __kmp_atomic_compare_store_rel(std::atomic<T> *p, T expected, T desired) {
expected, desired, std::memory_order_release, std::memory_order_relaxed);
}
// Symbol lookup on Linux/Windows
#if KMP_OS_WINDOWS
extern void *__kmp_lookup_symbol(const char *name);
#define KMP_DLSYM(name) __kmp_lookup_symbol(name)
#define KMP_DLSYM_NEXT(name) nullptr
#else
#define KMP_DLSYM(name) dlsym(RTLD_DEFAULT, name)
#define KMP_DLSYM_NEXT(name) dlsym(RTLD_NEXT, name)
#endif
#endif /* KMP_OS_H */
// Safe C API
#include "kmp_safe_c_api.h"

View File

@ -23,6 +23,8 @@
#include <ntsecapi.h> // UNICODE_STRING
#include <ntstatus.h>
#include <psapi.h>
#pragma comment(lib, "psapi.lib")
enum SYSTEM_INFORMATION_CLASS {
SystemProcessInformation = 5
@ -1632,6 +1634,29 @@ finish: // Clean up and exit.
return running_threads;
} //__kmp_get_load_balance()
// Find symbol from the loaded modules
void *__kmp_lookup_symbol(const char *name) {
HANDLE process = GetCurrentProcess();
DWORD needed;
HMODULE *modules = nullptr;
if (!EnumProcessModules(process, modules, 0, &needed))
return nullptr;
DWORD num_modules = needed / sizeof(HMODULE);
modules = (HMODULE *)malloc(num_modules * sizeof(HMODULE));
if (!EnumProcessModules(process, modules, needed, &needed)) {
free(modules);
return nullptr;
}
void *proc = nullptr;
for (uint32_t i = 0; i < num_modules; i++) {
proc = (void *)GetProcAddress(modules[i], name);
if (proc)
break;
}
free(modules);
return proc;
}
// Functions for hidden helper task
void __kmp_hidden_helper_worker_thread_wait() {
KMP_ASSERT(0 && "Hidden helper task is not supported on Windows");