1 /*
2     Copyright (c) 2014-2015 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 #if HOST_LIBRARY
32 #include "offload_table.h"
33 #include "offload_myo_host.h"
34 #else
35 #include "compiler_if_target.h"
36 #include "offload_target.h"
37 #include "offload_myo_target.h"
38 #endif
39 
40 // Initializes library and registers specified offload image.
41 // Don't use this declarations from offload_host.h as offload_table.h
42 // is used instead of it. Using offload_host.h contradicts with
43 // STL library compiled with VS2010.
44 extern "C" bool __offload_register_image(const void* image);
45 extern "C" void __offload_unregister_image(const void* image);
46 extern "C" bool __offload_target_image_is_executable(const void *image);
47 
48 #ifdef TARGET_WINNT
49 #define ALLOCATE(name) __declspec(allocate(name))
50 #define DLL_LOCAL
51 #else // TARGET_WINNT
52 #define ALLOCATE(name) __attribute__((section(name)))
53 #define DLL_LOCAL  __attribute__((visibility("hidden")))
54 #endif // TARGET_WINNT
55 
56 #if HOST_LIBRARY
57 // the host program/shared library should always have __offload_target_image
58 // symbol defined. This symbol specifies the beginning of the target program
59 // image.
60 extern "C" DLL_LOCAL const void* __offload_target_image;
61 #else // HOST_LIBRARY
62 // Define a weak main which would be used on target side in case usere's
63 // source file containing main does not have offload code.
64 #pragma weak main
main(void)65 int main(void)
66 {
67     OFFLOAD_TARGET_MAIN();
68     return 0;
69 }
70 
71 #pragma weak MAIN__
MAIN__(void)72 extern "C" int MAIN__(void)
73 {
74     OFFLOAD_TARGET_MAIN();
75     return 0;
76 }
77 #endif // HOST_LIBRARY
78 
79 // offload section prolog
80 ALLOCATE(OFFLOAD_ENTRY_TABLE_SECTION_START)
81 #ifdef TARGET_WINNT
82 __declspec(align(sizeof(FuncTable::Entry)))
83 #endif // TARGET_WINNT
84 static FuncTable::Entry __offload_entry_table_start = { 0 };
85 
86 // list element for the current module
87 static FuncList::Node __offload_entry_node = {
88     { &__offload_entry_table_start + 1, -1 },
89     0, 0
90 };
91 
92 // offload fp section prolog
93 ALLOCATE(OFFLOAD_FUNC_TABLE_SECTION_START)
94 #ifdef TARGET_WINNT
95 __declspec(align(sizeof(FuncTable::Entry)))
96 #endif // TARGET_WINNT
97 static FuncTable::Entry __offload_func_table_start = { 0 };
98 
99 // list element for the current module
100 static FuncList::Node __offload_func_node = {
101     { &__offload_func_table_start + 1, -1 },
102     0, 0
103 };
104 
105 // offload fp section prolog
106 ALLOCATE(OFFLOAD_VAR_TABLE_SECTION_START)
107 #ifdef TARGET_WINNT
108 __declspec(align(sizeof(VarTable::Entry)))
109 #endif // TARGET_WINNT
110 static VarTable::Entry __offload_var_table_start = { 0 };
111 
112 // list element for the current module
113 static VarList::Node __offload_var_node = {
114     { &__offload_var_table_start + 1 },
115     0, 0
116 };
117 
118 #ifdef MYO_SUPPORT
119 
120 // offload myo shared var section prolog
121 // first element is empty
122 ALLOCATE(OFFLOAD_MYO_SHARED_TABLE_SECTION_START)
123 #ifdef TARGET_WINNT
124 __declspec(align(sizeof(SharedTableEntry)))
125 #endif // TARGET_WINNT
126 static MYOVarTable::Entry __offload_myo_shared_var_start = { 0 };
127 
128 // list element for the current module
129 // table entry pointer skips the empty first entry
130 static MYOVarTableList::Node __offload_myo_shared_var_node = {
131     { &__offload_myo_shared_var_start + 1 },
132     0, 0
133 };
134 
135 // offload myo shared vtable section prolog
136 // first element is empty
137 ALLOCATE(OFFLOAD_MYO_SHARED_VTABLE_SECTION_START)
138 #ifdef TARGET_WINNT
139 __declspec(align(sizeof(SharedTableEntry)))
140 #endif // TARGET_WINNT
141 static MYOVarTable::Entry __offload_myo_shared_vtable_start = { 0 };
142 
143 // list element for the current module
144 // table entry pointer skips the empty first entry
145 static MYOVarTableList::Node __offload_myo_shared_vtable_node = {
146     { &__offload_myo_shared_vtable_start + 1 },
147     0, 0
148 };
149 
150 // offload myo shared var init section prolog
151 // first element is empty
152 ALLOCATE(OFFLOAD_MYO_SHARED_INIT_TABLE_SECTION_START)
153 #ifdef TARGET_WINNT
154 __declspec(align(sizeof(InitTableEntry)))
155 #endif // TARGET_WINNT
156 static MYOInitTable::Entry __offload_myo_init_table_start = { 0 };
157 
158 // list element for the current module
159 // table entry pointer skips the empty first entry
160 static MYOInitTableList::Node __offload_myo_init_table_node = {
161     { &__offload_myo_init_table_start + 1 },
162     0, 0
163 };
164 
165 // The functions and variables needed for a built-in
166 // remote function entry for vtable initialization on MIC
167 
168 #if !HOST_LIBRARY
__offload_init_vtables(void)169 MyoError __offload_init_vtables(void)
170 {
171     SharedTableEntry *t_start;
172 
173     //OFFLOAD_DEBUG_TRACE(3, "%s\n", __func__);
174     t_start = &__offload_myo_shared_vtable_start + 1;
175     //OFFLOAD_DEBUG_TRACE(3, "%s(%p)\n", __func__, t_start);
176     while (t_start->varName != 0) {
177         //OFFLOAD_DEBUG_TRACE(4,
178         //    "myo shared vtable \"%s\" &myo_ptr = %p myo_ptr = %p\n",
179         //    t_start->varName,
180         //    (void *)(t_start->sharedAddr),
181         //    ((void **)(t_start->sharedAddr))[0]);
182         t_start++;
183     }
184 
185     __offload_myo_shared_init_table_process(
186         &__offload_myo_init_table_start + 1);
187     return MYO_SUCCESS;
188 }
189 #endif  // !HOST_LIBRARY
190 
vtable_initializer()191 static void vtable_initializer()
192 {
193 }
194 
195 #if !HOST_LIBRARY
vtable_initializer_wrapper()196 static MyoError vtable_initializer_wrapper()
197 {
198     __offload_myoAcquire();
199     __offload_init_vtables();
200     __offload_myoRelease();
201     return MYO_SUCCESS;
202 }
203 #endif
204 
205 static void* __offload_vtable_initializer_thunk_ptr = 0;
206 
207 // offload myo fptr section prolog
208 // first element is pre-initialized to the MIC vtable initializer
209 ALLOCATE(OFFLOAD_MYO_FPTR_TABLE_SECTION_START)
210 #ifdef TARGET_WINNT
211 __declspec(align(sizeof(FptrTableEntry)))
212 #endif // TARGET_WINNT
213 static MYOFuncTable::Entry __offload_myo_fptr_table_start = {
214 #if HOST_LIBRARY
215     "--vtable_initializer--",
216     (void*)&vtable_initializer,
217     (void*)&__offload_vtable_initializer_thunk_ptr,
218 #ifdef TARGET_WINNT
219     // Dummy to pad up to 32 bytes
220     0
221 #endif // TARGET_WINNT
222 #else  // HOST_LIBRARY
223     "--vtable_initializer--",
224     (void*)&vtable_initializer,
225     (void*)&vtable_initializer_wrapper,
226     &__offload_vtable_initializer_thunk_ptr,
227 #endif // HOST_LIBRARY
228 };
229 
230 // list element for the current module
231 static MYOFuncTableList::Node __offload_myo_fptr_table_node = {
232     { &__offload_myo_fptr_table_start },
233     0, 0
234 };
235 
236 #endif // MYO_SUPPORT
237 
238 // init/fini code which adds/removes local lookup data to/from the global list
239 
240 static void offload_fini();
241 static void offload_fini_so();
242 
243 #ifndef TARGET_WINNT
244 static void offload_init() __attribute__((constructor(101)));
245 #else // TARGET_WINNT
246 static void offload_init();
247 
248 // Place offload initialization before user constructors
249 ALLOCATE(OFFLOAD_CRTINIT_SECTION_START)
250 static void (*addressof_offload_init)() = offload_init;
251 #endif // TARGET_WINNT
252 
offload_init()253 static void offload_init()
254 {
255     bool success;
256 
257     // register offload tables
258     __offload_register_tables(&__offload_entry_node,
259                               &__offload_func_node,
260                               &__offload_var_node);
261 
262 #if HOST_LIBRARY
263     success = __offload_register_image(&__offload_target_image);
264     if (!success)
265     {
266         return;
267     }
268 #endif // HOST_LIBRARY
269 #ifdef MYO_SUPPORT
270 #if HOST_LIBRARY
271     // If this was the main program register main atexit routine
272     if (__offload_myoProcessTables(
273             &__offload_target_image,
274             &__offload_myo_init_table_node,
275             &__offload_myo_shared_var_node,
276             &__offload_myo_shared_vtable_node,
277             &__offload_myo_fptr_table_node))
278     {
279         atexit(offload_fini);
280 #ifdef TARGET_WINNT
281     } else {
282         atexit(offload_fini_so);
283 #endif
284     }
285 #else // HOST_LIBRARY
286     __offload_myoProcessTables(
287         &__offload_myo_init_table_start + 1,
288         &__offload_myo_shared_var_start + 1,
289         &__offload_myo_shared_vtable_start + 1,
290         &__offload_myo_fptr_table_start
291     );
292 #endif // HOST_LIBRARY
293 #endif // MYO_SUPPORT
294 }
295 
296 #ifndef TARGET_WINNT
297 static void offload_fini_so() __attribute__((destructor(101)));
298 #else // TARGET_WINNT
299 static void offload_init_so();
300 #endif // TARGET_WINNT
301 
offload_fini()302 static void offload_fini()
303 {
304 #if HOST_LIBRARY
305     __offload_unregister_image(&__offload_target_image);
306 #endif // HOST_LIBRARY
307 }
308 
offload_fini_so()309 static void offload_fini_so()
310 {
311     // Offload and MYO tables need to be removed from list
312     // to prevent invalid accesses after dlclose
313     // Remove offload tables
314     __offload_unregister_tables(&__offload_entry_node,
315                                 &__offload_func_node,
316                                 &__offload_var_node);
317 #if HOST_LIBRARY
318    if(!__offload_target_image_is_executable(&__offload_target_image)) {
319       __offload_unregister_image(&__offload_target_image);
320    }
321 #endif
322 #ifdef MYO_SUPPORT
323 #if HOST_LIBRARY
324     // Remove MYO tables
325     __offload_myoRemoveTables(
326         &__offload_myo_init_table_node,
327         &__offload_myo_shared_var_node,
328         &__offload_myo_shared_vtable_node,
329         &__offload_myo_fptr_table_node);
330 #endif // HOST_LIBRARY
331 #endif // MYO_SUPPORT
332 }
333