On Wed, Jul 29, 2015 at 10:06:52PM +0300, Ilya Verbin wrote:
> @@ -1241,6 +1245,62 @@ GOMP_target_update (int device, const void *unused,
> size_t mapnum,
> gomp_update (devicep, mapnum, hostaddrs, sizes, kinds, false);
> }
>
> +static void
> +gomp_exit_data (struct gomp_device_descr *devicep, size_t mapnum,
> + void **hostaddrs, size_t *sizes, unsigned short *kinds)
> +{
> + const int typemask = 0xff;
> + size_t i;
> + gomp_mutex_lock (&devicep->lock);
> + for (i = 0; i < mapnum; i++)
> + {
> + struct splay_tree_key_s cur_node;
> + unsigned char kind = kinds[i] & typemask;
> + switch (kind)
> + {
> + case GOMP_MAP_FROM:
> + case GOMP_MAP_ALWAYS_FROM:
> + case GOMP_MAP_DELETE:
> + case GOMP_MAP_RELEASE:
Please handle here GOMP_MAP_ZERO_LEN_ARRAY_SECTION too.
It should use gomp_map_lookup (while all others splay_tree_lookup),
otherwise it is the same as GOMP_MAP_RELEASE.
> @@ -1280,13 +1337,20 @@ GOMP_target_enter_exit_data (int device, size_t
> mapnum, void **hostaddrs,
> }
>
> if (is_enter_data)
> - {
> - /* TODO */
> - }
> + for (i = 0; i < mapnum; i++)
> + {
> + struct target_mem_desc *tgt_var
> + = gomp_map_vars (devicep, 1, &hostaddrs[i], NULL, &sizes[i],
> + &kinds[i], true, false);
> + tgt_var->refcount--;
> +
> + /* If the variable was already mapped, tgt_var is not needed. Otherwise
> + tgt_var will be freed by gomp_unmap_vars or gomp_exit_data. */
> + if (tgt_var->refcount == 0)
> + free (tgt_var);
This is racy, you don't hold the device lock here anymore, so you shouldn't
decrease refcounts or test it etc.
I think better would be to change the bool is_target argument to
gomp_map_vars into an enum, and use 3 values there for now
- GOMP_VARS_MAP_TARGET, GOMP_VARS_MAP_DATA, GOMP_VARS_MAP_ENTER_DATA or so,
and for GOMP_VARS_MAP_ENTER_DATA perform the decrement of refcount and
freeing if it is zero (but then also better return NULL).
> diff --git a/libgomp/testsuite/libgomp.c/target-20.c
> b/libgomp/testsuite/libgomp.c/target-20.c
> new file mode 100644
> index 0000000..ec7e245
> --- /dev/null
> +++ b/libgomp/testsuite/libgomp.c/target-20.c
> @@ -0,0 +1,111 @@
> +/* { dg-require-effective-target offload_device } */
This test will fail on HSA, you don't assume just that it doesn't
fallback to host, but also non-shared address space.
I think it would be better to start with some check for non-shared address
space, like:
/* This test relies on non-shared address space. Punt otherwise. */
void ensure_nonshared_as (void)
{
int a = 8;
#pragma omp target map(to:a)
{
a++;
}
if (a == 8)
exit (0);
}
And generally, it is better to have most of the tests not relying on
offloading only or even non-shared address space, so that we also test
shared address space and host fallback. But a few tests won't hurt...
Jakub