-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[Offload] Implement olShutDown
#144055
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Offload] Implement olShutDown
#144055
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,7 +96,10 @@ struct AllocInfo { | |
|
|
||
| // Global shared state for liboffload | ||
| struct OffloadContext; | ||
| static OffloadContext *OffloadContextVal; | ||
| // This pointer is non-null if and only if the context is valid and fully | ||
| // initialized | ||
| static std::atomic<OffloadContext *> OffloadContextVal; | ||
| std::mutex OffloadContextValMutex; | ||
| struct OffloadContext { | ||
| OffloadContext(OffloadContext &) = delete; | ||
| OffloadContext(OffloadContext &&) = delete; | ||
|
|
@@ -107,6 +110,7 @@ struct OffloadContext { | |
| bool ValidationEnabled = true; | ||
| DenseMap<void *, AllocInfo> AllocInfoMap{}; | ||
| SmallVector<ol_platform_impl_t, 4> Platforms{}; | ||
| size_t RefCount; | ||
|
|
||
| ol_device_handle_t HostDevice() { | ||
| // The host platform is always inserted last | ||
|
|
@@ -145,20 +149,18 @@ constexpr ol_platform_backend_t pluginNameToBackend(StringRef Name) { | |
| #define PLUGIN_TARGET(Name) extern "C" GenericPluginTy *createPlugin_##Name(); | ||
| #include "Shared/Targets.def" | ||
|
|
||
| Error initPlugins() { | ||
| auto *Context = new OffloadContext{}; | ||
|
|
||
| Error initPlugins(OffloadContext &Context) { | ||
| // Attempt to create an instance of each supported plugin. | ||
| #define PLUGIN_TARGET(Name) \ | ||
| do { \ | ||
| Context->Platforms.emplace_back(ol_platform_impl_t{ \ | ||
| Context.Platforms.emplace_back(ol_platform_impl_t{ \ | ||
| std::unique_ptr<GenericPluginTy>(createPlugin_##Name()), \ | ||
| pluginNameToBackend(#Name)}); \ | ||
| } while (false); | ||
| #include "Shared/Targets.def" | ||
|
|
||
| // Preemptively initialize all devices in the plugin | ||
| for (auto &Platform : Context->Platforms) { | ||
| for (auto &Platform : Context.Platforms) { | ||
| // Do not use the host plugin - it isn't supported. | ||
| if (Platform.BackendType == OL_PLATFORM_BACKEND_UNKNOWN) | ||
| continue; | ||
|
|
@@ -178,31 +180,56 @@ Error initPlugins() { | |
| } | ||
|
|
||
| // Add the special host device | ||
| auto &HostPlatform = Context->Platforms.emplace_back( | ||
| auto &HostPlatform = Context.Platforms.emplace_back( | ||
| ol_platform_impl_t{nullptr, OL_PLATFORM_BACKEND_HOST}); | ||
| HostPlatform.Devices.emplace_back(-1, nullptr, nullptr, InfoTreeNode{}); | ||
| Context->HostDevice()->Platform = &HostPlatform; | ||
|
|
||
| Context->TracingEnabled = std::getenv("OFFLOAD_TRACE"); | ||
| Context->ValidationEnabled = !std::getenv("OFFLOAD_DISABLE_VALIDATION"); | ||
| Context.HostDevice()->Platform = &HostPlatform; | ||
|
|
||
| OffloadContextVal = Context; | ||
| Context.TracingEnabled = std::getenv("OFFLOAD_TRACE"); | ||
| Context.ValidationEnabled = !std::getenv("OFFLOAD_DISABLE_VALIDATION"); | ||
|
|
||
| return Plugin::success(); | ||
| } | ||
|
|
||
| // TODO: We can properly reference count here and manage the resources in a more | ||
| // clever way | ||
| Error olInit_impl() { | ||
| static std::once_flag InitFlag; | ||
| std::optional<Error> InitResult{}; | ||
| std::call_once(InitFlag, [&] { InitResult = initPlugins(); }); | ||
| std::lock_guard<std::mutex> Lock{OffloadContextValMutex}; | ||
|
|
||
| if (InitResult) | ||
| return std::move(*InitResult); | ||
| return Error::success(); | ||
| if (isOffloadInitialized()) { | ||
| OffloadContext::get().RefCount++; | ||
| return Plugin::success(); | ||
| } | ||
|
|
||
| // Use a temporary to ensure that entry points querying OffloadContextVal do | ||
| // not get a partially initialized context | ||
| auto *NewContext = new OffloadContext{}; | ||
| Error InitResult = initPlugins(*NewContext); | ||
| OffloadContextVal.store(NewContext); | ||
| OffloadContext::get().RefCount++; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't we be calling new and delete on this if it's null?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The context is |
||
|
|
||
| return InitResult; | ||
| } | ||
|
|
||
| Error olShutDown_impl() { | ||
| std::lock_guard<std::mutex> Lock{OffloadContextValMutex}; | ||
|
|
||
| if (--OffloadContext::get().RefCount != 0) | ||
| return Error::success(); | ||
|
|
||
| llvm::Error Result = Error::success(); | ||
| auto *OldContext = OffloadContextVal.exchange(nullptr); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, forgot to mention that this needed to be atomic since we're using it outside the mutex as a guard. |
||
|
|
||
| for (auto &P : OldContext->Platforms) { | ||
| // Host plugin is nullptr and has no deinit | ||
| if (!P.Plugin) | ||
| continue; | ||
|
||
|
|
||
| if (auto Res = P.Plugin->deinit()) | ||
| Result = llvm::joinErrors(std::move(Result), std::move(Res)); | ||
|
||
| } | ||
|
|
||
| delete OldContext; | ||
| return Result; | ||
| } | ||
| Error olShutDown_impl() { return Error::success(); } | ||
|
|
||
| Error olGetPlatformInfoImplDetail(ol_platform_handle_t Platform, | ||
| ol_platform_info_t PropName, size_t PropSize, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.