mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			402 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			402 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|     Copyright (c) 2014-2016 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"
 | |
| 
 |