From 8d2f4ddfd70f2ad9829cdc404e9c382f6fc9b072 Mon Sep 17 00:00:00 2001 From: Julian Brown Date: Wed, 20 Nov 2019 17:53:31 +0000 Subject: [PATCH] Fix host-to-device copies from rodata for AMD GCN libgomp/ * plugin/plugin-gcn.c (hsa_memory_copy_wrapper): New. (copy_data, GOMP_OFFLOAD_host2dev): Use above function. (GOMP_OFFLOAD_dev2host, GOMP_OFFLOAD_dev2dev): Check hsa_memory_copy return code. Reviewed-by: Andrew Stubbs From-SVN: r278516 --- libgomp/ChangeLog | 7 +++++++ libgomp/plugin/plugin-gcn.c | 38 +++++++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 9d4a34c90a3..eb51462bb3f 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,10 @@ +2019-11-20 Julian Brown + + * plugin/plugin-gcn.c (hsa_memory_copy_wrapper): New. + (copy_data, GOMP_OFFLOAD_host2dev): Use above function. + (GOMP_OFFLOAD_dev2host, GOMP_OFFLOAD_dev2dev): Check hsa_memory_copy + return code. + 2019-11-20 Julian Brown PR libgomp/92511 diff --git a/libgomp/plugin/plugin-gcn.c b/libgomp/plugin/plugin-gcn.c index 583916759a5..392a0eeca95 100644 --- a/libgomp/plugin/plugin-gcn.c +++ b/libgomp/plugin/plugin-gcn.c @@ -2940,6 +2940,32 @@ maybe_init_omp_async (struct agent_info *agent) = GOMP_OFFLOAD_openacc_async_construct (agent->device_id); } +/* A wrapper that works around an issue in the HSA runtime with host-to-device + copies from read-only pages. */ + +static void +hsa_memory_copy_wrapper (void *dst, const void *src, size_t len) +{ + hsa_status_t status = hsa_fns.hsa_memory_copy_fn (dst, src, len); + + if (status == HSA_STATUS_SUCCESS) + return; + + /* It appears that the copy fails if the source data is in a read-only page. + We can't detect that easily, so try copying the data to a temporary buffer + and doing the copy again if we got an error above. */ + + GCN_WARNING ("Read-only data transfer bug workaround triggered for " + "[%p:+%d]\n", (void *) src, (int) len); + + void *src_copy = malloc (len); + memcpy (src_copy, src, len); + status = hsa_fns.hsa_memory_copy_fn (dst, (const void *) src_copy, len); + free (src_copy); + if (status != HSA_STATUS_SUCCESS) + GOMP_PLUGIN_error ("memory copy failed"); +} + /* Copy data to or from a device. This is intended for use as an async callback event. */ @@ -2950,7 +2976,7 @@ copy_data (void *data_) GCN_DEBUG ("Async thread %d:%d: Copying %zu bytes from (%p) to (%p)\n", data->aq->agent->device_id, data->aq->id, data->len, data->src, data->dst); - hsa_fns.hsa_memory_copy_fn (data->dst, data->src, data->len); + hsa_memory_copy_wrapper (data->dst, data->src, data->len); if (data->free_src) free ((void *) data->src); free (data); @@ -3643,7 +3669,9 @@ GOMP_OFFLOAD_dev2host (int device, void *dst, const void *src, size_t n) { GCN_DEBUG ("Copying %zu bytes from device %d (%p) to host (%p)\n", n, device, src, dst); - hsa_fns.hsa_memory_copy_fn (dst, src, n); + hsa_status_t status = hsa_fns.hsa_memory_copy_fn (dst, src, n); + if (status != HSA_STATUS_SUCCESS) + GOMP_PLUGIN_error ("memory copy failed"); return true; } @@ -3654,7 +3682,7 @@ GOMP_OFFLOAD_host2dev (int device, void *dst, const void *src, size_t n) { GCN_DEBUG ("Copying %zu bytes from host (%p) to device %d (%p)\n", n, src, device, dst); - hsa_fns.hsa_memory_copy_fn (dst, src, n); + hsa_memory_copy_wrapper (dst, src, n); return true; } @@ -3675,7 +3703,9 @@ GOMP_OFFLOAD_dev2dev (int device, void *dst, const void *src, size_t n) GCN_DEBUG ("Copying %zu bytes from device %d (%p) to device %d (%p)\n", n, device, src, device, dst); - hsa_fns.hsa_memory_copy_fn (dst, src, n); + hsa_status_t status = hsa_fns.hsa_memory_copy_fn (dst, src, n); + if (status != HSA_STATUS_SUCCESS) + GOMP_PLUGIN_error ("memory copy failed"); return true; } -- 2.30.2