Skip to content

Commit e88a611

Browse files
[SYCL] Add a mutex to state-modifying program functions (#1204)
This is done in order to consistently report errors if the user tries to compile/link/build the same program from multiple threads. Signed-off-by: Sergey Semenov <[email protected]>
1 parent ec80987 commit e88a611

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

sycl/source/detail/program_impl.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515

1616
#include <algorithm>
1717
#include <fstream>
18+
#include <list>
1819
#include <memory>
20+
#include <mutex>
1921

2022
__SYCL_INLINE_NAMESPACE(cl) {
2123
namespace sycl {
@@ -38,14 +40,26 @@ program_impl::program_impl(
3840
throw runtime_error("Non-empty vector of programs expected",
3941
PI_INVALID_VALUE);
4042
}
43+
44+
// Sort the programs to avoid deadlocks due to locking multiple mutexes &
45+
// verify that all programs are unique.
46+
std::sort(ProgramList.begin(), ProgramList.end());
47+
auto It = std::unique(ProgramList.begin(), ProgramList.end());
48+
if (It != ProgramList.end()) {
49+
throw runtime_error("Attempting to link a program with itself",
50+
PI_INVALID_PROGRAM);
51+
}
52+
4153
MContext = ProgramList[0]->MContext;
4254
MDevices = ProgramList[0]->MDevices;
4355
vector_class<device> DevicesSorted;
4456
if (!is_host()) {
4557
DevicesSorted = sort_devices_by_cl_device_id(MDevices);
4658
}
4759
check_device_feature_support<info::device::is_linker_available>(MDevices);
60+
std::list<std::lock_guard<std::mutex>> Locks;
4861
for (const auto &Prg : ProgramList) {
62+
Locks.emplace_back(Prg->MMutex);
4963
Prg->throw_if_state_is_not(program_state::compiled);
5064
if (Prg->MContext != MContext) {
5165
throw invalid_object_error(
@@ -184,6 +198,7 @@ cl_program program_impl::get() const {
184198
void program_impl::compile_with_kernel_name(string_class KernelName,
185199
string_class CompileOptions,
186200
OSModuleHandle M) {
201+
std::lock_guard<std::mutex> Lock(MMutex);
187202
throw_if_state_is_not(program_state::none);
188203
MProgramModuleHandle = M;
189204
if (!is_host()) {
@@ -195,6 +210,7 @@ void program_impl::compile_with_kernel_name(string_class KernelName,
195210

196211
void program_impl::compile_with_source(string_class KernelSource,
197212
string_class CompileOptions) {
213+
std::lock_guard<std::mutex> Lock(MMutex);
198214
throw_if_state_is_not(program_state::none);
199215
// TODO should it throw if it's host?
200216
if (!is_host()) {
@@ -207,6 +223,7 @@ void program_impl::compile_with_source(string_class KernelSource,
207223
void program_impl::build_with_kernel_name(string_class KernelName,
208224
string_class BuildOptions,
209225
OSModuleHandle Module) {
226+
std::lock_guard<std::mutex> Lock(MMutex);
210227
throw_if_state_is_not(program_state::none);
211228
MProgramModuleHandle = Module;
212229
if (!is_host()) {
@@ -227,6 +244,7 @@ void program_impl::build_with_kernel_name(string_class KernelName,
227244

228245
void program_impl::build_with_source(string_class KernelSource,
229246
string_class BuildOptions) {
247+
std::lock_guard<std::mutex> Lock(MMutex);
230248
throw_if_state_is_not(program_state::none);
231249
// TODO should it throw if it's host?
232250
if (!is_host()) {
@@ -237,6 +255,7 @@ void program_impl::build_with_source(string_class KernelSource,
237255
}
238256

239257
void program_impl::link(string_class LinkOptions) {
258+
std::lock_guard<std::mutex> Lock(MMutex);
240259
throw_if_state_is_not(program_state::compiled);
241260
if (!is_host()) {
242261
check_device_feature_support<info::device::is_linker_available>(MDevices);

sycl/source/detail/program_impl.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <cassert>
2121
#include <fstream>
2222
#include <memory>
23+
#include <mutex>
2324

2425
__SYCL_INLINE_NAMESPACE(cl) {
2526
namespace sycl {
@@ -380,6 +381,7 @@ class program_impl {
380381

381382
RT::PiProgram MProgram = nullptr;
382383
program_state MState = program_state::none;
384+
std::mutex MMutex;
383385
ContextImplPtr MContext;
384386
bool MLinkable = false;
385387
vector_class<device> MDevices;

0 commit comments

Comments
 (0)