From 22be23495a1f0cd1ae6a1aca32c39edb9f7a9c51 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 21 Jul 2015 13:30:06 +0000 Subject: [PATCH] target.c (gomp_offload_image_to_device): Rename to ... libgomp/ * target.c (gomp_offload_image_to_device): Rename to ... (gomp_load_image_to_device): ... here. (GOMP_offload_register): Adjust call. (gomp_init_device): Likewise. (gomp_unload_image_from_device): New. Broken out of ... (GOMP_offload_unregister): ... here. Call it. (gomp_unload_device): New. * libgomp.h (gomp_unload_device): Declare. * oacc-init.c (acc_shutdown_1): Unload from device before deleting mem maps. gcc/ * config/nvptx/mkoffload.c (process): Add static destructor call. From-SVN: r226039 --- gcc/ChangeLog | 4 + gcc/config/nvptx/mkoffload.c | 21 +++-- libgomp/ChangeLog | 13 ++++ libgomp/libgomp.h | 1 + libgomp/oacc-init.c | 13 +++- libgomp/target.c | 146 ++++++++++++++++++++--------------- 6 files changed, 130 insertions(+), 68 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4ede93948c4..69e5bbef35b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,7 @@ +2015-07-21 Nathan Sidwell + + * config/nvptx/mkoffload.c (process): Add static destructor call. + 2015-07-21 Kyrylo Tkachov PR middle-end/66915 diff --git a/gcc/config/nvptx/mkoffload.c b/gcc/config/nvptx/mkoffload.c index ab381799909..1e154c8412c 100644 --- a/gcc/config/nvptx/mkoffload.c +++ b/gcc/config/nvptx/mkoffload.c @@ -880,18 +880,29 @@ process (FILE *in, FILE *out) fprintf (out, "#ifdef __cplusplus\n" "extern \"C\" {\n" "#endif\n"); + fprintf (out, "extern void GOMP_offload_register" " (const void *, int, const void *);\n"); + fprintf (out, "extern void GOMP_offload_unregister" + " (const void *, int, const void *);\n"); + fprintf (out, "#ifdef __cplusplus\n" "}\n" "#endif\n"); fprintf (out, "extern const void *const __OFFLOAD_TABLE__[];\n\n"); - fprintf (out, "static __attribute__((constructor)) void init (void)\n{\n"); - fprintf (out, " GOMP_offload_register (__OFFLOAD_TABLE__, %d,\n", - GOMP_DEVICE_NVIDIA_PTX); - fprintf (out, " &target_data);\n"); - fprintf (out, "};\n"); + + fprintf (out, "static __attribute__((constructor)) void init (void)\n" + "{\n" + " GOMP_offload_register (__OFFLOAD_TABLE__, %d/*NVIDIA_PTX*/,\n" + " &target_data);\n" + "};\n", GOMP_DEVICE_NVIDIA_PTX); + + fprintf (out, "static __attribute__((destructor)) void fini (void)\n" + "{\n" + " GOMP_offload_unregister (__OFFLOAD_TABLE__, %d/*NVIDIA_PTX*/,\n" + " &target_data);\n" + "};\n", GOMP_DEVICE_NVIDIA_PTX); } static void diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 0628b77d523..12c9e947e20 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,16 @@ +2015-07-21 Nathan Sidwell + + * target.c (gomp_offload_image_to_device): Rename to ... + (gomp_load_image_to_device): ... here. + (GOMP_offload_register): Adjust call. + (gomp_init_device): Likewise. + (gomp_unload_image_from_device): New. Broken out of ... + (GOMP_offload_unregister): ... here. Call it. + (gomp_unload_device): New. + * libgomp.h (gomp_unload_device): Declare. + * oacc-init.c (acc_shutdown_1): Unload from device before deleting + mem maps. + 2015-07-20 Nathan Sidwell * oacc-parallel.c (GOACC_parallel): Move variadic handling into diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h index 420ac83e9e7..ac40e2aa510 100644 --- a/libgomp/libgomp.h +++ b/libgomp/libgomp.h @@ -782,6 +782,7 @@ extern void gomp_unmap_vars (struct target_mem_desc *, bool); extern void gomp_init_device (struct gomp_device_descr *); extern void gomp_free_memmap (struct splay_tree_s *); extern void gomp_fini_device (struct gomp_device_descr *); +extern void gomp_unload_device (struct gomp_device_descr *); /* work.c */ diff --git a/libgomp/oacc-init.c b/libgomp/oacc-init.c index c91731edcac..105d9dc45de 100644 --- a/libgomp/oacc-init.c +++ b/libgomp/oacc-init.c @@ -252,6 +252,18 @@ acc_shutdown_1 (acc_device_t d) /* Get the base device for this device type. */ base_dev = resolve_device (d, true); + ndevs = base_dev->get_num_devices_func (); + + /* Unload all the devices of this type that have been opened. */ + for (i = 0; i < ndevs; i++) + { + struct gomp_device_descr *acc_dev = &base_dev[i]; + + gomp_mutex_lock (&acc_dev->lock); + gomp_unload_device (acc_dev); + gomp_mutex_unlock (&acc_dev->lock); + } + gomp_mutex_lock (&goacc_thread_lock); /* Free target-specific TLS data and close all devices. */ @@ -290,7 +302,6 @@ acc_shutdown_1 (acc_device_t d) gomp_mutex_unlock (&goacc_thread_lock); - ndevs = base_dev->get_num_devices_func (); /* Close all the devices of this type that have been opened. */ for (i = 0; i < ndevs; i++) diff --git a/libgomp/target.c b/libgomp/target.c index bc88a1fe586..7b3d0f9572d 100644 --- a/libgomp/target.c +++ b/libgomp/target.c @@ -638,12 +638,13 @@ gomp_update (struct gomp_device_descr *devicep, size_t mapnum, void **hostaddrs, /* Load image pointed by TARGET_DATA to the device, specified by DEVICEP. And insert to splay tree the mapping between addresses from HOST_TABLE and - from loaded target image. */ + from loaded target image. We rely in the host and device compiler + emitting variable and functions in the same order. */ static void -gomp_offload_image_to_device (struct gomp_device_descr *devicep, - const void *host_table, const void *target_data, - bool is_register_lock) +gomp_load_image_to_device (struct gomp_device_descr *devicep, + const void *host_table, const void *target_data, + bool is_register_lock) { void **host_func_table = ((void ***) host_table)[0]; void **host_funcs_end = ((void ***) host_table)[1]; @@ -658,7 +659,8 @@ gomp_offload_image_to_device (struct gomp_device_descr *devicep, /* Load image to device and get target addresses for the image. */ struct addr_pair *target_table = NULL; int i, num_target_entries - = devicep->load_image_func (devicep->target_id, target_data, &target_table); + = devicep->load_image_func (devicep->target_id, target_data, + &target_table); if (num_target_entries != num_funcs + num_vars) { @@ -725,6 +727,60 @@ gomp_offload_image_to_device (struct gomp_device_descr *devicep, free (target_table); } +/* Unload the mappings described by target_data from device DEVICE_P. + The device must be locked. */ + +static void +gomp_unload_image_from_device (struct gomp_device_descr *devicep, + const void *host_table, const void *target_data) +{ + void **host_func_table = ((void ***) host_table)[0]; + void **host_funcs_end = ((void ***) host_table)[1]; + void **host_var_table = ((void ***) host_table)[2]; + void **host_vars_end = ((void ***) host_table)[3]; + + /* The func table contains only addresses, the var table contains addresses + and corresponding sizes. */ + int num_funcs = host_funcs_end - host_func_table; + int num_vars = (host_vars_end - host_var_table) / 2; + + unsigned j; + struct splay_tree_key_s k; + splay_tree_key node = NULL; + + /* Find mapping at start of node array */ + if (num_funcs || num_vars) + { + k.host_start = (num_funcs ? (uintptr_t) host_func_table[0] + : (uintptr_t) host_var_table[0]); + k.host_end = k.host_start + 1; + node = splay_tree_lookup (&devicep->mem_map, &k); + } + + devicep->unload_image_func (devicep->target_id, target_data); + + /* Remove mappings from splay tree. */ + for (j = 0; j < num_funcs; j++) + { + k.host_start = (uintptr_t) host_func_table[j]; + k.host_end = k.host_start + 1; + splay_tree_remove (&devicep->mem_map, &k); + } + + for (j = 0; j < num_vars; j++) + { + k.host_start = (uintptr_t) host_var_table[j * 2]; + k.host_end = k.host_start + (uintptr_t) host_var_table[j * 2 + 1]; + splay_tree_remove (&devicep->mem_map, &k); + } + + if (node) + { + free (node->tgt); + free (node); + } +} + /* This function should be called from every offload image while loading. It gets the descriptor of the host func and var tables HOST_TABLE, TYPE of the target, and TARGET_DATA needed by target plugin. */ @@ -742,7 +798,7 @@ GOMP_offload_register (const void *host_table, int target_type, struct gomp_device_descr *devicep = &devices[i]; gomp_mutex_lock (&devicep->lock); if (devicep->type == target_type && devicep->is_initialized) - gomp_offload_image_to_device (devicep, host_table, target_data, true); + gomp_load_image_to_device (devicep, host_table, target_data, true); gomp_mutex_unlock (&devicep->lock); } @@ -767,69 +823,17 @@ void GOMP_offload_unregister (const void *host_table, int target_type, const void *target_data) { - void **host_func_table = ((void ***) host_table)[0]; - void **host_funcs_end = ((void ***) host_table)[1]; - void **host_var_table = ((void ***) host_table)[2]; - void **host_vars_end = ((void ***) host_table)[3]; int i; - /* The func table contains only addresses, the var table contains addresses - and corresponding sizes. */ - int num_funcs = host_funcs_end - host_func_table; - int num_vars = (host_vars_end - host_var_table) / 2; - gomp_mutex_lock (®ister_lock); /* Unload image from all initialized devices. */ for (i = 0; i < num_devices; i++) { - int j; struct gomp_device_descr *devicep = &devices[i]; gomp_mutex_lock (&devicep->lock); - if (devicep->type != target_type || !devicep->is_initialized) - { - gomp_mutex_unlock (&devicep->lock); - continue; - } - - devicep->unload_image_func (devicep->target_id, target_data); - - /* Remove mapping from splay tree. */ - struct splay_tree_key_s k; - splay_tree_key node = NULL; - if (num_funcs > 0) - { - k.host_start = (uintptr_t) host_func_table[0]; - k.host_end = k.host_start + 1; - node = splay_tree_lookup (&devicep->mem_map, &k); - } - else if (num_vars > 0) - { - k.host_start = (uintptr_t) host_var_table[0]; - k.host_end = k.host_start + (uintptr_t) host_var_table[1]; - node = splay_tree_lookup (&devicep->mem_map, &k); - } - - for (j = 0; j < num_funcs; j++) - { - k.host_start = (uintptr_t) host_func_table[j]; - k.host_end = k.host_start + 1; - splay_tree_remove (&devicep->mem_map, &k); - } - - for (j = 0; j < num_vars; j++) - { - k.host_start = (uintptr_t) host_var_table[j * 2]; - k.host_end = k.host_start + (uintptr_t) host_var_table[j * 2 + 1]; - splay_tree_remove (&devicep->mem_map, &k); - } - - if (node) - { - free (node->tgt); - free (node); - } - + if (devicep->type == target_type && devicep->is_initialized) + gomp_unload_image_from_device (devicep, host_table, target_data); gomp_mutex_unlock (&devicep->lock); } @@ -858,13 +862,31 @@ gomp_init_device (struct gomp_device_descr *devicep) { struct offload_image_descr *image = &offload_images[i]; if (image->type == devicep->type) - gomp_offload_image_to_device (devicep, image->host_table, - image->target_data, false); + gomp_load_image_to_device (devicep, image->host_table, + image->target_data, false); } devicep->is_initialized = true; } +attribute_hidden void +gomp_unload_device (struct gomp_device_descr *devicep) +{ + if (devicep->is_initialized) + { + unsigned i; + + /* Unload from device all images registered at the moment. */ + for (i = 0; i < num_offload_images; i++) + { + struct offload_image_descr *image = &offload_images[i]; + if (image->type == devicep->type) + gomp_unload_image_from_device (devicep, image->host_table, + image->target_data); + } + } +} + /* Free address mapping tables. MM must be locked on entry, and remains locked on return. */ -- 2.30.2