123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671 |
- /*
- Copyright (c) 2014-2016 Intel Corporation. All Rights Reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "offload_table.h"
- #include "offload_common.h"
- // Offload Library versioning
- // We initialize version to OFFLOAD_VERSION_16
- // 15.0 application downgrades this to 1500 for MYO to use the older version.
- // 15.0 pragma works without needing version-specific code.
- // 16.0-U2 added a call from ofldbegin.cpp to set the version explicitly.
- // Pre-16.0-U2 application will find pre-initialized version number as 1600.
- // Post 16.0-U2 application will set its own version explicitly.
- int offload_version = OFFLOAD_VERSION_16;
- int offload_version_count = 0;
- #if !HOST_LIBRARY
- // Predefined offload entries
- extern void omp_set_num_threads_lrb(void*);
- extern void omp_get_max_threads_lrb(void*);
- extern void omp_get_num_procs_lrb(void*);
- extern void omp_set_dynamic_lrb(void*);
- extern void omp_get_dynamic_lrb(void*);
- extern void omp_set_nested_lrb(void*);
- extern void omp_get_nested_lrb(void*);
- extern void omp_set_schedule_lrb(void*);
- extern void omp_get_schedule_lrb(void*);
- extern void omp_init_lock_lrb(void*);
- extern void omp_destroy_lock_lrb(void*);
- extern void omp_set_lock_lrb(void*);
- extern void omp_unset_lock_lrb(void*);
- extern void omp_test_lock_lrb(void*);
- extern void omp_init_nest_lock_lrb(void*);
- extern void omp_destroy_nest_lock_lrb(void*);
- extern void omp_set_nest_lock_lrb(void*);
- extern void omp_unset_nest_lock_lrb(void*);
- extern void omp_test_nest_lock_lrb(void*);
- // OpenMP 4.5 APIs
- extern void omp_target_alloc_target(void*);
- extern void omp_target_free_target(void*);
- extern void omp_target_memcpy_target(void*);
- extern void omp_target_memcpy_rect_target(void*);
- // Predefined entries on the target side
- static FuncTable::Entry predefined_entries[] = {
- "omp_set_num_threads_target",
- (void*) &omp_set_num_threads_lrb,
- "omp_get_max_threads_target",
- (void*) &omp_get_max_threads_lrb,
- "omp_get_num_procs_target",
- (void*) &omp_get_num_procs_lrb,
- "omp_set_dynamic_target",
- (void*) &omp_set_dynamic_lrb,
- "omp_get_dynamic_target",
- (void*) &omp_get_dynamic_lrb,
- "omp_set_nested_target",
- (void*) &omp_set_nested_lrb,
- "omp_get_nested_target",
- (void*) &omp_get_nested_lrb,
- "omp_set_schedule_target",
- (void*) &omp_set_schedule_lrb,
- "omp_get_schedule_target",
- (void*) &omp_get_schedule_lrb,
- "omp_init_lock_target",
- (void*) &omp_init_lock_lrb,
- "omp_destroy_lock_target",
- (void*) &omp_destroy_lock_lrb,
- "omp_set_lock_target",
- (void*) &omp_set_lock_lrb,
- "omp_unset_lock_target",
- (void*) &omp_unset_lock_lrb,
- "omp_test_lock_target",
- (void*) &omp_test_lock_lrb,
- "omp_init_nest_lock_target",
- (void*) &omp_init_nest_lock_lrb,
- "omp_destroy_nest_lock_target",
- (void*) &omp_destroy_nest_lock_lrb,
- "omp_set_nest_lock_target",
- (void*) &omp_set_nest_lock_lrb,
- "omp_unset_nest_lock_target",
- (void*) &omp_unset_nest_lock_lrb,
- "omp_test_nest_lock_target",
- (void*) &omp_test_nest_lock_lrb,
- "omp_target_alloc_target",
- (void*) &omp_target_alloc_target,
- "omp_target_free_target",
- (void*) &omp_target_free_target,
- "omp_target_memcpy_target",
- (void*) &omp_target_memcpy_target,
- "omp_target_memcpy_rect_target",
- (void*) &omp_target_memcpy_rect_target,
- (const char*) -1,
- (void*) -1
- };
- static FuncList::Node predefined_table = {
- { predefined_entries, -1 },
- 0, 0
- };
- // Entry table
- FuncList __offload_entries(&predefined_table);
- #else
- FuncList __offload_entries;
- #endif // !HOST_LIBRARY
- extern "C" {
- // Set library version
- void __offload_set_version(int v)
- {
- offload_version_count++;
- if (offload_version_count == 1)
- {
- offload_version = v;
- }
- else
- {
- // Mix of versions is not supported
- if (v != offload_version)
- {
- LIBOFFLOAD_ERROR(c_mixed_versions);
- exit(1);
- }
- }
- }
- } // extern "C"
- // Function table. No predefined entries.
- FuncList __offload_funcs;
- // Var table
- VarList __offload_vars;
- // Given the function name returns the associtated function pointer
- const void* FuncList::find_addr(const char *name)
- {
- const void* func = 0;
- m_lock.lock();
- for (Node *n = m_head; n != 0; n = n->next) {
- for (const Table::Entry *e = n->table.entries;
- e->name != (const char*) -1; e++) {
- if (e->name != 0 && strcmp(e->name, name) == 0) {
- func = e->func;
- break;
- }
- }
- }
- m_lock.unlock();
- return func;
- }
- // Given the function pointer returns the associtated function name
- const char* FuncList::find_name(const void *func)
- {
- const char* name = 0;
- m_lock.lock();
- for (Node *n = m_head; n != 0; n = n->next) {
- for (const Table::Entry *e = n->table.entries;
- e->name != (const char*) -1; e++) {
- if (e->func == func) {
- name = e->name;
- break;
- }
- }
- }
- m_lock.unlock();
- return name;
- }
- // Returns max name length from all tables
- int64_t FuncList::max_name_length(void)
- {
- if (m_max_name_len < 0) {
- m_lock.lock();
- m_max_name_len = 0;
- for (Node *n = m_head; n != 0; n = n->next) {
- if (n->table.max_name_len < 0) {
- n->table.max_name_len = 0;
- // calculate max name length in a single table
- for (const Table::Entry *e = n->table.entries;
- e->name != (const char*) -1; e++) {
- if (e->name != 0) {
- size_t len = strlen(e->name) + 1;
- if (n->table.max_name_len < len) {
- n->table.max_name_len = len;
- }
- }
- }
- }
- // select max from all tables
- if (m_max_name_len < n->table.max_name_len) {
- m_max_name_len = n->table.max_name_len;
- }
- }
- m_lock.unlock();
- }
- return m_max_name_len;
- }
- // Debugging dump
- void FuncList::dump(void)
- {
- OFFLOAD_DEBUG_TRACE(2, "Function table:\n");
- m_lock.lock();
- for (Node *n = m_head; n != 0; n = n->next) {
- for (const Table::Entry *e = n->table.entries;
- e->name != (const char*) -1; e++) {
- if (e->name != 0) {
- OFFLOAD_DEBUG_TRACE(2, "%p %s\n", e->func, e->name);
- }
- }
- }
- m_lock.unlock();
- }
- // Debugging dump
- void VarList::dump(void)
- {
- OFFLOAD_DEBUG_TRACE(2, "Var table:\n");
- m_lock.lock();
- for (Node *n = m_head; n != 0; n = n->next) {
- for (const Table::Entry *e = n->table.entries;
- e->name != (const char*) -1; e++) {
- if (e->name != 0) {
- #if HOST_LIBRARY
- OFFLOAD_DEBUG_TRACE(2, "%s %p %ld\n", e->name, e->addr,
- e->size);
- #else // HOST_LIBRARY
- OFFLOAD_DEBUG_TRACE(2, "%s %p\n", e->name, e->addr);
- #endif // HOST_LIBRARY
- }
- }
- }
- m_lock.unlock();
- }
- //
- int64_t VarList::table_size(int64_t &nelems)
- {
- int64_t length = 0;
- nelems = 0;
- // calculate string table size and number of elements
- for (Node *n = m_head; n != 0; n = n->next) {
- for (const Table::Entry *e = n->table.entries;
- e->name != (const char*) -1; e++) {
- if (e->name != 0) {
- length += strlen(e->name) + 1;
- nelems++;
- }
- }
- }
- return nelems * sizeof(BufEntry) + length;
- }
- // copy table to the gven buffer
- void VarList::table_copy(void *buf, int64_t nelems)
- {
- BufEntry* elems = static_cast<BufEntry*>(buf);
- char* names = reinterpret_cast<char*>(elems + nelems);
- // copy entries to buffer
- for (Node *n = m_head; n != 0; n = n->next) {
- for (const Table::Entry *e = n->table.entries;
- e->name != (const char*) -1; e++) {
- if (e->name != 0) {
- // name field contains offset to the name from the beginning
- // of the buffer
- elems->name = names - static_cast<char*>(buf);
- elems->addr = reinterpret_cast<intptr_t>(e->addr);
- // copy name to string table
- const char *name = e->name;
- while ((*names++ = *name++) != '\0');
- elems++;
- }
- }
- }
- }
- // patch name offsets in a buffer
- void VarList::table_patch_names(void *buf, int64_t nelems)
- {
- BufEntry* elems = static_cast<BufEntry*>(buf);
- for (int i = 0; i < nelems; i++) {
- elems[i].name += reinterpret_cast<intptr_t>(buf);
- }
- }
- #if HOST_LIBRARY
- // 16.0 and earlier compilers used the following VarTable
- struct OldVarTable {
- const char* name;
- void* addr;
- // uint64_t var_alloc_type missing in 16.0 and earlier
- uint64_t size;
- };
- static void convert_OldVarTable_to_NewVarTable(VarList::Node *vt_start)
- {
- int table_size = 0;
- char * new_var_table;
- OldVarTable *old_var_table;
- OFFLOAD_DEBUG_TRACE(2,
- "Converting old var table to new var table to support backward compatiblity\n");
- // Calculate size of memory to be malloced
- old_var_table = (OldVarTable *) vt_start->table.entries;
- while (old_var_table->name != (const char*) -1) {
- table_size++;
- old_var_table++;
- }
- if (table_size != 0) {
- // Add 1 to table_size for end of table signature
- VarTable::Entry *new_var_table =
- new VarTable::Entry[table_size+1];
- if (new_var_table == NULL)
- LIBOFFLOAD_ERROR(c_malloc);
- old_var_table = (OldVarTable *) vt_start->table.entries;
- // Update VarList with new table
- vt_start->table.entries = new_var_table;
- // Fix up the new table value from old table
- for (int i=0; i< table_size; i++) {
- new_var_table->name = old_var_table->name;
- new_var_table->addr = old_var_table->addr;
- new_var_table->size = old_var_table->size;
- // Assign value of 0 for the missing field.
- // Implying it is neither IMPLICIT or LINK variable as
- // they were not supported in earlier compilers
- new_var_table->var_alloc_type = 0;
- old_var_table++;
- new_var_table++;
- }
- new_var_table->name = (const char *)-1;
- }
- }
- #endif //HOST_LIBRARY
- // Adds given list element to the global lookup table list
- extern "C" void __offload_register_tables(
- FuncList::Node *entry_table,
- FuncList::Node *func_table,
- VarList::Node *var_table
- )
- {
- OFFLOAD_DEBUG_TRACE(2, "Registering offload function entry table %p\n",
- entry_table);
- __offload_entries.add_table(entry_table);
- OFFLOAD_DEBUG_TRACE(2, "Registering function table %p\n", func_table);
- __offload_funcs.add_table(func_table);
- OFFLOAD_DEBUG_TRACE(2, "Registering var table %p\n", var_table);
- // Compiler earlier than 17.0 used a different var_table.
- // Convert the old table to new var_table format.
- // Only the host table for LINUX has changed.
- #ifndef TARGET_WINNT
- #if HOST_LIBRARY
- if (offload_version < OFFLOAD_VERSION_17) {
- convert_OldVarTable_to_NewVarTable(var_table);
- }
- #endif
- #endif
- __offload_vars.add_table(var_table);
- }
- // Removes given list element from the global lookup table list
- extern "C" void __offload_unregister_tables(
- FuncList::Node *entry_table,
- FuncList::Node *func_table,
- VarList::Node *var_table
- )
- {
- OFFLOAD_DEBUG_TRACE(2, "Unregistering offload function entry table %p\n",
- entry_table);
- __offload_entries.remove_table(entry_table);
- OFFLOAD_DEBUG_TRACE(2, "Unregistering function table %p\n", func_table);
- __offload_funcs.remove_table(func_table);
- OFFLOAD_DEBUG_TRACE(2, "Unregistering var table %p\n", var_table);
- #ifndef TARGET_WINNT
- #if HOST_LIBRARY
- if (offload_version < OFFLOAD_VERSION_17) {
- // Free the malloced var_table created for backward compatiblity
- delete var_table->table.entries;
- }
- #endif
- #endif
- __offload_vars.remove_table(var_table);
- }
- #ifdef MYO_SUPPORT
- MYOVarTableList __offload_myo_var_tables;
- MYOVarTableList __offload_myo_vtable_tables;
- MYOFuncTableList __offload_myo_func_tables;
- MYOInitTableList __offload_myo_init_tables;
- // Debugging dump
- void MYOVarTableList::dump(void)
- {
- OFFLOAD_DEBUG_TRACE(2, "MYO Var tables:\n");
- m_lock.lock();
- for (Node *n = m_head; n != 0; n = n->next) {
- OFFLOAD_DEBUG_TRACE(2, " MYO Var table:\n");
- for (const Table::Entry *e = n->table.entries;
- e->varName != MYO_TABLE_END_MARKER(); e++) {
- #ifdef TARGET_WINNT
- if (e->varName == 0) {
- continue;
- }
- #endif // TARGET_WINNT
- OFFLOAD_DEBUG_TRACE(2, " %s %p\n",
- e->varName, e->sharedAddr);
- }
- }
- m_lock.unlock();
- }
- // check if any shared variables
- bool MYOVarTableList::is_empty()
- {
- OFFLOAD_DEBUG_TRACE(3, "Are MYO Var tables empty?\n");
- m_lock.lock();
- for (Node *n = m_head; n != 0; n = n->next) {
- for (const Table::Entry *e = n->table.entries;
- e->varName != MYO_TABLE_END_MARKER(); e++) {
- #ifdef TARGET_WINNT
- if (e->varName == 0) {
- continue;
- }
- #endif // TARGET_WINNT
- m_lock.unlock();
- OFFLOAD_DEBUG_TRACE(3, "No\n");
- return false;
- }
- }
- m_lock.unlock();
- OFFLOAD_DEBUG_TRACE(3, "Yes\n");
- return true;
- }
- void MYOFuncTableList::dump(void)
- {
- OFFLOAD_DEBUG_TRACE(2, "MYO Func tables:\n");
- m_lock.lock();
- for (Node *n = m_head; n != 0; n = n->next) {
- OFFLOAD_DEBUG_TRACE(2, " MYO Func table:\n");
- for (const Table::Entry *e = n->table.entries;
- e->funcName != MYO_TABLE_END_MARKER(); e++) {
- #ifdef TARGET_WINNT
- if (e->funcName == 0) {
- continue;
- }
- #endif // TARGET_WINNT
- #if HOST_LIBRARY
- OFFLOAD_DEBUG_TRACE(2, " %s %p %p\n",
- e->funcName, e->funcAddr, e->localThunkAddr);
- #else // HOST_LIBRARY
- OFFLOAD_DEBUG_TRACE(2, " %s %p %p %p\n",
- e->funcName, e->funcAddr, e->wrapFuncAddr, e->localThunkAddr);
- #endif // HOST_LIBRARY
- }
- }
- m_lock.unlock();
- }
- // check if any shared functions
- bool MYOFuncTableList::is_empty()
- {
- OFFLOAD_DEBUG_TRACE(3, "Are MYO Func tables empty?\n");
- m_lock.lock();
- for (Node *n = m_head; n != 0; n = n->next) {
- int count = 0;
- for (const Table::Entry *e = n->table.entries;
- e->funcName != MYO_TABLE_END_MARKER(); e++) {
- #ifdef TARGET_WINNT
- if (e->funcName == 0) {
- continue;
- }
- #endif // TARGET_WINNT
- count++;
- if (count > 1) {
- m_lock.unlock();
- OFFLOAD_DEBUG_TRACE(3, "No\n");
- return false;
- }
- }
- }
- m_lock.unlock();
- OFFLOAD_DEBUG_TRACE(3, "Yes\n");
- return true;
- }
- void MYOInitTableList::dump(void)
- {
- OFFLOAD_DEBUG_TRACE(2, "MYO Init tables:\n");
- m_lock.lock();
- for (Node *n = m_head; n != 0; n = n->next) {
- OFFLOAD_DEBUG_TRACE(2, " MYO Init table:\n");
- for (const Table::Entry *e = n->table.entries;
- #ifdef TARGET_WINNT
- e->funcName != MYO_TABLE_END_MARKER(); e++) {
- if (e->funcName == 0) {
- continue;
- }
- OFFLOAD_DEBUG_TRACE(2, " %s %p\n", e->funcName, e->func);
- #else // TARGET_WINNT
- e->func != 0; e++) {
- OFFLOAD_DEBUG_TRACE(2, " %p\n", e->func);
- #endif // TARGET_WINNT
- }
- }
- m_lock.unlock();
- }
- // check if any shared functions
- bool MYOInitTableList::is_empty()
- {
- OFFLOAD_DEBUG_TRACE(3, "Are MYO Init tables empty?\n");
- m_lock.lock();
- for (Node *n = m_head; n != 0; n = n->next) {
- for (const Table::Entry *e = n->table.entries;
- #ifdef TARGET_WINNT
- e->funcName != MYO_TABLE_END_MARKER(); e++) {
- if (e->funcName == 0) {
- continue;
- }
- m_lock.unlock();
- OFFLOAD_DEBUG_TRACE(3, "No\n");
- return false;
- #else // TARGET_WINNT
- e->func != 0; e++) {
- #endif // TARGET_WINNT
- }
- }
- m_lock.unlock();
- OFFLOAD_DEBUG_TRACE(3, "Yes\n");
- return true;
- }
- extern "C" void __offload_myoRegisterTables1(
- MYOInitTableList::Node *init_table,
- MYOVarTableList::Node *shared_table,
- MYOVarTableList::Node *shared_vtable,
- MYOFuncTableList::Node *fptr_table
- )
- {
- OFFLOAD_DEBUG_TRACE(2, "Registering MYO shared var table %p\n",
- shared_table);
- __offload_myo_var_tables.add_table(shared_table);
- OFFLOAD_DEBUG_TRACE(2, "Registering MYO shared vtable table %p\n",
- shared_vtable);
- __offload_myo_vtable_tables.add_table(shared_vtable);
- OFFLOAD_DEBUG_TRACE(2, "Registering MYO function table %p\n", fptr_table);
- __offload_myo_func_tables.add_table(fptr_table);
- OFFLOAD_DEBUG_TRACE(2, "Registering MYO init table %p\n", init_table);
- __offload_myo_init_tables.add_table(init_table);
- }
- extern "C" void __offload_myoRemoveTables(
- MYOInitTableList::Node *init_table,
- MYOVarTableList::Node *shared_table,
- MYOVarTableList::Node *shared_vtable,
- MYOFuncTableList::Node *fptr_table
- )
- {
- OFFLOAD_DEBUG_TRACE(3, "%s\n", __func__);
- OFFLOAD_DEBUG_TRACE(2, "Removing MYO shared var table %p\n",
- shared_table);
- __offload_myo_var_tables.remove_table(shared_table);
- OFFLOAD_DEBUG_TRACE(2, "Removing MYO shared vtable table %p\n",
- shared_vtable);
- __offload_myo_vtable_tables.remove_table(shared_vtable);
- OFFLOAD_DEBUG_TRACE(2, "Removing MYO function table %p\n", fptr_table);
- __offload_myo_func_tables.remove_table(fptr_table);
- OFFLOAD_DEBUG_TRACE(2, "Removing MYO init table %p\n", init_table);
- __offload_myo_init_tables.remove_table(init_table);
- }
- #endif // MYO_SUPPORT
|