private static List <Tuple <XElement, XElement> > CreateNodeLabels(Dictionary <JoinableTask, XElement> tasksAndElements) { Requires.NotNull(tasksAndElements, nameof(tasksAndElements)); var result = new List <Tuple <XElement, XElement> >(); foreach (KeyValuePair <JoinableTask, XElement> tasksAndElement in tasksAndElements) { JoinableTask?pendingTask = tasksAndElement.Key; XElement? node = tasksAndElement.Value; int queueIndex = 0; foreach (JoinableTaskFactory.SingleExecuteProtector?pendingTasksElement in pendingTask.MainThreadQueueContents) { queueIndex++; XElement?callstackNode = Dgml.Node(node.Attribute("Id").Value + "MTQueue#" + queueIndex, GetAsyncReturnStack(pendingTasksElement)); XElement?callstackLink = Dgml.Link(callstackNode, node); result.Add(Tuple.Create(callstackNode, callstackLink)); } foreach (JoinableTaskFactory.SingleExecuteProtector?pendingTasksElement in pendingTask.ThreadPoolQueueContents) { queueIndex++; XElement?callstackNode = Dgml.Node(node.Attribute("Id").Value + "TPQueue#" + queueIndex, GetAsyncReturnStack(pendingTasksElement)); XElement?callstackLink = Dgml.Link(callstackNode, node); result.Add(Tuple.Create(callstackNode, callstackLink)); } } return(result); }
private static ICollection <XElement> CreateCollectionContainingTaskLinks(Dictionary <JoinableTask, XElement> tasks, Dictionary <JoinableTaskCollection, XElement> collections) { Requires.NotNull(tasks, nameof(tasks)); Requires.NotNull(collections, nameof(collections)); var result = new List <XElement>(); foreach (KeyValuePair <JoinableTask, XElement> task in tasks) { foreach (JoinableTaskCollection?collection in task.Key.ContainingCollections) { XElement?collectionElement = collections[collection]; result.Add(Dgml.Link(collectionElement, task.Value).WithCategories("Contains")); } } return(result); }
private static ICollection <XElement> CreatesLinksBetweenNodes(Dictionary <JoinableTask, XElement> pendingTasksElements) { Requires.NotNull(pendingTasksElements, nameof(pendingTasksElements)); var links = new List <XElement>(); foreach (KeyValuePair <JoinableTask, XElement> joinableTaskAndElement in pendingTasksElements) { foreach (JoinableTask?joinedTask in JoinableTaskDependencyGraph.GetAllDirectlyDependentJoinableTasks(joinableTaskAndElement.Key)) { if (pendingTasksElements.TryGetValue(joinedTask, out XElement? joinedTaskElement)) { links.Add(Dgml.Link(joinableTaskAndElement.Value, joinedTaskElement)); } } } return(links); }
private static ICollection <XElement> CreatesLinksBetweenNodes(Dictionary <JoinableTask, XElement> pendingTasksElements) { Requires.NotNull(pendingTasksElements, nameof(pendingTasksElements)); var links = new List <XElement>(); foreach (var joinableTaskAndElement in pendingTasksElements) { foreach (var joinedTask in joinableTaskAndElement.Key.ChildOrJoinedJobs) { if (pendingTasksElements.TryGetValue(joinedTask, out XElement joinedTaskElement)) { links.Add(Dgml.Link(joinableTaskAndElement.Value, joinedTaskElement)); } } } return(links); }
protected virtual HangReportContribution GetHangReport() { using (this.NoMessagePumpSynchronizationContext.Apply()) { // It's possible that the hang is due to a deadlock on our own private lock, // so while we're reporting the hang, don't accidentally deadlock ourselves // while trying to do the right thing by taking the lock. bool lockAcquired = false; try { Monitor.TryEnter(this.syncObject, 1000, ref lockAcquired); var dgml = CreateDgml(out XElement nodes, out XElement links); if (!lockAcquired) { nodes.Add(Dgml.Comment("WARNING: failed to acquire our own lock in formulating this report.")); } var liveAwaiterMetadata = new HashSet <AwaiterMetadata>(); liveAwaiterMetadata.UnionWith(this.waitingReaders.Select(a => new AwaiterMetadata(a, AwaiterCollection.Waiting | AwaiterCollection.ReadLock))); liveAwaiterMetadata.UnionWith(this.waitingUpgradeableReaders.Select(a => new AwaiterMetadata(a, AwaiterCollection.Waiting | AwaiterCollection.UpgradeableReadLock))); liveAwaiterMetadata.UnionWith(this.waitingWriters.Select(a => new AwaiterMetadata(a, AwaiterCollection.Waiting | AwaiterCollection.WriteLock))); liveAwaiterMetadata.UnionWith(this.issuedReadLocks.Select(a => new AwaiterMetadata(a, AwaiterCollection.Issued | AwaiterCollection.ReadLock))); liveAwaiterMetadata.UnionWith(this.issuedUpgradeableReadLocks.Select(a => new AwaiterMetadata(a, AwaiterCollection.Issued | AwaiterCollection.UpgradeableReadLock))); liveAwaiterMetadata.UnionWith(this.issuedWriteLocks.Select(a => new AwaiterMetadata(a, AwaiterCollection.Issued | AwaiterCollection.WriteLock))); var liveAwaiters = liveAwaiterMetadata.Select(am => am.Awaiter); var releasedAwaiterMetadata = new HashSet <AwaiterMetadata>(liveAwaiters.SelectMany(GetLockStack).Distinct().Except(liveAwaiters).Select(AwaiterMetadata.Released)); var allAwaiterMetadata = new HashSet <AwaiterMetadata>(liveAwaiterMetadata.Concat(releasedAwaiterMetadata)); // Build the lock stack containers. dgml.WithContainers(allAwaiterMetadata.Select(am => am.GroupId).Distinct().Select(id => Dgml.Container(id, "Lock stack"))); // Add each lock awaiter. nodes.Add(allAwaiterMetadata.Select(am => CreateAwaiterNode(am.Awaiter).WithCategories(am.Categories.ToArray()).ContainedBy(am.GroupId, dgml))); // Link the lock stacks among themselves. links.Add(allAwaiterMetadata.Where(a => a.Awaiter.NestingLock != null).Select(a => Dgml.Link(GetAwaiterId(a.Awaiter.NestingLock), GetAwaiterId(a.Awaiter)))); return(new HangReportContribution( dgml.ToString(), "application/xml", this.GetType().Name + ".dgml")); } finally { if (lockAcquired) { Monitor.Exit(this.syncObject); } } } }