diff --git a/opencl/source/command_queue/command_queue.cpp b/opencl/source/command_queue/command_queue.cpp index 37e38c65e0..ecb6ebf2fa 100644 --- a/opencl/source/command_queue/command_queue.cpp +++ b/opencl/source/command_queue/command_queue.cpp @@ -1291,13 +1291,14 @@ WaitStatus CommandQueue::waitForAllEngines(bool blockedQueue, PrintfHandler *pri } } + TakeOwnershipWrapper queueOwnership(*this); auto taskCountToWait = taskCount; + queueOwnership.unlock(); waitStatus = waitUntilComplete(taskCountToWait, activeBcsStates, flushStamp->peekStamp(), false, cleanTemporaryAllocationsList, waitedOnTimestamps); { - TakeOwnershipWrapper queueOwnership(*this); - + queueOwnership.lock(); /* Check if queue resources cleanup after wait is possible. If new submission happened during wait, we need to query completion (without waiting). diff --git a/opencl/test/unit_test/mt_tests/enqueue_kernel/CMakeLists.txt b/opencl/test/unit_test/mt_tests/enqueue_kernel/CMakeLists.txt new file mode 100644 index 0000000000..689d9c9c8e --- /dev/null +++ b/opencl/test/unit_test/mt_tests/enqueue_kernel/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Copyright (C) 2023 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +set(IGDRCL_SRCS_mt_tests_enqueue_kernel + # local files + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/enqueue_kernel_tests_mt.cpp +) +target_sources(igdrcl_mt_tests PRIVATE ${IGDRCL_SRCS_mt_tests_enqueue_kernel}) diff --git a/opencl/test/unit_test/mt_tests/enqueue_kernel/enqueue_kernel_tests_mt.cpp b/opencl/test/unit_test/mt_tests/enqueue_kernel/enqueue_kernel_tests_mt.cpp new file mode 100644 index 0000000000..e441292891 --- /dev/null +++ b/opencl/test/unit_test/mt_tests/enqueue_kernel/enqueue_kernel_tests_mt.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "opencl/test/unit_test/command_queue/enqueue_fixture.h" +#include "opencl/test/unit_test/fixtures/hello_world_fixture.h" + +using namespace NEO; + +typedef HelloWorldTest EnqueueKernelTestsMt; + +TEST_F(EnqueueKernelTestsMt, WhenCallEnqueueKernelsThenAllCallsPass) { + size_t workSize[] = {1}; + const int iterNum = 10; + const int threadNum = 10; + const int taskNum = 10; + std::atomic result = {0}; + + for (int iter = 0; iter < iterNum; iter++) { + std::vector threads; + for (int thr = 0; thr < threadNum; thr++) { + threads.emplace_back([&]() { + for (int j = 0; j < taskNum; j++) { + result += EnqueueKernelHelper<>::enqueueKernel(pCmdQ, + KernelFixture::pKernel, + 1, + nullptr, + workSize, + workSize, + 0, nullptr, nullptr); + result += clFinish(pCmdQ); + } + }); + } + for (auto &t : threads) + t.join(); + EXPECT_EQ(CL_SUCCESS, result); + } +} diff --git a/shared/test/common/libult/ult_command_stream_receiver.h b/shared/test/common/libult/ult_command_stream_receiver.h index 0d21d56cae..636925cb62 100644 --- a/shared/test/common/libult/ult_command_stream_receiver.h +++ b/shared/test/common/libult/ult_command_stream_receiver.h @@ -241,6 +241,7 @@ class UltCommandStreamReceiver : public CommandStreamReceiverHw, publ } WaitStatus waitForCompletionWithTimeout(const WaitParams ¶ms, TaskCountType taskCountToWait) override { + std::lock_guard guard(mutex); latestWaitForCompletionWithTimeoutTaskCount.store(taskCountToWait); latestWaitForCompletionWithTimeoutWaitParams = params; waitForCompletionWithTimeoutTaskCountCalled++; @@ -320,6 +321,7 @@ class UltCommandStreamReceiver : public CommandStreamReceiverHw, publ addAubCommentCalled = true; } bool flushBatchedSubmissions() override { + auto commandStreamReceieverOwnership = this->obtainUniqueOwnership(); flushBatchedSubmissionsCalled = true; if (shouldFailFlushBatchedSubmissions) { @@ -473,6 +475,7 @@ class UltCommandStreamReceiver : public CommandStreamReceiverHw, publ LinearStream *lastFlushedCommandStream = nullptr; const IndirectHeap *recordedSsh = nullptr; + std::mutex mutex; std::atomic recursiveLockCounter; std::atomic waitForCompletionWithTimeoutTaskCountCalled{0}; uint32_t makeSurfacePackNonResidentCalled = false;