2 Copyright (c) 2014 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.
32 #include "coi_version_asm.h"
34 #define CYCLE_FREQUENCY 1000000000
36 /* Environment variables. */
37 extern char **environ
;
39 /* List of directories for removing on exit. */
41 unsigned tmp_dirs_num
= 0;
43 /* Number of KNC engines. */
46 /* Mutex to sync parallel execution. */
47 pthread_mutex_t mutex
= PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
;
97 read_long_env (const char *env_name
, long *var
, long var_default
)
99 char *str
= getenv (env_name
);
102 if (!str
|| *str
== '\0')
107 *var
= strtol (str
, &s
, 0);
108 if (errno
!= 0 || s
== str
|| *s
!= '\0')
109 COIERROR ("Variable %s has invalid value.", env_name
);
115 __attribute__((constructor
))
119 if (read_long_env (OFFLOAD_EMUL_KNC_NUM_ENV
, &knc_engines_num
, 1)
125 /* Helper function for directory removing. */
126 static COIRESULT
remove_directory (char *path
)
129 struct dirent
*entry
;
130 struct stat statfile
;
131 DIR *dir
= opendir (path
);
133 COIERROR ("Cannot open directory %s.", dir
);
135 while (entry
= readdir (dir
))
137 if (!strcmp (entry
->d_name
, ".") || !strcmp (entry
->d_name
, ".."))
140 MALLOC (char *, file
, strlen (path
) + strlen (entry
->d_name
) + 2);
141 sprintf (file
, "%s/%s", path
, entry
->d_name
);
143 if (stat (file
, &statfile
) < 0)
144 COIERROR ("Cannot retrieve information about file %s.", file
);
146 if (S_ISDIR (statfile
.st_mode
))
148 if (remove_directory (file
) == COI_ERROR
)
153 if (unlink (file
) < 0)
154 COIERROR ("Cannot unlink file %s.", file
);
160 if (closedir (dir
) < 0)
161 COIERROR ("Cannot close directory %s.", path
);
162 if (rmdir (path
) < 0)
163 COIERROR ("Cannot remove directory %s.", path
);
168 __attribute__((destructor
))
173 for (i
= 0; i
< tmp_dirs_num
; i
++)
175 remove_directory (tmp_dirs
[i
]);
187 SYMBOL_VERSION (COIBufferCopy
, 1) (COIBUFFER dest_buffer
,
188 COIBUFFER source_buffer
,
189 uint64_t dest_offset
,
190 uint64_t source_offset
,
193 uint32_t dependencies_num
, // Ignored
194 const COIEVENT
*dependencies
, // Ignored
195 COIEVENT
*completion
) // Ignored
197 COITRACE ("COIBufferCopy");
199 /* Convert input arguments. */
200 Buffer
*dest
= (Buffer
*) dest_buffer
;
201 Buffer
*source
= (Buffer
*) source_buffer
;
203 /* Features of liboffload. */
204 assert (type
== COI_COPY_UNSPECIFIED
);
206 /* Start critical section. */
207 if (pthread_mutex_lock (&mutex
) != 0)
208 COIERROR ("Cannot lock mutex.");
210 /* Map buffers if needed. */
211 if (dest
->data
== 0 && dest
->type
== BUFFER_NORMAL
)
212 if (COIBufferMap (dest_buffer
, 0, dest
->size
, (COI_MAP_TYPE
) 0,
213 0, 0, 0, 0, 0) == COI_ERROR
)
215 if (source
->data
== 0 && source
->type
== BUFFER_NORMAL
)
216 if (COIBufferMap (source_buffer
, 0, source
->size
, (COI_MAP_TYPE
) 0,
217 0, 0, 0, 0, 0) == COI_ERROR
)
221 if (source
->data
!= 0 && dest
->data
!= 0)
222 memcpy ((void *) ((uintptr_t) dest
->data
+dest_offset
),
223 (void *) ((uintptr_t) source
->data
+source_offset
), length
);
226 assert (dest
->process
== source
->process
);
229 cmd_t cmd
= CMD_BUFFER_COPY
;
230 Pipeline
*pipeline
= dest
->process
->pipeline
;
232 /* Create intermediary buffer. */
233 if (COIBufferCreate (length
, COI_BUFFER_NORMAL
, 0, 0, 1,
234 (COIPROCESS
*) &dest
->process
,
235 (COIBUFFER
*) &buffer
) == COI_ERROR
)
238 /* Copy from source to intermediary buffer. */
239 if (source
->data
== 0)
241 assert (source
->data_target
!= 0);
243 /* Send data to target. */
244 WRITE (pipeline
->pipe_target
, &cmd
, sizeof (cmd_t
));
245 WRITE (pipeline
->pipe_target
, &(buffer
->data_target
), sizeof (void *));
246 WRITE (pipeline
->pipe_target
, &(source
->data_target
), sizeof (void *));
247 WRITE (pipeline
->pipe_target
, &(buffer
->size
), sizeof (uint64_t));
249 /* Receive data from target. */
250 READ (pipeline
->pipe_host
, &cmd
, sizeof (cmd_t
));
254 if (COIBufferCopy ((COIBUFFER
) buffer
, source_buffer
, 0, source_offset
,
255 length
, type
, 0, 0, 0) == COI_ERROR
)
259 /* Copy from intermediary buffer to dest. */
262 assert (dest
->data_target
!= 0);
264 /* Send data to target. */
265 WRITE (pipeline
->pipe_target
, &cmd
, sizeof (cmd_t
));
266 WRITE (pipeline
->pipe_target
, &(dest
->data_target
), sizeof (void *));
267 WRITE (pipeline
->pipe_target
, &(buffer
->data_target
), sizeof (void *));
268 WRITE (pipeline
->pipe_target
, &(buffer
->size
), sizeof (uint64_t));
270 /* Receive data from target. */
271 READ (pipeline
->pipe_host
, &cmd
, sizeof (cmd_t
));
275 if (COIBufferCopy (dest_buffer
, (COIBUFFER
) buffer
, dest_offset
,
276 0, length
, type
, 0, 0, 0) == COI_ERROR
)
280 /* Unmap on target and destroy intermediary buffer. */
281 if (COIBufferDestroy ((COIBUFFER
) buffer
) == COI_ERROR
)
285 /* Unmap buffers if needed. */
286 if (dest
->type
== BUFFER_NORMAL
)
287 if (COIBufferUnmap ((COIMAPINSTANCE
) dest
, 0, 0, 0) == COI_ERROR
)
289 if (source
->type
== BUFFER_NORMAL
)
290 if (COIBufferUnmap ((COIMAPINSTANCE
) source
, 0, 0, 0) == COI_ERROR
)
293 /* Finish critical section. */
294 if (pthread_mutex_unlock (&mutex
) != 0)
295 COIERROR ("Cannot unlock mutex.");
302 SYMBOL_VERSION (COIBufferCreate
, 1) (uint64_t size
,
303 COI_BUFFER_TYPE type
,
305 const void *init_data
,
306 uint32_t processes_num
,
307 const COIPROCESS
*processes
,
310 COITRACE ("COIBufferCreate");
313 cmd_t cmd
= CMD_BUFFER_MAP
;
315 const int ullong_max_len
= 20;
317 unsigned long long i
;
322 /* Features of liboffload. */
323 assert (type
== COI_BUFFER_NORMAL
);
324 assert ((flags
& COI_SINK_MEMORY
) == 0);
325 assert ((flags
& COI_SAME_ADDRESS_SINKS
) == 0);
326 assert ((flags
& COI_SAME_ADDRESS_SINKS_AND_SOURCE
) == 0);
327 assert (init_data
== 0);
328 assert (processes_num
== 1);
330 /* Create shared memory with an unique name. */
331 MALLOC (char *, shm_name
, strlen (SHM_NAME
) + ullong_max_len
+ 1);
332 for (i
= 0; i
>= 0; i
++)
334 sprintf (shm_name
, SHM_NAME
"%lu", i
);
335 shm_fd
= shm_open (shm_name
, O_CLOEXEC
| O_CREAT
| O_EXCL
| O_RDWR
,
340 if (ftruncate (shm_fd
, size
) < 0)
341 COIERROR ("Cannot truncate shared memory file.");
344 MALLOC (Buffer
*, buf
, sizeof (Buffer
));
347 buf
->process
= (Process
*) processes
[0];
349 buf
->type
= BUFFER_NORMAL
;
350 STRDUP (buf
->name
, shm_name
);
352 /* Map buffer on target. */
353 len
= strlen (buf
->name
) + 1;
354 pipeline
= buf
->process
->pipeline
;
356 /* Start critical section. */
357 if (pthread_mutex_lock (&mutex
) != 0)
358 COIERROR ("Cannot lock mutex.");
360 /* Send data to target. */
361 WRITE (pipeline
->pipe_target
, &cmd
, sizeof (cmd_t
));
362 WRITE (pipeline
->pipe_target
, &len
, sizeof (size_t));
363 WRITE (pipeline
->pipe_target
, buf
->name
, len
);
364 WRITE (pipeline
->pipe_target
, &(buf
->size
), sizeof (uint64_t));
366 /* Receive data from target. */
367 READ (pipeline
->pipe_host
, &(buf
->fd_target
), sizeof (int));
368 READ (pipeline
->pipe_host
, &(buf
->data_target
), sizeof (void *));
370 /* Finish critical section. */
371 if (pthread_mutex_unlock (&mutex
) != 0)
372 COIERROR ("Cannot unlock mutex.");
374 /* Prepare output arguments. */
375 *buffer
= (COIBUFFER
) buf
;
385 SYMBOL_VERSION (COIBufferCreateFromMemory
, 1) (uint64_t size
,
386 COI_BUFFER_TYPE type
,
389 uint32_t processes_num
,
390 const COIPROCESS
*processes
,
393 COITRACE ("COIBufferCreateFromMemory");
397 /* Features of liboffload. */
398 assert (type
== COI_BUFFER_NORMAL
);
399 assert ((flags
& COI_SAME_ADDRESS_SINKS
) == 0);
400 assert ((flags
& COI_SAME_ADDRESS_SINKS_AND_SOURCE
) == 0);
401 assert (processes_num
== 1);
404 MALLOC (Buffer
*, buf
, sizeof (Buffer
));
405 buf
->data
= (flags
& COI_SINK_MEMORY
) == 0 ? memory
: 0;
406 buf
->data_target
= (flags
& COI_SINK_MEMORY
) != 0 ? memory
: 0;
407 buf
->process
= (Process
*) processes
[0];
409 buf
->type
= BUFFER_MEMORY
;
411 /* Prepare output argument. */
412 *buffer
= (COIBUFFER
) buf
;
419 SYMBOL_VERSION (COIBufferDestroy
, 1) (COIBUFFER buffer
)
421 COITRACE ("COIBufferDestroy");
423 cmd_t cmd
= CMD_BUFFER_UNMAP
;
425 /* Convert input arguments. */
426 Buffer
*buf
= (Buffer
*) buffer
;
427 Pipeline
*pipeline
= buf
->process
->pipeline
;
429 /* Unmap buffer on host. */
430 if (buf
->data
!= 0 && buf
->type
== BUFFER_NORMAL
)
431 if (COIBufferUnmap ((COIMAPINSTANCE
) buffer
, 0, 0, 0) == COI_ERROR
)
434 /* Unmap buffer on target. */
435 if (buf
->data_target
!= 0)
437 /* Start critical section. */
438 if (pthread_mutex_lock (&mutex
) != 0)
439 COIERROR ("Cannot lock mutex.");
441 /* Send data to target. */
442 WRITE (pipeline
->pipe_target
, &cmd
, sizeof (cmd_t
));
443 WRITE (pipeline
->pipe_target
, &(buf
->fd_target
), sizeof (int));
444 WRITE (pipeline
->pipe_target
, &(buf
->data_target
), sizeof (void *));
445 WRITE (pipeline
->pipe_target
, &(buf
->size
), sizeof (uint64_t));
447 /* Receive data from target. */
448 READ (pipeline
->pipe_host
, &cmd
, sizeof (cmd_t
));
450 /* Finish critical section. */
451 if (pthread_mutex_unlock (&mutex
) != 0)
452 COIERROR ("Cannot unlock mutex.");
455 /* Unlink shared memory. */
456 if (buf
->type
== BUFFER_NORMAL
)
458 if (close (buf
->fd
) < 0)
459 COIERROR ("Cannot close shared memory file.");
460 if (shm_unlink (buf
->name
) < 0)
461 COIERROR ("Cannot unlink shared memory.");
473 SYMBOL_VERSION (COIBufferGetSinkAddress
, 1) (COIBUFFER buffer
,
476 COITRACE ("COIBufferGetSinkAddress");
478 /* Convert input arguments. */
479 Buffer
*buf
= (Buffer
*) buffer
;
481 /* Here should come BUFFER_NORMAL buffer. */
482 assert (buf
->type
== BUFFER_NORMAL
);
484 /* Prepare output argument. */
485 *data
= (uint64_t) buf
->data_target
;
492 SYMBOL_VERSION (COIBufferMap
, 1) (COIBUFFER buffer
,
495 COI_MAP_TYPE type
, // Ignored
496 uint32_t dependencies_num
, // Ignored
497 const COIEVENT
*dependencies
, // Ignored
498 COIEVENT
*completion
, // Ignored
499 COIMAPINSTANCE
*map_instance
,
502 COITRACE ("COIBufferMap");
504 /* Features of liboffload. */
505 assert (offset
== 0);
507 /* Convert input arguments. */
508 Buffer
*buf
= (Buffer
*) buffer
;
510 /* Only BUFFER_NORMAL buffers should come here. */
511 assert (buf
->type
== BUFFER_NORMAL
);
513 /* Map shared memory. */
514 buf
->data
= mmap (NULL
, buf
->size
, PROT_READ
| PROT_WRITE
,
515 MAP_SHARED
, buf
->fd
, 0);
516 if (buf
->data
== NULL
)
517 COIERROR ("Cannot map shared memory.");
519 /* Prepare output arguments. */
520 if (map_instance
!= 0)
521 *map_instance
= (COIMAPINSTANCE
) buf
;
530 SYMBOL_VERSION (COIBufferRead
, 1) (COIBUFFER buffer
,
535 uint32_t dependencies_num
, // Ignored
536 const COIEVENT
*dependencies
, // Ignored
537 COIEVENT
*completion
) // Ignored
539 COITRACE ("COIBufferRead");
541 /* Convert input arguments. */
542 Buffer
*buf
= (Buffer
*) buffer
;
544 /* Features of liboffload. */
545 assert (type
== COI_COPY_UNSPECIFIED
);
547 /* Start critical section. */
548 if (pthread_mutex_lock (&mutex
) != 0)
549 COIERROR ("Cannot lock mutex.");
551 /* Map buffers if needed. */
552 if (buf
->data
== 0 && buf
->type
== BUFFER_NORMAL
)
553 if (COIBufferMap (buffer
, 0, buf
->size
, (COI_MAP_TYPE
) 0,
554 0, 0, 0, 0, 0) == COI_ERROR
)
558 memcpy (data
, (void *) ((uintptr_t) buf
->data
+offset
), length
);
560 /* Unmap buffers if needed. */
561 if (buf
->type
== BUFFER_NORMAL
)
562 if (COIBufferUnmap ((COIMAPINSTANCE
) buf
, 0, 0, 0) == COI_ERROR
)
565 /* Finish critical section. */
566 if (pthread_mutex_unlock (&mutex
) != 0)
567 COIERROR ("Cannot unlock mutex.");
574 SYMBOL_VERSION (COIBufferSetState
, 1) (COIBUFFER buffer
,
576 COI_BUFFER_STATE state
,
577 COI_BUFFER_MOVE_FLAG flag
,
578 uint32_t dependencies_num
, // Ignored
579 const COIEVENT
*dependencies
, // Ignored
580 COIEVENT
*completion
) // Ignored
582 COITRACE ("COIBufferSetState");
584 /* Features of liboffload. */
585 assert (flag
== COI_BUFFER_NO_MOVE
);
587 /* Looks like we have nothing to do here. */
594 SYMBOL_VERSION (COIBufferUnmap
, 1) (COIMAPINSTANCE map_instance
,
595 uint32_t dependencies_num
, // Ignored
596 const COIEVENT
*dependencies
, // Ignored
597 COIEVENT
*completion
) // Ignored
599 COITRACE ("COIBufferUnmap");
601 /* Convert input arguments. */
602 Buffer
*buffer
= (Buffer
*) map_instance
;
604 /* Only BUFFER_NORMAL buffers should come here. */
605 assert (buffer
->type
== BUFFER_NORMAL
);
607 /* Unmap shared memory. */
608 if (munmap (buffer
->data
, buffer
->size
) < 0)
609 COIERROR ("Cannot unmap shared memory.");
618 SYMBOL_VERSION (COIBufferWrite
, 1) (COIBUFFER buffer
,
623 uint32_t dependencies_num
, // Ignored
624 const COIEVENT
*dependencies
, // Ignored
625 COIEVENT
*completion
) // Ignored
627 COITRACE ("COIBufferWrite");
629 /* Convert input arguments. */
630 Buffer
*buf
= (Buffer
*) buffer
;
632 /* Features of liboffload. */
633 assert (type
== COI_COPY_UNSPECIFIED
);
635 /* Start critical section. */
636 if (pthread_mutex_lock (&mutex
) != 0)
637 COIERROR ("Cannot lock mutex.");
639 /* Map buffers if needed. */
640 if (buf
->data
== 0 && buf
->type
== BUFFER_NORMAL
)
641 if (COIBufferMap (buffer
, 0, buf
->size
, (COI_MAP_TYPE
) 0,
642 0, 0, 0, 0, 0) == COI_ERROR
)
646 memcpy ((void *) ((uintptr_t) buf
->data
+offset
), data
, length
);
648 /* Unmap buffers if needed. */
649 if (buf
->type
== BUFFER_NORMAL
)
650 if (COIBufferUnmap ((COIMAPINSTANCE
) buf
, 0, 0, 0) == COI_ERROR
)
653 /* Finish critical section. */
654 if (pthread_mutex_unlock (&mutex
) != 0)
655 COIERROR ("Cannot unlock mutex.");
662 SYMBOL_VERSION (COIEngineGetCount
, 1) (COI_ISA_TYPE isa
,
665 COITRACE ("COIEngineGetCount");
667 /* Features of liboffload. */
668 assert (isa
== COI_ISA_KNC
);
670 /* Prepare output arguments. */
671 *count
= knc_engines_num
;
678 SYMBOL_VERSION (COIEngineGetHandle
, 1) (COI_ISA_TYPE isa
,
682 COITRACE ("COIEngineGetHandle");
686 /* Features of liboffload. */
687 assert (isa
== COI_ISA_KNC
);
689 /* Check engine index. */
690 if (index
>= knc_engines_num
)
691 COIERROR ("Wrong engine index.");
693 /* Create engine handle. */
694 MALLOC (Engine
*, engine
, sizeof (Engine
));
696 engine
->index
= index
;
699 /* Prepare output argument. */
700 *handle
= (COIENGINE
) engine
;
707 SYMBOL_VERSION (COIEventWait
, 1) (uint16_t events_num
, // Ignored
708 const COIEVENT
*events
, // Ignored
709 int32_t timeout
, // Ignored
711 uint32_t *signaled_num
,
712 uint32_t *signaled_indices
)
714 COITRACE ("COIEventWait");
716 /* Features of liboffload. */
717 assert (wait_all
== 1);
718 assert (signaled_num
== 0);
719 assert (signaled_indices
== 0);
721 /* Looks like we have nothing to do here. */
728 SYMBOL_VERSION (COIPipelineCreate
, 1) (COIPROCESS process
,
730 uint32_t stack_size
, // Ignored
731 COIPIPELINE
*pipeline
)
733 COITRACE ("COIPipelineCreate");
735 /* Features of liboffload. */
738 /* Prepare output arguments. */
739 *pipeline
= (COIPIPELINE
) ((Process
*) process
)->pipeline
;
746 SYMBOL_VERSION (COIPipelineDestroy
, 1) (COIPIPELINE pipeline
)
748 COITRACE ("COIPipelineDestroy");
750 /* Do nothing here. Pipeline will be closed during COIProcessDestroy. */
757 SYMBOL_VERSION (COIPipelineRunFunction
, 1) (COIPIPELINE pipeline
,
758 COIFUNCTION function
,
759 uint32_t buffers_num
,
760 const COIBUFFER
*buffers
,
761 const COI_ACCESS_FLAGS
*access_flags
, // Ignored
762 uint32_t dependencies_num
, // Ignored
763 const COIEVENT
*dependencies
, // Ignored
764 const void *misc_data
,
765 uint16_t misc_data_len
,
767 uint16_t return_data_len
,
768 COIEVENT
*completion
) // Ignored
770 COITRACE ("COIPipelineRunFunction");
772 cmd_t cmd
= CMD_RUN_FUNCTION
;
778 /* Convert input arguments. */
779 Buffer
**bufs
= (Buffer
**) buffers
;
780 Function
*func
= (Function
*) function
;
781 Pipeline
*pipe
= (Pipeline
*) pipeline
;
783 /* Start critical section. */
784 if (pthread_mutex_lock (&mutex
) != 0)
785 COIERROR ("Cannot lock mutex.");
787 /* Send data to target. */
788 WRITE (pipe
->pipe_target
, &cmd
, sizeof (cmd_t
));
789 WRITE (pipe
->pipe_target
, &(func
->ptr
), sizeof (void *));
790 WRITE (pipe
->pipe_target
, &buffers_num
, sizeof (uint32_t));
791 for (i
= 0; i
< buffers_num
; i
++)
793 WRITE (pipe
->pipe_target
, &(bufs
[i
]->size
), sizeof (uint64_t));
794 WRITE (pipe
->pipe_target
, &(bufs
[i
]->data_target
), sizeof (void *));
796 WRITE (pipe
->pipe_target
, &misc_data_len
, sizeof (uint16_t));
797 if (misc_data_len
> 0)
798 WRITE (pipe
->pipe_target
, misc_data
, misc_data_len
);
799 WRITE (pipe
->pipe_target
, &return_data_len
, sizeof (uint16_t));
801 /* Receive data from target. In emulator we don't need any asynchronous data
802 transfer, so we wait for target process whether it has any data or not. */
803 ret_len
= read (pipe
->pipe_host
, return_data_len
> 0 ? return_data
: &cmd
,
804 return_data_len
> 0 ? return_data_len
: sizeof (cmd_t
));
806 return COI_PROCESS_DIED
;
807 else if (ret_len
!= (return_data_len
> 0 ? return_data_len
: sizeof (cmd_t
)))
808 COIERROR ("Cannot read from pipe.");
810 /* Finish critical section. */
811 if (pthread_mutex_unlock (&mutex
) != 0)
812 COIERROR ("Cannot unlock mutex.");
819 SYMBOL_VERSION (COIProcessCreateFromMemory
, 1) (COIENGINE engine
,
820 const char *bin_name
,
821 const void *bin_buffer
,
822 uint64_t bin_buffer_len
,
826 const char **additional_env
,
827 uint8_t proxy_active
, // Ignored
828 const char *proxyfs_root
, // Ignored
829 uint64_t buffer_space
, // Ignored
830 const char *lib_search_path
,
831 const char *file_of_origin
, // Ignored
832 uint64_t file_of_origin_offset
, // Ignored
835 COITRACE ("COIProcessCreateFromMemory");
837 const int run_max_args_num
= 128;
839 char *run_argv
[run_max_args_num
];
840 char *emul_run
= getenv (OFFLOAD_EMUL_RUN_ENV
);
841 char *env_name
, *tok
;
842 char *pipe_host_path
, *pipe_target_path
, *pipes_path
, *target_exe
;
845 int i
, j
, env_i
, env_num
;
846 int pipe_host
, pipe_target
;
847 const int uint_max_len
= 11;
852 /* Features of liboffload. */
856 /* Convert input arguments. */
857 Engine
*eng
= (Engine
*) engine
;
859 /* Create temporary directory for engine files. */
860 assert (eng
->dir
== NULL
);
861 STRDUP (eng
->dir
, ENGINE_PATH
);
862 if (mkdtemp (eng
->dir
) == NULL
)
863 COIERROR ("Cannot create temporary directory %s.", eng
->dir
);
865 /* Save path to engine directory for clean up on exit. */
867 tmp_dirs
= (char **) realloc (tmp_dirs
, tmp_dirs_num
* sizeof (char *));
869 COIERROR ("Cannot allocate memory.");
870 STRDUP (tmp_dirs
[tmp_dirs_num
- 1], eng
->dir
);
872 /* Create target executable file. */
873 MALLOC (char *, target_exe
, strlen (eng
->dir
) + strlen (bin_name
) + 2);
874 sprintf (target_exe
, "%s/%s", eng
->dir
, bin_name
);
875 fd
= open (target_exe
, O_CLOEXEC
| O_CREAT
| O_WRONLY
, S_IRUSR
| S_IWUSR
);
877 COIERROR ("Cannot create file %s.", target_exe
);
878 file
= fdopen (fd
, "wb");
880 COIERROR ("Cannot associate stream with file descriptor.");
881 if (fwrite (bin_buffer
, 1, bin_buffer_len
, file
) != bin_buffer_len
)
882 COIERROR ("Cannot write in file %s.", target_exe
);
883 if (fclose (file
) != 0)
884 COIERROR ("Cannot close file %s.", target_exe
);
886 /* Fix file permissions. */
887 if (chmod (target_exe
, S_IRWXU
) < 0)
888 COIERROR ("Cannot change permissions for file %s.", target_exe
);
890 /* Create directory for pipes to prevent names collision. */
891 MALLOC (char *, pipes_path
, strlen (PIPES_PATH
) + strlen (eng
->dir
) + 1);
892 sprintf (pipes_path
, "%s"PIPES_PATH
, eng
->dir
);
893 if (mkdir (pipes_path
, S_IRWXU
) < 0)
894 COIERROR ("Cannot create folder %s.", pipes_path
);
897 MALLOC (char *, pipe_host_path
,
898 strlen (PIPE_HOST_PATH
) + strlen (eng
->dir
) + 1);
899 MALLOC (char *, pipe_target_path
,
900 strlen (PIPE_TARGET_PATH
) + strlen (eng
->dir
) + 1);
901 if (pipe_target_path
== NULL
)
902 COIERROR ("Cannot allocate memory.");
903 sprintf (pipe_host_path
, "%s"PIPE_HOST_PATH
, eng
->dir
);
904 sprintf (pipe_target_path
, "%s"PIPE_TARGET_PATH
, eng
->dir
);
905 if (mkfifo (pipe_host_path
, S_IRUSR
| S_IWUSR
) < 0)
906 COIERROR ("Cannot create pipe %s.", pipe_host_path
);
907 if (mkfifo (pipe_target_path
, S_IRUSR
| S_IWUSR
) < 0)
908 COIERROR ("Cannot create pipe %s.", pipe_target_path
);
911 if (emul_run
== NULL
|| strcmp (emul_run
, "") == 0)
913 STRDUP (run_argv
[0], target_exe
);
914 run_argv
[1] = (char *) NULL
;
920 STRDUP (tmp
, emul_run
);
921 tok
= strtok_r (tmp
, " ", &ptr
);
924 if (i
>= run_max_args_num
)
925 COIERROR ("Run command has too many arguments.");
926 STRDUP (run_argv
[i
++], tok
);
927 tok
= strtok_r (NULL
, " ", &ptr
);
929 STRDUP (run_argv
[i
], target_exe
);
930 run_argv
[i
+1] = (char *) NULL
;
935 /* FIXME: take into account additional_env. */
936 assert (additional_env
== NULL
);
939 if (inherit_env
== true)
940 while (environ
[env_num
++]);
941 env_num
+= 4; // LD_LIBRARY_PATH, MIC_DIR, MIC_INDEX, NULL
943 MALLOC (char **, envp
, env_num
* sizeof (char *));
946 if (inherit_env
== true)
947 for (i
= 0; environ
[i
] != NULL
; i
++)
949 STRDUP (env_name
, environ
[i
]);
950 for (j
= 0; env_name
[j
] != '=' && env_name
[j
] != '\0'; j
++);
952 if (strcmp (env_name
, "LD_LIBRARY_PATH") != 0
953 && strcmp (env_name
, MIC_DIR_ENV
) != 0
954 && strcmp (env_name
, MIC_INDEX_ENV
) != 0)
955 STRDUP (envp
[env_i
++], environ
[i
]);
959 MALLOC (char *, envp
[env_i
], strlen (MIC_DIR_ENV
) + strlen (eng
->dir
) + 2);
960 sprintf (envp
[env_i
], "%s=%s", MIC_DIR_ENV
, eng
->dir
);
962 MALLOC (char *, envp
[env_i
+1], strlen (MIC_INDEX_ENV
) + uint_max_len
+ 1);
963 sprintf (envp
[env_i
+1], "%s=%u", MIC_INDEX_ENV
, eng
->index
);
965 MALLOC (char *, envp
[env_i
+2],
966 strlen ("LD_LIBRARY_PATH=") + strlen (lib_search_path
) + 1);
967 sprintf (envp
[env_i
+2], "LD_LIBRARY_PATH=%s", lib_search_path
);
969 envp
[env_i
+3] = (char *) NULL
;
971 /* Create target process. */
974 COIERROR ("Cannot create child process.");
978 /* Run target executable. */
979 if (execvpe (run_argv
[0], run_argv
, envp
) == -1)
980 COIERROR ("Cannot execute file %s.", target_exe
);
984 pipe_host
= open (pipe_host_path
, O_CLOEXEC
| O_RDONLY
);
986 COIERROR ("Cannot open target-to-host pipe.");
987 pipe_target
= open (pipe_target_path
, O_CLOEXEC
| O_WRONLY
);
989 COIERROR ("Cannot open host-to-target pipe.");
991 /* Create pipeline handle. */
992 MALLOC (Pipeline
*, pipeline
, sizeof (Pipeline
));
993 pipeline
->pipe_host
= pipe_host
;
994 pipeline
->pipe_target
= pipe_target
;
996 /* Create process handle. */
997 MALLOC (Process
*, proc
, sizeof (Process
));
1000 proc
->functions
= 0;
1001 proc
->pipeline
= pipeline
;
1003 /* Prepare output arguments. */
1004 *process
= (COIPROCESS
) proc
;
1007 for (i
= 0; run_argv
[i
] != NULL
; i
++)
1009 for (i
= 0; envp
[i
] != NULL
; i
++)
1012 free (pipe_host_path
);
1013 free (pipe_target_path
);
1022 SYMBOL_VERSION (COIProcessDestroy
, 1) (COIPROCESS process
,
1023 int32_t wait_timeout
, // Ignored
1025 int8_t *proc_return
,
1028 COITRACE ("COIProcessDestroy");
1032 /* Convert input arguments. */
1033 Process
*proc
= (Process
*) process
;
1035 /* Close pipeline. */
1036 if (close (proc
->pipeline
->pipe_host
) < 0)
1037 COIERROR ("Cannot close target-to-host pipe.");
1038 if (close (proc
->pipeline
->pipe_target
) < 0)
1039 COIERROR ("Cannot close host-to-target pipe.");
1040 free (proc
->pipeline
);
1042 /* Shutdown target process by force. */
1044 kill (proc
->pid
, SIGTERM
);
1047 for (i
= 0; proc
->functions
[i
] != 0; i
++)
1049 free (proc
->functions
[i
]->name
);
1050 free (proc
->functions
[i
]);
1052 free (proc
->engine
->dir
);
1053 free (proc
->engine
);
1054 free (proc
->functions
);
1057 /* Prepare output arguments. */
1066 SYMBOL_VERSION (COIProcessGetFunctionHandles
, 1) (COIPROCESS process
,
1067 uint32_t functions_num
,
1068 const char **function_names
,
1069 COIFUNCTION
*function_handles
)
1071 COITRACE ("COIProcessGetFunctionHandles");
1073 cmd_t cmd
= CMD_GET_FUNCTION_HANDLE
;
1079 /* Convert input arguments. */
1080 Process
*proc
= (Process
*) process
;
1082 /* This function should be called once for the process. */
1083 assert (proc
->functions
== 0);
1085 /* Create array of function pointers. Last element is 0, what shows
1086 the end of the array. This array is used to free memory when process
1088 proc
->functions
= (Function
**) calloc (functions_num
+ 1,
1089 sizeof (Function
*));
1090 if (proc
->functions
== NULL
)
1091 COIERROR ("Cannot allocate memory.");
1093 /* Get handles for functions. */
1094 for (i
= 0; i
< functions_num
; i
++)
1096 MALLOC (Function
*, function
, sizeof (Function
));
1098 len
= strlen (function_names
[i
]) + 1;
1100 /* Start critical section. */
1101 if (pthread_mutex_lock (&mutex
) != 0)
1102 COIERROR ("Cannot lock mutex.");
1104 /* Send data to target. */
1105 WRITE (proc
->pipeline
->pipe_target
, &cmd
, sizeof (cmd_t
));
1106 WRITE (proc
->pipeline
->pipe_target
, &len
, sizeof (size_t));
1107 WRITE (proc
->pipeline
->pipe_target
, function_names
[i
], len
);
1109 /* Receive data from target. */
1110 READ (proc
->pipeline
->pipe_host
, &ptr
, sizeof (void *));
1112 /* Finish critical section. */
1113 if (pthread_mutex_unlock (&mutex
) != 0)
1114 COIERROR ("Cannot unlock mutex.");
1116 /* Prepare output arguments. */
1117 STRDUP (function
->name
, function_names
[i
]);
1118 if (function
->name
== NULL
)
1119 COIERROR ("Cannot allocate memory.");
1120 function
->ptr
= ptr
;
1121 function_handles
[i
] = (COIFUNCTION
) function
;
1123 /* Save function pointer. */
1124 proc
->functions
[i
] = function
;
1132 SYMBOL_VERSION (COIProcessLoadLibraryFromMemory
, 2) (COIPROCESS process
,
1133 const void *lib_buffer
,
1134 uint64_t lib_buffer_len
,
1135 const char *lib_name
,
1136 const char *lib_search_path
,
1137 const char *file_of_origin
, // Ignored
1138 uint64_t file_from_origin_offset
, // Ignored
1139 uint32_t flags
, // Ignored
1140 COILIBRARY
*library
) // Ignored
1142 COITRACE ("COIProcessLoadLibraryFromMemory");
1145 cmd_t cmd
= CMD_OPEN_LIBRARY
;
1150 /* Convert input arguments. */
1151 Process
*proc
= (Process
*) process
;
1153 /* Create target library file. */
1154 MALLOC (char *, lib_path
,
1155 strlen (proc
->engine
->dir
) + strlen (lib_name
) + 2);
1156 sprintf (lib_path
, "%s/%s", proc
->engine
->dir
, lib_name
);
1157 fd
= open (lib_path
, O_CLOEXEC
| O_CREAT
| O_WRONLY
, S_IRUSR
| S_IWUSR
);
1159 COIERROR ("Cannot create file %s.", lib_path
);
1160 file
= fdopen (fd
, "wb");
1162 COIERROR ("Cannot associate stream with file descriptor.");
1163 if (fwrite (lib_buffer
, 1, lib_buffer_len
, file
) != lib_buffer_len
)
1164 COIERROR ("Cannot write in file %s.", lib_path
);
1165 if (fclose (file
) != 0)
1166 COIERROR ("Cannot close file %s.", lib_path
);
1168 len
= strlen (lib_path
) + 1;
1170 /* Start critical section. */
1171 if (pthread_mutex_lock (&mutex
) != 0)
1172 COIERROR ("Cannot lock mutex.");
1174 /* Make target open library. */
1175 WRITE (proc
->pipeline
->pipe_target
, &cmd
, sizeof (cmd_t
));
1176 WRITE (proc
->pipeline
->pipe_target
, &len
, sizeof (size_t));
1177 WRITE (proc
->pipeline
->pipe_target
, lib_path
, len
);
1179 /* Finish critical section. */
1180 if (pthread_mutex_unlock (&mutex
) != 0)
1181 COIERROR ("Cannot unlock mutex.");
1191 SYMBOL_VERSION (COIProcessRegisterLibraries
, 1) (uint32_t libraries_num
,
1192 const void **libraries
,
1193 const uint64_t *library_sizes
,
1194 const char **files_of_origin
,
1195 const uint64_t *file_of_origin_offsets
)
1197 COITRACE ("COIProcessRegisterLibraries");
1199 /* Looks like we have nothing to do here. */
1206 SYMBOL_VERSION (COIPerfGetCycleFrequency
, 1) ()
1208 COITRACE ("COIPerfGetCycleFrequency");
1210 return (uint64_t) CYCLE_FREQUENCY
;