libgomp: Fix reverse offload issues If there is nothing to map, skip the mapping and attempting to copy addrs, sizes and kinds which may have issues for size = 0. Additionally, it could happen that a non-allocated address was deallocated, e.g. a pointer set - such that there was a double free for the actual data or in multiple other ways. libgomp/ * target.c (gomp_target_rev): Handle mapnum == 0 and avoid freeing not allocated memory. * testsuite/libgomp.fortran/reverse-offload-6.f90: New test. libgomp/target.c | 8 +++--- .../libgomp.fortran/reverse-offload-6.f90 | 32 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/libgomp/target.c b/libgomp/target.c index b16ee761a95..c1682caea13 100644 --- a/libgomp/target.c +++ b/libgomp/target.c @@ -3324,7 +3324,7 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr, gomp_fatal ("Cannot find reverse-offload function"); void (*host_fn)() = (void (*)()) n->k->host_start; - if (devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM) + if ((devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM) || mapnum == 0) { devaddrs = (uint64_t *) (uintptr_t) devaddrs_ptr; sizes = (uint64_t *) (uintptr_t) sizes_ptr; @@ -3402,7 +3402,7 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr, } } - if (!(devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)) + if (!(devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM) && mapnum > 0) { size_t j, struct_cpy = 0; splay_tree_key n2; @@ -3638,7 +3638,7 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr, host_fn (devaddrs); - if (!(devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM)) + if (!(devicep->capabilities & GOMP_OFFLOAD_CAP_SHARED_MEM) && mapnum > 0) { uint64_t struct_cpy = 0; bool clean_struct = false; @@ -3680,7 +3680,7 @@ gomp_target_rev (uint64_t fn_ptr, uint64_t mapnum, uint64_t devaddrs_ptr, clean_struct = true; struct_cpy = sizes[i]; } - else if (cdata[i].aligned) + else if (!cdata[i].present && cdata[i].aligned) gomp_aligned_free ((void *) (uintptr_t) devaddrs[i]); else if (!cdata[i].present) free ((void *) (uintptr_t) devaddrs[i]); diff --git a/libgomp/testsuite/libgomp.fortran/reverse-offload-6.f90 b/libgomp/testsuite/libgomp.fortran/reverse-offload-6.f90 new file mode 100644 index 00000000000..04866edbba7 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/reverse-offload-6.f90 @@ -0,0 +1,32 @@ +! +! Ensure that a mapping with no argument works +! + +module m + implicit none (type, external) + integer :: x = 32 + integer :: dev_num2 = -1 +contains +subroutine foo() + use omp_lib, only: omp_get_device_num + x = x + 10 + dev_num2 = omp_get_device_num() +end +end module m + +use m +use omp_lib +!$omp requires reverse_offload +implicit none (type, external) +integer :: dev_num = -1 +!$omp target map(from:dev_num) + dev_num = omp_get_device_num() + ! This calls GOMP_target_ext with number of maps = 0 + !$omp target device(ancestor:1) + call foo + !$omp end target +!$omp end target + +if (omp_get_num_devices() > 0 .and. dev_num2 == dev_num) stop 1 +if (x /= 42) stop 2 +end