2 Copyright (c) 2014-2016 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
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.
36 #include "coi_version_asm.h"
38 #define CYCLE_FREQUENCY 1000000000
58 void * *bufs_data_target
;
59 uint16_t misc_data_len
;
61 uint16_t return_value_len
;
63 COIEVENT completion_event
;
68 COI_EVENT_CALLBACK ptr
;
86 char *pipe_host2tgt_path
;
87 char *pipe_tgt2host_path
;
90 std::queue
<Function
> queue
;
107 /* Environment variables. */
108 extern char **environ
;
110 /* List of directories for removing on exit. */
111 static char **tmp_dirs
;
112 static unsigned tmp_dirs_num
;
114 /* Number of emulated MIC engines. */
115 static long num_engines
;
117 /* Number of the last COI pipeline. */
118 static uint32_t max_pipeline_num
;
120 /* Set of undestroyed pipelines. */
121 static std::set
<Pipeline
*> pipelines
;
123 /* Number of the last COI event, the event #0 is always signalled. */
124 static uint64_t max_event_num
= 1;
126 /* Set of created COI events, which are not signalled. */
127 static std::set
<uint64_t> non_signalled_events
;
129 /* Set of COI events, which encountered errors. */
130 static std::map
<uint64_t, COIRESULT
> errored_events
;
132 /* Set of registered callbacks, indexed by event number. */
133 static std::map
<uint64_t, Callback
> callbacks
;
135 /* Mutex to sync parallel execution. */
136 static pthread_mutex_t mutex
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
;
140 read_long_env (const char *env_name
, long *var
, long var_default
)
142 char *str
= getenv (env_name
);
145 if (!str
|| *str
== '\0')
150 *var
= strtol (str
, &s
, 0);
151 if (errno
!= 0 || s
== str
|| *s
!= '\0')
152 COIERROR ("Variable %s has invalid value.", env_name
);
158 __attribute__((constructor
))
162 if (read_long_env (OFFLOAD_EMUL_NUM_ENV
, &num_engines
, 1) == COI_ERROR
)
167 /* Helper function for directory removing. */
168 static COIRESULT
remove_directory (char *path
)
171 struct dirent
*entry
;
172 struct stat statfile
;
173 DIR *dir
= opendir (path
);
175 COIERROR ("Cannot open directory %s.", dir
);
177 while (entry
= readdir (dir
))
179 if (!strcmp (entry
->d_name
, ".") || !strcmp (entry
->d_name
, ".."))
182 MALLOC (char *, file
, strlen (path
) + strlen (entry
->d_name
) + 2);
183 sprintf (file
, "%s/%s", path
, entry
->d_name
);
185 if (stat (file
, &statfile
) < 0)
186 COIERROR ("Cannot retrieve information about file %s.", file
);
188 if (S_ISDIR (statfile
.st_mode
))
190 if (remove_directory (file
) == COI_ERROR
)
195 if (unlink (file
) < 0)
196 COIERROR ("Cannot unlink file %s.", file
);
202 if (closedir (dir
) < 0)
203 COIERROR ("Cannot close directory %s.", path
);
204 if (rmdir (path
) < 0)
205 COIERROR ("Cannot remove directory %s.", path
);
210 __attribute__((destructor
))
214 for (unsigned i
= 0; i
< tmp_dirs_num
; i
++)
216 remove_directory (tmp_dirs
[i
]);
223 start_critical_section ()
225 if (pthread_mutex_lock (&mutex
) != 0)
226 COIERROR ("Cannot lock mutex.");
231 finish_critical_section ()
233 if (pthread_mutex_unlock (&mutex
) != 0)
234 COIERROR ("Cannot unlock mutex.");
239 pipeline_is_destroyed (const Pipeline
*pipeline
)
241 start_critical_section ();
242 bool res
= pipeline
->is_destroyed
;
243 finish_critical_section ();
248 maybe_invoke_callback (const COIEVENT event
, const COIRESULT result
)
250 std::map
<uint64_t, Callback
>::iterator cb
= callbacks
.find (event
.opaque
[0]);
252 if (cb
!= callbacks
.end ())
254 Callback callback
= cb
->second
;
255 callback
.ptr (event
, result
, callback
.data
);
256 callbacks
.erase (cb
);
261 signal_event (const COIEVENT event
, const COIRESULT result
)
263 if (result
!= COI_SUCCESS
)
264 errored_events
.insert (std::pair
<uint64_t, COIRESULT
> (event
.opaque
[0],
266 non_signalled_events
.erase (event
.opaque
[0]);
268 maybe_invoke_callback (event
, result
);
272 get_event_result (const COIEVENT event
)
274 COIRESULT res
= COI_SUCCESS
;
276 std::map
<uint64_t, COIRESULT
>::iterator ee
277 = errored_events
.find (event
.opaque
[0]);
279 if (ee
!= errored_events
.end ())
290 SYMBOL_VERSION (COIBufferCopy
, 1) (COIBUFFER in_DestBuffer
,
291 COIBUFFER in_SourceBuffer
,
292 uint64_t in_DestOffset
,
293 uint64_t in_SourceOffset
,
295 COI_COPY_TYPE in_Type
,
296 uint32_t in_NumDependencies
,
297 const COIEVENT
*in_pDependencies
, // Ignored
298 COIEVENT
*out_pCompletion
)
300 COITRACE ("COIBufferCopy");
302 /* Features of liboffloadmic. */
303 assert (in_DestBuffer
!= NULL
);
304 assert (in_SourceBuffer
!= NULL
);
305 assert (in_Type
== COI_COPY_UNSPECIFIED
);
306 assert (in_NumDependencies
== 0);
308 /* Convert input arguments. */
309 Buffer
*dest
= (Buffer
*) in_DestBuffer
;
310 Buffer
*source
= (Buffer
*) in_SourceBuffer
;
312 start_critical_section ();
314 /* Map buffers if needed. */
315 if (dest
->data
== 0 && dest
->type
== BUFFER_NORMAL
)
316 if (COIBufferMap (in_DestBuffer
, 0, dest
->size
, (COI_MAP_TYPE
) 0,
317 0, 0, 0, 0, 0) == COI_ERROR
)
319 if (source
->data
== 0 && source
->type
== BUFFER_NORMAL
)
320 if (COIBufferMap (in_SourceBuffer
, 0, source
->size
, (COI_MAP_TYPE
) 0,
321 0, 0, 0, 0, 0) == COI_ERROR
)
325 if (source
->data
!= 0 && dest
->data
!= 0)
326 memcpy ((void *) ((uintptr_t) dest
->data
+ in_DestOffset
),
327 (void *) ((uintptr_t) source
->data
+ in_SourceOffset
), in_Length
);
330 assert (dest
->process
== source
->process
);
333 cmd_t cmd
= CMD_BUFFER_COPY
;
335 /* Create intermediary buffer. */
336 if (COIBufferCreate (in_Length
, COI_BUFFER_NORMAL
, 0, 0, 1,
337 (COIPROCESS
*) &dest
->process
,
338 (COIBUFFER
*) &buffer
) == COI_ERROR
)
341 int pipe_host2tgt
= dest
->process
->pipe_host2tgt
;
342 int pipe_tgt2host
= dest
->process
->pipe_tgt2host
;
344 /* Copy from source to intermediary buffer. */
345 if (source
->data
== 0)
347 assert (source
->data_target
!= 0);
349 /* Send data to target. */
350 WRITE (pipe_host2tgt
, &cmd
, sizeof (cmd_t
));
351 WRITE (pipe_host2tgt
, &buffer
->data_target
, sizeof (void *));
352 WRITE (pipe_host2tgt
, &source
->data_target
, sizeof (void *));
353 WRITE (pipe_host2tgt
, &buffer
->size
, sizeof (uint64_t));
355 /* Receive data from target. */
356 READ (pipe_tgt2host
, &cmd
, sizeof (cmd_t
));
360 if (COIBufferCopy ((COIBUFFER
) buffer
, in_SourceBuffer
, 0,
361 in_SourceOffset
, in_Length
, in_Type
, 0, 0, 0)
366 /* Copy from intermediary buffer to dest. */
369 assert (dest
->data_target
!= 0);
371 /* Send data to target. */
372 WRITE (pipe_host2tgt
, &cmd
, sizeof (cmd_t
));
373 WRITE (pipe_host2tgt
, &dest
->data_target
, sizeof (void *));
374 WRITE (pipe_host2tgt
, &buffer
->data_target
, sizeof (void *));
375 WRITE (pipe_host2tgt
, &buffer
->size
, sizeof (uint64_t));
377 /* Receive data from target. */
378 READ (pipe_tgt2host
, &cmd
, sizeof (cmd_t
));
382 if (COIBufferCopy (in_DestBuffer
, (COIBUFFER
) buffer
, in_DestOffset
,
383 0, in_Length
, in_Type
, 0, 0, 0) == COI_ERROR
)
387 /* Unmap on target and destroy intermediary buffer. */
388 if (COIBufferDestroy ((COIBUFFER
) buffer
) == COI_ERROR
)
392 /* Unmap buffers if needed. */
393 if (dest
->type
== BUFFER_NORMAL
)
394 if (COIBufferUnmap ((COIMAPINSTANCE
) dest
, 0, 0, 0) == COI_ERROR
)
396 if (source
->type
== BUFFER_NORMAL
)
397 if (COIBufferUnmap ((COIMAPINSTANCE
) source
, 0, 0, 0) == COI_ERROR
)
400 finish_critical_section ();
403 out_pCompletion
->opaque
[0] = 0;
410 SYMBOL_VERSION (COIBufferCreate
, 1) (uint64_t in_Size
,
411 COI_BUFFER_TYPE in_Type
,
413 const void *in_pInitData
,
414 uint32_t in_NumProcesses
,
415 const COIPROCESS
*in_pProcesses
,
416 COIBUFFER
*out_pBuffer
)
418 COITRACE ("COIBufferCreate");
422 const int ullong_max_len
= 20;
424 /* Features of liboffloadmic. */
425 assert (in_Type
== COI_BUFFER_NORMAL
|| in_Type
== COI_BUFFER_OPENCL
);
426 assert ((in_Flags
& COI_SINK_MEMORY
) == 0);
427 assert ((in_Flags
& COI_SAME_ADDRESS_SINKS
) == 0);
428 assert ((in_Flags
& COI_SAME_ADDRESS_SINKS_AND_SOURCE
) == 0);
429 assert (in_pInitData
== NULL
);
430 assert (in_NumProcesses
== 1);
431 assert (in_pProcesses
!= NULL
);
432 assert (out_pBuffer
!= NULL
);
434 /* Create shared memory with an unique name. */
435 MALLOC (char *, shm_name
, strlen (SHM_NAME
) + ullong_max_len
+ 1);
436 for (unsigned long long i
= 0; i
>= 0; i
++)
438 sprintf (shm_name
, SHM_NAME
"%lu", i
);
439 shm_fd
= shm_open (shm_name
, O_CLOEXEC
| O_CREAT
| O_EXCL
| O_RDWR
,
444 if (ftruncate (shm_fd
, in_Size
) < 0)
445 COIERROR ("Cannot truncate shared memory file.");
448 Buffer
*buf
= new Buffer
;
451 buf
->process
= (Process
*) in_pProcesses
[0];
453 buf
->type
= BUFFER_NORMAL
;
454 STRDUP (buf
->name
, shm_name
);
456 /* Map buffer on target. */
457 size_t len
= strlen (buf
->name
) + 1;
459 start_critical_section ();
461 /* Send data to target. */
462 const cmd_t cmd
= CMD_BUFFER_MAP
;
463 int pipe_host2tgt
= buf
->process
->pipe_host2tgt
;
464 WRITE (pipe_host2tgt
, &cmd
, sizeof (cmd_t
));
465 WRITE (pipe_host2tgt
, &len
, sizeof (size_t));
466 WRITE (pipe_host2tgt
, buf
->name
, len
);
467 WRITE (pipe_host2tgt
, &buf
->size
, sizeof (uint64_t));
469 /* Receive data from target. */
470 int pipe_tgt2host
= buf
->process
->pipe_tgt2host
;
471 READ (pipe_tgt2host
, &buf
->fd_target
, sizeof (int));
472 READ (pipe_tgt2host
, &buf
->data_target
, sizeof (void *));
474 finish_critical_section ();
476 /* Prepare output arguments. */
477 *out_pBuffer
= (COIBUFFER
) buf
;
487 SYMBOL_VERSION (COIBufferCreateFromMemory
, 1) (uint64_t in_Size
,
488 COI_BUFFER_TYPE in_Type
,
491 uint32_t in_NumProcesses
,
492 const COIPROCESS
*in_pProcesses
,
493 COIBUFFER
*out_pBuffer
)
495 COITRACE ("COIBufferCreateFromMemory");
497 /* Features of liboffloadmic. */
498 assert (in_Type
== COI_BUFFER_NORMAL
);
499 assert ((in_Flags
& COI_SAME_ADDRESS_SINKS
) == 0);
500 assert ((in_Flags
& COI_SAME_ADDRESS_SINKS_AND_SOURCE
) == 0);
501 assert (in_NumProcesses
== 1);
502 assert (in_pProcesses
!= NULL
);
503 assert (out_pBuffer
!= NULL
);
506 Buffer
*buf
= new Buffer
;
507 buf
->data
= (in_Flags
& COI_SINK_MEMORY
) == 0 ? in_Memory
: 0;
508 buf
->data_target
= (in_Flags
& COI_SINK_MEMORY
) != 0 ? in_Memory
: 0;
509 buf
->process
= (Process
*) in_pProcesses
[0];
511 buf
->type
= BUFFER_MEMORY
;
513 /* Prepare output argument. */
514 *out_pBuffer
= (COIBUFFER
) buf
;
521 SYMBOL_VERSION (COIBufferDestroy
, 1) (COIBUFFER in_Buffer
)
523 COITRACE ("COIBufferDestroy");
525 cmd_t cmd
= CMD_BUFFER_UNMAP
;
527 assert (in_Buffer
!= NULL
);
529 /* Convert input arguments. */
530 Buffer
*buf
= (Buffer
*) in_Buffer
;
532 /* Unmap buffer on host. */
533 if (buf
->data
!= 0 && buf
->type
== BUFFER_NORMAL
)
534 if (COIBufferUnmap ((COIMAPINSTANCE
) in_Buffer
, 0, 0, 0) == COI_ERROR
)
537 /* Unmap buffer on target. */
538 if (buf
->data_target
!= 0)
540 start_critical_section ();
542 /* Send data to target. */
543 int pipe_host2tgt
= buf
->process
->pipe_host2tgt
;
544 WRITE (pipe_host2tgt
, &cmd
, sizeof (cmd_t
));
545 WRITE (pipe_host2tgt
, &buf
->fd_target
, sizeof (int));
546 WRITE (pipe_host2tgt
, &buf
->data_target
, sizeof (void *));
547 WRITE (pipe_host2tgt
, &buf
->size
, sizeof (uint64_t));
549 /* Receive data from target. */
550 READ (buf
->process
->pipe_tgt2host
, &cmd
, sizeof (cmd_t
));
552 finish_critical_section ();
555 /* Unlink shared memory. */
556 if (buf
->type
== BUFFER_NORMAL
)
558 if (close (buf
->fd
) < 0)
559 COIERROR ("Cannot close shared memory file.");
560 if (shm_unlink (buf
->name
) < 0)
561 COIERROR ("Cannot unlink shared memory.");
573 SYMBOL_VERSION (COIBufferGetSinkAddress
, 1) (COIBUFFER in_Buffer
,
574 uint64_t *out_pAddress
)
576 COITRACE ("COIBufferGetSinkAddress");
578 assert (in_Buffer
!= NULL
);
579 assert (out_pAddress
!= NULL
);
581 /* Convert input arguments. */
582 Buffer
*buf
= (Buffer
*) in_Buffer
;
584 /* Here should come BUFFER_NORMAL buffer. */
585 assert (buf
->type
== BUFFER_NORMAL
);
587 /* Prepare output argument. */
588 *out_pAddress
= (uint64_t) buf
->data_target
;
595 SYMBOL_VERSION (COIBufferMap
, 1) (COIBUFFER in_Buffer
,
597 uint64_t in_Length
, // Ignored
598 COI_MAP_TYPE in_Type
, // Ignored
599 uint32_t in_NumDependencies
,
600 const COIEVENT
*in_pDependencies
, // Ignored
601 COIEVENT
*out_pCompletion
,
602 COIMAPINSTANCE
*out_pMapInstance
,
605 COITRACE ("COIBufferMap");
607 /* Features of liboffloadmic. */
608 assert (in_Offset
== 0);
609 assert (in_NumDependencies
== 0);
611 /* Convert input arguments. */
612 Buffer
*buf
= (Buffer
*) in_Buffer
;
614 /* Only BUFFER_NORMAL buffers should come here. */
615 assert (buf
->type
== BUFFER_NORMAL
);
617 /* Map shared memory. */
618 buf
->data
= mmap (NULL
, buf
->size
, PROT_READ
| PROT_WRITE
,
619 MAP_SHARED
, buf
->fd
, 0);
620 if (buf
->data
== NULL
)
621 COIERROR ("Cannot map shared memory.");
623 /* Prepare output arguments. */
624 if (out_pMapInstance
!= 0)
625 *out_pMapInstance
= (COIMAPINSTANCE
) buf
;
627 *out_ppData
= buf
->data
;
630 out_pCompletion
->opaque
[0] = 0;
637 SYMBOL_VERSION (COIBufferRead
, 1) (COIBUFFER in_SourceBuffer
,
641 COI_COPY_TYPE in_Type
,
642 uint32_t in_NumDependencies
,
643 const COIEVENT
*in_pDependencies
, // Ignored
644 COIEVENT
*out_pCompletion
)
646 COITRACE ("COIBufferRead");
648 /* Features of liboffloadmic. */
649 assert (in_pDestData
!= NULL
);
650 assert (in_Type
== COI_COPY_UNSPECIFIED
);
651 assert (in_NumDependencies
== 0);
653 /* Convert input arguments. */
654 Buffer
*buf
= (Buffer
*) in_SourceBuffer
;
656 start_critical_section ();
658 /* Map buffers if needed. */
659 if (buf
->data
== 0 && buf
->type
== BUFFER_NORMAL
)
660 if (COIBufferMap (in_SourceBuffer
, 0, buf
->size
, (COI_MAP_TYPE
) 0, 0, 0, 0,
665 memcpy (in_pDestData
, (void *) ((uintptr_t) buf
->data
+ in_Offset
),
668 /* Unmap buffers if needed. */
669 if (buf
->type
== BUFFER_NORMAL
)
670 if (COIBufferUnmap ((COIMAPINSTANCE
) buf
, 0, 0, 0) == COI_ERROR
)
673 finish_critical_section ();
676 out_pCompletion
->opaque
[0] = 0;
683 SYMBOL_VERSION (COIBufferSetState
, 1) (COIBUFFER in_Buffer
, // Ignored
684 COIPROCESS in_Process
, // Ignored
685 COI_BUFFER_STATE in_State
, // Ignored
686 COI_BUFFER_MOVE_FLAG in_DataMove
,
687 uint32_t in_NumDependencies
,
688 const COIEVENT
*in_pDependencies
, // Ignored
689 COIEVENT
*out_pCompletion
)
691 COITRACE ("COIBufferSetState");
693 /* Features of liboffloadmic. */
694 assert (in_DataMove
== COI_BUFFER_NO_MOVE
);
695 assert (in_NumDependencies
== 0);
697 /* Looks like we have nothing to do here. */
700 out_pCompletion
->opaque
[0] = 0;
707 SYMBOL_VERSION (COIBufferUnmap
, 1) (COIMAPINSTANCE in_MapInstance
,
708 uint32_t in_NumDependencies
,
709 const COIEVENT
*in_pDependencies
, // Ignored
710 COIEVENT
*out_pCompletion
)
712 COITRACE ("COIBufferUnmap");
714 /* Features of liboffloadmic. */
715 assert (in_MapInstance
!= NULL
);
716 assert (in_NumDependencies
== 0);
718 /* Convert input arguments. */
719 Buffer
*buffer
= (Buffer
*) in_MapInstance
;
721 /* Only BUFFER_NORMAL buffers should come here. */
722 assert (buffer
->type
== BUFFER_NORMAL
);
724 /* Unmap shared memory. */
725 if (munmap (buffer
->data
, buffer
->size
) < 0)
726 COIERROR ("Cannot unmap shared memory.");
731 out_pCompletion
->opaque
[0] = 0;
738 SYMBOL_VERSION (COIBufferWrite
, 1) (COIBUFFER in_DestBuffer
,
740 const void *in_pSourceData
,
742 COI_COPY_TYPE in_Type
,
743 uint32_t in_NumDependencies
,
744 const COIEVENT
*in_pDependencies
, // Ignored
745 COIEVENT
*out_pCompletion
)
747 COITRACE ("COIBufferWrite");
749 /* Features of liboffloadmic. */
750 assert (in_DestBuffer
!= NULL
);
751 assert (in_pSourceData
!= NULL
);
752 assert (in_Type
== COI_COPY_UNSPECIFIED
);
753 assert (in_NumDependencies
== 0);
755 /* Convert input arguments. */
756 Buffer
*buf
= (Buffer
*) in_DestBuffer
;
758 start_critical_section ();
760 /* Map buffers if needed. */
761 if (buf
->data
== 0 && buf
->type
== BUFFER_NORMAL
)
762 if (COIBufferMap (in_DestBuffer
, 0, buf
->size
, (COI_MAP_TYPE
) 0, 0, 0, 0, 0,
767 memcpy ((void *) ((uintptr_t) buf
->data
+ in_Offset
), in_pSourceData
,
770 /* Unmap buffers if needed. */
771 if (buf
->type
== BUFFER_NORMAL
)
772 if (COIBufferUnmap ((COIMAPINSTANCE
) buf
, 0, 0, 0) == COI_ERROR
)
775 finish_critical_section ();
778 out_pCompletion
->opaque
[0] = 0;
785 SYMBOL_VERSION (COIEngineGetCount
, 1) (COI_ISA_TYPE isa
,
788 COITRACE ("COIEngineGetCount");
790 /* Features of liboffloadmic. */
791 assert (isa
== COI_ISA_MIC
);
792 assert (count
!= NULL
);
794 /* Prepare output arguments. */
795 *count
= num_engines
;
802 SYMBOL_VERSION (COIEngineGetHandle
, 1) (COI_ISA_TYPE in_ISA
,
803 uint32_t in_EngineIndex
,
804 COIENGINE
*out_pEngineHandle
)
806 COITRACE ("COIEngineGetHandle");
808 /* Features of liboffloadmic. */
809 assert (in_ISA
== COI_ISA_MIC
);
810 assert (out_pEngineHandle
!= NULL
);
812 /* Check engine index. */
813 if (in_EngineIndex
>= num_engines
)
814 COIERROR ("Wrong engine index.");
816 /* Create engine handle. */
817 Engine
*engine
= new Engine
;
819 engine
->index
= in_EngineIndex
;
820 engine
->type
= in_ISA
;
822 /* Prepare output argument. */
823 *out_pEngineHandle
= (COIENGINE
) engine
;
830 SYMBOL_VERSION (COIEventWait
, 1) (uint16_t in_NumEvents
,
831 const COIEVENT
*in_pEvents
,
832 int32_t in_TimeoutMilliseconds
,
833 uint8_t in_WaitForAll
,
834 uint32_t *out_pNumSignaled
,
835 uint32_t *out_pSignaledIndices
)
837 COITRACE ("COIEventWait");
839 /* Features of liboffloadmic. */
840 assert (in_pEvents
!= NULL
);
841 assert (in_TimeoutMilliseconds
== 0 || in_TimeoutMilliseconds
== -1);
842 assert (in_WaitForAll
== 1);
843 assert (out_pNumSignaled
== NULL
);
844 assert (out_pSignaledIndices
== NULL
);
846 if (in_TimeoutMilliseconds
== 0)
848 /* If some event is not signalled, return timeout error. */
849 for (uint16_t i
= 0; i
< in_NumEvents
; i
++)
850 if (non_signalled_events
.count (in_pEvents
[i
].opaque
[0]) > 0)
851 return COI_TIME_OUT_REACHED
;
854 /* If the event signalled with an error, return that error. */
855 start_critical_section ();
856 COIRESULT res
= get_event_result (in_pEvents
[i
]);
857 finish_critical_section ();
858 if (res
!= COI_SUCCESS
)
864 /* Wait indefinitely for all events. */
865 for (uint16_t i
= 0; i
< in_NumEvents
; i
++)
867 while (non_signalled_events
.count (in_pEvents
[i
].opaque
[0]) > 0)
870 /* If the event signalled with an error, return that error. */
871 start_critical_section ();
872 COIRESULT res
= get_event_result (in_pEvents
[i
]);
873 finish_critical_section ();
874 if (res
!= COI_SUCCESS
)
884 SYMBOL_VERSION (COIEventRegisterCallback
, 1) (const COIEVENT in_Event
,
885 COI_EVENT_CALLBACK in_Callback
,
886 const void *in_UserData
,
887 const uint64_t in_Flags
)
889 COITRACE ("COIEventRegisterCallback");
891 /* Features of liboffloadmic. */
892 assert (in_Callback
!= NULL
);
893 assert (in_UserData
!= NULL
);
894 assert (in_Flags
== 0);
896 start_critical_section ();
897 if (non_signalled_events
.count (in_Event
.opaque
[0]) == 0)
899 /* If the event is already signalled, invoke the callback immediately. */
900 COIRESULT res
= get_event_result (in_Event
);
901 in_Callback (in_Event
, res
, in_UserData
);
906 callback
.ptr
= in_Callback
;
907 callback
.data
= in_UserData
;
908 callbacks
.insert (std::pair
<uint64_t, Callback
> (in_Event
.opaque
[0],
911 finish_critical_section ();
917 /* The start routine for the COI pipeline thread. */
920 pipeline_thread_routine (void *in_Pipeline
)
922 /* Convert input arguments. */
923 Pipeline
*pipeline
= (Pipeline
*) in_Pipeline
;
926 pipeline
->pipe_host2tgt
927 = open (pipeline
->pipe_host2tgt_path
, O_CLOEXEC
| O_WRONLY
);
928 if (pipeline
->pipe_host2tgt
< 0)
929 COIERRORN ("Cannot open host-to-target pipe.");
930 pipeline
->pipe_tgt2host
931 = open (pipeline
->pipe_tgt2host_path
, O_CLOEXEC
| O_RDONLY
);
932 if (pipeline
->pipe_tgt2host
< 0)
933 COIERRORN ("Cannot open target-to-host pipe.");
935 free (pipeline
->pipe_host2tgt_path
);
936 free (pipeline
->pipe_tgt2host_path
);
937 pipeline
->pipe_host2tgt_path
= NULL
;
938 pipeline
->pipe_tgt2host_path
= NULL
;
940 while (!pipeline
->destroy
)
941 if (pipeline
->queue
.empty ())
945 Function func
= pipeline
->queue
.front ();
946 start_critical_section ();
947 pipeline
->queue
.pop ();
948 finish_critical_section ();
950 /* Send data to target. */
951 cmd_t cmd
= CMD_PIPELINE_RUN_FUNCTION
;
952 WRITEN (pipeline
->pipe_host2tgt
, &cmd
, sizeof (cmd_t
));
953 WRITEN (pipeline
->pipe_host2tgt
, &func
.ptr
, sizeof (void *));
954 WRITEN (pipeline
->pipe_host2tgt
, &func
.num_buffers
, sizeof (uint32_t));
955 for (uint32_t i
= 0; i
< func
.num_buffers
; i
++)
957 WRITEN (pipeline
->pipe_host2tgt
, &func
.bufs_size
[i
],
959 WRITEN (pipeline
->pipe_host2tgt
, &func
.bufs_data_target
[i
],
962 WRITEN (pipeline
->pipe_host2tgt
, &func
.misc_data_len
,
964 if (func
.misc_data_len
> 0)
965 WRITEN (pipeline
->pipe_host2tgt
, func
.misc_data
, func
.misc_data_len
);
966 WRITEN (pipeline
->pipe_host2tgt
, &func
.return_value_len
,
969 delete [] func
.bufs_size
;
970 delete [] func
.bufs_data_target
;
972 /* Receive data from target. Wait for target function to complete,
973 whether it has any data to return or not. */
974 bool has_return_value
= func
.return_value_len
> 0;
976 = read (pipeline
->pipe_tgt2host
,
977 has_return_value
? func
.return_value
: &cmd
,
978 has_return_value
? func
.return_value_len
: sizeof (cmd_t
));
981 start_critical_section ();
982 signal_event (func
.completion_event
, COI_PROCESS_DIED
);
983 pipeline
->is_destroyed
= true;
984 finish_critical_section ();
987 else if (ret_len
!= (has_return_value
? func
.return_value_len
989 COIERRORN ("Cannot read from pipe.");
991 start_critical_section ();
992 signal_event (func
.completion_event
, COI_SUCCESS
);
993 finish_critical_section ();
996 /* Send data to target. */
997 const cmd_t cmd
= CMD_PIPELINE_DESTROY
;
998 WRITEN (pipeline
->pipe_host2tgt
, &cmd
, sizeof (cmd_t
));
1001 if (close (pipeline
->pipe_host2tgt
) < 0)
1002 COIERRORN ("Cannot close host-to-target pipe.");
1003 if (close (pipeline
->pipe_tgt2host
) < 0)
1004 COIERRORN ("Cannot close target-to-host pipe.");
1006 start_critical_section ();
1007 pipeline
->is_destroyed
= true;
1008 finish_critical_section ();
1014 SYMBOL_VERSION (COIPipelineCreate
, 1) (COIPROCESS in_Process
,
1015 COI_CPU_MASK in_Mask
,
1016 uint32_t in_StackSize
, // Ignored
1017 COIPIPELINE
*out_pPipeline
)
1019 COITRACE ("COIPipelineCreate");
1021 /* Features of liboffloadmic. */
1022 assert (in_Process
!= NULL
);
1023 assert (in_Mask
== 0);
1024 assert (out_pPipeline
!= NULL
);
1026 /* Convert input arguments. */
1027 Process
*proc
= (Process
*) in_Process
;
1029 start_critical_section ();
1031 /* Create pipeline handle. */
1032 Pipeline
*pipeline
= new Pipeline
;
1033 pipeline
->destroy
= false;
1034 pipeline
->is_destroyed
= false;
1035 pipeline
->process
= proc
;
1036 pipelines
.insert (pipeline
);
1039 uint32_t pipeline_num
= max_pipeline_num
++;
1040 char *eng_dir
= pipeline
->process
->engine
->dir
;
1041 MALLOC (char *, pipeline
->pipe_host2tgt_path
,
1042 strlen (eng_dir
) + sizeof (PIPE_HOST2TGT_NAME
"0000000000"));
1043 MALLOC (char *, pipeline
->pipe_tgt2host_path
,
1044 strlen (eng_dir
) + sizeof (PIPE_TGT2HOST_NAME
"0000000000"));
1045 sprintf (pipeline
->pipe_host2tgt_path
, "%s" PIPE_HOST2TGT_NAME
"%010d",
1046 eng_dir
, pipeline_num
);
1047 sprintf (pipeline
->pipe_tgt2host_path
, "%s" PIPE_TGT2HOST_NAME
"%010d",
1048 eng_dir
, pipeline_num
);
1049 if (mkfifo (pipeline
->pipe_host2tgt_path
, S_IRUSR
| S_IWUSR
) < 0)
1050 COIERROR ("Cannot create pipe %s.", pipeline
->pipe_host2tgt_path
);
1051 if (mkfifo (pipeline
->pipe_tgt2host_path
, S_IRUSR
| S_IWUSR
) < 0)
1052 COIERROR ("Cannot create pipe %s.", pipeline
->pipe_tgt2host_path
);
1054 /* Send data to target. */
1055 const cmd_t cmd
= CMD_PIPELINE_CREATE
;
1056 WRITE (proc
->pipe_host2tgt
, &cmd
, sizeof (cmd_t
));
1057 WRITE (proc
->pipe_host2tgt
, &pipeline_num
, sizeof (pipeline_num
));
1059 /* Create a new thread for the pipeline. */
1060 if (pthread_create (&pipeline
->thread
, NULL
, pipeline_thread_routine
,
1062 COIERROR ("Cannot create new thread.");
1064 finish_critical_section ();
1066 /* Prepare output arguments. */
1067 *out_pPipeline
= (COIPIPELINE
) pipeline
;
1074 SYMBOL_VERSION (COIPipelineDestroy
, 1) (COIPIPELINE in_Pipeline
)
1076 COITRACE ("COIPipelineDestroy");
1078 assert (in_Pipeline
!= NULL
);
1080 /* Convert input arguments. */
1081 Pipeline
*pipeline
= (Pipeline
*) in_Pipeline
;
1083 start_critical_section ();
1084 /* Remove pipeline from the set of undestroyed pipelines. */
1085 pipelines
.erase (pipeline
);
1087 /* Exit pipeline thread. */
1088 pipeline
->destroy
= true;
1089 finish_critical_section ();
1091 while (!pipeline_is_destroyed (pipeline
))
1094 /* Join with a destroyed thread. */
1095 if (pthread_join (pipeline
->thread
, NULL
))
1096 COIERROR ("Cannot join with a thread.");
1105 SYMBOL_VERSION (COIPipelineRunFunction
, 1) (COIPIPELINE in_Pipeline
,
1106 COIFUNCTION in_Function
,
1107 uint32_t in_NumBuffers
,
1108 const COIBUFFER
*in_Buffers
,
1109 const COI_ACCESS_FLAGS
*in_pBufferAccessFlags
, // Ignored
1110 uint32_t in_NumDependencies
,
1111 const COIEVENT
*in_pDependencies
, // Ignored
1112 const void *in_pMiscData
,
1113 uint16_t in_MiscDataLen
,
1114 void *out_pAsyncReturnValue
,
1115 uint16_t in_AsyncReturnValueLen
,
1116 COIEVENT
*out_pCompletion
)
1118 COITRACE ("COIPipelineRunFunction");
1120 /* Features of liboffloadmic. */
1121 assert (in_Pipeline
!= NULL
);
1122 assert (in_Function
!= NULL
);
1123 assert (in_NumDependencies
== 0);
1126 func
.ptr
= (void *) in_Function
;
1127 func
.num_buffers
= in_NumBuffers
;
1128 func
.bufs_size
= new uint64_t [in_NumBuffers
];
1129 func
.bufs_data_target
= new void * [in_NumBuffers
];
1130 for (uint32_t i
= 0; i
< in_NumBuffers
; i
++)
1132 Buffer
**bufs
= (Buffer
**) in_Buffers
;
1133 func
.bufs_size
[i
] = bufs
[i
]->size
;
1134 func
.bufs_data_target
[i
] = bufs
[i
]->data_target
;
1136 func
.misc_data
= (void *) in_pMiscData
;
1137 func
.misc_data_len
= in_MiscDataLen
;
1138 func
.return_value
= out_pAsyncReturnValue
;
1139 func
.return_value_len
= in_AsyncReturnValueLen
;
1141 start_critical_section ();
1142 func
.completion_event
.opaque
[0] = max_event_num
++;
1143 non_signalled_events
.insert (func
.completion_event
.opaque
[0]);
1144 ((Pipeline
*) in_Pipeline
)->queue
.push (func
);
1145 finish_critical_section ();
1147 /* In case of synchronous execution we have to wait for target. */
1148 if (out_pCompletion
== NULL
)
1149 COIEventWait (1, &func
.completion_event
, -1, 1, NULL
, NULL
);
1151 *out_pCompletion
= func
.completion_event
;
1158 SYMBOL_VERSION (COIProcessCreateFromMemory
, 1) (COIENGINE in_Engine
,
1159 const char *in_pBinaryName
,
1160 const void *in_pBinaryBuffer
,
1161 uint64_t in_BinaryBufferLength
,
1163 const char **in_ppArgv
,
1165 const char **in_ppAdditionalEnv
,
1166 uint8_t in_ProxyActive
, // Ignored
1167 const char *in_Reserved
, // Ignored
1168 uint64_t in_InitialBufferSpace
, // Ignored
1169 const char *in_LibrarySearchPath
,
1170 const char *in_FileOfOrigin
, // Ignored
1171 uint64_t in_FileOfOriginOffset
, // Ignored
1172 COIPROCESS
*out_pProcess
)
1174 COITRACE ("COIProcessCreateFromMemory");
1176 const int run_max_args_num
= 128;
1177 char *run_argv
[run_max_args_num
];
1178 char *emul_run
= getenv (OFFLOAD_EMUL_RUN_ENV
);
1179 const int uint_max_len
= 11;
1181 /* Features of liboffloadmic. */
1182 assert (in_Engine
!= NULL
);
1183 assert (in_pBinaryName
!= NULL
);
1184 assert (in_pBinaryBuffer
!= NULL
);
1185 assert (in_Argc
== 0);
1186 assert (in_ppArgv
== NULL
);
1187 assert (in_ppAdditionalEnv
== NULL
);
1188 assert (in_LibrarySearchPath
!= NULL
);
1189 assert (out_pProcess
!= NULL
);
1191 /* Convert input arguments. */
1192 Engine
*eng
= (Engine
*) in_Engine
;
1194 /* Create temporary directory for engine files. */
1195 assert (eng
->dir
== NULL
);
1196 STRDUP (eng
->dir
, ENGINE_PATH
);
1197 if (mkdtemp (eng
->dir
) == NULL
)
1198 COIERROR ("Cannot create temporary directory %s.", eng
->dir
);
1200 /* Save path to engine directory for clean up on exit. */
1202 tmp_dirs
= (char **) realloc (tmp_dirs
, tmp_dirs_num
* sizeof (char *));
1204 COIERROR ("Cannot allocate memory.");
1205 STRDUP (tmp_dirs
[tmp_dirs_num
- 1], eng
->dir
);
1207 /* Create target executable file. */
1209 MALLOC (char *, target_exe
, strlen (eng
->dir
) + strlen (in_pBinaryName
) + 2);
1210 sprintf (target_exe
, "%s/%s", eng
->dir
, in_pBinaryName
);
1211 int fd
= open (target_exe
, O_CLOEXEC
| O_CREAT
| O_WRONLY
, S_IRUSR
| S_IWUSR
);
1213 COIERROR ("Cannot create file %s.", target_exe
);
1214 FILE *file
= fdopen (fd
, "wb");
1216 COIERROR ("Cannot associate stream with file descriptor.");
1217 if (fwrite (in_pBinaryBuffer
, 1, in_BinaryBufferLength
, file
)
1218 != in_BinaryBufferLength
)
1219 COIERROR ("Cannot write in file %s.", target_exe
);
1220 if (fclose (file
) != 0)
1221 COIERROR ("Cannot close file %s.", target_exe
);
1223 /* Fix file permissions. */
1224 if (chmod (target_exe
, S_IRWXU
) < 0)
1225 COIERROR ("Cannot change permissions for file %s.", target_exe
);
1227 /* Create directory for pipes to prevent names collision. */
1229 MALLOC (char *, pipes_path
, strlen (eng
->dir
) + sizeof (PIPES_PATH
));
1230 sprintf (pipes_path
, "%s" PIPES_PATH
, eng
->dir
);
1231 if (mkdir (pipes_path
, S_IRWXU
) < 0)
1232 COIERROR ("Cannot create folder %s.", pipes_path
);
1234 /* Create 2 main pipes for inter-process communication. */
1235 char *pipe_host2tgt_path
, *pipe_tgt2host_path
;
1236 MALLOC (char *, pipe_host2tgt_path
,
1237 strlen (eng
->dir
) + sizeof (PIPE_HOST2TGT_NAME
"mainpipe"));
1238 MALLOC (char *, pipe_tgt2host_path
,
1239 strlen (eng
->dir
) + sizeof (PIPE_TGT2HOST_NAME
"mainpipe"));
1240 sprintf (pipe_host2tgt_path
, "%s" PIPE_HOST2TGT_NAME
"mainpipe", eng
->dir
);
1241 sprintf (pipe_tgt2host_path
, "%s" PIPE_TGT2HOST_NAME
"mainpipe", eng
->dir
);
1242 if (mkfifo (pipe_host2tgt_path
, S_IRUSR
| S_IWUSR
) < 0)
1243 COIERROR ("Cannot create main pipe %s.", pipe_host2tgt_path
);
1244 if (mkfifo (pipe_tgt2host_path
, S_IRUSR
| S_IWUSR
) < 0)
1245 COIERROR ("Cannot create main pipe %s.", pipe_tgt2host_path
);
1248 if (emul_run
== NULL
|| strcmp (emul_run
, "") == 0)
1250 STRDUP (run_argv
[0], target_exe
);
1251 run_argv
[1] = (char *) NULL
;
1257 STRDUP (tmp
, emul_run
);
1258 char *tok
= strtok_r (tmp
, " ", &ptr
);
1261 if (i
>= run_max_args_num
)
1262 COIERROR ("Run command has too many arguments.");
1263 STRDUP (run_argv
[i
++], tok
);
1264 tok
= strtok_r (NULL
, " ", &ptr
);
1266 STRDUP (run_argv
[i
], target_exe
);
1267 run_argv
[i
+ 1] = (char *) NULL
;
1273 if (in_DupEnv
== true)
1274 while (environ
[env_num
++]);
1275 env_num
+= 4; // LD_LIBRARY_PATH, MIC_DIR, MIC_INDEX, NULL
1278 MALLOC (char **, envp
, env_num
* sizeof (char *));
1281 if (in_DupEnv
== true)
1282 for (unsigned i
= 0; environ
[i
] != NULL
; i
++)
1286 STRDUP (env_name
, environ
[i
]);
1287 for (j
= 0; env_name
[j
] != '=' && env_name
[j
] != '\0'; j
++);
1289 if (strcmp (env_name
, "LD_LIBRARY_PATH") != 0
1290 && strcmp (env_name
, MIC_DIR_ENV
) != 0
1291 && strcmp (env_name
, MIC_INDEX_ENV
) != 0)
1292 STRDUP (envp
[env_i
++], environ
[i
]);
1296 MALLOC (char *, envp
[env_i
], strlen (MIC_DIR_ENV
) + strlen (eng
->dir
) + 2);
1297 sprintf (envp
[env_i
], "%s=%s", MIC_DIR_ENV
, eng
->dir
);
1299 MALLOC (char *, envp
[env_i
+ 1], strlen (MIC_INDEX_ENV
) + uint_max_len
+ 1);
1300 sprintf (envp
[env_i
+ 1], "%s=%u", MIC_INDEX_ENV
, eng
->index
);
1302 MALLOC (char *, envp
[env_i
+ 2],
1303 strlen ("LD_LIBRARY_PATH=") + strlen (in_LibrarySearchPath
) + 1);
1304 sprintf (envp
[env_i
+ 2], "LD_LIBRARY_PATH=%s", in_LibrarySearchPath
);
1306 envp
[env_i
+ 3] = (char *) NULL
;
1308 /* Create target process. */
1309 pid_t pid
= vfork ();
1311 COIERROR ("Cannot create child process.");
1315 /* Run target executable. */
1316 if (execvpe (run_argv
[0], run_argv
, envp
) == -1)
1317 COIERROR ("Cannot execute file %s.", target_exe
);
1320 /* Open main pipes. */
1321 int pipe_host2tgt
= open (pipe_host2tgt_path
, O_CLOEXEC
| O_WRONLY
);
1322 if (pipe_host2tgt
< 0)
1323 COIERROR ("Cannot open host-to-target main pipe.");
1324 int pipe_tgt2host
= open (pipe_tgt2host_path
, O_CLOEXEC
| O_RDONLY
);
1325 if (pipe_tgt2host
< 0)
1326 COIERROR ("Cannot open target-to-host main pipe.");
1328 /* Create process handle. */
1329 Process
*proc
= new Process
;
1331 proc
->pipe_host2tgt
= pipe_host2tgt
;
1332 proc
->pipe_tgt2host
= pipe_tgt2host
;
1334 proc
->functions
= NULL
;
1336 /* Prepare output arguments. */
1337 *out_pProcess
= (COIPROCESS
) proc
;
1340 for (unsigned i
= 0; run_argv
[i
] != NULL
; i
++)
1342 for (unsigned i
= 0; envp
[i
] != NULL
; i
++)
1345 free (pipe_host2tgt_path
);
1346 free (pipe_tgt2host_path
);
1355 SYMBOL_VERSION (COIProcessCreateFromFile
, 1) (COIENGINE in_Engine
,
1356 const char *in_pBinaryName
,
1358 const char **in_ppArgv
,
1360 const char **in_ppAdditionalEnv
,
1361 uint8_t in_ProxyActive
,
1362 const char *in_Reserved
,
1363 uint64_t in_BufferSpace
,
1364 const char *in_LibrarySearchPath
,
1365 COIPROCESS
*out_pProcess
)
1367 COITRACE ("COIProcessCreateFromFile");
1369 /* liboffloadmic with GCC compiled binaries should never go here. */
1376 SYMBOL_VERSION (COIProcessDestroy
, 1) (COIPROCESS in_Process
,
1377 int32_t in_WaitForMainTimeout
, // Ignored
1378 uint8_t in_ForceDestroy
,
1379 int8_t *out_pProcessReturn
,
1380 uint32_t *out_pTerminationCode
)
1382 COITRACE ("COIProcessDestroy");
1384 assert (in_Process
!= NULL
);
1385 assert (out_pProcessReturn
!= NULL
);
1386 assert (out_pTerminationCode
!= NULL
);
1388 /* Convert input arguments. */
1389 Process
*proc
= (Process
*) in_Process
;
1391 /* Destroy all undestroyed pipelines. */
1392 while (!pipelines
.empty ())
1394 std::set
<Pipeline
*>::iterator p
= pipelines
.begin ();
1395 COIPipelineDestroy ((COIPIPELINE
) *p
);
1398 /* Close main pipes. */
1399 if (close (proc
->pipe_host2tgt
) < 0)
1400 COIERROR ("Cannot close host-to-target main pipe.");
1401 if (close (proc
->pipe_tgt2host
) < 0)
1402 COIERROR ("Cannot close target-to-host main pipe.");
1404 /* Shutdown target process by force. */
1405 if (in_ForceDestroy
)
1406 kill (proc
->pid
, SIGTERM
);
1409 free (proc
->engine
->dir
);
1410 free (proc
->functions
);
1411 delete proc
->engine
;
1414 /* Prepare output arguments. */
1415 *out_pProcessReturn
= 0;
1416 *out_pTerminationCode
= 0;
1423 SYMBOL_VERSION (COIProcessGetFunctionHandles
, 1) (COIPROCESS in_Process
,
1424 uint32_t in_NumFunctions
,
1425 const char **in_ppFunctionNameArray
,
1426 COIFUNCTION
*out_pFunctionHandleArray
)
1428 COITRACE ("COIProcessGetFunctionHandles");
1430 assert (in_Process
!= NULL
);
1431 assert (in_ppFunctionNameArray
!= NULL
);
1432 assert (out_pFunctionHandleArray
!= NULL
);
1434 /* Convert input arguments. */
1435 Process
*proc
= (Process
*) in_Process
;
1437 /* This function should be called once for the process. */
1438 assert (proc
->functions
== NULL
);
1440 /* Create array of function pointers. Last element is 0, what shows the end
1441 of the array. This array is used to free memory when process is
1443 proc
->functions
= (void **) calloc (in_NumFunctions
+ 1, sizeof (void *));
1444 if (proc
->functions
== NULL
)
1445 COIERROR ("Cannot allocate memory.");
1447 /* Get handles for functions. */
1448 for (uint32_t i
= 0; i
< in_NumFunctions
; i
++)
1450 size_t len
= strlen (in_ppFunctionNameArray
[i
]) + 1;
1452 start_critical_section ();
1454 /* Send data to target. */
1455 const cmd_t cmd
= CMD_GET_FUNCTION_HANDLE
;
1456 WRITE (proc
->pipe_host2tgt
, &cmd
, sizeof (cmd_t
));
1457 WRITE (proc
->pipe_host2tgt
, &len
, sizeof (size_t));
1458 WRITE (proc
->pipe_host2tgt
, in_ppFunctionNameArray
[i
], len
);
1460 /* Receive data from target. */
1462 READ (proc
->pipe_tgt2host
, &fn_ptr
, sizeof (void *));
1464 finish_critical_section ();
1466 /* Save function pointer. */
1467 proc
->functions
[i
] = fn_ptr
;
1469 /* Prepare output arguments. */
1470 out_pFunctionHandleArray
[i
] = (COIFUNCTION
) fn_ptr
;
1478 SYMBOL_VERSION (COIProcessLoadLibraryFromMemory
, 2) (COIPROCESS in_Process
,
1479 const void *in_pLibraryBuffer
,
1480 uint64_t in_LibraryBufferLength
,
1481 const char *in_pLibraryName
,
1482 const char *in_LibrarySearchPath
, // Ignored
1483 const char *in_FileOfOrigin
, // Ignored
1484 uint64_t in_FileOfOriginOffset
, // Ignored
1485 uint32_t in_Flags
, // Ignored
1486 COILIBRARY
*out_pLibrary
)
1488 COITRACE ("COIProcessLoadLibraryFromMemory");
1490 assert (in_Process
!= NULL
);
1491 assert (in_pLibraryBuffer
!= NULL
);
1492 assert (out_pLibrary
!= NULL
);
1494 /* Convert input arguments. */
1495 Process
*proc
= (Process
*) in_Process
;
1497 /* Create target library file. */
1499 size_t len
= strlen (proc
->engine
->dir
) + strlen (in_pLibraryName
) + 2;
1500 MALLOC (char *, lib_path
, len
);
1501 sprintf (lib_path
, "%s/%s", proc
->engine
->dir
, in_pLibraryName
);
1502 int fd
= open (lib_path
, O_CLOEXEC
| O_CREAT
| O_WRONLY
, S_IRUSR
| S_IWUSR
);
1504 COIERROR ("Cannot create file %s.", lib_path
);
1505 FILE *file
= fdopen (fd
, "wb");
1507 COIERROR ("Cannot associate stream with file descriptor.");
1508 if (fwrite (in_pLibraryBuffer
, 1, in_LibraryBufferLength
, file
)
1509 != in_LibraryBufferLength
)
1510 COIERROR ("Cannot write in file %s.", lib_path
);
1511 if (fclose (file
) != 0)
1512 COIERROR ("Cannot close file %s.", lib_path
);
1514 start_critical_section ();
1516 /* Make target open library. */
1517 const cmd_t cmd
= CMD_OPEN_LIBRARY
;
1518 WRITE (proc
->pipe_host2tgt
, &cmd
, sizeof (cmd_t
));
1519 WRITE (proc
->pipe_host2tgt
, &len
, sizeof (size_t));
1520 WRITE (proc
->pipe_host2tgt
, lib_path
, len
);
1522 /* Receive data from target. */
1524 READ (proc
->pipe_tgt2host
, &handle
, sizeof (void *));
1526 finish_critical_section ();
1531 *out_pLibrary
= (COILIBRARY
) handle
;
1537 SYMBOL_VERSION (COIProcessRegisterLibraries
, 1) (uint32_t in_NumLibraries
, // Ignored
1538 const void **in_ppLibraryArray
, // Ignored
1539 const uint64_t *in_pLibrarySizeArray
, // Ignored
1540 const char **in_ppFileOfOriginArray
, // Ignored
1541 const uint64_t *in_pFileOfOriginOffSetArray
) // Ignored
1543 COITRACE ("COIProcessRegisterLibraries");
1545 /* Looks like we have nothing to do here. */
1552 SYMBOL_VERSION (COIProcessUnloadLibrary
, 1) (COIPROCESS in_Process
,
1553 COILIBRARY in_Library
)
1555 COITRACE ("COIProcessUnloadLibrary");
1557 assert (in_Process
!= NULL
);
1558 assert (in_Library
!= NULL
);
1560 const cmd_t cmd
= CMD_CLOSE_LIBRARY
;
1562 /* Convert input arguments. */
1563 Process
*proc
= (Process
*) in_Process
;
1565 start_critical_section ();
1567 /* Make target close library. */
1568 WRITE (proc
->pipe_host2tgt
, &cmd
, sizeof (cmd_t
));
1569 WRITE (proc
->pipe_host2tgt
, &in_Library
, sizeof (void *));
1571 finish_critical_section ();
1578 SYMBOL_VERSION (COIPerfGetCycleFrequency
, 1) ()
1580 COITRACE ("COIPerfGetCycleFrequency");
1582 return (uint64_t) CYCLE_FREQUENCY
;
1587 SYMBOL_VERSION (COIPipelineClearCPUMask
, 1) (COI_CPU_MASK
*in_Mask
)
1589 COITRACE ("COIPipelineClearCPUMask");
1591 /* Looks like we have nothing to do here. */
1598 SYMBOL_VERSION (COIPipelineSetCPUMask
, 1) (COIPROCESS in_Process
,
1600 uint8_t in_ThreadID
,
1601 COI_CPU_MASK
*out_pMask
)
1603 COITRACE ("COIPipelineSetCPUMask");
1605 /* Looks like we have nothing to do here. */
1612 SYMBOL_VERSION (COIEngineGetInfo
, 1) (COIENGINE in_EngineHandle
, // Ignored
1613 uint32_t in_EngineInfoSize
, // Ignored
1614 COI_ENGINE_INFO
*out_pEngineInfo
)
1616 COITRACE ("COIEngineGetInfo");
1618 assert (out_pEngineInfo
!= NULL
);
1620 out_pEngineInfo
->ISA
= COI_DEVICE_KNL
;
1621 out_pEngineInfo
->NumCores
= 1;
1622 out_pEngineInfo
->NumThreads
= 8;
1623 out_pEngineInfo
->CoreMaxFrequency
= SYMBOL_VERSION(COIPerfGetCycleFrequency
,1)() / 1000000;
1624 out_pEngineInfo
->PhysicalMemory
= 1024;
1625 out_pEngineInfo
->PhysicalMemoryFree
= 1024;
1626 out_pEngineInfo
->SwapMemory
= 1024;
1627 out_pEngineInfo
->SwapMemoryFree
= 1024;
1628 out_pEngineInfo
->MiscFlags
= COI_ENG_ECC_DISABLED
;