gcc/libgomp/testsuite/libgomp.oacc-c-c++-common/mdc-refcount-2.c
Julian Brown bc4ed079dc 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>
2020-07-27 09:16:57 -07:00

123 lines
2.7 KiB
C

/* Verify that OpenACC 'attach'/'detach' doesn't interfere with reference
counting. */
#include <assert.h>
#include <stdlib.h>
#include <openacc.h>
/* Need to shared this (and, in particular, implicit '&data_work' in
'attach'/'detach' clauses) between 'test' and 'test_'. */
static unsigned char *data_work;
static void test_(unsigned variant,
unsigned char *data,
void *data_d)
{
assert(acc_is_present(&data_work, sizeof data_work));
assert(data_work == data);
acc_update_self(&data_work, sizeof data_work);
assert(data_work == data);
if (variant & 1)
{
#pragma acc enter data attach(data_work)
}
else
acc_attach((void **) &data_work);
acc_update_self(&data_work, sizeof data_work);
assert(data_work == data_d);
if (variant & 4)
{
if (variant & 2)
{ // attach some more
data_work = data;
acc_attach((void **) &data_work);
#pragma acc enter data attach(data_work)
acc_attach((void **) &data_work);
#pragma acc enter data attach(data_work)
#pragma acc enter data attach(data_work)
#pragma acc enter data attach(data_work)
acc_attach((void **) &data_work);
acc_attach((void **) &data_work);
#pragma acc enter data attach(data_work)
}
else
{}
}
else
{ // detach
data_work = data;
if (variant & 2)
{
#pragma acc exit data detach(data_work)
}
else
acc_detach((void **) &data_work);
acc_update_self(&data_work, sizeof data_work);
assert(data_work == data);
// now not attached anymore
#if 0
if (TODO)
{
acc_detach(&data_work); //TODO PR95203 "libgomp: attach count underflow"
acc_update_self(&data_work, sizeof data_work);
assert(data_work == data);
}
#endif
}
assert(acc_is_present(&data_work, sizeof data_work));
}
static void test(unsigned variant)
{
const int size = sizeof (void *);
unsigned char *data = (unsigned char *) malloc(size);
assert(data);
void *data_d = acc_create(data, size);
assert(data_d);
assert(acc_is_present(data, size));
data_work = data;
if (variant & 8)
{
#pragma acc data copyin(data_work)
test_(variant, data, data_d);
}
else
{
acc_copyin(&data_work, sizeof data_work);
test_(variant, data, data_d);
acc_delete(&data_work, sizeof data_work);
}
#if ACC_MEM_SHARED
assert(acc_is_present(&data_work, sizeof data_work));
#else
assert(!acc_is_present(&data_work, sizeof data_work));
#endif
data_work = NULL;
assert(acc_is_present(data, size));
acc_delete(data, size);
data_d = NULL;
#if ACC_MEM_SHARED
assert(acc_is_present(data, size));
#else
assert(!acc_is_present(data, size));
#endif
free(data);
data = NULL;
}
int main()
{
for (size_t i = 0; i < 16; ++i)
test(i);
return 0;
}