1330d8983SJohannes Doerfert //===-- PluginManager.h - Plugin loading and communication API --*- C++ -*-===// 2330d8983SJohannes Doerfert // 3330d8983SJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4330d8983SJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information. 5330d8983SJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6330d8983SJohannes Doerfert // 7330d8983SJohannes Doerfert //===----------------------------------------------------------------------===// 8330d8983SJohannes Doerfert // 9330d8983SJohannes Doerfert // Declarations for managing devices that are handled by RTL plugins. 10330d8983SJohannes Doerfert // 11330d8983SJohannes Doerfert //===----------------------------------------------------------------------===// 12330d8983SJohannes Doerfert 13330d8983SJohannes Doerfert #ifndef OMPTARGET_PLUGIN_MANAGER_H 14330d8983SJohannes Doerfert #define OMPTARGET_PLUGIN_MANAGER_H 15330d8983SJohannes Doerfert 16fa9e90f5SJoseph Huber #include "PluginInterface.h" 17fa9e90f5SJoseph Huber 18330d8983SJohannes Doerfert #include "DeviceImage.h" 19330d8983SJohannes Doerfert #include "ExclusiveAccess.h" 20330d8983SJohannes Doerfert #include "Shared/APITypes.h" 21330d8983SJohannes Doerfert #include "Shared/Requirements.h" 22330d8983SJohannes Doerfert 23330d8983SJohannes Doerfert #include "device.h" 24330d8983SJohannes Doerfert 25330d8983SJohannes Doerfert #include "llvm/ADT/DenseSet.h" 26330d8983SJohannes Doerfert #include "llvm/ADT/SmallVector.h" 27330d8983SJohannes Doerfert #include "llvm/ADT/iterator.h" 28330d8983SJohannes Doerfert #include "llvm/ADT/iterator_range.h" 29330d8983SJohannes Doerfert #include "llvm/Support/DynamicLibrary.h" 30330d8983SJohannes Doerfert #include "llvm/Support/Error.h" 31330d8983SJohannes Doerfert 32330d8983SJohannes Doerfert #include <cstdint> 33330d8983SJohannes Doerfert #include <list> 34330d8983SJohannes Doerfert #include <memory> 35330d8983SJohannes Doerfert #include <mutex> 36330d8983SJohannes Doerfert #include <string> 37330d8983SJohannes Doerfert 38fa9e90f5SJoseph Huber using GenericPluginTy = llvm::omp::target::plugin::GenericPluginTy; 39330d8983SJohannes Doerfert 40330d8983SJohannes Doerfert /// Struct for the data required to handle plugins 41330d8983SJohannes Doerfert struct PluginManager { 42330d8983SJohannes Doerfert /// Type of the devices container. We hand out DeviceTy& to queries which are 43330d8983SJohannes Doerfert /// stable addresses regardless if the container changes. 44330d8983SJohannes Doerfert using DeviceContainerTy = llvm::SmallVector<std::unique_ptr<DeviceTy>>; 45330d8983SJohannes Doerfert 46330d8983SJohannes Doerfert /// Exclusive accessor type for the device container. 47330d8983SJohannes Doerfert using ExclusiveDevicesAccessorTy = Accessor<DeviceContainerTy>; 48330d8983SJohannes Doerfert 49330d8983SJohannes Doerfert PluginManager() {} 50330d8983SJohannes Doerfert 51330d8983SJohannes Doerfert void init(); 52330d8983SJohannes Doerfert 53fa9e90f5SJoseph Huber void deinit(); 54fa9e90f5SJoseph Huber 55330d8983SJohannes Doerfert // Register a shared library with all (compatible) RTLs. 56330d8983SJohannes Doerfert void registerLib(__tgt_bin_desc *Desc); 57330d8983SJohannes Doerfert 58330d8983SJohannes Doerfert // Unregister a shared library from all RTLs. 59330d8983SJohannes Doerfert void unregisterLib(__tgt_bin_desc *Desc); 60330d8983SJohannes Doerfert 61330d8983SJohannes Doerfert void addDeviceImage(__tgt_bin_desc &TgtBinDesc, 62330d8983SJohannes Doerfert __tgt_device_image &TgtDeviceImage) { 63330d8983SJohannes Doerfert DeviceImages.emplace_back( 64330d8983SJohannes Doerfert std::make_unique<DeviceImageTy>(TgtBinDesc, TgtDeviceImage)); 65330d8983SJohannes Doerfert } 66330d8983SJohannes Doerfert 67330d8983SJohannes Doerfert /// Return the device presented to the user as device \p DeviceNo if it is 68330d8983SJohannes Doerfert /// initialized and ready. Otherwise return an error explaining the problem. 69330d8983SJohannes Doerfert llvm::Expected<DeviceTy &> getDevice(uint32_t DeviceNo); 70330d8983SJohannes Doerfert 71330d8983SJohannes Doerfert /// Iterate over all initialized and ready devices registered with this 72330d8983SJohannes Doerfert /// plugin. 73330d8983SJohannes Doerfert auto devices(ExclusiveDevicesAccessorTy &DevicesAccessor) { 74330d8983SJohannes Doerfert return llvm::make_pointee_range(*DevicesAccessor); 75330d8983SJohannes Doerfert } 76330d8983SJohannes Doerfert 77330d8983SJohannes Doerfert /// Iterate over all device images registered with this plugin. 78330d8983SJohannes Doerfert auto deviceImages() { return llvm::make_pointee_range(DeviceImages); } 79330d8983SJohannes Doerfert 80330d8983SJohannes Doerfert /// Translation table retreived from the binary 81330d8983SJohannes Doerfert HostEntriesBeginToTransTableTy HostEntriesBeginToTransTable; 82330d8983SJohannes Doerfert std::mutex TrlTblMtx; ///< For Translation Table 83330d8983SJohannes Doerfert /// Host offload entries in order of image registration 846518b121SJoseph Huber llvm::SmallVector<llvm::offloading::EntryTy *> 856518b121SJoseph Huber HostEntriesBeginRegistrationOrder; 86330d8983SJohannes Doerfert 87330d8983SJohannes Doerfert /// Map from ptrs on the host to an entry in the Translation Table 88330d8983SJohannes Doerfert HostPtrToTableMapTy HostPtrToTableMap; 89330d8983SJohannes Doerfert std::mutex TblMapMtx; ///< For HostPtrToTableMap 90330d8983SJohannes Doerfert 91330d8983SJohannes Doerfert // Work around for plugins that call dlopen on shared libraries that call 92330d8983SJohannes Doerfert // tgt_register_lib during their initialisation. Stash the pointers in a 93330d8983SJohannes Doerfert // vector until the plugins are all initialised and then register them. 94330d8983SJohannes Doerfert bool delayRegisterLib(__tgt_bin_desc *Desc) { 95330d8983SJohannes Doerfert if (RTLsLoaded) 96330d8983SJohannes Doerfert return false; 97330d8983SJohannes Doerfert DelayedBinDesc.push_back(Desc); 98330d8983SJohannes Doerfert return true; 99330d8983SJohannes Doerfert } 100330d8983SJohannes Doerfert 101330d8983SJohannes Doerfert void registerDelayedLibraries() { 102330d8983SJohannes Doerfert // Only called by libomptarget constructor 103330d8983SJohannes Doerfert RTLsLoaded = true; 104330d8983SJohannes Doerfert for (auto *Desc : DelayedBinDesc) 105330d8983SJohannes Doerfert __tgt_register_lib(Desc); 106330d8983SJohannes Doerfert DelayedBinDesc.clear(); 107330d8983SJohannes Doerfert } 108330d8983SJohannes Doerfert 109330d8983SJohannes Doerfert /// Return the number of usable devices. 110330d8983SJohannes Doerfert int getNumDevices() { return getExclusiveDevicesAccessor()->size(); } 111330d8983SJohannes Doerfert 112330d8983SJohannes Doerfert /// Return an exclusive handle to access the devices container. 113330d8983SJohannes Doerfert ExclusiveDevicesAccessorTy getExclusiveDevicesAccessor() { 114330d8983SJohannes Doerfert return Devices.getExclusiveAccessor(); 115330d8983SJohannes Doerfert } 116330d8983SJohannes Doerfert 1177102592aSJohannes Doerfert /// Initialize \p Plugin. Returns true on success. 1187102592aSJohannes Doerfert bool initializePlugin(GenericPluginTy &Plugin); 1197102592aSJohannes Doerfert 1207102592aSJohannes Doerfert /// Initialize device \p DeviceNo of \p Plugin. Returns true on success. 1217102592aSJohannes Doerfert bool initializeDevice(GenericPluginTy &Plugin, int32_t DeviceId); 1227102592aSJohannes Doerfert 1237102592aSJohannes Doerfert /// Eagerly initialize all plugins and their devices. 1247102592aSJohannes Doerfert void initializeAllDevices(); 125330d8983SJohannes Doerfert 126fa9e90f5SJoseph Huber /// Iterator range for all plugins (in use or not, but always valid). 127fa9e90f5SJoseph Huber auto plugins() { return llvm::make_pointee_range(Plugins); } 128330d8983SJohannes Doerfert 129435aa766SJoseph Huber /// Iterator range for all plugins (in use or not, but always valid). 130435aa766SJoseph Huber auto plugins() const { return llvm::make_pointee_range(Plugins); } 131435aa766SJoseph Huber 132330d8983SJohannes Doerfert /// Return the user provided requirements. 133330d8983SJohannes Doerfert int64_t getRequirements() const { return Requirements.getRequirements(); } 134330d8983SJohannes Doerfert 135330d8983SJohannes Doerfert /// Add \p Flags to the user provided requirements. 136330d8983SJohannes Doerfert void addRequirements(int64_t Flags) { Requirements.addRequirements(Flags); } 137330d8983SJohannes Doerfert 138435aa766SJoseph Huber /// Returns the number of plugins that are active. 139435aa766SJoseph Huber int getNumActivePlugins() const { 140435aa766SJoseph Huber int count = 0; 141435aa766SJoseph Huber for (auto &R : plugins()) 142435aa766SJoseph Huber if (R.is_initialized()) 143435aa766SJoseph Huber ++count; 144435aa766SJoseph Huber 145435aa766SJoseph Huber return count; 146435aa766SJoseph Huber } 147435aa766SJoseph Huber 148330d8983SJohannes Doerfert private: 149330d8983SJohannes Doerfert bool RTLsLoaded = false; 150330d8983SJohannes Doerfert llvm::SmallVector<__tgt_bin_desc *> DelayedBinDesc; 151330d8983SJohannes Doerfert 152fa9e90f5SJoseph Huber // List of all plugins, in use or not. 153fa9e90f5SJoseph Huber llvm::SmallVector<std::unique_ptr<GenericPluginTy>> Plugins; 154330d8983SJohannes Doerfert 155435aa766SJoseph Huber // Mapping of plugins to the OpenMP device identifier. 156435aa766SJoseph Huber llvm::DenseMap<std::pair<const GenericPluginTy *, int32_t>, int32_t> 157435aa766SJoseph Huber DeviceIds; 158330d8983SJohannes Doerfert 159330d8983SJohannes Doerfert // Set of all device images currently in use. 160330d8983SJohannes Doerfert llvm::DenseSet<const __tgt_device_image *> UsedImages; 161330d8983SJohannes Doerfert 162330d8983SJohannes Doerfert /// Executable images and information extracted from the input images passed 163330d8983SJohannes Doerfert /// to the runtime. 164330d8983SJohannes Doerfert llvm::SmallVector<std::unique_ptr<DeviceImageTy>> DeviceImages; 165330d8983SJohannes Doerfert 166330d8983SJohannes Doerfert /// The user provided requirements. 167330d8983SJohannes Doerfert RequirementCollection Requirements; 168330d8983SJohannes Doerfert 169330d8983SJohannes Doerfert std::mutex RTLsMtx; ///< For RTLs 170330d8983SJohannes Doerfert 171330d8983SJohannes Doerfert /// Devices associated with plugins, accesses to the container are exclusive. 172330d8983SJohannes Doerfert ProtectedObj<DeviceContainerTy> Devices; 173*13dcc95dSJoseph Huber 174*13dcc95dSJoseph Huber /// References to upgraded legacy offloading entires. 175*13dcc95dSJoseph Huber std::list<llvm::SmallVector<llvm::offloading::EntryTy, 0>> LegacyEntries; 176*13dcc95dSJoseph Huber std::list<llvm::SmallVector<__tgt_device_image, 0>> LegacyImages; 177*13dcc95dSJoseph Huber llvm::DenseMap<__tgt_bin_desc *, __tgt_bin_desc> UpgradedDescriptors; 178*13dcc95dSJoseph Huber __tgt_bin_desc *upgradeLegacyEntries(__tgt_bin_desc *Desc); 179330d8983SJohannes Doerfert }; 180330d8983SJohannes Doerfert 181330d8983SJohannes Doerfert /// Initialize the plugin manager and OpenMP runtime. 182330d8983SJohannes Doerfert void initRuntime(); 183330d8983SJohannes Doerfert 184330d8983SJohannes Doerfert /// Deinitialize the plugin and delete it. 185330d8983SJohannes Doerfert void deinitRuntime(); 186330d8983SJohannes Doerfert 187330d8983SJohannes Doerfert extern PluginManager *PM; 188330d8983SJohannes Doerfert 189330d8983SJohannes Doerfert #endif // OMPTARGET_PLUGIN_MANAGER_H 190