@@ -39,16 +39,34 @@ program_impl::program_impl(
39
39
throw runtime_error (" Non-empty vector of programs expected" ,
40
40
PI_INVALID_VALUE);
41
41
}
42
+
43
+ // Sort the programs to avoid deadlocks due to locking multiple mutexes &
44
+ // verify that all programs are unique.
45
+ std::sort (ProgramList.begin (), ProgramList.end (),
46
+ [](const shared_ptr_class<program_impl> &A,
47
+ const shared_ptr_class<program_impl> &B) {
48
+ return A.get () < B.get ();
49
+ });
50
+ auto It = std::unique (ProgramList.begin (), ProgramList.end (),
51
+ [](const shared_ptr_class<program_impl> &A,
52
+ const shared_ptr_class<program_impl> &B) {
53
+ return A.get () == B.get ();
54
+ });
55
+ if (It != ProgramList.end ()) {
56
+ throw runtime_error (" Attempting to link a program with itself" ,
57
+ PI_INVALID_PROGRAM);
58
+ }
59
+
42
60
MContext = ProgramList[0 ]->MContext ;
43
61
MDevices = ProgramList[0 ]->MDevices ;
44
62
vector_class<device> DevicesSorted;
45
63
if (!is_host ()) {
46
64
DevicesSorted = sort_devices_by_cl_device_id (MDevices);
47
65
}
48
66
check_device_feature_support<info::device::is_linker_available>(MDevices);
49
- vector_class<std::unique_lock <std::mutex>> Locks;
67
+ vector_class<unique_ptr_class< std::lock_guard <std::mutex> >> Locks;
50
68
for (const auto &Prg : ProgramList) {
51
- Locks.emplace_back (Prg->MMutex );
69
+ Locks.emplace_back (new std::lock_guard<std::mutex>( Prg->MMutex ) );
52
70
Prg->throw_if_state_is_not (program_state::compiled);
53
71
if (Prg->MContext != MContext) {
54
72
throw invalid_object_error (
@@ -187,7 +205,7 @@ cl_program program_impl::get() const {
187
205
void program_impl::compile_with_kernel_name (string_class KernelName,
188
206
string_class CompileOptions,
189
207
OSModuleHandle M) {
190
- std::unique_lock <std::mutex> Lock (MMutex);
208
+ std::lock_guard <std::mutex> Lock (MMutex);
191
209
throw_if_state_is_not (program_state::none);
192
210
MProgramModuleHandle = M;
193
211
if (!is_host ()) {
@@ -199,7 +217,7 @@ void program_impl::compile_with_kernel_name(string_class KernelName,
199
217
200
218
void program_impl::compile_with_source (string_class KernelSource,
201
219
string_class CompileOptions) {
202
- std::unique_lock <std::mutex> Lock (MMutex);
220
+ std::lock_guard <std::mutex> Lock (MMutex);
203
221
throw_if_state_is_not (program_state::none);
204
222
// TODO should it throw if it's host?
205
223
if (!is_host ()) {
@@ -212,7 +230,7 @@ void program_impl::compile_with_source(string_class KernelSource,
212
230
void program_impl::build_with_kernel_name (string_class KernelName,
213
231
string_class BuildOptions,
214
232
OSModuleHandle Module) {
215
- std::unique_lock <std::mutex> Lock (MMutex);
233
+ std::lock_guard <std::mutex> Lock (MMutex);
216
234
throw_if_state_is_not (program_state::none);
217
235
MProgramModuleHandle = Module;
218
236
if (!is_host ()) {
@@ -233,7 +251,7 @@ void program_impl::build_with_kernel_name(string_class KernelName,
233
251
234
252
void program_impl::build_with_source (string_class KernelSource,
235
253
string_class BuildOptions) {
236
- std::unique_lock <std::mutex> Lock (MMutex);
254
+ std::lock_guard <std::mutex> Lock (MMutex);
237
255
throw_if_state_is_not (program_state::none);
238
256
// TODO should it throw if it's host?
239
257
if (!is_host ()) {
@@ -244,7 +262,7 @@ void program_impl::build_with_source(string_class KernelSource,
244
262
}
245
263
246
264
void program_impl::link (string_class LinkOptions) {
247
- std::unique_lock <std::mutex> Lock (MMutex);
265
+ std::lock_guard <std::mutex> Lock (MMutex);
248
266
throw_if_state_is_not (program_state::compiled);
249
267
if (!is_host ()) {
250
268
check_device_feature_support<info::device::is_linker_available>(MDevices);
0 commit comments