coi_host.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215
  1. /*
  2. Copyright (c) 2014 Intel Corporation. All Rights Reserved.
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions
  5. are met:
  6. * Redistributions of source code must retain the above copyright
  7. notice, this list of conditions and the following disclaimer.
  8. * Redistributions in binary form must reproduce the above copyright
  9. notice, this list of conditions and the following disclaimer in the
  10. documentation and/or other materials provided with the distribution.
  11. * Neither the name of Intel Corporation nor the names of its
  12. contributors may be used to endorse or promote products derived
  13. from this software without specific prior written permission.
  14. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  15. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  16. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  17. A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  18. HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  19. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  20. LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "coi_host.h"
  27. #include "coi_version_asm.h"
  28. #define CYCLE_FREQUENCY 1000000000
  29. /* Environment variables. */
  30. extern char **environ;
  31. /* List of directories for removing on exit. */
  32. char **tmp_dirs;
  33. unsigned tmp_dirs_num = 0;
  34. /* Number of KNC engines. */
  35. long knc_engines_num;
  36. /* Mutex to sync parallel execution. */
  37. pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
  38. typedef enum
  39. {
  40. BUFFER_NORMAL,
  41. BUFFER_MEMORY
  42. } buffer_t;
  43. typedef struct
  44. {
  45. COI_ISA_TYPE type;
  46. uint32_t index;
  47. char *dir;
  48. } Engine;
  49. typedef struct
  50. {
  51. char *name;
  52. void *ptr;
  53. } Function;
  54. typedef struct
  55. {
  56. int pipe_host;
  57. int pipe_target;
  58. } Pipeline;
  59. typedef struct
  60. {
  61. pid_t pid;
  62. Engine *engine;
  63. Function **functions;
  64. Pipeline *pipeline;
  65. } Process;
  66. typedef struct
  67. {
  68. buffer_t type;
  69. char *name;
  70. int fd;
  71. int fd_target;
  72. uint64_t size;
  73. void *data;
  74. void *data_target;
  75. Process *process;
  76. } Buffer;
  77. static COIRESULT
  78. read_long_env (const char *env_name, long *var, long var_default)
  79. {
  80. char *str = getenv (env_name);
  81. char *s;
  82. if (!str || *str == '\0')
  83. *var = var_default;
  84. else
  85. {
  86. errno = 0;
  87. *var = strtol (str, &s, 0);
  88. if (errno != 0 || s == str || *s != '\0')
  89. COIERROR ("Variable %s has invalid value.", env_name);
  90. }
  91. return COI_SUCCESS;
  92. }
  93. __attribute__((constructor))
  94. static void
  95. init ()
  96. {
  97. if (read_long_env (OFFLOAD_EMUL_KNC_NUM_ENV, &knc_engines_num, 1)
  98. == COI_ERROR)
  99. exit (0);
  100. }
  101. /* Helper function for directory removing. */
  102. static COIRESULT remove_directory (char *path)
  103. {
  104. char *file;
  105. struct dirent *entry;
  106. struct stat statfile;
  107. DIR *dir = opendir (path);
  108. if (dir == NULL)
  109. COIERROR ("Cannot open directory %s.", dir);
  110. while (entry = readdir (dir))
  111. {
  112. if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
  113. continue;
  114. MALLOC (char *, file, strlen (path) + strlen (entry->d_name) + 2);
  115. sprintf (file, "%s/%s", path, entry->d_name);
  116. if (stat (file, &statfile) < 0)
  117. COIERROR ("Cannot retrieve information about file %s.", file);
  118. if (S_ISDIR (statfile.st_mode))
  119. {
  120. if (remove_directory (file) == COI_ERROR)
  121. return COI_ERROR;
  122. }
  123. else
  124. {
  125. if (unlink (file) < 0)
  126. COIERROR ("Cannot unlink file %s.", file);
  127. }
  128. free (file);
  129. }
  130. if (closedir (dir) < 0)
  131. COIERROR ("Cannot close directory %s.", path);
  132. if (rmdir (path) < 0)
  133. COIERROR ("Cannot remove directory %s.", path);
  134. return COI_SUCCESS;
  135. }
  136. __attribute__((destructor))
  137. static void
  138. cleanup ()
  139. {
  140. unsigned i;
  141. for (i = 0; i < tmp_dirs_num; i++)
  142. {
  143. remove_directory (tmp_dirs[i]);
  144. free (tmp_dirs[i]);
  145. }
  146. if (tmp_dirs)
  147. free (tmp_dirs);
  148. }
  149. extern "C"
  150. {
  151. COIRESULT
  152. SYMBOL_VERSION (COIBufferCopy, 1) (COIBUFFER dest_buffer,
  153. COIBUFFER source_buffer,
  154. uint64_t dest_offset,
  155. uint64_t source_offset,
  156. uint64_t length,
  157. COI_COPY_TYPE type,
  158. uint32_t dependencies_num, // Ignored
  159. const COIEVENT *dependencies, // Ignored
  160. COIEVENT *completion) // Ignored
  161. {
  162. COITRACE ("COIBufferCopy");
  163. /* Convert input arguments. */
  164. Buffer *dest = (Buffer *) dest_buffer;
  165. Buffer *source = (Buffer *) source_buffer;
  166. /* Features of liboffload. */
  167. assert (type == COI_COPY_UNSPECIFIED);
  168. /* Start critical section. */
  169. if (pthread_mutex_lock (&mutex) != 0)
  170. COIERROR ("Cannot lock mutex.");
  171. /* Map buffers if needed. */
  172. if (dest->data == 0 && dest->type == BUFFER_NORMAL)
  173. if (COIBufferMap (dest_buffer, 0, dest->size, (COI_MAP_TYPE) 0,
  174. 0, 0, 0, 0, 0) == COI_ERROR)
  175. return COI_ERROR;
  176. if (source->data == 0 && source->type == BUFFER_NORMAL)
  177. if (COIBufferMap (source_buffer, 0, source->size, (COI_MAP_TYPE) 0,
  178. 0, 0, 0, 0, 0) == COI_ERROR)
  179. return COI_ERROR;
  180. /* Copy data. */
  181. if (source->data != 0 && dest->data != 0)
  182. memcpy ((void *) ((uintptr_t) dest->data+dest_offset),
  183. (void *) ((uintptr_t) source->data+source_offset), length);
  184. else
  185. {
  186. assert (dest->process == source->process);
  187. Buffer *buffer;
  188. cmd_t cmd = CMD_BUFFER_COPY;
  189. Pipeline *pipeline = dest->process->pipeline;
  190. /* Create intermediary buffer. */
  191. if (COIBufferCreate (length, COI_BUFFER_NORMAL, 0, 0, 1,
  192. (COIPROCESS*) &dest->process,
  193. (COIBUFFER *) &buffer) == COI_ERROR)
  194. return COI_ERROR;
  195. /* Copy from source to intermediary buffer. */
  196. if (source->data == 0)
  197. {
  198. assert (source->data_target != 0);
  199. /* Send data to target. */
  200. WRITE (pipeline->pipe_target, &cmd, sizeof (cmd_t));
  201. WRITE (pipeline->pipe_target, &(buffer->data_target), sizeof (void *));
  202. WRITE (pipeline->pipe_target, &(source->data_target), sizeof (void *));
  203. WRITE (pipeline->pipe_target, &(buffer->size), sizeof (uint64_t));
  204. /* Receive data from target. */
  205. READ (pipeline->pipe_host, &cmd, sizeof (cmd_t));
  206. }
  207. else
  208. {
  209. if (COIBufferCopy ((COIBUFFER) buffer, source_buffer, 0, source_offset,
  210. length, type, 0, 0, 0) == COI_ERROR)
  211. return COI_ERROR;
  212. }
  213. /* Copy from intermediary buffer to dest. */
  214. if (dest->data == 0)
  215. {
  216. assert (dest->data_target != 0);
  217. /* Send data to target. */
  218. WRITE (pipeline->pipe_target, &cmd, sizeof (cmd_t));
  219. WRITE (pipeline->pipe_target, &(dest->data_target), sizeof (void *));
  220. WRITE (pipeline->pipe_target, &(buffer->data_target), sizeof (void *));
  221. WRITE (pipeline->pipe_target, &(buffer->size), sizeof (uint64_t));
  222. /* Receive data from target. */
  223. READ (pipeline->pipe_host, &cmd, sizeof (cmd_t));
  224. }
  225. else
  226. {
  227. if (COIBufferCopy (dest_buffer, (COIBUFFER) buffer, dest_offset,
  228. 0, length, type, 0, 0, 0) == COI_ERROR)
  229. return COI_ERROR;
  230. }
  231. /* Unmap on target and destroy intermediary buffer. */
  232. if (COIBufferDestroy ((COIBUFFER) buffer) == COI_ERROR)
  233. return COI_ERROR;
  234. }
  235. /* Unmap buffers if needed. */
  236. if (dest->type == BUFFER_NORMAL)
  237. if (COIBufferUnmap ((COIMAPINSTANCE) dest, 0, 0, 0) == COI_ERROR)
  238. return COI_ERROR;
  239. if (source->type == BUFFER_NORMAL)
  240. if (COIBufferUnmap ((COIMAPINSTANCE) source, 0, 0, 0) == COI_ERROR)
  241. return COI_ERROR;
  242. /* Finish critical section. */
  243. if (pthread_mutex_unlock (&mutex) != 0)
  244. COIERROR ("Cannot unlock mutex.");
  245. return COI_SUCCESS;
  246. }
  247. COIRESULT
  248. SYMBOL_VERSION (COIBufferCreate, 1) (uint64_t size,
  249. COI_BUFFER_TYPE type,
  250. uint32_t flags,
  251. const void *init_data,
  252. uint32_t processes_num,
  253. const COIPROCESS *processes,
  254. COIBUFFER *buffer)
  255. {
  256. COITRACE ("COIBufferCreate");
  257. char *shm_name;
  258. cmd_t cmd = CMD_BUFFER_MAP;
  259. int shm_fd;
  260. const int ullong_max_len = 20;
  261. size_t len;
  262. unsigned long long i;
  263. Buffer *buf;
  264. Pipeline *pipeline;
  265. /* Features of liboffload. */
  266. assert (type == COI_BUFFER_NORMAL);
  267. assert ((flags & COI_SINK_MEMORY) == 0);
  268. assert ((flags & COI_SAME_ADDRESS_SINKS) == 0);
  269. assert ((flags & COI_SAME_ADDRESS_SINKS_AND_SOURCE) == 0);
  270. assert (init_data == 0);
  271. assert (processes_num == 1);
  272. /* Create shared memory with an unique name. */
  273. MALLOC (char *, shm_name, strlen (SHM_NAME) + ullong_max_len + 1);
  274. for (i = 0; i >= 0; i++)
  275. {
  276. sprintf (shm_name, SHM_NAME"%lu", i);
  277. shm_fd = shm_open (shm_name, O_CLOEXEC | O_CREAT | O_EXCL | O_RDWR,
  278. S_IRUSR | S_IWUSR);
  279. if (shm_fd > 0)
  280. break;
  281. }
  282. if (ftruncate (shm_fd, size) < 0)
  283. COIERROR ("Cannot truncate shared memory file.");
  284. /* Create buffer. */
  285. MALLOC (Buffer *, buf, sizeof (Buffer));
  286. buf->data = 0;
  287. buf->fd = shm_fd;
  288. buf->process = (Process *) processes[0];
  289. buf->size = size;
  290. buf->type = BUFFER_NORMAL;
  291. STRDUP (buf->name, shm_name);
  292. /* Map buffer on target. */
  293. len = strlen (buf->name) + 1;
  294. pipeline = buf->process->pipeline;
  295. /* Start critical section. */
  296. if (pthread_mutex_lock (&mutex) != 0)
  297. COIERROR ("Cannot lock mutex.");
  298. /* Send data to target. */
  299. WRITE (pipeline->pipe_target, &cmd, sizeof (cmd_t));
  300. WRITE (pipeline->pipe_target, &len, sizeof (size_t));
  301. WRITE (pipeline->pipe_target, buf->name, len);
  302. WRITE (pipeline->pipe_target, &(buf->size), sizeof (uint64_t));
  303. /* Receive data from target. */
  304. READ (pipeline->pipe_host, &(buf->fd_target), sizeof (int));
  305. READ (pipeline->pipe_host, &(buf->data_target), sizeof (void *));
  306. /* Finish critical section. */
  307. if (pthread_mutex_unlock (&mutex) != 0)
  308. COIERROR ("Cannot unlock mutex.");
  309. /* Prepare output arguments. */
  310. *buffer = (COIBUFFER) buf;
  311. /* Clean up. */
  312. free (shm_name);
  313. return COI_SUCCESS;
  314. }
  315. COIRESULT
  316. SYMBOL_VERSION (COIBufferCreateFromMemory, 1) (uint64_t size,
  317. COI_BUFFER_TYPE type,
  318. uint32_t flags,
  319. void *memory,
  320. uint32_t processes_num,
  321. const COIPROCESS *processes,
  322. COIBUFFER *buffer)
  323. {
  324. COITRACE ("COIBufferCreateFromMemory");
  325. Buffer *buf;
  326. /* Features of liboffload. */
  327. assert (type == COI_BUFFER_NORMAL);
  328. assert ((flags & COI_SAME_ADDRESS_SINKS) == 0);
  329. assert ((flags & COI_SAME_ADDRESS_SINKS_AND_SOURCE) == 0);
  330. assert (processes_num == 1);
  331. /* Create buffer. */
  332. MALLOC (Buffer *, buf, sizeof (Buffer));
  333. buf->data = (flags & COI_SINK_MEMORY) == 0 ? memory : 0;
  334. buf->data_target = (flags & COI_SINK_MEMORY) != 0 ? memory : 0;
  335. buf->process = (Process *) processes[0];
  336. buf->size = size;
  337. buf->type = BUFFER_MEMORY;
  338. /* Prepare output argument. */
  339. *buffer = (COIBUFFER) buf;
  340. return COI_SUCCESS;
  341. }
  342. COIRESULT
  343. SYMBOL_VERSION (COIBufferDestroy, 1) (COIBUFFER buffer)
  344. {
  345. COITRACE ("COIBufferDestroy");
  346. cmd_t cmd = CMD_BUFFER_UNMAP;
  347. /* Convert input arguments. */
  348. Buffer *buf = (Buffer *) buffer;
  349. Pipeline *pipeline = buf->process->pipeline;
  350. /* Unmap buffer on host. */
  351. if (buf->data != 0 && buf->type == BUFFER_NORMAL)
  352. if (COIBufferUnmap ((COIMAPINSTANCE) buffer, 0, 0, 0) == COI_ERROR)
  353. return COI_ERROR;
  354. /* Unmap buffer on target. */
  355. if (buf->data_target != 0)
  356. {
  357. /* Start critical section. */
  358. if (pthread_mutex_lock (&mutex) != 0)
  359. COIERROR ("Cannot lock mutex.");
  360. /* Send data to target. */
  361. WRITE (pipeline->pipe_target, &cmd, sizeof (cmd_t));
  362. WRITE (pipeline->pipe_target, &(buf->fd_target), sizeof (int));
  363. WRITE (pipeline->pipe_target, &(buf->data_target), sizeof (void *));
  364. WRITE (pipeline->pipe_target, &(buf->size), sizeof (uint64_t));
  365. /* Receive data from target. */
  366. READ (pipeline->pipe_host, &cmd, sizeof (cmd_t));
  367. /* Finish critical section. */
  368. if (pthread_mutex_unlock (&mutex) != 0)
  369. COIERROR ("Cannot unlock mutex.");
  370. }
  371. /* Unlink shared memory. */
  372. if (buf->type == BUFFER_NORMAL)
  373. {
  374. if (close (buf->fd) < 0)
  375. COIERROR ("Cannot close shared memory file.");
  376. if (shm_unlink (buf->name) < 0)
  377. COIERROR ("Cannot unlink shared memory.");
  378. free (buf->name);
  379. }
  380. /* Clean up. */
  381. free (buf);
  382. return COI_SUCCESS;
  383. }
  384. COIRESULT
  385. SYMBOL_VERSION (COIBufferGetSinkAddress, 1) (COIBUFFER buffer,
  386. uint64_t *data)
  387. {
  388. COITRACE ("COIBufferGetSinkAddress");
  389. /* Convert input arguments. */
  390. Buffer *buf = (Buffer *) buffer;
  391. /* Here should come BUFFER_NORMAL buffer. */
  392. assert (buf->type == BUFFER_NORMAL);
  393. /* Prepare output argument. */
  394. *data = (uint64_t) buf->data_target;
  395. return COI_SUCCESS;
  396. }
  397. COIRESULT
  398. SYMBOL_VERSION (COIBufferMap, 1) (COIBUFFER buffer,
  399. uint64_t offset,
  400. uint64_t length,
  401. COI_MAP_TYPE type, // Ignored
  402. uint32_t dependencies_num, // Ignored
  403. const COIEVENT *dependencies, // Ignored
  404. COIEVENT *completion, // Ignored
  405. COIMAPINSTANCE *map_instance,
  406. void **data)
  407. {
  408. COITRACE ("COIBufferMap");
  409. /* Features of liboffload. */
  410. assert (offset == 0);
  411. /* Convert input arguments. */
  412. Buffer *buf = (Buffer *) buffer;
  413. /* Only BUFFER_NORMAL buffers should come here. */
  414. assert (buf->type == BUFFER_NORMAL);
  415. /* Map shared memory. */
  416. buf->data = mmap (NULL, buf->size, PROT_READ | PROT_WRITE,
  417. MAP_SHARED, buf->fd, 0);
  418. if (buf->data == NULL)
  419. COIERROR ("Cannot map shared memory.");
  420. /* Prepare output arguments. */
  421. if (map_instance != 0)
  422. *map_instance = (COIMAPINSTANCE) buf;
  423. if (data != 0)
  424. *data = buf->data;
  425. return COI_SUCCESS;
  426. }
  427. COIRESULT
  428. SYMBOL_VERSION (COIBufferRead, 1) (COIBUFFER buffer,
  429. uint64_t offset,
  430. void *data,
  431. uint64_t length,
  432. COI_COPY_TYPE type,
  433. uint32_t dependencies_num, // Ignored
  434. const COIEVENT *dependencies, // Ignored
  435. COIEVENT *completion) // Ignored
  436. {
  437. COITRACE ("COIBufferRead");
  438. /* Convert input arguments. */
  439. Buffer *buf = (Buffer *) buffer;
  440. /* Features of liboffload. */
  441. assert (type == COI_COPY_UNSPECIFIED);
  442. /* Start critical section. */
  443. if (pthread_mutex_lock (&mutex) != 0)
  444. COIERROR ("Cannot lock mutex.");
  445. /* Map buffers if needed. */
  446. if (buf->data == 0 && buf->type == BUFFER_NORMAL)
  447. if (COIBufferMap (buffer, 0, buf->size, (COI_MAP_TYPE) 0,
  448. 0, 0, 0, 0, 0) == COI_ERROR)
  449. return COI_ERROR;
  450. /* Copy data. */
  451. memcpy (data, (void *) ((uintptr_t) buf->data+offset), length);
  452. /* Unmap buffers if needed. */
  453. if (buf->type == BUFFER_NORMAL)
  454. if (COIBufferUnmap ((COIMAPINSTANCE) buf, 0, 0, 0) == COI_ERROR)
  455. return COI_ERROR;
  456. /* Finish critical section. */
  457. if (pthread_mutex_unlock (&mutex) != 0)
  458. COIERROR ("Cannot unlock mutex.");
  459. return COI_SUCCESS;
  460. }
  461. COIRESULT
  462. SYMBOL_VERSION (COIBufferSetState, 1) (COIBUFFER buffer,
  463. COIPROCESS process,
  464. COI_BUFFER_STATE state,
  465. COI_BUFFER_MOVE_FLAG flag,
  466. uint32_t dependencies_num, // Ignored
  467. const COIEVENT *dependencies, // Ignored
  468. COIEVENT *completion) // Ignored
  469. {
  470. COITRACE ("COIBufferSetState");
  471. /* Features of liboffload. */
  472. assert (flag == COI_BUFFER_NO_MOVE);
  473. /* Looks like we have nothing to do here. */
  474. return COI_SUCCESS;
  475. }
  476. COIRESULT
  477. SYMBOL_VERSION (COIBufferUnmap, 1) (COIMAPINSTANCE map_instance,
  478. uint32_t dependencies_num, // Ignored
  479. const COIEVENT *dependencies, // Ignored
  480. COIEVENT *completion) // Ignored
  481. {
  482. COITRACE ("COIBufferUnmap");
  483. /* Convert input arguments. */
  484. Buffer *buffer = (Buffer *) map_instance;
  485. /* Only BUFFER_NORMAL buffers should come here. */
  486. assert (buffer->type == BUFFER_NORMAL);
  487. /* Unmap shared memory. */
  488. if (munmap (buffer->data, buffer->size) < 0)
  489. COIERROR ("Cannot unmap shared memory.");
  490. buffer->data = 0;
  491. return COI_SUCCESS;
  492. }
  493. COIRESULT
  494. SYMBOL_VERSION (COIBufferWrite, 1) (COIBUFFER buffer,
  495. uint64_t offset,
  496. const void *data,
  497. uint64_t length,
  498. COI_COPY_TYPE type,
  499. uint32_t dependencies_num, // Ignored
  500. const COIEVENT *dependencies, // Ignored
  501. COIEVENT *completion) // Ignored
  502. {
  503. COITRACE ("COIBufferWrite");
  504. /* Convert input arguments. */
  505. Buffer *buf = (Buffer *) buffer;
  506. /* Features of liboffload. */
  507. assert (type == COI_COPY_UNSPECIFIED);
  508. /* Start critical section. */
  509. if (pthread_mutex_lock (&mutex) != 0)
  510. COIERROR ("Cannot lock mutex.");
  511. /* Map buffers if needed. */
  512. if (buf->data == 0 && buf->type == BUFFER_NORMAL)
  513. if (COIBufferMap (buffer, 0, buf->size, (COI_MAP_TYPE) 0,
  514. 0, 0, 0, 0, 0) == COI_ERROR)
  515. return COI_ERROR;
  516. /* Copy data. */
  517. memcpy ((void *) ((uintptr_t) buf->data+offset), data, length);
  518. /* Unmap buffers if needed. */
  519. if (buf->type == BUFFER_NORMAL)
  520. if (COIBufferUnmap ((COIMAPINSTANCE) buf, 0, 0, 0) == COI_ERROR)
  521. return COI_ERROR;
  522. /* Finish critical section. */
  523. if (pthread_mutex_unlock (&mutex) != 0)
  524. COIERROR ("Cannot unlock mutex.");
  525. return COI_SUCCESS;
  526. }
  527. COIRESULT
  528. SYMBOL_VERSION (COIEngineGetCount, 1) (COI_ISA_TYPE isa,
  529. uint32_t *count)
  530. {
  531. COITRACE ("COIEngineGetCount");
  532. /* Features of liboffload. */
  533. assert (isa == COI_ISA_KNC);
  534. /* Prepare output arguments. */
  535. *count = knc_engines_num;
  536. return COI_SUCCESS;
  537. }
  538. COIRESULT
  539. SYMBOL_VERSION (COIEngineGetHandle, 1) (COI_ISA_TYPE isa,
  540. uint32_t index,
  541. COIENGINE *handle)
  542. {
  543. COITRACE ("COIEngineGetHandle");
  544. Engine *engine;
  545. /* Features of liboffload. */
  546. assert (isa == COI_ISA_KNC);
  547. /* Check engine index. */
  548. if (index >= knc_engines_num)
  549. COIERROR ("Wrong engine index.");
  550. /* Create engine handle. */
  551. MALLOC (Engine *, engine, sizeof (Engine));
  552. engine->dir = NULL;
  553. engine->index = index;
  554. engine->type = isa;
  555. /* Prepare output argument. */
  556. *handle = (COIENGINE) engine;
  557. return COI_SUCCESS;
  558. }
  559. COIRESULT
  560. SYMBOL_VERSION (COIEventWait, 1) (uint16_t events_num, // Ignored
  561. const COIEVENT *events, // Ignored
  562. int32_t timeout, // Ignored
  563. uint8_t wait_all,
  564. uint32_t *signaled_num,
  565. uint32_t *signaled_indices)
  566. {
  567. COITRACE ("COIEventWait");
  568. /* Features of liboffload. */
  569. assert (wait_all == 1);
  570. assert (signaled_num == 0);
  571. assert (signaled_indices == 0);
  572. /* Looks like we have nothing to do here. */
  573. return COI_SUCCESS;
  574. }
  575. COIRESULT
  576. SYMBOL_VERSION (COIPipelineCreate, 1) (COIPROCESS process,
  577. COI_CPU_MASK mask,
  578. uint32_t stack_size, // Ignored
  579. COIPIPELINE *pipeline)
  580. {
  581. COITRACE ("COIPipelineCreate");
  582. /* Features of liboffload. */
  583. assert (mask == 0);
  584. /* Prepare output arguments. */
  585. *pipeline = (COIPIPELINE) ((Process *) process)->pipeline;
  586. return COI_SUCCESS;
  587. }
  588. COIRESULT
  589. SYMBOL_VERSION (COIPipelineDestroy, 1) (COIPIPELINE pipeline)
  590. {
  591. COITRACE ("COIPipelineDestroy");
  592. /* Do nothing here. Pipeline will be closed during COIProcessDestroy. */
  593. return COI_SUCCESS;
  594. }
  595. COIRESULT
  596. SYMBOL_VERSION (COIPipelineRunFunction, 1) (COIPIPELINE pipeline,
  597. COIFUNCTION function,
  598. uint32_t buffers_num,
  599. const COIBUFFER *buffers,
  600. const COI_ACCESS_FLAGS *access_flags, // Ignored
  601. uint32_t dependencies_num, // Ignored
  602. const COIEVENT *dependencies, // Ignored
  603. const void *misc_data,
  604. uint16_t misc_data_len,
  605. void *return_data,
  606. uint16_t return_data_len,
  607. COIEVENT *completion) // Ignored
  608. {
  609. COITRACE ("COIPipelineRunFunction");
  610. cmd_t cmd = CMD_RUN_FUNCTION;
  611. int ret_len;
  612. uint32_t i;
  613. uint64_t size;
  614. void *ptr;
  615. /* Convert input arguments. */
  616. Buffer **bufs = (Buffer **) buffers;
  617. Function *func = (Function *) function;
  618. Pipeline *pipe = (Pipeline *) pipeline;
  619. /* Start critical section. */
  620. if (pthread_mutex_lock (&mutex) != 0)
  621. COIERROR ("Cannot lock mutex.");
  622. /* Send data to target. */
  623. WRITE (pipe->pipe_target, &cmd, sizeof (cmd_t));
  624. WRITE (pipe->pipe_target, &(func->ptr), sizeof (void *));
  625. WRITE (pipe->pipe_target, &buffers_num, sizeof (uint32_t));
  626. for (i = 0; i < buffers_num; i++)
  627. {
  628. WRITE (pipe->pipe_target, &(bufs[i]->size), sizeof (uint64_t));
  629. WRITE (pipe->pipe_target, &(bufs[i]->data_target), sizeof (void *));
  630. }
  631. WRITE (pipe->pipe_target, &misc_data_len, sizeof (uint16_t));
  632. if (misc_data_len > 0)
  633. WRITE (pipe->pipe_target, misc_data, misc_data_len);
  634. WRITE (pipe->pipe_target, &return_data_len, sizeof (uint16_t));
  635. /* Receive data from target. In emulator we don't need any asynchronous data
  636. transfer, so we wait for target process whether it has any data or not. */
  637. ret_len = read (pipe->pipe_host, return_data_len > 0 ? return_data : &cmd,
  638. return_data_len > 0 ? return_data_len : sizeof (cmd_t));
  639. if (ret_len == 0)
  640. return COI_PROCESS_DIED;
  641. else if (ret_len != (return_data_len > 0 ? return_data_len : sizeof (cmd_t)))
  642. COIERROR ("Cannot read from pipe.");
  643. /* Finish critical section. */
  644. if (pthread_mutex_unlock (&mutex) != 0)
  645. COIERROR ("Cannot unlock mutex.");
  646. return COI_SUCCESS;
  647. }
  648. COIRESULT
  649. SYMBOL_VERSION (COIProcessCreateFromMemory, 1) (COIENGINE engine,
  650. const char *bin_name,
  651. const void *bin_buffer,
  652. uint64_t bin_buffer_len,
  653. int argc,
  654. const char **argv,
  655. uint8_t inherit_env,
  656. const char **additional_env,
  657. uint8_t proxy_active, // Ignored
  658. const char *proxyfs_root, // Ignored
  659. uint64_t buffer_space, // Ignored
  660. const char *lib_search_path,
  661. const char *file_of_origin, // Ignored
  662. uint64_t file_of_origin_offset, // Ignored
  663. COIPROCESS *process)
  664. {
  665. COITRACE ("COIProcessCreateFromMemory");
  666. const int run_max_args_num = 128;
  667. char **envp;
  668. char *run_argv[run_max_args_num];
  669. char *emul_run = getenv (OFFLOAD_EMUL_RUN_ENV);
  670. char *env_name, *tok;
  671. char *pipe_host_path, *pipe_target_path, *pipes_path, *target_exe;
  672. FILE *file;
  673. int fd;
  674. int i, j, env_i, env_num;
  675. int pipe_host, pipe_target;
  676. const int uint_max_len = 11;
  677. pid_t pid;
  678. Pipeline *pipeline;
  679. Process *proc;
  680. /* Features of liboffload. */
  681. assert (argc == 0);
  682. assert (argv == 0);
  683. /* Convert input arguments. */
  684. Engine *eng = (Engine *) engine;
  685. /* Create temporary directory for engine files. */
  686. assert (eng->dir == NULL);
  687. STRDUP (eng->dir, ENGINE_PATH);
  688. if (mkdtemp (eng->dir) == NULL)
  689. COIERROR ("Cannot create temporary directory %s.", eng->dir);
  690. /* Save path to engine directory for clean up on exit. */
  691. tmp_dirs_num++;
  692. tmp_dirs = (char **) realloc (tmp_dirs, tmp_dirs_num * sizeof (char *));
  693. if (!tmp_dirs)
  694. COIERROR ("Cannot allocate memory.");
  695. STRDUP (tmp_dirs[tmp_dirs_num - 1], eng->dir);
  696. /* Create target executable file. */
  697. MALLOC (char *, target_exe, strlen (eng->dir) + strlen (bin_name) + 2);
  698. sprintf (target_exe, "%s/%s", eng->dir, bin_name);
  699. fd = open (target_exe, O_CLOEXEC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
  700. if (fd < 0)
  701. COIERROR ("Cannot create file %s.", target_exe);
  702. file = fdopen (fd, "wb");
  703. if (file == NULL)
  704. COIERROR ("Cannot associate stream with file descriptor.");
  705. if (fwrite (bin_buffer, 1, bin_buffer_len, file) != bin_buffer_len)
  706. COIERROR ("Cannot write in file %s.", target_exe);
  707. if (fclose (file) != 0)
  708. COIERROR ("Cannot close file %s.", target_exe);
  709. /* Fix file permissions. */
  710. if (chmod (target_exe, S_IRWXU) < 0)
  711. COIERROR ("Cannot change permissions for file %s.", target_exe);
  712. /* Create directory for pipes to prevent names collision. */
  713. MALLOC (char *, pipes_path, strlen (PIPES_PATH) + strlen (eng->dir) + 1);
  714. sprintf (pipes_path, "%s"PIPES_PATH, eng->dir);
  715. if (mkdir (pipes_path, S_IRWXU) < 0)
  716. COIERROR ("Cannot create folder %s.", pipes_path);
  717. /* Create pipes. */
  718. MALLOC (char *, pipe_host_path,
  719. strlen (PIPE_HOST_PATH) + strlen (eng->dir) + 1);
  720. MALLOC (char *, pipe_target_path,
  721. strlen (PIPE_TARGET_PATH) + strlen (eng->dir) + 1);
  722. if (pipe_target_path == NULL)
  723. COIERROR ("Cannot allocate memory.");
  724. sprintf (pipe_host_path, "%s"PIPE_HOST_PATH, eng->dir);
  725. sprintf (pipe_target_path, "%s"PIPE_TARGET_PATH, eng->dir);
  726. if (mkfifo (pipe_host_path, S_IRUSR | S_IWUSR) < 0)
  727. COIERROR ("Cannot create pipe %s.", pipe_host_path);
  728. if (mkfifo (pipe_target_path, S_IRUSR | S_IWUSR) < 0)
  729. COIERROR ("Cannot create pipe %s.", pipe_target_path);
  730. /* Prepare argv. */
  731. if (emul_run == NULL || strcmp (emul_run, "") == 0)
  732. {
  733. STRDUP (run_argv[0], target_exe);
  734. run_argv[1] = (char *) NULL;
  735. }
  736. else
  737. {
  738. char *ptr, *tmp;
  739. i = 0;
  740. STRDUP (tmp, emul_run);
  741. tok = strtok_r (tmp, " ", &ptr);
  742. while (tok != NULL)
  743. {
  744. if (i >= run_max_args_num)
  745. COIERROR ("Run command has too many arguments.");
  746. STRDUP (run_argv[i++], tok);
  747. tok = strtok_r (NULL, " ", &ptr);
  748. }
  749. STRDUP (run_argv[i], target_exe);
  750. run_argv[i+1] = (char *) NULL;
  751. free (tmp);
  752. }
  753. /* Prepare envp. */
  754. /* FIXME: take into account additional_env. */
  755. assert (additional_env == NULL);
  756. env_num = 0;
  757. if (inherit_env == true)
  758. while (environ[env_num++]);
  759. env_num += 4; // LD_LIBRARY_PATH, MIC_DIR, MIC_INDEX, NULL
  760. MALLOC (char **, envp, env_num * sizeof (char *));
  761. env_i = 0;
  762. if (inherit_env == true)
  763. for (i = 0; environ[i] != NULL; i++)
  764. {
  765. STRDUP (env_name, environ[i]);
  766. for (j = 0; env_name[j] != '=' && env_name[j] != '\0'; j++);
  767. env_name[j] = '\0';
  768. if (strcmp (env_name, "LD_LIBRARY_PATH") != 0
  769. && strcmp (env_name, MIC_DIR_ENV) != 0
  770. && strcmp (env_name, MIC_INDEX_ENV) != 0)
  771. STRDUP (envp[env_i++], environ[i]);
  772. free (env_name);
  773. }
  774. MALLOC (char *, envp[env_i], strlen (MIC_DIR_ENV) + strlen (eng->dir) + 2);
  775. sprintf (envp[env_i], "%s=%s", MIC_DIR_ENV, eng->dir);
  776. MALLOC (char *, envp[env_i+1], strlen (MIC_INDEX_ENV) + uint_max_len + 1);
  777. sprintf (envp[env_i+1], "%s=%u", MIC_INDEX_ENV, eng->index);
  778. MALLOC (char *, envp[env_i+2],
  779. strlen ("LD_LIBRARY_PATH=") + strlen (lib_search_path) + 1);
  780. sprintf (envp[env_i+2], "LD_LIBRARY_PATH=%s", lib_search_path);
  781. envp[env_i+3] = (char *) NULL;
  782. /* Create target process. */
  783. pid = vfork ();
  784. if (pid < 0)
  785. COIERROR ("Cannot create child process.");
  786. if (pid == 0)
  787. {
  788. /* Run target executable. */
  789. if (execvpe (run_argv[0], run_argv, envp) == -1)
  790. COIERROR ("Cannot execute file %s.", target_exe);
  791. }
  792. /* Open pipes. */
  793. pipe_host = open (pipe_host_path, O_CLOEXEC | O_RDONLY);
  794. if (pipe_host < 0)
  795. COIERROR ("Cannot open target-to-host pipe.");
  796. pipe_target = open (pipe_target_path, O_CLOEXEC | O_WRONLY);
  797. if (pipe_target < 0)
  798. COIERROR ("Cannot open host-to-target pipe.");
  799. /* Create pipeline handle. */
  800. MALLOC (Pipeline *, pipeline, sizeof (Pipeline));
  801. pipeline->pipe_host = pipe_host;
  802. pipeline->pipe_target = pipe_target;
  803. /* Create process handle. */
  804. MALLOC (Process *, proc, sizeof (Process));
  805. proc->pid = pid;
  806. proc->engine = eng;
  807. proc->functions = 0;
  808. proc->pipeline = pipeline;
  809. /* Prepare output arguments. */
  810. *process = (COIPROCESS) proc;
  811. /* Clean up. */
  812. for (i = 0; run_argv[i] != NULL; i++)
  813. free (run_argv[i]);
  814. for (i = 0; envp[i] != NULL; i++)
  815. free (envp[i]);
  816. free (envp);
  817. free (pipe_host_path);
  818. free (pipe_target_path);
  819. free (pipes_path);
  820. free (target_exe);
  821. return COI_SUCCESS;
  822. }
  823. COIRESULT
  824. SYMBOL_VERSION (COIProcessDestroy, 1) (COIPROCESS process,
  825. int32_t wait_timeout, // Ignored
  826. uint8_t force,
  827. int8_t *proc_return,
  828. uint32_t *reason)
  829. {
  830. COITRACE ("COIProcessDestroy");
  831. int i;
  832. /* Convert input arguments. */
  833. Process *proc = (Process *) process;
  834. /* Close pipeline. */
  835. if (close (proc->pipeline->pipe_host) < 0)
  836. COIERROR ("Cannot close target-to-host pipe.");
  837. if (close (proc->pipeline->pipe_target) < 0)
  838. COIERROR ("Cannot close host-to-target pipe.");
  839. free (proc->pipeline);
  840. /* Shutdown target process by force. */
  841. if (force)
  842. kill (proc->pid, SIGTERM);
  843. /* Clean up. */
  844. for (i = 0; proc->functions[i] != 0; i++)
  845. {
  846. free (proc->functions[i]->name);
  847. free (proc->functions[i]);
  848. }
  849. free (proc->engine->dir);
  850. free (proc->engine);
  851. free (proc->functions);
  852. free (proc);
  853. /* Prepare output arguments. */
  854. *proc_return = 0;
  855. *reason = 0;
  856. return COI_SUCCESS;
  857. }
  858. COIRESULT
  859. SYMBOL_VERSION (COIProcessGetFunctionHandles, 1) (COIPROCESS process,
  860. uint32_t functions_num,
  861. const char **function_names,
  862. COIFUNCTION *function_handles)
  863. {
  864. COITRACE ("COIProcessGetFunctionHandles");
  865. cmd_t cmd = CMD_GET_FUNCTION_HANDLE;
  866. Function *function;
  867. size_t len;
  868. void *ptr;
  869. uint32_t i;
  870. /* Convert input arguments. */
  871. Process *proc = (Process *) process;
  872. /* This function should be called once for the process. */
  873. assert (proc->functions == 0);
  874. /* Create array of function pointers. Last element is 0, what shows
  875. the end of the array. This array is used to free memory when process
  876. is destroyed. */
  877. proc->functions = (Function **) calloc (functions_num + 1,
  878. sizeof (Function *));
  879. if (proc->functions == NULL)
  880. COIERROR ("Cannot allocate memory.");
  881. /* Get handles for functions. */
  882. for (i = 0; i < functions_num; i++)
  883. {
  884. MALLOC (Function *, function, sizeof (Function));
  885. len = strlen (function_names[i]) + 1;
  886. /* Start critical section. */
  887. if (pthread_mutex_lock (&mutex) != 0)
  888. COIERROR ("Cannot lock mutex.");
  889. /* Send data to target. */
  890. WRITE (proc->pipeline->pipe_target, &cmd, sizeof (cmd_t));
  891. WRITE (proc->pipeline->pipe_target, &len, sizeof (size_t));
  892. WRITE (proc->pipeline->pipe_target, function_names[i], len);
  893. /* Receive data from target. */
  894. READ (proc->pipeline->pipe_host, &ptr, sizeof (void *));
  895. /* Finish critical section. */
  896. if (pthread_mutex_unlock (&mutex) != 0)
  897. COIERROR ("Cannot unlock mutex.");
  898. /* Prepare output arguments. */
  899. STRDUP (function->name, function_names[i]);
  900. if (function->name == NULL)
  901. COIERROR ("Cannot allocate memory.");
  902. function->ptr = ptr;
  903. function_handles[i] = (COIFUNCTION) function;
  904. /* Save function pointer. */
  905. proc->functions[i] = function;
  906. }
  907. return COI_SUCCESS;
  908. }
  909. COIRESULT
  910. SYMBOL_VERSION (COIProcessLoadLibraryFromMemory, 2) (COIPROCESS process,
  911. const void *lib_buffer,
  912. uint64_t lib_buffer_len,
  913. const char *lib_name,
  914. const char *lib_search_path,
  915. const char *file_of_origin, // Ignored
  916. uint64_t file_from_origin_offset, // Ignored
  917. uint32_t flags, // Ignored
  918. COILIBRARY *library) // Ignored
  919. {
  920. COITRACE ("COIProcessLoadLibraryFromMemory");
  921. char *lib_path;
  922. cmd_t cmd = CMD_OPEN_LIBRARY;
  923. int fd;
  924. FILE *file;
  925. size_t len;
  926. /* Convert input arguments. */
  927. Process *proc = (Process *) process;
  928. /* Create target library file. */
  929. MALLOC (char *, lib_path,
  930. strlen (proc->engine->dir) + strlen (lib_name) + 2);
  931. sprintf (lib_path, "%s/%s", proc->engine->dir, lib_name);
  932. fd = open (lib_path, O_CLOEXEC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
  933. if (fd < 0)
  934. COIERROR ("Cannot create file %s.", lib_path);
  935. file = fdopen (fd, "wb");
  936. if (file == NULL)
  937. COIERROR ("Cannot associate stream with file descriptor.");
  938. if (fwrite (lib_buffer, 1, lib_buffer_len, file) != lib_buffer_len)
  939. COIERROR ("Cannot write in file %s.", lib_path);
  940. if (fclose (file) != 0)
  941. COIERROR ("Cannot close file %s.", lib_path);
  942. len = strlen (lib_path) + 1;
  943. /* Start critical section. */
  944. if (pthread_mutex_lock (&mutex) != 0)
  945. COIERROR ("Cannot lock mutex.");
  946. /* Make target open library. */
  947. WRITE (proc->pipeline->pipe_target, &cmd, sizeof (cmd_t));
  948. WRITE (proc->pipeline->pipe_target, &len, sizeof (size_t));
  949. WRITE (proc->pipeline->pipe_target, lib_path, len);
  950. /* Finish critical section. */
  951. if (pthread_mutex_unlock (&mutex) != 0)
  952. COIERROR ("Cannot unlock mutex.");
  953. /* Clean up. */
  954. free (lib_path);
  955. return COI_SUCCESS;
  956. }
  957. COIRESULT
  958. SYMBOL_VERSION (COIProcessRegisterLibraries, 1) (uint32_t libraries_num,
  959. const void **libraries,
  960. const uint64_t *library_sizes,
  961. const char **files_of_origin,
  962. const uint64_t *file_of_origin_offsets)
  963. {
  964. COITRACE ("COIProcessRegisterLibraries");
  965. /* Looks like we have nothing to do here. */
  966. return COI_SUCCESS;
  967. }
  968. uint64_t
  969. SYMBOL_VERSION (COIPerfGetCycleFrequency, 1) ()
  970. {
  971. COITRACE ("COIPerfGetCycleFrequency");
  972. return (uint64_t) CYCLE_FREQUENCY;
  973. }
  974. } // extern "C"