aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-07-29 14:17:27 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-07-29 14:25:14 +0200
commit495e79341b8bbbd43bcb92d4cff5ad87111886f0 (patch)
tree5f85d428ff5e6cdab336eef2fc033976582d9209
parent28055d044d0c21ff5556de52c3e273d5f4969408 (diff)
Fix bug in execution algorithms
-rw-r--r--build2/algorithm.cxx26
-rw-r--r--build2/target.hxx4
2 files changed, 9 insertions, 21 deletions
diff --git a/build2/algorithm.cxx b/build2/algorithm.cxx
index 5e18441..dc1c418 100644
--- a/build2/algorithm.cxx
+++ b/build2/algorithm.cxx
@@ -1020,11 +1020,6 @@ namespace build2
return t.executed_state ();
}
- // We use the target pointer mark mechanism to indicate whether the target
- // was already busy. Probably not worth it (we are saving an atomic load),
- // but what the hell. Note that this means we have to always "harvest" all
- // the targets to clear the mark.
- //
template <typename T>
target_state
straight_execute_members (action a, const target& t, T ts[], size_t n)
@@ -1051,14 +1046,13 @@ namespace build2
r |= s;
mt = nullptr;
}
- else if (s == target_state::busy)
- mark (mt);
}
wg.wait ();
- // Now all the targets in prerequisite_targets must be executed and
- // synchronized (and we have blanked out all the postponed ones).
+ // Now all the targets in prerequisite_targets must be either still busy
+ // or executed and synchronized (and we have blanked out all the postponed
+ // ones).
//
for (size_t i (0); i != n; ++i)
{
@@ -1067,9 +1061,9 @@ namespace build2
if (mt == nullptr)
continue;
- // If the target was already busy, wait for its completion.
+ // If the target is still busy, wait for its completion.
//
- if (unmark (mt))
+ if (mt->task_count.load (memory_order_acquire) >= target::count_busy ())
sched.wait (
target::count_executed (), mt->task_count, scheduler::work_none);
@@ -1105,8 +1099,6 @@ namespace build2
r |= s;
mt = nullptr;
}
- else if (s == target_state::busy)
- mark (mt);
}
wg.wait ();
@@ -1118,7 +1110,7 @@ namespace build2
if (mt == nullptr)
continue;
- if (unmark (mt))
+ if (mt->task_count.load (memory_order_acquire) >= target::count_busy ())
sched.wait (
target::count_executed (), mt->task_count, scheduler::work_none);
@@ -1181,8 +1173,6 @@ namespace build2
rs |= s;
pt = nullptr;
}
- else if (s == target_state::busy)
- mark (pt);
}
wg.wait ();
@@ -1197,9 +1187,7 @@ namespace build2
if (pt == nullptr)
continue;
- // If the target was already busy, wait for its completion.
- //
- if (unmark (pt))
+ if (pt->task_count.load (memory_order_acquire) >= target::count_busy ())
sched.wait (
target::count_executed (), pt->task_count, scheduler::work_none);
diff --git a/build2/target.hxx b/build2/target.hxx
index 92c5768..7cc7f95 100644
--- a/build2/target.hxx
+++ b/build2/target.hxx
@@ -478,8 +478,8 @@ namespace build2
mutable atomic_count task_count {0}; // Start offset_touched - 1.
// This function should only be called during match if we have observed
- // (synchronization-wise) that the this target has been matched (i.e.,
- // the rule has been applied) for this action.
+ // (synchronization-wise) that this target has been matched (i.e., the
+ // rule has been applied) for this action.
//
target_state
matched_state (action a, bool fail = true) const;