Fix top-down resolve re-walking graph too much.

Firing off multiple concurrent walks of the same sub-tree with the same
conditions. Data race meant every walk would proceed. Move the logic to
entry of walk function and compare under lock.

Bug: 255526010

Test: m droid

Test: m out/soong/.intermediates/packages/modules/StatsD/apex/com.android.os.statsd/android_common_com.android.os.statsd_image/NOTICE.html.gz

Change-Id: Ie30edbb2ac9eaa9aa55badfc518d51eaadbb6be6
This commit is contained in:
Bob Badour
2022-10-25 19:56:33 -07:00
parent aff9f3a77c
commit d2c28ba897

View File

@@ -171,42 +171,47 @@ func TraceTopDownConditions(lg *LicenseGraph, conditionsFn TraceConditions) {
walk = func(fnode *TargetNode, cs LicenseConditionSet, treatAsAggregate bool) {
defer wg.Done()
continueWalk := func() bool {
mu.Lock()
defer mu.Unlock()
depcs := fnode.resolution
_, alreadyWalked := amap[fnode]
if alreadyWalked {
if cs.IsEmpty() {
return false
}
if cs.Difference(depcs).IsEmpty() {
// no new conditions
// pure aggregates never need walking a 2nd time with same conditions
if treatAsAggregate {
return false
}
// non-aggregates don't need walking as non-aggregate a 2nd time
if !fnode.pure {
return false
}
// previously walked as pure aggregate; need to re-walk as non-aggregate
}
}
fnode.resolution |= conditionsFn(fnode)
fnode.resolution |= cs
fnode.pure = treatAsAggregate
amap[fnode] = struct{}{}
cs = fnode.resolution
mu.Unlock()
return true
}()
if !continueWalk {
return
}
// for each dependency
for _, edge := range fnode.edges {
func(edge *TargetEdge) {
// dcs holds the dpendency conditions inherited from the target
dcs := targetConditionsPropagatingToDep(lg, edge, cs, treatAsAggregate, conditionsFn)
dnode := edge.dependency
mu.Lock()
defer mu.Unlock()
depcs := dnode.resolution
_, alreadyWalked := amap[dnode]
if !dcs.IsEmpty() && alreadyWalked {
if dcs.Difference(depcs).IsEmpty() {
// no new conditions
// pure aggregates never need walking a 2nd time with same conditions
if treatAsAggregate {
return
}
// non-aggregates don't need walking as non-aggregate a 2nd time
if !dnode.pure {
return
}
// previously walked as pure aggregate; need to re-walk as non-aggregate
}
}
// add the conditions to the dependency
wg.Add(1)
go walk(dnode, dcs, treatAsAggregate && dnode.IsContainer())
}(edge)
}
}