mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			672 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			672 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|     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
 |