This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

offload data version number


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.

ok?

nathan
2015-07-21  Nathan Sidwell  <nathan@acm.org>

	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/libgomp.map
===================================================================
--- libgomp/libgomp.map	(revision 226017)
+++ 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: libgomp/target.c
===================================================================
--- libgomp/target.c	(revision 226017)
+++ 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;
@@ -641,7 +642,8 @@ gomp_update (struct gomp_device_descr *d
    from loaded target image.  */
 
 static void
-gomp_offload_image_to_device (struct gomp_device_descr *devicep,
+gomp_offload_image_to_device (unsigned version,
+			      struct gomp_device_descr *devicep,
 			      const void *host_table, const void *target_data,
 			      bool is_register_lock)
 {
@@ -657,15 +659,28 @@ gomp_offload_image_to_device (struct gom
 
   /* 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 (&register_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.  */
@@ -730,10 +745,15 @@ gomp_offload_image_to_device (struct gom
    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 (&register_lock);
 
   /* Load image to all initialized devices.  */
@@ -742,7 +762,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_offload_image_to_device (devicep, host_table, target_data, true);
+	gomp_offload_image_to_device (version, devicep,
+				      host_table, target_data, true);
       gomp_mutex_unlock (&devicep->lock);
     }
 
@@ -751,6 +772,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;
@@ -759,13 +781,20 @@ GOMP_offload_register (const void *host_
   gomp_mutex_unlock (&register_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)
 {
   void **host_func_table = ((void ***) host_table)[0];
   void **host_funcs_end  = ((void ***) host_table)[1];
@@ -792,7 +821,11 @@ GOMP_offload_unregister (const void *hos
 	  continue;
 	}
 
-      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 mapping from splay tree.  */
       struct splay_tree_key_s k;
@@ -844,6 +877,13 @@ GOMP_offload_unregister (const void *hos
   gomp_mutex_unlock (&register_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.  */
 
@@ -858,8 +898,9 @@ gomp_init_device (struct gomp_device_des
     {
       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_offload_image_to_device (image->version, devicep,
+				      image->host_table, image->target_data,
+				      false);
     }
 
   devicep->is_initialized = true;
@@ -1113,6 +1154,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 226017)
+++ 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 226017)
+++ 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: include/gomp-constants.h
===================================================================
--- include/gomp-constants.h	(revision 226017)
+++ 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 226017)
+++ gcc/config/nvptx/mkoffload.c	(working copy)
@@ -880,18 +880,21 @@ 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_register_2"
+	   " (unsigned,  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",
+
+  fprintf (out, "static __attribute__((constructor)) void init (void)\n"
+	   "{\n"
+	   "  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, "                         &target_data);\n");
-  fprintf (out, "};\n");
 }
 
 static void

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]