@@ -110,22 +110,22 @@ DeviceImage &ProgramManager::getDeviceImage(OSModuleHandle M,
110
110
}
111
111
112
112
template <typename ExceptionT, typename RetT>
113
- RetT *
114
- waitUntilBuilt (KernelProgramCache &Cache,
115
- KernelProgramCache::EntityWithState<RetT> *WithBuildState) {
113
+ RetT *waitUntilBuilt (KernelProgramCache &Cache,
114
+ KernelProgramCache::BuildResult<RetT> *BuildResult) {
116
115
// any thread which will find nullptr in cache will wait until the pointer
117
116
// is not null anymore
118
- Cache.waitUntilBuilt ([WithBuildState ]() {
119
- int State = WithBuildState ->State .load ();
117
+ Cache.waitUntilBuilt ([BuildResult ]() {
118
+ int State = BuildResult ->State .load ();
120
119
121
120
return State == BS_Done || State == BS_Failed;
122
121
});
123
122
124
- RetT *Result = WithBuildState->Ptr .load ();
123
+ if (BuildResult->Error .FilledIn ) {
124
+ const KernelProgramCache::BuildError &Error = BuildResult->Error ;
125
+ throw ExceptionT (Error.Msg , Error.Code );
126
+ }
125
127
126
- if (!Result)
127
- throw ExceptionT (" The other thread tried to build the program/kernel but "
128
- " did not succeed." );
128
+ RetT *Result = BuildResult->Ptr .load ();
129
129
130
130
return Result;
131
131
}
@@ -152,7 +152,7 @@ template <typename RetT, typename ExceptionT, typename KeyT, typename AcquireFT,
152
152
RetT *getOrBuild (KernelProgramCache &KPCache, const KeyT &CacheKey,
153
153
AcquireFT &&Acquire, GetCacheFT &&GetCache, BuildFT &&Build) {
154
154
bool InsertionTookPlace;
155
- KernelProgramCache::EntityWithState <RetT> *WithState ;
155
+ KernelProgramCache::BuildResult <RetT> *BuildResult ;
156
156
157
157
{
158
158
auto LockedCache = Acquire (KPCache);
@@ -162,36 +162,59 @@ RetT *getOrBuild(KernelProgramCache &KPCache, const KeyT &CacheKey,
162
162
std::forward_as_tuple (nullptr , BS_InProgress));
163
163
164
164
InsertionTookPlace = Inserted.second ;
165
- WithState = &Inserted.first ->second ;
165
+ BuildResult = &Inserted.first ->second ;
166
166
}
167
167
168
168
// no insertion took place, thus some other thread has already inserted smth
169
169
// in the cache
170
170
if (!InsertionTookPlace) {
171
- return waitUntilBuilt<ExceptionT>(KPCache, WithState);
171
+ for (;;) {
172
+ RetT *Result = waitUntilBuilt<ExceptionT>(KPCache, BuildResult);
173
+
174
+ if (Result)
175
+ return Result;
176
+
177
+ // Previous build is failed. There was no SYCL exception though.
178
+ // We might try to build once more.
179
+ int Expected = BS_Failed;
180
+ int Desired = BS_InProgress;
181
+
182
+ if (BuildResult->State .compare_exchange_strong (Expected, Desired))
183
+ break ; // this thread is the building thread now
184
+ }
172
185
}
173
186
174
- // only the building thread will run this, and only once.
187
+ // only the building thread will run this
175
188
try {
176
189
RetT *Desired = Build ();
177
190
178
191
#ifndef NDEBUG
179
192
RetT *Expected = nullptr ;
180
193
181
- if (!WithState ->Ptr .compare_exchange_strong (Expected, Desired))
194
+ if (!BuildResult ->Ptr .compare_exchange_strong (Expected, Desired))
182
195
// We've got a funny story here
183
196
assert (false && " We've build an entity that is already have been built." );
184
197
#else
185
- WithState ->Ptr .store (Desired);
198
+ BuildResult ->Ptr .store (Desired);
186
199
#endif
187
200
188
- WithState ->State .store (BS_Done);
201
+ BuildResult ->State .store (BS_Done);
189
202
190
203
KPCache.notifyAllBuild ();
191
204
192
205
return Desired;
206
+ } catch (const exception &Ex) {
207
+ BuildResult->Error .Msg = Ex.what ();
208
+ BuildResult->Error .Code = Ex.get_cl_code ();
209
+ BuildResult->Error .FilledIn = true ;
210
+
211
+ BuildResult->State .store (BS_Failed);
212
+
213
+ KPCache.notifyAllBuild ();
214
+
215
+ std::rethrow_exception (std::current_exception ());
193
216
} catch (...) {
194
- WithState ->State .store (BS_Failed);
217
+ BuildResult ->State .store (BS_Failed);
195
218
196
219
KPCache.notifyAllBuild ();
197
220
0 commit comments