xref: /llvm-project/offload/include/PluginManager.h (revision 13dcc95dcd4999ff99f2de89d881f1aed5b21709)
1 //===-- PluginManager.h - Plugin loading and communication API --*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Declarations for managing devices that are handled by RTL plugins.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef OMPTARGET_PLUGIN_MANAGER_H
14 #define OMPTARGET_PLUGIN_MANAGER_H
15 
16 #include "PluginInterface.h"
17 
18 #include "DeviceImage.h"
19 #include "ExclusiveAccess.h"
20 #include "Shared/APITypes.h"
21 #include "Shared/Requirements.h"
22 
23 #include "device.h"
24 
25 #include "llvm/ADT/DenseSet.h"
26 #include "llvm/ADT/SmallVector.h"
27 #include "llvm/ADT/iterator.h"
28 #include "llvm/ADT/iterator_range.h"
29 #include "llvm/Support/DynamicLibrary.h"
30 #include "llvm/Support/Error.h"
31 
32 #include <cstdint>
33 #include <list>
34 #include <memory>
35 #include <mutex>
36 #include <string>
37 
38 using GenericPluginTy = llvm::omp::target::plugin::GenericPluginTy;
39 
40 /// Struct for the data required to handle plugins
41 struct PluginManager {
42   /// Type of the devices container. We hand out DeviceTy& to queries which are
43   /// stable addresses regardless if the container changes.
44   using DeviceContainerTy = llvm::SmallVector<std::unique_ptr<DeviceTy>>;
45 
46   /// Exclusive accessor type for the device container.
47   using ExclusiveDevicesAccessorTy = Accessor<DeviceContainerTy>;
48 
49   PluginManager() {}
50 
51   void init();
52 
53   void deinit();
54 
55   // Register a shared library with all (compatible) RTLs.
56   void registerLib(__tgt_bin_desc *Desc);
57 
58   // Unregister a shared library from all RTLs.
59   void unregisterLib(__tgt_bin_desc *Desc);
60 
61   void addDeviceImage(__tgt_bin_desc &TgtBinDesc,
62                       __tgt_device_image &TgtDeviceImage) {
63     DeviceImages.emplace_back(
64         std::make_unique<DeviceImageTy>(TgtBinDesc, TgtDeviceImage));
65   }
66 
67   /// Return the device presented to the user as device \p DeviceNo if it is
68   /// initialized and ready. Otherwise return an error explaining the problem.
69   llvm::Expected<DeviceTy &> getDevice(uint32_t DeviceNo);
70 
71   /// Iterate over all initialized and ready devices registered with this
72   /// plugin.
73   auto devices(ExclusiveDevicesAccessorTy &DevicesAccessor) {
74     return llvm::make_pointee_range(*DevicesAccessor);
75   }
76 
77   /// Iterate over all device images registered with this plugin.
78   auto deviceImages() { return llvm::make_pointee_range(DeviceImages); }
79 
80   /// Translation table retreived from the binary
81   HostEntriesBeginToTransTableTy HostEntriesBeginToTransTable;
82   std::mutex TrlTblMtx; ///< For Translation Table
83   /// Host offload entries in order of image registration
84   llvm::SmallVector<llvm::offloading::EntryTy *>
85       HostEntriesBeginRegistrationOrder;
86 
87   /// Map from ptrs on the host to an entry in the Translation Table
88   HostPtrToTableMapTy HostPtrToTableMap;
89   std::mutex TblMapMtx; ///< For HostPtrToTableMap
90 
91   // Work around for plugins that call dlopen on shared libraries that call
92   // tgt_register_lib during their initialisation. Stash the pointers in a
93   // vector until the plugins are all initialised and then register them.
94   bool delayRegisterLib(__tgt_bin_desc *Desc) {
95     if (RTLsLoaded)
96       return false;
97     DelayedBinDesc.push_back(Desc);
98     return true;
99   }
100 
101   void registerDelayedLibraries() {
102     // Only called by libomptarget constructor
103     RTLsLoaded = true;
104     for (auto *Desc : DelayedBinDesc)
105       __tgt_register_lib(Desc);
106     DelayedBinDesc.clear();
107   }
108 
109   /// Return the number of usable devices.
110   int getNumDevices() { return getExclusiveDevicesAccessor()->size(); }
111 
112   /// Return an exclusive handle to access the devices container.
113   ExclusiveDevicesAccessorTy getExclusiveDevicesAccessor() {
114     return Devices.getExclusiveAccessor();
115   }
116 
117   /// Initialize \p Plugin. Returns true on success.
118   bool initializePlugin(GenericPluginTy &Plugin);
119 
120   /// Initialize device \p DeviceNo of \p Plugin. Returns true on success.
121   bool initializeDevice(GenericPluginTy &Plugin, int32_t DeviceId);
122 
123   /// Eagerly initialize all plugins and their devices.
124   void initializeAllDevices();
125 
126   /// Iterator range for all plugins (in use or not, but always valid).
127   auto plugins() { return llvm::make_pointee_range(Plugins); }
128 
129   /// Iterator range for all plugins (in use or not, but always valid).
130   auto plugins() const { return llvm::make_pointee_range(Plugins); }
131 
132   /// Return the user provided requirements.
133   int64_t getRequirements() const { return Requirements.getRequirements(); }
134 
135   /// Add \p Flags to the user provided requirements.
136   void addRequirements(int64_t Flags) { Requirements.addRequirements(Flags); }
137 
138   /// Returns the number of plugins that are active.
139   int getNumActivePlugins() const {
140     int count = 0;
141     for (auto &R : plugins())
142       if (R.is_initialized())
143         ++count;
144 
145     return count;
146   }
147 
148 private:
149   bool RTLsLoaded = false;
150   llvm::SmallVector<__tgt_bin_desc *> DelayedBinDesc;
151 
152   // List of all plugins, in use or not.
153   llvm::SmallVector<std::unique_ptr<GenericPluginTy>> Plugins;
154 
155   // Mapping of plugins to the OpenMP device identifier.
156   llvm::DenseMap<std::pair<const GenericPluginTy *, int32_t>, int32_t>
157       DeviceIds;
158 
159   // Set of all device images currently in use.
160   llvm::DenseSet<const __tgt_device_image *> UsedImages;
161 
162   /// Executable images and information extracted from the input images passed
163   /// to the runtime.
164   llvm::SmallVector<std::unique_ptr<DeviceImageTy>> DeviceImages;
165 
166   /// The user provided requirements.
167   RequirementCollection Requirements;
168 
169   std::mutex RTLsMtx; ///< For RTLs
170 
171   /// Devices associated with plugins, accesses to the container are exclusive.
172   ProtectedObj<DeviceContainerTy> Devices;
173 
174   /// References to upgraded legacy offloading entires.
175   std::list<llvm::SmallVector<llvm::offloading::EntryTy, 0>> LegacyEntries;
176   std::list<llvm::SmallVector<__tgt_device_image, 0>> LegacyImages;
177   llvm::DenseMap<__tgt_bin_desc *, __tgt_bin_desc> UpgradedDescriptors;
178   __tgt_bin_desc *upgradeLegacyEntries(__tgt_bin_desc *Desc);
179 };
180 
181 /// Initialize the plugin manager and OpenMP runtime.
182 void initRuntime();
183 
184 /// Deinitialize the plugin and delete it.
185 void deinitRuntime();
186 
187 extern PluginManager *PM;
188 
189 #endif // OMPTARGET_PLUGIN_MANAGER_H
190