Skip to content

Commit b43f03a

Browse files
[SYCL] Create static shared-release handler after loading plugins (#4843)
To enforce default contexts to be released before global variables in plugins and associated libraries, these changes intializes a function-local static variable after the plugins have been loaded. Due to the guarantees of std::exit the destructor of the new function-local variable will be called before the destructor of all global variables initialized prior to the function-local static variable's initialization. Signed-off-by: Steffen Larsen <[email protected]>
1 parent 9fd0944 commit b43f03a

File tree

3 files changed

+30
-12
lines changed

3 files changed

+30
-12
lines changed

sycl/source/detail/global_handler.cpp

+17-11
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ std::mutex &GlobalHandler::getHandlerExtendedMembersMutex() {
8989
return getOrCreate(MHandlerExtendedMembersMutex);
9090
}
9191

92-
void releaseSharedGlobalHandles() {
92+
void releaseDefaultContexts() {
9393
// Release shared-pointers to SYCL objects.
9494
#ifndef _WIN32
9595
GlobalHandler::instance().MPlatformToDefaultContextCache.Inst.reset(nullptr);
@@ -101,11 +101,26 @@ void releaseSharedGlobalHandles() {
101101
// routines will be called in the end.
102102
GlobalHandler::instance().MPlatformToDefaultContextCache.Inst.release();
103103
#endif
104-
GlobalHandler::instance().MPlatformCache.Inst.reset(nullptr);
104+
}
105+
106+
struct DefaultContextReleaseHandler {
107+
~DefaultContextReleaseHandler() { releaseDefaultContexts(); }
108+
};
109+
110+
void GlobalHandler::registerDefaultContextReleaseHandler() {
111+
static DefaultContextReleaseHandler handler{};
105112
}
106113

107114
void shutdown() {
115+
// If default contexts are requested after the first default contexts have
116+
// been released there may be a new default context. These must be released
117+
// prior to closing the plugins.
118+
// Note: Releasing a default context here may cause failures in plugins with
119+
// global state as the global state may have been released.
120+
releaseDefaultContexts();
121+
108122
// First, release resources, that may access plugins.
123+
GlobalHandler::instance().MPlatformCache.Inst.reset(nullptr);
109124
GlobalHandler::instance().MScheduler.Inst.reset(nullptr);
110125
GlobalHandler::instance().MProgramManager.Inst.reset(nullptr);
111126

@@ -135,7 +150,6 @@ extern "C" __SYCL_EXPORT BOOL WINAPI DllMain(HINSTANCE hinstDLL,
135150
// Perform actions based on the reason for calling.
136151
switch (fdwReason) {
137152
case DLL_PROCESS_DETACH:
138-
releaseSharedGlobalHandles();
139153
shutdown();
140154
break;
141155
case DLL_PROCESS_ATTACH:
@@ -146,14 +160,6 @@ extern "C" __SYCL_EXPORT BOOL WINAPI DllMain(HINSTANCE hinstDLL,
146160
return TRUE; // Successful DLL_PROCESS_ATTACH.
147161
}
148162
#else
149-
// Release shared SYCL object implementation handles at normal destructor
150-
// priority to avoid the global handler from keeping the objects alive after
151-
// the backends have destroyed any state they may rely on to correctly handle
152-
// further operations.
153-
__attribute__((destructor)) static void syclPreunload() {
154-
releaseSharedGlobalHandles();
155-
}
156-
157163
// Setting low priority on destructor ensures it runs after all other global
158164
// destructors. Priorities 0-100 are reserved by the compiler. The priority
159165
// value 110 allows SYCL users to run their destructors after runtime library

sycl/source/detail/global_handler.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,10 @@ class GlobalHandler {
6868
XPTIRegistry &getXPTIRegistry();
6969
std::mutex &getHandlerExtendedMembersMutex();
7070

71+
static void registerDefaultContextReleaseHandler();
72+
7173
private:
72-
friend void releaseSharedGlobalHandles();
74+
friend void releaseDefaultContexts();
7375
friend void shutdown();
7476

7577
// Constructor and destructor are declared out-of-line to allow incomplete

sycl/source/detail/platform_impl.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ std::vector<platform> platform_impl::get_platforms() {
127127
}
128128
}
129129

130+
// Register default context release handler after plugins have been loaded and
131+
// after the first calls to each plugin. This initializes a function-local
132+
// variable that should be destroyed before any global variables in the
133+
// plugins are destroyed. This is done after the first call to the backends to
134+
// ensure any lazy-loaded dependencies are loaded prior to the handler
135+
// variable's initialization. Note: The default context release handler is not
136+
// guaranteed to be destroyed before function-local static variables as they
137+
// may be initialized after.
138+
GlobalHandler::registerDefaultContextReleaseHandler();
139+
130140
// The host platform should always be available unless not allowed by the
131141
// SYCL_DEVICE_FILTER
132142
detail::device_filter_list *FilterList =

0 commit comments

Comments
 (0)