public static ThreadBlockGraph BuildThreadBlockGraph(ClrThread[] threads, BlockingObject[] blocks, out string error) { error = null; try { var thrCmp = new ClrThreadCmp(); var blkCmp = new BlockingObjectCmp(); var ownerGraph = new List <KeyValuePair <int, List <int> > >(threads.Length); var waiterGraph = new Dictionary <int, List <int> >(threads.Length); var thSet = new HashSet <int>(); var blkSet = new HashSet <int>(); for (int i = 0, icnt = blocks.Length; i < icnt; ++i) { var blk = blocks[i]; if (blk.Taken && blk.HasSingleOwner && blk.Owner != null) { var ndx = Array.BinarySearch(threads, blk.Owner, thrCmp); if (ndx != Constants.InvalidIndex) { ownerGraph.Add(new KeyValuePair <int, List <int> >(i, new List <int>() { ndx })); thSet.Add(ndx); blkSet.Add(i); } } else if (blk.Owners != null && blk.Owners.Count > 0) { List <int> owners = null; foreach (ClrThread th in blk.Owners) { if (th != null) { var ndx = Array.BinarySearch(threads, th, thrCmp); if (ndx != Constants.InvalidIndex) { if (owners == null) { owners = new List <int>(); } owners.Add(ndx); thSet.Add(ndx); } } } if (owners != null) { ownerGraph.Add(new KeyValuePair <int, List <int> >(i, owners)); blkSet.Add(i); } } if (blk.Waiters != null && blk.Waiters.Count > 0) { // List<int> waiters = null; bool hasWaiters = false; foreach (ClrThread th in blk.Waiters) { if (th != null) { var ndx = Array.BinarySearch(threads, th, thrCmp); if (ndx != Constants.InvalidIndex) { List <int> blks; if (waiterGraph.TryGetValue(ndx, out blks)) { if (!blks.Contains(i)) { blks.Add(i); } } else { waiterGraph.Add(ndx, new List <int>() { i }); } thSet.Add(ndx); hasWaiters = true; } } } if (hasWaiters) { blkSet.Add(i); } } } var graph = new int[thSet.Count + blkSet.Count][]; // for circuit check for (int i = 0, icnt = graph.Length; i < icnt; ++i) { graph[i] = Utils.EmptyArray <int> .Value; } var thary = thSet.ToArray(); Array.Sort(thary); var blkary = blkSet.ToArray(); Array.Sort(blkary); int edgeCount = 0; int graphThreadCnt = thary.Length; foreach (var kv in waiterGraph) { int thGraphNdx = Array.BinarySearch(thary, kv.Key); Debug.Assert(thGraphNdx >= 0); var graphAry = new int[kv.Value.Count]; for (int i = 0, icnt = graphAry.Length; i < icnt; ++i) { int blkGraphNdx = Array.BinarySearch(blkary, kv.Value[i]); Debug.Assert(blkGraphNdx >= 0); graphAry[i] = blkGraphNdx + graphThreadCnt; } graph[thGraphNdx] = graphAry; edgeCount += graphAry.Length; } int tharylen = thary.Length; for (int i = 0, icnt = ownerGraph.Count; i < icnt; ++i) { int blkGraphNdx = Array.BinarySearch(blkary, ownerGraph[i].Key); Debug.Assert(blkGraphNdx >= 0); List <int> lst = ownerGraph[i].Value; var graphAry = new int[lst.Count]; for (int j = 0, jcnt = graphAry.Length; j < jcnt; ++j) { int thGraphNdx = Array.BinarySearch(thary, lst[j]); Debug.Assert(thGraphNdx >= 0); graphAry[j] = thGraphNdx; } graph[blkGraphNdx + graphThreadCnt] = graphAry; edgeCount += graphAry.Length; } var map = new int[thary.Length + blkary.Length]; Array.Copy(thary, 0, map, 0, thary.Length); Array.Copy(blkary, 0, map, thary.Length, blkary.Length); int[][] deadlock = null; if (DGraph.HasCycle(graph)) { deadlock = Circuits.GetCycles(graph, out error); } return(new ThreadBlockGraph(graph, edgeCount, graphThreadCnt, map, deadlock)); } catch (Exception ex) { error = Utils.GetExceptionErrorString(ex); return(null); } }
public static bool Dump(BinaryWriter wr, DGraph graph, out string error) { return(Dump(wr, graph.Graph, graph.EdgeCount, out error)); }