Skip to content

Commit 349a0d3

Browse files
Ilya Stepykinbader
authored andcommitted
[SYCL] Make sycl::queue threadsafe
Add mutex to protect fields of queue_impl class when they're accessed by multiple threads. Signed-off-by: Ilya Stepykin <[email protected]>
1 parent a65b499 commit 349a0d3

File tree

1 file changed

+41
-15
lines changed

1 file changed

+41
-15
lines changed

sycl/include/CL/sycl/detail/queue_impl.hpp

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ class queue_impl {
3737
async_handler AsyncHandler, QueueOrder Order,
3838
const property_list &PropList)
3939
: m_Device(SyclDevice), m_Context(Context), m_AsyncHandler(AsyncHandler),
40-
m_PropList(PropList), m_HostQueue(m_Device.is_host()) {
41-
m_OpenCLInterop = !m_HostQueue;
40+
m_PropList(PropList), m_HostQueue(m_Device.is_host()),
41+
m_OpenCLInterop(!m_HostQueue) {
4242
if (!m_HostQueue) {
4343
m_CommandQueue = createQueue(Order);
4444
}
@@ -47,7 +47,7 @@ class queue_impl {
4747
queue_impl(cl_command_queue CLQueue, const context &SyclContext,
4848
const async_handler &AsyncHandler)
4949
: m_Context(SyclContext), m_AsyncHandler(AsyncHandler),
50-
m_OpenCLInterop(true), m_HostQueue(false) {
50+
m_HostQueue(false), m_OpenCLInterop(true) {
5151

5252
m_CommandQueue = pi::cast<RT::PiQueue>(CLQueue);
5353

@@ -94,7 +94,10 @@ class queue_impl {
9494
try {
9595
Event = submit_impl(cgf, self);
9696
} catch (...) {
97-
m_Exceptions.PushBack(std::current_exception());
97+
{
98+
std::lock_guard<mutex_class> guard(m_Mutex);
99+
m_Exceptions.PushBack(std::current_exception());
100+
}
98101
Event = second_queue->submit(cgf, second_queue);
99102
}
100103
return Event;
@@ -105,13 +108,14 @@ class queue_impl {
105108
try {
106109
Event = submit_impl(cgf, self);
107110
} catch (...) {
111+
std::lock_guard<mutex_class> guard(m_Mutex);
108112
m_Exceptions.PushBack(std::current_exception());
109113
}
110114
return Event;
111115
}
112116

113117
void wait() {
114-
// TODO: Make thread safe.
118+
std::lock_guard<mutex_class> guard(m_Mutex);
115119
for (auto &evnt : m_Events)
116120
evnt.wait();
117121
m_Events.clear();
@@ -125,9 +129,18 @@ class queue_impl {
125129
}
126130

127131
void throw_asynchronous() {
132+
std::unique_lock<mutex_class> lock(m_Mutex);
133+
128134
if (m_AsyncHandler && m_Exceptions.size()) {
129135
exception_list Exceptions;
136+
130137
std::swap(m_Exceptions, Exceptions);
138+
139+
// Unlock the mutex before calling user-provided handler to avoid
140+
// potential deadlock if the same queue is somehow referenced in the
141+
// handler.
142+
lock.unlock();
143+
131144
m_AsyncHandler(std::move(Exceptions));
132145
}
133146
}
@@ -162,6 +175,8 @@ class queue_impl {
162175

163176
// Warning. Returned reference will be invalid if queue_impl was destroyed.
164177
RT::PiQueue &getExclusiveQueueHandleRef() {
178+
std::lock_guard<mutex_class> guard(m_Mutex);
179+
165180
// To achive parallelism for FPGA with in order execution model with
166181
// possibility of two kernels to share data with each other we shall
167182
// create a queue for every kernel enqueued.
@@ -184,9 +199,15 @@ class queue_impl {
184199
return m_CommandQueue;
185200
}
186201

187-
if (m_Queues.empty()) {
188-
m_Queues.push_back(m_CommandQueue);
189-
return m_CommandQueue;
202+
{
203+
// Reduce the scope since this mutex is also
204+
// locked inside of getExclusiveQueueHandleRef()
205+
std::lock_guard<mutex_class> guard(m_Mutex);
206+
207+
if (m_Queues.empty()) {
208+
m_Queues.push_back(m_CommandQueue);
209+
return m_CommandQueue;
210+
}
190211
}
191212

192213
return getExclusiveQueueHandleRef();
@@ -210,17 +231,22 @@ class queue_impl {
210231
handler Handler(std::move(self), m_HostQueue);
211232
cgf(Handler);
212233
event Event = Handler.finalize();
213-
// TODO: Make thread safe.
214-
m_Events.push_back(Event);
234+
{
235+
std::lock_guard<mutex_class> guard(m_Mutex);
236+
m_Events.push_back(Event);
237+
}
215238
return Event;
216239
}
217240

241+
// Protects all the fields that can be changed by class' methods
242+
mutex_class m_Mutex;
243+
218244
device m_Device;
219-
context m_Context;
245+
const context m_Context;
220246
vector_class<event> m_Events;
221247
exception_list m_Exceptions;
222-
async_handler m_AsyncHandler;
223-
property_list m_PropList;
248+
const async_handler m_AsyncHandler;
249+
const property_list m_PropList;
224250

225251
RT::PiQueue m_CommandQueue = nullptr;
226252

@@ -229,8 +255,8 @@ class queue_impl {
229255
// Iterator through m_Queues.
230256
size_t m_QueueNumber = 0;
231257

232-
bool m_OpenCLInterop = false;
233-
bool m_HostQueue = false;
258+
const bool m_HostQueue = false;
259+
const bool m_OpenCLInterop = false;
234260
// Assume OOO support by default.
235261
bool m_SupportOOO = true;
236262
};

0 commit comments

Comments
 (0)