diff options
author | Julian Brown <julian@codesourcery.com> | 2020-06-18 05:11:08 -0700 |
---|---|---|
committer | Julian Brown <julian@codesourcery.com> | 2020-07-27 09:16:57 -0700 |
commit | bc4ed079dc09a62168699227a794ac52a5b6f6a4 (patch) | |
tree | 48c5dac67ba13e457724af37f8cec35501cf3d2e /libgomp/oacc-mem.c | |
parent | 2251b4a5423efa8ee0d7e67537b63e404a1f6afa (diff) | |
download | gcc-bc4ed079dc09a62168699227a794ac52a5b6f6a4.zip gcc-bc4ed079dc09a62168699227a794ac52a5b6f6a4.tar.gz gcc-bc4ed079dc09a62168699227a794ac52a5b6f6a4.tar.bz2 |
openacc: Deep copy attach/detach should not affect reference counts
Attach and detach operations are not supposed to affect structural or
dynamic reference counts for OpenACC. Previously they did so, which led to
subtle problems in some circumstances. We can avoid reference-counting
attach/detach operations by extending and slightly repurposing the
do_detach field in target_var_desc. It is now called is_attach to better
reflect its new role.
2020-07-27 Julian Brown <julian@codesourcery.com>
Thomas Schwinge <thomas@codesourcery.com>
libgomp/
* libgomp.h (struct target_var_desc): Rename do_detach field to
is_attach.
* oacc-mem.c (goacc_exit_datum_1): Add assert. Don't set finalize for
GOMP_MAP_FORCE_DETACH. Update checking to use is_attach field.
(goacc_enter_data_internal): Don't affect reference counts
for attach mappings.
(goacc_exit_data_internal): Don't affect reference counts for detach
mappings.
* target.c (gomp_map_vars_existing): Don't affect reference counts for
attach mappings.
(gomp_map_vars_internal): Set renamed is_attach flag unconditionally to
mark attach mappings.
(gomp_unmap_vars_internal): Use is_attach flag to prevent affecting
reference count for attach mappings.
* testsuite/libgomp.oacc-c-c++-common/mdc-refcount-1.c: New test.
* testsuite/libgomp.oacc-c-c++-common/mdc-refcount-2.c: New test.
* testsuite/libgomp.oacc-c-c++-common/mdc-refcount-2.c: New test.
* testsuite/libgomp.oacc-fortran/deep-copy-6-no_finalize.F90: Mark
test as shouldfail.
* testsuite/libgomp.oacc-fortran/deep-copy-6.f90: Adjust to fail
gracefully in no-finalize mode.
Co-Authored-By: Thomas Schwinge <thomas@codesourcery.com>
Diffstat (limited to 'libgomp/oacc-mem.c')
-rw-r--r-- | libgomp/oacc-mem.c | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/libgomp/oacc-mem.c b/libgomp/oacc-mem.c index 855cad8..65757ab 100644 --- a/libgomp/oacc-mem.c +++ b/libgomp/oacc-mem.c @@ -667,6 +667,9 @@ static void goacc_exit_datum_1 (struct gomp_device_descr *acc_dev, void *h, size_t s, unsigned short kind, splay_tree_key n, goacc_aq aq) { + assert (kind != GOMP_MAP_DETACH + && kind != GOMP_MAP_FORCE_DETACH); + if ((uintptr_t) h < n->host_start || (uintptr_t) h + s > n->host_end) { size_t host_size = n->host_end - n->host_start; @@ -676,8 +679,7 @@ goacc_exit_datum_1 (struct gomp_device_descr *acc_dev, void *h, size_t s, } bool finalize = (kind == GOMP_MAP_FORCE_FROM - || kind == GOMP_MAP_DELETE - || kind == GOMP_MAP_FORCE_DETACH); + || kind == GOMP_MAP_DELETE); assert (n->refcount != REFCOUNT_LINK); if (n->refcount != REFCOUNT_INFINITY @@ -725,7 +727,8 @@ goacc_exit_datum_1 (struct gomp_device_descr *acc_dev, void *h, size_t s, zero. Otherwise (e.g. for a 'GOMP_MAP_STRUCT' mapping with multiple members), fall back to skipping the test. */ for (size_t l_i = 0; l_i < n->tgt->list_count; ++l_i) - if (n->tgt->list[l_i].key) + if (n->tgt->list[l_i].key + && !n->tgt->list[l_i].is_attach) ++num_mappings; bool is_tgt_unmapped = gomp_remove_var (acc_dev, n); assert (is_tgt_unmapped || num_mappings > 1); @@ -1135,12 +1138,15 @@ goacc_enter_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum, void *h = hostaddrs[i]; size_t s = sizes[i]; - /* A standalone attach clause. */ if ((kinds[i] & 0xff) == GOMP_MAP_ATTACH) - gomp_attach_pointer (acc_dev, aq, &acc_dev->mem_map, n, - (uintptr_t) h, s, NULL); - - goacc_map_var_existing (acc_dev, h, s, n); + { + gomp_attach_pointer (acc_dev, aq, &acc_dev->mem_map, n, + (uintptr_t) h, s, NULL); + /* OpenACC 'attach'/'detach' doesn't affect structured/dynamic + reference counts ('n->refcount', 'n->dynamic_refcount'). */ + } + else + goacc_map_var_existing (acc_dev, h, s, n); } else if (n && groupnum > 1) { @@ -1168,7 +1174,9 @@ goacc_enter_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum, list, and increment the refcounts for each item in that group. */ for (size_t k = 0; k < groupnum; k++) - if (j + k < tgt->list_count && tgt->list[j + k].key) + if (j + k < tgt->list_count + && tgt->list[j + k].key + && !tgt->list[j + k].is_attach) { tgt->list[j + k].key->refcount++; tgt->list[j + k].key->dynamic_refcount++; @@ -1202,7 +1210,7 @@ goacc_enter_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum, for (size_t j = 0; j < tgt->list_count; j++) { n = tgt->list[j].key; - if (n) + if (n && !tgt->list[j].is_attach) n->dynamic_refcount++; } } @@ -1268,14 +1276,10 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum, case GOMP_MAP_POINTER: case GOMP_MAP_DELETE: case GOMP_MAP_RELEASE: - case GOMP_MAP_DETACH: - case GOMP_MAP_FORCE_DETACH: { struct splay_tree_key_s cur_node; size_t size; - if (kind == GOMP_MAP_POINTER - || kind == GOMP_MAP_DETACH - || kind == GOMP_MAP_FORCE_DETACH) + if (kind == GOMP_MAP_POINTER) size = sizeof (void *); else size = sizes[i]; @@ -1298,6 +1302,12 @@ goacc_exit_data_internal (struct gomp_device_descr *acc_dev, size_t mapnum, 'GOMP_MAP_STRUCT's anymore. */ break; + case GOMP_MAP_DETACH: + case GOMP_MAP_FORCE_DETACH: + /* OpenACC 'attach'/'detach' doesn't affect structured/dynamic + reference counts ('n->refcount', 'n->dynamic_refcount'). */ + break; + default: gomp_fatal (">>>> goacc_exit_data_internal UNHANDLED kind 0x%.2x", kind); |