Files
clang-p2996/openmp/libomptarget/include/PluginManager.h
Joseph Huber 254287658f [Libomptarget] Remove handling of old ctor / dtor entries (#80153)
Summary:
A previous patch removed creating these entries in clang in favor of the
backend emitting a callable kernel and having the runtime call that if
present. The support for the old style was kept around in LLVM 18.0 but
now that we have forked to 19.0 we should remove the support.

The effect of this would be that an application linking against a newer
libomptarget that still had the old constructors will no longer be
called. In that case, they can either recompile or use the
`libomptarget.so.18` that comes with the previous release.
2024-01-31 11:48:07 -06:00

212 lines
7.2 KiB
C++

//===-- PluginManager.h - Plugin loading and communication API --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Declarations for managing devices that are handled by RTL plugins.
//
//===----------------------------------------------------------------------===//
#ifndef OMPTARGET_PLUGIN_MANAGER_H
#define OMPTARGET_PLUGIN_MANAGER_H
#include "DeviceImage.h"
#include "ExclusiveAccess.h"
#include "Shared/APITypes.h"
#include "Shared/PluginAPI.h"
#include "Shared/Requirements.h"
#include "device.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/Error.h"
#include <cstdint>
#include <list>
#include <memory>
#include <mutex>
#include <string>
struct PluginManager;
/// Plugin adaptors should be created via `PluginAdaptorTy::create` which will
/// invoke the constructor and call `PluginAdaptorTy::init`. Eventual errors are
/// reported back to the caller, otherwise a valid and initialized adaptor is
/// returned.
struct PluginAdaptorTy {
/// Try to create a plugin adaptor from a filename.
static llvm::Expected<std::unique_ptr<PluginAdaptorTy>>
create(const std::string &Name);
/// Initialize as many devices as possible for this plugin adaptor. Devices
/// that fail to initialize are ignored.
void initDevices(PluginManager &PM);
bool isUsed() const { return DeviceOffset >= 0; }
/// Return the number of devices visible to the underlying plugin.
int32_t getNumberOfPluginDevices() const { return NumberOfPluginDevices; }
/// Return the number of devices successfully initialized and visible to the
/// user.
int32_t getNumberOfUserDevices() const { return NumberOfUserDevices; }
/// RTL index, index is the number of devices of other RTLs that were
/// registered before, i.e. the OpenMP index of the first device to be
/// registered with this RTL.
int32_t DeviceOffset = -1;
/// Name of the shared object file representing the plugin.
std::string Name;
/// Access to the shared object file representing the plugin.
std::unique_ptr<llvm::sys::DynamicLibrary> LibraryHandler;
#define PLUGIN_API_HANDLE(NAME, MANDATORY) \
using NAME##_ty = decltype(__tgt_rtl_##NAME); \
NAME##_ty *NAME = nullptr;
#include "Shared/PluginAPI.inc"
#undef PLUGIN_API_HANDLE
llvm::DenseSet<const __tgt_device_image *> UsedImages;
private:
/// Number of devices the underling plugins sees.
int32_t NumberOfPluginDevices = -1;
/// Number of devices exposed to the user. This can be less than the number of
/// devices for the plugin if some failed to initialize.
int32_t NumberOfUserDevices = 0;
/// Create a plugin adaptor for filename \p Name with a dynamic library \p DL.
PluginAdaptorTy(const std::string &Name,
std::unique_ptr<llvm::sys::DynamicLibrary> DL);
/// Initialize the plugin adaptor, this can fail in which case the adaptor is
/// useless.
llvm::Error init();
};
/// Struct for the data required to handle plugins
struct PluginManager {
/// Type of the devices container. We hand out DeviceTy& to queries which are
/// stable addresses regardless if the container changes.
using DeviceContainerTy = llvm::SmallVector<std::unique_ptr<DeviceTy>>;
/// Exclusive accessor type for the device container.
using ExclusiveDevicesAccessorTy = Accessor<DeviceContainerTy>;
PluginManager() {}
void init();
// Register a shared library with all (compatible) RTLs.
void registerLib(__tgt_bin_desc *Desc);
// Unregister a shared library from all RTLs.
void unregisterLib(__tgt_bin_desc *Desc);
void addDeviceImage(__tgt_bin_desc &TgtBinDesc, __tgt_device_image &TgtDeviceImage) {
DeviceImages.emplace_back(std::make_unique<DeviceImageTy>(TgtBinDesc, TgtDeviceImage));
}
/// Return the device presented to the user as device \p DeviceNo if it is
/// initialized and ready. Otherwise return an error explaining the problem.
llvm::Expected<DeviceTy &> getDevice(uint32_t DeviceNo);
/// Iterate over all initialized and ready devices registered with this
/// plugin.
auto devices(ExclusiveDevicesAccessorTy &DevicesAccessor) {
return llvm::make_pointee_range(*DevicesAccessor);
}
/// Iterate over all device images registered with this plugin.
auto deviceImages() { return llvm::make_pointee_range(DeviceImages); }
/// Translation table retreived from the binary
HostEntriesBeginToTransTableTy HostEntriesBeginToTransTable;
std::mutex TrlTblMtx; ///< For Translation Table
/// Host offload entries in order of image registration
llvm::SmallVector<__tgt_offload_entry *> HostEntriesBeginRegistrationOrder;
/// Map from ptrs on the host to an entry in the Translation Table
HostPtrToTableMapTy HostPtrToTableMap;
std::mutex TblMapMtx; ///< For HostPtrToTableMap
// Work around for plugins that call dlopen on shared libraries that call
// tgt_register_lib during their initialisation. Stash the pointers in a
// vector until the plugins are all initialised and then register them.
bool delayRegisterLib(__tgt_bin_desc *Desc) {
if (RTLsLoaded)
return false;
DelayedBinDesc.push_back(Desc);
return true;
}
void registerDelayedLibraries() {
// Only called by libomptarget constructor
RTLsLoaded = true;
for (auto *Desc : DelayedBinDesc)
__tgt_register_lib(Desc);
DelayedBinDesc.clear();
}
/// Return the number of usable devices.
int getNumDevices() { return getExclusiveDevicesAccessor()->size(); }
/// Return an exclusive handle to access the devices container.
ExclusiveDevicesAccessorTy getExclusiveDevicesAccessor() {
return Devices.getExclusiveAccessor();
}
int getNumUsedPlugins() const {
int NCI = 0;
for (auto &P : PluginAdaptors)
NCI += P->isUsed();
return NCI;
}
// Initialize all plugins.
void initAllPlugins();
/// Iterator range for all plugin adaptors (in use or not, but always valid).
auto pluginAdaptors() { return llvm::make_pointee_range(PluginAdaptors); }
/// Return the user provided requirements.
int64_t getRequirements() const { return Requirements.getRequirements(); }
/// Add \p Flags to the user provided requirements.
void addRequirements(int64_t Flags) { Requirements.addRequirements(Flags); }
private:
bool RTLsLoaded = false;
llvm::SmallVector<__tgt_bin_desc *> DelayedBinDesc;
// List of all plugin adaptors, in use or not.
llvm::SmallVector<std::unique_ptr<PluginAdaptorTy>> PluginAdaptors;
/// Executable images and information extracted from the input images passed
/// to the runtime.
llvm::SmallVector<std::unique_ptr<DeviceImageTy>> DeviceImages;
/// The user provided requirements.
RequirementCollection Requirements;
std::mutex RTLsMtx; ///< For RTLs
/// Devices associated with plugins, accesses to the container are exclusive.
ProtectedObj<DeviceContainerTy> Devices;
};
extern PluginManager *PM;
#endif // OMPTARGET_PLUGIN_MANAGER_H