diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2020-06-12 21:35:39 +0200 |
---|---|---|
committer | Milian Wolff <milian.wolff@kdab.com> | 2020-09-11 10:30:40 +0000 |
commit | fdb22739980e188aadfa369881f50bf737e82c43 (patch) | |
tree | a6ab24b76c51d28822c2407f1a1ec33f49cd8231 /app/perfunwind.cpp | |
parent | d793de5b3c6aa88c556609935fdee41884b24a7e (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.cpp | 16 |
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); |