@@ -231,4 +231,5 @@ GOMP_4.0 {
GOMP_4.0.1 {
global:
GOMP_offload_register;
+ GOMP_offload_unregister;
} GOMP_4.0;
@@ -31,14 +31,12 @@ enum offload_target_type
OFFLOAD_TARGET_TYPE_INTEL_MIC
};
-/* Auxiliary struct, used for transferring a host-target address range mapping
- from plugin to libgomp. */
-struct mapping_table
+/* Auxiliary struct, used for transferring pairs of addresses from plugin
+ to libgomp. */
+struct addr_pair
{
- uintptr_t host_start;
- uintptr_t host_end;
- uintptr_t tgt_start;
- uintptr_t tgt_end;
+ uintptr_t start;
+ uintptr_t end;
};
#endif /* LIBGOMP_TARGET_H */
@@ -143,9 +143,9 @@ struct gomp_device_descr
/* Function handlers. */
int (*get_type_func) (void);
int (*get_num_devices_func) (void);
- void (*register_image_func) (void *, void *);
void (*init_device_func) (int);
- int (*get_table_func) (int, void *);
+ int (*load_image_func) (int, void *, struct addr_pair **);
+ void (*unload_image_func) (int, void *);
void *(*alloc_func) (int, size_t);
void (*free_func) (int, void *);
void *(*host2dev_func) (int, void *, const void *, size_t);
@@ -600,7 +600,82 @@ gomp_update (struct gomp_device_descr *devicep, size_t mapnum,
gomp_mutex_unlock (&devicep->dev_env_lock);
}
-/* This function should be called from every offload image.
+/* Insert mapping of host -> target address pairs to splay tree. */
+
+static void
+gomp_splay_tree_insert_mapping (struct gomp_device_descr *devicep,
+ struct addr_pair *host_addr,
+ struct addr_pair *tgt_addr)
+{
+ struct target_mem_desc *tgt = gomp_malloc (sizeof (*tgt));
+ tgt->refcount = 1;
+ tgt->array = gomp_malloc (sizeof (*tgt->array));
+ tgt->tgt_start = tgt_addr->start;
+ tgt->tgt_end = tgt_addr->end;
+ tgt->to_free = NULL;
+ tgt->list_count = 0;
+ tgt->device_descr = devicep;
+ splay_tree_node node = tgt->array;
+ splay_tree_key k = &node->key;
+ k->host_start = host_addr->start;
+ k->host_end = host_addr->end;
+ k->tgt_offset = 0;
+ k->refcount = 1;
+ k->copy_from = false;
+ k->tgt = tgt;
+ node->left = NULL;
+ node->right = NULL;
+ splay_tree_insert (&devicep->dev_splay_tree, node);
+}
+
+/* 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. */
+
+static void
+gomp_offload_image_to_device (struct gomp_device_descr *devicep,
+ void *host_table, 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;
+
+ /* 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);
+
+ if (num_target_entries != num_funcs + num_vars)
+ gomp_fatal ("Can't map target functions or variables");
+
+ /* Insert host-target address mapping into devicep->dev_splay_tree. */
+ for (i = 0; i < num_funcs; i++)
+ {
+ struct addr_pair host_addr;
+ host_addr.start = (uintptr_t) host_func_table[i];
+ host_addr.end = host_addr.start + 1;
+ gomp_splay_tree_insert_mapping (devicep, &host_addr, &target_table[i]);
+ }
+
+ for (i = 0; i < num_vars; i++)
+ {
+ struct addr_pair host_addr;
+ host_addr.start = (uintptr_t) host_var_table[i*2];
+ host_addr.end = host_addr.start + (uintptr_t) host_var_table[i*2+1];
+ gomp_splay_tree_insert_mapping (devicep, &host_addr,
+ &target_table[num_funcs+i]);
+ }
+
+ free (target_table);
+}
+
+/* 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. */
@@ -608,6 +683,17 @@ void
GOMP_offload_register (void *host_table, enum offload_target_type target_type,
void *target_data)
{
+ int i;
+
+ /* Load image to all initialized devices. */
+ for (i = 0; i < num_devices; i++)
+ {
+ struct gomp_device_descr *devicep = &devices[i];
+ if (devicep->type == target_type && devicep->is_initialized)
+ gomp_offload_image_to_device (devicep, host_table, target_data);
+ }
+
+ /* Insert image to array of pending images. */
offload_images = gomp_realloc (offload_images,
(num_offload_images + 1)
* sizeof (struct offload_image_descr));
@@ -619,43 +705,81 @@ GOMP_offload_register (void *host_table, enum offload_target_type target_type,
num_offload_images++;
}
+/* 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 (void *host_table, enum offload_target_type target_type,
+ 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;
+
+ /* Unload image from all initialized devices. */
+ for (i = 0; i < num_devices; i++)
+ {
+ int j;
+ struct gomp_device_descr *devicep = &devices[i];
+
+ if (devicep->type != target_type || !devicep->is_initialized)
+ continue;
+
+ devicep->unload_image_func (devicep->target_id, target_data);
+
+ /* Remove mapping from splay tree. */
+ for (j = 0; j < num_funcs; j++)
+ {
+ struct splay_tree_key_s k;
+ k.host_start = (uintptr_t) host_func_table[j];
+ k.host_end = k.host_start + 1;
+ splay_tree_remove (&devicep->dev_splay_tree, &k);
+ }
+
+ for (j = 0; j < num_vars; j++)
+ {
+ struct splay_tree_key_s k;
+ 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->dev_splay_tree, &k);
+ }
+ }
+
+ /* Remove image from array of pending images. */
+ for (i = 0; i < num_offload_images; i++)
+ if (offload_images[i].target_data == target_data)
+ {
+ offload_images[i] = offload_images[--num_offload_images];
+ break;
+ }
+}
+
/* This function initializes the target device, specified by DEVICEP. */
static void
gomp_init_device (struct gomp_device_descr *devicep)
{
- devicep->init_device_func (devicep->target_id);
+ int i;
- /* Get address mapping table for device. */
- struct mapping_table *table = NULL;
- int num_entries = devicep->get_table_func (devicep->target_id, &table);
+ devicep->init_device_func (devicep->target_id);
- /* Insert host-target address mapping into dev_splay_tree. */
- int i;
- for (i = 0; i < num_entries; i++)
+ /* Load to device all images registered by the moment. */
+ for (i = 0; i < num_offload_images; i++)
{
- struct target_mem_desc *tgt = gomp_malloc (sizeof (*tgt));
- tgt->refcount = 1;
- tgt->array = gomp_malloc (sizeof (*tgt->array));
- tgt->tgt_start = table[i].tgt_start;
- tgt->tgt_end = table[i].tgt_end;
- tgt->to_free = NULL;
- tgt->list_count = 0;
- tgt->device_descr = devicep;
- splay_tree_node node = tgt->array;
- splay_tree_key k = &node->key;
- k->host_start = table[i].host_start;
- k->host_end = table[i].host_end;
- k->tgt_offset = 0;
- k->refcount = 1;
- k->copy_from = false;
- k->tgt = tgt;
- node->left = NULL;
- node->right = NULL;
- splay_tree_insert (&devicep->dev_splay_tree, node);
+ 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);
}
- free (table);
devicep->is_initialized = true;
}
@@ -823,9 +947,9 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device,
while (0)
DLSYM (get_type);
DLSYM (get_num_devices);
- DLSYM (register_image);
DLSYM (init_device);
- DLSYM (get_table);
+ DLSYM (load_image);
+ DLSYM (unload_image);
DLSYM (alloc);
DLSYM (free);
DLSYM (dev2host);
@@ -836,21 +960,6 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device,
return true;
}
-/* This function finds OFFLOAD_IMAGES corresponding to DEVICE type, and
- registers them in the plugin. */
-
-static void
-gomp_register_images_for_device (struct gomp_device_descr *device)
-{
- int i;
- for (i = 0; i < num_offload_images; i++)
- {
- struct offload_image_descr *image = &offload_images[i];
- if (image->type == device->type)
- device->register_image_func (image->host_table, image->target_data);
- }
-}
-
/* This function initializes the runtime needed for offloading.
It parses the list of offload targets and tries to load the plugins for these
targets. Result of the function is properly initialized variable NUM_DEVICES
@@ -905,7 +1014,6 @@ gomp_target_init (void)
current_device.type = current_device.get_type_func ();
current_device.is_initialized = false;
current_device.dev_splay_tree.root = NULL;
- gomp_register_images_for_device (¤t_device);
for (i = 0; i < new_num_devices; i++)
{
current_device.id = num_devices + 1;
@@ -921,10 +1029,6 @@ gomp_target_init (void)
cur = next + 1;
}
while (next);
-
- free (offload_images);
- offload_images = NULL;
- num_offload_images = 0;
}
#else /* PLUGIN_SUPPORT */