On 07/21/15 09:25, Nathan Sidwell wrote:
This trunk patch implements new register and unregister entry points to allow specifying data version information. (I'll shortly be posting patches changing the PTX offload data format.)We now have GOMP_offload_{,un}register_2, which take an additional unsigned int version number. The version number is composed of two parts. 16 bits for the libgomp version and 16 bits for the device-specific plugin. Currently both are zero. When the PTX data changes, that device-specific value will increment. The existing register/unregister calls forward to the new ones, providing zero for the version information. On the plugin side I've added 2 new entry points GOMP_OFFLOAD_{,un}load_image_2, which also take an additional version number argument. These entry points are optional, and only added to the PTX plugin. The existing plugin entrypoints forward to the new ones. libgomp will use these new entry points if they exist, otherwise use the original entry points, provided the incoming version is zero. I added the GOMP_offload_{,un}register_2 routines to the libgomp map file as version 4.0.2 -- I wasn't sure whether to increment it more than that. Advice sought.
this version is updated following committing the unload patch. there were a few (expected) collisions.
nathan
2015-07-21 Nathan Sidwell <[email protected]> include/ * gomp-constants.h (GOMP_VERSION, GOMP_VERSION_NVIDIA_PTX): New. (GOMP_VERSION_PACK, GOMP_VERSION_LIB, GOMP_VERSION_DEV): New. libgomp/ * plugin/plugin-nvptx.c: Include gomp-constants.h. (GOMP_OFFLOAD_load_image): Replace with stub function. Move bulk to .... (GOMP_OFFLOAD_load_image_2): ... here. Add version argument and check it. (GOMP_OFFLOAD_unload_image): Replace with stub function. Move bulk to .... (GOMP_OFFLOAD_unload_image_2): ... here. Add version argument and check it. * libgomp.map: Add 4.0.2 version. * target.c (offload_image_descr): Add versionn field. (gomp_offload_image_to_device): Add version argument. Forward to load_image_func_2 if available. Improve load mismatch diagnostic. (GOMP_offload_regster): Make stub function, move bulk to ... (GOMP_offload_register_2): ... here. Process version argument. (GOMP_offload_unregister): Make stub function, move bulk to ... (GOMP_offload_unregister_2): ... here. Process version argument. (gomp_init_device): Process version field. (gomp_load_plugin_for_device): Search for load_image_2 and unload_image_2 entry points. * libgomp.h (gomp_device_descr) Add load_image_2 and unload_image_2 fields. gcc/ * config/nvptx/mkoffload.c (process): Replace GOMP_offload_register with GOMP_offload_register_2. Index: libgomp/target.c =================================================================== --- libgomp/target.c (revision 226039) +++ libgomp/target.c (working copy) @@ -56,6 +56,7 @@ static gomp_mutex_t register_lock; It contains type of the target device, pointer to host table descriptor, and pointer to target data. */ struct offload_image_descr { + unsigned version; enum offload_target_type type; const void *host_table; const void *target_data; @@ -642,7 +643,8 @@ gomp_update (struct gomp_device_descr *d emitting variable and functions in the same order. */ static void -gomp_load_image_to_device (struct gomp_device_descr *devicep, +gomp_load_image_to_device (unsigned version, + struct gomp_device_descr *devicep, const void *host_table, const void *target_data, bool is_register_lock) { @@ -658,16 +660,28 @@ gomp_load_image_to_device (struct gomp_d /* 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); + int i, num_target_entries; + + if (devicep->load_image_2_func) + num_target_entries + = devicep->load_image_2_func (version, devicep->target_id, + target_data, &target_table); + else if (GOMP_VERSION_DEV (version)) + gomp_fatal ("Plugin too old for offload data (0 < %u)", + GOMP_VERSION_DEV (version)); + else + num_target_entries + = devicep->load_image_func (devicep->target_id, + target_data, &target_table); if (num_target_entries != num_funcs + num_vars) { gomp_mutex_unlock (&devicep->lock); if (is_register_lock) gomp_mutex_unlock (®ister_lock); - gomp_fatal ("Can't map target functions or variables"); + gomp_fatal ("Cannot map target functions or variables" + " (expected %u, have %u)", num_funcs + num_vars, + num_target_entries); } /* Insert host-target address mapping into splay tree. */ @@ -731,7 +745,8 @@ gomp_load_image_to_device (struct gomp_d The device must be locked. */ static void -gomp_unload_image_from_device (struct gomp_device_descr *devicep, +gomp_unload_image_from_device (unsigned version, + struct gomp_device_descr *devicep, const void *host_table, const void *target_data) { void **host_func_table = ((void ***) host_table)[0]; @@ -756,8 +771,12 @@ gomp_unload_image_from_device (struct go k.host_end = k.host_start + 1; node = splay_tree_lookup (&devicep->mem_map, &k); } - - devicep->unload_image_func (devicep->target_id, target_data); + + if (devicep->unload_image_2_func) + devicep->unload_image_2_func (version, + devicep->target_id, target_data); + else + devicep->unload_image_func (devicep->target_id, target_data); /* Remove mappings from splay tree. */ for (j = 0; j < num_funcs; j++) @@ -786,10 +805,15 @@ gomp_unload_image_from_device (struct go the target, and TARGET_DATA needed by target plugin. */ void -GOMP_offload_register (const void *host_table, int target_type, - const void *target_data) +GOMP_offload_register_2 (unsigned version, const void *host_table, + int target_type, const void *target_data) { int i; + + if (GOMP_VERSION_LIB (version) > GOMP_VERSION) + gomp_fatal ("Library too old for offload (version %u < %u)", + GOMP_VERSION, GOMP_VERSION_LIB (version)); + gomp_mutex_lock (®ister_lock); /* Load image to all initialized devices. */ @@ -798,7 +822,8 @@ GOMP_offload_register (const void *host_ struct gomp_device_descr *devicep = &devices[i]; gomp_mutex_lock (&devicep->lock); if (devicep->type == target_type && devicep->is_initialized) - gomp_load_image_to_device (devicep, host_table, target_data, true); + gomp_load_image_to_device (version, devicep, + host_table, target_data, true); gomp_mutex_unlock (&devicep->lock); } @@ -807,6 +832,7 @@ GOMP_offload_register (const void *host_ = gomp_realloc_unlock (offload_images, (num_offload_images + 1) * sizeof (struct offload_image_descr)); + offload_images[num_offload_images].version = version; offload_images[num_offload_images].type = target_type; offload_images[num_offload_images].host_table = host_table; offload_images[num_offload_images].target_data = target_data; @@ -815,13 +841,20 @@ GOMP_offload_register (const void *host_ gomp_mutex_unlock (®ister_lock); } +void +GOMP_offload_register (const void *host_table, int target_type, + const void *target_data) +{ + GOMP_offload_register_2 (0, host_table, target_type, target_data); +} + /* This function should be called from every offload image while unloading. It gets the descriptor of the host func and var tables HOST_TABLE, TYPE of the target, and TARGET_DATA needed by target plugin. */ void -GOMP_offload_unregister (const void *host_table, int target_type, - const void *target_data) +GOMP_offload_unregister_2 (unsigned version, const void *host_table, + int target_type, const void *target_data) { int i; @@ -833,7 +866,8 @@ GOMP_offload_unregister (const void *hos struct gomp_device_descr *devicep = &devices[i]; gomp_mutex_lock (&devicep->lock); if (devicep->type == target_type && devicep->is_initialized) - gomp_unload_image_from_device (devicep, host_table, target_data); + gomp_unload_image_from_device (version, devicep, + host_table, target_data); gomp_mutex_unlock (&devicep->lock); } @@ -848,6 +882,13 @@ GOMP_offload_unregister (const void *hos gomp_mutex_unlock (®ister_lock); } +void +GOMP_offload_unregister (const void *host_table, int target_type, + const void *target_data) +{ + GOMP_offload_unregister_2 (0, host_table, target_type, target_data); +} + /* This function initializes the target device, specified by DEVICEP. DEVICEP must be locked on entry, and remains locked on return. */ @@ -862,8 +903,9 @@ gomp_init_device (struct gomp_device_des { struct offload_image_descr *image = &offload_images[i]; if (image->type == devicep->type) - gomp_load_image_to_device (devicep, image->host_table, - image->target_data, false); + gomp_load_image_to_device (image->version, devicep, + image->host_table, image->target_data, + false); } devicep->is_initialized = true; @@ -881,7 +923,8 @@ gomp_unload_device (struct gomp_device_d { struct offload_image_descr *image = &offload_images[i]; if (image->type == devicep->type) - gomp_unload_image_from_device (devicep, image->host_table, + gomp_unload_image_from_device (image->version, devicep, + image->host_table, image->target_data); } } @@ -1135,6 +1178,8 @@ gomp_load_plugin_for_device (struct gomp DLSYM (free); DLSYM (dev2host); DLSYM (host2dev); + DLSYM_OPT (load_image_2, load_image_2); + DLSYM_OPT (unload_image_2, unload_image_2); device->capabilities = device->get_caps_func (); if (device->capabilities & GOMP_OFFLOAD_CAP_OPENMP_400) DLSYM (run); Index: libgomp/libgomp.h =================================================================== --- libgomp/libgomp.h (revision 226039) +++ libgomp/libgomp.h (working copy) @@ -749,7 +749,9 @@ struct gomp_device_descr void (*init_device_func) (int); void (*fini_device_func) (int); int (*load_image_func) (int, const void *, struct addr_pair **); + int (*load_image_2_func) (unsigned, int, const void *, struct addr_pair **); void (*unload_image_func) (int, const void *); + void (*unload_image_2_func) (unsigned, int, const void *); void *(*alloc_func) (int, size_t); void (*free_func) (int, void *); void *(*dev2host_func) (int, void *, const void *, size_t); Index: libgomp/plugin/plugin-nvptx.c =================================================================== --- libgomp/plugin/plugin-nvptx.c (revision 226039) +++ libgomp/plugin/plugin-nvptx.c (working copy) @@ -36,6 +36,7 @@ #include "libgomp-plugin.h" #include "oacc-ptx.h" #include "oacc-plugin.h" +#include "gomp-constants.h" #include <pthread.h> #include <cuda.h> @@ -1648,8 +1649,8 @@ typedef struct nvptx_tdata number ORD. Allocate and return TARGET_TABLE. */ int -GOMP_OFFLOAD_load_image (int ord, const void *target_data, - struct addr_pair **target_table) +GOMP_OFFLOAD_load_image_2 (unsigned version, int ord, const void *target_data, + struct addr_pair **target_table) { CUmodule module; const char *const *fn_names, *const *var_names; @@ -1661,6 +1662,11 @@ GOMP_OFFLOAD_load_image (int ord, const struct ptx_image_data *new_image; struct ptx_device *dev; + if (GOMP_VERSION_DEV (version) != GOMP_VERSION_NVIDIA_PTX) + GOMP_PLUGIN_fatal ("Offload data incompatible with PTX plugin" + " (version %u ! %u)", + GOMP_VERSION_NVIDIA_PTX, GOMP_VERSION_DEV (version)); + GOMP_OFFLOAD_init_device (ord); dev = ptx_devices[ord]; @@ -1726,15 +1732,26 @@ GOMP_OFFLOAD_load_image (int ord, const return fn_entries + var_entries; } +int +GOMP_OFFLOAD_load_image (int device, + const void *target_image, struct addr_pair **result) +{ + return GOMP_OFFLOAD_load_image_2 (0, device, target_image, result); +} + /* Unload the program described by TARGET_DATA. DEV_DATA is the function descriptors allocated by G_O_load_image. */ void -GOMP_OFFLOAD_unload_image (int ord, const void *target_data) +GOMP_OFFLOAD_unload_image_2 (unsigned version, int ord, + const void *target_data) { struct ptx_image_data *image, **prev_p; struct ptx_device *dev = ptx_devices[ord]; + if (GOMP_VERSION_DEV (version) != GOMP_VERSION_NVIDIA_PTX) + return; + pthread_mutex_lock (&dev->image_lock); for (prev_p = &dev->images; (image = *prev_p) != 0; prev_p = &image->next) if (image->target_data == target_data) @@ -1748,6 +1765,12 @@ GOMP_OFFLOAD_unload_image (int ord, cons pthread_mutex_unlock (&dev->image_lock); } +void +GOMP_OFFLOAD_unload_image (int ord, const void *target_data) +{ + GOMP_OFFLOAD_unload_image_2 (0, ord, target_data); +} + void * GOMP_OFFLOAD_alloc (int ord, size_t size) { Index: libgomp/libgomp.map =================================================================== --- libgomp/libgomp.map (revision 226039) +++ libgomp/libgomp.map (working copy) @@ -234,6 +234,12 @@ GOMP_4.0.1 { GOMP_offload_unregister; } GOMP_4.0; +GOMP_4.0.2 { + global: + GOMP_offload_register_2; + GOMP_offload_unregister_2; +} GOMP_4.0.1; + OACC_2.0 { global: acc_get_num_devices; Index: include/gomp-constants.h =================================================================== --- include/gomp-constants.h (revision 226039) +++ include/gomp-constants.h (working copy) @@ -113,4 +113,12 @@ enum gomp_map_kind #define GOMP_DEVICE_ICV -1 #define GOMP_DEVICE_HOST_FALLBACK -2 +/* Versions of libgomp and device-specific plugins. */ +#define GOMP_VERSION 0 +#define GOMP_VERSION_NVIDIA_PTX 1 + +#define GOMP_VERSION_PACK(LIB, DEV) (((LIB) << 16) | (DEV)) +#define GOMP_VERSION_LIB(PACK) (((PACK) >> 16) & 0xffff) +#define GOMP_VERSION_DEV(PACK) ((PACK) & 0xffff) + #endif Index: gcc/config/nvptx/mkoffload.c =================================================================== --- gcc/config/nvptx/mkoffload.c (revision 226039) +++ gcc/config/nvptx/mkoffload.c (working copy) @@ -881,10 +881,10 @@ process (FILE *in, FILE *out) "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, "extern void GOMP_offload_register_2" + " (unsigned, const void *, int, const void *);\n"); + fprintf (out, "extern void GOMP_offload_unregister_2" + " (unsigned, const void *, int, const void *);\n"); fprintf (out, "#ifdef __cplusplus\n" "}\n" @@ -894,15 +894,19 @@ process (FILE *in, FILE *out) 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); + " GOMP_offload_register_2 (%#x, __OFFLOAD_TABLE__," + "%d/*NVIDIA_PTX*/, &target_data);\n" + "};\n", + GOMP_VERSION_PACK (GOMP_VERSION, GOMP_VERSION_NVIDIA_PTX), + 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); + " GOMP_offload_unregister_2 (%#x, __OFFLOAD_TABLE__," + "%d/*NVIDIA_PTX*/, &target_data);\n" + "};\n", + GOMP_VERSION_PACK (GOMP_VERSION, GOMP_VERSION_NVIDIA_PTX), + GOMP_DEVICE_NVIDIA_PTX); } static void
