1 //===-- PluginManager.cpp - Plugin loading and communication API ---------===//
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
7 //===----------------------------------------------------------------------===//
9 // Functionality for handling plugins.
11 //===----------------------------------------------------------------------===//
13 #include "PluginManager.h"
14 #include "Shared/Debug.h"
15 #include "Shared/Profile.h"
17 #include "llvm/Support/Error.h"
18 #include "llvm/Support/ErrorHandling.h"
22 using namespace llvm::sys
;
24 PluginManager
*PM
= nullptr;
26 // Every plugin exports this method to create an instance of the plugin type.
27 #define PLUGIN_TARGET(Name) extern "C" GenericPluginTy *createPlugin_##Name();
28 #include "Shared/Targets.def"
30 void PluginManager::init() {
32 DP("Loading RTLs...\n");
34 // Attempt to create an instance of each supported plugin.
35 #define PLUGIN_TARGET(Name) \
37 Plugins.emplace_back( \
38 std::unique_ptr<GenericPluginTy>(createPlugin_##Name())); \
40 #include "Shared/Targets.def"
45 void PluginManager::deinit() {
47 DP("Unloading RTLs...\n");
49 for (auto &Plugin
: Plugins
) {
50 if (!Plugin
->is_initialized())
53 if (auto Err
= Plugin
->deinit()) {
54 [[maybe_unused
]] std::string InfoMsg
= toString(std::move(Err
));
55 DP("Failed to deinit plugin: %s\n", InfoMsg
.c_str());
60 DP("RTLs unloaded!\n");
63 void PluginManager::initAllPlugins() {
64 for (auto &R
: plugins()) {
65 if (auto Err
= R
.init()) {
66 [[maybe_unused
]] std::string InfoMsg
= toString(std::move(Err
));
67 DP("Failed to init plugin: %s\n", InfoMsg
.c_str());
70 DP("Registered plugin %s with %d visible device(s)\n", R
.getName(),
71 R
.number_of_devices());
75 void PluginManager::registerLib(__tgt_bin_desc
*Desc
) {
78 // Add in all the OpenMP requirements associated with this binary.
79 for (__tgt_offload_entry
&Entry
:
80 llvm::make_range(Desc
->HostEntriesBegin
, Desc
->HostEntriesEnd
))
81 if (Entry
.flags
== OMP_REGISTER_REQUIRES
)
82 PM
->addRequirements(Entry
.data
);
84 // Extract the exectuable image and extra information if availible.
85 for (int32_t i
= 0; i
< Desc
->NumDeviceImages
; ++i
)
86 PM
->addDeviceImage(*Desc
, Desc
->DeviceImages
[i
]);
88 // Register the images with the RTLs that understand them, if any.
89 for (DeviceImageTy
&DI
: PM
->deviceImages()) {
90 // Obtain the image and information that was previously extracted.
91 __tgt_device_image
*Img
= &DI
.getExecutableImage();
93 GenericPluginTy
*FoundRTL
= nullptr;
95 // Scan the RTLs that have associated images until we find one that supports
97 for (auto &R
: PM
->plugins()) {
98 if (!R
.is_plugin_compatible(Img
))
101 if (!R
.is_initialized()) {
102 if (auto Err
= R
.init()) {
103 [[maybe_unused
]] std::string InfoMsg
= toString(std::move(Err
));
104 DP("Failed to init plugin: %s\n", InfoMsg
.c_str());
107 DP("Registered plugin %s with %d visible device(s)\n", R
.getName(),
108 R
.number_of_devices());
111 if (!R
.number_of_devices()) {
112 DP("Skipping plugin %s with no visible devices\n", R
.getName());
116 for (int32_t DeviceId
= 0; DeviceId
< R
.number_of_devices(); ++DeviceId
) {
117 if (!R
.is_device_compatible(DeviceId
, Img
))
120 DP("Image " DPxMOD
" is compatible with RTL %s device %d!\n",
121 DPxPTR(Img
->ImageStart
), R
.getName(), DeviceId
);
123 if (!R
.is_device_initialized(DeviceId
)) {
124 // Initialize the device information for the RTL we are about to use.
125 auto ExclusiveDevicesAccessor
= getExclusiveDevicesAccessor();
127 int32_t UserId
= ExclusiveDevicesAccessor
->size();
129 // Set the device identifier offset in the plugin.
131 R
.set_device_identifier(UserId
, DeviceId
);
134 auto Device
= std::make_unique
<DeviceTy
>(&R
, UserId
, DeviceId
);
135 if (auto Err
= Device
->init()) {
136 [[maybe_unused
]] std::string InfoMsg
= toString(std::move(Err
));
137 DP("Failed to init device %d: %s\n", DeviceId
, InfoMsg
.c_str());
141 ExclusiveDevicesAccessor
->push_back(std::move(Device
));
143 // We need to map between the plugin's device identifier and the one
144 // that OpenMP will use.
145 PM
->DeviceIds
[std::make_pair(&R
, DeviceId
)] = UserId
;
148 // Initialize (if necessary) translation table for this library.
149 PM
->TrlTblMtx
.lock();
150 if (!PM
->HostEntriesBeginToTransTable
.count(Desc
->HostEntriesBegin
)) {
151 PM
->HostEntriesBeginRegistrationOrder
.push_back(
152 Desc
->HostEntriesBegin
);
153 TranslationTable
&TT
=
154 (PM
->HostEntriesBeginToTransTable
)[Desc
->HostEntriesBegin
];
155 TT
.HostTable
.EntriesBegin
= Desc
->HostEntriesBegin
;
156 TT
.HostTable
.EntriesEnd
= Desc
->HostEntriesEnd
;
159 // Retrieve translation table for this library.
160 TranslationTable
&TT
=
161 (PM
->HostEntriesBeginToTransTable
)[Desc
->HostEntriesBegin
];
163 DP("Registering image " DPxMOD
" with RTL %s!\n",
164 DPxPTR(Img
->ImageStart
), R
.getName());
166 auto UserId
= PM
->DeviceIds
[std::make_pair(&R
, DeviceId
)];
167 if (TT
.TargetsTable
.size() < static_cast<size_t>(UserId
+ 1)) {
168 TT
.DeviceTables
.resize(UserId
+ 1, {});
169 TT
.TargetsImages
.resize(UserId
+ 1, nullptr);
170 TT
.TargetsEntries
.resize(UserId
+ 1, {});
171 TT
.TargetsTable
.resize(UserId
+ 1, nullptr);
174 // Register the image for this target type and invalidate the table.
175 TT
.TargetsImages
[UserId
] = Img
;
176 TT
.TargetsTable
[UserId
] = nullptr;
178 PM
->UsedImages
.insert(Img
);
181 PM
->TrlTblMtx
.unlock();
185 DP("No RTL found for image " DPxMOD
"!\n", DPxPTR(Img
->ImageStart
));
187 PM
->RTLsMtx
.unlock();
189 bool UseAutoZeroCopy
= Plugins
.size() > 0;
191 auto ExclusiveDevicesAccessor
= getExclusiveDevicesAccessor();
192 for (const auto &Device
: *ExclusiveDevicesAccessor
)
193 UseAutoZeroCopy
&= Device
->useAutoZeroCopy();
195 // Auto Zero-Copy can only be currently triggered when the system is an
196 // homogeneous APU architecture without attached discrete GPUs.
197 // If all devices suggest to use it, change requirment flags to trigger
198 // zero-copy behavior when mapping memory.
200 addRequirements(OMPX_REQ_AUTO_ZERO_COPY
);
202 DP("Done registering entries!\n");
205 // Temporary forward declaration, old style CTor/DTor handling is going away.
206 int target(ident_t
*Loc
, DeviceTy
&Device
, void *HostPtr
,
207 KernelArgsTy
&KernelArgs
, AsyncInfoTy
&AsyncInfo
);
209 void PluginManager::unregisterLib(__tgt_bin_desc
*Desc
) {
210 DP("Unloading target library!\n");
213 // Find which RTL understands each image, if any.
214 for (DeviceImageTy
&DI
: PM
->deviceImages()) {
215 // Obtain the image and information that was previously extracted.
216 __tgt_device_image
*Img
= &DI
.getExecutableImage();
218 GenericPluginTy
*FoundRTL
= NULL
;
220 // Scan the RTLs that have associated images until we find one that supports
221 // the current image. We only need to scan RTLs that are already being used.
222 for (auto &R
: PM
->plugins()) {
223 if (R
.is_initialized())
226 // Ensure that we do not use any unused images associated with this RTL.
227 if (!UsedImages
.contains(Img
))
232 DP("Unregistered image " DPxMOD
" from RTL\n", DPxPTR(Img
->ImageStart
));
237 // if no RTL was found proceed to unregister the next image
239 DP("No RTLs in use support the image " DPxMOD
"!\n",
240 DPxPTR(Img
->ImageStart
));
243 PM
->RTLsMtx
.unlock();
244 DP("Done unregistering images!\n");
246 // Remove entries from PM->HostPtrToTableMap
247 PM
->TblMapMtx
.lock();
248 for (__tgt_offload_entry
*Cur
= Desc
->HostEntriesBegin
;
249 Cur
< Desc
->HostEntriesEnd
; ++Cur
) {
250 PM
->HostPtrToTableMap
.erase(Cur
->addr
);
253 // Remove translation table for this descriptor.
255 PM
->HostEntriesBeginToTransTable
.find(Desc
->HostEntriesBegin
);
256 if (TransTable
!= PM
->HostEntriesBeginToTransTable
.end()) {
257 DP("Removing translation table for descriptor " DPxMOD
"\n",
258 DPxPTR(Desc
->HostEntriesBegin
));
259 PM
->HostEntriesBeginToTransTable
.erase(TransTable
);
261 DP("Translation table for descriptor " DPxMOD
" cannot be found, probably "
262 "it has been already removed.\n",
263 DPxPTR(Desc
->HostEntriesBegin
));
266 PM
->TblMapMtx
.unlock();
268 DP("Done unregistering library!\n");
271 Expected
<DeviceTy
&> PluginManager::getDevice(uint32_t DeviceNo
) {
272 auto ExclusiveDevicesAccessor
= getExclusiveDevicesAccessor();
273 if (DeviceNo
>= ExclusiveDevicesAccessor
->size())
274 return createStringError(
275 inconvertibleErrorCode(),
276 "Device number '%i' out of range, only %i devices available", DeviceNo
,
277 ExclusiveDevicesAccessor
->size());
279 return *(*ExclusiveDevicesAccessor
)[DeviceNo
];