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 <nat...@codesourcery.com>
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