diff --git a/sycl/plugins/level_zero/pi_level_zero.cpp b/sycl/plugins/level_zero/pi_level_zero.cpp index 06d5e5517273a..ac3a6202e5986 100644 --- a/sycl/plugins/level_zero/pi_level_zero.cpp +++ b/sycl/plugins/level_zero/pi_level_zero.cpp @@ -924,18 +924,12 @@ pi_result _pi_ze_event_list_t::createAndRetainPiZeEventList( this->ZeEventList = nullptr; this->PiEventList = nullptr; - try { - if (CurQueue->isInOrderQueue() && CurQueue->LastCommandEvent != nullptr) { - this->ZeEventList = new ze_event_handle_t[EventListLength + 1]; - this->PiEventList = new pi_event[EventListLength + 1]; - } else if (EventListLength > 0) { + if (EventListLength > 0) { + try { this->ZeEventList = new ze_event_handle_t[EventListLength]; this->PiEventList = new pi_event[EventListLength]; - } + pi_uint32 TmpListLength = 0; - pi_uint32 TmpListLength = 0; - - if (EventListLength > 0) { for (pi_uint32 I = 0; I < EventListLength; I++) { auto ZeEvent = EventList[I]->ZeEvent; @@ -967,25 +961,15 @@ pi_result _pi_ze_event_list_t::createAndRetainPiZeEventList( this->PiEventList[TmpListLength] = EventList[I]; TmpListLength += 1; } - } - // For in-order queues, every command should be executed once after the - // previous command has finished. The event associated with the last - // enqued command is added into the waitlist to ensure in-order semantics. - if (CurQueue->isInOrderQueue() && CurQueue->LastCommandEvent != nullptr) { - this->ZeEventList[TmpListLength] = CurQueue->LastCommandEvent->ZeEvent; - this->PiEventList[TmpListLength] = CurQueue->LastCommandEvent; - TmpListLength += 1; + this->Length = TmpListLength; + } catch (...) { + return PI_OUT_OF_HOST_MEMORY; } - this->Length = TmpListLength; - - } catch (...) { - return PI_OUT_OF_HOST_MEMORY; - } - - for (pi_uint32 I = 0; I < this->Length; I++) { - PI_CALL(piEventRetain(this->PiEventList[I])); + for (pi_uint32 I = 0; I < this->Length; I++) { + PI_CALL(piEventRetain(this->PiEventList[I])); + } } return PI_SUCCESS; @@ -3729,6 +3713,11 @@ piEnqueueKernelLaunch(pi_queue Queue, pi_kernel Kernel, pi_uint32 WorkDim, PI_ASSERT(Event, PI_INVALID_EVENT); PI_ASSERT((WorkDim > 0) && (WorkDim < 4), PI_INVALID_WORK_DIMENSION); + _pi_ze_event_list_t TmpWaitList; + if (auto Res = TmpWaitList.createAndRetainPiZeEventList(NumEventsInWaitList, + EventWaitList, Queue)) + return Res; + if (GlobalWorkOffset != NULL) { for (pi_uint32 i = 0; i < WorkDim; i++) { if (GlobalWorkOffset[i] != 0) { @@ -3804,12 +3793,6 @@ piEnqueueKernelLaunch(pi_queue Queue, pi_kernel Kernel, pi_uint32 WorkDim, // Lock automatically releases when this goes out of scope. std::lock_guard lock(Queue->PiQueueMutex); - _pi_ze_event_list_t TmpWaitList; - - if (auto Res = TmpWaitList.createAndRetainPiZeEventList(NumEventsInWaitList, - EventWaitList, Queue)) - return Res; - // Get a new command list to be used on this call ze_command_list_handle_t ZeCommandList = nullptr; ze_fence_handle_t ZeFence = nullptr; @@ -3847,8 +3830,6 @@ piEnqueueKernelLaunch(pi_queue Queue, pi_kernel Kernel, pi_uint32 WorkDim, pi_cast(ZeEvent)); printZeEventList((*Event)->WaitList); - Queue->LastCommandEvent = *Event; - // Execute command list asynchronously, as the event will be used // to track down its completion. if (auto Res = Queue->executeCommandList(ZeCommandList, ZeFence, false, true)) @@ -4094,7 +4075,6 @@ pi_result piEventsWait(pi_uint32 NumEvents, const pi_event *EventList) { // sooner in case run-time is not calling piEventRelease soon enough. cleanupAfterEvent(EventList[I]); } - return PI_SUCCESS; } @@ -4332,14 +4312,14 @@ pi_result piEnqueueEventsWait(pi_queue Queue, pi_uint32 NumEventsInWaitList, if (EventWaitList) { PI_ASSERT(NumEventsInWaitList > 0, PI_INVALID_VALUE); - // Lock automatically releases when this goes out of scope. - std::lock_guard lock(Queue->PiQueueMutex); - _pi_ze_event_list_t TmpWaitList = {}; if (auto Res = TmpWaitList.createAndRetainPiZeEventList( NumEventsInWaitList, EventWaitList, Queue)) return Res; + // Lock automatically releases when this goes out of scope. + std::lock_guard lock(Queue->PiQueueMutex); + // Get a new command list to be used on this call ze_command_list_handle_t ZeCommandList = nullptr; ze_fence_handle_t ZeFence = nullptr; @@ -4361,8 +4341,6 @@ pi_result piEnqueueEventsWait(pi_queue Queue, pi_uint32 NumEventsInWaitList, ZE_CALL(zeCommandListAppendSignalEvent, (ZeCommandList, ZeEvent)); - Queue->LastCommandEvent = *Event; - // Execute command list asynchronously as the event will be used // to track down its completion. return Queue->executeCommandList(ZeCommandList, ZeFence); @@ -4372,10 +4350,6 @@ pi_result piEnqueueEventsWait(pi_queue Queue, pi_uint32 NumEventsInWaitList, // all previous enqueued commands to the command-queue have completed. // // TODO: find a way to do that without blocking the host. - - // Lock automatically releases when this goes out of scope. - std::lock_guard lock(Queue->PiQueueMutex); - auto Res = createEventAndAssociateQueue(Queue, Event, PI_COMMAND_TYPE_USER, nullptr); if (Res != PI_SUCCESS) @@ -4385,8 +4359,6 @@ pi_result piEnqueueEventsWait(pi_queue Queue, pi_uint32 NumEventsInWaitList, if (Queue->ZeCopyCommandQueue) ZE_CALL(zeHostSynchronize, (Queue->ZeCopyCommandQueue)); - Queue->LastCommandEvent = *Event; - ZE_CALL(zeEventHostSignal, ((*Event)->ZeEvent)); return PI_SUCCESS; } @@ -4398,14 +4370,14 @@ pi_result piEnqueueEventsWaitWithBarrier(pi_queue Queue, PI_ASSERT(Queue, PI_INVALID_QUEUE); PI_ASSERT(Event, PI_INVALID_EVENT); - // Lock automatically releases when this goes out of scope. - std::lock_guard lock(Queue->PiQueueMutex); - _pi_ze_event_list_t TmpWaitList; if (auto Res = TmpWaitList.createAndRetainPiZeEventList(NumEventsInWaitList, EventWaitList, Queue)) return Res; + // Lock automatically releases when this goes out of scope. + std::lock_guard lock(Queue->PiQueueMutex); + // Get a new command list to be used on this call ze_command_list_handle_t ZeCommandList = nullptr; ze_fence_handle_t ZeFence = nullptr; @@ -4425,8 +4397,6 @@ pi_result piEnqueueEventsWaitWithBarrier(pi_queue Queue, (ZeCommandList, ZeEvent, (*Event)->WaitList.Length, (*Event)->WaitList.ZeEventList)); - Queue->LastCommandEvent = *Event; - // Execute command list asynchronously as the event will be used // to track down its completion. return Queue->executeCommandList(ZeCommandList, ZeFence); @@ -4479,14 +4449,14 @@ static pi_result enqueueMemCopyHelper(pi_command_type CommandType, PI_ASSERT(Queue, PI_INVALID_QUEUE); PI_ASSERT(Event, PI_INVALID_EVENT); - // Lock automatically releases when this goes out of scope. - std::lock_guard lock(Queue->PiQueueMutex); - _pi_ze_event_list_t TmpWaitList; if (auto Res = TmpWaitList.createAndRetainPiZeEventList(NumEventsInWaitList, EventWaitList, Queue)) return Res; + // Lock automatically releases when this goes out of scope. + std::lock_guard lock(Queue->PiQueueMutex); + // Get a new command list to be used on this call ze_command_list_handle_t ZeCommandList = nullptr; ze_fence_handle_t ZeFence = nullptr; @@ -4504,7 +4474,6 @@ static pi_result enqueueMemCopyHelper(pi_command_type CommandType, const auto &WaitList = (*Event)->WaitList; if (WaitList.Length) { - ZE_CALL(zeCommandListAppendWaitOnEvents, (ZeCommandList, WaitList.Length, WaitList.ZeEventList)); } @@ -4517,8 +4486,6 @@ static pi_result enqueueMemCopyHelper(pi_command_type CommandType, pi_cast(ZeEvent)); printZeEventList(WaitList); - Queue->LastCommandEvent = *Event; - if (auto Res = Queue->executeCommandList(ZeCommandList, ZeFence, BlockingWrite)) return Res; @@ -4539,14 +4506,13 @@ static pi_result enqueueMemCopyRectHelper( PI_ASSERT(Region && SrcOrigin && DstOrigin && Queue, PI_INVALID_VALUE); PI_ASSERT(Event, PI_INVALID_EVENT); - // Lock automatically releases when this goes out of scope. - std::lock_guard lock(Queue->PiQueueMutex); - _pi_ze_event_list_t TmpWaitList; if (auto Res = TmpWaitList.createAndRetainPiZeEventList(NumEventsInWaitList, EventWaitList, Queue)) return Res; + // Lock automatically releases when this goes out of scope. + std::lock_guard lock(Queue->PiQueueMutex); // Get a new command list to be used on this call ze_command_list_handle_t ZeCommandList = nullptr; ze_fence_handle_t ZeFence = nullptr; @@ -4563,7 +4529,6 @@ static pi_result enqueueMemCopyRectHelper( (*Event)->WaitList = TmpWaitList; const auto &WaitList = (*Event)->WaitList; - if (WaitList.Length) { ZE_CALL(zeCommandListAppendWaitOnEvents, (ZeCommandList, WaitList.Length, WaitList.ZeEventList)); @@ -4616,8 +4581,6 @@ static pi_result enqueueMemCopyRectHelper( zePrint("calling zeCommandListAppendBarrier() with Event %#lx\n", pi_cast(ZeEvent)); - Queue->LastCommandEvent = *Event; - if (auto Res = Queue->executeCommandList(ZeCommandList, ZeFence, Blocking)) return Res; @@ -4714,14 +4677,14 @@ enqueueMemFillHelper(pi_command_type CommandType, pi_queue Queue, void *Ptr, PI_ASSERT(Queue, PI_INVALID_QUEUE); PI_ASSERT(Event, PI_INVALID_EVENT); - // Lock automatically releases when this goes out of scope. - std::lock_guard lock(Queue->PiQueueMutex); - _pi_ze_event_list_t TmpWaitList; if (auto Res = TmpWaitList.createAndRetainPiZeEventList(NumEventsInWaitList, EventWaitList, Queue)) return Res; + // Lock automatically releases when this goes out of scope. + std::lock_guard lock(Queue->PiQueueMutex); + // Get a new command list to be used on this call ze_command_list_handle_t ZeCommandList = nullptr; ze_fence_handle_t ZeFence = nullptr; @@ -4740,7 +4703,6 @@ enqueueMemFillHelper(pi_command_type CommandType, pi_queue Queue, void *Ptr, (*Event)->WaitList = TmpWaitList; const auto &WaitList = (*Event)->WaitList; - if (WaitList.Length) { ZE_CALL(zeCommandListAppendWaitOnEvents, (ZeCommandList, WaitList.Length, WaitList.ZeEventList)); @@ -4758,8 +4720,6 @@ enqueueMemFillHelper(pi_command_type CommandType, pi_queue Queue, void *Ptr, pi_cast(ZeEvent)); printZeEventList(WaitList); - Queue->LastCommandEvent = *Event; - // Execute command list asynchronously, as the event will be used // to track down its completion. if (auto Res = Queue->executeCommandList(ZeCommandList, ZeFence)) @@ -4800,7 +4760,12 @@ pi_result piEnqueueMemBufferMap(pi_queue Queue, pi_mem Buffer, PI_ASSERT(Queue, PI_INVALID_QUEUE); PI_ASSERT(Event, PI_INVALID_EVENT); - // For integrated devices we don't need a commandlist + _pi_ze_event_list_t TmpWaitList; + if (auto Res = TmpWaitList.createAndRetainPiZeEventList(NumEventsInWaitList, + EventWaitList, Queue)) + return Res; + + // For discrete devices we don't need a commandlist ze_command_list_handle_t ZeCommandList = nullptr; ze_fence_handle_t ZeFence = nullptr; ze_event_handle_t ZeEvent = nullptr; @@ -4809,11 +4774,6 @@ pi_result piEnqueueMemBufferMap(pi_queue Queue, pi_mem Buffer, // Lock automatically releases when this goes out of scope. std::lock_guard lock(Queue->PiQueueMutex); - _pi_ze_event_list_t TmpWaitList; - if (auto Res = TmpWaitList.createAndRetainPiZeEventList( - NumEventsInWaitList, EventWaitList, Queue)) - return Res; - auto Res = createEventAndAssociateQueue( Queue, Event, PI_COMMAND_TYPE_MEM_BUFFER_MAP, ZeCommandList); if (Res != PI_SUCCESS) @@ -4838,21 +4798,6 @@ pi_result piEnqueueMemBufferMap(pi_queue Queue, pi_mem Buffer, if (Buffer->OnHost) { // Wait on incoming events before doing the copy PI_CALL(piEventsWait(NumEventsInWaitList, EventWaitList)); - - if (Queue->isInOrderQueue()) { - pi_event TmpLastCommandEvent = nullptr; - - { - // Lock automatically releases when this goes out of scope. - std::lock_guard lock(Queue->PiQueueMutex); - TmpLastCommandEvent = Queue->LastCommandEvent; - } - - if (TmpLastCommandEvent != nullptr) { - PI_CALL(piEventsWait(1, &TmpLastCommandEvent)); - } - } - if (Buffer->MapHostPtr) { *RetMap = Buffer->MapHostPtr + Offset; if (!(MapFlags & PI_MAP_WRITE_INVALIDATE_REGION)) @@ -4891,19 +4836,15 @@ pi_result piEnqueueMemBufferMap(pi_queue Queue, pi_mem Buffer, } const auto &WaitList = (*Event)->WaitList; - if (WaitList.Length) { ZE_CALL(zeCommandListAppendWaitOnEvents, (ZeCommandList, WaitList.Length, WaitList.ZeEventList)); } - ZE_CALL(zeCommandListAppendMemoryCopy, (ZeCommandList, *RetMap, pi_cast(Buffer->getZeHandle()) + Offset, Size, ZeEvent, 0, nullptr)); - Queue->LastCommandEvent = *Event; - if (auto Res = Queue->executeCommandList(ZeCommandList, ZeFence, BlockingMap)) return Res; @@ -4916,6 +4857,11 @@ pi_result piEnqueueMemUnmap(pi_queue Queue, pi_mem MemObj, void *MappedPtr, PI_ASSERT(Queue, PI_INVALID_QUEUE); PI_ASSERT(Event, PI_INVALID_EVENT); + _pi_ze_event_list_t TmpWaitList; + if (auto Res = TmpWaitList.createAndRetainPiZeEventList(NumEventsInWaitList, + EventWaitList, Queue)) + return Res; + // Integrated devices don't need a command list. // If discrete we will get a commandlist later. ze_command_list_handle_t ZeCommandList = nullptr; @@ -4931,11 +4877,6 @@ pi_result piEnqueueMemUnmap(pi_queue Queue, pi_mem MemObj, void *MappedPtr, // Lock automatically releases when this goes out of scope. std::lock_guard lock(Queue->PiQueueMutex); - _pi_ze_event_list_t TmpWaitList; - if (auto Res = TmpWaitList.createAndRetainPiZeEventList( - NumEventsInWaitList, EventWaitList, Queue)) - return Res; - auto Res = createEventAndAssociateQueue( Queue, Event, PI_COMMAND_TYPE_MEM_BUFFER_UNMAP, ZeCommandList); if (Res != PI_SUCCESS) @@ -4962,21 +4903,6 @@ pi_result piEnqueueMemUnmap(pi_queue Queue, pi_mem MemObj, void *MappedPtr, if (MemObj->OnHost) { // Wait on incoming events before doing the copy PI_CALL(piEventsWait(NumEventsInWaitList, EventWaitList)); - - if (Queue->isInOrderQueue()) { - pi_event TmpLastCommandEvent = nullptr; - - { - // Lock automatically releases when this goes out of scope. - std::lock_guard lock(Queue->PiQueueMutex); - TmpLastCommandEvent = Queue->LastCommandEvent; - } - - if (TmpLastCommandEvent != nullptr) { - PI_CALL(piEventsWait(1, &TmpLastCommandEvent)); - } - } - if (MemObj->MapHostPtr) memcpy(pi_cast(MemObj->getZeHandle()) + MapInfo.Offset, MappedPtr, MapInfo.Size); @@ -5002,7 +4928,6 @@ pi_result piEnqueueMemUnmap(pi_queue Queue, pi_mem MemObj, void *MappedPtr, (ZeCommandList, (*Event)->WaitList.Length, (*Event)->WaitList.ZeEventList)); } - // TODO: Level Zero is missing the memory "mapping" capabilities, so we are // left to doing copy (write back to the device). // @@ -5014,8 +4939,6 @@ pi_result piEnqueueMemUnmap(pi_queue Queue, pi_mem MemObj, void *MappedPtr, pi_cast(MemObj->getZeHandle()) + MapInfo.Offset, MappedPtr, MapInfo.Size, ZeEvent, 0, nullptr)); - Queue->LastCommandEvent = *Event; - // Execute command list asynchronously, as the event will be used // to track down its completion. if (auto Res = Queue->executeCommandList(ZeCommandList, ZeFence)) @@ -5094,14 +5017,14 @@ static pi_result enqueueMemImageCommandHelper( PI_ASSERT(Queue, PI_INVALID_QUEUE); PI_ASSERT(Event, PI_INVALID_EVENT); - // Lock automatically releases when this goes out of scope. - std::lock_guard lock(Queue->PiQueueMutex); - _pi_ze_event_list_t TmpWaitList; if (auto Res = TmpWaitList.createAndRetainPiZeEventList(NumEventsInWaitList, EventWaitList, Queue)) return Res; + // Lock automatically releases when this goes out of scope. + std::lock_guard lock(Queue->PiQueueMutex); + // Get a new command list to be used on this call ze_command_list_handle_t ZeCommandList = nullptr; ze_fence_handle_t ZeFence = nullptr; @@ -5118,7 +5041,6 @@ static pi_result enqueueMemImageCommandHelper( (*Event)->WaitList = TmpWaitList; const auto &WaitList = (*Event)->WaitList; - if (WaitList.Length) { ZE_CALL(zeCommandListAppendWaitOnEvents, (ZeCommandList, WaitList.Length, WaitList.ZeEventList)); @@ -5212,8 +5134,6 @@ static pi_result enqueueMemImageCommandHelper( return PI_INVALID_OPERATION; } - Queue->LastCommandEvent = *Event; - if (auto Res = Queue->executeCommandList(ZeCommandList, ZeFence, IsBlocking)) return Res; @@ -5711,14 +5631,14 @@ pi_result piextUSMEnqueuePrefetch(pi_queue Queue, const void *Ptr, size_t Size, PI_ASSERT(Queue, PI_INVALID_QUEUE); PI_ASSERT(Event, PI_INVALID_EVENT); - // Lock automatically releases when this goes out of scope. - std::lock_guard lock(Queue->PiQueueMutex); - _pi_ze_event_list_t TmpWaitList; if (auto Res = TmpWaitList.createAndRetainPiZeEventList(NumEventsInWaitList, EventWaitList, Queue)) return Res; + // Lock automatically releases when this goes out of scope. + std::lock_guard lock(Queue->PiQueueMutex); + // Get a new command list to be used on this call ze_command_list_handle_t ZeCommandList = nullptr; ze_fence_handle_t ZeFence = nullptr; @@ -5741,7 +5661,6 @@ pi_result piextUSMEnqueuePrefetch(pi_queue Queue, const void *Ptr, size_t Size, return Res; const auto &WaitList = (*Event)->WaitList; - if (WaitList.Length) { ZE_CALL(zeCommandListAppendWaitOnEvents, (ZeCommandList, WaitList.Length, WaitList.ZeEventList)); @@ -5753,8 +5672,6 @@ pi_result piextUSMEnqueuePrefetch(pi_queue Queue, const void *Ptr, size_t Size, // so manually add command to signal our event. ZE_CALL(zeCommandListAppendSignalEvent, (ZeCommandList, ZeEvent)); - Queue->LastCommandEvent = *Event; - if (auto Res = Queue->executeCommandList(ZeCommandList, ZeFence, false)) return Res; @@ -5798,22 +5715,9 @@ pi_result piextUSMEnqueueMemAdvise(pi_queue Queue, const void *Ptr, return Res; ZeEvent = (*Event)->ZeEvent; - if (auto Res = - (*Event)->WaitList.createAndRetainPiZeEventList(0, nullptr, Queue)) - return Res; - - const auto &WaitList = (*Event)->WaitList; - - if (WaitList.Length) { - ZE_CALL(zeCommandListAppendWaitOnEvents, - (ZeCommandList, WaitList.Length, WaitList.ZeEventList)); - } - ZE_CALL(zeCommandListAppendMemAdvise, (ZeCommandList, Queue->Device->ZeDevice, Ptr, Length, ZeAdvice)); - Queue->LastCommandEvent = *Event; - // TODO: Level Zero does not have a completion "event" with the advise API, // so manually add command to signal our event. ZE_CALL(zeCommandListAppendSignalEvent, (ZeCommandList, ZeEvent)); diff --git a/sycl/plugins/level_zero/pi_level_zero.hpp b/sycl/plugins/level_zero/pi_level_zero.hpp index 704b25330a352..16fcc805daad8 100644 --- a/sycl/plugins/level_zero/pi_level_zero.hpp +++ b/sycl/plugins/level_zero/pi_level_zero.hpp @@ -331,12 +331,6 @@ struct _pi_queue : _pi_object { // needed/used for the queue data structures. std::mutex PiQueueMutex; - // Keeps track of the event associated with the last enqueued command into - // this queue. this is used to add dependency with the last command to add - // in-order semantics and updated with the latest event each time a new - // command is enqueued. - pi_event LastCommandEvent = nullptr; - // Open command list field for batching commands into this queue. ze_command_list_handle_t ZeOpenCommandList = {nullptr}; ze_fence_handle_t ZeOpenCommandListFence = {nullptr}; diff --git a/sycl/source/detail/scheduler/commands.cpp b/sycl/source/detail/scheduler/commands.cpp index af1ce7df439fe..1072c23fbdafd 100644 --- a/sycl/source/detail/scheduler/commands.cpp +++ b/sycl/source/detail/scheduler/commands.cpp @@ -497,9 +497,14 @@ void Command::processDepEvent(EventImplPtr DepEvent, const DepDesc &Dep) { } // Do not add redundant event dependencies for in-order queues. - if (Dep.MDepCommand && Dep.MDepCommand->getWorkerQueue() == WorkerQueue && - WorkerQueue->has_property()) - return; + // TODO temporarily disabled with Level Zero since the enqueued operations + // that are implemented directly in the plugin (e.g. map/unmap) do not satisfy + // in-order queue requirements. + if (WorkerQueue->is_host() || + WorkerQueue->getPlugin().getBackend() != backend::level_zero) + if (Dep.MDepCommand && Dep.MDepCommand->getWorkerQueue() == WorkerQueue && + WorkerQueue->has_property()) + return; ContextImplPtr DepEventContext = DepEvent->getContextImpl(); // If contexts don't match we'll connect them using host task diff --git a/sycl/unittests/scheduler/InOrderQueueDeps.cpp b/sycl/unittests/scheduler/InOrderQueueDeps.cpp index cec7c1772852c..009fd8cf42c27 100644 --- a/sycl/unittests/scheduler/InOrderQueueDeps.cpp +++ b/sycl/unittests/scheduler/InOrderQueueDeps.cpp @@ -83,6 +83,13 @@ TEST_F(SchedulerTest, InOrderQueueDeps) { std::cout << "Not run due to host-only environment\n"; return; } + if (detail::getSyclObjImpl(Plt)->getPlugin().getBackend() == + backend::level_zero) { + std::cout << "Removal of redundant dependencies in in-order queues is " + "disabled for Level Zero until it is supported by the plugin" + << std::endl; + return; + } unittest::PiMock Mock{Plt}; Mock.redefine(redefinedMemBufferCreate);