aboutsummaryrefslogtreecommitdiff
path: root/offload/include/OpenMP/InteropAPI.h
diff options
context:
space:
mode:
Diffstat (limited to 'offload/include/OpenMP/InteropAPI.h')
-rw-r--r--offload/include/OpenMP/InteropAPI.h150
1 files changed, 145 insertions, 5 deletions
diff --git a/offload/include/OpenMP/InteropAPI.h b/offload/include/OpenMP/InteropAPI.h
index 71c7876..53ac4be 100644
--- a/offload/include/OpenMP/InteropAPI.h
+++ b/offload/include/OpenMP/InteropAPI.h
@@ -13,17 +13,69 @@
#include "omp.h"
+#include "PerThreadTable.h"
#include "omptarget.h"
extern "C" {
typedef enum kmp_interop_type_t {
kmp_interop_type_unknown = -1,
- kmp_interop_type_platform,
- kmp_interop_type_device,
- kmp_interop_type_tasksync,
+ kmp_interop_type_target,
+ kmp_interop_type_targetsync,
} kmp_interop_type_t;
+struct interop_attrs_t {
+ bool inorder : 1;
+ int reserved : 31;
+
+ /// Check if the supported attributes are compatible with the current
+ /// attributes. Only if an attribute is supported can the value be true,
+ /// otherwise it needs to be false
+ bool checkSupportedOnly(interop_attrs_t supported) const {
+ return supported.inorder || (!supported.inorder && !inorder);
+ }
+};
+
+struct interop_spec_t {
+ int32_t fr_id;
+ interop_attrs_t attrs; // Common attributes
+ int64_t impl_attrs; // Implementation specific attributes (recognized by each
+ // plugin)
+};
+
+struct interop_flags_t {
+ bool implicit : 1; // dispatch (true) or interop (false)
+ bool nowait : 1; // has nowait flag
+ int reserved : 30;
+};
+
+struct interop_ctx_t {
+ uint32_t version; // version of the interface (current is 0)
+ interop_flags_t flags;
+ int gtid;
+};
+
+struct dep_pack_t {
+ int32_t ndeps;
+ int32_t ndeps_noalias;
+ kmp_depend_info_t *deplist;
+ kmp_depend_info_t *noalias_deplist;
+};
+
+struct omp_interop_val_t;
+
+typedef void ompx_interop_cb_t(omp_interop_val_t *interop, void *data);
+
+struct omp_interop_cb_instance_t {
+ ompx_interop_cb_t *cb;
+ void *data;
+
+ omp_interop_cb_instance_t(ompx_interop_cb_t *cb, void *data)
+ : cb(cb), data(data) {}
+
+ void operator()(omp_interop_val_t *interop) { cb(interop, data); }
+};
+
/// The interop value type, aka. the interop object.
typedef struct omp_interop_val_t {
/// Device and interop-type are determined at construction time and fix.
@@ -34,10 +86,98 @@ typedef struct omp_interop_val_t {
__tgt_device_info device_info;
const kmp_interop_type_t interop_type;
const intptr_t device_id;
- const omp_foreign_runtime_ids_t vendor_id = cuda;
- const intptr_t backend_type_id = omp_interop_backend_type_cuda_1;
+ omp_vendor_id_t vendor_id = omp_vendor_llvm;
+ tgt_foreign_runtime_id_t fr_id = tgt_fr_none;
+ interop_attrs_t attrs{false, 0}; // Common prefer specification attributes
+ int64_t impl_attrs = 0; // Implementation prefer specification attributes
+
+ // Constants
+ static constexpr int no_owner = -1; // This interop has no current owner
+
+ void *rtl_property = nullptr; // Plugin dependent information
+ // For implicitly created Interop objects (e.g., from a dispatch construct)
+ // who owns the object
+ int owner_gtid = no_owner;
+ // Marks whether the object was requested since the last time it was synced
+ bool clean = true;
+
+ typedef llvm::SmallVector<omp_interop_cb_instance_t> callback_list_t;
+
+ callback_list_t completion_cbs;
+
+ void reset() {
+ owner_gtid = no_owner;
+ markClean();
+ clearCompletionCbs();
+ }
+
+ llvm::Expected<DeviceTy &> getDevice() const;
+
+ bool hasOwner() const { return owner_gtid != no_owner; }
+
+ void setOwner(int gtid) { owner_gtid = gtid; }
+ bool isOwnedBy(int gtid) { return owner_gtid == gtid; }
+ bool isCompatibleWith(int32_t InteropType, const interop_spec_t &Spec);
+ bool isCompatibleWith(int32_t InteropType, const interop_spec_t &Spec,
+ int64_t DeviceNum, int gtid);
+ void markClean() { clean = true; }
+ void markDirty() { clean = false; }
+ bool isClean() const { return clean; }
+
+ int32_t flush(DeviceTy &Device);
+ int32_t sync_barrier(DeviceTy &Device);
+ int32_t async_barrier(DeviceTy &Device);
+ int32_t release(DeviceTy &Device);
+
+ void addCompletionCb(ompx_interop_cb_t *cb, void *data) {
+ completion_cbs.push_back(omp_interop_cb_instance_t(cb, data));
+ }
+
+ int numCompletionCbs() const { return completion_cbs.size(); }
+ void clearCompletionCbs() { completion_cbs.clear(); }
+
+ void runCompletionCbs() {
+ for (auto &cbInstance : completion_cbs)
+ cbInstance(this);
+ clearCompletionCbs();
+ }
} omp_interop_val_t;
} // extern "C"
+struct InteropTableEntry {
+ using ContainerTy = typename std::vector<omp_interop_val_t *>;
+ using iterator = typename ContainerTy::iterator;
+
+ ContainerTy Interops;
+
+ static constexpr int reservedEntriesPerThread =
+ 20; // reserve some entries to avoid reallocation
+
+ void add(omp_interop_val_t *obj) {
+ if (Interops.capacity() == 0)
+ Interops.reserve(reservedEntriesPerThread);
+ Interops.push_back(obj);
+ }
+
+ template <class ClearFuncTy> void clear(ClearFuncTy f) {
+ for (auto &Obj : Interops) {
+ f(Obj);
+ }
+ }
+
+ /// vector interface
+ int size() const { return Interops.size(); }
+ iterator begin() { return Interops.begin(); }
+ iterator end() { return Interops.end(); }
+ iterator erase(iterator it) { return Interops.erase(it); }
+};
+
+struct InteropTblTy
+ : public PerThreadTable<InteropTableEntry, omp_interop_val_t *> {
+ void clear();
+};
+
+void syncImplicitInterops(int gtid, void *event);
+
#endif // OMPTARGET_OPENMP_INTEROP_API_H