diff options
Diffstat (limited to 'libgomp/target.c')
-rw-r--r-- | libgomp/target.c | 87 |
1 files changed, 72 insertions, 15 deletions
diff --git a/libgomp/target.c b/libgomp/target.c index 932b176..1ab30f7 100644 --- a/libgomp/target.c +++ b/libgomp/target.c @@ -464,7 +464,7 @@ gomp_map_vars (struct gomp_device_descr *devicep, size_t mapnum, } else n = splay_tree_lookup (mem_map, &cur_node); - if (n) + if (n && n->refcount != REFCOUNT_LINK) gomp_map_vars_existing (devicep, n, &cur_node, &tgt->list[i], kind & typemask); else @@ -628,11 +628,19 @@ gomp_map_vars (struct gomp_device_descr *devicep, size_t mapnum, else k->host_end = k->host_start + sizeof (void *); splay_tree_key n = splay_tree_lookup (mem_map, k); - if (n) + if (n && n->refcount != REFCOUNT_LINK) gomp_map_vars_existing (devicep, n, k, &tgt->list[i], kind & typemask); else { + k->link_key = NULL; + if (n && n->refcount == REFCOUNT_LINK) + { + /* Replace target address of the pointer with target address + of mapped object in the splay tree. */ + splay_tree_remove (mem_map, n); + k->link_key = n; + } size_t align = (size_t) 1 << (kind >> rshift); tgt->list[i].key = k; k->tgt = tgt; @@ -752,6 +760,16 @@ gomp_map_vars (struct gomp_device_descr *devicep, size_t mapnum, gomp_fatal ("%s: unhandled kind 0x%.2x", __FUNCTION__, kind); } + + if (k->link_key) + { + /* Set link pointer on target to the device address of the + mapped object. */ + void *tgt_addr = (void *) (tgt->tgt_start + k->tgt_offset); + devicep->host2dev_func (devicep->target_id, + (void *) n->tgt_offset, + &tgt_addr, sizeof (void *)); + } array++; } } @@ -884,6 +902,9 @@ gomp_unmap_vars (struct target_mem_desc *tgt, bool do_copyfrom) if (do_unmap) { splay_tree_remove (&devicep->mem_map, k); + if (k->link_key) + splay_tree_insert (&devicep->mem_map, + (splay_tree_node) k->link_key); if (k->tgt->refcount > 1) k->tgt->refcount--; else @@ -1020,31 +1041,40 @@ gomp_load_image_to_device (struct gomp_device_descr *devicep, unsigned version, k->tgt_offset = target_table[i].start; k->refcount = REFCOUNT_INFINITY; k->async_refcount = 0; + k->link_key = NULL; array->left = NULL; array->right = NULL; splay_tree_insert (&devicep->mem_map, array); array++; } + /* Most significant bit of the size in host and target tables marks + "omp declare target link" variables. */ + const uintptr_t link_bit = 1ULL << (sizeof (uintptr_t) * __CHAR_BIT__ - 1); + const uintptr_t size_mask = ~link_bit; + for (i = 0; i < num_vars; i++) { struct addr_pair *target_var = &target_table[num_funcs + i]; - if (target_var->end - target_var->start - != (uintptr_t) host_var_table[i * 2 + 1]) + uintptr_t target_size = target_var->end - target_var->start; + + if ((uintptr_t) host_var_table[i * 2 + 1] != target_size) { gomp_mutex_unlock (&devicep->lock); if (is_register_lock) gomp_mutex_unlock (®ister_lock); - gomp_fatal ("Can't map target variables (size mismatch)"); + gomp_fatal ("Cannot map target variables (size mismatch)"); } splay_tree_key k = &array->key; k->host_start = (uintptr_t) host_var_table[i * 2]; - k->host_end = k->host_start + (uintptr_t) host_var_table[i * 2 + 1]; + k->host_end + = k->host_start + (size_mask & (uintptr_t) host_var_table[i * 2 + 1]); k->tgt = tgt; k->tgt_offset = target_var->start; - k->refcount = REFCOUNT_INFINITY; + k->refcount = target_size & link_bit ? REFCOUNT_LINK : REFCOUNT_INFINITY; k->async_refcount = 0; + k->link_key = NULL; array->left = NULL; array->right = NULL; splay_tree_insert (&devicep->mem_map, array); @@ -1072,7 +1102,6 @@ gomp_unload_image_from_device (struct gomp_device_descr *devicep, int num_funcs = host_funcs_end - host_func_table; int num_vars = (host_vars_end - host_var_table) / 2; - unsigned j; struct splay_tree_key_s k; splay_tree_key node = NULL; @@ -1088,21 +1117,46 @@ gomp_unload_image_from_device (struct gomp_device_descr *devicep, devicep->unload_image_func (devicep->target_id, version, target_data); /* Remove mappings from splay tree. */ - for (j = 0; j < num_funcs; j++) + int i; + for (i = 0; i < num_funcs; i++) { - k.host_start = (uintptr_t) host_func_table[j]; + k.host_start = (uintptr_t) host_func_table[i]; k.host_end = k.host_start + 1; splay_tree_remove (&devicep->mem_map, &k); } - for (j = 0; j < num_vars; j++) + /* Most significant bit of the size in host and target tables marks + "omp declare target link" variables. */ + const uintptr_t link_bit = 1ULL << (sizeof (uintptr_t) * __CHAR_BIT__ - 1); + const uintptr_t size_mask = ~link_bit; + bool is_tgt_unmapped = false; + + for (i = 0; i < num_vars; i++) { - 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->mem_map, &k); + k.host_start = (uintptr_t) host_var_table[i * 2]; + k.host_end + = k.host_start + (size_mask & (uintptr_t) host_var_table[i * 2 + 1]); + + if (!(link_bit & (uintptr_t) host_var_table[i * 2 + 1])) + splay_tree_remove (&devicep->mem_map, &k); + else + { + splay_tree_key n = splay_tree_lookup (&devicep->mem_map, &k); + splay_tree_remove (&devicep->mem_map, n); + if (n->link_key) + { + if (n->tgt->refcount > 1) + n->tgt->refcount--; + else + { + is_tgt_unmapped = true; + gomp_unmap_tgt (n->tgt); + } + } + } } - if (node) + if (node && !is_tgt_unmapped) { free (node->tgt); free (node); @@ -1658,6 +1712,9 @@ gomp_exit_data (struct gomp_device_descr *devicep, size_t mapnum, if (k->refcount == 0) { splay_tree_remove (&devicep->mem_map, k); + if (k->link_key) + splay_tree_insert (&devicep->mem_map, + (splay_tree_node) k->link_key); if (k->tgt->refcount > 1) k->tgt->refcount--; else |