blob: fd46477f2dbe3e693fa2d1263020e6ec4b59def0 [file] [log] [blame]
Jonas Hahnfeld43322802017-12-06 21:59:07 +00001//===----------- rtl.cpp - Target independent OpenMP target RTL -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.txt for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Functionality for handling RTL plugins.
11//
12//===----------------------------------------------------------------------===//
13
14#include "device.h"
15#include "private.h"
16#include "rtl.h"
17
18#include <cassert>
Dimitry Andric9f496762018-01-18 18:24:22 +000019#include <cstdlib>
Jonas Hahnfeld43322802017-12-06 21:59:07 +000020#include <cstring>
21#include <dlfcn.h>
22#include <mutex>
Jonas Hahnfelde5499112018-01-18 10:58:43 +000023#include <string>
Jonas Hahnfeld43322802017-12-06 21:59:07 +000024
25// List of all plugins that can support offloading.
26static const char *RTLNames[] = {
27 /* PowerPC target */ "libomptarget.rtl.ppc64.so",
28 /* x86_64 target */ "libomptarget.rtl.x86_64.so",
29 /* CUDA target */ "libomptarget.rtl.cuda.so",
30 /* AArch64 target */ "libomptarget.rtl.aarch64.so"};
31
32RTLsTy RTLs;
33std::mutex RTLsMtx;
34
35HostEntriesBeginToTransTableTy HostEntriesBeginToTransTable;
36std::mutex TrlTblMtx;
37
38HostPtrToTableMapTy HostPtrToTableMap;
39std::mutex TblMapMtx;
40
41void RTLsTy::LoadRTLs() {
42#ifdef OMPTARGET_DEBUG
43 if (char *envStr = getenv("LIBOMPTARGET_DEBUG")) {
44 DebugLevel = std::stoi(envStr);
45 }
46#endif // OMPTARGET_DEBUG
47
48 // Parse environment variable OMP_TARGET_OFFLOAD (if set)
Alexandre Eichenberger1b4a6662018-08-23 16:22:42 +000049 TargetOffloadPolicy = (kmp_target_offload_kind_t) __kmpc_get_target_offload();
50 if (TargetOffloadPolicy == tgt_disabled) {
Jonas Hahnfeld43322802017-12-06 21:59:07 +000051 return;
52 }
53
54 DP("Loading RTLs...\n");
55
56 // Attempt to open all the plugins and, if they exist, check if the interface
57 // is correct and if they are supporting any devices.
58 for (auto *Name : RTLNames) {
59 DP("Loading library '%s'...\n", Name);
60 void *dynlib_handle = dlopen(Name, RTLD_NOW);
61
62 if (!dynlib_handle) {
63 // Library does not exist or cannot be found.
64 DP("Unable to load library '%s': %s!\n", Name, dlerror());
65 continue;
66 }
67
68 DP("Successfully loaded library '%s'!\n", Name);
69
70 // Retrieve the RTL information from the runtime library.
71 RTLInfoTy R;
72
73 R.LibraryHandler = dynlib_handle;
74 R.isUsed = false;
75
76#ifdef OMPTARGET_DEBUG
77 R.RTLName = Name;
78#endif
79
80 if (!(*((void**) &R.is_valid_binary) = dlsym(
81 dynlib_handle, "__tgt_rtl_is_valid_binary")))
82 continue;
83 if (!(*((void**) &R.number_of_devices) = dlsym(
84 dynlib_handle, "__tgt_rtl_number_of_devices")))
85 continue;
86 if (!(*((void**) &R.init_device) = dlsym(
87 dynlib_handle, "__tgt_rtl_init_device")))
88 continue;
89 if (!(*((void**) &R.load_binary) = dlsym(
90 dynlib_handle, "__tgt_rtl_load_binary")))
91 continue;
92 if (!(*((void**) &R.data_alloc) = dlsym(
93 dynlib_handle, "__tgt_rtl_data_alloc")))
94 continue;
95 if (!(*((void**) &R.data_submit) = dlsym(
96 dynlib_handle, "__tgt_rtl_data_submit")))
97 continue;
98 if (!(*((void**) &R.data_retrieve) = dlsym(
99 dynlib_handle, "__tgt_rtl_data_retrieve")))
100 continue;
101 if (!(*((void**) &R.data_delete) = dlsym(
102 dynlib_handle, "__tgt_rtl_data_delete")))
103 continue;
104 if (!(*((void**) &R.run_region) = dlsym(
105 dynlib_handle, "__tgt_rtl_run_target_region")))
106 continue;
107 if (!(*((void**) &R.run_team_region) = dlsym(
108 dynlib_handle, "__tgt_rtl_run_target_team_region")))
109 continue;
110
111 // No devices are supported by this RTL?
112 if (!(R.NumberOfDevices = R.number_of_devices())) {
113 DP("No devices supported in this RTL\n");
114 continue;
115 }
116
117 DP("Registering RTL %s supporting %d devices!\n",
118 R.RTLName.c_str(), R.NumberOfDevices);
119
120 // The RTL is valid! Will save the information in the RTLs list.
121 AllRTLs.push_back(R);
122 }
123
124 DP("RTLs loaded!\n");
125
126 return;
127}
128
129////////////////////////////////////////////////////////////////////////////////
130// Functionality for registering libs
131
132static void RegisterImageIntoTranslationTable(TranslationTable &TT,
133 RTLInfoTy &RTL, __tgt_device_image *image) {
134
135 // same size, as when we increase one, we also increase the other.
136 assert(TT.TargetsTable.size() == TT.TargetsImages.size() &&
137 "We should have as many images as we have tables!");
138
139 // Resize the Targets Table and Images to accommodate the new targets if
140 // required
141 unsigned TargetsTableMinimumSize = RTL.Idx + RTL.NumberOfDevices;
142
143 if (TT.TargetsTable.size() < TargetsTableMinimumSize) {
144 TT.TargetsImages.resize(TargetsTableMinimumSize, 0);
145 TT.TargetsTable.resize(TargetsTableMinimumSize, 0);
146 }
147
148 // Register the image in all devices for this target type.
149 for (int32_t i = 0; i < RTL.NumberOfDevices; ++i) {
150 // If we are changing the image we are also invalidating the target table.
151 if (TT.TargetsImages[RTL.Idx + i] != image) {
152 TT.TargetsImages[RTL.Idx + i] = image;
153 TT.TargetsTable[RTL.Idx + i] = 0; // lazy initialization of target table.
154 }
155 }
156}
157
158////////////////////////////////////////////////////////////////////////////////
159// Functionality for registering Ctors/Dtors
160
161static void RegisterGlobalCtorsDtorsForImage(__tgt_bin_desc *desc,
162 __tgt_device_image *img, RTLInfoTy *RTL) {
163
164 for (int32_t i = 0; i < RTL->NumberOfDevices; ++i) {
165 DeviceTy &Device = Devices[RTL->Idx + i];
166 Device.PendingGlobalsMtx.lock();
167 Device.HasPendingGlobals = true;
168 for (__tgt_offload_entry *entry = img->EntriesBegin;
169 entry != img->EntriesEnd; ++entry) {
170 if (entry->flags & OMP_DECLARE_TARGET_CTOR) {
171 DP("Adding ctor " DPxMOD " to the pending list.\n",
172 DPxPTR(entry->addr));
173 Device.PendingCtorsDtors[desc].PendingCtors.push_back(entry->addr);
174 } else if (entry->flags & OMP_DECLARE_TARGET_DTOR) {
175 // Dtors are pushed in reverse order so they are executed from end
176 // to beginning when unregistering the library!
177 DP("Adding dtor " DPxMOD " to the pending list.\n",
178 DPxPTR(entry->addr));
179 Device.PendingCtorsDtors[desc].PendingDtors.push_front(entry->addr);
180 }
181
182 if (entry->flags & OMP_DECLARE_TARGET_LINK) {
183 DP("The \"link\" attribute is not yet supported!\n");
184 }
185 }
186 Device.PendingGlobalsMtx.unlock();
187 }
188}
189
190void RTLsTy::RegisterLib(__tgt_bin_desc *desc) {
191 // Attempt to load all plugins available in the system.
192 std::call_once(initFlag, &RTLsTy::LoadRTLs, this);
193
194 RTLsMtx.lock();
195 // Register the images with the RTLs that understand them, if any.
196 for (int32_t i = 0; i < desc->NumDeviceImages; ++i) {
197 // Obtain the image.
198 __tgt_device_image *img = &desc->DeviceImages[i];
199
200 RTLInfoTy *FoundRTL = NULL;
201
202 // Scan the RTLs that have associated images until we find one that supports
203 // the current image.
204 for (auto &R : RTLs.AllRTLs) {
205 if (!R.is_valid_binary(img)) {
206 DP("Image " DPxMOD " is NOT compatible with RTL %s!\n",
207 DPxPTR(img->ImageStart), R.RTLName.c_str());
208 continue;
209 }
210
211 DP("Image " DPxMOD " is compatible with RTL %s!\n",
212 DPxPTR(img->ImageStart), R.RTLName.c_str());
213
214 // If this RTL is not already in use, initialize it.
215 if (!R.isUsed) {
216 // Initialize the device information for the RTL we are about to use.
217 DeviceTy device(&R);
Jonas Hahnfeld43322802017-12-06 21:59:07 +0000218 size_t start = Devices.size();
219 Devices.resize(start + R.NumberOfDevices, device);
220 for (int32_t device_id = 0; device_id < R.NumberOfDevices;
221 device_id++) {
222 // global device ID
223 Devices[start + device_id].DeviceID = start + device_id;
224 // RTL local device ID
225 Devices[start + device_id].RTLDeviceID = device_id;
Jonas Hahnfeld43322802017-12-06 21:59:07 +0000226 }
227
228 // Initialize the index of this RTL and save it in the used RTLs.
229 R.Idx = (RTLs.UsedRTLs.empty())
230 ? 0
231 : RTLs.UsedRTLs.back()->Idx +
232 RTLs.UsedRTLs.back()->NumberOfDevices;
233 assert((size_t) R.Idx == start &&
234 "RTL index should equal the number of devices used so far.");
235 R.isUsed = true;
236 RTLs.UsedRTLs.push_back(&R);
237
238 DP("RTL " DPxMOD " has index %d!\n", DPxPTR(R.LibraryHandler), R.Idx);
239 }
240
241 // Initialize (if necessary) translation table for this library.
242 TrlTblMtx.lock();
243 if(!HostEntriesBeginToTransTable.count(desc->HostEntriesBegin)){
244 TranslationTable &tt =
245 HostEntriesBeginToTransTable[desc->HostEntriesBegin];
246 tt.HostTable.EntriesBegin = desc->HostEntriesBegin;
247 tt.HostTable.EntriesEnd = desc->HostEntriesEnd;
248 }
249
250 // Retrieve translation table for this library.
251 TranslationTable &TransTable =
252 HostEntriesBeginToTransTable[desc->HostEntriesBegin];
253
254 DP("Registering image " DPxMOD " with RTL %s!\n",
255 DPxPTR(img->ImageStart), R.RTLName.c_str());
256 RegisterImageIntoTranslationTable(TransTable, R, img);
257 TrlTblMtx.unlock();
258 FoundRTL = &R;
259
260 // Load ctors/dtors for static objects
261 RegisterGlobalCtorsDtorsForImage(desc, img, FoundRTL);
262
263 // if an RTL was found we are done - proceed to register the next image
264 break;
265 }
266
267 if (!FoundRTL) {
268 DP("No RTL found for image " DPxMOD "!\n", DPxPTR(img->ImageStart));
269 }
270 }
271 RTLsMtx.unlock();
272
273
274 DP("Done registering entries!\n");
275}
276
277void RTLsTy::UnregisterLib(__tgt_bin_desc *desc) {
278 DP("Unloading target library!\n");
279
280 RTLsMtx.lock();
281 // Find which RTL understands each image, if any.
282 for (int32_t i = 0; i < desc->NumDeviceImages; ++i) {
283 // Obtain the image.
284 __tgt_device_image *img = &desc->DeviceImages[i];
285
286 RTLInfoTy *FoundRTL = NULL;
287
288 // Scan the RTLs that have associated images until we find one that supports
289 // the current image. We only need to scan RTLs that are already being used.
290 for (auto *R : RTLs.UsedRTLs) {
291
292 assert(R->isUsed && "Expecting used RTLs.");
293
294 if (!R->is_valid_binary(img)) {
295 DP("Image " DPxMOD " is NOT compatible with RTL " DPxMOD "!\n",
296 DPxPTR(img->ImageStart), DPxPTR(R->LibraryHandler));
297 continue;
298 }
299
300 DP("Image " DPxMOD " is compatible with RTL " DPxMOD "!\n",
301 DPxPTR(img->ImageStart), DPxPTR(R->LibraryHandler));
302
303 FoundRTL = R;
304
305 // Execute dtors for static objects if the device has been used, i.e.
306 // if its PendingCtors list has been emptied.
307 for (int32_t i = 0; i < FoundRTL->NumberOfDevices; ++i) {
308 DeviceTy &Device = Devices[FoundRTL->Idx + i];
309 Device.PendingGlobalsMtx.lock();
310 if (Device.PendingCtorsDtors[desc].PendingCtors.empty()) {
311 for (auto &dtor : Device.PendingCtorsDtors[desc].PendingDtors) {
312 int rc = target(Device.DeviceID, dtor, 0, NULL, NULL, NULL, NULL, 1,
313 1, true /*team*/);
314 if (rc != OFFLOAD_SUCCESS) {
315 DP("Running destructor " DPxMOD " failed.\n", DPxPTR(dtor));
316 }
317 }
318 // Remove this library's entry from PendingCtorsDtors
319 Device.PendingCtorsDtors.erase(desc);
320 }
321 Device.PendingGlobalsMtx.unlock();
322 }
323
324 DP("Unregistered image " DPxMOD " from RTL " DPxMOD "!\n",
325 DPxPTR(img->ImageStart), DPxPTR(R->LibraryHandler));
326
327 break;
328 }
329
330 // if no RTL was found proceed to unregister the next image
331 if (!FoundRTL){
332 DP("No RTLs in use support the image " DPxMOD "!\n",
333 DPxPTR(img->ImageStart));
334 }
335 }
336 RTLsMtx.unlock();
337 DP("Done unregistering images!\n");
338
339 // Remove entries from HostPtrToTableMap
340 TblMapMtx.lock();
341 for (__tgt_offload_entry *cur = desc->HostEntriesBegin;
342 cur < desc->HostEntriesEnd; ++cur) {
343 HostPtrToTableMap.erase(cur->addr);
344 }
345
346 // Remove translation table for this descriptor.
347 auto tt = HostEntriesBeginToTransTable.find(desc->HostEntriesBegin);
348 if (tt != HostEntriesBeginToTransTable.end()) {
349 DP("Removing translation table for descriptor " DPxMOD "\n",
350 DPxPTR(desc->HostEntriesBegin));
351 HostEntriesBeginToTransTable.erase(tt);
352 } else {
353 DP("Translation table for descriptor " DPxMOD " cannot be found, probably "
354 "it has been already removed.\n", DPxPTR(desc->HostEntriesBegin));
355 }
356
357 TblMapMtx.unlock();
358
359 // TODO: Remove RTL and the devices it manages if it's not used anymore?
360 // TODO: Write some RTL->unload_image(...) function?
361
362 DP("Done unregistering library!\n");
363}