On 28 Feb 17:21, Bernd Schmidt wrote: > It would help to see the code you have on the libgomp side, I don't > believe that's been posted yet?
It was posted here: http://gcc.gnu.org/ml/gcc-patches/2013-12/msg01777.html And below is the updated version. --- libgomp/libgomp.map | 1 + libgomp/target.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 132 insertions(+), 7 deletions(-) diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map index cb52e45..d33673d 100644 --- a/libgomp/libgomp.map +++ b/libgomp/libgomp.map @@ -208,6 +208,7 @@ GOMP_3.0 { GOMP_4.0 { global: + GOMP_register_lib; GOMP_barrier_cancel; GOMP_cancel; GOMP_cancellation_point; diff --git a/libgomp/target.c b/libgomp/target.c index a6a5505..7fafa9a 100644 --- a/libgomp/target.c +++ b/libgomp/target.c @@ -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; @@ -107,6 +120,12 @@ splay_compare (splay_tree_key x, splay_tree_key y) #include "splay-tree.h" +struct target_table_s +{ + void **entries; + int num_entries; +}; + /* This structure describes accelerator device. It contains name of the corresponding libgomp plugin, function handlers for interaction with the device, ID-number of the device, and information about @@ -117,15 +136,21 @@ 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) (int); + struct target_table_s (*device_load_image_func) (void *, int); void *(*device_alloc_func) (size_t); void (*device_free_func) (void *); void *(*device_dev2host_func)(void *, const void *, size_t); void *(*device_host2dev_func)(void *, const void *, size_t); + void (*device_run_func) (void *, void *); /* Splay tree containing information about mapped memory regions. */ struct splay_tree_s dev_splay_tree; @@ -471,6 +496,80 @@ 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) +{ + /* Initialize the target device. */ + devicep->device_init_func (devicep->id); + + /* Load shared libraries into target device and + perform host-target address mapping. */ + int i; + for (i = 0; i < num_libraries; i++) + { + /* Get the pointer to the target image from the library descriptor. */ + void **lib = libraries[i]; + + /* FIXME: Select the proper target image, if there are several. */ + void *target_image = lib[DESCR_IMAGE_START]; + int target_img_size = lib[DESCR_IMAGE_END] - lib[DESCR_IMAGE_START]; + + /* Calculate the size of host address table. */ + void **host_table_start = lib[DESCR_TABLE_START]; + void **host_table_end = lib[DESCR_TABLE_END]; + int host_table_size = host_table_end - host_table_start; + + /* Load library into target device and receive its address table. */ + struct target_table_s target_table + = devicep->device_load_image_func (target_image, target_img_size); + + if (host_table_size != target_table.num_entries) + gomp_fatal ("Can't map target objects"); + + void **host_entry, **target_entry; + for (host_entry = host_table_start, target_entry = target_table.entries; + 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_offset = 0; + k->tgt = tgt; + node->left = NULL; + node->right = NULL; + splay_tree_insert (&devicep->dev_splay_tree, node); + } + + free (target_table.entries); + } + + free (libraries); + num_libraries = 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. @@ -487,7 +586,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 (); @@ -504,7 +604,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; @@ -514,10 +625,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, + (void *) tgt_vars->tgt_start); gomp_free_thread (thr); *thr = old_thr; - gomp_unmap_vars (tgt); + gomp_unmap_vars (tgt_vars); } void @@ -525,7 +637,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); @@ -543,6 +656,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); @@ -567,9 +683,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_init_device (devicep); + gomp_update (devicep, mapnum, hostaddrs, sizes, kinds); } @@ -637,10 +757,13 @@ gomp_load_plugin_for_device (struct gomp_device_descr *device, } \ while (0) DLSYM (device_available); + DLSYM (device_init); + DLSYM (device_load_image); DLSYM (device_alloc); DLSYM (device_free); DLSYM (device_dev2host); DLSYM (device_host2dev); + DLSYM (device_run); #undef DLSYM out: @@ -700,6 +823,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++; -- 1.7.1 -- Ilya