Skip to content

Commit

Permalink
[SYCL] Guard access to MCreateShadowCopy (#15273)
Browse files Browse the repository at this point in the history
Fixes a flaky failure when getting write access to a buffer from
multiple threads.

---------

Co-authored-by: Artur Gainullin <artur.gainullin@intel.com>
  • Loading branch information
sergey-semenov and againull authored Sep 4, 2024
1 parent fe9aa1e commit 3d07790
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 2 deletions.
7 changes: 5 additions & 2 deletions sycl/source/detail/sycl_mem_obj_t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,11 @@ void SYCLMemObjT::detachMemoryObject(

void SYCLMemObjT::handleWriteAccessorCreation() {
const auto InitialUserPtr = MUserPtr;
MCreateShadowCopy();
MCreateShadowCopy = []() -> void {};
{
std::lock_guard<std::mutex> Lock(MCreateShadowCopyMtx);
MCreateShadowCopy();
MCreateShadowCopy = []() -> void {};
}
if (MRecord != nullptr && MUserPtr != InitialUserPtr) {
for (auto &it : MRecord->MAllocaCommands) {
if (it->MMemAllocation == InitialUserPtr) {
Expand Down
4 changes: 4 additions & 0 deletions sycl/source/detail/sycl_mem_obj_t.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <atomic>
#include <cstring>
#include <memory>
#include <mutex>
#include <type_traits>

namespace sycl {
Expand Down Expand Up @@ -196,6 +197,7 @@ class SYCLMemObjT : public SYCLMemObjI {
MUserPtr = HostPtr;
} else if (canReadHostPtr(HostPtr, RequiredAlign)) {
MUserPtr = HostPtr;
std::lock_guard<std::mutex> Lock(MCreateShadowCopyMtx);
MCreateShadowCopy = [this, RequiredAlign, HostPtr]() -> void {
setAlign(RequiredAlign);
MShadowCopy = allocateHostMem();
Expand Down Expand Up @@ -229,6 +231,7 @@ class SYCLMemObjT : public SYCLMemObjI {
MUserPtr = HostPtr.get();
} else if (canReadHostPtr(HostPtr.get(), RequiredAlign)) {
MUserPtr = HostPtr.get();
std::lock_guard<std::mutex> Lock(MCreateShadowCopyMtx);
MCreateShadowCopy = [this, RequiredAlign, HostPtr]() -> void {
setAlign(RequiredAlign);
MShadowCopy = allocateHostMem();
Expand Down Expand Up @@ -375,6 +378,7 @@ class SYCLMemObjT : public SYCLMemObjI {
// defer the memory allocation and copying to the point where a writable
// accessor is created.
std::function<void(void)> MCreateShadowCopy = []() -> void {};
std::mutex MCreateShadowCopyMtx;
bool MOwnNativeHandle = true;
};
} // namespace detail
Expand Down
35 changes: 35 additions & 0 deletions sycl/test-e2e/Regression/multithread_write_accessor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// RUN: %{build} -o %t.out
// RUN: %{run} %t.out
#include <sycl/detail/core.hpp>

#include <cassert>
#include <thread>
#include <vector>

constexpr int NThreads = 8;

class KernelA;

void threadFunction(sycl::buffer<int, 1> &Buf) {
sycl::queue Q;
Q.submit([&](sycl::handler &Cgh) {
auto Acc = Buf.get_access<sycl::access::mode::read_write>(Cgh);
Cgh.single_task<class KernelA>([=]() { Acc[0] += 1; });
});
}
int main() {
std::vector<std::thread> Threads;
Threads.reserve(NThreads);

int Val = 0;
{
sycl::buffer<int, 1> Buf(&Val, sycl::range<1>(1));
sycl::queue Q;

for (int I = 0; I < NThreads; ++I)
Threads.emplace_back(threadFunction, std::ref(Buf));
for (auto &t : Threads)
t.join();
}
assert(Val == NThreads);
}

0 comments on commit 3d07790

Please sign in to comment.