@@ -208,6 +208,7 @@ GOMP_3.0 {
GOMP_4.0 {
global:
+ GOMP_register_lib;
GOMP_barrier_cancel;
GOMP_cancel;
GOMP_cancellation_point;
@@ -84,6 +84,19 @@ struct splay_tree_key_s {
bool copy_from;
};
+enum library_descr {
+ DESCR_TABLE_START,
+ DESCR_TABLE_END,
+ DESCR_IMAGE_START,
+ DESCR_IMAGE_END
+};
+
+/* Array of pointers to target shared library descriptors. */
+static void **libraries;
+
+/* Total number of target shared libraries. */
+static int num_libraries;
+
/* Array of descriptors of all available devices. */
static struct gomp_device_descr *devices;
@@ -117,11 +130,16 @@ struct gomp_device_descr
TARGET construct. */
int id;
+ /* Set to true when device is initialized. */
+ bool is_initialized;
+
/* Plugin file handler. */
void *plugin_handle;
/* Function handlers. */
- bool (*device_available_func) (void);
+ bool (*device_available_func) (int);
+ void (*device_init_func) (void **, int *, int, void ***, int *);
+ void (*device_run_func) (void *, uintptr_t);
/* Splay tree containing information about mapped memory regions. */
struct splay_tree_s dev_splay_tree;
@@ -466,6 +484,89 @@ gomp_update (struct gomp_device_descr *devicep, size_t mapnum,
gomp_mutex_unlock (&devicep->dev_env_lock);
}
+void
+GOMP_register_lib (const void *openmp_target)
+{
+ libraries = realloc (libraries, (num_libraries + 1) * sizeof (void *));
+
+ if (libraries == NULL)
+ return;
+
+ libraries[num_libraries] = (void *) openmp_target;
+
+ num_libraries++;
+}
+
+static void
+gomp_init_device (struct gomp_device_descr *devicep)
+{
+ void **target_images = malloc (num_libraries * sizeof (void *));
+ int *target_img_sizes = malloc (num_libraries * sizeof (int));
+ if (target_images == NULL || target_img_sizes == NULL)
+ gomp_fatal ("Can not allocate memory");
+
+ /* Collect target images from the library descriptors and calculate the total
+ size of host address table. */
+ int i, host_table_size = 0;
+ for (i = 0; i < num_libraries; i++)
+ {
+ void **lib = libraries[i];
+ void **host_table_start = lib[DESCR_TABLE_START];
+ void **host_table_end = lib[DESCR_TABLE_END];
+ /* FIXME: Select the proper target image. */
+ target_images[i] = lib[DESCR_IMAGE_START];
+ target_img_sizes[i] = lib[DESCR_IMAGE_END] - lib[DESCR_IMAGE_START];
+ host_table_size += host_table_end - host_table_start;
+ }
+
+ /* Initialize the target device and receive the address table from target. */
+ void **target_table = NULL;
+ int target_table_size = 0;
+ devicep->device_init_func (target_images, target_img_sizes, num_libraries,
+ &target_table, &target_table_size);
+ free (target_images);
+ free (target_img_sizes);
+
+ if (host_table_size != target_table_size)
+ gomp_fatal ("Can't map target objects");
+
+ /* Initialize the mapping data structure. */
+ void **target_entry = target_table;
+ for (i = 0; i < num_libraries; i++)
+ {
+ void **lib = libraries[i];
+ void **host_table_start = lib[DESCR_TABLE_START];
+ void **host_table_end = lib[DESCR_TABLE_END];
+ void **host_entry;
+ for (host_entry = host_table_start; host_entry < host_table_end;
+ host_entry += 2, target_entry += 2)
+ {
+ struct target_mem_desc *tgt = gomp_malloc (sizeof (*tgt));
+ tgt->refcount = 1;
+ tgt->array = gomp_malloc (sizeof (*tgt->array));
+ tgt->tgt_start = (uintptr_t) *target_entry;
+ tgt->tgt_end = tgt->tgt_start + (uint64_t) *(target_entry+1);
+ 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 = (uintptr_t) *host_entry;
+ k->host_end = k->host_start + (uint64_t) *(host_entry+1);
+ k->tgt = tgt;
+ node->left = NULL;
+ node->right = NULL;
+ splay_tree_insert (&devicep->dev_splay_tree, node);
+ }
+ }
+
+ free (libraries);
+ num_libraries = 0;
+ free (target_table);
+ target_table_size = 0;
+ devicep->is_initialized = true;
+}
+
/* Called when encountering a target directive. If DEVICE
is -1, it means use device-var ICV. If it is -2 (or any other value
larger than last available hw device, use host fallback.
@@ -482,7 +583,8 @@ GOMP_target (int device, void (*fn) (void *), const void *openmp_target,
unsigned char *kinds)
{
struct gomp_device_descr *devicep = resolve_device (device);
- if (devicep == NULL)
+ if (openmp_target == NULL || devicep == NULL
+ || !devicep->device_available_func (devicep->id))
{
/* Host fallback. */
struct gomp_thread old_thr, *thr = gomp_thread ();
@@ -499,7 +601,18 @@ GOMP_target (int device, void (*fn) (void *), const void *openmp_target,
return;
}
- struct target_mem_desc *tgt
+ if (!devicep->is_initialized)
+ gomp_init_device (devicep);
+
+ splay_tree_node node = gomp_malloc (sizeof (*node));
+ splay_tree_key k = &node->key;
+ k->host_start = (uintptr_t) fn;
+ k->host_end = k->host_start + 1;
+ splay_tree_key tgt_fn = splay_tree_lookup (&devicep->dev_splay_tree, k);
+ if (tgt_fn == NULL)
+ gomp_fatal ("Target function wasn't mapped");
+
+ struct target_mem_desc *tgt_vars
= gomp_map_vars (devicep, mapnum, hostaddrs, sizes, kinds, true);
struct gomp_thread old_thr, *thr = gomp_thread ();
old_thr = *thr;
@@ -509,10 +622,11 @@ GOMP_target (int device, void (*fn) (void *), const void *openmp_target,
thr->place = old_thr.place;
thr->ts.place_partition_len = gomp_places_list_len;
}
- fn ((void *) tgt->tgt_start);
+ devicep->device_run_func ((void *) tgt_fn->tgt->tgt_start,
+ tgt_vars->tgt_start);
gomp_free_thread (thr);
*thr = old_thr;
- gomp_unmap_vars (tgt);
+ gomp_unmap_vars (tgt_vars);
}
void
@@ -520,7 +634,8 @@ GOMP_target_data (int device, const void *openmp_target, size_t mapnum,
void **hostaddrs, size_t *sizes, unsigned char *kinds)
{
struct gomp_device_descr *devicep = resolve_device (device);
- if (devicep == NULL)
+ if (openmp_target == NULL || devicep == NULL
+ || !devicep->device_available_func (devicep->id))
{
/* Host fallback. */
struct gomp_task_icv *icv = gomp_icv (false);
@@ -538,6 +653,9 @@ GOMP_target_data (int device, const void *openmp_target, size_t mapnum,
return;
}
+ if (!devicep->is_initialized)
+ gomp_init_device (devicep);
+
struct target_mem_desc *tgt
= gomp_map_vars (devicep, mapnum, hostaddrs, sizes, kinds, false);
struct gomp_task_icv *icv = gomp_icv (true);
@@ -562,9 +680,13 @@ GOMP_target_update (int device, const void *openmp_target, size_t mapnum,
void **hostaddrs, size_t *sizes, unsigned char *kinds)
{
struct gomp_device_descr *devicep = resolve_device (device);
- if (devicep == NULL)
+ if (openmp_target == NULL || devicep == NULL
+ || !devicep->device_available_func (devicep->id))
return;
+ if (!devicep->is_initialized)
+ gomp_fatal ("Target device wasn't initialized");
+
gomp_update (devicep, mapnum, hostaddrs, sizes, kinds);
}
@@ -619,8 +741,7 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device,
dlerror ();
/* Check if all required functions are available in the plugin and store
- their handlers.
- TODO: check for other routines as well. */
+ their handlers. */
device->device_available_func = dlsym (device->plugin_handle,
"device_available");
if (dlerror () != NULL)
@@ -629,6 +750,20 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device,
return false;
}
+ device->device_init_func = dlsym (device->plugin_handle, "device_init");
+ if (dlerror () != NULL)
+ {
+ dlclose (device->plugin_handle);
+ return false;
+ }
+
+ device->device_run_func = dlsym (device->plugin_handle, "device_run");
+ if (dlerror () != NULL)
+ {
+ dlclose (device->plugin_handle);
+ return false;
+ }
+
return true;
}
@@ -680,6 +815,7 @@ gomp_find_available_plugins (void)
devices[num_devices] = current_device;
devices[num_devices].id = num_devices + 1;
+ devices[num_devices].is_initialized = false;
devices[num_devices].dev_splay_tree.root = NULL;
gomp_mutex_init (&devices[num_devices].dev_env_lock);
num_devices++;