On Fri, Dec 11, 2015 at 18:27:13 +0100, Jakub Jelinek wrote:
> On Tue, Dec 08, 2015 at 05:45:59PM +0300, Ilya Verbin wrote:
> > --- a/libgomp/oacc-init.c
> > +++ b/libgomp/oacc-init.c
> > @@ -306,10 +306,11 @@ acc_shutdown_1 (acc_device_t d)
> > {
> > struct gomp_device_descr *acc_dev = &base_dev[i];
> > gomp_mutex_lock (&acc_dev->lock);
> > - if (acc_dev->is_initialized)
> > + if (acc_dev->state == GOMP_DEVICE_INITIALIZED)
> > {
> > devices_active = true;
> > - gomp_fini_device (acc_dev);
> > + acc_dev->fini_device_func (acc_dev->target_id);
> > + acc_dev->state = GOMP_DEVICE_UNINITIALIZED;
> > }
> > gomp_mutex_unlock (&acc_dev->lock);
> > }
>
> I'd bet you want to set state here to GOMP_DEVICE_FINALIZED too,
> but I'd leave that to the OpenACC folks to do that incrementally
> once they test it and/or decide what to do.
libgomp/testsuite/libgomp.oacc-c-c++-common/lib-5.c contains a call to acc_init,
next acc_shutdown, and acc_init again, so I guess that OpenACC allows to
initialize the device again after acc_shutdown, but GOMP_DEVICE_FINALIZED means
that it's terminally finalized.
> > @@ -356,6 +361,11 @@ gomp_map_vars (struct gomp_device_descr *devicep,
> > size_t mapnum,
> > }
> >
> > gomp_mutex_lock (&devicep->lock);
> > + if (devicep->state == GOMP_DEVICE_FINALIZED)
> > + {
> > + gomp_mutex_unlock (&devicep->lock);
>
> You need to free (tgt); here I think to avoid leaking memory.
>
> > + return NULL;
> > + }
> >
> > for (i = 0; i < mapnum; i++)
> > {
> > @@ -834,6 +844,11 @@ gomp_unmap_vars (struct target_mem_desc *tgt, bool
> > do_copyfrom)
> > }
> >
> > gomp_mutex_lock (&devicep->lock);
> > + if (devicep->state == GOMP_DEVICE_FINALIZED)
> > + {
> > + gomp_mutex_unlock (&devicep->lock);
> > + return;
>
> Supposedly you want at least free (tgt->array); free (tgt); here.
> Plus the question is if the mappings shouldn't be removed from the splay tree
> before that.
>
> > +/* This function finalizes all initialized devices. */
> > +
> > +static void
> > +gomp_target_fini (void)
> > +{
> > + int i;
> > + for (i = 0; i < num_devices; i++)
> > + {
> > + struct gomp_device_descr *devicep = &devices[i];
> > + gomp_mutex_lock (&devicep->lock);
> > + if (devicep->state == GOMP_DEVICE_INITIALIZED)
> > + {
> > + devicep->fini_device_func (devicep->target_id);
> > + devicep->state = GOMP_DEVICE_FINALIZED;
> > + }
> > + gomp_mutex_unlock (&devicep->lock);
> > + }
> > +}
>
> The question is what will this do if there are async target tasks still
> running on some of the devices at this point (forgotten #pragma omp taskwait
> or similar if target nowait regions are started outside of parallel region,
> or exit inside of parallel, etc. But perhaps it can be handled incrementally.
> Also there is the question that the
> So I think the patch is ok with the above mentioned changes.
>
> What is the state of the link clause implementation patch? Does it depend
> on this?
It's ready, but it depends on this. I will retest and resend "link" patch after
checking-in "init/fini" patch.
-- Ilya