diff --git a/source/adapters/level_zero/adapter.cpp b/source/adapters/level_zero/adapter.cpp index 5ae1d52e7b..ed52254ec3 100644 --- a/source/adapters/level_zero/adapter.cpp +++ b/source/adapters/level_zero/adapter.cpp @@ -12,6 +12,14 @@ #include "ur_level_zero.hpp" #include +// As windows order of unloading dlls is reversed from linux, windows will call +// umfTearDown before it could release umf objects in level_zero, so we call +// umfInit on urAdapterGet and umfAdapterTearDown to enforce the teardown of umf +// after umf objects are destructed. +#if defined(_WIN32) +#include +#endif + // Due to multiple DLLMain definitions with SYCL, Global Adapter is init at // variable creation. #if defined(_WIN32) @@ -19,7 +27,12 @@ ur_adapter_handle_t_ *GlobalAdapter = new ur_adapter_handle_t_(); #else ur_adapter_handle_t_ *GlobalAdapter; #endif - +// This is a temporary workaround on windows, where UR adapter is teardowned +// before the UR loader, which will result in access violation when we use print +// function as the overrided print function was already released with the UR +// adapter. +// TODO: Change adapters to use a common sink class in the loader instead of +// using thier own sink class that inherit from logger::Sink. class ur_legacy_sink : public logger::Sink { public: ur_legacy_sink(std::string logger_name = "", bool skip_prefix = true) @@ -32,7 +45,11 @@ class ur_legacy_sink : public logger::Sink { fprintf(stderr, "%s", msg.c_str()); } - ~ur_legacy_sink() = default; + ~ur_legacy_sink() { +#if defined(_WIN32) + logger::isTearDowned = true; +#endif + }; }; ur_result_t initPlatforms(PlatformVec &platforms) noexcept try { @@ -74,7 +91,14 @@ ur_result_t initPlatforms(PlatformVec &platforms) noexcept try { return exceptionToResult(std::current_exception()); } -ur_result_t adapterStateInit() { return UR_RESULT_SUCCESS; } +ur_result_t adapterStateInit() { + +#if defined(_WIN32) + umfInit(); +#endif + + return UR_RESULT_SUCCESS; +} ur_adapter_handle_t_::ur_adapter_handle_t_() : logger(logger::get_logger("level_zero")) { @@ -258,6 +282,7 @@ ur_result_t adapterStateTeardown() { // Due to multiple DLLMain definitions with SYCL, register to cleanup the // Global Adapter after refcnt is 0 #if defined(_WIN32) + umfTearDown(); std::atexit(globalAdapterOnDemandCleanup); #endif diff --git a/source/common/logger/ur_sinks.hpp b/source/common/logger/ur_sinks.hpp index b2ebf72a7a..e0d8144a31 100644 --- a/source/common/logger/ur_sinks.hpp +++ b/source/common/logger/ur_sinks.hpp @@ -17,6 +17,10 @@ namespace logger { +#if defined(_WIN32) +inline bool isTearDowned = false; +#endif + class Sink { public: template @@ -28,7 +32,21 @@ class Sink { } format(buffer, fmt, std::forward(args)...); +// This is a temporary workaround on windows, where UR adapter is teardowned +// before the UR loader, which will result in access violation when we use print +// function as the overrided print function was already released with the UR +// adapter. +// TODO: Change adapters to use a common sink class in the loader instead of +// using thier own sink class that inherit from logger::Sink. +#if defined(_WIN32) + if (isTearDowned) { + std::cerr << buffer.str() << "\n"; + } else { + print(level, buffer.str()); + } +#else print(level, buffer.str()); +#endif } void setFlushLevel(logger::Level level) { this->flush_level = level; }