@@ -111,7 +111,8 @@ DeviceImage &ProgramManager::getDeviceImage(OSModuleHandle M,
111
111
112
112
template <typename ExceptionT, typename RetT>
113
113
RetT *waitUntilBuilt (KernelProgramCache &Cache,
114
- KernelProgramCache::BuildResult<RetT> *BuildResult) {
114
+ KernelProgramCache::BuildResult<RetT> *BuildResult,
115
+ bool &TryAgain) {
115
116
// any thread which will find nullptr in cache will wait until the pointer
116
117
// is not null anymore
117
118
Cache.waitUntilBuilt ([BuildResult]() {
@@ -127,7 +128,9 @@ RetT *waitUntilBuilt(KernelProgramCache &Cache,
127
128
128
129
RetT *Result = BuildResult->Ptr .load ();
129
130
130
- assert (Result && " An exception should have been thrown" );
131
+ // if the result is still null then there was no SYCL exception and we may try
132
+ // to build kernel/program once more to generate the original exception
133
+ TryAgain = !Result;
131
134
132
135
return Result;
133
136
}
@@ -170,10 +173,29 @@ RetT *getOrBuild(KernelProgramCache &KPCache, const KeyT &CacheKey,
170
173
// no insertion took place, thus some other thread has already inserted smth
171
174
// in the cache
172
175
if (!InsertionTookPlace) {
173
- return waitUntilBuilt<ExceptionT>(KPCache, BuildResult);
176
+ bool TryAgain = false ;
177
+
178
+ for (;;) {
179
+ RetT *Result = waitUntilBuilt<ExceptionT>(KPCache, BuildResult, TryAgain);
180
+
181
+ if (TryAgain) {
182
+ // Previous build is failed. There was no SYCL exception though.
183
+ // We might try to build once more.
184
+ int Expected = BS_Failed;
185
+ int Desired = BS_InProgress;
186
+
187
+ if (BuildResult->State .compare_exchange_strong (Expected, Desired)) {
188
+ // this thread is the building thread now
189
+ break ;
190
+ }
191
+
192
+ continue ;
193
+ } else // no need to try once more
194
+ return Result;
195
+ }
174
196
}
175
197
176
- // only the building thread will run this, and only once.
198
+ // only the building thread will run this
177
199
try {
178
200
RetT *Desired = Build ();
179
201
@@ -184,7 +206,7 @@ RetT *getOrBuild(KernelProgramCache &KPCache, const KeyT &CacheKey,
184
206
// We've got a funny story here
185
207
assert (false && " We've build an entity that is already have been built." );
186
208
#else
187
- WithState ->Ptr .store (Desired);
209
+ BuildResult ->Ptr .store (Desired);
188
210
#endif
189
211
190
212
BuildResult->State .store (BS_Done);
0 commit comments