Skip to content

Commit 3c7adbf

Browse files
sergey-semenovagainull
authored andcommitted
[SYCL] Guard access to MCreateShadowCopy (#15273)
Fixes a flaky failure when getting write access to a buffer from multiple threads. --------- Co-authored-by: Artur Gainullin <artur.gainullin@intel.com>
1 parent acd8dbd commit 3c7adbf

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

sycl/source/detail/sycl_mem_obj_t.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,11 @@ void SYCLMemObjT::detachMemoryObject(
228228

229229
void SYCLMemObjT::handleWriteAccessorCreation() {
230230
const auto InitialUserPtr = MUserPtr;
231-
MCreateShadowCopy();
232-
MCreateShadowCopy = []() -> void {};
231+
{
232+
std::lock_guard<std::mutex> Lock(MCreateShadowCopyMtx);
233+
MCreateShadowCopy();
234+
MCreateShadowCopy = []() -> void {};
235+
}
233236
if (MRecord != nullptr && MUserPtr != InitialUserPtr) {
234237
for (auto &it : MRecord->MAllocaCommands) {
235238
if (it->MMemAllocation == InitialUserPtr) {

sycl/source/detail/sycl_mem_obj_t.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <atomic>
2424
#include <cstring>
2525
#include <memory>
26+
#include <mutex>
2627
#include <type_traits>
2728

2829
namespace sycl {
@@ -196,6 +197,7 @@ class SYCLMemObjT : public SYCLMemObjI {
196197
MUserPtr = HostPtr;
197198
} else if (canReadHostPtr(HostPtr, RequiredAlign)) {
198199
MUserPtr = HostPtr;
200+
std::lock_guard<std::mutex> Lock(MCreateShadowCopyMtx);
199201
MCreateShadowCopy = [this, RequiredAlign, HostPtr]() -> void {
200202
setAlign(RequiredAlign);
201203
MShadowCopy = allocateHostMem();
@@ -229,6 +231,7 @@ class SYCLMemObjT : public SYCLMemObjI {
229231
MUserPtr = HostPtr.get();
230232
} else if (canReadHostPtr(HostPtr.get(), RequiredAlign)) {
231233
MUserPtr = HostPtr.get();
234+
std::lock_guard<std::mutex> Lock(MCreateShadowCopyMtx);
232235
MCreateShadowCopy = [this, RequiredAlign, HostPtr]() -> void {
233236
setAlign(RequiredAlign);
234237
MShadowCopy = allocateHostMem();
@@ -375,6 +378,7 @@ class SYCLMemObjT : public SYCLMemObjI {
375378
// defer the memory allocation and copying to the point where a writable
376379
// accessor is created.
377380
std::function<void(void)> MCreateShadowCopy = []() -> void {};
381+
std::mutex MCreateShadowCopyMtx;
378382
bool MOwnNativeHandle = true;
379383
};
380384
} // namespace detail
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %{build} -o %t.out
2+
// RUN: %{run} %t.out
3+
#include <sycl/detail/core.hpp>
4+
5+
#include <cassert>
6+
#include <thread>
7+
#include <vector>
8+
9+
constexpr int NThreads = 8;
10+
11+
class KernelA;
12+
13+
void threadFunction(sycl::buffer<int, 1> &Buf) {
14+
sycl::queue Q;
15+
Q.submit([&](sycl::handler &Cgh) {
16+
auto Acc = Buf.get_access<sycl::access::mode::read_write>(Cgh);
17+
Cgh.single_task<class KernelA>([=]() { Acc[0] += 1; });
18+
});
19+
}
20+
int main() {
21+
std::vector<std::thread> Threads;
22+
Threads.reserve(NThreads);
23+
24+
int Val = 0;
25+
{
26+
sycl::buffer<int, 1> Buf(&Val, sycl::range<1>(1));
27+
sycl::queue Q;
28+
29+
for (int I = 0; I < NThreads; ++I)
30+
Threads.emplace_back(threadFunction, std::ref(Buf));
31+
for (auto &t : Threads)
32+
t.join();
33+
}
34+
assert(Val == NThreads);
35+
}

0 commit comments

Comments
 (0)