1/* 2 Copyright (c) 2014 Intel Corporation. All Rights Reserved. 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions 6 are met: 7 8 * Redistributions of source code must retain the above copyright 9 notice, this list of conditions and the following disclaimer. 10 * Redistributions in binary form must reproduce the above copyright 11 notice, this list of conditions and the following disclaimer in the 12 documentation and/or other materials provided with the distribution. 13 * Neither the name of Intel Corporation nor the names of its 14 contributors may be used to endorse or promote products derived 15 from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*/ 29 30 31#include "offload_table.h" 32#include "offload_common.h" 33 34#if !HOST_LIBRARY 35// Predefined offload entries 36extern void omp_set_num_threads_lrb(void*); 37extern void omp_get_max_threads_lrb(void*); 38extern void omp_get_num_procs_lrb(void*); 39extern void omp_set_dynamic_lrb(void*); 40extern void omp_get_dynamic_lrb(void*); 41extern void omp_set_nested_lrb(void*); 42extern void omp_get_nested_lrb(void*); 43extern void omp_set_schedule_lrb(void*); 44extern void omp_get_schedule_lrb(void*); 45 46extern void omp_init_lock_lrb(void*); 47extern void omp_destroy_lock_lrb(void*); 48extern void omp_set_lock_lrb(void*); 49extern void omp_unset_lock_lrb(void*); 50extern void omp_test_lock_lrb(void*); 51 52extern void omp_init_nest_lock_lrb(void*); 53extern void omp_destroy_nest_lock_lrb(void*); 54extern void omp_set_nest_lock_lrb(void*); 55extern void omp_unset_nest_lock_lrb(void*); 56extern void omp_test_nest_lock_lrb(void*); 57 58// Predefined entries on the target side 59static FuncTable::Entry predefined_entries[] = { 60 "omp_set_num_threads_target", 61 (void*) &omp_set_num_threads_lrb, 62 "omp_get_max_threads_target", 63 (void*) &omp_get_max_threads_lrb, 64 "omp_get_num_procs_target", 65 (void*) &omp_get_num_procs_lrb, 66 "omp_set_dynamic_target", 67 (void*) &omp_set_dynamic_lrb, 68 "omp_get_dynamic_target", 69 (void*) &omp_get_dynamic_lrb, 70 "omp_set_nested_target", 71 (void*) &omp_set_nested_lrb, 72 "omp_get_nested_target", 73 (void*) &omp_get_nested_lrb, 74 "omp_set_schedule_target", 75 (void*) &omp_set_schedule_lrb, 76 "omp_get_schedule_target", 77 (void*) &omp_get_schedule_lrb, 78 79 "omp_init_lock_target", 80 (void*) &omp_init_lock_lrb, 81 "omp_destroy_lock_target", 82 (void*) &omp_destroy_lock_lrb, 83 "omp_set_lock_target", 84 (void*) &omp_set_lock_lrb, 85 "omp_unset_lock_target", 86 (void*) &omp_unset_lock_lrb, 87 "omp_test_lock_target", 88 (void*) &omp_test_lock_lrb, 89 90 "omp_init_nest_lock_target", 91 (void*) &omp_init_nest_lock_lrb, 92 "omp_destroy_nest_lock_target", 93 (void*) &omp_destroy_nest_lock_lrb, 94 "omp_set_nest_lock_target", 95 (void*) &omp_set_nest_lock_lrb, 96 "omp_unset_nest_lock_target", 97 (void*) &omp_unset_nest_lock_lrb, 98 "omp_test_nest_lock_target", 99 (void*) &omp_test_nest_lock_lrb, 100 101 (const char*) -1, 102 (void*) -1 103}; 104 105static FuncList::Node predefined_table = { 106 { predefined_entries, -1 }, 107 0, 0 108}; 109 110// Entry table 111FuncList __offload_entries(&predefined_table); 112#else 113FuncList __offload_entries; 114#endif // !HOST_LIBRARY 115 116// Function table. No predefined entries. 117FuncList __offload_funcs; 118 119// Var table 120VarList __offload_vars; 121 122// Given the function name returns the associtated function pointer 123const void* FuncList::find_addr(const char *name) 124{ 125 const void* func = 0; 126 127 m_lock.lock(); 128 129 for (Node *n = m_head; n != 0; n = n->next) { 130 for (const Table::Entry *e = n->table.entries; 131 e->name != (const char*) -1; e++) { 132 if (e->name != 0 && strcmp(e->name, name) == 0) { 133 func = e->func; 134 break; 135 } 136 } 137 } 138 139 m_lock.unlock(); 140 141 return func; 142} 143 144// Given the function pointer returns the associtated function name 145const char* FuncList::find_name(const void *func) 146{ 147 const char* name = 0; 148 149 m_lock.lock(); 150 151 for (Node *n = m_head; n != 0; n = n->next) { 152 for (const Table::Entry *e = n->table.entries; 153 e->name != (const char*) -1; e++) { 154 if (e->func == func) { 155 name = e->name; 156 break; 157 } 158 } 159 } 160 161 m_lock.unlock(); 162 163 return name; 164} 165 166// Returns max name length from all tables 167int64_t FuncList::max_name_length(void) 168{ 169 if (m_max_name_len < 0) { 170 m_lock.lock(); 171 172 m_max_name_len = 0; 173 for (Node *n = m_head; n != 0; n = n->next) { 174 if (n->table.max_name_len < 0) { 175 n->table.max_name_len = 0; 176 177 // calculate max name length in a single table 178 for (const Table::Entry *e = n->table.entries; 179 e->name != (const char*) -1; e++) { 180 if (e->name != 0) { 181 size_t len = strlen(e->name) + 1; 182 if (n->table.max_name_len < len) { 183 n->table.max_name_len = len; 184 } 185 } 186 } 187 } 188 189 // select max from all tables 190 if (m_max_name_len < n->table.max_name_len) { 191 m_max_name_len = n->table.max_name_len; 192 } 193 } 194 195 m_lock.unlock(); 196 } 197 return m_max_name_len; 198} 199 200// Debugging dump 201void FuncList::dump(void) 202{ 203 OFFLOAD_DEBUG_TRACE(2, "Function table:\n"); 204 205 m_lock.lock(); 206 207 for (Node *n = m_head; n != 0; n = n->next) { 208 for (const Table::Entry *e = n->table.entries; 209 e->name != (const char*) -1; e++) { 210 if (e->name != 0) { 211 OFFLOAD_DEBUG_TRACE(2, "%p %s\n", e->func, e->name); 212 } 213 } 214 } 215 216 m_lock.unlock(); 217} 218 219// Debugging dump 220void VarList::dump(void) 221{ 222 OFFLOAD_DEBUG_TRACE(2, "Var table:\n"); 223 224 m_lock.lock(); 225 226 for (Node *n = m_head; n != 0; n = n->next) { 227 for (const Table::Entry *e = n->table.entries; 228 e->name != (const char*) -1; e++) { 229 if (e->name != 0) { 230#if HOST_LIBRARY 231 OFFLOAD_DEBUG_TRACE(2, "%s %p %ld\n", e->name, e->addr, 232 e->size); 233#else // HOST_LIBRARY 234 OFFLOAD_DEBUG_TRACE(2, "%s %p\n", e->name, e->addr); 235#endif // HOST_LIBRARY 236 } 237 } 238 } 239 240 m_lock.unlock(); 241} 242 243// 244int64_t VarList::table_size(int64_t &nelems) 245{ 246 int64_t length = 0; 247 248 nelems = 0; 249 250 // calculate string table size and number of elements 251 for (Node *n = m_head; n != 0; n = n->next) { 252 for (const Table::Entry *e = n->table.entries; 253 e->name != (const char*) -1; e++) { 254 if (e->name != 0) { 255 length += strlen(e->name) + 1; 256 nelems++; 257 } 258 } 259 } 260 261 return nelems * sizeof(BufEntry) + length; 262} 263 264// copy table to the gven buffer 265void VarList::table_copy(void *buf, int64_t nelems) 266{ 267 BufEntry* elems = static_cast<BufEntry*>(buf); 268 char* names = reinterpret_cast<char*>(elems + nelems); 269 270 // copy entries to buffer 271 for (Node *n = m_head; n != 0; n = n->next) { 272 for (const Table::Entry *e = n->table.entries; 273 e->name != (const char*) -1; e++) { 274 if (e->name != 0) { 275 // name field contains offset to the name from the beginning 276 // of the buffer 277 elems->name = names - static_cast<char*>(buf); 278 elems->addr = reinterpret_cast<intptr_t>(e->addr); 279 280 // copy name to string table 281 const char *name = e->name; 282 while ((*names++ = *name++) != '\0'); 283 284 elems++; 285 } 286 } 287 } 288} 289 290// patch name offsets in a buffer 291void VarList::table_patch_names(void *buf, int64_t nelems) 292{ 293 BufEntry* elems = static_cast<BufEntry*>(buf); 294 for (int i = 0; i < nelems; i++) { 295 elems[i].name += reinterpret_cast<intptr_t>(buf); 296 } 297} 298 299// Adds given list element to the global lookup table list 300extern "C" void __offload_register_tables( 301 FuncList::Node *entry_table, 302 FuncList::Node *func_table, 303 VarList::Node *var_table 304) 305{ 306 OFFLOAD_DEBUG_TRACE(2, "Registering offload function entry table %p\n", 307 entry_table); 308 __offload_entries.add_table(entry_table); 309 310 OFFLOAD_DEBUG_TRACE(2, "Registering function table %p\n", func_table); 311 __offload_funcs.add_table(func_table); 312 313 OFFLOAD_DEBUG_TRACE(2, "Registering var table %p\n", var_table); 314 __offload_vars.add_table(var_table); 315} 316 317// Removes given list element from the global lookup table list 318extern "C" void __offload_unregister_tables( 319 FuncList::Node *entry_table, 320 FuncList::Node *func_table, 321 VarList::Node *var_table 322) 323{ 324 __offload_entries.remove_table(entry_table); 325 326 OFFLOAD_DEBUG_TRACE(2, "Unregistering function table %p\n", func_table); 327 __offload_funcs.remove_table(func_table); 328 329 OFFLOAD_DEBUG_TRACE(2, "Unregistering var table %p\n", var_table); 330 __offload_vars.remove_table(var_table); 331} 332