2015-09-25 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / liboffloadmic / runtime / offload_table.cpp
blobf3c5100cacd922fe2693023c60119d20586ee312
1 /*
2 Copyright (c) 2014-2015 Intel Corporation. All Rights Reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
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.
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.
31 #include "offload_table.h"
32 #include "offload_common.h"
34 #if !HOST_LIBRARY
35 // Predefined offload entries
36 extern void omp_set_num_threads_lrb(void*);
37 extern void omp_get_max_threads_lrb(void*);
38 extern void omp_get_num_procs_lrb(void*);
39 extern void omp_set_dynamic_lrb(void*);
40 extern void omp_get_dynamic_lrb(void*);
41 extern void omp_set_nested_lrb(void*);
42 extern void omp_get_nested_lrb(void*);
43 extern void omp_set_schedule_lrb(void*);
44 extern void omp_get_schedule_lrb(void*);
46 extern void omp_init_lock_lrb(void*);
47 extern void omp_destroy_lock_lrb(void*);
48 extern void omp_set_lock_lrb(void*);
49 extern void omp_unset_lock_lrb(void*);
50 extern void omp_test_lock_lrb(void*);
52 extern void omp_init_nest_lock_lrb(void*);
53 extern void omp_destroy_nest_lock_lrb(void*);
54 extern void omp_set_nest_lock_lrb(void*);
55 extern void omp_unset_nest_lock_lrb(void*);
56 extern void omp_test_nest_lock_lrb(void*);
58 // Predefined entries on the target side
59 static 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,
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,
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,
101 (const char*) -1,
102 (void*) -1
105 static FuncList::Node predefined_table = {
106 { predefined_entries, -1 },
107 0, 0
110 // Entry table
111 FuncList __offload_entries(&predefined_table);
112 #else
113 FuncList __offload_entries;
114 #endif // !HOST_LIBRARY
116 // Function table. No predefined entries.
117 FuncList __offload_funcs;
119 // Var table
120 VarList __offload_vars;
122 // Given the function name returns the associtated function pointer
123 const void* FuncList::find_addr(const char *name)
125 const void* func = 0;
127 m_lock.lock();
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;
139 m_lock.unlock();
141 return func;
144 // Given the function pointer returns the associtated function name
145 const char* FuncList::find_name(const void *func)
147 const char* name = 0;
149 m_lock.lock();
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;
161 m_lock.unlock();
163 return name;
166 // Returns max name length from all tables
167 int64_t FuncList::max_name_length(void)
169 if (m_max_name_len < 0) {
170 m_lock.lock();
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;
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;
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;
195 m_lock.unlock();
197 return m_max_name_len;
200 // Debugging dump
201 void FuncList::dump(void)
203 OFFLOAD_DEBUG_TRACE(2, "Function table:\n");
205 m_lock.lock();
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);
216 m_lock.unlock();
219 // Debugging dump
220 void VarList::dump(void)
222 OFFLOAD_DEBUG_TRACE(2, "Var table:\n");
224 m_lock.lock();
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
240 m_lock.unlock();
244 int64_t VarList::table_size(int64_t &nelems)
246 int64_t length = 0;
248 nelems = 0;
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++;
261 return nelems * sizeof(BufEntry) + length;
264 // copy table to the gven buffer
265 void VarList::table_copy(void *buf, int64_t nelems)
267 BufEntry* elems = static_cast<BufEntry*>(buf);
268 char* names = reinterpret_cast<char*>(elems + nelems);
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);
280 // copy name to string table
281 const char *name = e->name;
282 while ((*names++ = *name++) != '\0');
284 elems++;
290 // patch name offsets in a buffer
291 void VarList::table_patch_names(void *buf, int64_t nelems)
293 BufEntry* elems = static_cast<BufEntry*>(buf);
294 for (int i = 0; i < nelems; i++) {
295 elems[i].name += reinterpret_cast<intptr_t>(buf);
299 // Adds given list element to the global lookup table list
300 extern "C" void __offload_register_tables(
301 FuncList::Node *entry_table,
302 FuncList::Node *func_table,
303 VarList::Node *var_table
306 OFFLOAD_DEBUG_TRACE(2, "Registering offload function entry table %p\n",
307 entry_table);
308 __offload_entries.add_table(entry_table);
310 OFFLOAD_DEBUG_TRACE(2, "Registering function table %p\n", func_table);
311 __offload_funcs.add_table(func_table);
313 OFFLOAD_DEBUG_TRACE(2, "Registering var table %p\n", var_table);
314 __offload_vars.add_table(var_table);
317 // Removes given list element from the global lookup table list
318 extern "C" void __offload_unregister_tables(
319 FuncList::Node *entry_table,
320 FuncList::Node *func_table,
321 VarList::Node *var_table
324 OFFLOAD_DEBUG_TRACE(2, "Unregistering offload function entry table %p\n",
325 entry_table);
326 __offload_entries.remove_table(entry_table);
328 OFFLOAD_DEBUG_TRACE(2, "Unregistering function table %p\n", func_table);
329 __offload_funcs.remove_table(func_table);
331 OFFLOAD_DEBUG_TRACE(2, "Unregistering var table %p\n", var_table);
332 __offload_vars.remove_table(var_table);
335 #ifdef MYO_SUPPORT
337 MYOVarTableList __offload_myo_var_tables;
338 MYOVarTableList __offload_myo_vtable_tables;
339 MYOFuncTableList __offload_myo_func_tables;
340 MYOInitTableList __offload_myo_init_tables;
342 // Debugging dump
343 void MYOVarTableList::dump(void)
345 OFFLOAD_DEBUG_TRACE(2, "MYO Var tables:\n");
347 m_lock.lock();
349 for (Node *n = m_head; n != 0; n = n->next) {
350 OFFLOAD_DEBUG_TRACE(2, " MYO Var table:\n");
351 for (const Table::Entry *e = n->table.entries;
352 e->varName != MYO_TABLE_END_MARKER(); e++) {
353 #ifdef TARGET_WINNT
354 if (e->varName == 0) {
355 continue;
357 #endif // TARGET_WINNT
358 OFFLOAD_DEBUG_TRACE(2, " %s %p\n",
359 e->varName, e->sharedAddr);
363 m_lock.unlock();
366 // check if any shared variables
367 bool MYOVarTableList::is_empty()
369 OFFLOAD_DEBUG_TRACE(3, "Are MYO Var tables empty?\n");
371 m_lock.lock();
373 for (Node *n = m_head; n != 0; n = n->next) {
374 for (const Table::Entry *e = n->table.entries;
375 e->varName != MYO_TABLE_END_MARKER(); e++) {
376 #ifdef TARGET_WINNT
377 if (e->varName == 0) {
378 continue;
380 #endif // TARGET_WINNT
381 m_lock.unlock();
382 OFFLOAD_DEBUG_TRACE(3, "No\n");
383 return false;
387 m_lock.unlock();
388 OFFLOAD_DEBUG_TRACE(3, "Yes\n");
389 return true;
392 void MYOFuncTableList::dump(void)
394 OFFLOAD_DEBUG_TRACE(2, "MYO Func tables:\n");
396 m_lock.lock();
398 for (Node *n = m_head; n != 0; n = n->next) {
399 OFFLOAD_DEBUG_TRACE(2, " MYO Func table:\n");
400 for (const Table::Entry *e = n->table.entries;
401 e->funcName != MYO_TABLE_END_MARKER(); e++) {
402 #ifdef TARGET_WINNT
403 if (e->funcName == 0) {
404 continue;
406 #endif // TARGET_WINNT
407 #if HOST_LIBRARY
408 OFFLOAD_DEBUG_TRACE(2, " %s %p %p\n",
409 e->funcName, e->funcAddr, e->localThunkAddr);
410 #else // HOST_LIBRARY
411 OFFLOAD_DEBUG_TRACE(2, " %s %p %p %p\n",
412 e->funcName, e->funcAddr, e->wrapFuncAddr, e->localThunkAddr);
413 #endif // HOST_LIBRARY
417 m_lock.unlock();
420 // check if any shared functions
421 bool MYOFuncTableList::is_empty()
423 OFFLOAD_DEBUG_TRACE(3, "Are MYO Func tables empty?\n");
425 m_lock.lock();
427 for (Node *n = m_head; n != 0; n = n->next) {
428 int count = 0;
429 for (const Table::Entry *e = n->table.entries;
430 e->funcName != MYO_TABLE_END_MARKER(); e++) {
431 #ifdef TARGET_WINNT
432 if (e->funcName == 0) {
433 continue;
435 #endif // TARGET_WINNT
436 count++;
437 if (count > 1) {
438 m_lock.unlock();
439 OFFLOAD_DEBUG_TRACE(3, "No\n");
440 return false;
445 m_lock.unlock();
446 OFFLOAD_DEBUG_TRACE(3, "Yes\n");
447 return true;
450 void MYOInitTableList::dump(void)
452 OFFLOAD_DEBUG_TRACE(2, "MYO Init tables:\n");
454 m_lock.lock();
456 for (Node *n = m_head; n != 0; n = n->next) {
457 OFFLOAD_DEBUG_TRACE(2, " MYO Init table:\n");
458 for (const Table::Entry *e = n->table.entries;
459 #ifdef TARGET_WINNT
460 e->funcName != MYO_TABLE_END_MARKER(); e++) {
461 if (e->funcName == 0) {
462 continue;
464 OFFLOAD_DEBUG_TRACE(2, " %s %p\n", e->funcName, e->func);
465 #else // TARGET_WINNT
466 e->func != 0; e++) {
467 OFFLOAD_DEBUG_TRACE(2, " %p\n", e->func);
468 #endif // TARGET_WINNT
472 m_lock.unlock();
475 // check if any shared functions
476 bool MYOInitTableList::is_empty()
478 OFFLOAD_DEBUG_TRACE(3, "Are MYO Init tables empty?\n");
480 m_lock.lock();
482 for (Node *n = m_head; n != 0; n = n->next) {
483 for (const Table::Entry *e = n->table.entries;
484 #ifdef TARGET_WINNT
485 e->funcName != MYO_TABLE_END_MARKER(); e++) {
486 if (e->funcName == 0) {
487 continue;
489 m_lock.unlock();
490 OFFLOAD_DEBUG_TRACE(3, "No\n");
491 return false;
492 #else // TARGET_WINNT
493 e->func != 0; e++) {
494 #endif // TARGET_WINNT
498 m_lock.unlock();
499 OFFLOAD_DEBUG_TRACE(3, "Yes\n");
500 return true;
503 extern "C" void __offload_myoRegisterTables1(
504 MYOInitTableList::Node *init_table,
505 MYOVarTableList::Node *shared_table,
506 MYOVarTableList::Node *shared_vtable,
507 MYOFuncTableList::Node *fptr_table
510 OFFLOAD_DEBUG_TRACE(2, "Registering MYO shared var table %p\n",
511 shared_table);
512 __offload_myo_var_tables.add_table(shared_table);
514 OFFLOAD_DEBUG_TRACE(2, "Registering MYO shared vtable table %p\n",
515 shared_vtable);
516 __offload_myo_vtable_tables.add_table(shared_vtable);
518 OFFLOAD_DEBUG_TRACE(2, "Registering MYO function table %p\n", fptr_table);
519 __offload_myo_func_tables.add_table(fptr_table);
521 OFFLOAD_DEBUG_TRACE(2, "Registering MYO init table %p\n", init_table);
522 __offload_myo_init_tables.add_table(init_table);
525 extern "C" void __offload_myoRemoveTables(
526 MYOInitTableList::Node *init_table,
527 MYOVarTableList::Node *shared_table,
528 MYOVarTableList::Node *shared_vtable,
529 MYOFuncTableList::Node *fptr_table
532 OFFLOAD_DEBUG_TRACE(3, "%s\n", __func__);
534 OFFLOAD_DEBUG_TRACE(2, "Removing MYO shared var table %p\n",
535 shared_table);
536 __offload_myo_var_tables.remove_table(shared_table);
538 OFFLOAD_DEBUG_TRACE(2, "Removing MYO shared vtable table %p\n",
539 shared_vtable);
540 __offload_myo_vtable_tables.remove_table(shared_vtable);
542 OFFLOAD_DEBUG_TRACE(2, "Removing MYO function table %p\n", fptr_table);
543 __offload_myo_func_tables.remove_table(fptr_table);
545 OFFLOAD_DEBUG_TRACE(2, "Removing MYO init table %p\n", init_table);
546 __offload_myo_init_tables.remove_table(init_table);
549 #endif // MYO_SUPPORT