blob: 6a91e245453c8682f426c2b616fe445ce9ac0e75 [file] [log] [blame]
//===-- 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 "Shared/APITypes.h"
#include "device.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DynamicLibrary.h"
#include <list>
#include <mutex>
struct PluginAdaptorTy {
typedef int32_t(init_plugin_ty)();
typedef int32_t(is_valid_binary_ty)(void *);
typedef int32_t(is_valid_binary_info_ty)(void *, void *);
typedef int32_t(is_data_exchangable_ty)(int32_t, int32_t);
typedef int32_t(number_of_devices_ty)();
typedef int32_t(init_device_ty)(int32_t);
typedef __tgt_target_table *(load_binary_ty)(int32_t, void *);
typedef void *(data_alloc_ty)(int32_t, int64_t, void *, int32_t);
typedef int32_t(data_submit_ty)(int32_t, void *, void *, int64_t);
typedef int32_t(data_submit_async_ty)(int32_t, void *, void *, int64_t,
__tgt_async_info *);
typedef int32_t(data_retrieve_ty)(int32_t, void *, void *, int64_t);
typedef int32_t(data_retrieve_async_ty)(int32_t, void *, void *, int64_t,
__tgt_async_info *);
typedef int32_t(data_exchange_ty)(int32_t, void *, int32_t, void *, int64_t);
typedef int32_t(data_exchange_async_ty)(int32_t, void *, int32_t, void *,
int64_t, __tgt_async_info *);
typedef int32_t(data_delete_ty)(int32_t, void *, int32_t);
typedef int32_t(launch_kernel_ty)(int32_t, void *, void **, ptrdiff_t *,
const KernelArgsTy *, __tgt_async_info *);
typedef int64_t(init_requires_ty)(int64_t);
typedef int32_t(synchronize_ty)(int32_t, __tgt_async_info *);
typedef int32_t(query_async_ty)(int32_t, __tgt_async_info *);
typedef int32_t(supports_empty_images_ty)();
typedef void(print_device_info_ty)(int32_t);
typedef void(set_info_flag_ty)(uint32_t);
typedef int32_t(create_event_ty)(int32_t, void **);
typedef int32_t(record_event_ty)(int32_t, void *, __tgt_async_info *);
typedef int32_t(wait_event_ty)(int32_t, void *, __tgt_async_info *);
typedef int32_t(sync_event_ty)(int32_t, void *);
typedef int32_t(destroy_event_ty)(int32_t, void *);
typedef int32_t(release_async_info_ty)(int32_t, __tgt_async_info *);
typedef int32_t(init_async_info_ty)(int32_t, __tgt_async_info **);
typedef int64_t(init_device_into_ty)(int64_t, __tgt_device_info *,
const char **);
typedef int32_t(data_lock_ty)(int32_t, void *, int64_t, void **);
typedef int32_t(data_unlock_ty)(int32_t, void *);
typedef int32_t(data_notify_mapped_ty)(int32_t, void *, int64_t);
typedef int32_t(data_notify_unmapped_ty)(int32_t, void *);
typedef int32_t(set_device_offset_ty)(int32_t);
typedef int32_t(activate_record_replay_ty)(int32_t, uint64_t, void *, bool,
bool, uint64_t &);
int32_t Idx = -1; // 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 NumberOfDevices = -1; // Number of devices this RTL deals with.
std::unique_ptr<llvm::sys::DynamicLibrary> LibraryHandler;
#ifdef OMPTARGET_DEBUG
std::string RTLName;
#endif
// Functions implemented in the RTL.
init_plugin_ty *init_plugin = nullptr;
is_valid_binary_ty *is_valid_binary = nullptr;
is_valid_binary_info_ty *is_valid_binary_info = nullptr;
is_data_exchangable_ty *is_data_exchangable = nullptr;
number_of_devices_ty *number_of_devices = nullptr;
init_device_ty *init_device = nullptr;
load_binary_ty *load_binary = nullptr;
data_alloc_ty *data_alloc = nullptr;
data_submit_ty *data_submit = nullptr;
data_submit_async_ty *data_submit_async = nullptr;
data_retrieve_ty *data_retrieve = nullptr;
data_retrieve_async_ty *data_retrieve_async = nullptr;
data_exchange_ty *data_exchange = nullptr;
data_exchange_async_ty *data_exchange_async = nullptr;
data_delete_ty *data_delete = nullptr;
launch_kernel_ty *launch_kernel = nullptr;
init_requires_ty *init_requires = nullptr;
synchronize_ty *synchronize = nullptr;
query_async_ty *query_async = nullptr;
supports_empty_images_ty *supports_empty_images = nullptr;
set_info_flag_ty *set_info_flag = nullptr;
print_device_info_ty *print_device_info = nullptr;
create_event_ty *create_event = nullptr;
record_event_ty *record_event = nullptr;
wait_event_ty *wait_event = nullptr;
sync_event_ty *sync_event = nullptr;
destroy_event_ty *destroy_event = nullptr;
init_async_info_ty *init_async_info = nullptr;
init_device_into_ty *init_device_info = nullptr;
release_async_info_ty *release_async_info = nullptr;
data_lock_ty *data_lock = nullptr;
data_unlock_ty *data_unlock = nullptr;
data_notify_mapped_ty *data_notify_mapped = nullptr;
data_notify_unmapped_ty *data_notify_unmapped = nullptr;
set_device_offset_ty *set_device_offset = nullptr;
activate_record_replay_ty *activate_record_replay = nullptr;
// Are there images associated with this RTL.
bool IsUsed = false;
llvm::DenseSet<const __tgt_device_image *> UsedImages;
// Mutex for thread-safety when calling RTL interface functions.
// It is easier to enforce thread-safety at the libomptarget level,
// so that developers of new RTLs do not have to worry about it.
std::mutex Mtx;
};
/// RTLs identified in the system.
struct PluginAdaptorManagerTy {
// List of the detected runtime libraries.
std::list<PluginAdaptorTy> AllRTLs;
// Array of pointers to the detected runtime libraries that have compatible
// binaries.
llvm::SmallVector<PluginAdaptorTy *> UsedRTLs;
int64_t RequiresFlags = OMP_REQ_UNDEFINED;
explicit PluginAdaptorManagerTy() = default;
// Register the clauses of the requires directive.
void registerRequires(int64_t Flags);
// Initialize RTL if it has not been initialized
void initRTLonce(PluginAdaptorTy &RTL);
// Initialize all RTLs
void initAllRTLs();
// 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);
// not thread-safe, called from global constructor (i.e. once)
void loadRTLs();
private:
static bool attemptLoadRTL(const std::string &RTLName, PluginAdaptorTy &RTL);
};
/// Struct for the data required to handle plugins
struct PluginManager {
PluginManager(bool UseEventsForAtomicTransfers)
: UseEventsForAtomicTransfers(UseEventsForAtomicTransfers) {}
/// RTLs identified on the host
PluginAdaptorManagerTy RTLs;
/// Executable images and information extracted from the input images passed
/// to the runtime.
std::list<std::pair<__tgt_device_image, __tgt_image_info>> Images;
/// Devices associated with RTLs
llvm::SmallVector<std::unique_ptr<DeviceTy>> Devices;
std::mutex RTLsMtx; ///< For RTLs and Devices
/// 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
// Store target policy (disabled, mandatory, default)
kmp_target_offload_kind_t TargetOffloadPolicy = tgt_default;
std::mutex TargetOffloadMtx; ///< For TargetOffloadPolicy
/// Flag to indicate if we use events to ensure the atomicity of
/// map clauses or not. Can be modified with an environment variable.
const bool UseEventsForAtomicTransfers;
// 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();
}
private:
bool RTLsLoaded = false;
llvm::SmallVector<__tgt_bin_desc *> DelayedBinDesc;
};
extern PluginManager *PM;
#endif // OMPTARGET_PLUGIN_MANAGER_H