From b7238a711792e729e6974c556e998d335778362a Mon Sep 17 00:00:00 2001 From: Arnaud Fiorini Date: Wed, 6 May 2026 15:57:08 -0400 Subject: [PATCH 1/2] callstack: add the possibility of having multiple callstacks having the same tid Signed-off-by: Arnaud Fiorini --- .../instrumented/FlameChartDataProvider.java | 47 ++++++++++--------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/analysis/org.eclipse.tracecompass.analysis.profiling.core/src/org/eclipse/tracecompass/internal/analysis/profiling/core/instrumented/FlameChartDataProvider.java b/analysis/org.eclipse.tracecompass.analysis.profiling.core/src/org/eclipse/tracecompass/internal/analysis/profiling/core/instrumented/FlameChartDataProvider.java index 9e02d8f1a0..ea64b6cee0 100644 --- a/analysis/org.eclipse.tracecompass.analysis.profiling.core/src/org/eclipse/tracecompass/internal/analysis/profiling/core/instrumented/FlameChartDataProvider.java +++ b/analysis/org.eclipse.tracecompass.analysis.profiling.core/src/org/eclipse/tracecompass/internal/analysis/profiling/core/instrumented/FlameChartDataProvider.java @@ -289,6 +289,7 @@ public TmfModelResponse> fetchTooltip(Map fe return new TmfModelResponse<>(tooltip, Status.COMPLETED, CommonStatusMessage.COMPLETED); } } + private @Nullable Map getTooltip(Long entryId, FlameChartEntryModel entryModel, Long time) { switch (entryModel.getEntryType()) { case FUNCTION: { @@ -579,23 +580,27 @@ private Map> getKernelStates(List ti Map> kernelStates = new HashMap<>(); IHostModel model = ModelManager.getModelFor(getTrace().getHostId()); - Map threadIdsToEntryIds = tids.stream().collect(Collectors.toMap(tid -> tid.fTid.getTid(), tid -> tid.fLinked)); + Map> threadIdsToEntryIds = tids.stream().collect(Collectors.groupingBy( + tid -> tid.fTid.getTid(), + Collectors.mapping(tid -> tid.fLinked, Collectors.toSet()))); Map> kernelStatuses = model.getThreadStatusIntervals(threadIdsToEntryIds.keySet(), times, monitor); for (Entry> processStatuses : kernelStatuses.entrySet()) { - Long linkedEntryId = threadIdsToEntryIds.get(processStatuses.getKey()); - if (linkedEntryId == null) { + Set linkedEntryIds = threadIdsToEntryIds.get(processStatuses.getKey()); + if (linkedEntryIds == null) { continue; } - Long entryId = fLinkedEntries.get(linkedEntryId); - if (entryId == null) { - entryId = linkedEntryId; - } - List states = kernelStates.computeIfAbsent(linkedEntryId, k -> new ArrayList<>()); - for (ProcessStatusInterval processStatus : Objects.requireNonNull(processStatuses.getValue())) { - OutputElementStyle style = new OutputElementStyle( - FlameWithKernelPalette.getStyleFor(processStatus.getProcessStatus().getStateValue().unboxInt())); - ITimeGraphState state = new TimeGraphState(processStatus.getStart(), processStatus.getLength(), processStatus.getSyscallName(), style); - applyFilterAndAddState(states, state, entryId, predicates, monitor); + for (Long linkedEntryId : linkedEntryIds) { + Long entryId = fLinkedEntries.get(linkedEntryId); + if (entryId == null) { + entryId = linkedEntryId; + } + List states = kernelStates.computeIfAbsent(linkedEntryId, k -> new ArrayList<>()); + for (ProcessStatusInterval processStatus : Objects.requireNonNull(processStatuses.getValue())) { + OutputElementStyle style = new OutputElementStyle( + FlameWithKernelPalette.getStyleFor(processStatus.getProcessStatus().getStateValue().unboxInt())); + ITimeGraphState state = new TimeGraphState(processStatus.getStart(), processStatus.getLength(), processStatus.getSyscallName(), style); + applyFilterAndAddState(states, state, entryId, predicates, monitor); + } } } return kernelStates; @@ -727,7 +732,7 @@ public TmfModelResponse fetchStyle(Map fetchPa @Override public TmfModelResponse fetchAnnotationCategories(Map fetchParameters, @Nullable IProgressMonitor monitor) { - return new TmfModelResponse<>(new AnnotationCategoriesModel(Collections.singletonList( InstrumentedCallStackAnalysis.ANNOTATIONS)), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED); + return new TmfModelResponse<>(new AnnotationCategoriesModel(Collections.singletonList(InstrumentedCallStackAnalysis.ANNOTATIONS)), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED); } @Override @@ -758,7 +763,7 @@ public TmfModelResponse fetchAnnotations(Map fe continue; } int parentQuark = ss.getParentAttributeQuark(ss.getParentAttributeQuark(cs.getQuark())); - int markersQuark = ss.optQuarkRelative(parentQuark, InstrumentedCallStackAnalysis.ANNOTATIONS); + int markersQuark = ss.optQuarkRelative(parentQuark, InstrumentedCallStackAnalysis.ANNOTATIONS); if (markersQuark != ITmfStateSystem.INVALID_ATTRIBUTE) { List times = DataProviderParameterUtils.extractTimeRequested(fetchParameters); for (ITmfStateInterval markerInterval : ss.query2D(Collections.singleton(markersQuark), times)) { @@ -780,11 +785,11 @@ public TmfModelResponse fetchAnnotations(Map fe ITmfStateValue a = markerInterval.getStateValue(); String annotValue = a.toString(); - OutputElementStyle style = new OutputElementStyle(null, ImmutableMap.of( - StyleProperties.COLOR, "#7D3D31", //$NON-NLS-1$ - StyleProperties.HEIGHT, 0.33f, - StyleProperties.SYMBOL_TYPE, SymbolType.DIAMOND)); - annotations.add(new Annotation(startTime, 0, rowId, annotValue, style)); + OutputElementStyle style = new OutputElementStyle(null, ImmutableMap.of( + StyleProperties.COLOR, "#7D3D31", //$NON-NLS-1$ + StyleProperties.HEIGHT, 0.33f, + StyleProperties.SYMBOL_TYPE, SymbolType.DIAMOND)); + annotations.add(new Annotation(startTime, 0, rowId, annotValue, style)); } } } @@ -793,6 +798,6 @@ public TmfModelResponse fetchAnnotations(Map fe return new TmfModelResponse<>(null, ITmfResponse.Status.FAILED, e.getMessage()); } - return new TmfModelResponse<>(new AnnotationModel(Collections.singletonMap( InstrumentedCallStackAnalysis.ANNOTATIONS, annotations)), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED); + return new TmfModelResponse<>(new AnnotationModel(Collections.singletonMap(InstrumentedCallStackAnalysis.ANNOTATIONS, annotations)), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED); } } From 9a9e5c5e309628403613d36f2c172973c7fb2f55 Mon Sep 17 00:00:00 2001 From: Arnaud Fiorini Date: Wed, 6 May 2026 16:15:23 -0400 Subject: [PATCH 2/2] kernel: make status for threads work again Signed-off-by: Arnaud Fiorini --- .../linux/core/kernel/KernelThreadInformationProvider.java | 2 +- .../profiling/core/tests/FlameChartDataProviderTest.java | 5 +++-- .../profiling/core/tests/stubs2/KernelStateProviderStub.java | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernel/KernelThreadInformationProvider.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernel/KernelThreadInformationProvider.java index 4fdd70ad0d..4316b26fc8 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernel/KernelThreadInformationProvider.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.core/src/org/eclipse/tracecompass/analysis/os/linux/core/kernel/KernelThreadInformationProvider.java @@ -548,7 +548,7 @@ public static Map> getStatusIntervalsForThreads if (ss == null) { return Objects.requireNonNull(Collections.emptyMap()); } - List currentTimes = times.stream().filter(time -> (time > ss.getCurrentEndTime() || time < ss.getStartTime())).sorted().collect(Collectors.toList()); + List currentTimes = times.stream().filter(time -> (time < ss.getCurrentEndTime() && time > ss.getStartTime())).sorted().collect(Collectors.toList()); if (currentTimes.isEmpty()) { return Objects.requireNonNull(Collections.emptyMap()); } diff --git a/analysis/org.eclipse.tracecompass.analysis.profiling.core.tests/src/org/eclipse/tracecompass/analysis/profiling/core/tests/FlameChartDataProviderTest.java b/analysis/org.eclipse.tracecompass.analysis.profiling.core.tests/src/org/eclipse/tracecompass/analysis/profiling/core/tests/FlameChartDataProviderTest.java index 659b6a00f2..11e1fe93a3 100644 --- a/analysis/org.eclipse.tracecompass.analysis.profiling.core.tests/src/org/eclipse/tracecompass/analysis/profiling/core/tests/FlameChartDataProviderTest.java +++ b/analysis/org.eclipse.tracecompass.analysis.profiling.core.tests/src/org/eclipse/tracecompass/analysis/profiling/core/tests/FlameChartDataProviderTest.java @@ -262,7 +262,7 @@ public void testFetchModel() { new TimeGraphState(6, 2, null, new OutputElementStyle(LinuxStyle.WAIT_FOR_CPU.getLabel())), new TimeGraphState(8, 2, null, new OutputElementStyle(LinuxStyle.USERMODE.getLabel())), new TimeGraphState(10, 2, null, new OutputElementStyle(LinuxStyle.WAIT_FOR_CPU.getLabel())), - new TimeGraphState(12, 8, null, new OutputElementStyle(LinuxStyle.USERMODE.getLabel()))), true); + new TimeGraphState(12, 8, "openat", new OutputElementStyle(LinuxStyle.SYSCALL.getLabel()))), true); // Get the row model for those entries with low resolution rowResponse = dataProvider.fetchRowModel(FetchParametersUtils.selectionTimeQueryToMap(new SelectionTimeQueryFilter(3, 15, 2, selectedIds)), new NullProgressMonitor()); @@ -300,7 +300,7 @@ public void testFetchModel() { // Verify kernel statuses of tid 6 verifyStates(rows, FlameDataProviderTestUtils.findEntryByDepthAndType(tid6Children, -1, EntryType.KERNEL), ImmutableList.of( new TimeGraphState(1, 5, null, new OutputElementStyle(LinuxStyle.USERMODE.getLabel())), - new TimeGraphState(12, 8, null, new OutputElementStyle(LinuxStyle.USERMODE.getLabel()))), true); + new TimeGraphState(12, 8, "openat", new OutputElementStyle(LinuxStyle.SYSCALL.getLabel()))), true); // Check arrows FlameChartEntryModel tid2 = FlameDataProviderTestUtils.findEntryByNameAndType(modelEntries, "2", EntryType.LEVEL); @@ -436,6 +436,7 @@ private static void verifyStates(List rowModels, FlameChartE assertNotNull(rowModel); @SuppressWarnings("null") List states = rowModel.getStates(); + assertEquals(expectedStates.size(), states.size()); for (int i = 0; i < states.size(); i++) { String entryName = entry.getName(); if (i > expectedStates.size() - 1) { diff --git a/analysis/org.eclipse.tracecompass.analysis.profiling.core.tests/stubs/org/eclipse/tracecompass/analysis/profiling/core/tests/stubs2/KernelStateProviderStub.java b/analysis/org.eclipse.tracecompass.analysis.profiling.core.tests/stubs/org/eclipse/tracecompass/analysis/profiling/core/tests/stubs2/KernelStateProviderStub.java index 45d071af63..603c03133b 100644 --- a/analysis/org.eclipse.tracecompass.analysis.profiling.core.tests/stubs/org/eclipse/tracecompass/analysis/profiling/core/tests/stubs2/KernelStateProviderStub.java +++ b/analysis/org.eclipse.tracecompass.analysis.profiling.core.tests/stubs/org/eclipse/tracecompass/analysis/profiling/core/tests/stubs2/KernelStateProviderStub.java @@ -59,14 +59,15 @@ public ITmfStateProvider getNewInstance() { @Override protected void eventHandle(ITmfEvent event) { ITmfStateSystemBuilder ssb = getStateSystemBuilder(); - if (ssb == null) { + if (ssb == null || event.getName().equals("instant_event")) { return; } int threadQuark = ssb.getQuarkAbsoluteAndAdd(Attributes.THREADS, event.getContent().getFieldValue(String.class, "tid")); boolean isEntry = event.getName().equals(ENTRY); long timestamp = event.getTimestamp().getValue(); if (isEntry) { - if (event.getName().equals("op4")) { + String operationName = event.getContent().getFieldValue(String.class, "op"); + if (operationName != null && operationName.equals("op4")) { int systemCallQuark = ssb.getQuarkRelativeAndAdd(threadQuark, Attributes.SYSTEM_CALL); ssb.modifyAttribute(timestamp, "openat", systemCallQuark); /* Put the process in system call mode */