1330d8983SJohannes Doerfert //===----------- api.cpp - Target independent OpenMP target RTL -----------===// 2330d8983SJohannes Doerfert // 3330d8983SJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4330d8983SJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information. 5330d8983SJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6330d8983SJohannes Doerfert // 7330d8983SJohannes Doerfert //===----------------------------------------------------------------------===// 8330d8983SJohannes Doerfert // 9330d8983SJohannes Doerfert // Implementation of OpenMP API interface functions. 10330d8983SJohannes Doerfert // 11330d8983SJohannes Doerfert //===----------------------------------------------------------------------===// 12330d8983SJohannes Doerfert 13330d8983SJohannes Doerfert #include "PluginManager.h" 14330d8983SJohannes Doerfert #include "device.h" 15330d8983SJohannes Doerfert #include "omptarget.h" 16330d8983SJohannes Doerfert #include "rtl.h" 17330d8983SJohannes Doerfert 18330d8983SJohannes Doerfert #include "OpenMP/InternalTypes.h" 19330d8983SJohannes Doerfert #include "OpenMP/Mapping.h" 20330d8983SJohannes Doerfert #include "OpenMP/OMPT/Interface.h" 21330d8983SJohannes Doerfert #include "OpenMP/omp.h" 22330d8983SJohannes Doerfert #include "Shared/Profile.h" 23330d8983SJohannes Doerfert 24330d8983SJohannes Doerfert #include "llvm/ADT/SmallVector.h" 25330d8983SJohannes Doerfert 26330d8983SJohannes Doerfert #include <climits> 27330d8983SJohannes Doerfert #include <cstdlib> 28330d8983SJohannes Doerfert #include <cstring> 29330d8983SJohannes Doerfert #include <mutex> 30330d8983SJohannes Doerfert 31330d8983SJohannes Doerfert EXTERN void ompx_dump_mapping_tables() { 32330d8983SJohannes Doerfert ident_t Loc = {0, 0, 0, 0, ";libomptarget;libomptarget;0;0;;"}; 33330d8983SJohannes Doerfert auto ExclusiveDevicesAccessor = PM->getExclusiveDevicesAccessor(); 34330d8983SJohannes Doerfert for (auto &Device : PM->devices(ExclusiveDevicesAccessor)) 35330d8983SJohannes Doerfert dumpTargetPointerMappings(&Loc, Device, true); 36330d8983SJohannes Doerfert } 37330d8983SJohannes Doerfert 38330d8983SJohannes Doerfert #ifdef OMPT_SUPPORT 39330d8983SJohannes Doerfert using namespace llvm::omp::target::ompt; 40330d8983SJohannes Doerfert #endif 41330d8983SJohannes Doerfert 42330d8983SJohannes Doerfert void *targetAllocExplicit(size_t Size, int DeviceNum, int Kind, 43330d8983SJohannes Doerfert const char *Name); 44330d8983SJohannes Doerfert void targetFreeExplicit(void *DevicePtr, int DeviceNum, int Kind, 45330d8983SJohannes Doerfert const char *Name); 46330d8983SJohannes Doerfert void *targetLockExplicit(void *HostPtr, size_t Size, int DeviceNum, 47330d8983SJohannes Doerfert const char *Name); 48330d8983SJohannes Doerfert void targetUnlockExplicit(void *HostPtr, int DeviceNum, const char *Name); 49330d8983SJohannes Doerfert 50330d8983SJohannes Doerfert // Implemented in libomp, they are called from within __tgt_* functions. 51330d8983SJohannes Doerfert extern "C" { 52330d8983SJohannes Doerfert int __kmpc_get_target_offload(void) __attribute__((weak)); 53330d8983SJohannes Doerfert kmp_task_t *__kmpc_omp_task_alloc(ident_t *loc_ref, int32_t gtid, int32_t flags, 54330d8983SJohannes Doerfert size_t sizeof_kmp_task_t, 55330d8983SJohannes Doerfert size_t sizeof_shareds, 56330d8983SJohannes Doerfert kmp_routine_entry_t task_entry) 57330d8983SJohannes Doerfert __attribute__((weak)); 58330d8983SJohannes Doerfert 59330d8983SJohannes Doerfert kmp_task_t * 60330d8983SJohannes Doerfert __kmpc_omp_target_task_alloc(ident_t *loc_ref, int32_t gtid, int32_t flags, 61330d8983SJohannes Doerfert size_t sizeof_kmp_task_t, size_t sizeof_shareds, 62330d8983SJohannes Doerfert kmp_routine_entry_t task_entry, int64_t device_id) 63330d8983SJohannes Doerfert __attribute__((weak)); 64330d8983SJohannes Doerfert 65330d8983SJohannes Doerfert int32_t __kmpc_omp_task_with_deps(ident_t *loc_ref, int32_t gtid, 66330d8983SJohannes Doerfert kmp_task_t *new_task, int32_t ndeps, 67330d8983SJohannes Doerfert kmp_depend_info_t *dep_list, 68330d8983SJohannes Doerfert int32_t ndeps_noalias, 69330d8983SJohannes Doerfert kmp_depend_info_t *noalias_dep_list) 70330d8983SJohannes Doerfert __attribute__((weak)); 71330d8983SJohannes Doerfert } 72330d8983SJohannes Doerfert 73330d8983SJohannes Doerfert EXTERN int omp_get_num_devices(void) { 74330d8983SJohannes Doerfert TIMESCOPE(); 75330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 76330d8983SJohannes Doerfert size_t NumDevices = PM->getNumDevices(); 77330d8983SJohannes Doerfert 78330d8983SJohannes Doerfert DP("Call to omp_get_num_devices returning %zd\n", NumDevices); 79330d8983SJohannes Doerfert 80330d8983SJohannes Doerfert return NumDevices; 81330d8983SJohannes Doerfert } 82330d8983SJohannes Doerfert 83330d8983SJohannes Doerfert EXTERN int omp_get_device_num(void) { 84330d8983SJohannes Doerfert TIMESCOPE(); 85330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 86330d8983SJohannes Doerfert int HostDevice = omp_get_initial_device(); 87330d8983SJohannes Doerfert 88330d8983SJohannes Doerfert DP("Call to omp_get_device_num returning %d\n", HostDevice); 89330d8983SJohannes Doerfert 90330d8983SJohannes Doerfert return HostDevice; 91330d8983SJohannes Doerfert } 92330d8983SJohannes Doerfert 93330d8983SJohannes Doerfert EXTERN int omp_get_initial_device(void) { 94330d8983SJohannes Doerfert TIMESCOPE(); 95330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 96330d8983SJohannes Doerfert int HostDevice = omp_get_num_devices(); 97330d8983SJohannes Doerfert DP("Call to omp_get_initial_device returning %d\n", HostDevice); 98330d8983SJohannes Doerfert return HostDevice; 99330d8983SJohannes Doerfert } 100330d8983SJohannes Doerfert 101330d8983SJohannes Doerfert EXTERN void *omp_target_alloc(size_t Size, int DeviceNum) { 102330d8983SJohannes Doerfert TIMESCOPE_WITH_DETAILS("dst_dev=" + std::to_string(DeviceNum) + 103330d8983SJohannes Doerfert ";size=" + std::to_string(Size)); 104330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 105330d8983SJohannes Doerfert return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_DEFAULT, __func__); 106330d8983SJohannes Doerfert } 107330d8983SJohannes Doerfert 108330d8983SJohannes Doerfert EXTERN void *llvm_omp_target_alloc_device(size_t Size, int DeviceNum) { 109330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 110330d8983SJohannes Doerfert return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_DEVICE, __func__); 111330d8983SJohannes Doerfert } 112330d8983SJohannes Doerfert 113330d8983SJohannes Doerfert EXTERN void *llvm_omp_target_alloc_host(size_t Size, int DeviceNum) { 114330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 115330d8983SJohannes Doerfert return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_HOST, __func__); 116330d8983SJohannes Doerfert } 117330d8983SJohannes Doerfert 118330d8983SJohannes Doerfert EXTERN void *llvm_omp_target_alloc_shared(size_t Size, int DeviceNum) { 119330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 120330d8983SJohannes Doerfert return targetAllocExplicit(Size, DeviceNum, TARGET_ALLOC_SHARED, __func__); 121330d8983SJohannes Doerfert } 122330d8983SJohannes Doerfert 123330d8983SJohannes Doerfert EXTERN void omp_target_free(void *Ptr, int DeviceNum) { 124330d8983SJohannes Doerfert TIMESCOPE(); 125330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 126330d8983SJohannes Doerfert return targetFreeExplicit(Ptr, DeviceNum, TARGET_ALLOC_DEFAULT, __func__); 127330d8983SJohannes Doerfert } 128330d8983SJohannes Doerfert 129330d8983SJohannes Doerfert EXTERN void llvm_omp_target_free_device(void *Ptr, int DeviceNum) { 130330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 131330d8983SJohannes Doerfert return targetFreeExplicit(Ptr, DeviceNum, TARGET_ALLOC_DEVICE, __func__); 132330d8983SJohannes Doerfert } 133330d8983SJohannes Doerfert 134330d8983SJohannes Doerfert EXTERN void llvm_omp_target_free_host(void *Ptr, int DeviceNum) { 135330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 136330d8983SJohannes Doerfert return targetFreeExplicit(Ptr, DeviceNum, TARGET_ALLOC_HOST, __func__); 137330d8983SJohannes Doerfert } 138330d8983SJohannes Doerfert 139330d8983SJohannes Doerfert EXTERN void llvm_omp_target_free_shared(void *Ptre, int DeviceNum) { 140330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 141330d8983SJohannes Doerfert return targetFreeExplicit(Ptre, DeviceNum, TARGET_ALLOC_SHARED, __func__); 142330d8983SJohannes Doerfert } 143330d8983SJohannes Doerfert 144330d8983SJohannes Doerfert EXTERN void *llvm_omp_target_dynamic_shared_alloc() { 145330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 146330d8983SJohannes Doerfert return nullptr; 147330d8983SJohannes Doerfert } 148330d8983SJohannes Doerfert 149330d8983SJohannes Doerfert EXTERN void *llvm_omp_get_dynamic_shared() { 150330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 151330d8983SJohannes Doerfert return nullptr; 152330d8983SJohannes Doerfert } 153330d8983SJohannes Doerfert 154330d8983SJohannes Doerfert EXTERN [[nodiscard]] void *llvm_omp_target_lock_mem(void *Ptr, size_t Size, 155330d8983SJohannes Doerfert int DeviceNum) { 156330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 157330d8983SJohannes Doerfert return targetLockExplicit(Ptr, Size, DeviceNum, __func__); 158330d8983SJohannes Doerfert } 159330d8983SJohannes Doerfert 160330d8983SJohannes Doerfert EXTERN void llvm_omp_target_unlock_mem(void *Ptr, int DeviceNum) { 161330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 162330d8983SJohannes Doerfert targetUnlockExplicit(Ptr, DeviceNum, __func__); 163330d8983SJohannes Doerfert } 164330d8983SJohannes Doerfert 165330d8983SJohannes Doerfert EXTERN int omp_target_is_present(const void *Ptr, int DeviceNum) { 166330d8983SJohannes Doerfert TIMESCOPE(); 167330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 168330d8983SJohannes Doerfert DP("Call to omp_target_is_present for device %d and address " DPxMOD "\n", 169330d8983SJohannes Doerfert DeviceNum, DPxPTR(Ptr)); 170330d8983SJohannes Doerfert 171330d8983SJohannes Doerfert if (!Ptr) { 172330d8983SJohannes Doerfert DP("Call to omp_target_is_present with NULL ptr, returning false\n"); 173330d8983SJohannes Doerfert return false; 174330d8983SJohannes Doerfert } 175330d8983SJohannes Doerfert 176330d8983SJohannes Doerfert if (DeviceNum == omp_get_initial_device()) { 177330d8983SJohannes Doerfert DP("Call to omp_target_is_present on host, returning true\n"); 178330d8983SJohannes Doerfert return true; 179330d8983SJohannes Doerfert } 180330d8983SJohannes Doerfert 181330d8983SJohannes Doerfert auto DeviceOrErr = PM->getDevice(DeviceNum); 182330d8983SJohannes Doerfert if (!DeviceOrErr) 183330d8983SJohannes Doerfert FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str()); 184330d8983SJohannes Doerfert 185330d8983SJohannes Doerfert // omp_target_is_present tests whether a host pointer refers to storage that 186330d8983SJohannes Doerfert // is mapped to a given device. However, due to the lack of the storage size, 187330d8983SJohannes Doerfert // only check 1 byte. Cannot set size 0 which checks whether the pointer (zero 188330d8983SJohannes Doerfert // lengh array) is mapped instead of the referred storage. 189330d8983SJohannes Doerfert TargetPointerResultTy TPR = 190330d8983SJohannes Doerfert DeviceOrErr->getMappingInfo().getTgtPtrBegin(const_cast<void *>(Ptr), 1, 191330d8983SJohannes Doerfert /*UpdateRefCount=*/false, 192330d8983SJohannes Doerfert /*UseHoldRefCount=*/false); 193330d8983SJohannes Doerfert int Rc = TPR.isPresent(); 194330d8983SJohannes Doerfert DP("Call to omp_target_is_present returns %d\n", Rc); 195330d8983SJohannes Doerfert return Rc; 196330d8983SJohannes Doerfert } 197330d8983SJohannes Doerfert 198330d8983SJohannes Doerfert EXTERN int omp_target_memcpy(void *Dst, const void *Src, size_t Length, 199330d8983SJohannes Doerfert size_t DstOffset, size_t SrcOffset, int DstDevice, 200330d8983SJohannes Doerfert int SrcDevice) { 201330d8983SJohannes Doerfert TIMESCOPE_WITH_DETAILS("dst_dev=" + std::to_string(DstDevice) + 202330d8983SJohannes Doerfert ";src_dev=" + std::to_string(SrcDevice) + 203330d8983SJohannes Doerfert ";size=" + std::to_string(Length)); 204330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 205330d8983SJohannes Doerfert DP("Call to omp_target_memcpy, dst device %d, src device %d, " 206330d8983SJohannes Doerfert "dst addr " DPxMOD ", src addr " DPxMOD ", dst offset %zu, " 207330d8983SJohannes Doerfert "src offset %zu, length %zu\n", 208330d8983SJohannes Doerfert DstDevice, SrcDevice, DPxPTR(Dst), DPxPTR(Src), DstOffset, SrcOffset, 209330d8983SJohannes Doerfert Length); 210330d8983SJohannes Doerfert 211330d8983SJohannes Doerfert if (!Dst || !Src || Length <= 0) { 212330d8983SJohannes Doerfert if (Length == 0) { 213330d8983SJohannes Doerfert DP("Call to omp_target_memcpy with zero length, nothing to do\n"); 214330d8983SJohannes Doerfert return OFFLOAD_SUCCESS; 215330d8983SJohannes Doerfert } 216330d8983SJohannes Doerfert 217330d8983SJohannes Doerfert REPORT("Call to omp_target_memcpy with invalid arguments\n"); 218330d8983SJohannes Doerfert return OFFLOAD_FAIL; 219330d8983SJohannes Doerfert } 220330d8983SJohannes Doerfert 221330d8983SJohannes Doerfert int Rc = OFFLOAD_SUCCESS; 222330d8983SJohannes Doerfert void *SrcAddr = (char *)const_cast<void *>(Src) + SrcOffset; 223330d8983SJohannes Doerfert void *DstAddr = (char *)Dst + DstOffset; 224330d8983SJohannes Doerfert 225330d8983SJohannes Doerfert if (SrcDevice == omp_get_initial_device() && 226330d8983SJohannes Doerfert DstDevice == omp_get_initial_device()) { 227330d8983SJohannes Doerfert DP("copy from host to host\n"); 228330d8983SJohannes Doerfert const void *P = memcpy(DstAddr, SrcAddr, Length); 229330d8983SJohannes Doerfert if (P == NULL) 230330d8983SJohannes Doerfert Rc = OFFLOAD_FAIL; 231330d8983SJohannes Doerfert } else if (SrcDevice == omp_get_initial_device()) { 232330d8983SJohannes Doerfert DP("copy from host to device\n"); 233330d8983SJohannes Doerfert auto DstDeviceOrErr = PM->getDevice(DstDevice); 234330d8983SJohannes Doerfert if (!DstDeviceOrErr) 235330d8983SJohannes Doerfert FATAL_MESSAGE(DstDevice, "%s", 236330d8983SJohannes Doerfert toString(DstDeviceOrErr.takeError()).c_str()); 237330d8983SJohannes Doerfert AsyncInfoTy AsyncInfo(*DstDeviceOrErr); 238330d8983SJohannes Doerfert Rc = DstDeviceOrErr->submitData(DstAddr, SrcAddr, Length, AsyncInfo); 239330d8983SJohannes Doerfert } else if (DstDevice == omp_get_initial_device()) { 240330d8983SJohannes Doerfert DP("copy from device to host\n"); 241330d8983SJohannes Doerfert auto SrcDeviceOrErr = PM->getDevice(SrcDevice); 242330d8983SJohannes Doerfert if (!SrcDeviceOrErr) 243330d8983SJohannes Doerfert FATAL_MESSAGE(SrcDevice, "%s", 244330d8983SJohannes Doerfert toString(SrcDeviceOrErr.takeError()).c_str()); 245330d8983SJohannes Doerfert AsyncInfoTy AsyncInfo(*SrcDeviceOrErr); 246330d8983SJohannes Doerfert Rc = SrcDeviceOrErr->retrieveData(DstAddr, SrcAddr, Length, AsyncInfo); 247330d8983SJohannes Doerfert } else { 248330d8983SJohannes Doerfert DP("copy from device to device\n"); 249330d8983SJohannes Doerfert auto SrcDeviceOrErr = PM->getDevice(SrcDevice); 250330d8983SJohannes Doerfert if (!SrcDeviceOrErr) 251330d8983SJohannes Doerfert FATAL_MESSAGE(SrcDevice, "%s", 252330d8983SJohannes Doerfert toString(SrcDeviceOrErr.takeError()).c_str()); 253330d8983SJohannes Doerfert AsyncInfoTy AsyncInfo(*SrcDeviceOrErr); 254330d8983SJohannes Doerfert auto DstDeviceOrErr = PM->getDevice(DstDevice); 255330d8983SJohannes Doerfert if (!DstDeviceOrErr) 256330d8983SJohannes Doerfert FATAL_MESSAGE(DstDevice, "%s", 257330d8983SJohannes Doerfert toString(DstDeviceOrErr.takeError()).c_str()); 258330d8983SJohannes Doerfert // First try to use D2D memcpy which is more efficient. If fails, fall back 259330d8983SJohannes Doerfert // to unefficient way. 260330d8983SJohannes Doerfert if (SrcDeviceOrErr->isDataExchangable(*DstDeviceOrErr)) { 261330d8983SJohannes Doerfert AsyncInfoTy AsyncInfo(*SrcDeviceOrErr); 262330d8983SJohannes Doerfert Rc = SrcDeviceOrErr->dataExchange(SrcAddr, *DstDeviceOrErr, DstAddr, 263330d8983SJohannes Doerfert Length, AsyncInfo); 264330d8983SJohannes Doerfert if (Rc == OFFLOAD_SUCCESS) 265330d8983SJohannes Doerfert return OFFLOAD_SUCCESS; 266330d8983SJohannes Doerfert } 267330d8983SJohannes Doerfert 268330d8983SJohannes Doerfert void *Buffer = malloc(Length); 269330d8983SJohannes Doerfert { 270330d8983SJohannes Doerfert AsyncInfoTy AsyncInfo(*SrcDeviceOrErr); 271330d8983SJohannes Doerfert Rc = SrcDeviceOrErr->retrieveData(Buffer, SrcAddr, Length, AsyncInfo); 272330d8983SJohannes Doerfert } 273330d8983SJohannes Doerfert if (Rc == OFFLOAD_SUCCESS) { 274330d8983SJohannes Doerfert AsyncInfoTy AsyncInfo(*DstDeviceOrErr); 275330d8983SJohannes Doerfert Rc = DstDeviceOrErr->submitData(DstAddr, Buffer, Length, AsyncInfo); 276330d8983SJohannes Doerfert } 277330d8983SJohannes Doerfert free(Buffer); 278330d8983SJohannes Doerfert } 279330d8983SJohannes Doerfert 280330d8983SJohannes Doerfert DP("omp_target_memcpy returns %d\n", Rc); 281330d8983SJohannes Doerfert return Rc; 282330d8983SJohannes Doerfert } 283330d8983SJohannes Doerfert 284330d8983SJohannes Doerfert // The helper function that calls omp_target_memcpy or omp_target_memcpy_rect 285330d8983SJohannes Doerfert static int libomp_target_memcpy_async_task(int32_t Gtid, kmp_task_t *Task) { 286330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 287330d8983SJohannes Doerfert if (Task == nullptr) 288330d8983SJohannes Doerfert return OFFLOAD_FAIL; 289330d8983SJohannes Doerfert 290330d8983SJohannes Doerfert TargetMemcpyArgsTy *Args = (TargetMemcpyArgsTy *)Task->shareds; 291330d8983SJohannes Doerfert 292330d8983SJohannes Doerfert if (Args == nullptr) 293330d8983SJohannes Doerfert return OFFLOAD_FAIL; 294330d8983SJohannes Doerfert 295330d8983SJohannes Doerfert // Call blocked version 296330d8983SJohannes Doerfert int Rc = OFFLOAD_SUCCESS; 297330d8983SJohannes Doerfert if (Args->IsRectMemcpy) { 298330d8983SJohannes Doerfert Rc = omp_target_memcpy_rect( 299330d8983SJohannes Doerfert Args->Dst, Args->Src, Args->ElementSize, Args->NumDims, Args->Volume, 300330d8983SJohannes Doerfert Args->DstOffsets, Args->SrcOffsets, Args->DstDimensions, 301330d8983SJohannes Doerfert Args->SrcDimensions, Args->DstDevice, Args->SrcDevice); 302330d8983SJohannes Doerfert 303330d8983SJohannes Doerfert DP("omp_target_memcpy_rect returns %d\n", Rc); 304330d8983SJohannes Doerfert } else { 305330d8983SJohannes Doerfert Rc = omp_target_memcpy(Args->Dst, Args->Src, Args->Length, Args->DstOffset, 306330d8983SJohannes Doerfert Args->SrcOffset, Args->DstDevice, Args->SrcDevice); 307330d8983SJohannes Doerfert 308330d8983SJohannes Doerfert DP("omp_target_memcpy returns %d\n", Rc); 309330d8983SJohannes Doerfert } 310330d8983SJohannes Doerfert 311330d8983SJohannes Doerfert // Release the arguments object 312330d8983SJohannes Doerfert delete Args; 313330d8983SJohannes Doerfert 314330d8983SJohannes Doerfert return Rc; 315330d8983SJohannes Doerfert } 316330d8983SJohannes Doerfert 317330d8983SJohannes Doerfert static int libomp_target_memset_async_task(int32_t Gtid, kmp_task_t *Task) { 318330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 319330d8983SJohannes Doerfert if (!Task) 320330d8983SJohannes Doerfert return OFFLOAD_FAIL; 321330d8983SJohannes Doerfert 322330d8983SJohannes Doerfert auto *Args = reinterpret_cast<TargetMemsetArgsTy *>(Task->shareds); 323330d8983SJohannes Doerfert if (!Args) 324330d8983SJohannes Doerfert return OFFLOAD_FAIL; 325330d8983SJohannes Doerfert 326330d8983SJohannes Doerfert // call omp_target_memset() 327330d8983SJohannes Doerfert omp_target_memset(Args->Ptr, Args->C, Args->N, Args->DeviceNum); 328330d8983SJohannes Doerfert 329330d8983SJohannes Doerfert delete Args; 330330d8983SJohannes Doerfert 331330d8983SJohannes Doerfert return OFFLOAD_SUCCESS; 332330d8983SJohannes Doerfert } 333330d8983SJohannes Doerfert 334330d8983SJohannes Doerfert static inline void 335330d8983SJohannes Doerfert convertDepObjVector(llvm::SmallVector<kmp_depend_info_t> &Vec, int DepObjCount, 336330d8983SJohannes Doerfert omp_depend_t *DepObjList) { 337330d8983SJohannes Doerfert for (int i = 0; i < DepObjCount; ++i) { 338330d8983SJohannes Doerfert omp_depend_t DepObj = DepObjList[i]; 339330d8983SJohannes Doerfert Vec.push_back(*((kmp_depend_info_t *)DepObj)); 340330d8983SJohannes Doerfert } 341330d8983SJohannes Doerfert } 342330d8983SJohannes Doerfert 343330d8983SJohannes Doerfert template <class T> 344330d8983SJohannes Doerfert static inline int 345330d8983SJohannes Doerfert libomp_helper_task_creation(T *Args, int (*Fn)(int32_t, kmp_task_t *), 346330d8983SJohannes Doerfert int DepObjCount, omp_depend_t *DepObjList) { 347330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 348330d8983SJohannes Doerfert // Create global thread ID 349330d8983SJohannes Doerfert int Gtid = __kmpc_global_thread_num(nullptr); 350330d8983SJohannes Doerfert 351330d8983SJohannes Doerfert // Setup the hidden helper flags 352330d8983SJohannes Doerfert int32_t Flags = 0; 353330d8983SJohannes Doerfert kmp_tasking_flags_t *InputFlags = (kmp_tasking_flags_t *)&Flags; 354330d8983SJohannes Doerfert InputFlags->hidden_helper = 1; 355330d8983SJohannes Doerfert 356330d8983SJohannes Doerfert // Alloc the helper task 357330d8983SJohannes Doerfert kmp_task_t *Task = __kmpc_omp_target_task_alloc( 358330d8983SJohannes Doerfert nullptr, Gtid, Flags, sizeof(kmp_task_t), 0, Fn, -1); 359330d8983SJohannes Doerfert if (!Task) { 360330d8983SJohannes Doerfert delete Args; 361330d8983SJohannes Doerfert return OFFLOAD_FAIL; 362330d8983SJohannes Doerfert } 363330d8983SJohannes Doerfert 364330d8983SJohannes Doerfert // Setup the arguments for the helper task 365330d8983SJohannes Doerfert Task->shareds = Args; 366330d8983SJohannes Doerfert 367330d8983SJohannes Doerfert // Convert types of depend objects 368330d8983SJohannes Doerfert llvm::SmallVector<kmp_depend_info_t> DepObjs; 369330d8983SJohannes Doerfert convertDepObjVector(DepObjs, DepObjCount, DepObjList); 370330d8983SJohannes Doerfert 371330d8983SJohannes Doerfert // Launch the helper task 372330d8983SJohannes Doerfert int Rc = __kmpc_omp_task_with_deps(nullptr, Gtid, Task, DepObjCount, 373330d8983SJohannes Doerfert DepObjs.data(), 0, nullptr); 374330d8983SJohannes Doerfert 375330d8983SJohannes Doerfert return Rc; 376330d8983SJohannes Doerfert } 377330d8983SJohannes Doerfert 378330d8983SJohannes Doerfert EXTERN void *omp_target_memset(void *Ptr, int ByteVal, size_t NumBytes, 379330d8983SJohannes Doerfert int DeviceNum) { 380330d8983SJohannes Doerfert TIMESCOPE(); 381330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 382330d8983SJohannes Doerfert DP("Call to omp_target_memset, device %d, device pointer %p, size %zu\n", 383330d8983SJohannes Doerfert DeviceNum, Ptr, NumBytes); 384330d8983SJohannes Doerfert 385330d8983SJohannes Doerfert // Behave as a no-op if N==0 or if Ptr is nullptr (as a useful implementation 386330d8983SJohannes Doerfert // of unspecified behavior, see OpenMP spec). 387330d8983SJohannes Doerfert if (!Ptr || NumBytes == 0) { 388330d8983SJohannes Doerfert return Ptr; 389330d8983SJohannes Doerfert } 390330d8983SJohannes Doerfert 391330d8983SJohannes Doerfert if (DeviceNum == omp_get_initial_device()) { 392330d8983SJohannes Doerfert DP("filling memory on host via memset"); 393330d8983SJohannes Doerfert memset(Ptr, ByteVal, NumBytes); // ignore return value, memset() cannot fail 394330d8983SJohannes Doerfert } else { 395330d8983SJohannes Doerfert // TODO: replace the omp_target_memset() slow path with the fast path. 396330d8983SJohannes Doerfert // That will require the ability to execute a kernel from within 397330d8983SJohannes Doerfert // libomptarget.so (which we do not have at the moment). 398330d8983SJohannes Doerfert 399330d8983SJohannes Doerfert // This is a very slow path: create a filled array on the host and upload 400330d8983SJohannes Doerfert // it to the GPU device. 401330d8983SJohannes Doerfert int InitialDevice = omp_get_initial_device(); 402330d8983SJohannes Doerfert void *Shadow = omp_target_alloc(NumBytes, InitialDevice); 403330d8983SJohannes Doerfert if (Shadow) { 404330d8983SJohannes Doerfert (void)memset(Shadow, ByteVal, NumBytes); 405330d8983SJohannes Doerfert (void)omp_target_memcpy(Ptr, Shadow, NumBytes, 0, 0, DeviceNum, 406330d8983SJohannes Doerfert InitialDevice); 407330d8983SJohannes Doerfert (void)omp_target_free(Shadow, InitialDevice); 408330d8983SJohannes Doerfert } else { 409330d8983SJohannes Doerfert // If the omp_target_alloc has failed, let's just not do anything. 410330d8983SJohannes Doerfert // omp_target_memset does not have any good way to fail, so we 411330d8983SJohannes Doerfert // simply avoid a catastrophic failure of the process for now. 412330d8983SJohannes Doerfert DP("omp_target_memset failed to fill memory due to error with " 413330d8983SJohannes Doerfert "omp_target_alloc"); 414330d8983SJohannes Doerfert } 415330d8983SJohannes Doerfert } 416330d8983SJohannes Doerfert 417330d8983SJohannes Doerfert DP("omp_target_memset returns %p\n", Ptr); 418330d8983SJohannes Doerfert return Ptr; 419330d8983SJohannes Doerfert } 420330d8983SJohannes Doerfert 421330d8983SJohannes Doerfert EXTERN void *omp_target_memset_async(void *Ptr, int ByteVal, size_t NumBytes, 422330d8983SJohannes Doerfert int DeviceNum, int DepObjCount, 423330d8983SJohannes Doerfert omp_depend_t *DepObjList) { 424330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 425330d8983SJohannes Doerfert DP("Call to omp_target_memset_async, device %d, device pointer %p, size %zu", 426330d8983SJohannes Doerfert DeviceNum, Ptr, NumBytes); 427330d8983SJohannes Doerfert 428330d8983SJohannes Doerfert // Behave as a no-op if N==0 or if Ptr is nullptr (as a useful implementation 429330d8983SJohannes Doerfert // of unspecified behavior, see OpenMP spec). 430330d8983SJohannes Doerfert if (!Ptr || NumBytes == 0) 431330d8983SJohannes Doerfert return Ptr; 432330d8983SJohannes Doerfert 433330d8983SJohannes Doerfert // Create the task object to deal with the async invocation 434330d8983SJohannes Doerfert auto *Args = new TargetMemsetArgsTy{Ptr, ByteVal, NumBytes, DeviceNum}; 435330d8983SJohannes Doerfert 436330d8983SJohannes Doerfert // omp_target_memset_async() cannot fail via a return code, so ignore the 437330d8983SJohannes Doerfert // return code of the helper function 438330d8983SJohannes Doerfert (void)libomp_helper_task_creation(Args, &libomp_target_memset_async_task, 439330d8983SJohannes Doerfert DepObjCount, DepObjList); 440330d8983SJohannes Doerfert 441330d8983SJohannes Doerfert return Ptr; 442330d8983SJohannes Doerfert } 443330d8983SJohannes Doerfert 444330d8983SJohannes Doerfert EXTERN int omp_target_memcpy_async(void *Dst, const void *Src, size_t Length, 445330d8983SJohannes Doerfert size_t DstOffset, size_t SrcOffset, 446330d8983SJohannes Doerfert int DstDevice, int SrcDevice, 447330d8983SJohannes Doerfert int DepObjCount, omp_depend_t *DepObjList) { 448330d8983SJohannes Doerfert TIMESCOPE_WITH_DETAILS("dst_dev=" + std::to_string(DstDevice) + 449330d8983SJohannes Doerfert ";src_dev=" + std::to_string(SrcDevice) + 450330d8983SJohannes Doerfert ";size=" + std::to_string(Length)); 451330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 452330d8983SJohannes Doerfert DP("Call to omp_target_memcpy_async, dst device %d, src device %d, " 453330d8983SJohannes Doerfert "dst addr " DPxMOD ", src addr " DPxMOD ", dst offset %zu, " 454330d8983SJohannes Doerfert "src offset %zu, length %zu\n", 455330d8983SJohannes Doerfert DstDevice, SrcDevice, DPxPTR(Dst), DPxPTR(Src), DstOffset, SrcOffset, 456330d8983SJohannes Doerfert Length); 457330d8983SJohannes Doerfert 458330d8983SJohannes Doerfert // Check the source and dest address 459330d8983SJohannes Doerfert if (Dst == nullptr || Src == nullptr) 460330d8983SJohannes Doerfert return OFFLOAD_FAIL; 461330d8983SJohannes Doerfert 462330d8983SJohannes Doerfert // Create task object 463330d8983SJohannes Doerfert TargetMemcpyArgsTy *Args = new TargetMemcpyArgsTy( 464330d8983SJohannes Doerfert Dst, Src, Length, DstOffset, SrcOffset, DstDevice, SrcDevice); 465330d8983SJohannes Doerfert 466330d8983SJohannes Doerfert // Create and launch helper task 467330d8983SJohannes Doerfert int Rc = libomp_helper_task_creation(Args, &libomp_target_memcpy_async_task, 468330d8983SJohannes Doerfert DepObjCount, DepObjList); 469330d8983SJohannes Doerfert 470330d8983SJohannes Doerfert DP("omp_target_memcpy_async returns %d\n", Rc); 471330d8983SJohannes Doerfert return Rc; 472330d8983SJohannes Doerfert } 473330d8983SJohannes Doerfert 474330d8983SJohannes Doerfert EXTERN int 475330d8983SJohannes Doerfert omp_target_memcpy_rect(void *Dst, const void *Src, size_t ElementSize, 476330d8983SJohannes Doerfert int NumDims, const size_t *Volume, 477330d8983SJohannes Doerfert const size_t *DstOffsets, const size_t *SrcOffsets, 478330d8983SJohannes Doerfert const size_t *DstDimensions, const size_t *SrcDimensions, 479330d8983SJohannes Doerfert int DstDevice, int SrcDevice) { 480330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 481330d8983SJohannes Doerfert DP("Call to omp_target_memcpy_rect, dst device %d, src device %d, " 482330d8983SJohannes Doerfert "dst addr " DPxMOD ", src addr " DPxMOD ", dst offsets " DPxMOD ", " 483330d8983SJohannes Doerfert "src offsets " DPxMOD ", dst dims " DPxMOD ", src dims " DPxMOD ", " 484330d8983SJohannes Doerfert "volume " DPxMOD ", element size %zu, num_dims %d\n", 485330d8983SJohannes Doerfert DstDevice, SrcDevice, DPxPTR(Dst), DPxPTR(Src), DPxPTR(DstOffsets), 486330d8983SJohannes Doerfert DPxPTR(SrcOffsets), DPxPTR(DstDimensions), DPxPTR(SrcDimensions), 487330d8983SJohannes Doerfert DPxPTR(Volume), ElementSize, NumDims); 488330d8983SJohannes Doerfert 489330d8983SJohannes Doerfert if (!(Dst || Src)) { 490330d8983SJohannes Doerfert DP("Call to omp_target_memcpy_rect returns max supported dimensions %d\n", 491330d8983SJohannes Doerfert INT_MAX); 492330d8983SJohannes Doerfert return INT_MAX; 493330d8983SJohannes Doerfert } 494330d8983SJohannes Doerfert 495330d8983SJohannes Doerfert if (!Dst || !Src || ElementSize < 1 || NumDims < 1 || !Volume || 496330d8983SJohannes Doerfert !DstOffsets || !SrcOffsets || !DstDimensions || !SrcDimensions) { 497330d8983SJohannes Doerfert REPORT("Call to omp_target_memcpy_rect with invalid arguments\n"); 498330d8983SJohannes Doerfert return OFFLOAD_FAIL; 499330d8983SJohannes Doerfert } 500330d8983SJohannes Doerfert 501330d8983SJohannes Doerfert int Rc; 502330d8983SJohannes Doerfert if (NumDims == 1) { 503330d8983SJohannes Doerfert Rc = omp_target_memcpy(Dst, Src, ElementSize * Volume[0], 504330d8983SJohannes Doerfert ElementSize * DstOffsets[0], 505330d8983SJohannes Doerfert ElementSize * SrcOffsets[0], DstDevice, SrcDevice); 506330d8983SJohannes Doerfert } else { 507330d8983SJohannes Doerfert size_t DstSliceSize = ElementSize; 508330d8983SJohannes Doerfert size_t SrcSliceSize = ElementSize; 509330d8983SJohannes Doerfert for (int I = 1; I < NumDims; ++I) { 510330d8983SJohannes Doerfert DstSliceSize *= DstDimensions[I]; 511330d8983SJohannes Doerfert SrcSliceSize *= SrcDimensions[I]; 512330d8983SJohannes Doerfert } 513330d8983SJohannes Doerfert 514330d8983SJohannes Doerfert size_t DstOff = DstOffsets[0] * DstSliceSize; 515330d8983SJohannes Doerfert size_t SrcOff = SrcOffsets[0] * SrcSliceSize; 516330d8983SJohannes Doerfert for (size_t I = 0; I < Volume[0]; ++I) { 517330d8983SJohannes Doerfert Rc = omp_target_memcpy_rect( 518330d8983SJohannes Doerfert (char *)Dst + DstOff + DstSliceSize * I, 519330d8983SJohannes Doerfert (char *)const_cast<void *>(Src) + SrcOff + SrcSliceSize * I, 520330d8983SJohannes Doerfert ElementSize, NumDims - 1, Volume + 1, DstOffsets + 1, SrcOffsets + 1, 521330d8983SJohannes Doerfert DstDimensions + 1, SrcDimensions + 1, DstDevice, SrcDevice); 522330d8983SJohannes Doerfert 523330d8983SJohannes Doerfert if (Rc) { 524330d8983SJohannes Doerfert DP("Recursive call to omp_target_memcpy_rect returns unsuccessfully\n"); 525330d8983SJohannes Doerfert return Rc; 526330d8983SJohannes Doerfert } 527330d8983SJohannes Doerfert } 528330d8983SJohannes Doerfert } 529330d8983SJohannes Doerfert 530330d8983SJohannes Doerfert DP("omp_target_memcpy_rect returns %d\n", Rc); 531330d8983SJohannes Doerfert return Rc; 532330d8983SJohannes Doerfert } 533330d8983SJohannes Doerfert 534330d8983SJohannes Doerfert EXTERN int omp_target_memcpy_rect_async( 535330d8983SJohannes Doerfert void *Dst, const void *Src, size_t ElementSize, int NumDims, 536330d8983SJohannes Doerfert const size_t *Volume, const size_t *DstOffsets, const size_t *SrcOffsets, 537330d8983SJohannes Doerfert const size_t *DstDimensions, const size_t *SrcDimensions, int DstDevice, 538330d8983SJohannes Doerfert int SrcDevice, int DepObjCount, omp_depend_t *DepObjList) { 539330d8983SJohannes Doerfert TIMESCOPE_WITH_DETAILS("dst_dev=" + std::to_string(DstDevice) + 540330d8983SJohannes Doerfert ";src_dev=" + std::to_string(SrcDevice) + 541330d8983SJohannes Doerfert ";size=" + std::to_string(ElementSize) + 542330d8983SJohannes Doerfert ";num_dims=" + std::to_string(NumDims)); 543330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 544330d8983SJohannes Doerfert DP("Call to omp_target_memcpy_rect_async, dst device %d, src device %d, " 545330d8983SJohannes Doerfert "dst addr " DPxMOD ", src addr " DPxMOD ", dst offsets " DPxMOD ", " 546330d8983SJohannes Doerfert "src offsets " DPxMOD ", dst dims " DPxMOD ", src dims " DPxMOD ", " 547330d8983SJohannes Doerfert "volume " DPxMOD ", element size %zu, num_dims %d\n", 548330d8983SJohannes Doerfert DstDevice, SrcDevice, DPxPTR(Dst), DPxPTR(Src), DPxPTR(DstOffsets), 549330d8983SJohannes Doerfert DPxPTR(SrcOffsets), DPxPTR(DstDimensions), DPxPTR(SrcDimensions), 550330d8983SJohannes Doerfert DPxPTR(Volume), ElementSize, NumDims); 551330d8983SJohannes Doerfert 552330d8983SJohannes Doerfert // Need to check this first to not return OFFLOAD_FAIL instead 553330d8983SJohannes Doerfert if (!Dst && !Src) { 554330d8983SJohannes Doerfert DP("Call to omp_target_memcpy_rect returns max supported dimensions %d\n", 555330d8983SJohannes Doerfert INT_MAX); 556330d8983SJohannes Doerfert return INT_MAX; 557330d8983SJohannes Doerfert } 558330d8983SJohannes Doerfert 559330d8983SJohannes Doerfert // Check the source and dest address 560330d8983SJohannes Doerfert if (Dst == nullptr || Src == nullptr) 561330d8983SJohannes Doerfert return OFFLOAD_FAIL; 562330d8983SJohannes Doerfert 563330d8983SJohannes Doerfert // Create task object 564330d8983SJohannes Doerfert TargetMemcpyArgsTy *Args = new TargetMemcpyArgsTy( 565330d8983SJohannes Doerfert Dst, Src, ElementSize, NumDims, Volume, DstOffsets, SrcOffsets, 566330d8983SJohannes Doerfert DstDimensions, SrcDimensions, DstDevice, SrcDevice); 567330d8983SJohannes Doerfert 568330d8983SJohannes Doerfert // Create and launch helper task 569330d8983SJohannes Doerfert int Rc = libomp_helper_task_creation(Args, &libomp_target_memcpy_async_task, 570330d8983SJohannes Doerfert DepObjCount, DepObjList); 571330d8983SJohannes Doerfert 572330d8983SJohannes Doerfert DP("omp_target_memcpy_rect_async returns %d\n", Rc); 573330d8983SJohannes Doerfert return Rc; 574330d8983SJohannes Doerfert } 575330d8983SJohannes Doerfert 576330d8983SJohannes Doerfert EXTERN int omp_target_associate_ptr(const void *HostPtr, const void *DevicePtr, 577330d8983SJohannes Doerfert size_t Size, size_t DeviceOffset, 578330d8983SJohannes Doerfert int DeviceNum) { 579330d8983SJohannes Doerfert TIMESCOPE(); 580330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 581330d8983SJohannes Doerfert DP("Call to omp_target_associate_ptr with host_ptr " DPxMOD ", " 582330d8983SJohannes Doerfert "device_ptr " DPxMOD ", size %zu, device_offset %zu, device_num %d\n", 583330d8983SJohannes Doerfert DPxPTR(HostPtr), DPxPTR(DevicePtr), Size, DeviceOffset, DeviceNum); 584330d8983SJohannes Doerfert 585330d8983SJohannes Doerfert if (!HostPtr || !DevicePtr || Size <= 0) { 586330d8983SJohannes Doerfert REPORT("Call to omp_target_associate_ptr with invalid arguments\n"); 587330d8983SJohannes Doerfert return OFFLOAD_FAIL; 588330d8983SJohannes Doerfert } 589330d8983SJohannes Doerfert 590330d8983SJohannes Doerfert if (DeviceNum == omp_get_initial_device()) { 591330d8983SJohannes Doerfert REPORT("omp_target_associate_ptr: no association possible on the host\n"); 592330d8983SJohannes Doerfert return OFFLOAD_FAIL; 593330d8983SJohannes Doerfert } 594330d8983SJohannes Doerfert 595330d8983SJohannes Doerfert auto DeviceOrErr = PM->getDevice(DeviceNum); 596330d8983SJohannes Doerfert if (!DeviceOrErr) 597330d8983SJohannes Doerfert FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str()); 598330d8983SJohannes Doerfert 599330d8983SJohannes Doerfert void *DeviceAddr = (void *)((uint64_t)DevicePtr + (uint64_t)DeviceOffset); 600*caaf8099SJan Patrick Lehr 601*caaf8099SJan Patrick Lehr OMPT_IF_BUILT(InterfaceRAII( 602*caaf8099SJan Patrick Lehr RegionInterface.getCallbacks<ompt_target_data_associate>(), DeviceNum, 603*caaf8099SJan Patrick Lehr const_cast<void *>(HostPtr), const_cast<void *>(DevicePtr), Size, 604*caaf8099SJan Patrick Lehr __builtin_return_address(0))); 605*caaf8099SJan Patrick Lehr 606330d8983SJohannes Doerfert int Rc = DeviceOrErr->getMappingInfo().associatePtr( 607330d8983SJohannes Doerfert const_cast<void *>(HostPtr), const_cast<void *>(DeviceAddr), Size); 608330d8983SJohannes Doerfert DP("omp_target_associate_ptr returns %d\n", Rc); 609330d8983SJohannes Doerfert return Rc; 610330d8983SJohannes Doerfert } 611330d8983SJohannes Doerfert 612330d8983SJohannes Doerfert EXTERN int omp_target_disassociate_ptr(const void *HostPtr, int DeviceNum) { 613330d8983SJohannes Doerfert TIMESCOPE(); 614330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 615330d8983SJohannes Doerfert DP("Call to omp_target_disassociate_ptr with host_ptr " DPxMOD ", " 616330d8983SJohannes Doerfert "device_num %d\n", 617330d8983SJohannes Doerfert DPxPTR(HostPtr), DeviceNum); 618330d8983SJohannes Doerfert 619330d8983SJohannes Doerfert if (!HostPtr) { 620330d8983SJohannes Doerfert REPORT("Call to omp_target_associate_ptr with invalid host_ptr\n"); 621330d8983SJohannes Doerfert return OFFLOAD_FAIL; 622330d8983SJohannes Doerfert } 623330d8983SJohannes Doerfert 624330d8983SJohannes Doerfert if (DeviceNum == omp_get_initial_device()) { 625330d8983SJohannes Doerfert REPORT( 626330d8983SJohannes Doerfert "omp_target_disassociate_ptr: no association possible on the host\n"); 627330d8983SJohannes Doerfert return OFFLOAD_FAIL; 628330d8983SJohannes Doerfert } 629330d8983SJohannes Doerfert 630330d8983SJohannes Doerfert auto DeviceOrErr = PM->getDevice(DeviceNum); 631330d8983SJohannes Doerfert if (!DeviceOrErr) 632330d8983SJohannes Doerfert FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str()); 633330d8983SJohannes Doerfert 634*caaf8099SJan Patrick Lehr OMPT_IF_BUILT(InterfaceRAII( 635*caaf8099SJan Patrick Lehr RegionInterface.getCallbacks<ompt_target_data_disassociate>(), DeviceNum, 636*caaf8099SJan Patrick Lehr const_cast<void *>(HostPtr), 637*caaf8099SJan Patrick Lehr /*DevicePtr=*/nullptr, /*Size=*/0, __builtin_return_address(0))); 638*caaf8099SJan Patrick Lehr 639330d8983SJohannes Doerfert int Rc = DeviceOrErr->getMappingInfo().disassociatePtr( 640330d8983SJohannes Doerfert const_cast<void *>(HostPtr)); 641330d8983SJohannes Doerfert DP("omp_target_disassociate_ptr returns %d\n", Rc); 642330d8983SJohannes Doerfert return Rc; 643330d8983SJohannes Doerfert } 644330d8983SJohannes Doerfert 645330d8983SJohannes Doerfert EXTERN void *omp_get_mapped_ptr(const void *Ptr, int DeviceNum) { 646330d8983SJohannes Doerfert TIMESCOPE(); 647330d8983SJohannes Doerfert OMPT_IF_BUILT(ReturnAddressSetterRAII RA(__builtin_return_address(0))); 648330d8983SJohannes Doerfert DP("Call to omp_get_mapped_ptr with ptr " DPxMOD ", device_num %d.\n", 649330d8983SJohannes Doerfert DPxPTR(Ptr), DeviceNum); 650330d8983SJohannes Doerfert 651330d8983SJohannes Doerfert if (!Ptr) { 652330d8983SJohannes Doerfert REPORT("Call to omp_get_mapped_ptr with nullptr.\n"); 653330d8983SJohannes Doerfert return nullptr; 654330d8983SJohannes Doerfert } 655330d8983SJohannes Doerfert 65681d20d86SJoseph Huber int NumDevices = omp_get_initial_device(); 657330d8983SJohannes Doerfert if (DeviceNum == NumDevices) { 658330d8983SJohannes Doerfert DP("Device %d is initial device, returning Ptr " DPxMOD ".\n", 659330d8983SJohannes Doerfert DeviceNum, DPxPTR(Ptr)); 660330d8983SJohannes Doerfert return const_cast<void *>(Ptr); 661330d8983SJohannes Doerfert } 662330d8983SJohannes Doerfert 663330d8983SJohannes Doerfert if (NumDevices <= DeviceNum) { 664330d8983SJohannes Doerfert DP("DeviceNum %d is invalid, returning nullptr.\n", DeviceNum); 665330d8983SJohannes Doerfert return nullptr; 666330d8983SJohannes Doerfert } 667330d8983SJohannes Doerfert 668330d8983SJohannes Doerfert auto DeviceOrErr = PM->getDevice(DeviceNum); 669330d8983SJohannes Doerfert if (!DeviceOrErr) 670330d8983SJohannes Doerfert FATAL_MESSAGE(DeviceNum, "%s", toString(DeviceOrErr.takeError()).c_str()); 671330d8983SJohannes Doerfert 672330d8983SJohannes Doerfert TargetPointerResultTy TPR = 673330d8983SJohannes Doerfert DeviceOrErr->getMappingInfo().getTgtPtrBegin(const_cast<void *>(Ptr), 1, 674330d8983SJohannes Doerfert /*UpdateRefCount=*/false, 675330d8983SJohannes Doerfert /*UseHoldRefCount=*/false); 676330d8983SJohannes Doerfert if (!TPR.isPresent()) { 677330d8983SJohannes Doerfert DP("Ptr " DPxMOD "is not present on device %d, returning nullptr.\n", 678330d8983SJohannes Doerfert DPxPTR(Ptr), DeviceNum); 679330d8983SJohannes Doerfert return nullptr; 680330d8983SJohannes Doerfert } 681330d8983SJohannes Doerfert 682330d8983SJohannes Doerfert DP("omp_get_mapped_ptr returns " DPxMOD ".\n", DPxPTR(TPR.TargetPointer)); 683330d8983SJohannes Doerfert 684330d8983SJohannes Doerfert return TPR.TargetPointer; 685330d8983SJohannes Doerfert } 686