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