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 @@ -508,4 +508,10 @@ extern PluginManager *PM; +/// Allocate memory and initialize the plugin manager. +void initLibomptarget(); + +/// Deallocate the plugin manager. +void deinitLibomptarget(); + #endif 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 @@ -21,10 +21,18 @@ #include #include +// The number of libraries that have been registered by the user. +static std::atomic LibraryUsers; + //////////////////////////////////////////////////////////////////////////////// /// adds requires flags EXTERN void __tgt_register_requires(int64_t Flags) { TIMESCOPE(); + + // Make sure that someone has initialized Libomptarget first. + if (!PM) + initLibomptarget(); + PM->RTLs.registerRequires(Flags); } @@ -32,6 +40,12 @@ /// adds a target shared library to the target execution image EXTERN void __tgt_register_lib(__tgt_bin_desc *Desc) { TIMESCOPE(); + + // Before we load any libraries we need to make sure that Libomptarget has + // been initialized. + if (!PM) + initLibomptarget(); + std::call_once(PM->RTLs.InitFlag, &RTLsTy::loadRTLs, &PM->RTLs); for (auto &RTL : PM->RTLs.AllRTLs) { if (RTL.register_lib) { @@ -41,6 +55,8 @@ } } PM->RTLs.registerLib(Desc); + + LibraryUsers++; } //////////////////////////////////////////////////////////////////////////////// @@ -59,6 +75,10 @@ } } } + + // Uninitialize libomptarget once all the libraries have been unloaded. + if (!--LibraryUsers) + deinitLibomptarget(); } /// creates host-to-target data mapping, stores it in the diff --git a/openmp/libomptarget/src/omptarget.cpp b/openmp/libomptarget/src/omptarget.cpp --- a/openmp/libomptarget/src/omptarget.cpp +++ b/openmp/libomptarget/src/omptarget.cpp @@ -268,9 +268,9 @@ } static bool isOffloadDisabled() { - if (PM->TargetOffloadPolicy == tgt_default) + if (PM && PM->TargetOffloadPolicy == tgt_default) handleDefaultTargetOffload(); - return PM->TargetOffloadPolicy == tgt_disabled; + return !PM || PM->TargetOffloadPolicy == tgt_disabled; } // If offload is enabled, ensure that device DeviceID has been initialized, 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 @@ -17,6 +17,7 @@ #include "llvm/Object/OffloadBinary.h" #include +#include #include #include #include @@ -34,13 +35,21 @@ /* Remote target */ "libomptarget.rtl.rpc.so", }; -PluginManager *PM; +PluginManager *PM = nullptr; +static std::mutex PluginMutex; #if OMPTARGET_PROFILE_ENABLED static char *ProfileTraceFile = nullptr; #endif -__attribute__((constructor(101))) void init() { +void initLibomptarget() { + PluginMutex.lock(); + + if (PM) { + PluginMutex.unlock(); + return; + } + DP("Init target library!\n"); bool UseEventsForAtomicTransfers = true; @@ -63,9 +72,10 @@ if (ProfileTraceFile) llvm::timeTraceProfilerInitialize(500 /* us */, "libomptarget"); #endif + PluginMutex.unlock(); } -__attribute__((destructor(101))) void deinit() { +void deinitLibomptarget() { DP("Deinit target library!\n"); for (auto *R : PM->RTLs.UsedRTLs) {