Dictionary <ulong, ThreadListType> RunDiscoveryIteration(bool ignoreCachedMemoryValues, out int expectedThreads) { LiveVariableQueryMode queryMode = ignoreCachedMemoryValues ? LiveVariableQueryMode.QueryDirectly : LiveVariableQueryMode.UseCacheIfAvailable; Dictionary <ulong, ThreadListType> result = new Dictionary <ulong, ThreadListType>(); expectedThreads = (int)_Root._uxCurrentNumberOfTasks.GetValue(queryMode).ToUlong(); if (expectedThreads < 0 || expectedThreads > 4096) { throw new Exception("Unexpected FreeRTOS thread count: " + expectedThreads); } foreach (var list in _ThreadLists) { list.Walk(_Root.Engine, result, _ProcessedNodes, expectedThreads + 1, _Cache, queryMode); } if (_IncludeCurrentTCB) { var pxCurrentTCB = _Root._pxCurrentTCB.GetValue(queryMode).ToUlong(); if (pxCurrentTCB != 0) { result[pxCurrentTCB] = ThreadListType.Running; } } return(result); }
public void Walk(ILiveWatchEngine engine, Dictionary <ulong, ThreadListType> result, HashSet <ulong> processedNodes, int maxThreadsToLoad, LinkedListNodeCache nodeCache, LiveVariableQueryMode queryMode) { int threadsFound = 0; ulong pxNext = 0; for (var pListNode = xListEnd_pxNext.GetValue(queryMode).ToUlong(); pListNode != 0 && !processedNodes.Contains(pListNode); pListNode = pxNext, threadsFound++) { if (threadsFound >= maxThreadsToLoad) { break; } processedNodes.Add(pListNode); try { var pTCB = pListNode - _ListItemOffsetInTCB; var cachedListNode = nodeCache.ProvideNode(pListNode); cachedListNode.ReadValues(queryMode, out ulong pvOwner, out pxNext); if (pvOwner != pTCB) { if ((uint)pvOwner == uint.MaxValue) { //This is the end-of-list node. Continue checking past it. continue; } else { //The list node doesn't point to the object itself anymore. Most likely, it has been freed and reused. cachedListNode.RemoveFromCache(); break; } } result[pTCB] = Type; } catch (Exception ex) { engine.LogException(ex, $"failed to process TCB node at {pListNode}"); break; } } }
ulong[] RunSingleDiscoveryIteration(out int expectedCount, LiveVariableQueryMode queryMode = LiveVariableQueryMode.UseCacheIfAvailable) { expectedCount = (int)(_ThreadList?.uxNumberOfItems?.GetValue().ToUlong() ?? 0); if (expectedCount == 0) { return(new ulong[0]); } Dictionary <ulong, ThreadListType> result = new Dictionary <ulong, ThreadListType>(); HashSet <ulong> processedNodes = new HashSet <ulong>(); _ThreadList.Walk(_Queue._Engine, result, processedNodes, expectedCount * 2, _Queue._Root.EventThreadListCache, queryMode); return(result.Keys.ToArray()); }
public void ReadValues(LiveVariableQueryMode queryMode, out ulong pvOwner, out ulong pxNext) { var value = _Variable.GetValue(queryMode); if (!value.IsValid) { pvOwner = pxNext = 0; } else { pvOwner = BitConverter.ToUInt32(value.Value, _Cache.pvOwner_RelativeOffset); pxNext = BitConverter.ToUInt32(value.Value, _Cache.pxNext_RelativeOffset); } }
public override LiveWatchNodeState UpdateState(LiveWatchUpdateContext context) { if (_ThreadList == null) { return(base.UpdateState(context)); } RawValue = _ThreadList.uxNumberOfItems.GetValue(); LiveVariableQueryMode queryMode = LiveVariableQueryMode.UseCacheIfAvailable; ulong[] taskAddresses = null; bool mismatch = true; for (int iter = 0; iter < 3; iter++) { taskAddresses = RunSingleDiscoveryIteration(out var expectedCount, queryMode); if (taskAddresses.Length == expectedCount) { mismatch = false; break; } queryMode = LiveVariableQueryMode.QueryDirectly; } string value = "---"; if (taskAddresses.Length > 0) { value = string.Join(", ", taskAddresses.Select(_Queue._Root.GetThreadName).ToArray()); } if (mismatch) { value += " (imprecise)"; } return(new LiveWatchNodeState { Value = value, Icon = LiveWatchNodeIcon.Thread, }); }