coi_host.cpp 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634
  1. /*
  2. Copyright (c) 2014-2016 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 <set>
  27. #include <map>
  28. #include <queue>
  29. #include "coi_host.h"
  30. #include "coi_version_asm.h"
  31. #define CYCLE_FREQUENCY 1000000000
  32. enum buffer_t
  33. {
  34. BUFFER_NORMAL,
  35. BUFFER_MEMORY
  36. };
  37. struct Engine
  38. {
  39. COI_ISA_TYPE type;
  40. uint32_t index;
  41. char *dir;
  42. };
  43. struct Function
  44. {
  45. void *ptr;
  46. uint32_t num_buffers;
  47. uint64_t *bufs_size;
  48. void * *bufs_data_target;
  49. uint16_t misc_data_len;
  50. void *misc_data;
  51. uint16_t return_value_len;
  52. void *return_value;
  53. COIEVENT completion_event;
  54. };
  55. struct Callback
  56. {
  57. COI_EVENT_CALLBACK ptr;
  58. const void *data;
  59. };
  60. struct Process
  61. {
  62. pid_t pid;
  63. int pipe_host2tgt;
  64. int pipe_tgt2host;
  65. Engine *engine;
  66. void **functions;
  67. };
  68. struct Pipeline
  69. {
  70. pthread_t thread;
  71. bool destroy;
  72. bool is_destroyed;
  73. char *pipe_host2tgt_path;
  74. char *pipe_tgt2host_path;
  75. int pipe_host2tgt;
  76. int pipe_tgt2host;
  77. std::queue<Function> queue;
  78. Process *process;
  79. };
  80. struct Buffer
  81. {
  82. buffer_t type;
  83. char *name;
  84. int fd;
  85. int fd_target;
  86. uint64_t size;
  87. void *data;
  88. void *data_target;
  89. Process *process;
  90. };
  91. /* Environment variables. */
  92. extern char **environ;
  93. /* List of directories for removing on exit. */
  94. static char **tmp_dirs;
  95. static unsigned tmp_dirs_num;
  96. /* Number of emulated MIC engines. */
  97. static long num_engines;
  98. /* Number of the last COI pipeline. */
  99. static uint32_t max_pipeline_num;
  100. /* Set of undestroyed pipelines. */
  101. static std::set<Pipeline *> pipelines;
  102. /* Number of the last COI event, the event #0 is always signalled. */
  103. static uint64_t max_event_num = 1;
  104. /* Set of created COI events, which are not signalled. */
  105. static std::set<uint64_t> non_signalled_events;
  106. /* Set of COI events, which encountered errors. */
  107. static std::map<uint64_t, COIRESULT> errored_events;
  108. /* Set of registered callbacks, indexed by event number. */
  109. static std::map<uint64_t, Callback> callbacks;
  110. /* Mutex to sync parallel execution. */
  111. static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
  112. static COIRESULT
  113. read_long_env (const char *env_name, long *var, long var_default)
  114. {
  115. char *str = getenv (env_name);
  116. char *s;
  117. if (!str || *str == '\0')
  118. *var = var_default;
  119. else
  120. {
  121. errno = 0;
  122. *var = strtol (str, &s, 0);
  123. if (errno != 0 || s == str || *s != '\0')
  124. COIERROR ("Variable %s has invalid value.", env_name);
  125. }
  126. return COI_SUCCESS;
  127. }
  128. __attribute__((constructor))
  129. static void
  130. init ()
  131. {
  132. if (read_long_env (OFFLOAD_EMUL_NUM_ENV, &num_engines, 1) == COI_ERROR)
  133. exit (0);
  134. }
  135. /* Helper function for directory removing. */
  136. static COIRESULT remove_directory (char *path)
  137. {
  138. char *file;
  139. struct dirent *entry;
  140. struct stat statfile;
  141. DIR *dir = opendir (path);
  142. if (dir == NULL)
  143. COIERROR ("Cannot open directory %s.", dir);
  144. while (entry = readdir (dir))
  145. {
  146. if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
  147. continue;
  148. MALLOC (char *, file, strlen (path) + strlen (entry->d_name) + 2);
  149. sprintf (file, "%s/%s", path, entry->d_name);
  150. if (stat (file, &statfile) < 0)
  151. COIERROR ("Cannot retrieve information about file %s.", file);
  152. if (S_ISDIR (statfile.st_mode))
  153. {
  154. if (remove_directory (file) == COI_ERROR)
  155. return COI_ERROR;
  156. }
  157. else
  158. {
  159. if (unlink (file) < 0)
  160. COIERROR ("Cannot unlink file %s.", file);
  161. }
  162. free (file);
  163. }
  164. if (closedir (dir) < 0)
  165. COIERROR ("Cannot close directory %s.", path);
  166. if (rmdir (path) < 0)
  167. COIERROR ("Cannot remove directory %s.", path);
  168. return COI_SUCCESS;
  169. }
  170. __attribute__((destructor))
  171. static void
  172. cleanup ()
  173. {
  174. for (unsigned i = 0; i < tmp_dirs_num; i++)
  175. {
  176. remove_directory (tmp_dirs[i]);
  177. free (tmp_dirs[i]);
  178. }
  179. free (tmp_dirs);
  180. }
  181. static COIRESULT
  182. start_critical_section ()
  183. {
  184. if (pthread_mutex_lock (&mutex) != 0)
  185. COIERROR ("Cannot lock mutex.");
  186. return COI_SUCCESS;
  187. }
  188. static COIRESULT
  189. finish_critical_section ()
  190. {
  191. if (pthread_mutex_unlock (&mutex) != 0)
  192. COIERROR ("Cannot unlock mutex.");
  193. return COI_SUCCESS;
  194. }
  195. static bool
  196. pipeline_is_destroyed (const Pipeline *pipeline)
  197. {
  198. start_critical_section ();
  199. bool res = pipeline->is_destroyed;
  200. finish_critical_section ();
  201. return res;
  202. }
  203. static void
  204. maybe_invoke_callback (const COIEVENT event, const COIRESULT result)
  205. {
  206. std::map<uint64_t, Callback>::iterator cb = callbacks.find (event.opaque[0]);
  207. if (cb != callbacks.end ())
  208. {
  209. Callback callback = cb->second;
  210. callback.ptr (event, result, callback.data);
  211. callbacks.erase (cb);
  212. }
  213. }
  214. static void
  215. signal_event (const COIEVENT event, const COIRESULT result)
  216. {
  217. if (result != COI_SUCCESS)
  218. errored_events.insert (std::pair <uint64_t, COIRESULT> (event.opaque[0],
  219. result));
  220. non_signalled_events.erase (event.opaque[0]);
  221. maybe_invoke_callback (event, result);
  222. }
  223. static COIRESULT
  224. get_event_result (const COIEVENT event)
  225. {
  226. COIRESULT res = COI_SUCCESS;
  227. std::map<uint64_t, COIRESULT>::iterator ee
  228. = errored_events.find (event.opaque[0]);
  229. if (ee != errored_events.end ())
  230. res = ee->second;
  231. return res;
  232. }
  233. extern "C"
  234. {
  235. COIRESULT
  236. SYMBOL_VERSION (COIBufferCopy, 1) (COIBUFFER in_DestBuffer,
  237. COIBUFFER in_SourceBuffer,
  238. uint64_t in_DestOffset,
  239. uint64_t in_SourceOffset,
  240. uint64_t in_Length,
  241. COI_COPY_TYPE in_Type,
  242. uint32_t in_NumDependencies,
  243. const COIEVENT *in_pDependencies, // Ignored
  244. COIEVENT *out_pCompletion)
  245. {
  246. COITRACE ("COIBufferCopy");
  247. /* Features of liboffloadmic. */
  248. assert (in_DestBuffer != NULL);
  249. assert (in_SourceBuffer != NULL);
  250. assert (in_Type == COI_COPY_UNSPECIFIED);
  251. assert (in_NumDependencies == 0);
  252. /* Convert input arguments. */
  253. Buffer *dest = (Buffer *) in_DestBuffer;
  254. Buffer *source = (Buffer *) in_SourceBuffer;
  255. start_critical_section ();
  256. /* Map buffers if needed. */
  257. if (dest->data == 0 && dest->type == BUFFER_NORMAL)
  258. if (COIBufferMap (in_DestBuffer, 0, dest->size, (COI_MAP_TYPE) 0,
  259. 0, 0, 0, 0, 0) == COI_ERROR)
  260. return COI_ERROR;
  261. if (source->data == 0 && source->type == BUFFER_NORMAL)
  262. if (COIBufferMap (in_SourceBuffer, 0, source->size, (COI_MAP_TYPE) 0,
  263. 0, 0, 0, 0, 0) == COI_ERROR)
  264. return COI_ERROR;
  265. /* Copy data. */
  266. if (source->data != 0 && dest->data != 0)
  267. memcpy ((void *) ((uintptr_t) dest->data + in_DestOffset),
  268. (void *) ((uintptr_t) source->data + in_SourceOffset), in_Length);
  269. else
  270. {
  271. assert (dest->process == source->process);
  272. Buffer *buffer;
  273. cmd_t cmd = CMD_BUFFER_COPY;
  274. /* Create intermediary buffer. */
  275. if (COIBufferCreate (in_Length, COI_BUFFER_NORMAL, 0, 0, 1,
  276. (COIPROCESS*) &dest->process,
  277. (COIBUFFER *) &buffer) == COI_ERROR)
  278. return COI_ERROR;
  279. int pipe_host2tgt = dest->process->pipe_host2tgt;
  280. int pipe_tgt2host = dest->process->pipe_tgt2host;
  281. /* Copy from source to intermediary buffer. */
  282. if (source->data == 0)
  283. {
  284. assert (source->data_target != 0);
  285. /* Send data to target. */
  286. WRITE (pipe_host2tgt, &cmd, sizeof (cmd_t));
  287. WRITE (pipe_host2tgt, &buffer->data_target, sizeof (void *));
  288. WRITE (pipe_host2tgt, &source->data_target, sizeof (void *));
  289. WRITE (pipe_host2tgt, &buffer->size, sizeof (uint64_t));
  290. /* Receive data from target. */
  291. READ (pipe_tgt2host, &cmd, sizeof (cmd_t));
  292. }
  293. else
  294. {
  295. if (COIBufferCopy ((COIBUFFER) buffer, in_SourceBuffer, 0,
  296. in_SourceOffset, in_Length, in_Type, 0, 0, 0)
  297. == COI_ERROR)
  298. return COI_ERROR;
  299. }
  300. /* Copy from intermediary buffer to dest. */
  301. if (dest->data == 0)
  302. {
  303. assert (dest->data_target != 0);
  304. /* Send data to target. */
  305. WRITE (pipe_host2tgt, &cmd, sizeof (cmd_t));
  306. WRITE (pipe_host2tgt, &dest->data_target, sizeof (void *));
  307. WRITE (pipe_host2tgt, &buffer->data_target, sizeof (void *));
  308. WRITE (pipe_host2tgt, &buffer->size, sizeof (uint64_t));
  309. /* Receive data from target. */
  310. READ (pipe_tgt2host, &cmd, sizeof (cmd_t));
  311. }
  312. else
  313. {
  314. if (COIBufferCopy (in_DestBuffer, (COIBUFFER) buffer, in_DestOffset,
  315. 0, in_Length, in_Type, 0, 0, 0) == COI_ERROR)
  316. return COI_ERROR;
  317. }
  318. /* Unmap on target and destroy intermediary buffer. */
  319. if (COIBufferDestroy ((COIBUFFER) buffer) == COI_ERROR)
  320. return COI_ERROR;
  321. }
  322. /* Unmap buffers if needed. */
  323. if (dest->type == BUFFER_NORMAL)
  324. if (COIBufferUnmap ((COIMAPINSTANCE) dest, 0, 0, 0) == COI_ERROR)
  325. return COI_ERROR;
  326. if (source->type == BUFFER_NORMAL)
  327. if (COIBufferUnmap ((COIMAPINSTANCE) source, 0, 0, 0) == COI_ERROR)
  328. return COI_ERROR;
  329. finish_critical_section ();
  330. if (out_pCompletion)
  331. out_pCompletion->opaque[0] = 0;
  332. return COI_SUCCESS;
  333. }
  334. COIRESULT
  335. SYMBOL_VERSION (COIBufferCreate, 1) (uint64_t in_Size,
  336. COI_BUFFER_TYPE in_Type,
  337. uint32_t in_Flags,
  338. const void *in_pInitData,
  339. uint32_t in_NumProcesses,
  340. const COIPROCESS *in_pProcesses,
  341. COIBUFFER *out_pBuffer)
  342. {
  343. COITRACE ("COIBufferCreate");
  344. char *shm_name;
  345. int shm_fd;
  346. const int ullong_max_len = 20;
  347. /* Features of liboffloadmic. */
  348. assert (in_Type == COI_BUFFER_NORMAL || in_Type == COI_BUFFER_OPENCL);
  349. assert ((in_Flags & COI_SINK_MEMORY) == 0);
  350. assert ((in_Flags & COI_SAME_ADDRESS_SINKS) == 0);
  351. assert ((in_Flags & COI_SAME_ADDRESS_SINKS_AND_SOURCE) == 0);
  352. assert (in_pInitData == NULL);
  353. assert (in_NumProcesses == 1);
  354. assert (in_pProcesses != NULL);
  355. assert (out_pBuffer != NULL);
  356. /* Create shared memory with an unique name. */
  357. MALLOC (char *, shm_name, strlen (SHM_NAME) + ullong_max_len + 1);
  358. for (unsigned long long i = 0; i >= 0; i++)
  359. {
  360. sprintf (shm_name, SHM_NAME "%lu", i);
  361. shm_fd = shm_open (shm_name, O_CLOEXEC | O_CREAT | O_EXCL | O_RDWR,
  362. S_IRUSR | S_IWUSR);
  363. if (shm_fd > 0)
  364. break;
  365. }
  366. if (ftruncate (shm_fd, in_Size) < 0)
  367. COIERROR ("Cannot truncate shared memory file.");
  368. /* Create buffer. */
  369. Buffer *buf = new Buffer;
  370. buf->data = 0;
  371. buf->fd = shm_fd;
  372. buf->process = (Process *) in_pProcesses[0];
  373. buf->size = in_Size;
  374. buf->type = BUFFER_NORMAL;
  375. STRDUP (buf->name, shm_name);
  376. /* Map buffer on target. */
  377. size_t len = strlen (buf->name) + 1;
  378. start_critical_section ();
  379. /* Send data to target. */
  380. const cmd_t cmd = CMD_BUFFER_MAP;
  381. int pipe_host2tgt = buf->process->pipe_host2tgt;
  382. WRITE (pipe_host2tgt, &cmd, sizeof (cmd_t));
  383. WRITE (pipe_host2tgt, &len, sizeof (size_t));
  384. WRITE (pipe_host2tgt, buf->name, len);
  385. WRITE (pipe_host2tgt, &buf->size, sizeof (uint64_t));
  386. /* Receive data from target. */
  387. int pipe_tgt2host = buf->process->pipe_tgt2host;
  388. READ (pipe_tgt2host, &buf->fd_target, sizeof (int));
  389. READ (pipe_tgt2host, &buf->data_target, sizeof (void *));
  390. finish_critical_section ();
  391. /* Prepare output arguments. */
  392. *out_pBuffer = (COIBUFFER) buf;
  393. /* Clean up. */
  394. free (shm_name);
  395. return COI_SUCCESS;
  396. }
  397. COIRESULT
  398. SYMBOL_VERSION (COIBufferCreateFromMemory, 1) (uint64_t in_Size,
  399. COI_BUFFER_TYPE in_Type,
  400. uint32_t in_Flags,
  401. void *in_Memory,
  402. uint32_t in_NumProcesses,
  403. const COIPROCESS *in_pProcesses,
  404. COIBUFFER *out_pBuffer)
  405. {
  406. COITRACE ("COIBufferCreateFromMemory");
  407. /* Features of liboffloadmic. */
  408. assert (in_Type == COI_BUFFER_NORMAL);
  409. assert ((in_Flags & COI_SAME_ADDRESS_SINKS) == 0);
  410. assert ((in_Flags & COI_SAME_ADDRESS_SINKS_AND_SOURCE) == 0);
  411. assert (in_NumProcesses == 1);
  412. assert (in_pProcesses != NULL);
  413. assert (out_pBuffer != NULL);
  414. /* Create buffer. */
  415. Buffer *buf = new Buffer;
  416. buf->data = (in_Flags & COI_SINK_MEMORY) == 0 ? in_Memory : 0;
  417. buf->data_target = (in_Flags & COI_SINK_MEMORY) != 0 ? in_Memory : 0;
  418. buf->process = (Process *) in_pProcesses[0];
  419. buf->size = in_Size;
  420. buf->type = BUFFER_MEMORY;
  421. /* Prepare output argument. */
  422. *out_pBuffer = (COIBUFFER) buf;
  423. return COI_SUCCESS;
  424. }
  425. COIRESULT
  426. SYMBOL_VERSION (COIBufferDestroy, 1) (COIBUFFER in_Buffer)
  427. {
  428. COITRACE ("COIBufferDestroy");
  429. cmd_t cmd = CMD_BUFFER_UNMAP;
  430. assert (in_Buffer != NULL);
  431. /* Convert input arguments. */
  432. Buffer *buf = (Buffer *) in_Buffer;
  433. /* Unmap buffer on host. */
  434. if (buf->data != 0 && buf->type == BUFFER_NORMAL)
  435. if (COIBufferUnmap ((COIMAPINSTANCE) in_Buffer, 0, 0, 0) == COI_ERROR)
  436. return COI_ERROR;
  437. /* Unmap buffer on target. */
  438. if (buf->data_target != 0)
  439. {
  440. start_critical_section ();
  441. /* Send data to target. */
  442. int pipe_host2tgt = buf->process->pipe_host2tgt;
  443. WRITE (pipe_host2tgt, &cmd, sizeof (cmd_t));
  444. WRITE (pipe_host2tgt, &buf->fd_target, sizeof (int));
  445. WRITE (pipe_host2tgt, &buf->data_target, sizeof (void *));
  446. WRITE (pipe_host2tgt, &buf->size, sizeof (uint64_t));
  447. /* Receive data from target. */
  448. READ (buf->process->pipe_tgt2host, &cmd, sizeof (cmd_t));
  449. finish_critical_section ();
  450. }
  451. /* Unlink shared memory. */
  452. if (buf->type == BUFFER_NORMAL)
  453. {
  454. if (close (buf->fd) < 0)
  455. COIERROR ("Cannot close shared memory file.");
  456. if (shm_unlink (buf->name) < 0)
  457. COIERROR ("Cannot unlink shared memory.");
  458. free (buf->name);
  459. }
  460. /* Clean up. */
  461. delete buf;
  462. return COI_SUCCESS;
  463. }
  464. COIRESULT
  465. SYMBOL_VERSION (COIBufferGetSinkAddress, 1) (COIBUFFER in_Buffer,
  466. uint64_t *out_pAddress)
  467. {
  468. COITRACE ("COIBufferGetSinkAddress");
  469. assert (in_Buffer != NULL);
  470. assert (out_pAddress != NULL);
  471. /* Convert input arguments. */
  472. Buffer *buf = (Buffer *) in_Buffer;
  473. /* Here should come BUFFER_NORMAL buffer. */
  474. assert (buf->type == BUFFER_NORMAL);
  475. /* Prepare output argument. */
  476. *out_pAddress = (uint64_t) buf->data_target;
  477. return COI_SUCCESS;
  478. }
  479. COIRESULT
  480. SYMBOL_VERSION (COIBufferMap, 1) (COIBUFFER in_Buffer,
  481. uint64_t in_Offset,
  482. uint64_t in_Length, // Ignored
  483. COI_MAP_TYPE in_Type, // Ignored
  484. uint32_t in_NumDependencies,
  485. const COIEVENT *in_pDependencies, // Ignored
  486. COIEVENT *out_pCompletion,
  487. COIMAPINSTANCE *out_pMapInstance,
  488. void **out_ppData)
  489. {
  490. COITRACE ("COIBufferMap");
  491. /* Features of liboffloadmic. */
  492. assert (in_Offset == 0);
  493. assert (in_NumDependencies == 0);
  494. /* Convert input arguments. */
  495. Buffer *buf = (Buffer *) in_Buffer;
  496. /* Only BUFFER_NORMAL buffers should come here. */
  497. assert (buf->type == BUFFER_NORMAL);
  498. /* Map shared memory. */
  499. buf->data = mmap (NULL, buf->size, PROT_READ | PROT_WRITE,
  500. MAP_SHARED, buf->fd, 0);
  501. if (buf->data == NULL)
  502. COIERROR ("Cannot map shared memory.");
  503. /* Prepare output arguments. */
  504. if (out_pMapInstance != 0)
  505. *out_pMapInstance = (COIMAPINSTANCE) buf;
  506. if (out_ppData != 0)
  507. *out_ppData = buf->data;
  508. if (out_pCompletion)
  509. out_pCompletion->opaque[0] = 0;
  510. return COI_SUCCESS;
  511. }
  512. COIRESULT
  513. SYMBOL_VERSION (COIBufferRead, 1) (COIBUFFER in_SourceBuffer,
  514. uint64_t in_Offset,
  515. void *in_pDestData,
  516. uint64_t in_Length,
  517. COI_COPY_TYPE in_Type,
  518. uint32_t in_NumDependencies,
  519. const COIEVENT *in_pDependencies, // Ignored
  520. COIEVENT *out_pCompletion)
  521. {
  522. COITRACE ("COIBufferRead");
  523. /* Features of liboffloadmic. */
  524. assert (in_pDestData != NULL);
  525. assert (in_Type == COI_COPY_UNSPECIFIED);
  526. assert (in_NumDependencies == 0);
  527. /* Convert input arguments. */
  528. Buffer *buf = (Buffer *) in_SourceBuffer;
  529. start_critical_section ();
  530. /* Map buffers if needed. */
  531. if (buf->data == 0 && buf->type == BUFFER_NORMAL)
  532. if (COIBufferMap (in_SourceBuffer, 0, buf->size, (COI_MAP_TYPE) 0, 0, 0, 0,
  533. 0, 0) == COI_ERROR)
  534. return COI_ERROR;
  535. /* Copy data. */
  536. memcpy (in_pDestData, (void *) ((uintptr_t) buf->data + in_Offset),
  537. in_Length);
  538. /* Unmap buffers if needed. */
  539. if (buf->type == BUFFER_NORMAL)
  540. if (COIBufferUnmap ((COIMAPINSTANCE) buf, 0, 0, 0) == COI_ERROR)
  541. return COI_ERROR;
  542. finish_critical_section ();
  543. if (out_pCompletion)
  544. out_pCompletion->opaque[0] = 0;
  545. return COI_SUCCESS;
  546. }
  547. COIRESULT
  548. SYMBOL_VERSION (COIBufferSetState, 1) (COIBUFFER in_Buffer, // Ignored
  549. COIPROCESS in_Process, // Ignored
  550. COI_BUFFER_STATE in_State, // Ignored
  551. COI_BUFFER_MOVE_FLAG in_DataMove,
  552. uint32_t in_NumDependencies,
  553. const COIEVENT *in_pDependencies, // Ignored
  554. COIEVENT *out_pCompletion)
  555. {
  556. COITRACE ("COIBufferSetState");
  557. /* Features of liboffloadmic. */
  558. assert (in_DataMove == COI_BUFFER_NO_MOVE);
  559. assert (in_NumDependencies == 0);
  560. /* Looks like we have nothing to do here. */
  561. if (out_pCompletion)
  562. out_pCompletion->opaque[0] = 0;
  563. return COI_SUCCESS;
  564. }
  565. COIRESULT
  566. SYMBOL_VERSION (COIBufferUnmap, 1) (COIMAPINSTANCE in_MapInstance,
  567. uint32_t in_NumDependencies,
  568. const COIEVENT *in_pDependencies, // Ignored
  569. COIEVENT *out_pCompletion)
  570. {
  571. COITRACE ("COIBufferUnmap");
  572. /* Features of liboffloadmic. */
  573. assert (in_MapInstance != NULL);
  574. assert (in_NumDependencies == 0);
  575. /* Convert input arguments. */
  576. Buffer *buffer = (Buffer *) in_MapInstance;
  577. /* Only BUFFER_NORMAL buffers should come here. */
  578. assert (buffer->type == BUFFER_NORMAL);
  579. /* Unmap shared memory. */
  580. if (munmap (buffer->data, buffer->size) < 0)
  581. COIERROR ("Cannot unmap shared memory.");
  582. buffer->data = 0;
  583. if (out_pCompletion)
  584. out_pCompletion->opaque[0] = 0;
  585. return COI_SUCCESS;
  586. }
  587. COIRESULT
  588. SYMBOL_VERSION (COIBufferWrite, 1) (COIBUFFER in_DestBuffer,
  589. uint64_t in_Offset,
  590. const void *in_pSourceData,
  591. uint64_t in_Length,
  592. COI_COPY_TYPE in_Type,
  593. uint32_t in_NumDependencies,
  594. const COIEVENT *in_pDependencies, // Ignored
  595. COIEVENT *out_pCompletion)
  596. {
  597. COITRACE ("COIBufferWrite");
  598. /* Features of liboffloadmic. */
  599. assert (in_DestBuffer != NULL);
  600. assert (in_pSourceData != NULL);
  601. assert (in_Type == COI_COPY_UNSPECIFIED);
  602. assert (in_NumDependencies == 0);
  603. /* Convert input arguments. */
  604. Buffer *buf = (Buffer *) in_DestBuffer;
  605. start_critical_section ();
  606. /* Map buffers if needed. */
  607. if (buf->data == 0 && buf->type == BUFFER_NORMAL)
  608. if (COIBufferMap (in_DestBuffer, 0, buf->size, (COI_MAP_TYPE) 0, 0, 0, 0, 0,
  609. 0) == COI_ERROR)
  610. return COI_ERROR;
  611. /* Copy data. */
  612. memcpy ((void *) ((uintptr_t) buf->data + in_Offset), in_pSourceData,
  613. in_Length);
  614. /* Unmap buffers if needed. */
  615. if (buf->type == BUFFER_NORMAL)
  616. if (COIBufferUnmap ((COIMAPINSTANCE) buf, 0, 0, 0) == COI_ERROR)
  617. return COI_ERROR;
  618. finish_critical_section ();
  619. if (out_pCompletion)
  620. out_pCompletion->opaque[0] = 0;
  621. return COI_SUCCESS;
  622. }
  623. COIRESULT
  624. SYMBOL_VERSION (COIEngineGetCount, 1) (COI_ISA_TYPE isa,
  625. uint32_t *count)
  626. {
  627. COITRACE ("COIEngineGetCount");
  628. /* Features of liboffloadmic. */
  629. assert (isa == COI_ISA_MIC);
  630. assert (count != NULL);
  631. /* Prepare output arguments. */
  632. *count = num_engines;
  633. return COI_SUCCESS;
  634. }
  635. COIRESULT
  636. SYMBOL_VERSION (COIEngineGetHandle, 1) (COI_ISA_TYPE in_ISA,
  637. uint32_t in_EngineIndex,
  638. COIENGINE *out_pEngineHandle)
  639. {
  640. COITRACE ("COIEngineGetHandle");
  641. /* Features of liboffloadmic. */
  642. assert (in_ISA == COI_ISA_MIC);
  643. assert (out_pEngineHandle != NULL);
  644. /* Check engine index. */
  645. if (in_EngineIndex >= num_engines)
  646. COIERROR ("Wrong engine index.");
  647. /* Create engine handle. */
  648. Engine *engine = new Engine;
  649. engine->dir = NULL;
  650. engine->index = in_EngineIndex;
  651. engine->type = in_ISA;
  652. /* Prepare output argument. */
  653. *out_pEngineHandle = (COIENGINE) engine;
  654. return COI_SUCCESS;
  655. }
  656. COIRESULT
  657. SYMBOL_VERSION (COIEventWait, 1) (uint16_t in_NumEvents,
  658. const COIEVENT *in_pEvents,
  659. int32_t in_TimeoutMilliseconds,
  660. uint8_t in_WaitForAll,
  661. uint32_t *out_pNumSignaled,
  662. uint32_t *out_pSignaledIndices)
  663. {
  664. COITRACE ("COIEventWait");
  665. /* Features of liboffloadmic. */
  666. assert (in_pEvents != NULL);
  667. assert (in_TimeoutMilliseconds == 0 || in_TimeoutMilliseconds == -1);
  668. assert (in_WaitForAll == 1);
  669. assert (out_pNumSignaled == NULL);
  670. assert (out_pSignaledIndices == NULL);
  671. if (in_TimeoutMilliseconds == 0)
  672. {
  673. /* If some event is not signalled, return timeout error. */
  674. for (uint16_t i = 0; i < in_NumEvents; i++)
  675. if (non_signalled_events.count (in_pEvents[i].opaque[0]) > 0)
  676. return COI_TIME_OUT_REACHED;
  677. else
  678. {
  679. /* If the event signalled with an error, return that error. */
  680. start_critical_section ();
  681. COIRESULT res = get_event_result (in_pEvents[i]);
  682. finish_critical_section ();
  683. if (res != COI_SUCCESS)
  684. return res;
  685. }
  686. }
  687. else
  688. {
  689. /* Wait indefinitely for all events. */
  690. for (uint16_t i = 0; i < in_NumEvents; i++)
  691. {
  692. while (non_signalled_events.count (in_pEvents[i].opaque[0]) > 0)
  693. usleep (1000);
  694. /* If the event signalled with an error, return that error. */
  695. start_critical_section ();
  696. COIRESULT res = get_event_result (in_pEvents[i]);
  697. finish_critical_section ();
  698. if (res != COI_SUCCESS)
  699. return res;
  700. }
  701. }
  702. return COI_SUCCESS;
  703. }
  704. COIRESULT
  705. SYMBOL_VERSION (COIEventRegisterCallback, 1) (const COIEVENT in_Event,
  706. COI_EVENT_CALLBACK in_Callback,
  707. const void *in_UserData,
  708. const uint64_t in_Flags)
  709. {
  710. COITRACE ("COIEventRegisterCallback");
  711. /* Features of liboffloadmic. */
  712. assert (in_Callback != NULL);
  713. assert (in_UserData != NULL);
  714. assert (in_Flags == 0);
  715. start_critical_section ();
  716. if (non_signalled_events.count (in_Event.opaque[0]) == 0)
  717. {
  718. /* If the event is already signalled, invoke the callback immediately. */
  719. COIRESULT res = get_event_result (in_Event);
  720. in_Callback (in_Event, res, in_UserData);
  721. }
  722. else
  723. {
  724. Callback callback;
  725. callback.ptr = in_Callback;
  726. callback.data = in_UserData;
  727. callbacks.insert (std::pair <uint64_t, Callback> (in_Event.opaque[0],
  728. callback));
  729. }
  730. finish_critical_section ();
  731. return COI_SUCCESS;
  732. }
  733. /* The start routine for the COI pipeline thread. */
  734. static void *
  735. pipeline_thread_routine (void *in_Pipeline)
  736. {
  737. /* Convert input arguments. */
  738. Pipeline *pipeline = (Pipeline *) in_Pipeline;
  739. /* Open pipes. */
  740. pipeline->pipe_host2tgt
  741. = open (pipeline->pipe_host2tgt_path, O_CLOEXEC | O_WRONLY);
  742. if (pipeline->pipe_host2tgt < 0)
  743. COIERRORN ("Cannot open host-to-target pipe.");
  744. pipeline->pipe_tgt2host
  745. = open (pipeline->pipe_tgt2host_path, O_CLOEXEC | O_RDONLY);
  746. if (pipeline->pipe_tgt2host < 0)
  747. COIERRORN ("Cannot open target-to-host pipe.");
  748. free (pipeline->pipe_host2tgt_path);
  749. free (pipeline->pipe_tgt2host_path);
  750. pipeline->pipe_host2tgt_path = NULL;
  751. pipeline->pipe_tgt2host_path = NULL;
  752. while (!pipeline->destroy)
  753. if (pipeline->queue.empty ())
  754. usleep (1000);
  755. else
  756. {
  757. Function func = pipeline->queue.front ();
  758. start_critical_section ();
  759. pipeline->queue.pop ();
  760. finish_critical_section ();
  761. /* Send data to target. */
  762. cmd_t cmd = CMD_PIPELINE_RUN_FUNCTION;
  763. WRITEN (pipeline->pipe_host2tgt, &cmd, sizeof (cmd_t));
  764. WRITEN (pipeline->pipe_host2tgt, &func.ptr, sizeof (void *));
  765. WRITEN (pipeline->pipe_host2tgt, &func.num_buffers, sizeof (uint32_t));
  766. for (uint32_t i = 0; i < func.num_buffers; i++)
  767. {
  768. WRITEN (pipeline->pipe_host2tgt, &func.bufs_size[i],
  769. sizeof (uint64_t));
  770. WRITEN (pipeline->pipe_host2tgt, &func.bufs_data_target[i],
  771. sizeof (void *));
  772. }
  773. WRITEN (pipeline->pipe_host2tgt, &func.misc_data_len,
  774. sizeof (uint16_t));
  775. if (func.misc_data_len > 0)
  776. WRITEN (pipeline->pipe_host2tgt, func.misc_data, func.misc_data_len);
  777. WRITEN (pipeline->pipe_host2tgt, &func.return_value_len,
  778. sizeof (uint16_t));
  779. delete [] func.bufs_size;
  780. delete [] func.bufs_data_target;
  781. /* Receive data from target. Wait for target function to complete,
  782. whether it has any data to return or not. */
  783. bool has_return_value = func.return_value_len > 0;
  784. int ret_len
  785. = read (pipeline->pipe_tgt2host,
  786. has_return_value ? func.return_value : &cmd,
  787. has_return_value ? func.return_value_len : sizeof (cmd_t));
  788. if (ret_len == 0)
  789. {
  790. start_critical_section ();
  791. signal_event (func.completion_event, COI_PROCESS_DIED);
  792. pipeline->is_destroyed = true;
  793. finish_critical_section ();
  794. return NULL;
  795. }
  796. else if (ret_len != (has_return_value ? func.return_value_len
  797. : sizeof (cmd_t)))
  798. COIERRORN ("Cannot read from pipe.");
  799. start_critical_section ();
  800. signal_event (func.completion_event, COI_SUCCESS);
  801. finish_critical_section ();
  802. }
  803. /* Send data to target. */
  804. const cmd_t cmd = CMD_PIPELINE_DESTROY;
  805. WRITEN (pipeline->pipe_host2tgt, &cmd, sizeof (cmd_t));
  806. /* Close pipes. */
  807. if (close (pipeline->pipe_host2tgt) < 0)
  808. COIERRORN ("Cannot close host-to-target pipe.");
  809. if (close (pipeline->pipe_tgt2host) < 0)
  810. COIERRORN ("Cannot close target-to-host pipe.");
  811. start_critical_section ();
  812. pipeline->is_destroyed = true;
  813. finish_critical_section ();
  814. return NULL;
  815. }
  816. COIRESULT
  817. SYMBOL_VERSION (COIPipelineCreate, 1) (COIPROCESS in_Process,
  818. COI_CPU_MASK in_Mask,
  819. uint32_t in_StackSize, // Ignored
  820. COIPIPELINE *out_pPipeline)
  821. {
  822. COITRACE ("COIPipelineCreate");
  823. /* Features of liboffloadmic. */
  824. assert (in_Process != NULL);
  825. assert (in_Mask == 0);
  826. assert (out_pPipeline != NULL);
  827. /* Convert input arguments. */
  828. Process *proc = (Process *) in_Process;
  829. start_critical_section ();
  830. /* Create pipeline handle. */
  831. Pipeline *pipeline = new Pipeline;
  832. pipeline->destroy = false;
  833. pipeline->is_destroyed = false;
  834. pipeline->process = proc;
  835. pipelines.insert (pipeline);
  836. /* Create pipes. */
  837. uint32_t pipeline_num = max_pipeline_num++;
  838. char *eng_dir = pipeline->process->engine->dir;
  839. MALLOC (char *, pipeline->pipe_host2tgt_path,
  840. strlen (eng_dir) + sizeof (PIPE_HOST2TGT_NAME "0000000000"));
  841. MALLOC (char *, pipeline->pipe_tgt2host_path,
  842. strlen (eng_dir) + sizeof (PIPE_TGT2HOST_NAME "0000000000"));
  843. sprintf (pipeline->pipe_host2tgt_path, "%s" PIPE_HOST2TGT_NAME "%010d",
  844. eng_dir, pipeline_num);
  845. sprintf (pipeline->pipe_tgt2host_path, "%s" PIPE_TGT2HOST_NAME "%010d",
  846. eng_dir, pipeline_num);
  847. if (mkfifo (pipeline->pipe_host2tgt_path, S_IRUSR | S_IWUSR) < 0)
  848. COIERROR ("Cannot create pipe %s.", pipeline->pipe_host2tgt_path);
  849. if (mkfifo (pipeline->pipe_tgt2host_path, S_IRUSR | S_IWUSR) < 0)
  850. COIERROR ("Cannot create pipe %s.", pipeline->pipe_tgt2host_path);
  851. /* Send data to target. */
  852. const cmd_t cmd = CMD_PIPELINE_CREATE;
  853. WRITE (proc->pipe_host2tgt, &cmd, sizeof (cmd_t));
  854. WRITE (proc->pipe_host2tgt, &pipeline_num, sizeof (pipeline_num));
  855. /* Create a new thread for the pipeline. */
  856. if (pthread_create (&pipeline->thread, NULL, pipeline_thread_routine,
  857. pipeline))
  858. COIERROR ("Cannot create new thread.");
  859. finish_critical_section ();
  860. /* Prepare output arguments. */
  861. *out_pPipeline = (COIPIPELINE) pipeline;
  862. return COI_SUCCESS;
  863. }
  864. COIRESULT
  865. SYMBOL_VERSION (COIPipelineDestroy, 1) (COIPIPELINE in_Pipeline)
  866. {
  867. COITRACE ("COIPipelineDestroy");
  868. assert (in_Pipeline != NULL);
  869. /* Convert input arguments. */
  870. Pipeline *pipeline = (Pipeline *) in_Pipeline;
  871. start_critical_section ();
  872. /* Remove pipeline from the set of undestroyed pipelines. */
  873. pipelines.erase (pipeline);
  874. /* Exit pipeline thread. */
  875. pipeline->destroy = true;
  876. finish_critical_section ();
  877. while (!pipeline_is_destroyed (pipeline))
  878. usleep (1000);
  879. /* Join with a destroyed thread. */
  880. if (pthread_join (pipeline->thread, NULL))
  881. COIERROR ("Cannot join with a thread.");
  882. delete pipeline;
  883. return COI_SUCCESS;
  884. }
  885. COIRESULT
  886. SYMBOL_VERSION (COIPipelineRunFunction, 1) (COIPIPELINE in_Pipeline,
  887. COIFUNCTION in_Function,
  888. uint32_t in_NumBuffers,
  889. const COIBUFFER *in_Buffers,
  890. const COI_ACCESS_FLAGS *in_pBufferAccessFlags, // Ignored
  891. uint32_t in_NumDependencies,
  892. const COIEVENT *in_pDependencies, // Ignored
  893. const void *in_pMiscData,
  894. uint16_t in_MiscDataLen,
  895. void *out_pAsyncReturnValue,
  896. uint16_t in_AsyncReturnValueLen,
  897. COIEVENT *out_pCompletion)
  898. {
  899. COITRACE ("COIPipelineRunFunction");
  900. /* Features of liboffloadmic. */
  901. assert (in_Pipeline != NULL);
  902. assert (in_Function != NULL);
  903. assert (in_NumDependencies == 0);
  904. Function func;
  905. func.ptr = (void *) in_Function;
  906. func.num_buffers = in_NumBuffers;
  907. func.bufs_size = new uint64_t [in_NumBuffers];
  908. func.bufs_data_target = new void * [in_NumBuffers];
  909. for (uint32_t i = 0; i < in_NumBuffers; i++)
  910. {
  911. Buffer **bufs = (Buffer **) in_Buffers;
  912. func.bufs_size[i] = bufs[i]->size;
  913. func.bufs_data_target[i] = bufs[i]->data_target;
  914. }
  915. func.misc_data = (void *) in_pMiscData;
  916. func.misc_data_len = in_MiscDataLen;
  917. func.return_value = out_pAsyncReturnValue;
  918. func.return_value_len = in_AsyncReturnValueLen;
  919. start_critical_section ();
  920. func.completion_event.opaque[0] = max_event_num++;
  921. non_signalled_events.insert (func.completion_event.opaque[0]);
  922. ((Pipeline *) in_Pipeline)->queue.push (func);
  923. finish_critical_section ();
  924. /* In case of synchronous execution we have to wait for target. */
  925. if (out_pCompletion == NULL)
  926. COIEventWait (1, &func.completion_event, -1, 1, NULL, NULL);
  927. else
  928. *out_pCompletion = func.completion_event;
  929. return COI_SUCCESS;
  930. }
  931. COIRESULT
  932. SYMBOL_VERSION (COIProcessCreateFromMemory, 1) (COIENGINE in_Engine,
  933. const char *in_pBinaryName,
  934. const void *in_pBinaryBuffer,
  935. uint64_t in_BinaryBufferLength,
  936. int in_Argc,
  937. const char **in_ppArgv,
  938. uint8_t in_DupEnv,
  939. const char **in_ppAdditionalEnv,
  940. uint8_t in_ProxyActive, // Ignored
  941. const char *in_Reserved, // Ignored
  942. uint64_t in_InitialBufferSpace, // Ignored
  943. const char *in_LibrarySearchPath,
  944. const char *in_FileOfOrigin, // Ignored
  945. uint64_t in_FileOfOriginOffset, // Ignored
  946. COIPROCESS *out_pProcess)
  947. {
  948. COITRACE ("COIProcessCreateFromMemory");
  949. const int run_max_args_num = 128;
  950. char *run_argv[run_max_args_num];
  951. char *emul_run = getenv (OFFLOAD_EMUL_RUN_ENV);
  952. const int uint_max_len = 11;
  953. /* Features of liboffloadmic. */
  954. assert (in_Engine != NULL);
  955. assert (in_pBinaryName != NULL);
  956. assert (in_pBinaryBuffer != NULL);
  957. assert (in_Argc == 0);
  958. assert (in_ppArgv == NULL);
  959. assert (in_ppAdditionalEnv == NULL);
  960. assert (in_LibrarySearchPath != NULL);
  961. assert (out_pProcess != NULL);
  962. /* Convert input arguments. */
  963. Engine *eng = (Engine *) in_Engine;
  964. /* Create temporary directory for engine files. */
  965. assert (eng->dir == NULL);
  966. STRDUP (eng->dir, ENGINE_PATH);
  967. if (mkdtemp (eng->dir) == NULL)
  968. COIERROR ("Cannot create temporary directory %s.", eng->dir);
  969. /* Save path to engine directory for clean up on exit. */
  970. tmp_dirs_num++;
  971. tmp_dirs = (char **) realloc (tmp_dirs, tmp_dirs_num * sizeof (char *));
  972. if (!tmp_dirs)
  973. COIERROR ("Cannot allocate memory.");
  974. STRDUP (tmp_dirs[tmp_dirs_num - 1], eng->dir);
  975. /* Create target executable file. */
  976. char *target_exe;
  977. MALLOC (char *, target_exe, strlen (eng->dir) + strlen (in_pBinaryName) + 2);
  978. sprintf (target_exe, "%s/%s", eng->dir, in_pBinaryName);
  979. int fd = open (target_exe, O_CLOEXEC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
  980. if (fd < 0)
  981. COIERROR ("Cannot create file %s.", target_exe);
  982. FILE *file = fdopen (fd, "wb");
  983. if (file == NULL)
  984. COIERROR ("Cannot associate stream with file descriptor.");
  985. if (fwrite (in_pBinaryBuffer, 1, in_BinaryBufferLength, file)
  986. != in_BinaryBufferLength)
  987. COIERROR ("Cannot write in file %s.", target_exe);
  988. if (fclose (file) != 0)
  989. COIERROR ("Cannot close file %s.", target_exe);
  990. /* Fix file permissions. */
  991. if (chmod (target_exe, S_IRWXU) < 0)
  992. COIERROR ("Cannot change permissions for file %s.", target_exe);
  993. /* Create directory for pipes to prevent names collision. */
  994. char *pipes_path;
  995. MALLOC (char *, pipes_path, strlen (eng->dir) + sizeof (PIPES_PATH));
  996. sprintf (pipes_path, "%s" PIPES_PATH, eng->dir);
  997. if (mkdir (pipes_path, S_IRWXU) < 0)
  998. COIERROR ("Cannot create folder %s.", pipes_path);
  999. /* Create 2 main pipes for inter-process communication. */
  1000. char *pipe_host2tgt_path, *pipe_tgt2host_path;
  1001. MALLOC (char *, pipe_host2tgt_path,
  1002. strlen (eng->dir) + sizeof (PIPE_HOST2TGT_NAME "mainpipe"));
  1003. MALLOC (char *, pipe_tgt2host_path,
  1004. strlen (eng->dir) + sizeof (PIPE_TGT2HOST_NAME "mainpipe"));
  1005. sprintf (pipe_host2tgt_path, "%s" PIPE_HOST2TGT_NAME "mainpipe", eng->dir);
  1006. sprintf (pipe_tgt2host_path, "%s" PIPE_TGT2HOST_NAME "mainpipe", eng->dir);
  1007. if (mkfifo (pipe_host2tgt_path, S_IRUSR | S_IWUSR) < 0)
  1008. COIERROR ("Cannot create main pipe %s.", pipe_host2tgt_path);
  1009. if (mkfifo (pipe_tgt2host_path, S_IRUSR | S_IWUSR) < 0)
  1010. COIERROR ("Cannot create main pipe %s.", pipe_tgt2host_path);
  1011. /* Prepare argv. */
  1012. if (emul_run == NULL || strcmp (emul_run, "") == 0)
  1013. {
  1014. STRDUP (run_argv[0], target_exe);
  1015. run_argv[1] = (char *) NULL;
  1016. }
  1017. else
  1018. {
  1019. char *ptr, *tmp;
  1020. int i = 0;
  1021. STRDUP (tmp, emul_run);
  1022. char *tok = strtok_r (tmp, " ", &ptr);
  1023. while (tok != NULL)
  1024. {
  1025. if (i >= run_max_args_num)
  1026. COIERROR ("Run command has too many arguments.");
  1027. STRDUP (run_argv[i++], tok);
  1028. tok = strtok_r (NULL, " ", &ptr);
  1029. }
  1030. STRDUP (run_argv[i], target_exe);
  1031. run_argv[i + 1] = (char *) NULL;
  1032. free (tmp);
  1033. }
  1034. /* Prepare envp. */
  1035. int env_num = 0;
  1036. if (in_DupEnv == true)
  1037. while (environ[env_num++]);
  1038. env_num += 4; // LD_LIBRARY_PATH, MIC_DIR, MIC_INDEX, NULL
  1039. char **envp;
  1040. MALLOC (char **, envp, env_num * sizeof (char *));
  1041. int env_i = 0;
  1042. if (in_DupEnv == true)
  1043. for (unsigned i = 0; environ[i] != NULL; i++)
  1044. {
  1045. unsigned j;
  1046. char *env_name;
  1047. STRDUP (env_name, environ[i]);
  1048. for (j = 0; env_name[j] != '=' && env_name[j] != '\0'; j++);
  1049. env_name[j] = '\0';
  1050. if (strcmp (env_name, "LD_LIBRARY_PATH") != 0
  1051. && strcmp (env_name, MIC_DIR_ENV) != 0
  1052. && strcmp (env_name, MIC_INDEX_ENV) != 0)
  1053. STRDUP (envp[env_i++], environ[i]);
  1054. free (env_name);
  1055. }
  1056. MALLOC (char *, envp[env_i], strlen (MIC_DIR_ENV) + strlen (eng->dir) + 2);
  1057. sprintf (envp[env_i], "%s=%s", MIC_DIR_ENV, eng->dir);
  1058. MALLOC (char *, envp[env_i + 1], strlen (MIC_INDEX_ENV) + uint_max_len + 1);
  1059. sprintf (envp[env_i + 1], "%s=%u", MIC_INDEX_ENV, eng->index);
  1060. MALLOC (char *, envp[env_i + 2],
  1061. strlen ("LD_LIBRARY_PATH=") + strlen (in_LibrarySearchPath) + 1);
  1062. sprintf (envp[env_i + 2], "LD_LIBRARY_PATH=%s", in_LibrarySearchPath);
  1063. envp[env_i + 3] = (char *) NULL;
  1064. /* Create target process. */
  1065. pid_t pid = vfork ();
  1066. if (pid < 0)
  1067. COIERROR ("Cannot create child process.");
  1068. if (pid == 0)
  1069. {
  1070. /* Run target executable. */
  1071. if (execvpe (run_argv[0], run_argv, envp) == -1)
  1072. COIERROR ("Cannot execute file %s.", target_exe);
  1073. }
  1074. /* Open main pipes. */
  1075. int pipe_host2tgt = open (pipe_host2tgt_path, O_CLOEXEC | O_WRONLY);
  1076. if (pipe_host2tgt < 0)
  1077. COIERROR ("Cannot open host-to-target main pipe.");
  1078. int pipe_tgt2host = open (pipe_tgt2host_path, O_CLOEXEC | O_RDONLY);
  1079. if (pipe_tgt2host < 0)
  1080. COIERROR ("Cannot open target-to-host main pipe.");
  1081. /* Create process handle. */
  1082. Process *proc = new Process;
  1083. proc->pid = pid;
  1084. proc->pipe_host2tgt = pipe_host2tgt;
  1085. proc->pipe_tgt2host = pipe_tgt2host;
  1086. proc->engine = eng;
  1087. proc->functions = NULL;
  1088. /* Prepare output arguments. */
  1089. *out_pProcess = (COIPROCESS) proc;
  1090. /* Clean up. */
  1091. for (unsigned i = 0; run_argv[i] != NULL; i++)
  1092. free (run_argv[i]);
  1093. for (unsigned i = 0; envp[i] != NULL; i++)
  1094. free (envp[i]);
  1095. free (envp);
  1096. free (pipe_host2tgt_path);
  1097. free (pipe_tgt2host_path);
  1098. free (pipes_path);
  1099. free (target_exe);
  1100. return COI_SUCCESS;
  1101. }
  1102. COIRESULT
  1103. SYMBOL_VERSION (COIProcessCreateFromFile, 1) (COIENGINE in_Engine,
  1104. const char *in_pBinaryName,
  1105. int in_Argc,
  1106. const char **in_ppArgv,
  1107. uint8_t in_DupEnv,
  1108. const char **in_ppAdditionalEnv,
  1109. uint8_t in_ProxyActive,
  1110. const char *in_Reserved,
  1111. uint64_t in_BufferSpace,
  1112. const char *in_LibrarySearchPath,
  1113. COIPROCESS *out_pProcess)
  1114. {
  1115. COITRACE ("COIProcessCreateFromFile");
  1116. /* liboffloadmic with GCC compiled binaries should never go here. */
  1117. assert (false);
  1118. return COI_ERROR;
  1119. }
  1120. COIRESULT
  1121. SYMBOL_VERSION (COIProcessDestroy, 1) (COIPROCESS in_Process,
  1122. int32_t in_WaitForMainTimeout, // Ignored
  1123. uint8_t in_ForceDestroy,
  1124. int8_t *out_pProcessReturn,
  1125. uint32_t *out_pTerminationCode)
  1126. {
  1127. COITRACE ("COIProcessDestroy");
  1128. assert (in_Process != NULL);
  1129. assert (out_pProcessReturn != NULL);
  1130. assert (out_pTerminationCode != NULL);
  1131. /* Convert input arguments. */
  1132. Process *proc = (Process *) in_Process;
  1133. /* Destroy all undestroyed pipelines. */
  1134. while (!pipelines.empty ())
  1135. {
  1136. std::set<Pipeline *>::iterator p = pipelines.begin ();
  1137. COIPipelineDestroy ((COIPIPELINE) *p);
  1138. }
  1139. /* Close main pipes. */
  1140. if (close (proc->pipe_host2tgt) < 0)
  1141. COIERROR ("Cannot close host-to-target main pipe.");
  1142. if (close (proc->pipe_tgt2host) < 0)
  1143. COIERROR ("Cannot close target-to-host main pipe.");
  1144. /* Shutdown target process by force. */
  1145. if (in_ForceDestroy)
  1146. kill (proc->pid, SIGTERM);
  1147. /* Clean up. */
  1148. free (proc->engine->dir);
  1149. free (proc->functions);
  1150. delete proc->engine;
  1151. delete proc;
  1152. /* Prepare output arguments. */
  1153. *out_pProcessReturn = 0;
  1154. *out_pTerminationCode = 0;
  1155. return COI_SUCCESS;
  1156. }
  1157. COIRESULT
  1158. SYMBOL_VERSION (COIProcessGetFunctionHandles, 1) (COIPROCESS in_Process,
  1159. uint32_t in_NumFunctions,
  1160. const char **in_ppFunctionNameArray,
  1161. COIFUNCTION *out_pFunctionHandleArray)
  1162. {
  1163. COITRACE ("COIProcessGetFunctionHandles");
  1164. assert (in_Process != NULL);
  1165. assert (in_ppFunctionNameArray != NULL);
  1166. assert (out_pFunctionHandleArray != NULL);
  1167. /* Convert input arguments. */
  1168. Process *proc = (Process *) in_Process;
  1169. /* This function should be called once for the process. */
  1170. assert (proc->functions == NULL);
  1171. /* Create array of function pointers. Last element is 0, what shows the end
  1172. of the array. This array is used to free memory when process is
  1173. destroyed. */
  1174. proc->functions = (void **) calloc (in_NumFunctions + 1, sizeof (void *));
  1175. if (proc->functions == NULL)
  1176. COIERROR ("Cannot allocate memory.");
  1177. /* Get handles for functions. */
  1178. for (uint32_t i = 0; i < in_NumFunctions; i++)
  1179. {
  1180. size_t len = strlen (in_ppFunctionNameArray[i]) + 1;
  1181. start_critical_section ();
  1182. /* Send data to target. */
  1183. const cmd_t cmd = CMD_GET_FUNCTION_HANDLE;
  1184. WRITE (proc->pipe_host2tgt, &cmd, sizeof (cmd_t));
  1185. WRITE (proc->pipe_host2tgt, &len, sizeof (size_t));
  1186. WRITE (proc->pipe_host2tgt, in_ppFunctionNameArray[i], len);
  1187. /* Receive data from target. */
  1188. void *fn_ptr;
  1189. READ (proc->pipe_tgt2host, &fn_ptr, sizeof (void *));
  1190. finish_critical_section ();
  1191. /* Save function pointer. */
  1192. proc->functions[i] = fn_ptr;
  1193. /* Prepare output arguments. */
  1194. out_pFunctionHandleArray[i] = (COIFUNCTION) fn_ptr;
  1195. }
  1196. return COI_SUCCESS;
  1197. }
  1198. COIRESULT
  1199. SYMBOL_VERSION (COIProcessLoadLibraryFromMemory, 2) (COIPROCESS in_Process,
  1200. const void *in_pLibraryBuffer,
  1201. uint64_t in_LibraryBufferLength,
  1202. const char *in_pLibraryName,
  1203. const char *in_LibrarySearchPath, // Ignored
  1204. const char *in_FileOfOrigin, // Ignored
  1205. uint64_t in_FileOfOriginOffset, // Ignored
  1206. uint32_t in_Flags, // Ignored
  1207. COILIBRARY *out_pLibrary)
  1208. {
  1209. COITRACE ("COIProcessLoadLibraryFromMemory");
  1210. assert (in_Process != NULL);
  1211. assert (in_pLibraryBuffer != NULL);
  1212. assert (out_pLibrary != NULL);
  1213. /* Convert input arguments. */
  1214. Process *proc = (Process *) in_Process;
  1215. /* Create target library file. */
  1216. char *lib_path;
  1217. size_t len = strlen (proc->engine->dir) + strlen (in_pLibraryName) + 2;
  1218. MALLOC (char *, lib_path, len);
  1219. sprintf (lib_path, "%s/%s", proc->engine->dir, in_pLibraryName);
  1220. int fd = open (lib_path, O_CLOEXEC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
  1221. if (fd < 0)
  1222. COIERROR ("Cannot create file %s.", lib_path);
  1223. FILE *file = fdopen (fd, "wb");
  1224. if (file == NULL)
  1225. COIERROR ("Cannot associate stream with file descriptor.");
  1226. if (fwrite (in_pLibraryBuffer, 1, in_LibraryBufferLength, file)
  1227. != in_LibraryBufferLength)
  1228. COIERROR ("Cannot write in file %s.", lib_path);
  1229. if (fclose (file) != 0)
  1230. COIERROR ("Cannot close file %s.", lib_path);
  1231. start_critical_section ();
  1232. /* Make target open library. */
  1233. const cmd_t cmd = CMD_OPEN_LIBRARY;
  1234. WRITE (proc->pipe_host2tgt, &cmd, sizeof (cmd_t));
  1235. WRITE (proc->pipe_host2tgt, &len, sizeof (size_t));
  1236. WRITE (proc->pipe_host2tgt, lib_path, len);
  1237. /* Receive data from target. */
  1238. void *handle;
  1239. READ (proc->pipe_tgt2host, &handle, sizeof (void *));
  1240. finish_critical_section ();
  1241. /* Clean up. */
  1242. free (lib_path);
  1243. *out_pLibrary = (COILIBRARY) handle;
  1244. return COI_SUCCESS;
  1245. }
  1246. COIRESULT
  1247. SYMBOL_VERSION (COIProcessRegisterLibraries, 1) (uint32_t in_NumLibraries, // Ignored
  1248. const void **in_ppLibraryArray, // Ignored
  1249. const uint64_t *in_pLibrarySizeArray, // Ignored
  1250. const char **in_ppFileOfOriginArray, // Ignored
  1251. const uint64_t *in_pFileOfOriginOffSetArray) // Ignored
  1252. {
  1253. COITRACE ("COIProcessRegisterLibraries");
  1254. /* Looks like we have nothing to do here. */
  1255. return COI_SUCCESS;
  1256. }
  1257. COIRESULT
  1258. SYMBOL_VERSION (COIProcessUnloadLibrary, 1) (COIPROCESS in_Process,
  1259. COILIBRARY in_Library)
  1260. {
  1261. COITRACE ("COIProcessUnloadLibrary");
  1262. assert (in_Process != NULL);
  1263. assert (in_Library != NULL);
  1264. const cmd_t cmd = CMD_CLOSE_LIBRARY;
  1265. /* Convert input arguments. */
  1266. Process *proc = (Process *) in_Process;
  1267. start_critical_section ();
  1268. /* Make target close library. */
  1269. WRITE (proc->pipe_host2tgt, &cmd, sizeof (cmd_t));
  1270. WRITE (proc->pipe_host2tgt, &in_Library, sizeof (void *));
  1271. finish_critical_section ();
  1272. return COI_SUCCESS;
  1273. }
  1274. uint64_t
  1275. SYMBOL_VERSION (COIPerfGetCycleFrequency, 1) ()
  1276. {
  1277. COITRACE ("COIPerfGetCycleFrequency");
  1278. return (uint64_t) CYCLE_FREQUENCY;
  1279. }
  1280. COIRESULT
  1281. SYMBOL_VERSION (COIPipelineClearCPUMask, 1) (COI_CPU_MASK *in_Mask)
  1282. {
  1283. COITRACE ("COIPipelineClearCPUMask");
  1284. /* Looks like we have nothing to do here. */
  1285. return COI_SUCCESS;
  1286. }
  1287. COIRESULT
  1288. SYMBOL_VERSION (COIPipelineSetCPUMask, 1) (COIPROCESS in_Process,
  1289. uint32_t in_CoreID,
  1290. uint8_t in_ThreadID,
  1291. COI_CPU_MASK *out_pMask)
  1292. {
  1293. COITRACE ("COIPipelineSetCPUMask");
  1294. /* Looks like we have nothing to do here. */
  1295. return COI_SUCCESS;
  1296. }
  1297. COIRESULT
  1298. SYMBOL_VERSION (COIEngineGetInfo, 1) (COIENGINE in_EngineHandle, // Ignored
  1299. uint32_t in_EngineInfoSize, // Ignored
  1300. COI_ENGINE_INFO *out_pEngineInfo)
  1301. {
  1302. COITRACE ("COIEngineGetInfo");
  1303. assert (out_pEngineInfo != NULL);
  1304. out_pEngineInfo->ISA = COI_DEVICE_KNL;
  1305. out_pEngineInfo->NumCores = 1;
  1306. out_pEngineInfo->NumThreads = 8;
  1307. out_pEngineInfo->CoreMaxFrequency = SYMBOL_VERSION(COIPerfGetCycleFrequency,1)() / 1000000;
  1308. out_pEngineInfo->PhysicalMemory = 1024;
  1309. out_pEngineInfo->PhysicalMemoryFree = 1024;
  1310. out_pEngineInfo->SwapMemory = 1024;
  1311. out_pEngineInfo->SwapMemoryFree = 1024;
  1312. out_pEngineInfo->MiscFlags = COI_ENG_ECC_DISABLED;
  1313. return COI_SUCCESS;
  1314. }
  1315. } // extern "C"