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,17 +21,33 @@ #include #include +static std::list Flags; + //////////////////////////////////////////////////////////////////////////////// /// adds requires flags -EXTERN void __tgt_register_requires(int64_t Flags) { +EXTERN void __tgt_register_requires(int64_t Flag) { TIMESCOPE(); - PM->RTLs.registerRequires(Flags); + if (PM) + PM->RTLs.registerRequires(Flag); + else + Flags.push_back(Flag); } //////////////////////////////////////////////////////////////////////////////// /// 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. + initLibomptarget(); + + // Add any flags that may have been registered before libomptarget was fully + // initialized. + for (int64_t Flag : Flags) + PM->RTLs.registerRequires(Flag); + Flags.clear(); + std::call_once(PM->RTLs.InitFlag, &RTLsTy::loadRTLs, &PM->RTLs); for (auto &RTL : PM->RTLs.AllRTLs) { if (RTL.register_lib) { @@ -59,6 +75,9 @@ } } } + + // Uninitialize libomptarget once all the libraries have been unloaded. + 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 @@ -36,11 +36,18 @@ PluginManager *PM; +// The number of libraries that have been registered by the user. +std::atomic LibraryUsers; + #if OMPTARGET_PROFILE_ENABLED static char *ProfileTraceFile = nullptr; #endif -__attribute__((constructor(101))) void init() { +void initLibomptarget() { + // The target library is initialized by the first user to need it. + if (LibraryUsers++) + return; + DP("Init target library!\n"); bool UseEventsForAtomicTransfers = true; @@ -65,7 +72,11 @@ #endif } -__attribute__((destructor(101))) void deinit() { +void deinitLibomptarget() { + // The target library is uninitialized by the last user. + if (--LibraryUsers) + return; + DP("Deinit target library!\n"); for (auto *R : PM->RTLs.UsedRTLs) {