178 lines · c
1//===-- OpenMP/InteropAPI.h - OpenMP interoperability types and API - C++ -===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//===----------------------------------------------------------------------===//10 11#ifndef OMPTARGET_OPENMP_INTEROP_API_H12#define OMPTARGET_OPENMP_INTEROP_API_H13 14#include "omp.h"15 16#include "PerThreadTable.h"17#include "omptarget.h"18 19extern "C" {20 21typedef enum kmp_interop_type_t {22 kmp_interop_type_unknown = -1,23 kmp_interop_type_target,24 kmp_interop_type_targetsync,25} kmp_interop_type_t;26 27struct interop_attrs_t {28 uint32_t inorder : 1;29 uint32_t reserved : 31;30 31 /// Check if the supported attributes are compatible with the current32 /// attributes. Only if an attribute is supported can the value be true,33 /// otherwise it needs to be false34 bool checkSupportedOnly(interop_attrs_t supported) const {35 return supported.inorder || (!supported.inorder && !inorder);36 }37};38 39struct interop_spec_t {40 int32_t fr_id;41 interop_attrs_t attrs; // Common attributes42 int64_t impl_attrs; // Implementation specific attributes (recognized by each43 // plugin)44};45 46struct interop_flags_t {47 uint32_t implicit : 1; // dispatch (true) or interop (false)48 uint32_t nowait : 1; // has nowait flag49 uint32_t reserved : 30;50};51 52struct interop_ctx_t {53 uint32_t version; // version of the interface (current is 0)54 interop_flags_t flags;55 int32_t gtid;56};57 58struct dep_pack_t {59 int32_t ndeps;60 int32_t ndeps_noalias;61 kmp_depend_info_t *deplist;62 kmp_depend_info_t *noalias_deplist;63};64 65struct omp_interop_val_t;66 67typedef void ompx_interop_cb_t(omp_interop_val_t *interop, void *data);68 69struct omp_interop_cb_instance_t {70 ompx_interop_cb_t *cb;71 void *data;72 73 omp_interop_cb_instance_t(ompx_interop_cb_t *cb, void *data)74 : cb(cb), data(data) {}75 76 void operator()(omp_interop_val_t *interop) { cb(interop, data); }77};78 79/// The interop value type, aka. the interop object.80typedef struct omp_interop_val_t {81 /// Device and interop-type are determined at construction time and fix.82 omp_interop_val_t(intptr_t device_id, kmp_interop_type_t interop_type)83 : interop_type(interop_type), device_id(device_id) {}84 const char *err_str = nullptr;85 __tgt_async_info *async_info = nullptr;86 __tgt_device_info device_info;87 const kmp_interop_type_t interop_type;88 const intptr_t device_id;89 omp_vendor_id_t vendor_id = omp_vendor_llvm;90 tgt_foreign_runtime_id_t fr_id = tgt_fr_none;91 interop_attrs_t attrs{false, 0}; // Common prefer specification attributes92 int64_t impl_attrs = 0; // Implementation prefer specification attributes93 94 // Constants95 static constexpr int no_owner = -1; // This interop has no current owner96 97 void *rtl_property = nullptr; // Plugin dependent information98 // For implicitly created Interop objects (e.g., from a dispatch construct)99 // who owns the object100 int owner_gtid = no_owner;101 // Marks whether the object was requested since the last time it was synced102 bool clean = true;103 104 typedef llvm::SmallVector<omp_interop_cb_instance_t> callback_list_t;105 106 callback_list_t completion_cbs;107 108 void reset() {109 owner_gtid = no_owner;110 markClean();111 clearCompletionCbs();112 }113 114 llvm::Expected<DeviceTy &> getDevice() const;115 116 bool hasOwner() const { return owner_gtid != no_owner; }117 118 void setOwner(int gtid) { owner_gtid = gtid; }119 bool isOwnedBy(int gtid) { return owner_gtid == gtid; }120 bool isCompatibleWith(int32_t InteropType, const interop_spec_t &Spec);121 bool isCompatibleWith(int32_t InteropType, const interop_spec_t &Spec,122 int64_t DeviceNum, int gtid);123 void markClean() { clean = true; }124 void markDirty() { clean = false; }125 bool isClean() const { return clean; }126 127 int32_t flush(DeviceTy &Device);128 int32_t sync_barrier(DeviceTy &Device);129 int32_t async_barrier(DeviceTy &Device);130 int32_t release(DeviceTy &Device);131 132 void addCompletionCb(ompx_interop_cb_t *cb, void *data) {133 completion_cbs.push_back(omp_interop_cb_instance_t(cb, data));134 }135 136 int numCompletionCbs() const { return completion_cbs.size(); }137 void clearCompletionCbs() { completion_cbs.clear(); }138 139 void runCompletionCbs() {140 for (auto &cbInstance : completion_cbs)141 cbInstance(this);142 clearCompletionCbs();143 }144} omp_interop_val_t;145 146} // extern "C"147 148struct InteropTableEntry {149 using ContainerTy = typename std::vector<omp_interop_val_t *>;150 using iterator = typename ContainerTy::iterator;151 152 ContainerTy Interops;153 154 static constexpr int reservedEntriesPerThread =155 20; // reserve some entries to avoid reallocation156 157 void add(omp_interop_val_t *obj) {158 if (Interops.capacity() == 0)159 Interops.reserve(reservedEntriesPerThread);160 Interops.push_back(obj);161 }162 163 /// vector interface164 int size() const { return Interops.size(); }165 iterator begin() { return Interops.begin(); }166 iterator end() { return Interops.end(); }167 void clear() { Interops.clear(); }168};169 170struct InteropTblTy171 : public PerThreadTable<InteropTableEntry, omp_interop_val_t *> {172 void clear();173};174 175void syncImplicitInterops(int gtid, void *event);176 177#endif // OMPTARGET_OPENMP_INTEROP_API_H178