1313
1414#include " omp.h"
1515
16+ #include " PerThreadTable.h"
1617#include " omptarget.h"
1718
1819extern " C" {
1920
2021typedef enum kmp_interop_type_t {
2122 kmp_interop_type_unknown = -1 ,
22- kmp_interop_type_platform ,
23- kmp_interop_type_device ,
24- kmp_interop_type_tasksync ,
23+ kmp_interop_type_target,
24+ kmp_interop_type_targetsync,
2525} kmp_interop_type_t ;
2626
27+ struct interop_attrs_t {
28+ bool inorder : 1 ;
29+ int reserved : 31 ;
30+
31+ // / Check if the supported attributes are compatible with the current
32+ // / attributes. Only if an attribute is supported can the value be true,
33+ // / otherwise it needs to be false
34+ bool checkSupportedOnly (interop_attrs_t supported) const {
35+ return supported.inorder || (!supported.inorder && !inorder);
36+ }
37+ };
38+
39+ struct interop_spec_t {
40+ int32_t fr_id;
41+ interop_attrs_t attrs; // Common attributes
42+ int64_t impl_attrs; // Implementation specific attributes (recognized by each
43+ // plugin)
44+ };
45+
46+ struct interop_flags_t {
47+ bool implicit : 1 ; // dispatch (true) or interop (false)
48+ bool nowait : 1 ; // has nowait flag
49+ int reserved : 30 ;
50+ };
51+
52+ struct interop_ctx_t {
53+ uint32_t version; // version of the interface (current is 0)
54+ interop_flags_t flags;
55+ int gtid;
56+ };
57+
58+ struct 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+
65+ struct omp_interop_val_t ;
66+
67+ typedef void ompx_interop_cb_t (omp_interop_val_t *interop, void *data);
68+
69+ struct 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+
2779// / The interop value type, aka. the interop object.
2880typedef struct omp_interop_val_t {
2981 // / Device and interop-type are determined at construction time and fix.
@@ -34,10 +86,98 @@ typedef struct omp_interop_val_t {
3486 __tgt_device_info device_info;
3587 const kmp_interop_type_t interop_type;
3688 const intptr_t device_id;
37- const omp_foreign_runtime_ids_t vendor_id = cuda ;
38- const intptr_t backend_type_id = omp_interop_backend_type_cuda_1 ;
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 attributes
92+ int64_t impl_attrs = 0 ; // Implementation prefer specification attributes
93+
94+ // Constants
95+ static constexpr int no_owner = -1 ; // This interop has no current owner
96+
97+ void *rtl_property = nullptr ; // Plugin dependent information
98+ // For implicitly created Interop objects (e.g., from a dispatch construct)
99+ // who owns the object
100+ int owner_gtid = no_owner;
101+ // Marks whether the object was requested since the last time it was synced
102+ 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+ }
39144} omp_interop_val_t ;
40145
41146} // extern "C"
42147
148+ struct 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 reallocation
156+
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+ template <class ClearFuncTy > void clear (ClearFuncTy f) {
164+ for (auto &Obj : Interops) {
165+ f (Obj);
166+ }
167+ }
168+
169+ // / vector interface
170+ int size () const { return Interops.size (); }
171+ iterator begin () { return Interops.begin (); }
172+ iterator end () { return Interops.end (); }
173+ iterator erase (iterator it) { return Interops.erase (it); }
174+ };
175+
176+ struct InteropTblTy
177+ : public PerThreadTable<InteropTableEntry, omp_interop_val_t *> {
178+ void clear ();
179+ };
180+
181+ void syncImplicitInterops (int gtid, void *event);
182+
43183#endif // OMPTARGET_OPENMP_INTEROP_API_H
0 commit comments