Ping. (Patch is slightly updated) On 20 Dec 21:18, Ilya Verbin wrote: > Hi Jakub, > > Could you please take a look at this patch for libgomp? > > It adds new function GOMP_register_lib, that should be called from every > exec/lib with target regions (that was done in patch [1]). This function > maintains the array of pointers to the target shared library descriptors. > > Also this patch adds target device initialization into GOMP_target and > GOMP_target_data. At first, it calls "device_init" function from the plugin. > This function takes array of target-images as input, and returns the array of > target-side addresses. Currently, it always uses the first target-image from > the descriptor, this should be generalized later. Then libgomp reads the > tables > from host-side exec/libs. After that, it inserts host->target address mapping > into the splay tree. > > [1] http://gcc.gnu.org/ml/gcc-patches/2013-12/msg01486.html > > Thanks, > -- Ilya
-- Ilya --- libgomp/libgomp.map | 1 + libgomp/target.c | 154 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 146 insertions(+), 9 deletions(-) diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map index 2b64d05..792047f 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 d84a1fa..7677c28 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; @@ -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++; -- 1.7.1