diff --git a/openmp/libomptarget/include/device.h b/openmp/libomptarget/include/device.h --- a/openmp/libomptarget/include/device.h +++ b/openmp/libomptarget/include/device.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "ExclusiveAccess.h" #include "omptarget.h" @@ -530,6 +531,10 @@ /// Flag to indicate if we use events to ensure the atomicity of /// map clauses or not. Can be modified with an environment variable. const bool UseEventsForAtomicTransfers; + + // Work around plugins that call dlopen on shared libraries that call tgt_register_lib + std::atomic_bool RTLsLoaded = false; + llvm::SmallVector<__tgt_bin_desc*> postponed_register_lib_args; }; extern PluginManager *PM; diff --git a/openmp/libomptarget/src/interface.cpp b/openmp/libomptarget/src/interface.cpp --- a/openmp/libomptarget/src/interface.cpp +++ b/openmp/libomptarget/src/interface.cpp @@ -35,7 +35,10 @@ /// adds a target shared library to the target execution image EXTERN void __tgt_register_lib(__tgt_bin_desc *Desc) { TIMESCOPE(); - std::call_once(PM->RTLs.InitFlag, &RTLsTy::loadRTLs, &PM->RTLs); + if (!PM->RTLsLoaded) { + PM->postponed_register_lib_args.push_back(Desc); + return; + } for (auto &RTL : PM->RTLs.AllRTLs) { if (RTL.register_lib) { if ((*RTL.register_lib)(Desc) != OFFLOAD_SUCCESS) { diff --git a/openmp/libomptarget/src/rtl.cpp b/openmp/libomptarget/src/rtl.cpp --- a/openmp/libomptarget/src/rtl.cpp +++ b/openmp/libomptarget/src/rtl.cpp @@ -39,11 +39,16 @@ /* Remote target */ "libomptarget.rtl.rpc", }; -PluginManager *PM; +PluginManager *PM = nullptr; static char *ProfileTraceFile = nullptr; __attribute__((constructor(101))) void init() { + if (PM != nullptr) { + // In case one of the plugins chooses to call back into this constructor + return; + } + DP("Init target library!\n"); bool UseEventsForAtomicTransfers = true; @@ -64,11 +69,18 @@ // TODO: add a configuration option for time granularity if (ProfileTraceFile) timeTraceProfilerInitialize(500 /* us */, "libomptarget"); + + PM->RTLs.loadRTLs(); + PM->RTLsLoaded = true; + for (auto * d : PM->postponed_register_lib_args) { + __tgt_register_lib(d); + } } __attribute__((destructor(101))) void deinit() { DP("Deinit target library!\n"); delete PM; + PM = nullptr; if (ProfileTraceFile) { // TODO: add env var for file output