@@ -78,6 +78,10 @@ static int num_devices;
/* Number of GOMP_OFFLOAD_CAP_OPENMP_400 devices. */
static int num_devices_openmp;
+/* True when offloading runtime is finalized. */
+static bool finalized;
+
+
/* Similar to gomp_realloc, but release register_lock before gomp_fatal. */
static void *
@@ -108,6 +112,9 @@ gomp_get_num_devices (void)
static struct gomp_device_descr *
resolve_device (int device_id)
{
+ if (finalized)
+ return NULL;
+
if (device_id == GOMP_DEVICE_ICV)
{
struct gomp_task_icv *icv = gomp_icv (false);
@@ -1095,6 +1102,9 @@ GOMP_offload_register_ver (unsigned version, const void *host_table,
{
int i;
+ if (finalized)
+ return;
+
if (GOMP_VERSION_LIB (version) > GOMP_VERSION)
gomp_fatal ("Library too old for offload (version %u < %u)",
GOMP_VERSION, GOMP_VERSION_LIB (version));
@@ -1143,6 +1153,9 @@ GOMP_offload_unregister_ver (unsigned version, const void *host_table,
{
int i;
+ if (finalized)
+ return;
+
gomp_mutex_lock (®ister_lock);
/* Unload image from all initialized devices. */
@@ -2282,6 +2295,24 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device,
return 0;
}
+/* This function finalizes the runtime needed for offloading and all initialized
+ devices. */
+
+static void
+gomp_target_fini (void)
+{
+ finalized = true;
+
+ int i;
+ for (i = 0; i < num_devices; i++)
+ {
+ struct gomp_device_descr *devicep = &devices[i];
+ gomp_mutex_lock (&devicep->lock);
+ gomp_fini_device (devicep);
+ gomp_mutex_unlock (&devicep->lock);
+ }
+}
+
/* This function initializes the runtime needed for offloading.
It parses the list of offload targets and tries to load the plugins for
these targets. On return, the variables NUM_DEVICES and NUM_DEVICES_OPENMP
@@ -2387,6 +2418,9 @@ gomp_target_init (void)
if (devices[i].capabilities & GOMP_OFFLOAD_CAP_OPENACC_200)
goacc_register (&devices[i]);
}
+
+ if (atexit (gomp_target_fini) != 0)
+ gomp_fatal ("atexit failed");
}
#else /* PLUGIN_SUPPORT */
@@ -231,12 +231,6 @@ offload (const char *file, uint64_t line, int device, const char *name,
}
static void
-unregister_main_image ()
-{
- __offload_unregister_image (&main_target_image);
-}
-
-static void
register_main_image ()
{
/* Do not check the return value, because old versions of liboffloadmic did
@@ -246,12 +240,6 @@ register_main_image ()
/* liboffloadmic will call GOMP_PLUGIN_target_task_completion when
asynchronous task on target is completed. */
__offload_register_task_callback (GOMP_PLUGIN_target_task_completion);
-
- if (atexit (unregister_main_image) != 0)
- {
- fprintf (stderr, "%s: atexit failed\n", __FILE__);
- exit (1);
- }
}
/* liboffloadmic loads and runs offload_target_main on all available devices
@@ -269,8 +257,9 @@ extern "C" void
GOMP_OFFLOAD_fini_device (int device)
{
TRACE ("(device = %d)", device);
- /* Unreachable for GOMP_OFFLOAD_CAP_OPENMP_400. */
- abort ();
+
+ /* liboffloadmic will finalize target processes on all available devices. */
+ __offload_unregister_image (&main_target_image);
}
static void