2015-07-27 Nathan Sidwell include/ * gomp-constants.h (GOMP_VERSION_NVIDIA_PTX): Restore to zero. libgomp/ * libgomp.map: Rename GOMP_offload_{,un}register_2 to GOMP_offload_{,un}register_ver. * target.c (gomp_load_image_to_device): Check version function to determine interface to plugin. (gomp_unload_image_from_device): Likewise. (GOMP_offload_register_2): Rename to ... (GOMP_offload_register_ver): ... here. (GOMP_offload_unregister_2): Rename to ... (GOMP_offload_unregister_ver): ... here. (GOMP_offload_register, GOMP_offload_unregister): Adjust forwarding. (gomp_load_plugin_for_device): Reimplement DLSYM & DLSYM_OPT macros. Look for versioning function and check it. Fetch versioning loader and unloader if available. * libgomp.h (gomp_device_descr): Add version function field. Put loader and unloader fields in unions. * plugin/plugin-nvptx.c (GOMP_OFFLOAD_version): New. (GOMP_OFFLOAD_load_image_2): Renamed to ... (GOMP_OFFLOAD_load_image_ver): ... here. (GOMP_OFFLOAD_unload_image_2): Renamed to ... (GOMP_OFFLOAD_unload_image_ver): ... here. (GOMP_OFFLOAD_load_image, GOMP_OFFLOAD_unload_image): Delete. * oacc-host.c (host_dispatch): Adjust. gcc/ * config/nvptx/mkoffload.c (process): Rename _2 functions to _ver. Index: libgomp/libgomp.map =================================================================== --- libgomp/libgomp.map (revision 226237) +++ libgomp/libgomp.map (working copy) @@ -236,8 +236,8 @@ GOMP_4.0.1 { GOMP_4.0.2 { global: - GOMP_offload_register_2; - GOMP_offload_unregister_2; + GOMP_offload_register_ver; + GOMP_offload_unregister_ver; } GOMP_4.0.1; OACC_2.0 { Index: libgomp/target.c =================================================================== --- libgomp/target.c (revision 226237) +++ libgomp/target.c (working copy) @@ -671,17 +671,17 @@ gomp_load_image_to_device (unsigned vers struct addr_pair *target_table = NULL; int i, num_target_entries; - if (devicep->load_image_2_func) + if (devicep->version_func) num_target_entries - = devicep->load_image_2_func (version, devicep->target_id, - target_data, &target_table); + = devicep->load_image.ver_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); + = devicep->load_image.unver_func (devicep->target_id, + target_data, &target_table); if (num_target_entries != num_funcs + num_vars) { @@ -790,11 +790,11 @@ gomp_unload_image_from_device (unsigned node = splay_tree_lookup (&devicep->mem_map, &k); } - if (devicep->unload_image_2_func) - devicep->unload_image_2_func (version, - devicep->target_id, target_data); + if (devicep->version_func) + devicep->unload_image.ver_func (version, + devicep->target_id, target_data); else - devicep->unload_image_func (devicep->target_id, target_data); + devicep->unload_image.unver_func (devicep->target_id, target_data); /* Remove mappings from splay tree. */ for (j = 0; j < num_funcs; j++) @@ -823,8 +823,8 @@ gomp_unload_image_from_device (unsigned the target, and TARGET_DATA needed by target plugin. */ void -GOMP_offload_register_2 (unsigned version, const void *host_table, - int target_type, const void *target_data) +GOMP_offload_register_ver (unsigned version, const void *host_table, + int target_type, const void *target_data) { int i; @@ -863,7 +863,7 @@ 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); + GOMP_offload_register_ver (0, host_table, target_type, target_data); } /* This function should be called from every offload image while unloading. @@ -871,8 +871,8 @@ GOMP_offload_register (const void *host_ the target, and TARGET_DATA needed by target plugin. */ void -GOMP_offload_unregister_2 (unsigned version, const void *host_table, - int target_type, const void *target_data) +GOMP_offload_unregister_ver (unsigned version, const void *host_table, + int target_type, const void *target_data) { int i; @@ -904,7 +904,7 @@ 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); + GOMP_offload_unregister_ver (0, host_table, target_type, target_data); } /* This function initializes the target device, specified by DEVICEP. DEVICEP @@ -1130,43 +1130,41 @@ gomp_load_plugin_for_device (struct gomp const char *plugin_name) { const char *err = NULL, *last_missing = NULL; - int optional_present = 0, optional_total = 0; - - /* Clear any existing error. */ - dlerror (); void *plugin_handle = dlopen (plugin_name, RTLD_LAZY); if (!plugin_handle) - { - err = dlerror (); - goto out; - } + goto dl_fail; /* Check if all required functions are available in the plugin and store - their handlers. */ + their handlers. None of the symbols can legitimately be NULL, + so we don't need to check dlerror all the time. */ #define DLSYM(f) \ - do \ - { \ - device->f##_func = dlsym (plugin_handle, "GOMP_OFFLOAD_" #f); \ - err = dlerror (); \ - if (err != NULL) \ - goto out; \ - } \ - while (0) - /* Similar, but missing functions are not an error. */ -#define DLSYM_OPT(f, n) \ - do \ - { \ - const char *tmp_err; \ - device->f##_func = dlsym (plugin_handle, "GOMP_OFFLOAD_" #n); \ - tmp_err = dlerror (); \ - if (tmp_err == NULL) \ - optional_present++; \ - else \ - last_missing = #n; \ - optional_total++; \ - } \ - while (0) + if (!(device->f##_func = dlsym (plugin_handle, "GOMP_OFFLOAD_" #f))) \ + goto dl_fail + /* Similar, but missing functions are not an error. Return false if + failed, true otherwise. */ +#define DLSYM_OPT(f, n) \ + ((device->f##_func = dlsym (plugin_handle, "GOMP_OFFLOAD_" #n)) \ + || (last_missing = #n, 0)) + + if (DLSYM_OPT (version, version)) + { + unsigned v = device->version_func (); + if (v != GOMP_VERSION) + { + err = "plugin version mismatch"; + goto fail; + } + if (!DLSYM_OPT (load_image.ver, load_image_ver) + || !DLSYM_OPT (unload_image.ver, unload_image_ver)) + goto dl_fail; + } + else + { + if (!DLSYM_OPT (load_image.unver, load_image) + || !DLSYM_OPT (unload_image.unver, unload_image)) + goto dl_fail; + } DLSYM (get_name); DLSYM (get_caps); @@ -1174,66 +1172,67 @@ gomp_load_plugin_for_device (struct gomp DLSYM (get_num_devices); DLSYM (init_device); DLSYM (fini_device); - DLSYM (load_image); - DLSYM (unload_image); DLSYM (alloc); 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); if (device->capabilities & GOMP_OFFLOAD_CAP_OPENACC_200) { - optional_present = optional_total = 0; - DLSYM_OPT (openacc.exec, openacc_parallel); - DLSYM_OPT (openacc.register_async_cleanup, - openacc_register_async_cleanup); - DLSYM_OPT (openacc.async_test, openacc_async_test); - DLSYM_OPT (openacc.async_test_all, openacc_async_test_all); - DLSYM_OPT (openacc.async_wait, openacc_async_wait); - DLSYM_OPT (openacc.async_wait_async, openacc_async_wait_async); - DLSYM_OPT (openacc.async_wait_all, openacc_async_wait_all); - DLSYM_OPT (openacc.async_wait_all_async, openacc_async_wait_all_async); - DLSYM_OPT (openacc.async_set_async, openacc_async_set_async); - DLSYM_OPT (openacc.create_thread_data, openacc_create_thread_data); - DLSYM_OPT (openacc.destroy_thread_data, openacc_destroy_thread_data); - /* Require all the OpenACC handlers if we have - GOMP_OFFLOAD_CAP_OPENACC_200. */ - if (optional_present != optional_total) + if (!DLSYM_OPT (openacc.exec, openacc_parallel) + || !DLSYM_OPT (openacc.register_async_cleanup, + openacc_register_async_cleanup) + || !DLSYM_OPT (openacc.async_test, openacc_async_test) + || !DLSYM_OPT (openacc.async_test_all, openacc_async_test_all) + || !DLSYM_OPT (openacc.async_wait, openacc_async_wait) + || !DLSYM_OPT (openacc.async_wait_async, openacc_async_wait_async) + || !DLSYM_OPT (openacc.async_wait_all, openacc_async_wait_all) + || !DLSYM_OPT (openacc.async_wait_all_async, + openacc_async_wait_all_async) + || !DLSYM_OPT (openacc.async_set_async, openacc_async_set_async) + || !DLSYM_OPT (openacc.create_thread_data, + openacc_create_thread_data) + || !DLSYM_OPT (openacc.destroy_thread_data, + openacc_destroy_thread_data)) { + /* Require all the OpenACC handlers if we have + GOMP_OFFLOAD_CAP_OPENACC_200. */ err = "plugin missing OpenACC handler function"; - goto out; + goto fail; } - optional_present = optional_total = 0; - DLSYM_OPT (openacc.cuda.get_current_device, - openacc_get_current_cuda_device); - DLSYM_OPT (openacc.cuda.get_current_context, - openacc_get_current_cuda_context); - DLSYM_OPT (openacc.cuda.get_stream, openacc_get_cuda_stream); - DLSYM_OPT (openacc.cuda.set_stream, openacc_set_cuda_stream); - /* Make sure all the CUDA functions are there if any of them are. */ - if (optional_present && optional_present != optional_total) + + unsigned cuda = 0; + cuda += DLSYM_OPT (openacc.cuda.get_current_device, + openacc_get_current_cuda_device); + cuda += DLSYM_OPT (openacc.cuda.get_current_context, + openacc_get_current_cuda_context); + cuda += DLSYM_OPT (openacc.cuda.get_stream, openacc_get_cuda_stream); + cuda += DLSYM_OPT (openacc.cuda.set_stream, openacc_set_cuda_stream); + if (cuda && cuda != 4) { + /* Make sure all the CUDA functions are there if any of them are. */ err = "plugin missing OpenACC CUDA handler function"; - goto out; + goto fail; } } #undef DLSYM #undef DLSYM_OPT - out: - if (err != NULL) - { - gomp_error ("while loading %s: %s", plugin_name, err); - if (last_missing) - gomp_error ("missing function was %s", last_missing); - if (plugin_handle) - dlclose (plugin_handle); - } - return err == NULL; + + return 1; + + dl_fail: + err = dlerror (); + fail: + gomp_error ("while loading %s: %s", plugin_name, err); + if (last_missing) + gomp_error ("missing function was %s", last_missing); + if (plugin_handle) + dlclose (plugin_handle); + + return 0; } /* This function initializes the runtime needed for offloading. Index: libgomp/libgomp.h =================================================================== --- libgomp/libgomp.h (revision 226237) +++ libgomp/libgomp.h (working copy) @@ -750,10 +750,22 @@ struct gomp_device_descr int (*get_num_devices_func) (void); 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 *); + + unsigned (*version_func) (void); + + /* When all plugins updated, we can remove these unions and just + have the versioned entry points. */ + union + { + int (*unver_func) (int, const void *, struct addr_pair **); + int (*ver_func) (unsigned, int, const void *, struct addr_pair **); + } load_image; + union + { + void (*unver_func) (int, const void *); + void (*ver_func) (unsigned, int, const void *); + } unload_image; + 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 226237) +++ libgomp/plugin/plugin-nvptx.c (working copy) @@ -1615,12 +1615,22 @@ typedef struct nvptx_tdata size_t fn_num; } nvptx_tdata_t; +/* Return the libgomp version number we're compatible with. There is + no requirement for cross-version compatibility. */ + +unsigned +GOMP_OFFLOAD_version (void) +{ + return GOMP_VERSION; +} + /* Load the (partial) program described by TARGET_DATA to device number ORD. Allocate and return TARGET_TABLE. */ int -GOMP_OFFLOAD_load_image_2 (unsigned version, int ord, const void *target_data, - struct addr_pair **target_table) +GOMP_OFFLOAD_load_image_ver (unsigned version, int ord, + const void *target_data, + struct addr_pair **target_table) { CUmodule module; const char *const *fn_names, *const *var_names; @@ -1702,19 +1712,12 @@ GOMP_OFFLOAD_load_image_2 (unsigned vers 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_2 (unsigned version, int ord, - const void *target_data) +GOMP_OFFLOAD_unload_image_ver (unsigned version, int ord, + const void *target_data) { struct ptx_image_data *image, **prev_p; struct ptx_device *dev = ptx_devices[ord]; @@ -1735,12 +1738,6 @@ GOMP_OFFLOAD_unload_image_2 (unsigned ve 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/oacc-host.c =================================================================== --- libgomp/oacc-host.c (revision 226237) +++ libgomp/oacc-host.c (working copy) @@ -45,8 +45,9 @@ static struct gomp_device_descr host_dis .get_num_devices_func = GOMP_OFFLOAD_get_num_devices, .init_device_func = GOMP_OFFLOAD_init_device, .fini_device_func = GOMP_OFFLOAD_fini_device, - .load_image_func = GOMP_OFFLOAD_load_image, - .unload_image_func = GOMP_OFFLOAD_unload_image, + .version_func = NULL, + .load_image = {.unver_func = GOMP_OFFLOAD_load_image}, + .unload_image = {.unver_func = GOMP_OFFLOAD_unload_image}, .alloc_func = GOMP_OFFLOAD_alloc, .free_func = GOMP_OFFLOAD_free, .dev2host_func = GOMP_OFFLOAD_dev2host, Index: include/gomp-constants.h =================================================================== --- include/gomp-constants.h (revision 226237) +++ include/gomp-constants.h (working copy) @@ -124,7 +124,7 @@ enum gomp_map_kind /* Versions of libgomp and device-specific plugins. */ #define GOMP_VERSION 0 -#define GOMP_VERSION_NVIDIA_PTX 1 +#define GOMP_VERSION_NVIDIA_PTX 0 #define GOMP_VERSION_PACK(LIB, DEV) (((LIB) << 16) | (DEV)) #define GOMP_VERSION_LIB(PACK) (((PACK) >> 16) & 0xffff) Index: gcc/config/nvptx/mkoffload.c =================================================================== --- gcc/config/nvptx/mkoffload.c (revision 226237) +++ gcc/config/nvptx/mkoffload.c (working copy) @@ -296,9 +296,9 @@ process (FILE *in, FILE *out) "extern \"C\" {\n" "#endif\n"); - fprintf (out, "extern void GOMP_offload_register_2" + fprintf (out, "extern void GOMP_offload_register_ver" " (unsigned, const void *, int, const void *);\n"); - fprintf (out, "extern void GOMP_offload_unregister_2" + fprintf (out, "extern void GOMP_offload_unregister_ver" " (unsigned, const void *, int, const void *);\n"); fprintf (out, "#ifdef __cplusplus\n" @@ -309,7 +309,7 @@ process (FILE *in, FILE *out) fprintf (out, "static __attribute__((constructor)) void init (void)\n" "{\n" - " GOMP_offload_register_2 (%#x, __OFFLOAD_TABLE__," + " GOMP_offload_register_ver (%#x, __OFFLOAD_TABLE__," "%d/*NVIDIA_PTX*/, &target_data);\n" "};\n", GOMP_VERSION_PACK (GOMP_VERSION, GOMP_VERSION_NVIDIA_PTX), @@ -317,7 +317,7 @@ process (FILE *in, FILE *out) fprintf (out, "static __attribute__((destructor)) void fini (void)\n" "{\n" - " GOMP_offload_unregister_2 (%#x, __OFFLOAD_TABLE__," + " GOMP_offload_unregister_ver (%#x, __OFFLOAD_TABLE__," "%d/*NVIDIA_PTX*/, &target_data);\n" "};\n", GOMP_VERSION_PACK (GOMP_VERSION, GOMP_VERSION_NVIDIA_PTX),