Index: libomptarget/include/omptarget.h =================================================================== --- libomptarget/include/omptarget.h +++ libomptarget/include/omptarget.h @@ -47,6 +47,8 @@ OMP_TGT_MAPTYPE_LITERAL = 0x100, // mapping is implicit OMP_TGT_MAPTYPE_IMPLICIT = 0x200, + // copy data to device + OMP_TGT_MAPTYPE_CLOSE = 0x400, // member of struct, member given by [16 MSBs] - 1 OMP_TGT_MAPTYPE_MEMBER_OF = 0xffff000000000000 }; Index: libomptarget/src/omptarget.cpp =================================================================== --- libomptarget/src/omptarget.cpp +++ libomptarget/src/omptarget.cpp @@ -244,9 +244,14 @@ bool IsNew, Pointer_IsNew; bool IsHostPtr = false; bool IsImplicit = arg_types[i] & OMP_TGT_MAPTYPE_IMPLICIT; - // TODO: Check if this is correct - bool IsInUseDevicePtrClause = arg_types[i] & OMP_TGT_MAPTYPE_TARGET_PARAM && - arg_types[i] & OMP_TGT_MAPTYPE_RETURN_PARAM; + // TODO: Check if the use_device_ptr condition is correct + // Force the creation of a device side copy of the data when: + // - a use_device_ptr() was explicitely used by the user OR + // - a close map modifier was associated with a map that contained a to. + bool IsInUseDevicePtrClause = + (arg_types[i] & OMP_TGT_MAPTYPE_TARGET_PARAM && + arg_types[i] & OMP_TGT_MAPTYPE_RETURN_PARAM) || + arg_types[i] & OMP_TGT_MAPTYPE_CLOSE; // UpdateRef is based on MEMBER_OF instead of TARGET_PARAM because if we // have reached this point via __tgt_target_data_begin and not __tgt_target // then no argument is marked as TARGET_PARAM ("omp target data map" is not @@ -296,8 +301,11 @@ if (arg_types[i] & OMP_TGT_MAPTYPE_TO) { bool copy = false; - if (!(Device.RTLRequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY)) { - if (IsNew || (arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS)) { + bool Close = arg_types[i] & OMP_TGT_MAPTYPE_CLOSE; + if (!(Device.RTLRequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) || + (Device.RTLRequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY && + Close)) { + if (IsNew || (arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS) || Close) { copy = true; } else if (arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) { // Copy data only if the "parent" struct has RefCount==1. @@ -377,8 +385,10 @@ (arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ); bool ForceDelete = arg_types[i] & OMP_TGT_MAPTYPE_DELETE; // TODO: Check if this is correct - bool IsInUseDevicePtrClause = arg_types[i] & OMP_TGT_MAPTYPE_TARGET_PARAM && - arg_types[i] & OMP_TGT_MAPTYPE_RETURN_PARAM; + bool IsInUseDevicePtrClause = + (arg_types[i] & OMP_TGT_MAPTYPE_TARGET_PARAM && + arg_types[i] & OMP_TGT_MAPTYPE_RETURN_PARAM) || + arg_types[i] & OMP_TGT_MAPTYPE_CLOSE; // If PTR_AND_OBJ, HstPtrBegin is address of pointee void *TgtPtrBegin = Device.getTgtPtrBegin(HstPtrBegin, data_size, IsLast, @@ -398,8 +408,11 @@ // Move data back to the host if (arg_types[i] & OMP_TGT_MAPTYPE_FROM) { bool Always = arg_types[i] & OMP_TGT_MAPTYPE_ALWAYS; + bool Close = arg_types[i] & OMP_TGT_MAPTYPE_CLOSE; bool CopyMember = false; - if (!(Device.RTLRequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY)) { + if (!(Device.RTLRequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY) || + (Device.RTLRequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY && + Close)) { if ((arg_types[i] & OMP_TGT_MAPTYPE_MEMBER_OF) && !(arg_types[i] & OMP_TGT_MAPTYPE_PTR_AND_OBJ)) { // Copy data only if the "parent" struct has RefCount==1. @@ -412,12 +425,13 @@ } } - if (DelEntry || Always || CopyMember) { + if (DelEntry || Always || CopyMember || Close) { DP("Moving %" PRId64 " bytes (tgt:" DPxMOD ") -> (hst:" DPxMOD ")\n", data_size, DPxPTR(TgtPtrBegin), DPxPTR(HstPtrBegin)); int rt; if (Device.RTLRequiresFlags & OMP_REQ_UNIFIED_SHARED_MEMORY && - TgtPtrBegin == HstPtrBegin) + TgtPtrBegin == HstPtrBegin && + !Close) rt = OFFLOAD_SUCCESS; else rt = Device.data_retrieve(HstPtrBegin, TgtPtrBegin, data_size); Index: libomptarget/test/offloading/requires_unified_shared_memory_close.c =================================================================== --- /dev/null +++ libomptarget/test/offloading/requires_unified_shared_memory_close.c @@ -0,0 +1,131 @@ +// RUN: %libomptarget-compile-run-and-check-aarch64-unknown-linux-gnu +// RUN: %libomptarget-compile-run-and-check-powerpc64-ibm-linux-gnu +// RUN: %libomptarget-compile-run-and-check-powerpc64le-ibm-linux-gnu +// RUN: %libomptarget-compile-run-and-check-x86_64-pc-linux-gnu + +#include +#include + +#pragma omp requires unified_shared_memory + +#define N 1024 + +int main(int argc, char *argv[]) { + int fails; + long long host_alloc, device_alloc; + long long host_data, device_data; + double *alloc = (double *)malloc(N*sizeof(double)); + double data[N]; + + for(int i=0; i