/* Copyright (C) 2023-2024 Free Software Foundation, Inc. Contributed by Siemens. This file is part of the GNU Offloading and Multi Processing Library (libgomp). Libgomp is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ #include #include "libgomp.h" #define splay_tree_prefix indirect #define splay_tree_c #include "splay-tree.h" volatile void **GOMP_INDIRECT_ADDR_MAP = NULL; /* Use a splay tree to lookup the target address instead of using a linear search. */ #define USE_SPLAY_TREE_LOOKUP #ifdef USE_SPLAY_TREE_LOOKUP static struct indirect_splay_tree_s indirect_map; static indirect_splay_tree_node indirect_array = NULL; /* Build the splay tree used for host->target address lookups. */ void build_indirect_map (void) { size_t num_ind_funcs = 0; volatile void **map_entry; static int lock = 0; /* == gomp_mutex_t lock; gomp_mutex_init (&lock); */ if (!GOMP_INDIRECT_ADDR_MAP) return; gomp_mutex_lock (&lock); if (!indirect_array) { /* Count the number of entries in the NULL-terminated address map. */ for (map_entry = GOMP_INDIRECT_ADDR_MAP; *map_entry; map_entry += 2, num_ind_funcs++); /* Build splay tree for address lookup. */ indirect_array = gomp_malloc (num_ind_funcs * sizeof (*indirect_array)); indirect_splay_tree_node array = indirect_array; map_entry = GOMP_INDIRECT_ADDR_MAP; for (int i = 0; i < num_ind_funcs; i++, array++) { indirect_splay_tree_key k = &array->key; k->host_addr = (uint64_t) *map_entry++; k->target_addr = (uint64_t) *map_entry++; array->left = NULL; array->right = NULL; indirect_splay_tree_insert (&indirect_map, array); } } gomp_mutex_unlock (&lock); } void * GOMP_target_map_indirect_ptr (void *ptr) { /* NULL pointers always resolve to NULL. */ if (!ptr) return ptr; assert (indirect_array); struct indirect_splay_tree_key_s k; indirect_splay_tree_key node = NULL; k.host_addr = (uint64_t) ptr; node = indirect_splay_tree_lookup (&indirect_map, &k); return node ? (void *) node->target_addr : ptr; } #else void build_indirect_map (void) { } void * GOMP_target_map_indirect_ptr (void *ptr) { /* NULL pointers always resolve to NULL. */ if (!ptr) return ptr; assert (GOMP_INDIRECT_ADDR_MAP); for (volatile void **map_entry = GOMP_INDIRECT_ADDR_MAP; *map_entry; map_entry += 2) if (*map_entry == ptr) return (void *) *(map_entry + 1); return ptr; } #endif