mirror of
https://github.com/autc04/Retro68.git
synced 2024-11-08 09:07:53 +00:00
402 lines
11 KiB
C++
402 lines
11 KiB
C++
/*
|
|
Copyright (c) 2014-2015 Intel Corporation. All Rights Reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
* Neither the name of Intel Corporation nor the names of its
|
|
contributors may be used to endorse or promote products derived
|
|
from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "coi_device.h"
|
|
|
|
#include "coi_version_asm.h"
|
|
|
|
#define CYCLE_FREQUENCY 1000000000
|
|
|
|
|
|
static uint32_t engine_index;
|
|
static char *engine_dir;
|
|
|
|
|
|
extern "C"
|
|
{
|
|
|
|
COIRESULT
|
|
SYMBOL_VERSION (COIBufferAddRef, 1) (void *ptr)
|
|
{
|
|
COITRACE ("COIBufferAddRef");
|
|
|
|
/* Looks like we have nothing to do here. */
|
|
|
|
return COI_SUCCESS;
|
|
}
|
|
|
|
|
|
COIRESULT
|
|
SYMBOL_VERSION (COIBufferReleaseRef, 1) (void *ptr)
|
|
{
|
|
COITRACE ("COIBufferReleaseRef");
|
|
|
|
/* Looks like we have nothing to do here. */
|
|
|
|
return COI_SUCCESS;
|
|
}
|
|
|
|
|
|
COIRESULT
|
|
SYMBOL_VERSION (COIEngineGetIndex, 1) (COI_ISA_TYPE *type,
|
|
uint32_t *index)
|
|
{
|
|
COITRACE ("COIEngineGetIndex");
|
|
|
|
/* type is not used in liboffloadmic. */
|
|
*index = engine_index;
|
|
|
|
return COI_SUCCESS;
|
|
}
|
|
|
|
|
|
COIRESULT
|
|
SYMBOL_VERSION (COIPipelineStartExecutingRunFunctions, 1) ()
|
|
{
|
|
COITRACE ("COIPipelineStartExecutingRunFunctions");
|
|
|
|
/* Looks like we have nothing to do here. */
|
|
|
|
return COI_SUCCESS;
|
|
}
|
|
|
|
|
|
/* The start routine for the COI pipeline thread. */
|
|
|
|
static void *
|
|
pipeline_thread_routine (void *in_pipeline_num)
|
|
{
|
|
uint32_t pipeline_num = *(uint32_t *) in_pipeline_num;
|
|
free (in_pipeline_num);
|
|
|
|
/* Open pipes. */
|
|
char *pipe_host2tgt_path, *pipe_tgt2host_path;
|
|
MALLOCN (char *, pipe_host2tgt_path,
|
|
strlen (engine_dir) + sizeof (PIPE_HOST2TGT_NAME "0000000000"));
|
|
MALLOCN (char *, pipe_tgt2host_path,
|
|
strlen (engine_dir) + sizeof (PIPE_TGT2HOST_NAME "0000000000"));
|
|
sprintf (pipe_host2tgt_path, "%s" PIPE_HOST2TGT_NAME "%010d", engine_dir,
|
|
pipeline_num);
|
|
sprintf (pipe_tgt2host_path, "%s" PIPE_TGT2HOST_NAME "%010d", engine_dir,
|
|
pipeline_num);
|
|
int pipe_host2tgt = open (pipe_host2tgt_path, O_CLOEXEC | O_RDONLY);
|
|
if (pipe_host2tgt < 0)
|
|
COIERRORN ("Cannot open host-to-target pipe.");
|
|
int pipe_tgt2host = open (pipe_tgt2host_path, O_CLOEXEC | O_WRONLY);
|
|
if (pipe_tgt2host < 0)
|
|
COIERRORN ("Cannot open target-to-host pipe.");
|
|
|
|
free (pipe_host2tgt_path);
|
|
free (pipe_tgt2host_path);
|
|
|
|
while (1)
|
|
{
|
|
/* Read and execute command. */
|
|
cmd_t cmd = CMD_PIPELINE_DESTROY;
|
|
int cmd_len = read (pipe_host2tgt, &cmd, sizeof (cmd_t));
|
|
if (cmd_len != sizeof (cmd_t) && cmd_len != 0)
|
|
COIERRORN ("Cannot read from pipe.");
|
|
|
|
if (cmd == CMD_PIPELINE_DESTROY)
|
|
break;
|
|
else if (cmd == CMD_PIPELINE_RUN_FUNCTION)
|
|
{
|
|
/* Receive data from host. */
|
|
void (*func) (uint32_t, void **, uint64_t *, void *, uint16_t, void *,
|
|
uint16_t);
|
|
uint32_t buffer_count;
|
|
READN (pipe_host2tgt, &func, sizeof (void *));
|
|
READN (pipe_host2tgt, &buffer_count, sizeof (uint32_t));
|
|
void **buffers;
|
|
uint64_t *buffers_len;
|
|
MALLOCN (void **, buffers, buffer_count * sizeof (void *));
|
|
MALLOCN (uint64_t *, buffers_len, buffer_count * sizeof (uint64_t));
|
|
for (uint32_t i = 0; i < buffer_count; i++)
|
|
{
|
|
READN (pipe_host2tgt, &buffers_len[i], sizeof (uint64_t));
|
|
READN (pipe_host2tgt, &buffers[i], sizeof (void *));
|
|
}
|
|
uint16_t misc_data_len;
|
|
READN (pipe_host2tgt, &misc_data_len, sizeof (uint16_t));
|
|
void *misc_data = NULL;
|
|
if (misc_data_len > 0)
|
|
{
|
|
MALLOCN (void *, misc_data, misc_data_len);
|
|
READN (pipe_host2tgt, misc_data, misc_data_len);
|
|
}
|
|
uint16_t return_data_len;
|
|
READN (pipe_host2tgt, &return_data_len, sizeof (uint16_t));
|
|
void *return_data;
|
|
if (return_data_len > 0)
|
|
MALLOCN (void *, return_data, return_data_len);
|
|
|
|
/* Run function. */
|
|
func (buffer_count, buffers, buffers_len, misc_data,
|
|
misc_data_len, return_data, return_data_len);
|
|
|
|
/* Send data to host if any or just send notification. */
|
|
WRITEN (pipe_tgt2host, return_data_len > 0 ? return_data : &cmd,
|
|
return_data_len > 0 ? return_data_len : sizeof (cmd_t));
|
|
|
|
/* Clean up. */
|
|
free (buffers);
|
|
free (buffers_len);
|
|
if (misc_data_len > 0)
|
|
free (misc_data);
|
|
if (return_data_len > 0)
|
|
free (return_data);
|
|
}
|
|
else
|
|
COIERRORN ("Unrecognizable command from host.");
|
|
}
|
|
|
|
/* Close pipes. */
|
|
if (close (pipe_host2tgt) < 0)
|
|
COIERRORN ("Cannot close host-to-target pipe.");
|
|
if (close (pipe_tgt2host) < 0)
|
|
COIERRORN ("Cannot close target-to-host pipe.");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
COIRESULT
|
|
SYMBOL_VERSION (COIProcessWaitForShutdown, 1) ()
|
|
{
|
|
COITRACE ("COIProcessWaitForShutdown");
|
|
|
|
engine_dir = getenv (MIC_DIR_ENV);
|
|
char *mic_index = getenv (MIC_INDEX_ENV);
|
|
assert (engine_dir != NULL && mic_index != NULL);
|
|
|
|
/* Get engine index. */
|
|
engine_index = atoi (mic_index);
|
|
|
|
/* Open main pipes. */
|
|
char *pipe_host2tgt_path, *pipe_tgt2host_path;
|
|
MALLOC (char *, pipe_host2tgt_path,
|
|
strlen (engine_dir) + sizeof (PIPE_HOST2TGT_NAME "mainpipe"));
|
|
MALLOC (char *, pipe_tgt2host_path,
|
|
strlen (engine_dir) + sizeof (PIPE_TGT2HOST_NAME "mainpipe"));
|
|
sprintf (pipe_host2tgt_path, "%s" PIPE_HOST2TGT_NAME "mainpipe", engine_dir);
|
|
sprintf (pipe_tgt2host_path, "%s" PIPE_TGT2HOST_NAME "mainpipe", engine_dir);
|
|
int pipe_host2tgt = open (pipe_host2tgt_path, O_CLOEXEC | O_RDONLY);
|
|
if (pipe_host2tgt < 0)
|
|
COIERROR ("Cannot open host-to-target main pipe.");
|
|
int pipe_tgt2host = open (pipe_tgt2host_path, O_CLOEXEC | O_WRONLY);
|
|
if (pipe_tgt2host < 0)
|
|
COIERROR ("Cannot open target-to-host main pipe.");
|
|
|
|
/* Clean up. */
|
|
free (pipe_host2tgt_path);
|
|
free (pipe_tgt2host_path);
|
|
|
|
/* Handler. */
|
|
while (1)
|
|
{
|
|
/* Read and execute command. */
|
|
cmd_t cmd = CMD_SHUTDOWN;
|
|
int cmd_len = read (pipe_host2tgt, &cmd, sizeof (cmd_t));
|
|
if (cmd_len != sizeof (cmd_t) && cmd_len != 0)
|
|
COIERROR ("Cannot read from main pipe.");
|
|
|
|
switch (cmd)
|
|
{
|
|
case CMD_BUFFER_COPY:
|
|
{
|
|
uint64_t len;
|
|
void *dest, *source;
|
|
|
|
/* Receive data from host. */
|
|
READ (pipe_host2tgt, &dest, sizeof (void *));
|
|
READ (pipe_host2tgt, &source, sizeof (void *));
|
|
READ (pipe_host2tgt, &len, sizeof (uint64_t));
|
|
|
|
/* Copy. */
|
|
memcpy (dest, source, len);
|
|
|
|
/* Notify host about completion. */
|
|
WRITE (pipe_tgt2host, &cmd, sizeof (cmd_t));
|
|
|
|
break;
|
|
}
|
|
case CMD_BUFFER_MAP:
|
|
{
|
|
char *name;
|
|
size_t len;
|
|
uint64_t buffer_len;
|
|
void *buffer;
|
|
|
|
/* Receive data from host. */
|
|
READ (pipe_host2tgt, &len, sizeof (size_t));
|
|
MALLOC (char *, name, len);
|
|
READ (pipe_host2tgt, name, len);
|
|
READ (pipe_host2tgt, &buffer_len, sizeof (uint64_t));
|
|
|
|
/* Open shared memory. */
|
|
int fd = shm_open (name, O_CLOEXEC | O_RDWR, S_IRUSR | S_IWUSR);
|
|
if (fd < 0)
|
|
COIERROR ("Cannot open shared memory.");
|
|
|
|
/* Map shared memory. */
|
|
buffer = mmap (NULL, buffer_len, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED, fd, 0);
|
|
if (buffer == NULL)
|
|
COIERROR ("Cannot map shared memory.");
|
|
|
|
/* Send data to host. */
|
|
WRITE (pipe_tgt2host, &fd, sizeof (int));
|
|
WRITE (pipe_tgt2host, &buffer, sizeof (void *));
|
|
|
|
/* Clean up. */
|
|
free (name);
|
|
|
|
break;
|
|
}
|
|
case CMD_BUFFER_UNMAP:
|
|
{
|
|
int fd;
|
|
uint64_t buffer_len;
|
|
void *buffer;
|
|
|
|
/* Receive data from host. */
|
|
READ (pipe_host2tgt, &fd, sizeof (int));
|
|
READ (pipe_host2tgt, &buffer, sizeof (void *));
|
|
READ (pipe_host2tgt, &buffer_len, sizeof (uint64_t));
|
|
|
|
/* Unmap buffer. */
|
|
if (munmap (buffer, buffer_len) < 0)
|
|
COIERROR ("Cannot unmap shared memory.");
|
|
|
|
/* Close shared memory. */
|
|
if (close (fd) < 0)
|
|
COIERROR ("Cannot close shared memory file.");
|
|
|
|
/* Notify host about completion. */
|
|
WRITE (pipe_tgt2host, &cmd, sizeof (cmd_t));
|
|
|
|
break;
|
|
}
|
|
case CMD_GET_FUNCTION_HANDLE:
|
|
{
|
|
char *name;
|
|
size_t len;
|
|
|
|
/* Receive data from host. */
|
|
READ (pipe_host2tgt, &len, sizeof (size_t));
|
|
MALLOC (char *, name, len);
|
|
READ (pipe_host2tgt, name, len);
|
|
|
|
/* Find function. */
|
|
void *ptr = dlsym (RTLD_DEFAULT, name);
|
|
if (ptr == NULL)
|
|
COIERROR ("Cannot find symbol %s.", name);
|
|
|
|
/* Send data to host. */
|
|
WRITE (pipe_tgt2host, &ptr, sizeof (void *));
|
|
|
|
/* Clean up. */
|
|
free (name);
|
|
|
|
break;
|
|
}
|
|
case CMD_OPEN_LIBRARY:
|
|
{
|
|
char *lib_path;
|
|
size_t len;
|
|
|
|
/* Receive data from host. */
|
|
READ (pipe_host2tgt, &len, sizeof (size_t));
|
|
MALLOC (char *, lib_path, len);
|
|
READ (pipe_host2tgt, lib_path, len);
|
|
|
|
/* Open library. */
|
|
void *handle = dlopen (lib_path, RTLD_LAZY | RTLD_GLOBAL);
|
|
if (handle == NULL)
|
|
COIERROR ("Cannot load %s: %s", lib_path, dlerror ());
|
|
|
|
/* Send data to host. */
|
|
WRITE (pipe_tgt2host, &handle, sizeof (void *));
|
|
|
|
/* Clean up. */
|
|
free (lib_path);
|
|
|
|
break;
|
|
}
|
|
case CMD_CLOSE_LIBRARY:
|
|
{
|
|
/* Receive data from host. */
|
|
void *handle;
|
|
READ (pipe_host2tgt, &handle, sizeof (void *));
|
|
|
|
dlclose (handle);
|
|
|
|
break;
|
|
}
|
|
case CMD_PIPELINE_CREATE:
|
|
{
|
|
/* Receive data from host. */
|
|
uint32_t *pipeline_num;
|
|
MALLOC (uint32_t *, pipeline_num, sizeof (uint32_t));
|
|
READ (pipe_host2tgt, pipeline_num, sizeof (*pipeline_num));
|
|
|
|
/* Create a new thread for the pipeline. */
|
|
pthread_t thread;
|
|
if (pthread_create (&thread, NULL, pipeline_thread_routine,
|
|
pipeline_num))
|
|
COIERROR ("Cannot create new thread.");
|
|
break;
|
|
}
|
|
case CMD_SHUTDOWN:
|
|
if (close (pipe_host2tgt) < 0)
|
|
COIERROR ("Cannot close host-to-target main pipe.");
|
|
if (close (pipe_tgt2host) < 0)
|
|
COIERROR ("Cannot close target-to-host main pipe.");
|
|
return COI_SUCCESS;
|
|
default:
|
|
COIERROR ("Unrecognizable command from host.");
|
|
}
|
|
}
|
|
|
|
return COI_ERROR;
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
SYMBOL_VERSION (COIPerfGetCycleFrequency, 1) ()
|
|
{
|
|
COITRACE ("COIPerfGetCycleFrequency");
|
|
|
|
return (uint64_t) CYCLE_FREQUENCY;
|
|
}
|
|
|
|
} // extern "C"
|
|
|