]>
Commit | Line | Data |
---|---|---|
5f520819 | 1 | /* |
df26a50d | 2 | Copyright (c) 2014-2016 Intel Corporation. All Rights Reserved. |
5f520819 KY |
3 | |
4 | Redistribution and use in source and binary forms, with or without | |
5 | modification, are permitted provided that the following conditions | |
6 | are met: | |
7 | ||
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. | |
16 | ||
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. | |
28 | */ | |
29 | ||
30 | #include "coi_device.h" | |
31 | ||
32 | #include "coi_version_asm.h" | |
33 | ||
34 | #define CYCLE_FREQUENCY 1000000000 | |
35 | ||
36 | ||
37 | static uint32_t engine_index; | |
44799f87 | 38 | static char *engine_dir; |
5f520819 KY |
39 | |
40 | ||
41 | extern "C" | |
42 | { | |
43 | ||
44 | COIRESULT | |
45 | SYMBOL_VERSION (COIBufferAddRef, 1) (void *ptr) | |
46 | { | |
47 | COITRACE ("COIBufferAddRef"); | |
48 | ||
49 | /* Looks like we have nothing to do here. */ | |
50 | ||
51 | return COI_SUCCESS; | |
52 | } | |
53 | ||
54 | ||
55 | COIRESULT | |
56 | SYMBOL_VERSION (COIBufferReleaseRef, 1) (void *ptr) | |
57 | { | |
58 | COITRACE ("COIBufferReleaseRef"); | |
59 | ||
60 | /* Looks like we have nothing to do here. */ | |
61 | ||
62 | return COI_SUCCESS; | |
63 | } | |
64 | ||
65 | ||
66 | COIRESULT | |
67 | SYMBOL_VERSION (COIEngineGetIndex, 1) (COI_ISA_TYPE *type, | |
68 | uint32_t *index) | |
69 | { | |
70 | COITRACE ("COIEngineGetIndex"); | |
71 | ||
44799f87 | 72 | /* type is not used in liboffloadmic. */ |
5f520819 KY |
73 | *index = engine_index; |
74 | ||
75 | return COI_SUCCESS; | |
76 | } | |
77 | ||
78 | ||
79 | COIRESULT | |
80 | SYMBOL_VERSION (COIPipelineStartExecutingRunFunctions, 1) () | |
81 | { | |
82 | COITRACE ("COIPipelineStartExecutingRunFunctions"); | |
83 | ||
84 | /* Looks like we have nothing to do here. */ | |
85 | ||
86 | return COI_SUCCESS; | |
87 | } | |
88 | ||
89 | ||
44799f87 IV |
90 | /* The start routine for the COI pipeline thread. */ |
91 | ||
92 | static void * | |
93 | pipeline_thread_routine (void *in_pipeline_num) | |
94 | { | |
95 | uint32_t pipeline_num = *(uint32_t *) in_pipeline_num; | |
96 | free (in_pipeline_num); | |
97 | ||
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."); | |
114 | ||
115 | free (pipe_host2tgt_path); | |
116 | free (pipe_tgt2host_path); | |
117 | ||
118 | while (1) | |
119 | { | |
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."); | |
125 | ||
126 | if (cmd == CMD_PIPELINE_DESTROY) | |
127 | break; | |
128 | else if (cmd == CMD_PIPELINE_RUN_FUNCTION) | |
129 | { | |
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++) | |
141 | { | |
142 | READN (pipe_host2tgt, &buffers_len[i], sizeof (uint64_t)); | |
143 | READN (pipe_host2tgt, &buffers[i], sizeof (void *)); | |
144 | } | |
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) | |
149 | { | |
150 | MALLOCN (void *, misc_data, misc_data_len); | |
151 | READN (pipe_host2tgt, misc_data, misc_data_len); | |
152 | } | |
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); | |
158 | ||
159 | /* Run function. */ | |
160 | func (buffer_count, buffers, buffers_len, misc_data, | |
161 | misc_data_len, return_data, return_data_len); | |
162 | ||
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)); | |
166 | ||
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); | |
174 | } | |
175 | else | |
176 | COIERRORN ("Unrecognizable command from host."); | |
177 | } | |
178 | ||
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."); | |
184 | ||
185 | return NULL; | |
186 | } | |
187 | ||
188 | ||
5f520819 KY |
189 | COIRESULT |
190 | SYMBOL_VERSION (COIProcessWaitForShutdown, 1) () | |
191 | { | |
192 | COITRACE ("COIProcessWaitForShutdown"); | |
193 | ||
44799f87 | 194 | engine_dir = getenv (MIC_DIR_ENV); |
5f520819 | 195 | char *mic_index = getenv (MIC_INDEX_ENV); |
44799f87 | 196 | assert (engine_dir != NULL && mic_index != NULL); |
5f520819 KY |
197 | |
198 | /* Get engine index. */ | |
199 | engine_index = atoi (mic_index); | |
200 | ||
44799f87 IV |
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."); | |
5f520819 KY |
215 | |
216 | /* Clean up. */ | |
44799f87 IV |
217 | free (pipe_host2tgt_path); |
218 | free (pipe_tgt2host_path); | |
5f520819 KY |
219 | |
220 | /* Handler. */ | |
221 | while (1) | |
222 | { | |
223 | /* Read and execute command. */ | |
44799f87 IV |
224 | cmd_t cmd = CMD_SHUTDOWN; |
225 | int cmd_len = read (pipe_host2tgt, &cmd, sizeof (cmd_t)); | |
5f520819 | 226 | if (cmd_len != sizeof (cmd_t) && cmd_len != 0) |
44799f87 | 227 | COIERROR ("Cannot read from main pipe."); |
5f520819 KY |
228 | |
229 | switch (cmd) | |
230 | { | |
231 | case CMD_BUFFER_COPY: | |
232 | { | |
233 | uint64_t len; | |
234 | void *dest, *source; | |
235 | ||
236 | /* Receive data from host. */ | |
44799f87 IV |
237 | READ (pipe_host2tgt, &dest, sizeof (void *)); |
238 | READ (pipe_host2tgt, &source, sizeof (void *)); | |
239 | READ (pipe_host2tgt, &len, sizeof (uint64_t)); | |
5f520819 KY |
240 | |
241 | /* Copy. */ | |
242 | memcpy (dest, source, len); | |
243 | ||
244 | /* Notify host about completion. */ | |
44799f87 | 245 | WRITE (pipe_tgt2host, &cmd, sizeof (cmd_t)); |
5f520819 KY |
246 | |
247 | break; | |
248 | } | |
249 | case CMD_BUFFER_MAP: | |
250 | { | |
251 | char *name; | |
5f520819 KY |
252 | size_t len; |
253 | uint64_t buffer_len; | |
254 | void *buffer; | |
255 | ||
256 | /* Receive data from host. */ | |
44799f87 | 257 | READ (pipe_host2tgt, &len, sizeof (size_t)); |
5f520819 | 258 | MALLOC (char *, name, len); |
44799f87 IV |
259 | READ (pipe_host2tgt, name, len); |
260 | READ (pipe_host2tgt, &buffer_len, sizeof (uint64_t)); | |
5f520819 KY |
261 | |
262 | /* Open shared memory. */ | |
44799f87 | 263 | int fd = shm_open (name, O_CLOEXEC | O_RDWR, S_IRUSR | S_IWUSR); |
5f520819 KY |
264 | if (fd < 0) |
265 | COIERROR ("Cannot open shared memory."); | |
266 | ||
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."); | |
272 | ||
273 | /* Send data to host. */ | |
44799f87 IV |
274 | WRITE (pipe_tgt2host, &fd, sizeof (int)); |
275 | WRITE (pipe_tgt2host, &buffer, sizeof (void *)); | |
5f520819 KY |
276 | |
277 | /* Clean up. */ | |
278 | free (name); | |
279 | ||
280 | break; | |
281 | } | |
282 | case CMD_BUFFER_UNMAP: | |
283 | { | |
284 | int fd; | |
285 | uint64_t buffer_len; | |
286 | void *buffer; | |
287 | ||
288 | /* Receive data from host. */ | |
44799f87 IV |
289 | READ (pipe_host2tgt, &fd, sizeof (int)); |
290 | READ (pipe_host2tgt, &buffer, sizeof (void *)); | |
291 | READ (pipe_host2tgt, &buffer_len, sizeof (uint64_t)); | |
5f520819 KY |
292 | |
293 | /* Unmap buffer. */ | |
294 | if (munmap (buffer, buffer_len) < 0) | |
295 | COIERROR ("Cannot unmap shared memory."); | |
296 | ||
297 | /* Close shared memory. */ | |
298 | if (close (fd) < 0) | |
299 | COIERROR ("Cannot close shared memory file."); | |
300 | ||
301 | /* Notify host about completion. */ | |
44799f87 | 302 | WRITE (pipe_tgt2host, &cmd, sizeof (cmd_t)); |
5f520819 KY |
303 | |
304 | break; | |
305 | } | |
306 | case CMD_GET_FUNCTION_HANDLE: | |
307 | { | |
308 | char *name; | |
309 | size_t len; | |
5f520819 KY |
310 | |
311 | /* Receive data from host. */ | |
44799f87 | 312 | READ (pipe_host2tgt, &len, sizeof (size_t)); |
5f520819 | 313 | MALLOC (char *, name, len); |
44799f87 | 314 | READ (pipe_host2tgt, name, len); |
5f520819 KY |
315 | |
316 | /* Find function. */ | |
44799f87 | 317 | void *ptr = dlsym (RTLD_DEFAULT, name); |
5f520819 KY |
318 | if (ptr == NULL) |
319 | COIERROR ("Cannot find symbol %s.", name); | |
320 | ||
321 | /* Send data to host. */ | |
44799f87 | 322 | WRITE (pipe_tgt2host, &ptr, sizeof (void *)); |
5f520819 KY |
323 | |
324 | /* Clean up. */ | |
325 | free (name); | |
326 | ||
327 | break; | |
328 | } | |
329 | case CMD_OPEN_LIBRARY: | |
330 | { | |
331 | char *lib_path; | |
332 | size_t len; | |
333 | ||
334 | /* Receive data from host. */ | |
44799f87 | 335 | READ (pipe_host2tgt, &len, sizeof (size_t)); |
5f520819 | 336 | MALLOC (char *, lib_path, len); |
44799f87 | 337 | READ (pipe_host2tgt, lib_path, len); |
5f520819 KY |
338 | |
339 | /* Open library. */ | |
44799f87 | 340 | void *handle = dlopen (lib_path, RTLD_LAZY | RTLD_GLOBAL); |
2eab9666 | 341 | if (handle == NULL) |
5f520819 KY |
342 | COIERROR ("Cannot load %s: %s", lib_path, dlerror ()); |
343 | ||
2eab9666 | 344 | /* Send data to host. */ |
44799f87 | 345 | WRITE (pipe_tgt2host, &handle, sizeof (void *)); |
2eab9666 | 346 | |
5f520819 KY |
347 | /* Clean up. */ |
348 | free (lib_path); | |
349 | ||
2eab9666 IV |
350 | break; |
351 | } | |
352 | case CMD_CLOSE_LIBRARY: | |
353 | { | |
354 | /* Receive data from host. */ | |
355 | void *handle; | |
44799f87 | 356 | READ (pipe_host2tgt, &handle, sizeof (void *)); |
2eab9666 IV |
357 | |
358 | dlclose (handle); | |
359 | ||
5f520819 KY |
360 | break; |
361 | } | |
44799f87 | 362 | case CMD_PIPELINE_CREATE: |
5f520819 | 363 | { |
5f520819 | 364 | /* Receive data from host. */ |
6fd2e66a IV |
365 | uint32_t *pipeline_num; |
366 | MALLOC (uint32_t *, pipeline_num, sizeof (uint32_t)); | |
44799f87 IV |
367 | READ (pipe_host2tgt, pipeline_num, sizeof (*pipeline_num)); |
368 | ||
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."); | |
5f520819 KY |
374 | break; |
375 | } | |
376 | case CMD_SHUTDOWN: | |
44799f87 IV |
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."); | |
5f520819 KY |
381 | return COI_SUCCESS; |
382 | default: | |
383 | COIERROR ("Unrecognizable command from host."); | |
384 | } | |
385 | } | |
386 | ||
387 | return COI_ERROR; | |
388 | } | |
389 | ||
390 | ||
391 | ||
392 | uint64_t | |
393 | SYMBOL_VERSION (COIPerfGetCycleFrequency, 1) () | |
394 | { | |
395 | COITRACE ("COIPerfGetCycleFrequency"); | |
396 | ||
397 | return (uint64_t) CYCLE_FREQUENCY; | |
398 | } | |
399 | ||
400 | } // extern "C" | |
401 |