15
15
16
16
#include < algorithm>
17
17
#include < fstream>
18
+ #include < list>
18
19
#include < memory>
20
+ #include < mutex>
19
21
20
22
__SYCL_INLINE_NAMESPACE (cl) {
21
23
namespace sycl {
@@ -38,14 +40,26 @@ program_impl::program_impl(
38
40
throw runtime_error (" Non-empty vector of programs expected" ,
39
41
PI_INVALID_VALUE);
40
42
}
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
+
41
53
MContext = ProgramList[0 ]->MContext ;
42
54
MDevices = ProgramList[0 ]->MDevices ;
43
55
vector_class<device> DevicesSorted;
44
56
if (!is_host ()) {
45
57
DevicesSorted = sort_devices_by_cl_device_id (MDevices);
46
58
}
47
59
check_device_feature_support<info::device::is_linker_available>(MDevices);
60
+ std::list<std::lock_guard<std::mutex>> Locks;
48
61
for (const auto &Prg : ProgramList) {
62
+ Locks.emplace_back (Prg->MMutex );
49
63
Prg->throw_if_state_is_not (program_state::compiled);
50
64
if (Prg->MContext != MContext) {
51
65
throw invalid_object_error (
@@ -184,6 +198,7 @@ cl_program program_impl::get() const {
184
198
void program_impl::compile_with_kernel_name (string_class KernelName,
185
199
string_class CompileOptions,
186
200
OSModuleHandle M) {
201
+ std::lock_guard<std::mutex> Lock (MMutex);
187
202
throw_if_state_is_not (program_state::none);
188
203
MProgramModuleHandle = M;
189
204
if (!is_host ()) {
@@ -195,6 +210,7 @@ void program_impl::compile_with_kernel_name(string_class KernelName,
195
210
196
211
void program_impl::compile_with_source (string_class KernelSource,
197
212
string_class CompileOptions) {
213
+ std::lock_guard<std::mutex> Lock (MMutex);
198
214
throw_if_state_is_not (program_state::none);
199
215
// TODO should it throw if it's host?
200
216
if (!is_host ()) {
@@ -207,6 +223,7 @@ void program_impl::compile_with_source(string_class KernelSource,
207
223
void program_impl::build_with_kernel_name (string_class KernelName,
208
224
string_class BuildOptions,
209
225
OSModuleHandle Module) {
226
+ std::lock_guard<std::mutex> Lock (MMutex);
210
227
throw_if_state_is_not (program_state::none);
211
228
MProgramModuleHandle = Module;
212
229
if (!is_host ()) {
@@ -227,6 +244,7 @@ void program_impl::build_with_kernel_name(string_class KernelName,
227
244
228
245
void program_impl::build_with_source (string_class KernelSource,
229
246
string_class BuildOptions) {
247
+ std::lock_guard<std::mutex> Lock (MMutex);
230
248
throw_if_state_is_not (program_state::none);
231
249
// TODO should it throw if it's host?
232
250
if (!is_host ()) {
@@ -237,6 +255,7 @@ void program_impl::build_with_source(string_class KernelSource,
237
255
}
238
256
239
257
void program_impl::link (string_class LinkOptions) {
258
+ std::lock_guard<std::mutex> Lock (MMutex);
240
259
throw_if_state_is_not (program_state::compiled);
241
260
if (!is_host ()) {
242
261
check_device_feature_support<info::device::is_linker_available>(MDevices);
0 commit comments