1a3b147abSJonas Hahnfeld //===----------- api.cpp - Target independent OpenMP target RTL -----------===//
2a3b147abSJonas Hahnfeld //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a3b147abSJonas Hahnfeld //
7a3b147abSJonas Hahnfeld //===----------------------------------------------------------------------===//
8a3b147abSJonas Hahnfeld //
9a3b147abSJonas Hahnfeld // Implementation of OpenMP API interface functions.
10a3b147abSJonas Hahnfeld //
11a3b147abSJonas Hahnfeld //===----------------------------------------------------------------------===//
12a3b147abSJonas Hahnfeld 
13a3b147abSJonas Hahnfeld #include "device.h"
14758b8499SJohannes Doerfert #include "omptarget.h"
15a3b147abSJonas Hahnfeld #include "private.h"
16a3b147abSJonas Hahnfeld #include "rtl.h"
17a3b147abSJonas Hahnfeld 
18a3b147abSJonas Hahnfeld #include <climits>
199f49676aSDimitry Andric #include <cstdlib>
209cd1e222SJohannes Doerfert #include <cstring>
21a3b147abSJonas Hahnfeld 
omp_get_num_devices(void)22a3b147abSJonas Hahnfeld EXTERN int omp_get_num_devices(void) {
23e007b328SGiorgis Georgakoudis   TIMESCOPE();
24a95b25b2SAtmn Patel   PM->RTLsMtx.lock();
25a95b25b2SAtmn Patel   size_t DevicesSize = PM->Devices.size();
26a95b25b2SAtmn Patel   PM->RTLsMtx.unlock();
27a3b147abSJonas Hahnfeld 
28a95b25b2SAtmn Patel   DP("Call to omp_get_num_devices returning %zd\n", DevicesSize);
29a3b147abSJonas Hahnfeld 
30a95b25b2SAtmn Patel   return DevicesSize;
31a3b147abSJonas Hahnfeld }
32a3b147abSJonas Hahnfeld 
omp_get_device_num(void)33616dd9aeSJose M Monsalve Diaz EXTERN int omp_get_device_num(void) {
34616dd9aeSJose M Monsalve Diaz   TIMESCOPE();
35616dd9aeSJose M Monsalve Diaz   int HostDevice = omp_get_initial_device();
36616dd9aeSJose M Monsalve Diaz 
37616dd9aeSJose M Monsalve Diaz   DP("Call to omp_get_device_num returning %d\n", HostDevice);
38616dd9aeSJose M Monsalve Diaz 
39616dd9aeSJose M Monsalve Diaz   return HostDevice;
40616dd9aeSJose M Monsalve Diaz }
41616dd9aeSJose M Monsalve Diaz 
omp_get_initial_device(void)42a3b147abSJonas Hahnfeld EXTERN int omp_get_initial_device(void) {
43e007b328SGiorgis Georgakoudis   TIMESCOPE();
44*d27d0a67SJoseph Huber   int HostDevice = omp_get_num_devices();
45*d27d0a67SJoseph Huber   DP("Call to omp_get_initial_device returning %d\n", HostDevice);
46*d27d0a67SJoseph Huber   return HostDevice;
47a3b147abSJonas Hahnfeld }
48a3b147abSJonas Hahnfeld 
omp_target_alloc(size_t Size,int DeviceNum)49*d27d0a67SJoseph Huber EXTERN void *omp_target_alloc(size_t Size, int DeviceNum) {
50*d27d0a67SJoseph Huber   return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_DEFAULT, __func__);
51a3b147abSJonas Hahnfeld }
52a3b147abSJonas Hahnfeld 
llvm_omp_target_alloc_device(size_t Size,int DeviceNum)53*d27d0a67SJoseph Huber EXTERN void *llvm_omp_target_alloc_device(size_t Size, int DeviceNum) {
54*d27d0a67SJoseph Huber   return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_DEVICE, __func__);
55a3b147abSJonas Hahnfeld }
56a3b147abSJonas Hahnfeld 
llvm_omp_target_alloc_host(size_t Size,int DeviceNum)57*d27d0a67SJoseph Huber EXTERN void *llvm_omp_target_alloc_host(size_t Size, int DeviceNum) {
58*d27d0a67SJoseph Huber   return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_HOST, __func__);
59a3b147abSJonas Hahnfeld }
60a3b147abSJonas Hahnfeld 
llvm_omp_target_alloc_shared(size_t Size,int DeviceNum)61*d27d0a67SJoseph Huber EXTERN void *llvm_omp_target_alloc_shared(size_t Size, int DeviceNum) {
62*d27d0a67SJoseph Huber   return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_SHARED, __func__);
63a3b147abSJonas Hahnfeld }
64a3b147abSJonas Hahnfeld 
llvm_omp_target_dynamic_shared_alloc()65a3f423cfSJoseph Huber EXTERN void *llvm_omp_target_dynamic_shared_alloc() { return nullptr; }
llvm_omp_get_dynamic_shared()66208f9005SJoseph Huber EXTERN void *llvm_omp_get_dynamic_shared() { return nullptr; }
67208f9005SJoseph Huber 
omp_target_free(void * DevicePtr,int DeviceNum)68*d27d0a67SJoseph Huber EXTERN void omp_target_free(void *DevicePtr, int DeviceNum) {
69e007b328SGiorgis Georgakoudis   TIMESCOPE();
70a3b147abSJonas Hahnfeld   DP("Call to omp_target_free for device %d and address " DPxMOD "\n",
71*d27d0a67SJoseph Huber      DeviceNum, DPxPTR(DevicePtr));
72a3b147abSJonas Hahnfeld 
73*d27d0a67SJoseph Huber   if (!DevicePtr) {
74a3b147abSJonas Hahnfeld     DP("Call to omp_target_free with NULL ptr\n");
75a3b147abSJonas Hahnfeld     return;
76a3b147abSJonas Hahnfeld   }
77a3b147abSJonas Hahnfeld 
78*d27d0a67SJoseph Huber   if (DeviceNum == omp_get_initial_device()) {
79*d27d0a67SJoseph Huber     free(DevicePtr);
80a3b147abSJonas Hahnfeld     DP("omp_target_free deallocated host ptr\n");
81a3b147abSJonas Hahnfeld     return;
82a3b147abSJonas Hahnfeld   }
83a3b147abSJonas Hahnfeld 
84*d27d0a67SJoseph Huber   if (!deviceIsReady(DeviceNum)) {
85a3b147abSJonas Hahnfeld     DP("omp_target_free returns, nothing to do\n");
86a3b147abSJonas Hahnfeld     return;
87a3b147abSJonas Hahnfeld   }
88a3b147abSJonas Hahnfeld 
89*d27d0a67SJoseph Huber   PM->Devices[DeviceNum]->deleteData(DevicePtr);
90a3b147abSJonas Hahnfeld   DP("omp_target_free deallocated device ptr\n");
91a3b147abSJonas Hahnfeld }
92a3b147abSJonas Hahnfeld 
omp_target_is_present(const void * Ptr,int DeviceNum)93*d27d0a67SJoseph Huber EXTERN int omp_target_is_present(const void *Ptr, int DeviceNum) {
94e007b328SGiorgis Georgakoudis   TIMESCOPE();
95a3b147abSJonas Hahnfeld   DP("Call to omp_target_is_present for device %d and address " DPxMOD "\n",
96*d27d0a67SJoseph Huber      DeviceNum, DPxPTR(Ptr));
97a3b147abSJonas Hahnfeld 
98*d27d0a67SJoseph Huber   if (!Ptr) {
99a3b147abSJonas Hahnfeld     DP("Call to omp_target_is_present with NULL ptr, returning false\n");
100a3b147abSJonas Hahnfeld     return false;
101a3b147abSJonas Hahnfeld   }
102a3b147abSJonas Hahnfeld 
103*d27d0a67SJoseph Huber   if (DeviceNum == omp_get_initial_device()) {
104a3b147abSJonas Hahnfeld     DP("Call to omp_target_is_present on host, returning true\n");
105a3b147abSJonas Hahnfeld     return true;
106a3b147abSJonas Hahnfeld   }
107a3b147abSJonas Hahnfeld 
108a95b25b2SAtmn Patel   PM->RTLsMtx.lock();
109a95b25b2SAtmn Patel   size_t DevicesSize = PM->Devices.size();
110a95b25b2SAtmn Patel   PM->RTLsMtx.unlock();
111*d27d0a67SJoseph Huber   if (DevicesSize <= (size_t)DeviceNum) {
112a3b147abSJonas Hahnfeld     DP("Call to omp_target_is_present with invalid device ID, returning "
113a3b147abSJonas Hahnfeld        "false\n");
114a3b147abSJonas Hahnfeld     return false;
115a3b147abSJonas Hahnfeld   }
116a3b147abSJonas Hahnfeld 
117*d27d0a67SJoseph Huber   DeviceTy &Device = *PM->Devices[DeviceNum];
118a3b147abSJonas Hahnfeld   bool IsLast; // not used
119a1d20506SGheorghe-Teodor Bercea   bool IsHostPtr;
1208a880db5SYe Luo   // omp_target_is_present tests whether a host pointer refers to storage that
1218a880db5SYe Luo   // is mapped to a given device. However, due to the lack of the storage size,
1228a880db5SYe Luo   // only check 1 byte. Cannot set size 0 which checks whether the pointer (zero
1238a880db5SYe Luo   // lengh array) is mapped instead of the referred storage.
124b0789a1bSJohannes Doerfert   TargetPointerResultTy TPR =
125*d27d0a67SJoseph Huber       Device.getTgtPtrBegin(const_cast<void *>(Ptr), 1, IsLast,
126ec1ebcd3SJoel E. Denny                             /*UpdateRefCount=*/false,
127ec1ebcd3SJoel E. Denny                             /*UseHoldRefCount=*/false, IsHostPtr);
128*d27d0a67SJoseph Huber   int Rc = (TPR.TargetPointer != NULL);
129a1d20506SGheorghe-Teodor Bercea   // Under unified memory the host pointer can be returned by the
130a1d20506SGheorghe-Teodor Bercea   // getTgtPtrBegin() function which means that there is no device
131a1d20506SGheorghe-Teodor Bercea   // corresponding point for ptr. This function should return false
132a1d20506SGheorghe-Teodor Bercea   // in that situation.
133a95b25b2SAtmn Patel   if (PM->RTLs.RequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY)
134*d27d0a67SJoseph Huber     Rc = !IsHostPtr;
135*d27d0a67SJoseph Huber   DP("Call to omp_target_is_present returns %d\n", Rc);
136*d27d0a67SJoseph Huber   return Rc;
137a3b147abSJonas Hahnfeld }
138a3b147abSJonas Hahnfeld 
omp_target_memcpy(void * Dst,const void * Src,size_t Length,size_t DstOffset,size_t SrcOffset,int DstDevice,int SrcDevice)139*d27d0a67SJoseph Huber EXTERN int omp_target_memcpy(void *Dst, const void *Src, size_t Length,
140*d27d0a67SJoseph Huber                              size_t DstOffset, size_t SrcOffset, int DstDevice,
141*d27d0a67SJoseph Huber                              int SrcDevice) {
142e007b328SGiorgis Georgakoudis   TIMESCOPE();
143a3b147abSJonas Hahnfeld   DP("Call to omp_target_memcpy, dst device %d, src device %d, "
144a3b147abSJonas Hahnfeld      "dst addr " DPxMOD ", src addr " DPxMOD ", dst offset %zu, "
1459cd1e222SJohannes Doerfert      "src offset %zu, length %zu\n",
146*d27d0a67SJoseph Huber      DstDevice, SrcDevice, DPxPTR(Dst), DPxPTR(Src), DstOffset, SrcOffset,
147*d27d0a67SJoseph Huber      Length);
148a3b147abSJonas Hahnfeld 
149*d27d0a67SJoseph Huber   if (!Dst || !Src || Length <= 0) {
150*d27d0a67SJoseph Huber     if (Length == 0) {
151dec02904SGeorge Rokos       DP("Call to omp_target_memcpy with zero length, nothing to do\n");
152dec02904SGeorge Rokos       return OFFLOAD_SUCCESS;
153dec02904SGeorge Rokos     }
154dec02904SGeorge Rokos 
1557a5a74eaSJoseph Huber     REPORT("Call to omp_target_memcpy with invalid arguments\n");
156a3b147abSJonas Hahnfeld     return OFFLOAD_FAIL;
157a3b147abSJonas Hahnfeld   }
158a3b147abSJonas Hahnfeld 
159*d27d0a67SJoseph Huber   if (SrcDevice != omp_get_initial_device() && !deviceIsReady(SrcDevice)) {
1607a5a74eaSJoseph Huber     REPORT("omp_target_memcpy returns OFFLOAD_FAIL\n");
161a3b147abSJonas Hahnfeld     return OFFLOAD_FAIL;
162a3b147abSJonas Hahnfeld   }
163a3b147abSJonas Hahnfeld 
164*d27d0a67SJoseph Huber   if (DstDevice != omp_get_initial_device() && !deviceIsReady(DstDevice)) {
1657a5a74eaSJoseph Huber     REPORT("omp_target_memcpy returns OFFLOAD_FAIL\n");
166a3b147abSJonas Hahnfeld     return OFFLOAD_FAIL;
167a3b147abSJonas Hahnfeld   }
168a3b147abSJonas Hahnfeld 
169*d27d0a67SJoseph Huber   int Rc = OFFLOAD_SUCCESS;
170*d27d0a67SJoseph Huber   void *SrcAddr = (char *)const_cast<void *>(Src) + SrcOffset;
171*d27d0a67SJoseph Huber   void *DstAddr = (char *)Dst + DstOffset;
172a3b147abSJonas Hahnfeld 
173*d27d0a67SJoseph Huber   if (SrcDevice == omp_get_initial_device() &&
174*d27d0a67SJoseph Huber       DstDevice == omp_get_initial_device()) {
175a3b147abSJonas Hahnfeld     DP("copy from host to host\n");
176*d27d0a67SJoseph Huber     const void *P = memcpy(DstAddr, SrcAddr, Length);
177*d27d0a67SJoseph Huber     if (P == NULL)
178*d27d0a67SJoseph Huber       Rc = OFFLOAD_FAIL;
179*d27d0a67SJoseph Huber   } else if (SrcDevice == omp_get_initial_device()) {
180a3b147abSJonas Hahnfeld     DP("copy from host to device\n");
181*d27d0a67SJoseph Huber     DeviceTy &DstDev = *PM->Devices[DstDevice];
182758b8499SJohannes Doerfert     AsyncInfoTy AsyncInfo(DstDev);
183*d27d0a67SJoseph Huber     Rc = DstDev.submitData(DstAddr, SrcAddr, Length, AsyncInfo);
184*d27d0a67SJoseph Huber   } else if (DstDevice == omp_get_initial_device()) {
185a3b147abSJonas Hahnfeld     DP("copy from device to host\n");
186*d27d0a67SJoseph Huber     DeviceTy &SrcDev = *PM->Devices[SrcDevice];
187758b8499SJohannes Doerfert     AsyncInfoTy AsyncInfo(SrcDev);
188*d27d0a67SJoseph Huber     Rc = SrcDev.retrieveData(DstAddr, SrcAddr, Length, AsyncInfo);
189a3b147abSJonas Hahnfeld   } else {
190a3b147abSJonas Hahnfeld     DP("copy from device to device\n");
191*d27d0a67SJoseph Huber     DeviceTy &SrcDev = *PM->Devices[SrcDevice];
192*d27d0a67SJoseph Huber     DeviceTy &DstDev = *PM->Devices[DstDevice];
193a014fbbcSShilei Tian     // First try to use D2D memcpy which is more efficient. If fails, fall back
194a014fbbcSShilei Tian     // to unefficient way.
195a014fbbcSShilei Tian     if (SrcDev.isDataExchangable(DstDev)) {
196758b8499SJohannes Doerfert       AsyncInfoTy AsyncInfo(SrcDev);
197*d27d0a67SJoseph Huber       Rc = SrcDev.dataExchange(SrcAddr, DstDev, DstAddr, Length, AsyncInfo);
198*d27d0a67SJoseph Huber       if (Rc == OFFLOAD_SUCCESS)
199a014fbbcSShilei Tian         return OFFLOAD_SUCCESS;
200a014fbbcSShilei Tian     }
201a014fbbcSShilei Tian 
202*d27d0a67SJoseph Huber     void *Buffer = malloc(Length);
203758b8499SJohannes Doerfert     {
204758b8499SJohannes Doerfert       AsyncInfoTy AsyncInfo(SrcDev);
205*d27d0a67SJoseph Huber       Rc = SrcDev.retrieveData(Buffer, SrcAddr, Length, AsyncInfo);
206758b8499SJohannes Doerfert     }
207*d27d0a67SJoseph Huber     if (Rc == OFFLOAD_SUCCESS) {
208758b8499SJohannes Doerfert       AsyncInfoTy AsyncInfo(SrcDev);
209*d27d0a67SJoseph Huber       Rc = DstDev.submitData(DstAddr, Buffer, Length, AsyncInfo);
210758b8499SJohannes Doerfert     }
211*d27d0a67SJoseph Huber     free(Buffer);
212a3b147abSJonas Hahnfeld   }
213a3b147abSJonas Hahnfeld 
214*d27d0a67SJoseph Huber   DP("omp_target_memcpy returns %d\n", Rc);
215*d27d0a67SJoseph Huber   return Rc;
216a3b147abSJonas Hahnfeld }
217a3b147abSJonas Hahnfeld 
218*d27d0a67SJoseph Huber EXTERN int
omp_target_memcpy_rect(void * Dst,const void * Src,size_t ElementSize,int NumDims,const size_t * Volume,const size_t * DstOffsets,const size_t * SrcOffsets,const size_t * DstDimensions,const size_t * SrcDimensions,int DstDevice,int SrcDevice)219*d27d0a67SJoseph Huber omp_target_memcpy_rect(void *Dst, const void *Src, size_t ElementSize,
220*d27d0a67SJoseph Huber                        int NumDims, const size_t *Volume,
221*d27d0a67SJoseph Huber                        const size_t *DstOffsets, const size_t *SrcOffsets,
222*d27d0a67SJoseph Huber                        const size_t *DstDimensions, const size_t *SrcDimensions,
223*d27d0a67SJoseph Huber                        int DstDevice, int SrcDevice) {
224e007b328SGiorgis Georgakoudis   TIMESCOPE();
225a3b147abSJonas Hahnfeld   DP("Call to omp_target_memcpy_rect, dst device %d, src device %d, "
226a3b147abSJonas Hahnfeld      "dst addr " DPxMOD ", src addr " DPxMOD ", dst offsets " DPxMOD ", "
227a3b147abSJonas Hahnfeld      "src offsets " DPxMOD ", dst dims " DPxMOD ", src dims " DPxMOD ", "
2289cd1e222SJohannes Doerfert      "volume " DPxMOD ", element size %zu, num_dims %d\n",
229*d27d0a67SJoseph Huber      DstDevice, SrcDevice, DPxPTR(Dst), DPxPTR(Src), DPxPTR(DstOffsets),
230*d27d0a67SJoseph Huber      DPxPTR(SrcOffsets), DPxPTR(DstDimensions), DPxPTR(SrcDimensions),
231*d27d0a67SJoseph Huber      DPxPTR(Volume), ElementSize, NumDims);
232a3b147abSJonas Hahnfeld 
233*d27d0a67SJoseph Huber   if (!(Dst || Src)) {
234a3b147abSJonas Hahnfeld     DP("Call to omp_target_memcpy_rect returns max supported dimensions %d\n",
235a3b147abSJonas Hahnfeld        INT_MAX);
236a3b147abSJonas Hahnfeld     return INT_MAX;
237a3b147abSJonas Hahnfeld   }
238a3b147abSJonas Hahnfeld 
239*d27d0a67SJoseph Huber   if (!Dst || !Src || ElementSize < 1 || NumDims < 1 || !Volume ||
240*d27d0a67SJoseph Huber       !DstOffsets || !SrcOffsets || !DstDimensions || !SrcDimensions) {
2417a5a74eaSJoseph Huber     REPORT("Call to omp_target_memcpy_rect with invalid arguments\n");
242a3b147abSJonas Hahnfeld     return OFFLOAD_FAIL;
243a3b147abSJonas Hahnfeld   }
244a3b147abSJonas Hahnfeld 
245*d27d0a67SJoseph Huber   int Rc;
246*d27d0a67SJoseph Huber   if (NumDims == 1) {
247*d27d0a67SJoseph Huber     Rc = omp_target_memcpy(Dst, Src, ElementSize * Volume[0],
248*d27d0a67SJoseph Huber                            ElementSize * DstOffsets[0],
249*d27d0a67SJoseph Huber                            ElementSize * SrcOffsets[0], DstDevice, SrcDevice);
250a3b147abSJonas Hahnfeld   } else {
251*d27d0a67SJoseph Huber     size_t DstSliceSize = ElementSize;
252*d27d0a67SJoseph Huber     size_t SrcSliceSize = ElementSize;
253*d27d0a67SJoseph Huber     for (int I = 1; I < NumDims; ++I) {
254*d27d0a67SJoseph Huber       DstSliceSize *= DstDimensions[I];
255*d27d0a67SJoseph Huber       SrcSliceSize *= SrcDimensions[I];
256a3b147abSJonas Hahnfeld     }
257a3b147abSJonas Hahnfeld 
258*d27d0a67SJoseph Huber     size_t DstOff = DstOffsets[0] * DstSliceSize;
259*d27d0a67SJoseph Huber     size_t SrcOff = SrcOffsets[0] * SrcSliceSize;
260*d27d0a67SJoseph Huber     for (size_t I = 0; I < Volume[0]; ++I) {
261*d27d0a67SJoseph Huber       Rc = omp_target_memcpy_rect(
262*d27d0a67SJoseph Huber           (char *)Dst + DstOff + DstSliceSize * I,
263*d27d0a67SJoseph Huber           (char *)const_cast<void *>(Src) + SrcOff + SrcSliceSize * I,
264*d27d0a67SJoseph Huber           ElementSize, NumDims - 1, Volume + 1, DstOffsets + 1, SrcOffsets + 1,
265*d27d0a67SJoseph Huber           DstDimensions + 1, SrcDimensions + 1, DstDevice, SrcDevice);
266a3b147abSJonas Hahnfeld 
267*d27d0a67SJoseph Huber       if (Rc) {
268a3b147abSJonas Hahnfeld         DP("Recursive call to omp_target_memcpy_rect returns unsuccessfully\n");
269*d27d0a67SJoseph Huber         return Rc;
270a3b147abSJonas Hahnfeld       }
271a3b147abSJonas Hahnfeld     }
272a3b147abSJonas Hahnfeld   }
273a3b147abSJonas Hahnfeld 
274*d27d0a67SJoseph Huber   DP("omp_target_memcpy_rect returns %d\n", Rc);
275*d27d0a67SJoseph Huber   return Rc;
276a3b147abSJonas Hahnfeld }
277a3b147abSJonas Hahnfeld 
omp_target_associate_ptr(const void * HostPtr,const void * DevicePtr,size_t Size,size_t DeviceOffset,int DeviceNum)278*d27d0a67SJoseph Huber EXTERN int omp_target_associate_ptr(const void *HostPtr, const void *DevicePtr,
279*d27d0a67SJoseph Huber                                     size_t Size, size_t DeviceOffset,
280*d27d0a67SJoseph Huber                                     int DeviceNum) {
281e007b328SGiorgis Georgakoudis   TIMESCOPE();
282a3b147abSJonas Hahnfeld   DP("Call to omp_target_associate_ptr with host_ptr " DPxMOD ", "
283a3b147abSJonas Hahnfeld      "device_ptr " DPxMOD ", size %zu, device_offset %zu, device_num %d\n",
284*d27d0a67SJoseph Huber      DPxPTR(HostPtr), DPxPTR(DevicePtr), Size, DeviceOffset, DeviceNum);
285a3b147abSJonas Hahnfeld 
286*d27d0a67SJoseph Huber   if (!HostPtr || !DevicePtr || Size <= 0) {
2877a5a74eaSJoseph Huber     REPORT("Call to omp_target_associate_ptr with invalid arguments\n");
288a3b147abSJonas Hahnfeld     return OFFLOAD_FAIL;
289a3b147abSJonas Hahnfeld   }
290a3b147abSJonas Hahnfeld 
291*d27d0a67SJoseph Huber   if (DeviceNum == omp_get_initial_device()) {
2927a5a74eaSJoseph Huber     REPORT("omp_target_associate_ptr: no association possible on the host\n");
293a3b147abSJonas Hahnfeld     return OFFLOAD_FAIL;
294a3b147abSJonas Hahnfeld   }
295a3b147abSJonas Hahnfeld 
296*d27d0a67SJoseph Huber   if (!deviceIsReady(DeviceNum)) {
2977a5a74eaSJoseph Huber     REPORT("omp_target_associate_ptr returns OFFLOAD_FAIL\n");
298a3b147abSJonas Hahnfeld     return OFFLOAD_FAIL;
299a3b147abSJonas Hahnfeld   }
300a3b147abSJonas Hahnfeld 
301*d27d0a67SJoseph Huber   DeviceTy &Device = *PM->Devices[DeviceNum];
302*d27d0a67SJoseph Huber   void *DeviceAddr = (void *)((uint64_t)DevicePtr + (uint64_t)DeviceOffset);
303*d27d0a67SJoseph Huber   int Rc = Device.associatePtr(const_cast<void *>(HostPtr),
304*d27d0a67SJoseph Huber                                const_cast<void *>(DeviceAddr), Size);
305*d27d0a67SJoseph Huber   DP("omp_target_associate_ptr returns %d\n", Rc);
306*d27d0a67SJoseph Huber   return Rc;
307a3b147abSJonas Hahnfeld }
308a3b147abSJonas Hahnfeld 
omp_target_disassociate_ptr(const void * HostPtr,int DeviceNum)309*d27d0a67SJoseph Huber EXTERN int omp_target_disassociate_ptr(const void *HostPtr, int DeviceNum) {
310e007b328SGiorgis Georgakoudis   TIMESCOPE();
311a3b147abSJonas Hahnfeld   DP("Call to omp_target_disassociate_ptr with host_ptr " DPxMOD ", "
3129cd1e222SJohannes Doerfert      "device_num %d\n",
313*d27d0a67SJoseph Huber      DPxPTR(HostPtr), DeviceNum);
314a3b147abSJonas Hahnfeld 
315*d27d0a67SJoseph Huber   if (!HostPtr) {
3167a5a74eaSJoseph Huber     REPORT("Call to omp_target_associate_ptr with invalid host_ptr\n");
317a3b147abSJonas Hahnfeld     return OFFLOAD_FAIL;
318a3b147abSJonas Hahnfeld   }
319a3b147abSJonas Hahnfeld 
320*d27d0a67SJoseph Huber   if (DeviceNum == omp_get_initial_device()) {
3217a5a74eaSJoseph Huber     REPORT(
3227a5a74eaSJoseph Huber         "omp_target_disassociate_ptr: no association possible on the host\n");
323a3b147abSJonas Hahnfeld     return OFFLOAD_FAIL;
324a3b147abSJonas Hahnfeld   }
325a3b147abSJonas Hahnfeld 
326*d27d0a67SJoseph Huber   if (!deviceIsReady(DeviceNum)) {
3277a5a74eaSJoseph Huber     REPORT("omp_target_disassociate_ptr returns OFFLOAD_FAIL\n");
328a3b147abSJonas Hahnfeld     return OFFLOAD_FAIL;
329a3b147abSJonas Hahnfeld   }
330a3b147abSJonas Hahnfeld 
331*d27d0a67SJoseph Huber   DeviceTy &Device = *PM->Devices[DeviceNum];
332*d27d0a67SJoseph Huber   int Rc = Device.disassociatePtr(const_cast<void *>(HostPtr));
333*d27d0a67SJoseph Huber   DP("omp_target_disassociate_ptr returns %d\n", Rc);
334*d27d0a67SJoseph Huber   return Rc;
335a3b147abSJonas Hahnfeld }
336