diff --git a/sycl/source/detail/queue_impl.cpp b/sycl/source/detail/queue_impl.cpp index f9a9f41450ec4..cb1654258303a 100644 --- a/sycl/source/detail/queue_impl.cpp +++ b/sycl/source/detail/queue_impl.cpp @@ -349,7 +349,13 @@ queue_impl::submit_impl(const detail::type_erased_cgfo_ty &CGF, !requiresPostProcess; if (noLastEventPath) { - return finalizeHandlerInOrderNoEventsUnlocked(Handler); + std::unique_lock Lock(MMutex); + + // Check if we are still in no last event mode. There could + // have been a concurrent submit. + if (MNoLastEventMode.load(std::memory_order_relaxed)) { + return finalizeHandlerInOrderNoEventsUnlocked(Handler); + } } detail::EventImplPtr EventImpl; diff --git a/sycl/source/detail/queue_impl.hpp b/sycl/source/detail/queue_impl.hpp index ec7aa71196d8d..4c6f538a85303 100644 --- a/sycl/source/detail/queue_impl.hpp +++ b/sycl/source/detail/queue_impl.hpp @@ -750,7 +750,14 @@ class queue_impl : public std::enable_shared_from_this { synchronizeWithExternalEvent(Handler); - return parseEvent(Handler.finalize()); + auto Event = parseEvent(Handler.finalize()); + + if (Event && !Scheduler::CheckEventReadiness(*MContext, Event)) { + MDefaultGraphDeps.LastEventPtr = Event; + MNoLastEventMode.store(false, std::memory_order_relaxed); + } + + return Event; } template diff --git a/sycl/test-e2e/InorderQueue/in_order_multi_queue_host_task.cpp b/sycl/test-e2e/InorderQueue/in_order_multi_queue_host_task.cpp new file mode 100644 index 0000000000000..e8abb851068a1 --- /dev/null +++ b/sycl/test-e2e/InorderQueue/in_order_multi_queue_host_task.cpp @@ -0,0 +1,66 @@ +// RUN: %{build} -o %t.out +// RUN: %{run} %t.out +//==-------- in_order_multi_queue_host_task.cpp ---------------------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include +#include + +#include +#include +#include + +using namespace sycl; + +const int dataSize = 1024; + +int main() { + queue Queue1{property::queue::in_order()}; + queue Queue2{property::queue::in_order()}; + + int *dataA = malloc_host(dataSize, Queue1); + int *dataB = malloc_host(dataSize, Queue1); + int *dataC = malloc_host(dataSize, Queue1); + + bool ready = false; + std::mutex host_task_mtx; + std::condition_variable cv; + + auto Event1 = Queue1.submit([&](handler &cgh) { + cgh.host_task([&] { + std::unique_lock lk(host_task_mtx); + cv.wait(lk, [&] { return ready; }); + for (size_t i = 0; i < dataSize; ++i) { + dataA[i] = i; + } + }); + }); + + Queue2.submit([&](handler &cgh) { + cgh.depends_on(Event1); + cgh.parallel_for(range<1>(dataSize), + [=](id<1> idx) { dataB[idx[0]] = dataA[idx[0]]; }); + }); + + { + std::unique_lock lk(host_task_mtx); + ready = true; + } + cv.notify_one(); + + Queue2.wait(); + + for (size_t i = 0; i != dataSize; ++i) { + if (dataB[i] != i) { + std::cout << "Result mismatches " << dataB[i] << " vs expected " << i + << " for index " << i << std::endl; + return 1; + } + } + + return 0; +}