llvm-project

Форк
0
/
PluginManager.cpp 
280 строк · 9.5 Кб
1
//===-- PluginManager.cpp - Plugin loading and communication API ---------===//
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
// Functionality for handling plugins.
10
//
11
//===----------------------------------------------------------------------===//
12

13
#include "PluginManager.h"
14
#include "Shared/Debug.h"
15
#include "Shared/Profile.h"
16

17
#include "llvm/Support/Error.h"
18
#include "llvm/Support/ErrorHandling.h"
19
#include <memory>
20

21
using namespace llvm;
22
using namespace llvm::sys;
23

24
PluginManager *PM = nullptr;
25

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"
29

30
void PluginManager::init() {
31
  TIMESCOPE();
32
  DP("Loading RTLs...\n");
33

34
  // Attempt to create an instance of each supported plugin.
35
#define PLUGIN_TARGET(Name)                                                    \
36
  do {                                                                         \
37
    Plugins.emplace_back(                                                      \
38
        std::unique_ptr<GenericPluginTy>(createPlugin_##Name()));              \
39
  } while (false);
40
#include "Shared/Targets.def"
41

42
  DP("RTLs loaded!\n");
43
}
44

45
void PluginManager::deinit() {
46
  TIMESCOPE();
47
  DP("Unloading RTLs...\n");
48

49
  for (auto &Plugin : Plugins) {
50
    if (!Plugin->is_initialized())
51
      continue;
52

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());
56
    }
57
    Plugin.release();
58
  }
59

60
  DP("RTLs unloaded!\n");
61
}
62

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());
68
      continue;
69
    }
70
    DP("Registered plugin %s with %d visible device(s)\n", R.getName(),
71
       R.number_of_devices());
72
  }
73
}
74

75
void PluginManager::registerLib(__tgt_bin_desc *Desc) {
76
  PM->RTLsMtx.lock();
77

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);
83

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]);
87

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();
92

93
    GenericPluginTy *FoundRTL = nullptr;
94

95
    // Scan the RTLs that have associated images until we find one that supports
96
    // the current image.
97
    for (auto &R : PM->plugins()) {
98
      if (!R.is_plugin_compatible(Img))
99
        continue;
100

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());
105
          continue;
106
        }
107
        DP("Registered plugin %s with %d visible device(s)\n", R.getName(),
108
           R.number_of_devices());
109
      }
110

111
      if (!R.number_of_devices()) {
112
        DP("Skipping plugin %s with no visible devices\n", R.getName());
113
        continue;
114
      }
115

116
      for (int32_t DeviceId = 0; DeviceId < R.number_of_devices(); ++DeviceId) {
117
        if (!R.is_device_compatible(DeviceId, Img))
118
          continue;
119

120
        DP("Image " DPxMOD " is compatible with RTL %s device %d!\n",
121
           DPxPTR(Img->ImageStart), R.getName(), DeviceId);
122

123
        if (!R.is_device_initialized(DeviceId)) {
124
          // Initialize the device information for the RTL we are about to use.
125
          auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
126

127
          int32_t UserId = ExclusiveDevicesAccessor->size();
128

129
          // Set the device identifier offset in the plugin.
130
#ifdef OMPT_SUPPORT
131
          R.set_device_identifier(UserId, DeviceId);
132
#endif
133

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());
138
            continue;
139
          }
140

141
          ExclusiveDevicesAccessor->push_back(std::move(Device));
142

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;
146
        }
147

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;
157
        }
158

159
        // Retrieve translation table for this library.
160
        TranslationTable &TT =
161
            (PM->HostEntriesBeginToTransTable)[Desc->HostEntriesBegin];
162

163
        DP("Registering image " DPxMOD " with RTL %s!\n",
164
           DPxPTR(Img->ImageStart), R.getName());
165

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);
172
        }
173

174
        // Register the image for this target type and invalidate the table.
175
        TT.TargetsImages[UserId] = Img;
176
        TT.TargetsTable[UserId] = nullptr;
177

178
        PM->UsedImages.insert(Img);
179
        FoundRTL = &R;
180

181
        PM->TrlTblMtx.unlock();
182
      }
183
    }
184
    if (!FoundRTL)
185
      DP("No RTL found for image " DPxMOD "!\n", DPxPTR(Img->ImageStart));
186
  }
187
  PM->RTLsMtx.unlock();
188

189
  bool UseAutoZeroCopy = Plugins.size() > 0;
190

191
  auto ExclusiveDevicesAccessor = getExclusiveDevicesAccessor();
192
  for (const auto &Device : *ExclusiveDevicesAccessor)
193
    UseAutoZeroCopy &= Device->useAutoZeroCopy();
194

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.
199
  if (UseAutoZeroCopy)
200
    addRequirements(OMPX_REQ_AUTO_ZERO_COPY);
201

202
  DP("Done registering entries!\n");
203
}
204

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);
208

209
void PluginManager::unregisterLib(__tgt_bin_desc *Desc) {
210
  DP("Unloading target library!\n");
211

212
  PM->RTLsMtx.lock();
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();
217

218
    GenericPluginTy *FoundRTL = NULL;
219

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())
224
        continue;
225

226
      // Ensure that we do not use any unused images associated with this RTL.
227
      if (!UsedImages.contains(Img))
228
        continue;
229

230
      FoundRTL = &R;
231

232
      DP("Unregistered image " DPxMOD " from RTL\n", DPxPTR(Img->ImageStart));
233

234
      break;
235
    }
236

237
    // if no RTL was found proceed to unregister the next image
238
    if (!FoundRTL) {
239
      DP("No RTLs in use support the image " DPxMOD "!\n",
240
         DPxPTR(Img->ImageStart));
241
    }
242
  }
243
  PM->RTLsMtx.unlock();
244
  DP("Done unregistering images!\n");
245

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);
251
  }
252

253
  // Remove translation table for this descriptor.
254
  auto TransTable =
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);
260
  } else {
261
    DP("Translation table for descriptor " DPxMOD " cannot be found, probably "
262
       "it has been already removed.\n",
263
       DPxPTR(Desc->HostEntriesBegin));
264
  }
265

266
  PM->TblMapMtx.unlock();
267

268
  DP("Done unregistering library!\n");
269
}
270

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());
278

279
  return *(*ExclusiveDevicesAccessor)[DeviceNo];
280
}
281

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.