1 //===---------------interop.cpp - Implementation of interop directive -----===//
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-exception
7 //===----------------------------------------------------------------------===//
13 omp_interop_rc_t
getPropertyErrorType(omp_interop_property_t Property
) {
16 return omp_irc_type_int
;
18 return omp_irc_type_str
;
20 return omp_irc_type_int
;
21 case omp_ipr_vendor_name
:
22 return omp_irc_type_str
;
23 case omp_ipr_device_num
:
24 return omp_irc_type_int
;
25 case omp_ipr_platform
:
26 return omp_irc_type_int
;
28 return omp_irc_type_ptr
;
29 case omp_ipr_device_context
:
30 return omp_irc_type_ptr
;
31 case omp_ipr_targetsync
:
32 return omp_irc_type_ptr
;
34 return omp_irc_no_value
;
37 void getTypeMismatch(omp_interop_property_t Property
, int *Err
) {
39 *Err
= getPropertyErrorType(Property
);
42 const char *getVendorIdToStr(const omp_foreign_runtime_ids_t VendorId
) {
47 return ("cuda_driver");
55 return ("level_zero");
60 template <typename PropertyTy
>
61 PropertyTy
getProperty(omp_interop_val_t
&InteropVal
,
62 omp_interop_property_t Property
, int *Err
);
65 intptr_t getProperty
<intptr_t>(omp_interop_val_t
&InteropVal
,
66 omp_interop_property_t Property
, int *Err
) {
69 return InteropVal
.backend_type_id
;
71 return InteropVal
.vendor_id
;
72 case omp_ipr_device_num
:
73 return InteropVal
.device_id
;
76 getTypeMismatch(Property
, Err
);
81 const char *getProperty
<const char *>(omp_interop_val_t
&InteropVal
,
82 omp_interop_property_t Property
,
86 return InteropVal
.interop_type
== kmp_interop_type_tasksync
89 case omp_ipr_vendor_name
:
90 return getVendorIdToStr(InteropVal
.vendor_id
);
92 getTypeMismatch(Property
, Err
);
98 void *getProperty
<void *>(omp_interop_val_t
&InteropVal
,
99 omp_interop_property_t Property
, int *Err
) {
102 if (InteropVal
.device_info
.Device
)
103 return InteropVal
.device_info
.Device
;
104 *Err
= omp_irc_no_value
;
105 return const_cast<char *>(InteropVal
.err_str
);
106 case omp_ipr_device_context
:
107 return InteropVal
.device_info
.Context
;
108 case omp_ipr_targetsync
:
109 return InteropVal
.async_info
->Queue
;
112 getTypeMismatch(Property
, Err
);
116 bool getPropertyCheck(omp_interop_val_t
**InteropPtr
,
117 omp_interop_property_t Property
, int *Err
) {
119 *Err
= omp_irc_success
;
122 *Err
= omp_irc_empty
;
125 if (Property
>= 0 || Property
< omp_ipr_first
) {
127 *Err
= omp_irc_out_of_range
;
130 if (Property
== omp_ipr_targetsync
&&
131 (*InteropPtr
)->interop_type
!= kmp_interop_type_tasksync
) {
133 *Err
= omp_irc_other
;
136 if ((Property
== omp_ipr_device
|| Property
== omp_ipr_device_context
) &&
137 (*InteropPtr
)->interop_type
== kmp_interop_type_tasksync
) {
139 *Err
= omp_irc_other
;
147 #define __OMP_GET_INTEROP_TY(RETURN_TYPE, SUFFIX) \
148 RETURN_TYPE omp_get_interop_##SUFFIX(const omp_interop_t interop, \
149 omp_interop_property_t property_id, \
151 omp_interop_val_t *interop_val = (omp_interop_val_t *)interop; \
152 assert((interop_val)->interop_type == kmp_interop_type_tasksync); \
153 if (!getPropertyCheck(&interop_val, property_id, err)) { \
154 return (RETURN_TYPE)(0); \
156 return getProperty<RETURN_TYPE>(*interop_val, property_id, err); \
158 __OMP_GET_INTEROP_TY(intptr_t, int)
159 __OMP_GET_INTEROP_TY(void *, ptr
)
160 __OMP_GET_INTEROP_TY(const char *, str
)
161 #undef __OMP_GET_INTEROP_TY
163 #define __OMP_GET_INTEROP_TY3(RETURN_TYPE, SUFFIX) \
164 RETURN_TYPE omp_get_interop_##SUFFIX(const omp_interop_t interop, \
165 omp_interop_property_t property_id) { \
167 omp_interop_val_t *interop_val = (omp_interop_val_t *)interop; \
168 if (!getPropertyCheck(&interop_val, property_id, &err)) { \
169 return (RETURN_TYPE)(0); \
172 return getProperty<RETURN_TYPE>(*interop_val, property_id, &err); \
174 __OMP_GET_INTEROP_TY3(const char *, name
)
175 __OMP_GET_INTEROP_TY3(const char *, type_desc
)
176 __OMP_GET_INTEROP_TY3(const char *, rc_desc
)
177 #undef __OMP_GET_INTEROP_TY3
179 typedef int64_t kmp_int64
;
184 void __tgt_interop_init(ident_t
*LocRef
, kmp_int32 Gtid
,
185 omp_interop_val_t
*&InteropPtr
,
186 kmp_interop_type_t InteropType
, kmp_int32 DeviceId
,
187 kmp_int32 Ndeps
, kmp_depend_info_t
*DepList
,
188 kmp_int32 HaveNowait
) {
189 kmp_int32 NdepsNoalias
= 0;
190 kmp_depend_info_t
*NoaliasDepList
= NULL
;
191 assert(InteropType
!= kmp_interop_type_unknown
&&
192 "Cannot initialize with unknown interop_type!");
193 if (DeviceId
== -1) {
194 DeviceId
= omp_get_default_device();
197 if (InteropType
== kmp_interop_type_tasksync
) {
198 __kmpc_omp_wait_deps(LocRef
, Gtid
, Ndeps
, DepList
, NdepsNoalias
,
202 InteropPtr
= new omp_interop_val_t(DeviceId
, InteropType
);
203 if (!deviceIsReady(DeviceId
)) {
204 InteropPtr
->err_str
= "Device not ready!";
208 DeviceTy
&Device
= *PM
->Devices
[DeviceId
];
209 if (!Device
.RTL
|| !Device
.RTL
->init_device_info
||
210 Device
.RTL
->init_device_info(DeviceId
, &(InteropPtr
)->device_info
,
211 &(InteropPtr
)->err_str
)) {
213 InteropPtr
= omp_interop_none
;
215 if (InteropType
== kmp_interop_type_tasksync
) {
216 if (!Device
.RTL
|| !Device
.RTL
->init_async_info
||
217 Device
.RTL
->init_async_info(DeviceId
, &(InteropPtr
)->async_info
)) {
219 InteropPtr
= omp_interop_none
;
224 void __tgt_interop_use(ident_t
*LocRef
, kmp_int32 Gtid
,
225 omp_interop_val_t
*&InteropPtr
, kmp_int32 DeviceId
,
226 kmp_int32 Ndeps
, kmp_depend_info_t
*DepList
,
227 kmp_int32 HaveNowait
) {
228 kmp_int32 NdepsNoalias
= 0;
229 kmp_depend_info_t
*NoaliasDepList
= NULL
;
230 assert(InteropPtr
&& "Cannot use nullptr!");
231 omp_interop_val_t
*InteropVal
= InteropPtr
;
232 if (DeviceId
== -1) {
233 DeviceId
= omp_get_default_device();
235 assert(InteropVal
!= omp_interop_none
&&
236 "Cannot use uninitialized interop_ptr!");
237 assert((DeviceId
== -1 || InteropVal
->device_id
== DeviceId
) &&
238 "Inconsistent device-id usage!");
240 if (!deviceIsReady(DeviceId
)) {
241 InteropPtr
->err_str
= "Device not ready!";
245 if (InteropVal
->interop_type
== kmp_interop_type_tasksync
) {
246 __kmpc_omp_wait_deps(LocRef
, Gtid
, Ndeps
, DepList
, NdepsNoalias
,
249 // TODO Flush the queue associated with the interop through the plugin
252 void __tgt_interop_destroy(ident_t
*LocRef
, kmp_int32 Gtid
,
253 omp_interop_val_t
*&InteropPtr
, kmp_int32 DeviceId
,
254 kmp_int32 Ndeps
, kmp_depend_info_t
*DepList
,
255 kmp_int32 HaveNowait
) {
256 kmp_int32 NdepsNoalias
= 0;
257 kmp_depend_info_t
*NoaliasDepList
= NULL
;
258 assert(InteropPtr
&& "Cannot use nullptr!");
259 omp_interop_val_t
*InteropVal
= InteropPtr
;
260 if (DeviceId
== -1) {
261 DeviceId
= omp_get_default_device();
264 if (InteropVal
== omp_interop_none
)
267 assert((DeviceId
== -1 || InteropVal
->device_id
== DeviceId
) &&
268 "Inconsistent device-id usage!");
269 if (!deviceIsReady(DeviceId
)) {
270 InteropPtr
->err_str
= "Device not ready!";
274 if (InteropVal
->interop_type
== kmp_interop_type_tasksync
) {
275 __kmpc_omp_wait_deps(LocRef
, Gtid
, Ndeps
, DepList
, NdepsNoalias
,
278 // TODO Flush the queue associated with the interop through the plugin
279 // TODO Signal out dependences
282 InteropPtr
= omp_interop_none
;