summaryrefslogtreecommitdiffstats
path: root/app/perfunwind.cpp
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2020-06-12 21:35:39 +0200
committerMilian Wolff <milian.wolff@kdab.com>2020-09-11 10:30:40 +0000
commitfdb22739980e188aadfa369881f50bf737e82c43 (patch)
treea6ab24b76c51d28822c2407f1a1ec33f49cd8231 /app/perfunwind.cpp
parentd793de5b3c6aa88c556609935fdee41884b24a7e (diff)
Improve support for applications that rely on fork for parallelism
A forked process inherits the elfmap of the parent, thus we need to copy that data when we encounter a fork event. This is complicated by the fact that the task events and mmap events need to be sorted first. Thus, we need to find the fork event when we deplete the buffers after sorting and then initialize the child process elf map with the one from the parent process. Furthermore, pass the ppid through the ThreadStart event, to allow client applications to inherit the comm for the newly created process. Fixes: https://github.com/KDAB/hotspot/issues/241 Change-Id: I5de13644e12def6704c5f622428a815fd87d2af4 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'app/perfunwind.cpp')
-rw-r--r--app/perfunwind.cpp16
1 files changed, 12 insertions, 4 deletions
diff --git a/app/perfunwind.cpp b/app/perfunwind.cpp
index 07ead96..e277191 100644
--- a/app/perfunwind.cpp
+++ b/app/perfunwind.cpp
@@ -689,7 +689,7 @@ void PerfUnwind::analyze(const PerfRecordSample &sample)
void PerfUnwind::fork(const PerfRecordFork &sample)
{
bufferEvent(TaskEvent{sample.childPid(), sample.childTid(), sample.time(), sample.cpu(),
- 0, ThreadStart},
+ sample.parentPid(), ThreadStart},
&m_taskEventsBuffer, &m_stats.numTaskEventsInRound);
}
@@ -948,16 +948,24 @@ void PerfUnwind::flushEventBuffer(uint desiredBufferSize)
m_lastFlushMaxTime = timestamp;
}
- forwardMmapBuffer(mmapIt, mmapEnd, timestamp);
-
for (; taskEventIt != taskEventEnd && taskEventIt->time() <= sampleIt->time();
++taskEventIt) {
if (!m_stats.enabled) {
+ // flush the mmap buffer on fork events to allow initialization with the correct state
+ if (taskEventIt->m_type == ThreadStart && taskEventIt->m_pid != taskEventIt->m_payload) {
+ forwardMmapBuffer(mmapIt, mmapEnd, taskEventIt->time());
+ const auto childPid = taskEventIt->m_pid;
+ const auto parentPid = taskEventIt->m_payload;
+ symbolTable(childPid)->initAfterFork(symbolTable(parentPid));
+ }
+
sendTaskEvent(*taskEventIt);
}
m_eventBufferSize -= taskEventIt->size();
}
+ forwardMmapBuffer(mmapIt, mmapEnd, timestamp);
+
analyze(*sampleIt);
m_eventBufferSize -= sampleIt->size();
}
@@ -1034,7 +1042,7 @@ void PerfUnwind::sendTaskEvent(const TaskEvent& taskEvent)
if (taskEvent.m_type == ContextSwitchDefinition)
stream << static_cast<bool>(taskEvent.m_payload);
- else if (taskEvent.m_type == Command)
+ else if (taskEvent.m_type == Command || taskEvent.m_type == ThreadStart)
stream << taskEvent.m_payload;
sendBuffer(buffer);