Skip to content

Commit 4c9f289

Browse files
committed
Add test and fix priority bug
AddTarget cannot add edges to the ready queue before the critical time has been computed.
1 parent bb82c7e commit 4c9f289

File tree

3 files changed

+231
-37
lines changed

3 files changed

+231
-37
lines changed

src/build.cc

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,6 @@ bool Plan::AddSubTarget(const Node* node, const Node* dependent, string* err,
124124
if (node->dirty() && want == kWantNothing) {
125125
want = kWantToStart;
126126
EdgeWanted(edge);
127-
if (!dyndep_walk && edge->AllInputsReady())
128-
ScheduleWork(want_ins.first);
129127
}
130128

131129
if (dyndep_walk)
@@ -514,14 +512,27 @@ int64_t AssignEdgeRuntime(BuildLog* build_log,
514512
return total_time;
515513
}
516514

515+
int64_t AssignDefaultEdgeRuntime(std::map<Edge*, Plan::Want> &want) {
516+
int64_t total_time = 0;
517+
518+
for (std::map<Edge*, Plan::Want>::const_iterator it = want.begin(),
519+
end = want.end();
520+
it != end; ++it) {
521+
Edge* edge = it->first;
522+
if (edge->is_phony()) {
523+
continue;
524+
}
525+
526+
edge->set_run_time_ms(1);
527+
++total_time;
528+
}
529+
return total_time;
530+
}
531+
517532
} // namespace
518533

519534
void Plan::ComputeCriticalTime(BuildLog* build_log) {
520-
// testcases have no build_log
521-
if (!build_log)
522-
return;
523-
524-
METRIC_RECORD("ComputePriorityList");
535+
METRIC_RECORD("ComputeCriticalTime");
525536
// Remove duplicate targets
526537
{
527538
std::set<const Node*> seen;
@@ -533,7 +544,10 @@ void Plan::ComputeCriticalTime(BuildLog* build_log) {
533544
// total time if building all edges in serial. This value is big
534545
// enough to ensure higher priority target's initial critical time
535546
// is always bigger than lower ones
536-
int64_t total_time = AssignEdgeRuntime(build_log, want_);
547+
const int64_t total_time = build_log ?
548+
AssignEdgeRuntime(build_log, want_) :
549+
AssignDefaultEdgeRuntime(want_); // Plan tests have no build_log
550+
537551

538552
// Use backflow algorithm to compute critical times for all nodes, starting
539553
// from the destination nodes.
@@ -582,6 +596,42 @@ void Plan::ComputeCriticalTime(BuildLog* build_log) {
582596
}
583597
}
584598

599+
void Plan::ScheduleInitialEdges() {
600+
// Add ready edges to queue.
601+
assert(ready_.empty());
602+
std::set<Pool*> pools;
603+
604+
for (std::map<Edge*, Plan::Want>::iterator it = want_.begin(),
605+
end = want_.end(); it != end; ++it) {
606+
Edge* edge = it->first;
607+
Plan::Want want = it->second;
608+
if (!(want == kWantToStart && edge->AllInputsReady())) {
609+
continue;
610+
}
611+
612+
Pool* pool = edge->pool();
613+
if (pool->ShouldDelayEdge()) {
614+
pool->DelayEdge(edge);
615+
pools.insert(pool);
616+
} else {
617+
ScheduleWork(it);
618+
}
619+
}
620+
621+
// Call RetrieveReadyEdges only once at the end so higher priority
622+
// edges are retrieved first, not the ones that happen to be first
623+
// in the want_ map.
624+
for (std::set<Pool*>::iterator it=pools.begin(),
625+
end = pools.end(); it != end; ++it) {
626+
(*it)->RetrieveReadyEdges(&ready_);
627+
}
628+
}
629+
630+
void Plan::PrepareQueue(BuildLog* build_log) {
631+
ComputeCriticalTime(build_log);
632+
ScheduleInitialEdges();
633+
}
634+
585635
void Plan::Dump() const {
586636
printf("pending: %d\n", (int)want_.size());
587637
for (map<Edge*, Want>::const_iterator e = want_.begin(); e != want_.end(); ++e) {
@@ -743,8 +793,7 @@ bool Builder::AlreadyUpToDate() const {
743793

744794
bool Builder::Build(string* err) {
745795
assert(!AlreadyUpToDate());
746-
747-
plan_.ComputeCriticalTime(scan_.build_log());
796+
plan_.PrepareQueue(scan_.build_log());
748797

749798
status_->PlanHasTotalEdges(plan_.command_edge_count());
750799
int pending_commands = 0;

src/build.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ struct Plan {
7474

7575
/// Reset state. Clears want and ready sets.
7676
void Reset();
77-
void ComputeCriticalTime(BuildLog* build_log);
77+
78+
// After all targets have been added, prepares the ready queue for find work.
79+
void PrepareQueue(BuildLog* build_log);
7880

7981
/// Update the build plan to account for modifications made to the graph
8082
/// by information loaded from a dyndep file.
@@ -95,11 +97,16 @@ struct Plan {
9597
};
9698

9799
private:
100+
void ComputeCriticalTime(BuildLog* build_log);
98101
bool RefreshDyndepDependents(DependencyScan* scan, const Node* node, std::string* err);
99102
void UnmarkDependents(const Node* node, std::set<Node*>* dependents);
100103
bool AddSubTarget(const Node* node, const Node* dependent, std::string* err,
101104
std::set<Edge*>* dyndep_walk);
102105

106+
// Add edges that kWantToStart into the ready queue
107+
// Must be called after ComputeCriticalTime and before FindWork
108+
void ScheduleInitialEdges();
109+
103110
/// Update plan with knowledge that the given node is up to date.
104111
/// If the node is a dyndep binding on any of its dependents, this
105112
/// loads dynamic dependencies from the node's path.

0 commit comments

Comments
 (0)