12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634 |
- /*
- Copyright (c) 2014-2016 Intel Corporation. All Rights Reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of Intel Corporation nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <set>
- #include <map>
- #include <queue>
- #include "coi_host.h"
- #include "coi_version_asm.h"
- #define CYCLE_FREQUENCY 1000000000
- enum buffer_t
- {
- BUFFER_NORMAL,
- BUFFER_MEMORY
- };
- struct Engine
- {
- COI_ISA_TYPE type;
- uint32_t index;
- char *dir;
- };
- struct Function
- {
- void *ptr;
- uint32_t num_buffers;
- uint64_t *bufs_size;
- void * *bufs_data_target;
- uint16_t misc_data_len;
- void *misc_data;
- uint16_t return_value_len;
- void *return_value;
- COIEVENT completion_event;
- };
- struct Callback
- {
- COI_EVENT_CALLBACK ptr;
- const void *data;
- };
- struct Process
- {
- pid_t pid;
- int pipe_host2tgt;
- int pipe_tgt2host;
- Engine *engine;
- void **functions;
- };
- struct Pipeline
- {
- pthread_t thread;
- bool destroy;
- bool is_destroyed;
- char *pipe_host2tgt_path;
- char *pipe_tgt2host_path;
- int pipe_host2tgt;
- int pipe_tgt2host;
- std::queue<Function> queue;
- Process *process;
- };
- struct Buffer
- {
- buffer_t type;
- char *name;
- int fd;
- int fd_target;
- uint64_t size;
- void *data;
- void *data_target;
- Process *process;
- };
- /* Environment variables. */
- extern char **environ;
- /* List of directories for removing on exit. */
- static char **tmp_dirs;
- static unsigned tmp_dirs_num;
- /* Number of emulated MIC engines. */
- static long num_engines;
- /* Number of the last COI pipeline. */
- static uint32_t max_pipeline_num;
- /* Set of undestroyed pipelines. */
- static std::set<Pipeline *> pipelines;
- /* Number of the last COI event, the event #0 is always signalled. */
- static uint64_t max_event_num = 1;
- /* Set of created COI events, which are not signalled. */
- static std::set<uint64_t> non_signalled_events;
- /* Set of COI events, which encountered errors. */
- static std::map<uint64_t, COIRESULT> errored_events;
- /* Set of registered callbacks, indexed by event number. */
- static std::map<uint64_t, Callback> callbacks;
- /* Mutex to sync parallel execution. */
- static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
- static COIRESULT
- read_long_env (const char *env_name, long *var, long var_default)
- {
- char *str = getenv (env_name);
- char *s;
- if (!str || *str == '\0')
- *var = var_default;
- else
- {
- errno = 0;
- *var = strtol (str, &s, 0);
- if (errno != 0 || s == str || *s != '\0')
- COIERROR ("Variable %s has invalid value.", env_name);
- }
- return COI_SUCCESS;
- }
- __attribute__((constructor))
- static void
- init ()
- {
- if (read_long_env (OFFLOAD_EMUL_NUM_ENV, &num_engines, 1) == COI_ERROR)
- exit (0);
- }
- /* Helper function for directory removing. */
- static COIRESULT remove_directory (char *path)
- {
- char *file;
- struct dirent *entry;
- struct stat statfile;
- DIR *dir = opendir (path);
- if (dir == NULL)
- COIERROR ("Cannot open directory %s.", dir);
- while (entry = readdir (dir))
- {
- if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
- continue;
- MALLOC (char *, file, strlen (path) + strlen (entry->d_name) + 2);
- sprintf (file, "%s/%s", path, entry->d_name);
- if (stat (file, &statfile) < 0)
- COIERROR ("Cannot retrieve information about file %s.", file);
- if (S_ISDIR (statfile.st_mode))
- {
- if (remove_directory (file) == COI_ERROR)
- return COI_ERROR;
- }
- else
- {
- if (unlink (file) < 0)
- COIERROR ("Cannot unlink file %s.", file);
- }
- free (file);
- }
- if (closedir (dir) < 0)
- COIERROR ("Cannot close directory %s.", path);
- if (rmdir (path) < 0)
- COIERROR ("Cannot remove directory %s.", path);
- return COI_SUCCESS;
- }
- __attribute__((destructor))
- static void
- cleanup ()
- {
- for (unsigned i = 0; i < tmp_dirs_num; i++)
- {
- remove_directory (tmp_dirs[i]);
- free (tmp_dirs[i]);
- }
- free (tmp_dirs);
- }
- static COIRESULT
- start_critical_section ()
- {
- if (pthread_mutex_lock (&mutex) != 0)
- COIERROR ("Cannot lock mutex.");
- return COI_SUCCESS;
- }
- static COIRESULT
- finish_critical_section ()
- {
- if (pthread_mutex_unlock (&mutex) != 0)
- COIERROR ("Cannot unlock mutex.");
- return COI_SUCCESS;
- }
- static bool
- pipeline_is_destroyed (const Pipeline *pipeline)
- {
- start_critical_section ();
- bool res = pipeline->is_destroyed;
- finish_critical_section ();
- return res;
- }
- static void
- maybe_invoke_callback (const COIEVENT event, const COIRESULT result)
- {
- std::map<uint64_t, Callback>::iterator cb = callbacks.find (event.opaque[0]);
- if (cb != callbacks.end ())
- {
- Callback callback = cb->second;
- callback.ptr (event, result, callback.data);
- callbacks.erase (cb);
- }
- }
- static void
- signal_event (const COIEVENT event, const COIRESULT result)
- {
- if (result != COI_SUCCESS)
- errored_events.insert (std::pair <uint64_t, COIRESULT> (event.opaque[0],
- result));
- non_signalled_events.erase (event.opaque[0]);
- maybe_invoke_callback (event, result);
- }
- static COIRESULT
- get_event_result (const COIEVENT event)
- {
- COIRESULT res = COI_SUCCESS;
- std::map<uint64_t, COIRESULT>::iterator ee
- = errored_events.find (event.opaque[0]);
- if (ee != errored_events.end ())
- res = ee->second;
- return res;
- }
- extern "C"
- {
- COIRESULT
- SYMBOL_VERSION (COIBufferCopy, 1) (COIBUFFER in_DestBuffer,
- COIBUFFER in_SourceBuffer,
- uint64_t in_DestOffset,
- uint64_t in_SourceOffset,
- uint64_t in_Length,
- COI_COPY_TYPE in_Type,
- uint32_t in_NumDependencies,
- const COIEVENT *in_pDependencies, // Ignored
- COIEVENT *out_pCompletion)
- {
- COITRACE ("COIBufferCopy");
- /* Features of liboffloadmic. */
- assert (in_DestBuffer != NULL);
- assert (in_SourceBuffer != NULL);
- assert (in_Type == COI_COPY_UNSPECIFIED);
- assert (in_NumDependencies == 0);
- /* Convert input arguments. */
- Buffer *dest = (Buffer *) in_DestBuffer;
- Buffer *source = (Buffer *) in_SourceBuffer;
- start_critical_section ();
- /* Map buffers if needed. */
- if (dest->data == 0 && dest->type == BUFFER_NORMAL)
- if (COIBufferMap (in_DestBuffer, 0, dest->size, (COI_MAP_TYPE) 0,
- 0, 0, 0, 0, 0) == COI_ERROR)
- return COI_ERROR;
- if (source->data == 0 && source->type == BUFFER_NORMAL)
- if (COIBufferMap (in_SourceBuffer, 0, source->size, (COI_MAP_TYPE) 0,
- 0, 0, 0, 0, 0) == COI_ERROR)
- return COI_ERROR;
- /* Copy data. */
- if (source->data != 0 && dest->data != 0)
- memcpy ((void *) ((uintptr_t) dest->data + in_DestOffset),
- (void *) ((uintptr_t) source->data + in_SourceOffset), in_Length);
- else
- {
- assert (dest->process == source->process);
- Buffer *buffer;
- cmd_t cmd = CMD_BUFFER_COPY;
- /* Create intermediary buffer. */
- if (COIBufferCreate (in_Length, COI_BUFFER_NORMAL, 0, 0, 1,
- (COIPROCESS*) &dest->process,
- (COIBUFFER *) &buffer) == COI_ERROR)
- return COI_ERROR;
- int pipe_host2tgt = dest->process->pipe_host2tgt;
- int pipe_tgt2host = dest->process->pipe_tgt2host;
- /* Copy from source to intermediary buffer. */
- if (source->data == 0)
- {
- assert (source->data_target != 0);
- /* Send data to target. */
- WRITE (pipe_host2tgt, &cmd, sizeof (cmd_t));
- WRITE (pipe_host2tgt, &buffer->data_target, sizeof (void *));
- WRITE (pipe_host2tgt, &source->data_target, sizeof (void *));
- WRITE (pipe_host2tgt, &buffer->size, sizeof (uint64_t));
- /* Receive data from target. */
- READ (pipe_tgt2host, &cmd, sizeof (cmd_t));
- }
- else
- {
- if (COIBufferCopy ((COIBUFFER) buffer, in_SourceBuffer, 0,
- in_SourceOffset, in_Length, in_Type, 0, 0, 0)
- == COI_ERROR)
- return COI_ERROR;
- }
- /* Copy from intermediary buffer to dest. */
- if (dest->data == 0)
- {
- assert (dest->data_target != 0);
- /* Send data to target. */
- WRITE (pipe_host2tgt, &cmd, sizeof (cmd_t));
- WRITE (pipe_host2tgt, &dest->data_target, sizeof (void *));
- WRITE (pipe_host2tgt, &buffer->data_target, sizeof (void *));
- WRITE (pipe_host2tgt, &buffer->size, sizeof (uint64_t));
- /* Receive data from target. */
- READ (pipe_tgt2host, &cmd, sizeof (cmd_t));
- }
- else
- {
- if (COIBufferCopy (in_DestBuffer, (COIBUFFER) buffer, in_DestOffset,
- 0, in_Length, in_Type, 0, 0, 0) == COI_ERROR)
- return COI_ERROR;
- }
- /* Unmap on target and destroy intermediary buffer. */
- if (COIBufferDestroy ((COIBUFFER) buffer) == COI_ERROR)
- return COI_ERROR;
- }
- /* Unmap buffers if needed. */
- if (dest->type == BUFFER_NORMAL)
- if (COIBufferUnmap ((COIMAPINSTANCE) dest, 0, 0, 0) == COI_ERROR)
- return COI_ERROR;
- if (source->type == BUFFER_NORMAL)
- if (COIBufferUnmap ((COIMAPINSTANCE) source, 0, 0, 0) == COI_ERROR)
- return COI_ERROR;
- finish_critical_section ();
- if (out_pCompletion)
- out_pCompletion->opaque[0] = 0;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIBufferCreate, 1) (uint64_t in_Size,
- COI_BUFFER_TYPE in_Type,
- uint32_t in_Flags,
- const void *in_pInitData,
- uint32_t in_NumProcesses,
- const COIPROCESS *in_pProcesses,
- COIBUFFER *out_pBuffer)
- {
- COITRACE ("COIBufferCreate");
- char *shm_name;
- int shm_fd;
- const int ullong_max_len = 20;
- /* Features of liboffloadmic. */
- assert (in_Type == COI_BUFFER_NORMAL || in_Type == COI_BUFFER_OPENCL);
- assert ((in_Flags & COI_SINK_MEMORY) == 0);
- assert ((in_Flags & COI_SAME_ADDRESS_SINKS) == 0);
- assert ((in_Flags & COI_SAME_ADDRESS_SINKS_AND_SOURCE) == 0);
- assert (in_pInitData == NULL);
- assert (in_NumProcesses == 1);
- assert (in_pProcesses != NULL);
- assert (out_pBuffer != NULL);
- /* Create shared memory with an unique name. */
- MALLOC (char *, shm_name, strlen (SHM_NAME) + ullong_max_len + 1);
- for (unsigned long long i = 0; i >= 0; i++)
- {
- sprintf (shm_name, SHM_NAME "%lu", i);
- shm_fd = shm_open (shm_name, O_CLOEXEC | O_CREAT | O_EXCL | O_RDWR,
- S_IRUSR | S_IWUSR);
- if (shm_fd > 0)
- break;
- }
- if (ftruncate (shm_fd, in_Size) < 0)
- COIERROR ("Cannot truncate shared memory file.");
- /* Create buffer. */
- Buffer *buf = new Buffer;
- buf->data = 0;
- buf->fd = shm_fd;
- buf->process = (Process *) in_pProcesses[0];
- buf->size = in_Size;
- buf->type = BUFFER_NORMAL;
- STRDUP (buf->name, shm_name);
- /* Map buffer on target. */
- size_t len = strlen (buf->name) + 1;
- start_critical_section ();
- /* Send data to target. */
- const cmd_t cmd = CMD_BUFFER_MAP;
- int pipe_host2tgt = buf->process->pipe_host2tgt;
- WRITE (pipe_host2tgt, &cmd, sizeof (cmd_t));
- WRITE (pipe_host2tgt, &len, sizeof (size_t));
- WRITE (pipe_host2tgt, buf->name, len);
- WRITE (pipe_host2tgt, &buf->size, sizeof (uint64_t));
- /* Receive data from target. */
- int pipe_tgt2host = buf->process->pipe_tgt2host;
- READ (pipe_tgt2host, &buf->fd_target, sizeof (int));
- READ (pipe_tgt2host, &buf->data_target, sizeof (void *));
- finish_critical_section ();
- /* Prepare output arguments. */
- *out_pBuffer = (COIBUFFER) buf;
- /* Clean up. */
- free (shm_name);
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIBufferCreateFromMemory, 1) (uint64_t in_Size,
- COI_BUFFER_TYPE in_Type,
- uint32_t in_Flags,
- void *in_Memory,
- uint32_t in_NumProcesses,
- const COIPROCESS *in_pProcesses,
- COIBUFFER *out_pBuffer)
- {
- COITRACE ("COIBufferCreateFromMemory");
- /* Features of liboffloadmic. */
- assert (in_Type == COI_BUFFER_NORMAL);
- assert ((in_Flags & COI_SAME_ADDRESS_SINKS) == 0);
- assert ((in_Flags & COI_SAME_ADDRESS_SINKS_AND_SOURCE) == 0);
- assert (in_NumProcesses == 1);
- assert (in_pProcesses != NULL);
- assert (out_pBuffer != NULL);
- /* Create buffer. */
- Buffer *buf = new Buffer;
- buf->data = (in_Flags & COI_SINK_MEMORY) == 0 ? in_Memory : 0;
- buf->data_target = (in_Flags & COI_SINK_MEMORY) != 0 ? in_Memory : 0;
- buf->process = (Process *) in_pProcesses[0];
- buf->size = in_Size;
- buf->type = BUFFER_MEMORY;
- /* Prepare output argument. */
- *out_pBuffer = (COIBUFFER) buf;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIBufferDestroy, 1) (COIBUFFER in_Buffer)
- {
- COITRACE ("COIBufferDestroy");
- cmd_t cmd = CMD_BUFFER_UNMAP;
- assert (in_Buffer != NULL);
- /* Convert input arguments. */
- Buffer *buf = (Buffer *) in_Buffer;
- /* Unmap buffer on host. */
- if (buf->data != 0 && buf->type == BUFFER_NORMAL)
- if (COIBufferUnmap ((COIMAPINSTANCE) in_Buffer, 0, 0, 0) == COI_ERROR)
- return COI_ERROR;
- /* Unmap buffer on target. */
- if (buf->data_target != 0)
- {
- start_critical_section ();
- /* Send data to target. */
- int pipe_host2tgt = buf->process->pipe_host2tgt;
- WRITE (pipe_host2tgt, &cmd, sizeof (cmd_t));
- WRITE (pipe_host2tgt, &buf->fd_target, sizeof (int));
- WRITE (pipe_host2tgt, &buf->data_target, sizeof (void *));
- WRITE (pipe_host2tgt, &buf->size, sizeof (uint64_t));
- /* Receive data from target. */
- READ (buf->process->pipe_tgt2host, &cmd, sizeof (cmd_t));
- finish_critical_section ();
- }
- /* Unlink shared memory. */
- if (buf->type == BUFFER_NORMAL)
- {
- if (close (buf->fd) < 0)
- COIERROR ("Cannot close shared memory file.");
- if (shm_unlink (buf->name) < 0)
- COIERROR ("Cannot unlink shared memory.");
- free (buf->name);
- }
- /* Clean up. */
- delete buf;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIBufferGetSinkAddress, 1) (COIBUFFER in_Buffer,
- uint64_t *out_pAddress)
- {
- COITRACE ("COIBufferGetSinkAddress");
- assert (in_Buffer != NULL);
- assert (out_pAddress != NULL);
- /* Convert input arguments. */
- Buffer *buf = (Buffer *) in_Buffer;
- /* Here should come BUFFER_NORMAL buffer. */
- assert (buf->type == BUFFER_NORMAL);
- /* Prepare output argument. */
- *out_pAddress = (uint64_t) buf->data_target;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIBufferMap, 1) (COIBUFFER in_Buffer,
- uint64_t in_Offset,
- uint64_t in_Length, // Ignored
- COI_MAP_TYPE in_Type, // Ignored
- uint32_t in_NumDependencies,
- const COIEVENT *in_pDependencies, // Ignored
- COIEVENT *out_pCompletion,
- COIMAPINSTANCE *out_pMapInstance,
- void **out_ppData)
- {
- COITRACE ("COIBufferMap");
- /* Features of liboffloadmic. */
- assert (in_Offset == 0);
- assert (in_NumDependencies == 0);
- /* Convert input arguments. */
- Buffer *buf = (Buffer *) in_Buffer;
- /* Only BUFFER_NORMAL buffers should come here. */
- assert (buf->type == BUFFER_NORMAL);
- /* Map shared memory. */
- buf->data = mmap (NULL, buf->size, PROT_READ | PROT_WRITE,
- MAP_SHARED, buf->fd, 0);
- if (buf->data == NULL)
- COIERROR ("Cannot map shared memory.");
- /* Prepare output arguments. */
- if (out_pMapInstance != 0)
- *out_pMapInstance = (COIMAPINSTANCE) buf;
- if (out_ppData != 0)
- *out_ppData = buf->data;
- if (out_pCompletion)
- out_pCompletion->opaque[0] = 0;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIBufferRead, 1) (COIBUFFER in_SourceBuffer,
- uint64_t in_Offset,
- void *in_pDestData,
- uint64_t in_Length,
- COI_COPY_TYPE in_Type,
- uint32_t in_NumDependencies,
- const COIEVENT *in_pDependencies, // Ignored
- COIEVENT *out_pCompletion)
- {
- COITRACE ("COIBufferRead");
- /* Features of liboffloadmic. */
- assert (in_pDestData != NULL);
- assert (in_Type == COI_COPY_UNSPECIFIED);
- assert (in_NumDependencies == 0);
- /* Convert input arguments. */
- Buffer *buf = (Buffer *) in_SourceBuffer;
- start_critical_section ();
- /* Map buffers if needed. */
- if (buf->data == 0 && buf->type == BUFFER_NORMAL)
- if (COIBufferMap (in_SourceBuffer, 0, buf->size, (COI_MAP_TYPE) 0, 0, 0, 0,
- 0, 0) == COI_ERROR)
- return COI_ERROR;
- /* Copy data. */
- memcpy (in_pDestData, (void *) ((uintptr_t) buf->data + in_Offset),
- in_Length);
- /* Unmap buffers if needed. */
- if (buf->type == BUFFER_NORMAL)
- if (COIBufferUnmap ((COIMAPINSTANCE) buf, 0, 0, 0) == COI_ERROR)
- return COI_ERROR;
- finish_critical_section ();
- if (out_pCompletion)
- out_pCompletion->opaque[0] = 0;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIBufferSetState, 1) (COIBUFFER in_Buffer, // Ignored
- COIPROCESS in_Process, // Ignored
- COI_BUFFER_STATE in_State, // Ignored
- COI_BUFFER_MOVE_FLAG in_DataMove,
- uint32_t in_NumDependencies,
- const COIEVENT *in_pDependencies, // Ignored
- COIEVENT *out_pCompletion)
- {
- COITRACE ("COIBufferSetState");
- /* Features of liboffloadmic. */
- assert (in_DataMove == COI_BUFFER_NO_MOVE);
- assert (in_NumDependencies == 0);
- /* Looks like we have nothing to do here. */
- if (out_pCompletion)
- out_pCompletion->opaque[0] = 0;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIBufferUnmap, 1) (COIMAPINSTANCE in_MapInstance,
- uint32_t in_NumDependencies,
- const COIEVENT *in_pDependencies, // Ignored
- COIEVENT *out_pCompletion)
- {
- COITRACE ("COIBufferUnmap");
- /* Features of liboffloadmic. */
- assert (in_MapInstance != NULL);
- assert (in_NumDependencies == 0);
- /* Convert input arguments. */
- Buffer *buffer = (Buffer *) in_MapInstance;
- /* Only BUFFER_NORMAL buffers should come here. */
- assert (buffer->type == BUFFER_NORMAL);
- /* Unmap shared memory. */
- if (munmap (buffer->data, buffer->size) < 0)
- COIERROR ("Cannot unmap shared memory.");
- buffer->data = 0;
- if (out_pCompletion)
- out_pCompletion->opaque[0] = 0;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIBufferWrite, 1) (COIBUFFER in_DestBuffer,
- uint64_t in_Offset,
- const void *in_pSourceData,
- uint64_t in_Length,
- COI_COPY_TYPE in_Type,
- uint32_t in_NumDependencies,
- const COIEVENT *in_pDependencies, // Ignored
- COIEVENT *out_pCompletion)
- {
- COITRACE ("COIBufferWrite");
- /* Features of liboffloadmic. */
- assert (in_DestBuffer != NULL);
- assert (in_pSourceData != NULL);
- assert (in_Type == COI_COPY_UNSPECIFIED);
- assert (in_NumDependencies == 0);
- /* Convert input arguments. */
- Buffer *buf = (Buffer *) in_DestBuffer;
- start_critical_section ();
- /* Map buffers if needed. */
- if (buf->data == 0 && buf->type == BUFFER_NORMAL)
- if (COIBufferMap (in_DestBuffer, 0, buf->size, (COI_MAP_TYPE) 0, 0, 0, 0, 0,
- 0) == COI_ERROR)
- return COI_ERROR;
- /* Copy data. */
- memcpy ((void *) ((uintptr_t) buf->data + in_Offset), in_pSourceData,
- in_Length);
- /* Unmap buffers if needed. */
- if (buf->type == BUFFER_NORMAL)
- if (COIBufferUnmap ((COIMAPINSTANCE) buf, 0, 0, 0) == COI_ERROR)
- return COI_ERROR;
- finish_critical_section ();
- if (out_pCompletion)
- out_pCompletion->opaque[0] = 0;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIEngineGetCount, 1) (COI_ISA_TYPE isa,
- uint32_t *count)
- {
- COITRACE ("COIEngineGetCount");
- /* Features of liboffloadmic. */
- assert (isa == COI_ISA_MIC);
- assert (count != NULL);
- /* Prepare output arguments. */
- *count = num_engines;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIEngineGetHandle, 1) (COI_ISA_TYPE in_ISA,
- uint32_t in_EngineIndex,
- COIENGINE *out_pEngineHandle)
- {
- COITRACE ("COIEngineGetHandle");
- /* Features of liboffloadmic. */
- assert (in_ISA == COI_ISA_MIC);
- assert (out_pEngineHandle != NULL);
- /* Check engine index. */
- if (in_EngineIndex >= num_engines)
- COIERROR ("Wrong engine index.");
- /* Create engine handle. */
- Engine *engine = new Engine;
- engine->dir = NULL;
- engine->index = in_EngineIndex;
- engine->type = in_ISA;
- /* Prepare output argument. */
- *out_pEngineHandle = (COIENGINE) engine;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIEventWait, 1) (uint16_t in_NumEvents,
- const COIEVENT *in_pEvents,
- int32_t in_TimeoutMilliseconds,
- uint8_t in_WaitForAll,
- uint32_t *out_pNumSignaled,
- uint32_t *out_pSignaledIndices)
- {
- COITRACE ("COIEventWait");
- /* Features of liboffloadmic. */
- assert (in_pEvents != NULL);
- assert (in_TimeoutMilliseconds == 0 || in_TimeoutMilliseconds == -1);
- assert (in_WaitForAll == 1);
- assert (out_pNumSignaled == NULL);
- assert (out_pSignaledIndices == NULL);
- if (in_TimeoutMilliseconds == 0)
- {
- /* If some event is not signalled, return timeout error. */
- for (uint16_t i = 0; i < in_NumEvents; i++)
- if (non_signalled_events.count (in_pEvents[i].opaque[0]) > 0)
- return COI_TIME_OUT_REACHED;
- else
- {
- /* If the event signalled with an error, return that error. */
- start_critical_section ();
- COIRESULT res = get_event_result (in_pEvents[i]);
- finish_critical_section ();
- if (res != COI_SUCCESS)
- return res;
- }
- }
- else
- {
- /* Wait indefinitely for all events. */
- for (uint16_t i = 0; i < in_NumEvents; i++)
- {
- while (non_signalled_events.count (in_pEvents[i].opaque[0]) > 0)
- usleep (1000);
- /* If the event signalled with an error, return that error. */
- start_critical_section ();
- COIRESULT res = get_event_result (in_pEvents[i]);
- finish_critical_section ();
- if (res != COI_SUCCESS)
- return res;
- }
- }
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIEventRegisterCallback, 1) (const COIEVENT in_Event,
- COI_EVENT_CALLBACK in_Callback,
- const void *in_UserData,
- const uint64_t in_Flags)
- {
- COITRACE ("COIEventRegisterCallback");
- /* Features of liboffloadmic. */
- assert (in_Callback != NULL);
- assert (in_UserData != NULL);
- assert (in_Flags == 0);
- start_critical_section ();
- if (non_signalled_events.count (in_Event.opaque[0]) == 0)
- {
- /* If the event is already signalled, invoke the callback immediately. */
- COIRESULT res = get_event_result (in_Event);
- in_Callback (in_Event, res, in_UserData);
- }
- else
- {
- Callback callback;
- callback.ptr = in_Callback;
- callback.data = in_UserData;
- callbacks.insert (std::pair <uint64_t, Callback> (in_Event.opaque[0],
- callback));
- }
- finish_critical_section ();
- return COI_SUCCESS;
- }
- /* The start routine for the COI pipeline thread. */
- static void *
- pipeline_thread_routine (void *in_Pipeline)
- {
- /* Convert input arguments. */
- Pipeline *pipeline = (Pipeline *) in_Pipeline;
- /* Open pipes. */
- pipeline->pipe_host2tgt
- = open (pipeline->pipe_host2tgt_path, O_CLOEXEC | O_WRONLY);
- if (pipeline->pipe_host2tgt < 0)
- COIERRORN ("Cannot open host-to-target pipe.");
- pipeline->pipe_tgt2host
- = open (pipeline->pipe_tgt2host_path, O_CLOEXEC | O_RDONLY);
- if (pipeline->pipe_tgt2host < 0)
- COIERRORN ("Cannot open target-to-host pipe.");
- free (pipeline->pipe_host2tgt_path);
- free (pipeline->pipe_tgt2host_path);
- pipeline->pipe_host2tgt_path = NULL;
- pipeline->pipe_tgt2host_path = NULL;
- while (!pipeline->destroy)
- if (pipeline->queue.empty ())
- usleep (1000);
- else
- {
- Function func = pipeline->queue.front ();
- start_critical_section ();
- pipeline->queue.pop ();
- finish_critical_section ();
- /* Send data to target. */
- cmd_t cmd = CMD_PIPELINE_RUN_FUNCTION;
- WRITEN (pipeline->pipe_host2tgt, &cmd, sizeof (cmd_t));
- WRITEN (pipeline->pipe_host2tgt, &func.ptr, sizeof (void *));
- WRITEN (pipeline->pipe_host2tgt, &func.num_buffers, sizeof (uint32_t));
- for (uint32_t i = 0; i < func.num_buffers; i++)
- {
- WRITEN (pipeline->pipe_host2tgt, &func.bufs_size[i],
- sizeof (uint64_t));
- WRITEN (pipeline->pipe_host2tgt, &func.bufs_data_target[i],
- sizeof (void *));
- }
- WRITEN (pipeline->pipe_host2tgt, &func.misc_data_len,
- sizeof (uint16_t));
- if (func.misc_data_len > 0)
- WRITEN (pipeline->pipe_host2tgt, func.misc_data, func.misc_data_len);
- WRITEN (pipeline->pipe_host2tgt, &func.return_value_len,
- sizeof (uint16_t));
- delete [] func.bufs_size;
- delete [] func.bufs_data_target;
- /* Receive data from target. Wait for target function to complete,
- whether it has any data to return or not. */
- bool has_return_value = func.return_value_len > 0;
- int ret_len
- = read (pipeline->pipe_tgt2host,
- has_return_value ? func.return_value : &cmd,
- has_return_value ? func.return_value_len : sizeof (cmd_t));
- if (ret_len == 0)
- {
- start_critical_section ();
- signal_event (func.completion_event, COI_PROCESS_DIED);
- pipeline->is_destroyed = true;
- finish_critical_section ();
- return NULL;
- }
- else if (ret_len != (has_return_value ? func.return_value_len
- : sizeof (cmd_t)))
- COIERRORN ("Cannot read from pipe.");
- start_critical_section ();
- signal_event (func.completion_event, COI_SUCCESS);
- finish_critical_section ();
- }
- /* Send data to target. */
- const cmd_t cmd = CMD_PIPELINE_DESTROY;
- WRITEN (pipeline->pipe_host2tgt, &cmd, sizeof (cmd_t));
- /* Close pipes. */
- if (close (pipeline->pipe_host2tgt) < 0)
- COIERRORN ("Cannot close host-to-target pipe.");
- if (close (pipeline->pipe_tgt2host) < 0)
- COIERRORN ("Cannot close target-to-host pipe.");
- start_critical_section ();
- pipeline->is_destroyed = true;
- finish_critical_section ();
- return NULL;
- }
- COIRESULT
- SYMBOL_VERSION (COIPipelineCreate, 1) (COIPROCESS in_Process,
- COI_CPU_MASK in_Mask,
- uint32_t in_StackSize, // Ignored
- COIPIPELINE *out_pPipeline)
- {
- COITRACE ("COIPipelineCreate");
- /* Features of liboffloadmic. */
- assert (in_Process != NULL);
- assert (in_Mask == 0);
- assert (out_pPipeline != NULL);
- /* Convert input arguments. */
- Process *proc = (Process *) in_Process;
- start_critical_section ();
- /* Create pipeline handle. */
- Pipeline *pipeline = new Pipeline;
- pipeline->destroy = false;
- pipeline->is_destroyed = false;
- pipeline->process = proc;
- pipelines.insert (pipeline);
- /* Create pipes. */
- uint32_t pipeline_num = max_pipeline_num++;
- char *eng_dir = pipeline->process->engine->dir;
- MALLOC (char *, pipeline->pipe_host2tgt_path,
- strlen (eng_dir) + sizeof (PIPE_HOST2TGT_NAME "0000000000"));
- MALLOC (char *, pipeline->pipe_tgt2host_path,
- strlen (eng_dir) + sizeof (PIPE_TGT2HOST_NAME "0000000000"));
- sprintf (pipeline->pipe_host2tgt_path, "%s" PIPE_HOST2TGT_NAME "%010d",
- eng_dir, pipeline_num);
- sprintf (pipeline->pipe_tgt2host_path, "%s" PIPE_TGT2HOST_NAME "%010d",
- eng_dir, pipeline_num);
- if (mkfifo (pipeline->pipe_host2tgt_path, S_IRUSR | S_IWUSR) < 0)
- COIERROR ("Cannot create pipe %s.", pipeline->pipe_host2tgt_path);
- if (mkfifo (pipeline->pipe_tgt2host_path, S_IRUSR | S_IWUSR) < 0)
- COIERROR ("Cannot create pipe %s.", pipeline->pipe_tgt2host_path);
- /* Send data to target. */
- const cmd_t cmd = CMD_PIPELINE_CREATE;
- WRITE (proc->pipe_host2tgt, &cmd, sizeof (cmd_t));
- WRITE (proc->pipe_host2tgt, &pipeline_num, sizeof (pipeline_num));
- /* Create a new thread for the pipeline. */
- if (pthread_create (&pipeline->thread, NULL, pipeline_thread_routine,
- pipeline))
- COIERROR ("Cannot create new thread.");
- finish_critical_section ();
- /* Prepare output arguments. */
- *out_pPipeline = (COIPIPELINE) pipeline;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIPipelineDestroy, 1) (COIPIPELINE in_Pipeline)
- {
- COITRACE ("COIPipelineDestroy");
- assert (in_Pipeline != NULL);
- /* Convert input arguments. */
- Pipeline *pipeline = (Pipeline *) in_Pipeline;
- start_critical_section ();
- /* Remove pipeline from the set of undestroyed pipelines. */
- pipelines.erase (pipeline);
- /* Exit pipeline thread. */
- pipeline->destroy = true;
- finish_critical_section ();
- while (!pipeline_is_destroyed (pipeline))
- usleep (1000);
- /* Join with a destroyed thread. */
- if (pthread_join (pipeline->thread, NULL))
- COIERROR ("Cannot join with a thread.");
- delete pipeline;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIPipelineRunFunction, 1) (COIPIPELINE in_Pipeline,
- COIFUNCTION in_Function,
- uint32_t in_NumBuffers,
- const COIBUFFER *in_Buffers,
- const COI_ACCESS_FLAGS *in_pBufferAccessFlags, // Ignored
- uint32_t in_NumDependencies,
- const COIEVENT *in_pDependencies, // Ignored
- const void *in_pMiscData,
- uint16_t in_MiscDataLen,
- void *out_pAsyncReturnValue,
- uint16_t in_AsyncReturnValueLen,
- COIEVENT *out_pCompletion)
- {
- COITRACE ("COIPipelineRunFunction");
- /* Features of liboffloadmic. */
- assert (in_Pipeline != NULL);
- assert (in_Function != NULL);
- assert (in_NumDependencies == 0);
- Function func;
- func.ptr = (void *) in_Function;
- func.num_buffers = in_NumBuffers;
- func.bufs_size = new uint64_t [in_NumBuffers];
- func.bufs_data_target = new void * [in_NumBuffers];
- for (uint32_t i = 0; i < in_NumBuffers; i++)
- {
- Buffer **bufs = (Buffer **) in_Buffers;
- func.bufs_size[i] = bufs[i]->size;
- func.bufs_data_target[i] = bufs[i]->data_target;
- }
- func.misc_data = (void *) in_pMiscData;
- func.misc_data_len = in_MiscDataLen;
- func.return_value = out_pAsyncReturnValue;
- func.return_value_len = in_AsyncReturnValueLen;
- start_critical_section ();
- func.completion_event.opaque[0] = max_event_num++;
- non_signalled_events.insert (func.completion_event.opaque[0]);
- ((Pipeline *) in_Pipeline)->queue.push (func);
- finish_critical_section ();
- /* In case of synchronous execution we have to wait for target. */
- if (out_pCompletion == NULL)
- COIEventWait (1, &func.completion_event, -1, 1, NULL, NULL);
- else
- *out_pCompletion = func.completion_event;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIProcessCreateFromMemory, 1) (COIENGINE in_Engine,
- const char *in_pBinaryName,
- const void *in_pBinaryBuffer,
- uint64_t in_BinaryBufferLength,
- int in_Argc,
- const char **in_ppArgv,
- uint8_t in_DupEnv,
- const char **in_ppAdditionalEnv,
- uint8_t in_ProxyActive, // Ignored
- const char *in_Reserved, // Ignored
- uint64_t in_InitialBufferSpace, // Ignored
- const char *in_LibrarySearchPath,
- const char *in_FileOfOrigin, // Ignored
- uint64_t in_FileOfOriginOffset, // Ignored
- COIPROCESS *out_pProcess)
- {
- COITRACE ("COIProcessCreateFromMemory");
- const int run_max_args_num = 128;
- char *run_argv[run_max_args_num];
- char *emul_run = getenv (OFFLOAD_EMUL_RUN_ENV);
- const int uint_max_len = 11;
- /* Features of liboffloadmic. */
- assert (in_Engine != NULL);
- assert (in_pBinaryName != NULL);
- assert (in_pBinaryBuffer != NULL);
- assert (in_Argc == 0);
- assert (in_ppArgv == NULL);
- assert (in_ppAdditionalEnv == NULL);
- assert (in_LibrarySearchPath != NULL);
- assert (out_pProcess != NULL);
- /* Convert input arguments. */
- Engine *eng = (Engine *) in_Engine;
- /* Create temporary directory for engine files. */
- assert (eng->dir == NULL);
- STRDUP (eng->dir, ENGINE_PATH);
- if (mkdtemp (eng->dir) == NULL)
- COIERROR ("Cannot create temporary directory %s.", eng->dir);
- /* Save path to engine directory for clean up on exit. */
- tmp_dirs_num++;
- tmp_dirs = (char **) realloc (tmp_dirs, tmp_dirs_num * sizeof (char *));
- if (!tmp_dirs)
- COIERROR ("Cannot allocate memory.");
- STRDUP (tmp_dirs[tmp_dirs_num - 1], eng->dir);
- /* Create target executable file. */
- char *target_exe;
- MALLOC (char *, target_exe, strlen (eng->dir) + strlen (in_pBinaryName) + 2);
- sprintf (target_exe, "%s/%s", eng->dir, in_pBinaryName);
- int fd = open (target_exe, O_CLOEXEC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
- if (fd < 0)
- COIERROR ("Cannot create file %s.", target_exe);
- FILE *file = fdopen (fd, "wb");
- if (file == NULL)
- COIERROR ("Cannot associate stream with file descriptor.");
- if (fwrite (in_pBinaryBuffer, 1, in_BinaryBufferLength, file)
- != in_BinaryBufferLength)
- COIERROR ("Cannot write in file %s.", target_exe);
- if (fclose (file) != 0)
- COIERROR ("Cannot close file %s.", target_exe);
- /* Fix file permissions. */
- if (chmod (target_exe, S_IRWXU) < 0)
- COIERROR ("Cannot change permissions for file %s.", target_exe);
- /* Create directory for pipes to prevent names collision. */
- char *pipes_path;
- MALLOC (char *, pipes_path, strlen (eng->dir) + sizeof (PIPES_PATH));
- sprintf (pipes_path, "%s" PIPES_PATH, eng->dir);
- if (mkdir (pipes_path, S_IRWXU) < 0)
- COIERROR ("Cannot create folder %s.", pipes_path);
- /* Create 2 main pipes for inter-process communication. */
- char *pipe_host2tgt_path, *pipe_tgt2host_path;
- MALLOC (char *, pipe_host2tgt_path,
- strlen (eng->dir) + sizeof (PIPE_HOST2TGT_NAME "mainpipe"));
- MALLOC (char *, pipe_tgt2host_path,
- strlen (eng->dir) + sizeof (PIPE_TGT2HOST_NAME "mainpipe"));
- sprintf (pipe_host2tgt_path, "%s" PIPE_HOST2TGT_NAME "mainpipe", eng->dir);
- sprintf (pipe_tgt2host_path, "%s" PIPE_TGT2HOST_NAME "mainpipe", eng->dir);
- if (mkfifo (pipe_host2tgt_path, S_IRUSR | S_IWUSR) < 0)
- COIERROR ("Cannot create main pipe %s.", pipe_host2tgt_path);
- if (mkfifo (pipe_tgt2host_path, S_IRUSR | S_IWUSR) < 0)
- COIERROR ("Cannot create main pipe %s.", pipe_tgt2host_path);
- /* Prepare argv. */
- if (emul_run == NULL || strcmp (emul_run, "") == 0)
- {
- STRDUP (run_argv[0], target_exe);
- run_argv[1] = (char *) NULL;
- }
- else
- {
- char *ptr, *tmp;
- int i = 0;
- STRDUP (tmp, emul_run);
- char *tok = strtok_r (tmp, " ", &ptr);
- while (tok != NULL)
- {
- if (i >= run_max_args_num)
- COIERROR ("Run command has too many arguments.");
- STRDUP (run_argv[i++], tok);
- tok = strtok_r (NULL, " ", &ptr);
- }
- STRDUP (run_argv[i], target_exe);
- run_argv[i + 1] = (char *) NULL;
- free (tmp);
- }
- /* Prepare envp. */
- int env_num = 0;
- if (in_DupEnv == true)
- while (environ[env_num++]);
- env_num += 4; // LD_LIBRARY_PATH, MIC_DIR, MIC_INDEX, NULL
- char **envp;
- MALLOC (char **, envp, env_num * sizeof (char *));
- int env_i = 0;
- if (in_DupEnv == true)
- for (unsigned i = 0; environ[i] != NULL; i++)
- {
- unsigned j;
- char *env_name;
- STRDUP (env_name, environ[i]);
- for (j = 0; env_name[j] != '=' && env_name[j] != '\0'; j++);
- env_name[j] = '\0';
- if (strcmp (env_name, "LD_LIBRARY_PATH") != 0
- && strcmp (env_name, MIC_DIR_ENV) != 0
- && strcmp (env_name, MIC_INDEX_ENV) != 0)
- STRDUP (envp[env_i++], environ[i]);
- free (env_name);
- }
- MALLOC (char *, envp[env_i], strlen (MIC_DIR_ENV) + strlen (eng->dir) + 2);
- sprintf (envp[env_i], "%s=%s", MIC_DIR_ENV, eng->dir);
- MALLOC (char *, envp[env_i + 1], strlen (MIC_INDEX_ENV) + uint_max_len + 1);
- sprintf (envp[env_i + 1], "%s=%u", MIC_INDEX_ENV, eng->index);
- MALLOC (char *, envp[env_i + 2],
- strlen ("LD_LIBRARY_PATH=") + strlen (in_LibrarySearchPath) + 1);
- sprintf (envp[env_i + 2], "LD_LIBRARY_PATH=%s", in_LibrarySearchPath);
- envp[env_i + 3] = (char *) NULL;
- /* Create target process. */
- pid_t pid = vfork ();
- if (pid < 0)
- COIERROR ("Cannot create child process.");
- if (pid == 0)
- {
- /* Run target executable. */
- if (execvpe (run_argv[0], run_argv, envp) == -1)
- COIERROR ("Cannot execute file %s.", target_exe);
- }
- /* Open main pipes. */
- int pipe_host2tgt = open (pipe_host2tgt_path, O_CLOEXEC | O_WRONLY);
- if (pipe_host2tgt < 0)
- COIERROR ("Cannot open host-to-target main pipe.");
- int pipe_tgt2host = open (pipe_tgt2host_path, O_CLOEXEC | O_RDONLY);
- if (pipe_tgt2host < 0)
- COIERROR ("Cannot open target-to-host main pipe.");
- /* Create process handle. */
- Process *proc = new Process;
- proc->pid = pid;
- proc->pipe_host2tgt = pipe_host2tgt;
- proc->pipe_tgt2host = pipe_tgt2host;
- proc->engine = eng;
- proc->functions = NULL;
- /* Prepare output arguments. */
- *out_pProcess = (COIPROCESS) proc;
- /* Clean up. */
- for (unsigned i = 0; run_argv[i] != NULL; i++)
- free (run_argv[i]);
- for (unsigned i = 0; envp[i] != NULL; i++)
- free (envp[i]);
- free (envp);
- free (pipe_host2tgt_path);
- free (pipe_tgt2host_path);
- free (pipes_path);
- free (target_exe);
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIProcessCreateFromFile, 1) (COIENGINE in_Engine,
- const char *in_pBinaryName,
- int in_Argc,
- const char **in_ppArgv,
- uint8_t in_DupEnv,
- const char **in_ppAdditionalEnv,
- uint8_t in_ProxyActive,
- const char *in_Reserved,
- uint64_t in_BufferSpace,
- const char *in_LibrarySearchPath,
- COIPROCESS *out_pProcess)
- {
- COITRACE ("COIProcessCreateFromFile");
- /* liboffloadmic with GCC compiled binaries should never go here. */
- assert (false);
- return COI_ERROR;
- }
- COIRESULT
- SYMBOL_VERSION (COIProcessDestroy, 1) (COIPROCESS in_Process,
- int32_t in_WaitForMainTimeout, // Ignored
- uint8_t in_ForceDestroy,
- int8_t *out_pProcessReturn,
- uint32_t *out_pTerminationCode)
- {
- COITRACE ("COIProcessDestroy");
- assert (in_Process != NULL);
- assert (out_pProcessReturn != NULL);
- assert (out_pTerminationCode != NULL);
- /* Convert input arguments. */
- Process *proc = (Process *) in_Process;
- /* Destroy all undestroyed pipelines. */
- while (!pipelines.empty ())
- {
- std::set<Pipeline *>::iterator p = pipelines.begin ();
- COIPipelineDestroy ((COIPIPELINE) *p);
- }
- /* Close main pipes. */
- if (close (proc->pipe_host2tgt) < 0)
- COIERROR ("Cannot close host-to-target main pipe.");
- if (close (proc->pipe_tgt2host) < 0)
- COIERROR ("Cannot close target-to-host main pipe.");
- /* Shutdown target process by force. */
- if (in_ForceDestroy)
- kill (proc->pid, SIGTERM);
- /* Clean up. */
- free (proc->engine->dir);
- free (proc->functions);
- delete proc->engine;
- delete proc;
- /* Prepare output arguments. */
- *out_pProcessReturn = 0;
- *out_pTerminationCode = 0;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIProcessGetFunctionHandles, 1) (COIPROCESS in_Process,
- uint32_t in_NumFunctions,
- const char **in_ppFunctionNameArray,
- COIFUNCTION *out_pFunctionHandleArray)
- {
- COITRACE ("COIProcessGetFunctionHandles");
- assert (in_Process != NULL);
- assert (in_ppFunctionNameArray != NULL);
- assert (out_pFunctionHandleArray != NULL);
- /* Convert input arguments. */
- Process *proc = (Process *) in_Process;
- /* This function should be called once for the process. */
- assert (proc->functions == NULL);
- /* Create array of function pointers. Last element is 0, what shows the end
- of the array. This array is used to free memory when process is
- destroyed. */
- proc->functions = (void **) calloc (in_NumFunctions + 1, sizeof (void *));
- if (proc->functions == NULL)
- COIERROR ("Cannot allocate memory.");
- /* Get handles for functions. */
- for (uint32_t i = 0; i < in_NumFunctions; i++)
- {
- size_t len = strlen (in_ppFunctionNameArray[i]) + 1;
- start_critical_section ();
- /* Send data to target. */
- const cmd_t cmd = CMD_GET_FUNCTION_HANDLE;
- WRITE (proc->pipe_host2tgt, &cmd, sizeof (cmd_t));
- WRITE (proc->pipe_host2tgt, &len, sizeof (size_t));
- WRITE (proc->pipe_host2tgt, in_ppFunctionNameArray[i], len);
- /* Receive data from target. */
- void *fn_ptr;
- READ (proc->pipe_tgt2host, &fn_ptr, sizeof (void *));
- finish_critical_section ();
- /* Save function pointer. */
- proc->functions[i] = fn_ptr;
- /* Prepare output arguments. */
- out_pFunctionHandleArray[i] = (COIFUNCTION) fn_ptr;
- }
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIProcessLoadLibraryFromMemory, 2) (COIPROCESS in_Process,
- const void *in_pLibraryBuffer,
- uint64_t in_LibraryBufferLength,
- const char *in_pLibraryName,
- const char *in_LibrarySearchPath, // Ignored
- const char *in_FileOfOrigin, // Ignored
- uint64_t in_FileOfOriginOffset, // Ignored
- uint32_t in_Flags, // Ignored
- COILIBRARY *out_pLibrary)
- {
- COITRACE ("COIProcessLoadLibraryFromMemory");
- assert (in_Process != NULL);
- assert (in_pLibraryBuffer != NULL);
- assert (out_pLibrary != NULL);
- /* Convert input arguments. */
- Process *proc = (Process *) in_Process;
- /* Create target library file. */
- char *lib_path;
- size_t len = strlen (proc->engine->dir) + strlen (in_pLibraryName) + 2;
- MALLOC (char *, lib_path, len);
- sprintf (lib_path, "%s/%s", proc->engine->dir, in_pLibraryName);
- int fd = open (lib_path, O_CLOEXEC | O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
- if (fd < 0)
- COIERROR ("Cannot create file %s.", lib_path);
- FILE *file = fdopen (fd, "wb");
- if (file == NULL)
- COIERROR ("Cannot associate stream with file descriptor.");
- if (fwrite (in_pLibraryBuffer, 1, in_LibraryBufferLength, file)
- != in_LibraryBufferLength)
- COIERROR ("Cannot write in file %s.", lib_path);
- if (fclose (file) != 0)
- COIERROR ("Cannot close file %s.", lib_path);
- start_critical_section ();
- /* Make target open library. */
- const cmd_t cmd = CMD_OPEN_LIBRARY;
- WRITE (proc->pipe_host2tgt, &cmd, sizeof (cmd_t));
- WRITE (proc->pipe_host2tgt, &len, sizeof (size_t));
- WRITE (proc->pipe_host2tgt, lib_path, len);
- /* Receive data from target. */
- void *handle;
- READ (proc->pipe_tgt2host, &handle, sizeof (void *));
- finish_critical_section ();
- /* Clean up. */
- free (lib_path);
- *out_pLibrary = (COILIBRARY) handle;
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIProcessRegisterLibraries, 1) (uint32_t in_NumLibraries, // Ignored
- const void **in_ppLibraryArray, // Ignored
- const uint64_t *in_pLibrarySizeArray, // Ignored
- const char **in_ppFileOfOriginArray, // Ignored
- const uint64_t *in_pFileOfOriginOffSetArray) // Ignored
- {
- COITRACE ("COIProcessRegisterLibraries");
- /* Looks like we have nothing to do here. */
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIProcessUnloadLibrary, 1) (COIPROCESS in_Process,
- COILIBRARY in_Library)
- {
- COITRACE ("COIProcessUnloadLibrary");
- assert (in_Process != NULL);
- assert (in_Library != NULL);
- const cmd_t cmd = CMD_CLOSE_LIBRARY;
- /* Convert input arguments. */
- Process *proc = (Process *) in_Process;
- start_critical_section ();
- /* Make target close library. */
- WRITE (proc->pipe_host2tgt, &cmd, sizeof (cmd_t));
- WRITE (proc->pipe_host2tgt, &in_Library, sizeof (void *));
- finish_critical_section ();
- return COI_SUCCESS;
- }
- uint64_t
- SYMBOL_VERSION (COIPerfGetCycleFrequency, 1) ()
- {
- COITRACE ("COIPerfGetCycleFrequency");
- return (uint64_t) CYCLE_FREQUENCY;
- }
- COIRESULT
- SYMBOL_VERSION (COIPipelineClearCPUMask, 1) (COI_CPU_MASK *in_Mask)
- {
- COITRACE ("COIPipelineClearCPUMask");
- /* Looks like we have nothing to do here. */
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIPipelineSetCPUMask, 1) (COIPROCESS in_Process,
- uint32_t in_CoreID,
- uint8_t in_ThreadID,
- COI_CPU_MASK *out_pMask)
- {
- COITRACE ("COIPipelineSetCPUMask");
- /* Looks like we have nothing to do here. */
- return COI_SUCCESS;
- }
- COIRESULT
- SYMBOL_VERSION (COIEngineGetInfo, 1) (COIENGINE in_EngineHandle, // Ignored
- uint32_t in_EngineInfoSize, // Ignored
- COI_ENGINE_INFO *out_pEngineInfo)
- {
- COITRACE ("COIEngineGetInfo");
- assert (out_pEngineInfo != NULL);
- out_pEngineInfo->ISA = COI_DEVICE_KNL;
- out_pEngineInfo->NumCores = 1;
- out_pEngineInfo->NumThreads = 8;
- out_pEngineInfo->CoreMaxFrequency = SYMBOL_VERSION(COIPerfGetCycleFrequency,1)() / 1000000;
- out_pEngineInfo->PhysicalMemory = 1024;
- out_pEngineInfo->PhysicalMemoryFree = 1024;
- out_pEngineInfo->SwapMemory = 1024;
- out_pEngineInfo->SwapMemoryFree = 1024;
- out_pEngineInfo->MiscFlags = COI_ENG_ECC_DISABLED;
- return COI_SUCCESS;
- }
- } // extern "C"
|