Remove assert in get_def_bb_for_const
[official-gcc.git] / liboffloadmic / runtime / offload_myo_host.cpp
blob621494906413c247a677c8b64df2660da128d96d
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 #if defined(LINUX) || defined(FREEBSD)
32 #include <mm_malloc.h>
33 #endif
35 #include "offload_myo_host.h"
36 #include <errno.h>
37 #include <malloc.h>
38 #include "offload_host.h"
39 //#include "offload_util.h"
41 #define MYO_VERSION1 "MYO_1.0"
43 extern "C" void __cilkrts_cilk_for_32(void*, void*, uint32_t, int32_t);
44 extern "C" void __cilkrts_cilk_for_64(void*, void*, uint64_t, int32_t);
46 #ifndef TARGET_WINNT
47 #pragma weak __cilkrts_cilk_for_32
48 #pragma weak __cilkrts_cilk_for_64
49 #endif // TARGET_WINNT
51 static void __offload_myoProcessDeferredTables();
53 class MyoWrapper {
54 public:
55 MyoWrapper() : m_lib_handle(0), m_is_available(false)
58 bool is_available() const {
59 return m_is_available;
62 bool LoadLibrary(void);
64 // unloads the library
65 void UnloadLibrary(void) {
66 // if (m_lib_handle != 0) {
67 // DL_close(m_lib_handle);
68 // m_lib_handle = 0;
69 // }
72 // Wrappers for MYO client functions
73 void LibInit(void *arg, void *func) const {
74 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myoinit,
75 "%s(%p, %p)\n", __func__, arg, func);
76 CheckResult(__func__, m_lib_init(arg, func));
79 void LibFini(void) const {
80 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myofini, "%s()\n", __func__);
81 m_lib_fini();
84 void* SharedMalloc(size_t size) const {
85 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myosharedmalloc,
86 "%s(%lld)\n", __func__, size);
87 return m_shared_malloc(size);
90 void SharedFree(void *ptr) const {
91 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myosharedfree,
92 "%s(%p)\n", __func__, ptr);
93 m_shared_free(ptr);
96 void* SharedAlignedMalloc(size_t size, size_t align) const {
97 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myosharedalignedmalloc,
98 "%s(%lld, %lld)\n", __func__, size, align);
99 return m_shared_aligned_malloc(size, align);
102 void SharedAlignedFree(void *ptr) const {
103 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myosharedalignedfree,
104 "%s(%p)\n", __func__, ptr);
105 m_shared_aligned_free(ptr);
108 void Acquire(void) const {
109 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myoacquire,
110 "%s()\n", __func__);
111 CheckResult(__func__, m_acquire());
114 void Release(void) const {
115 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myorelease,
116 "%s()\n", __func__);
117 CheckResult(__func__, m_release());
120 void HostVarTablePropagate(void *table, int num_entries) const {
121 OFFLOAD_DEBUG_TRACE(4, "%s(%p, %d)\n", __func__, table, num_entries);
122 CheckResult(__func__, m_host_var_table_propagate(table, num_entries));
125 void HostFptrTableRegister(void *table, int num_entries,
126 int ordered) const {
127 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myoregister,
128 "%s(%p, %d, %d)\n", __func__, table,
129 num_entries, ordered);
130 CheckResult(__func__,
131 m_host_fptr_table_register(table, num_entries, ordered));
134 void RemoteThunkCall(void *thunk, void *args, int device) {
135 OFFLOAD_DEBUG_TRACE(4, "%s(%p, %p, %d)\n", __func__, thunk, args,
136 device);
137 CheckResult(__func__, m_remote_thunk_call(thunk, args, device));
140 MyoiRFuncCallHandle RemoteCall(const char *func, void *args, int device) const {
141 OFFLOAD_DEBUG_TRACE(4, "%s(%s, %p, %d)\n", __func__, func, args,
142 device);
143 return m_remote_call(func, args, device);
146 void GetResult(MyoiRFuncCallHandle handle) const {
147 OFFLOAD_DEBUG_TRACE(4, "%s(%p)\n", __func__, handle);
148 CheckResult(__func__, m_get_result(handle));
151 bool PostInitFuncSupported() const {
152 OFFLOAD_DEBUG_TRACE(4, "%s()\n", __func__);
153 if (m_feature_available) {
154 return m_feature_available(MYO_FEATURE_POST_LIB_INIT) ==
155 MYO_SUCCESS;
156 } else {
157 return false;
161 void CreateVtableArena();
163 MyoArena GetVtableArena()const {
164 return m_vtable_arena;
167 void ArenaCreate(
168 MyoOwnershipType ownership,
169 int consistency,
170 MyoArena* arena
171 ) const
173 OFFLOAD_DEBUG_TRACE(4, "%s(%d, %d, %p)\n",
174 __func__, ownership, consistency, arena);
175 CheckResult(__func__, m_arena_create(ownership, consistency, arena));
178 void* SharedAlignedArenaMalloc(
179 MyoArena arena,
180 size_t size,
181 size_t align
182 ) const
184 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myosharedalignedarenamalloc,
185 "%s(%u, %lld, %lld)\n",
186 __func__, arena, size, align);
187 return m_arena_aligned_malloc(arena, size, align);
190 void* SharedAlignedArenaFree(
191 MyoArena arena,
192 void* ptr
193 ) const
195 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myosharedalignedarenafree,
196 "%s(%u, %p)\n", __func__, arena, ptr);
197 return m_arena_aligned_free(arena, ptr);
200 void ArenaAcquire(
201 MyoArena arena
202 ) const
204 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myoarenaacquire,
205 "%s()\n", __func__);
206 CheckResult(__func__, m_arena_acquire(arena));
209 void ArenaRelease(
210 MyoArena arena
211 ) const
213 OFFLOAD_DEBUG_TRACE_1(4, 0, c_offload_myoarenarelease,
214 "%s()\n", __func__);
215 CheckResult(__func__, m_arena_release(arena));
218 private:
219 void CheckResult(const char *func, MyoError error) const {
220 if (error != MYO_SUCCESS) {
221 LIBOFFLOAD_ERROR(c_myowrapper_checkresult, func, error);
222 exit(1);
226 private:
227 void* m_lib_handle;
228 bool m_is_available;
229 int m_post_init_func;
230 MyoArena m_vtable_arena;
232 // pointers to functions from myo library
233 MyoError (*m_lib_init)(void*, void*);
234 void (*m_lib_fini)(void);
235 void* (*m_shared_malloc)(size_t);
236 void (*m_shared_free)(void*);
237 void* (*m_shared_aligned_malloc)(size_t, size_t);
238 void (*m_shared_aligned_free)(void*);
239 MyoError (*m_acquire)(void);
240 MyoError (*m_release)(void);
241 MyoError (*m_host_var_table_propagate)(void*, int);
242 MyoError (*m_host_fptr_table_register)(void*, int, int);
243 MyoError (*m_remote_thunk_call)(void*, void*, int);
244 MyoiRFuncCallHandle (*m_remote_call)(const char*, void*, int);
245 MyoError (*m_get_result)(MyoiRFuncCallHandle);
246 MyoError (*m_arena_create)(MyoOwnershipType, int, MyoArena*);
247 void* (*m_arena_aligned_malloc)(MyoArena, size_t, size_t);
248 void* (*m_arena_aligned_free)(MyoArena, void*);
249 MyoError (*m_arena_acquire)(MyoArena);
250 MyoError (*m_arena_release)(MyoArena);
251 // Placeholder until MYO headers support enum type for feature
252 MyoError (*m_feature_available)(int feature);
255 DLL_LOCAL bool MyoWrapper::LoadLibrary(void)
257 #ifndef TARGET_WINNT
258 const char *lib_name = "libmyo-client.so";
259 #else // TARGET_WINNT
260 const char *lib_name = "myo-client.dll";
261 #endif // TARGET_WINNT
263 OFFLOAD_DEBUG_TRACE(2, "Loading MYO library %s ...\n", lib_name);
265 m_lib_handle = DL_open(lib_name);
266 if (m_lib_handle == 0) {
267 OFFLOAD_DEBUG_TRACE(2, "Failed to load the library. errno = %d\n",
268 errno);
269 return false;
272 m_lib_init = (MyoError (*)(void*, void*))
273 DL_sym(m_lib_handle, "myoiLibInit", MYO_VERSION1);
274 if (m_lib_init == 0) {
275 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
276 "myoiLibInit");
277 UnloadLibrary();
278 return false;
281 m_lib_fini = (void (*)(void))
282 DL_sym(m_lib_handle, "myoiLibFini", MYO_VERSION1);
283 if (m_lib_fini == 0) {
284 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
285 "myoiLibFini");
286 UnloadLibrary();
287 return false;
290 m_shared_malloc = (void* (*)(size_t))
291 DL_sym(m_lib_handle, "myoSharedMalloc", MYO_VERSION1);
292 if (m_shared_malloc == 0) {
293 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
294 "myoSharedMalloc");
295 UnloadLibrary();
296 return false;
299 m_shared_free = (void (*)(void*))
300 DL_sym(m_lib_handle, "myoSharedFree", MYO_VERSION1);
301 if (m_shared_free == 0) {
302 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
303 "myoSharedFree");
304 UnloadLibrary();
305 return false;
308 m_shared_aligned_malloc = (void* (*)(size_t, size_t))
309 DL_sym(m_lib_handle, "myoSharedAlignedMalloc", MYO_VERSION1);
310 if (m_shared_aligned_malloc == 0) {
311 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
312 "myoSharedAlignedMalloc");
313 UnloadLibrary();
314 return false;
317 m_shared_aligned_free = (void (*)(void*))
318 DL_sym(m_lib_handle, "myoSharedAlignedFree", MYO_VERSION1);
319 if (m_shared_aligned_free == 0) {
320 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
321 "myoSharedAlignedFree");
322 UnloadLibrary();
323 return false;
326 m_acquire = (MyoError (*)(void))
327 DL_sym(m_lib_handle, "myoAcquire", MYO_VERSION1);
328 if (m_acquire == 0) {
329 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
330 "myoAcquire");
331 UnloadLibrary();
332 return false;
335 m_release = (MyoError (*)(void))
336 DL_sym(m_lib_handle, "myoRelease", MYO_VERSION1);
337 if (m_release == 0) {
338 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
339 "myoRelease");
340 UnloadLibrary();
341 return false;
344 m_host_var_table_propagate = (MyoError (*)(void*, int))
345 DL_sym(m_lib_handle, "myoiHostVarTablePropagate", MYO_VERSION1);
346 if (m_host_var_table_propagate == 0) {
347 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
348 "myoiHostVarTablePropagate");
349 UnloadLibrary();
350 return false;
353 m_host_fptr_table_register = (MyoError (*)(void*, int, int))
354 DL_sym(m_lib_handle, "myoiHostFptrTableRegister", MYO_VERSION1);
355 if (m_host_fptr_table_register == 0) {
356 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
357 "myoiHostFptrTableRegister");
358 UnloadLibrary();
359 return false;
362 m_remote_thunk_call = (MyoError (*)(void*, void*, int))
363 DL_sym(m_lib_handle, "myoiRemoteThunkCall", MYO_VERSION1);
364 if (m_remote_thunk_call == 0) {
365 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
366 "myoiRemoteThunkCall");
367 UnloadLibrary();
368 return false;
371 m_remote_call = (MyoiRFuncCallHandle (*)(const char*, void*, int))
372 DL_sym(m_lib_handle, "myoiRemoteCall", MYO_VERSION1);
373 if (m_remote_call == 0) {
374 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
375 "myoiRemoteCall");
376 UnloadLibrary();
377 return false;
380 m_get_result = (MyoError (*)(MyoiRFuncCallHandle))
381 DL_sym(m_lib_handle, "myoiGetResult", MYO_VERSION1);
382 if (m_get_result == 0) {
383 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
384 "myoiGetResult");
385 UnloadLibrary();
386 return false;
389 m_arena_create = (MyoError (*)(MyoOwnershipType, int, MyoArena*))
390 DL_sym(m_lib_handle, "myoArenaCreate", MYO_VERSION1);
391 if (m_arena_create == 0) {
392 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
393 "myoArenaCreate");
394 UnloadLibrary();
395 return false;
398 m_arena_aligned_malloc = (void* (*)(MyoArena, size_t, size_t))
399 DL_sym(m_lib_handle, "myoArenaAlignedMalloc", MYO_VERSION1);
400 if (m_arena_aligned_malloc == 0) {
401 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
402 "myoArenaAlignedMalloc");
403 UnloadLibrary();
404 return false;
407 m_arena_aligned_free = (void* (*)(MyoArena, void*))
408 DL_sym(m_lib_handle, "myoArenaAlignedFree", MYO_VERSION1);
409 if (m_arena_aligned_free == 0) {
410 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
411 "myoArenaAlignedFree");
412 UnloadLibrary();
413 return false;
416 m_arena_acquire = (MyoError (*)(MyoArena))
417 DL_sym(m_lib_handle, "myoArenaAcquire", MYO_VERSION1);
418 if (m_acquire == 0) {
419 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
420 "myoArenaAcquire");
421 UnloadLibrary();
422 return false;
425 m_arena_release = (MyoError (*)(MyoArena))
426 DL_sym(m_lib_handle, "myoArenaRelease", MYO_VERSION1);
427 if (m_release == 0) {
428 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
429 "myoArenaRelease");
430 UnloadLibrary();
431 return false;
434 // Check for "feature-available" API added in MPSS 3.3.
435 // Not finding it is not an error.
436 m_feature_available = (MyoError (*)(int))
437 DL_sym(m_lib_handle, "myoiSupportsFeature", MYO_VERSION1);
438 if (m_feature_available == 0) {
439 OFFLOAD_DEBUG_TRACE(2, "Failed to find %s in MYO library\n",
440 "myoiSupportsFeature");
443 OFFLOAD_DEBUG_TRACE(2, "The library was successfully loaded\n");
445 // Create arena if supported
446 CreateVtableArena();
447 OFFLOAD_DEBUG_TRACE(3, "Vtable arena created\n");
449 m_is_available = true;
451 return true;
454 static bool myo_is_available;
455 static MyoWrapper myo_wrapper;
457 void MyoWrapper::CreateVtableArena()
459 MyoArena* vtable_arena;
461 // Check if this MYO supports arenas for vtables
462 if (myo_wrapper.PostInitFuncSupported()) {
463 // Create arena for vtables
464 vtable_arena = (MyoArena *)myo_wrapper.SharedMalloc(sizeof(MyoArena));
465 myo_wrapper.ArenaCreate(
466 MYO_ARENA_OURS, MYO_NO_CONSISTENCY, vtable_arena);
467 m_vtable_arena = *vtable_arena;
468 OFFLOAD_DEBUG_TRACE(4, "created arena = %d\n", m_vtable_arena);
469 } else {
470 m_vtable_arena = 0;
474 struct MyoTable
476 MyoTable(SharedTableEntry *tab, int len) : var_tab(tab), var_tab_len(len)
479 SharedTableEntry* var_tab;
480 int var_tab_len;
483 typedef std::list<MyoTable> MyoTableList;
484 static MyoTableList __myo_table_list;
485 static mutex_t __myo_table_lock;
486 static bool __myo_tables = false;
488 static void __offload_myo_shared_vtable_process(SharedTableEntry *entry);
489 static void __offload_myo_shared_table_process(SharedTableEntry *entry);
490 static void __offload_myo_shared_init_table_process(InitTableEntry* entry);
491 static void __offload_myo_fptr_table_process(FptrTableEntry *entry);
492 static void __offload_propagate_shared_vars();
494 static void __offload_myoLoadLibrary_once(void)
496 if (__offload_init_library()) {
497 myo_wrapper.LoadLibrary();
501 static bool __offload_myoLoadLibrary(void)
503 OFFLOAD_DEBUG_TRACE(4, "__offload_myoLoadLibrary\n");
504 static OffloadOnceControl ctrl = OFFLOAD_ONCE_CONTROL_INIT;
505 __offload_run_once(&ctrl, __offload_myoLoadLibrary_once);
507 return myo_wrapper.is_available();
510 static void __offload_myoInit_once(void)
512 if (!__offload_myoLoadLibrary()) {
513 return;
516 // initialize all devices
517 for (int i = 0; i < mic_engines_total; i++) {
518 mic_engines[i].init();
521 // load and initialize MYO library
522 OFFLOAD_DEBUG_TRACE(2, "Initializing MYO library ...\n");
524 COIEVENT events[MIC_ENGINES_MAX];
526 // One entry per device +
527 // A pair of entries for the Host postInit func +
528 // A pair of entries for the MIC postInit func +
529 // end marker
530 MyoiUserParams params[MIC_ENGINES_MAX+5];
532 // Load target library to all devices and
533 // create libinit parameters for all devices
534 for (int i = 0; i < mic_engines_total; i++) {
535 mic_engines[i].init_myo(&events[i]);
537 params[i].type = MYOI_USERPARAMS_DEVID;
538 params[i].nodeid = mic_engines[i].get_physical_index() + 1;
539 OFFLOAD_DEBUG_TRACE(2, "params[%d] = { %d, %d }\n",
540 i, params[i].type, params[i].nodeid);
543 // Check if V2 myoLibInit is available
544 if (myo_wrapper.PostInitFuncSupported()) {
545 // Set the host post libInit function indicator
546 params[mic_engines_total].type =
547 MYOI_USERPARAMS_POST_MYO_LIB_INIT_FUNC;
548 params[mic_engines_total].nodeid =
549 MYOI_USERPARAMS_POST_MYO_LIB_INIT_FUNC_HOST_NODE;
550 OFFLOAD_DEBUG_TRACE(2, "params[%d] = { %d, %d }\n",
551 mic_engines_total,
552 params[mic_engines_total].type, params[mic_engines_total].nodeid);
554 // Set the host post libInit host function address
555 ((MyoiUserParamsPostLibInit*)(&params[mic_engines_total+1]))->
556 postLibInitHostFuncAddress =
557 (void (*)())&__offload_propagate_shared_vars;
558 OFFLOAD_DEBUG_TRACE(2, "params[%d] = { %p }\n",
559 mic_engines_total+1,
560 ((MyoiUserParamsPostLibInit*)(&params[mic_engines_total+1]))->
561 postLibInitHostFuncAddress);
563 // Set the target post libInit function indicator
564 params[mic_engines_total+2].type =
565 MYOI_USERPARAMS_POST_MYO_LIB_INIT_FUNC;
566 params[mic_engines_total+2].nodeid =
567 MYOI_USERPARAMS_POST_MYO_LIB_INIT_FUNC_ALL_NODES;
569 // Set the target post libInit target function name
570 ((MyoiUserParamsPostLibInit*)(&params[mic_engines_total+3]))->
571 postLibInitRemoveFuncName = "--vtable_initializer--";
572 OFFLOAD_DEBUG_TRACE(2, "params[%d] = { %s }\n",
573 mic_engines_total+3,
574 ((MyoiUserParamsPostLibInit*)(&params[mic_engines_total+1]))->
575 postLibInitRemoveFuncName);
577 params[mic_engines_total+4].type = MYOI_USERPARAMS_LAST_MSG;
578 params[mic_engines_total+4].nodeid = 0;
579 OFFLOAD_DEBUG_TRACE(2, "params[%d] = { %d, %d }\n",
580 mic_engines_total+4,
581 params[mic_engines_total+4].type,
582 params[mic_engines_total+4].nodeid);
583 } else {
584 params[mic_engines_total].type = MYOI_USERPARAMS_LAST_MSG;
585 params[mic_engines_total].nodeid = 0;
586 OFFLOAD_DEBUG_TRACE(2, "params[%d] = { %d, %d }\n",
587 mic_engines_total,
588 params[mic_engines_total].type, params[mic_engines_total].nodeid);
591 // initialize myo runtime on host
592 myo_wrapper.LibInit(params, 0);
594 // wait for the target init calls to finish
595 COIRESULT res;
596 res = COI::EventWait(mic_engines_total, events, -1, 1, 0, 0);
597 if (res != COI_SUCCESS) {
598 LIBOFFLOAD_ERROR(c_event_wait, res);
599 exit(1);
602 myo_is_available = true;
603 OFFLOAD_DEBUG_TRACE(2, "setting myo_is_available=%d\n", myo_is_available);
605 OFFLOAD_DEBUG_TRACE(2, "Initializing MYO library ... done\n");
608 static bool __offload_myoInit(void)
610 static OffloadOnceControl ctrl = OFFLOAD_ONCE_CONTROL_INIT;
611 __offload_run_once(&ctrl, __offload_myoInit_once);
613 // Check if using V1 myoLibInit
614 if (!myo_wrapper.PostInitFuncSupported()) {
615 __offload_propagate_shared_vars();
618 return myo_is_available;
621 static void __offload_propagate_shared_vars()
623 // Propagate pending shared var tables
624 if (__myo_tables) {
625 mutex_locker_t locker(__myo_table_lock);
627 if (__myo_tables) {
628 // Give tables with MYO so it can propagate to target
629 for(MyoTableList::const_iterator it = __myo_table_list.begin();
630 it != __myo_table_list.end(); ++it) {
631 #ifdef TARGET_WINNT
632 for (SharedTableEntry *entry = it->var_tab;
633 entry->varName != MYO_TABLE_END_MARKER(); entry++) {
634 if (entry->varName == 0) {
635 continue;
637 myo_wrapper.HostVarTablePropagate(entry, 1);
638 OFFLOAD_DEBUG_TRACE(2, "HostVarTablePropagate(%s, 1)\n",
639 entry->varName);
641 #else // TARGET_WINNT
642 myo_wrapper.HostVarTablePropagate(it->var_tab,
643 it->var_tab_len);
644 #endif // TARGET_WINNT
647 __myo_table_list.clear();
648 __myo_tables = false;
653 static bool shared_table_entries(
654 SharedTableEntry *entry
657 OFFLOAD_DEBUG_TRACE(3, "%s(%p)\n", __func__, entry);
659 for (; entry->varName != MYO_TABLE_END_MARKER(); entry++) {
660 #ifdef TARGET_WINNT
661 if (entry->varName == 0) {
662 continue;
664 #endif // TARGET_WINNT
666 return true;
669 return false;
672 static bool fptr_table_entries(
673 FptrTableEntry *entry
676 OFFLOAD_DEBUG_TRACE(3, "%s(%p)\n", __func__, entry);
678 for (; entry->funcName != MYO_TABLE_END_MARKER(); entry++) {
679 #ifdef TARGET_WINNT
680 if (entry->funcName == 0) {
681 continue;
683 #endif // TARGET_WINNT
685 return true;
688 return false;
691 extern "C" void __offload_myoRegisterTables(
692 InitTableEntry* init_table,
693 SharedTableEntry *shared_table,
694 FptrTableEntry *fptr_table
697 // check whether we need to initialize MYO library. It is
698 // initialized only if at least one myo table is not empty
699 if (shared_table_entries(shared_table) || fptr_table_entries(fptr_table)) {
700 // make sure myo library is loaded
701 __offload_myoLoadLibrary();
703 // register tables
704 __offload_myo_shared_table_process(shared_table);
705 __offload_myo_fptr_table_process(fptr_table);
706 __offload_myo_shared_init_table_process(init_table);
710 extern "C" bool __offload_myoProcessTables(
711 const void* image,
712 MYOInitTableList::Node *init_table,
713 MYOVarTableList::Node *shared_table,
714 MYOVarTableList::Node *shared_vtable,
715 MYOFuncTableList::Node *fptr_table
718 OFFLOAD_DEBUG_TRACE(3, "%s\n", __func__);
720 // Collect the tables in this .dll/.so
721 __offload_myoRegisterTables1(
722 init_table, shared_table, shared_vtable, fptr_table);
724 // Now check what type of module we are dealing with
725 if (__offload_target_image_is_executable(image)) {
726 OFFLOAD_DEBUG_TRACE(2, "Main encountered\n");
727 OFFLOAD_DEBUG_TRACE(2, "MYO initialization not deferred\n");
728 // MYO tables across dlls have been collected
729 // Now init MYO and process the tables
730 __offload_myoProcessDeferredTables();
731 // Return true to indicate that atexit needs to be calld by ofldbegin
732 return true;
733 } else {
734 // This is a shared library, either auto-loaded or dynamically loaded
735 // If __target_exe is set, then main has started running
736 if (__target_exe != 0) {
737 // Main is running: this is a dynamic load of a shared library
738 // Finish processing the tables in this library
739 OFFLOAD_DEBUG_TRACE(2,
740 "Dynamically loaded shared library encountered\n");
741 OFFLOAD_DEBUG_TRACE(2,
742 "MYO initialization not deferred\n");
743 __offload_myoProcessDeferredTables();
744 } else {
745 // Main is not running: this is an auto-loaded shared library
746 // Tables have been collected, nothing else to do
747 OFFLOAD_DEBUG_TRACE(2,
748 "Auto-loaded shared library encountered\n");
749 OFFLOAD_DEBUG_TRACE(2, "Deferring initialization of MYO\n");
751 return false;
755 // Process contents of all Var tables
756 void MYOVarTableList::process()
758 OFFLOAD_DEBUG_TRACE(2, "Process MYO Var tables:\n");
760 m_lock.lock();
762 for (Node *n = m_head; n != 0; n = n->next) {
763 __offload_myo_shared_table_process(
764 (SharedTableEntry*)n->table.entries);
766 for (Node *n = m_head; n != 0; n = n->next) {
767 remove_table(n);
770 m_lock.unlock();
773 // Process contents of all Var tables
774 void MYOVarTableList::process_vtable()
776 OFFLOAD_DEBUG_TRACE(2, "Process MYO Vtable tables:\n");
778 m_lock.lock();
780 for (Node *n = m_head; n != 0; n = n->next) {
781 __offload_myo_shared_vtable_process(
782 (SharedTableEntry*)n->table.entries);
784 for (Node *n = m_head; n != 0; n = n->next) {
785 remove_table(n);
788 m_lock.unlock();
791 // Process contents of all Func tables
792 void MYOFuncTableList::process()
794 OFFLOAD_DEBUG_TRACE(2, "Process MYO Func tables:\n");
796 m_lock.lock();
798 for (Node *n = m_head; n != 0; n = n->next) {
799 __offload_myo_fptr_table_process(
800 (FptrTableEntry*)n->table.entries);
802 for (Node *n = m_head; n != 0; n = n->next) {
803 remove_table(n);
806 m_lock.unlock();
809 // Process contents of all Init tables
810 void MYOInitTableList::process()
812 OFFLOAD_DEBUG_TRACE(2, "Process MYO Init tables:\n");
814 m_lock.lock();
816 for (Node *n = m_head; n != 0; n = n->next) {
817 __offload_myo_shared_init_table_process(
818 (InitTableEntry*)n->table.entries);
820 for (Node *n = m_head; n != 0; n = n->next) {
821 remove_table(n);
824 m_lock.unlock();
827 static void __offload_myoProcessDeferredTables()
829 OFFLOAD_DEBUG_TRACE(3, "%s()\n", __func__);
831 // Debug dumps of MYO tables
832 if (console_enabled >= 2) {
833 __offload_myo_var_tables.dump();
834 __offload_myo_vtable_tables.dump();
835 __offload_myo_func_tables.dump();
836 __offload_myo_init_tables.dump();
839 if (!__offload_myo_var_tables.is_empty() ||
840 !__offload_myo_vtable_tables.is_empty() ||
841 !__offload_myo_func_tables.is_empty() ||
842 !__offload_myo_init_tables.is_empty())
844 OFFLOAD_DEBUG_TRACE(3, "MYO usage detected in program\n");
846 // Make sure myo library is loaded
847 __offload_myoLoadLibrary();
848 OFFLOAD_DEBUG_TRACE(3, "Initialized MYO\n");
850 __offload_myo_var_tables.process();
851 __offload_myo_vtable_tables.process_vtable();
852 __offload_myo_func_tables.process();
853 __offload_myo_init_tables.process();
854 OFFLOAD_DEBUG_TRACE(3, "Finished processing MYO tables\n");
855 } else {
856 OFFLOAD_DEBUG_TRACE(3,
857 "MYO tables are empty; Will not initialize MYO\n");
861 DLL_LOCAL void __offload_myoFini(void)
863 if (myo_is_available) {
864 OFFLOAD_DEBUG_TRACE(3, "%s\n", __func__);
866 COIEVENT events[MIC_ENGINES_MAX];
868 // kick off myoiLibFini calls on all devices
869 for (int i = 0; i < mic_engines_total; i++) {
870 mic_engines[i].fini_myo(&events[i]);
873 // cleanup myo runtime on host
874 myo_wrapper.LibFini();
876 // wait for the target fini calls to finish
877 COIRESULT res;
878 res = COI::EventWait(mic_engines_total, events, -1, 1, 0, 0);
879 if (res != COI_SUCCESS) {
880 LIBOFFLOAD_ERROR(c_event_wait, res);
881 exit(1);
886 static void __offload_myo_shared_table_process(
887 SharedTableEntry *entry
890 OFFLOAD_DEBUG_TRACE(3, "%s(%p)\n", __func__, entry);
892 SharedTableEntry *start = entry;
893 int entries = 0;
895 // allocate shared memory for vars
896 for (; entry->varName != MYO_TABLE_END_MARKER(); entry++) {
897 #ifdef TARGET_WINNT
898 if (entry->varName == 0) {
899 OFFLOAD_DEBUG_TRACE(4,
900 "skip registering a NULL MyoSharedTable entry\n");
901 continue;
903 #endif // TARGET_WINNT
905 OFFLOAD_DEBUG_TRACE(4, "registering MyoSharedTable entry for %s @%p\n",
906 entry->varName, entry);
908 // Invoke the function to create shared memory
909 reinterpret_cast<void(*)(void)>(entry->sharedAddr)();
910 entries++;
913 // and table to the list if it is not empty
914 if (entries > 0) {
915 mutex_locker_t locker(__myo_table_lock);
916 __myo_table_list.push_back(MyoTable(start, entries));
917 __myo_tables = true;
921 static void __offload_myo_shared_vtable_process(
922 SharedTableEntry *entry
925 SharedTableEntry *start = entry;
926 int entries = 0;
928 OFFLOAD_DEBUG_TRACE(3, "%s(%p)\n", __func__, entry);
930 // allocate shared memory for vtables
931 for (; entry->varName != MYO_TABLE_END_MARKER(); entry++) {
932 #ifdef TARGET_WINNT
933 if (entry->varName == 0) {
934 OFFLOAD_DEBUG_TRACE(4,
935 "skip registering a NULL MyoSharedVTable entry\n");
936 continue;
938 #endif // TARGET_WINNT
940 OFFLOAD_DEBUG_TRACE(4,
941 "registering MyoSharedVTable entry for %s @%p\n",
942 entry->varName, entry);
944 // Invoke the function to create shared memory
945 reinterpret_cast<void(*)(MyoArena)>(entry->sharedAddr)(
946 myo_wrapper.GetVtableArena());
947 entries++;
950 // add table to the list if it is not empty
951 if (entries > 0) {
952 mutex_locker_t locker(__myo_table_lock);
953 __myo_table_list.push_back(MyoTable(start, entries));
954 __myo_tables = true;
958 void __offload_myo_shared_init_table_process(InitTableEntry* entry)
960 OFFLOAD_DEBUG_TRACE(3, "%s(%p)\n", __func__, entry);
962 #ifdef TARGET_WINNT
963 for (; entry->funcName != MYO_TABLE_END_MARKER(); entry++) {
964 if (entry->funcName == 0) {
965 OFFLOAD_DEBUG_TRACE(4,
966 "skip registering a NULL MyoSharedInit entry\n");
967 continue;
970 // Invoke the function to init the shared memory
971 OFFLOAD_DEBUG_TRACE(4, "execute MyoSharedInit routine for %s\n",
972 entry->funcName);
973 entry->func(myo_wrapper.GetVtableArena());
975 #else // TARGET_WINNT
976 for (; entry->func != 0; entry++) {
977 // Invoke the function to init the shared memory
978 entry->func(myo_wrapper.GetVtableArena());
980 #endif // TARGET_WINNT
983 static void __offload_myo_fptr_table_process(
984 FptrTableEntry *entry
987 OFFLOAD_DEBUG_TRACE(3, "%s(%p)\n", __func__, entry);
989 FptrTableEntry *start = entry;
990 int entries = 0;
992 for (; entry->funcName != MYO_TABLE_END_MARKER(); entry++) {
993 #ifdef TARGET_WINNT
994 if (entry->funcName == 0) {
995 OFFLOAD_DEBUG_TRACE(4,
996 "skip registering a NULL MyoFptrTable entry\n");
997 continue;
999 #endif // TARGET_WINNT
1001 if (!myo_wrapper.is_available()) {
1002 *(static_cast<void**>(entry->localThunkAddr)) = entry->funcAddr;
1005 OFFLOAD_DEBUG_TRACE(4, "registering MyoFptrTable entry for %s @%p\n",
1006 entry->funcName, entry);
1008 #ifdef TARGET_WINNT
1009 if (myo_wrapper.is_available()) {
1010 myo_wrapper.HostFptrTableRegister(entry, 1, false);
1012 #endif // TARGET_WINNT
1014 entries++;
1017 #ifndef TARGET_WINNT
1018 if (myo_wrapper.is_available() && entries > 0) {
1019 myo_wrapper.HostFptrTableRegister(start, entries, false);
1021 #endif // TARGET_WINNT
1024 extern "C" int __offload_myoIsAvailable(int target_number)
1026 OFFLOAD_DEBUG_TRACE(3, "%s(%d)\n", __func__, target_number);
1028 if (target_number >= -2) {
1029 bool is_default_number = (target_number == -2);
1031 if (__offload_myoInit()) {
1032 if (target_number >= 0) {
1033 // User provided the device number
1034 int num = target_number % mic_engines_total;
1036 // reserve device in ORSL
1037 target_number = ORSL::reserve(num) ? num : -1;
1039 else {
1040 // try to use device 0
1041 target_number = ORSL::reserve(0) ? 0 : -1;
1044 // make sure device is initialized
1045 if (target_number >= 0) {
1046 mic_engines[target_number].init();
1049 else {
1050 // fallback to CPU
1051 target_number = -1;
1054 if (target_number < 0 && !is_default_number) {
1055 LIBOFFLOAD_ERROR(c_device_is_not_available);
1056 exit(1);
1059 else {
1060 LIBOFFLOAD_ERROR(c_invalid_device_number);
1061 exit(1);
1064 return target_number;
1067 extern "C" void __offload_myoiRemoteIThunkCall(
1068 void *thunk,
1069 void *arg,
1070 int target_number
1073 OFFLOAD_DEBUG_TRACE(3, "%s(%p, %p, %d)\n", __func__, thunk, arg,
1074 target_number);
1076 myo_wrapper.Release();
1077 myo_wrapper.RemoteThunkCall(thunk, arg, target_number);
1078 myo_wrapper.Acquire();
1080 ORSL::release(target_number);
1083 extern "C" void* _Offload_shared_malloc(size_t size)
1085 OFFLOAD_DEBUG_TRACE(3, "%s(%lld)\n", __func__, size);
1087 if (__offload_myoLoadLibrary()) {
1088 return myo_wrapper.SharedMalloc(size);
1090 else {
1091 return malloc(size);
1095 extern "C" void _Offload_shared_free(void *ptr)
1097 OFFLOAD_DEBUG_TRACE(3, "%s(%p)\n", __func__, ptr);
1099 if (__offload_myoLoadLibrary()) {
1100 myo_wrapper.SharedFree(ptr);
1102 else {
1103 free(ptr);
1107 extern "C" void* _Offload_shared_aligned_malloc(size_t size, size_t align)
1109 OFFLOAD_DEBUG_TRACE(3, "%s(%lld, %lld)\n", __func__, size, align);
1111 if (__offload_myoLoadLibrary()) {
1112 return myo_wrapper.SharedAlignedMalloc(size, align);
1114 else {
1115 if (align < sizeof(void*)) {
1116 align = sizeof(void*);
1118 return _mm_malloc(size, align);
1122 extern "C" void _Offload_shared_aligned_free(void *ptr)
1124 OFFLOAD_DEBUG_TRACE(3, "%s(%p)\n", __func__, ptr);
1126 if (__offload_myoLoadLibrary()) {
1127 myo_wrapper.SharedAlignedFree(ptr);
1129 else {
1130 _mm_free(ptr);
1134 extern "C" void _Offload_shared_arena_create(
1135 MyoOwnershipType ownership,
1136 int consistency,
1137 MyoArena* arena
1140 OFFLOAD_DEBUG_TRACE(3, "%s(%d, %d, %p)\n",
1141 __func__, ownership, consistency, arena);
1143 if (__offload_myoLoadLibrary()) {
1144 myo_wrapper.ArenaCreate(ownership, consistency, arena);
1148 extern "C" void* _Offload_shared_aligned_arena_malloc(
1149 MyoArena arena,
1150 size_t size,
1151 size_t align
1154 OFFLOAD_DEBUG_TRACE(3, "%s(%u, %lld, %lld)\n",
1155 __func__, arena, size, align);
1157 if (__offload_myoLoadLibrary()) {
1158 void *p = myo_wrapper.SharedAlignedArenaMalloc(arena, size, align);
1159 OFFLOAD_DEBUG_TRACE(3, "%s(%u, %lld, %lld)->%p\n",
1160 __func__, arena, size, align, p);
1161 return p;
1163 else {
1164 if (align < sizeof(void*)) {
1165 align = sizeof(void*);
1167 return _mm_malloc(size, align);
1171 extern "C" void _Offload_shared_aligned_arena_free(
1172 MyoArena arena,
1173 void *ptr
1176 OFFLOAD_DEBUG_TRACE(3, "%s(%u, %p)\n", __func__, arena, ptr);
1178 if (__offload_myoLoadLibrary()) {
1179 myo_wrapper.SharedAlignedArenaFree(arena, ptr);
1181 else {
1182 _mm_free(ptr);
1186 extern "C" void _Offload_shared_arena_acquire(
1187 MyoArena arena
1190 OFFLOAD_DEBUG_TRACE(3, "%s(%u)\n", __func__, arena);
1192 if (__offload_myoLoadLibrary()) {
1193 myo_wrapper.ArenaAcquire(arena);
1197 extern "C" void _Offload_shared_arena_release(
1198 MyoArena arena
1201 OFFLOAD_DEBUG_TRACE(3, "%s(%u)\n", __func__, arena);
1203 if (__offload_myoLoadLibrary()) {
1204 myo_wrapper.ArenaRelease(arena);
1208 extern "C" void __intel_cilk_for_32_offload(
1209 int size,
1210 void (*copy_constructor)(void*, void*),
1211 int target_number,
1212 void *raddr,
1213 void *closure_object,
1214 unsigned int iters,
1215 unsigned int grain_size)
1217 OFFLOAD_DEBUG_TRACE(3, "%s\n", __func__);
1219 target_number = __offload_myoIsAvailable(target_number);
1220 if (target_number >= 0) {
1221 struct S {
1222 void *M1;
1223 unsigned int M2;
1224 unsigned int M3;
1225 char closure[];
1226 } *args;
1228 args = (struct S*) _Offload_shared_malloc(sizeof(struct S) + size);
1229 if (args == NULL)
1230 LIBOFFLOAD_ERROR(c_malloc);
1231 args->M1 = raddr;
1232 args->M2 = iters;
1233 args->M3 = grain_size;
1235 if (copy_constructor == 0) {
1236 memcpy(args->closure, closure_object, size);
1238 else {
1239 copy_constructor(args->closure, closure_object);
1242 myo_wrapper.Release();
1243 myo_wrapper.GetResult(
1244 myo_wrapper.RemoteCall("__intel_cilk_for_32_offload",
1245 args, target_number)
1247 myo_wrapper.Acquire();
1249 _Offload_shared_free(args);
1251 ORSL::release(target_number);
1253 else {
1254 __cilkrts_cilk_for_32(raddr,
1255 closure_object,
1256 iters,
1257 grain_size);
1261 extern "C" void __intel_cilk_for_64_offload(
1262 int size,
1263 void (*copy_constructor)(void*, void*),
1264 int target_number,
1265 void *raddr,
1266 void *closure_object,
1267 uint64_t iters,
1268 uint64_t grain_size)
1270 OFFLOAD_DEBUG_TRACE(3, "%s\n", __func__);
1272 target_number = __offload_myoIsAvailable(target_number);
1273 if (target_number >= 0) {
1274 struct S {
1275 void *M1;
1276 uint64_t M2;
1277 uint64_t M3;
1278 char closure[];
1279 } *args;
1281 args = (struct S*) _Offload_shared_malloc(sizeof(struct S) + size);
1282 if (args == NULL)
1283 LIBOFFLOAD_ERROR(c_malloc);
1284 args->M1 = raddr;
1285 args->M2 = iters;
1286 args->M3 = grain_size;
1288 if (copy_constructor == 0) {
1289 memcpy(args->closure, closure_object, size);
1291 else {
1292 copy_constructor(args->closure, closure_object);
1295 myo_wrapper.Release();
1296 myo_wrapper.GetResult(
1297 myo_wrapper.RemoteCall("__intel_cilk_for_64_offload", args,
1298 target_number)
1300 myo_wrapper.Acquire();
1302 _Offload_shared_free(args);
1304 ORSL::release(target_number);
1306 else {
1307 __cilkrts_cilk_for_64(raddr,
1308 closure_object,
1309 iters,
1310 grain_size);