* testsuite/26_numerics/headers/cmath/hypot.cc: XFAIL on AIX.
[official-gcc.git] / liboffloadmic / runtime / emulator / coi_device.cpp
blobc11214723e0fb7a18eb77ab9ca37903b366ce294
1 /*
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
6 are met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11 notice, this list of conditions and the following disclaimer in the
12 documentation and/or other materials provided with the distribution.
13 * Neither the name of Intel Corporation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "coi_device.h"
32 #include "coi_version_asm.h"
34 #define CYCLE_FREQUENCY 1000000000
37 static uint32_t engine_index;
38 static char *engine_dir;
41 extern "C"
44 COIRESULT
45 SYMBOL_VERSION (COIBufferAddRef, 1) (void *ptr)
47 COITRACE ("COIBufferAddRef");
49 /* Looks like we have nothing to do here. */
51 return COI_SUCCESS;
55 COIRESULT
56 SYMBOL_VERSION (COIBufferReleaseRef, 1) (void *ptr)
58 COITRACE ("COIBufferReleaseRef");
60 /* Looks like we have nothing to do here. */
62 return COI_SUCCESS;
66 COIRESULT
67 SYMBOL_VERSION (COIEngineGetIndex, 1) (COI_ISA_TYPE *type,
68 uint32_t *index)
70 COITRACE ("COIEngineGetIndex");
72 /* type is not used in liboffloadmic. */
73 *index = engine_index;
75 return COI_SUCCESS;
79 COIRESULT
80 SYMBOL_VERSION (COIPipelineStartExecutingRunFunctions, 1) ()
82 COITRACE ("COIPipelineStartExecutingRunFunctions");
84 /* Looks like we have nothing to do here. */
86 return COI_SUCCESS;
90 /* The start routine for the COI pipeline thread. */
92 static void *
93 pipeline_thread_routine (void *in_pipeline_num)
95 uint32_t pipeline_num = *(uint32_t *) in_pipeline_num;
96 free (in_pipeline_num);
98 /* Open pipes. */
99 char *pipe_host2tgt_path, *pipe_tgt2host_path;
100 MALLOCN (char *, pipe_host2tgt_path,
101 strlen (engine_dir) + sizeof (PIPE_HOST2TGT_NAME "0000000000"));
102 MALLOCN (char *, pipe_tgt2host_path,
103 strlen (engine_dir) + sizeof (PIPE_TGT2HOST_NAME "0000000000"));
104 sprintf (pipe_host2tgt_path, "%s" PIPE_HOST2TGT_NAME "%010d", engine_dir,
105 pipeline_num);
106 sprintf (pipe_tgt2host_path, "%s" PIPE_TGT2HOST_NAME "%010d", engine_dir,
107 pipeline_num);
108 int pipe_host2tgt = open (pipe_host2tgt_path, O_CLOEXEC | O_RDONLY);
109 if (pipe_host2tgt < 0)
110 COIERRORN ("Cannot open host-to-target pipe.");
111 int pipe_tgt2host = open (pipe_tgt2host_path, O_CLOEXEC | O_WRONLY);
112 if (pipe_tgt2host < 0)
113 COIERRORN ("Cannot open target-to-host pipe.");
115 free (pipe_host2tgt_path);
116 free (pipe_tgt2host_path);
118 while (1)
120 /* Read and execute command. */
121 cmd_t cmd = CMD_PIPELINE_DESTROY;
122 int cmd_len = read (pipe_host2tgt, &cmd, sizeof (cmd_t));
123 if (cmd_len != sizeof (cmd_t) && cmd_len != 0)
124 COIERRORN ("Cannot read from pipe.");
126 if (cmd == CMD_PIPELINE_DESTROY)
127 break;
128 else if (cmd == CMD_PIPELINE_RUN_FUNCTION)
130 /* Receive data from host. */
131 void (*func) (uint32_t, void **, uint64_t *, void *, uint16_t, void *,
132 uint16_t);
133 uint32_t buffer_count;
134 READN (pipe_host2tgt, &func, sizeof (void *));
135 READN (pipe_host2tgt, &buffer_count, sizeof (uint32_t));
136 void **buffers;
137 uint64_t *buffers_len;
138 MALLOCN (void **, buffers, buffer_count * sizeof (void *));
139 MALLOCN (uint64_t *, buffers_len, buffer_count * sizeof (uint64_t));
140 for (uint32_t i = 0; i < buffer_count; i++)
142 READN (pipe_host2tgt, &buffers_len[i], sizeof (uint64_t));
143 READN (pipe_host2tgt, &buffers[i], sizeof (void *));
145 uint16_t misc_data_len;
146 READN (pipe_host2tgt, &misc_data_len, sizeof (uint16_t));
147 void *misc_data = NULL;
148 if (misc_data_len > 0)
150 MALLOCN (void *, misc_data, misc_data_len);
151 READN (pipe_host2tgt, misc_data, misc_data_len);
153 uint16_t return_data_len;
154 READN (pipe_host2tgt, &return_data_len, sizeof (uint16_t));
155 void *return_data;
156 if (return_data_len > 0)
157 MALLOCN (void *, return_data, return_data_len);
159 /* Run function. */
160 func (buffer_count, buffers, buffers_len, misc_data,
161 misc_data_len, return_data, return_data_len);
163 /* Send data to host if any or just send notification. */
164 WRITEN (pipe_tgt2host, return_data_len > 0 ? return_data : &cmd,
165 return_data_len > 0 ? return_data_len : sizeof (cmd_t));
167 /* Clean up. */
168 free (buffers);
169 free (buffers_len);
170 if (misc_data_len > 0)
171 free (misc_data);
172 if (return_data_len > 0)
173 free (return_data);
175 else
176 COIERRORN ("Unrecognizable command from host.");
179 /* Close pipes. */
180 if (close (pipe_host2tgt) < 0)
181 COIERRORN ("Cannot close host-to-target pipe.");
182 if (close (pipe_tgt2host) < 0)
183 COIERRORN ("Cannot close target-to-host pipe.");
185 return NULL;
189 COIRESULT
190 SYMBOL_VERSION (COIProcessWaitForShutdown, 1) ()
192 COITRACE ("COIProcessWaitForShutdown");
194 engine_dir = getenv (MIC_DIR_ENV);
195 char *mic_index = getenv (MIC_INDEX_ENV);
196 assert (engine_dir != NULL && mic_index != NULL);
198 /* Get engine index. */
199 engine_index = atoi (mic_index);
201 /* Open main pipes. */
202 char *pipe_host2tgt_path, *pipe_tgt2host_path;
203 MALLOC (char *, pipe_host2tgt_path,
204 strlen (engine_dir) + sizeof (PIPE_HOST2TGT_NAME "mainpipe"));
205 MALLOC (char *, pipe_tgt2host_path,
206 strlen (engine_dir) + sizeof (PIPE_TGT2HOST_NAME "mainpipe"));
207 sprintf (pipe_host2tgt_path, "%s" PIPE_HOST2TGT_NAME "mainpipe", engine_dir);
208 sprintf (pipe_tgt2host_path, "%s" PIPE_TGT2HOST_NAME "mainpipe", engine_dir);
209 int pipe_host2tgt = open (pipe_host2tgt_path, O_CLOEXEC | O_RDONLY);
210 if (pipe_host2tgt < 0)
211 COIERROR ("Cannot open host-to-target main pipe.");
212 int pipe_tgt2host = open (pipe_tgt2host_path, O_CLOEXEC | O_WRONLY);
213 if (pipe_tgt2host < 0)
214 COIERROR ("Cannot open target-to-host main pipe.");
216 /* Clean up. */
217 free (pipe_host2tgt_path);
218 free (pipe_tgt2host_path);
220 /* Handler. */
221 while (1)
223 /* Read and execute command. */
224 cmd_t cmd = CMD_SHUTDOWN;
225 int cmd_len = read (pipe_host2tgt, &cmd, sizeof (cmd_t));
226 if (cmd_len != sizeof (cmd_t) && cmd_len != 0)
227 COIERROR ("Cannot read from main pipe.");
229 switch (cmd)
231 case CMD_BUFFER_COPY:
233 uint64_t len;
234 void *dest, *source;
236 /* Receive data from host. */
237 READ (pipe_host2tgt, &dest, sizeof (void *));
238 READ (pipe_host2tgt, &source, sizeof (void *));
239 READ (pipe_host2tgt, &len, sizeof (uint64_t));
241 /* Copy. */
242 memcpy (dest, source, len);
244 /* Notify host about completion. */
245 WRITE (pipe_tgt2host, &cmd, sizeof (cmd_t));
247 break;
249 case CMD_BUFFER_MAP:
251 char *name;
252 size_t len;
253 uint64_t buffer_len;
254 void *buffer;
256 /* Receive data from host. */
257 READ (pipe_host2tgt, &len, sizeof (size_t));
258 MALLOC (char *, name, len);
259 READ (pipe_host2tgt, name, len);
260 READ (pipe_host2tgt, &buffer_len, sizeof (uint64_t));
262 /* Open shared memory. */
263 int fd = shm_open (name, O_CLOEXEC | O_RDWR, S_IRUSR | S_IWUSR);
264 if (fd < 0)
265 COIERROR ("Cannot open shared memory.");
267 /* Map shared memory. */
268 buffer = mmap (NULL, buffer_len, PROT_READ | PROT_WRITE,
269 MAP_SHARED, fd, 0);
270 if (buffer == NULL)
271 COIERROR ("Cannot map shared memory.");
273 /* Send data to host. */
274 WRITE (pipe_tgt2host, &fd, sizeof (int));
275 WRITE (pipe_tgt2host, &buffer, sizeof (void *));
277 /* Clean up. */
278 free (name);
280 break;
282 case CMD_BUFFER_UNMAP:
284 int fd;
285 uint64_t buffer_len;
286 void *buffer;
288 /* Receive data from host. */
289 READ (pipe_host2tgt, &fd, sizeof (int));
290 READ (pipe_host2tgt, &buffer, sizeof (void *));
291 READ (pipe_host2tgt, &buffer_len, sizeof (uint64_t));
293 /* Unmap buffer. */
294 if (munmap (buffer, buffer_len) < 0)
295 COIERROR ("Cannot unmap shared memory.");
297 /* Close shared memory. */
298 if (close (fd) < 0)
299 COIERROR ("Cannot close shared memory file.");
301 /* Notify host about completion. */
302 WRITE (pipe_tgt2host, &cmd, sizeof (cmd_t));
304 break;
306 case CMD_GET_FUNCTION_HANDLE:
308 char *name;
309 size_t len;
311 /* Receive data from host. */
312 READ (pipe_host2tgt, &len, sizeof (size_t));
313 MALLOC (char *, name, len);
314 READ (pipe_host2tgt, name, len);
316 /* Find function. */
317 void *ptr = dlsym (RTLD_DEFAULT, name);
318 if (ptr == NULL)
319 COIERROR ("Cannot find symbol %s.", name);
321 /* Send data to host. */
322 WRITE (pipe_tgt2host, &ptr, sizeof (void *));
324 /* Clean up. */
325 free (name);
327 break;
329 case CMD_OPEN_LIBRARY:
331 char *lib_path;
332 size_t len;
334 /* Receive data from host. */
335 READ (pipe_host2tgt, &len, sizeof (size_t));
336 MALLOC (char *, lib_path, len);
337 READ (pipe_host2tgt, lib_path, len);
339 /* Open library. */
340 void *handle = dlopen (lib_path, RTLD_LAZY | RTLD_GLOBAL);
341 if (handle == NULL)
342 COIERROR ("Cannot load %s: %s", lib_path, dlerror ());
344 /* Send data to host. */
345 WRITE (pipe_tgt2host, &handle, sizeof (void *));
347 /* Clean up. */
348 free (lib_path);
350 break;
352 case CMD_CLOSE_LIBRARY:
354 /* Receive data from host. */
355 void *handle;
356 READ (pipe_host2tgt, &handle, sizeof (void *));
358 dlclose (handle);
360 break;
362 case CMD_PIPELINE_CREATE:
364 /* Receive data from host. */
365 uint32_t *pipeline_num;
366 MALLOC (uint32_t *, pipeline_num, sizeof (uint32_t));
367 READ (pipe_host2tgt, pipeline_num, sizeof (*pipeline_num));
369 /* Create a new thread for the pipeline. */
370 pthread_t thread;
371 if (pthread_create (&thread, NULL, pipeline_thread_routine,
372 pipeline_num))
373 COIERROR ("Cannot create new thread.");
374 break;
376 case CMD_SHUTDOWN:
377 if (close (pipe_host2tgt) < 0)
378 COIERROR ("Cannot close host-to-target main pipe.");
379 if (close (pipe_tgt2host) < 0)
380 COIERROR ("Cannot close target-to-host main pipe.");
381 return COI_SUCCESS;
382 default:
383 COIERROR ("Unrecognizable command from host.");
387 return COI_ERROR;
392 uint64_t
393 SYMBOL_VERSION (COIPerfGetCycleFrequency, 1) ()
395 COITRACE ("COIPerfGetCycleFrequency");
397 return (uint64_t) CYCLE_FREQUENCY;
400 } // extern "C"