MCPcopy Create free account
hub / github.com/build2/build2 / lock_impl

Function lock_impl

libbuild2/algorithm.cxx:241–356  ·  view source on GitHub ↗

If the work_queue is absent, then we don't wait. While already applied or executed targets are normally not locked, if options contain any bits that are not already in cur_options, then the target is locked even in these states.

Source from the content-addressed store, hash-verified

239 // target is locked even in these states.
240 //
241 target_lock
242 lock_impl (action a, const target& ct,
243 optional<scheduler::work_queue> wq,
244 uint64_t options)
245 {
246 context& ctx (ct.ctx);
247
248 assert (ctx.phase == run_phase::match);
249
250 // Most likely the target's state is (count_touched - 1), that is, 0 or
251 // previously executed, so let's start with that.
252 //
253 size_t b (ctx.count_base ());
254 size_t e (b + target::offset_touched - 1);
255
256 size_t appl (b + target::offset_applied);
257 size_t busy (b + target::offset_busy);
258
259 const target::opstate& cs (ct[a]);
260 atomic_count& task_count (cs.task_count);
261
262 while (!task_count.compare_exchange_strong (
263 e,
264 busy,
265 memory_order_acq_rel, // Synchronize on success.
266 memory_order_acquire)) // Synchronize on failure.
267 {
268 // Wait for the count to drop below busy if someone is already working
269 // on this target.
270 //
271 if (e >= busy)
272 {
273 // Check for dependency cycles. The cycle members should be evident
274 // from the "while ..." info lines that will follow.
275 //
276 if (dependency_cycle (a, ct))
277 fail << "dependency cycle detected involving target " << ct;
278
279 if (!wq)
280 return target_lock {a, nullptr, e - b, false};
281
282 // @@ TMP: remove if the queue_mark approach pans out.
283 //
284#if 0
285 // Don't work the queue if in the update during load during
286 // interrupting load. Failed that we may deadlock via dir_search().
287 //
288 if (ctx.update_during_load > 1)
289 *wq = scheduler::work_none;
290#endif
291
292 // We also unlock the phase for the duration of the wait. Why?
293 // Consider this scenario: we are trying to match a dir{} target whose
294 // buildfile still needs to be loaded. Let's say someone else started
295 // the match before us. So we wait for their completion and they wait
296 // to switch the phase to load. Which would result in a deadlock
297 // unless we release the phase.
298 //

Callers 3

match_implFunction · 0.85
match_only_syncFunction · 0.85
resolve_membersFunction · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected