aboutsummaryrefslogtreecommitdiff
path: root/tools/gator/daemon/PerfBuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gator/daemon/PerfBuffer.cpp')
-rw-r--r--tools/gator/daemon/PerfBuffer.cpp65
1 files changed, 42 insertions, 23 deletions
diff --git a/tools/gator/daemon/PerfBuffer.cpp b/tools/gator/daemon/PerfBuffer.cpp
index 5fad583f7bd0..f127c996d43b 100644
--- a/tools/gator/daemon/PerfBuffer.cpp
+++ b/tools/gator/daemon/PerfBuffer.cpp
@@ -20,6 +20,7 @@ PerfBuffer::PerfBuffer() {
for (int cpu = 0; cpu < ARRAY_LENGTH(mBuf); ++cpu) {
mBuf[cpu] = MAP_FAILED;
mDiscard[cpu] = false;
+ mFds[cpu] = -1;
}
}
@@ -31,8 +32,8 @@ PerfBuffer::~PerfBuffer() {
}
}
-bool PerfBuffer::useFd(const int cpu, const int fd, const int groupFd) {
- if (fd == groupFd) {
+bool PerfBuffer::useFd(const int cpu, const int fd) {
+ if (mFds[cpu] < 0) {
if (mBuf[cpu] != MAP_FAILED) {
logg->logMessage("%s(%s:%i): cpu %i already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__, cpu);
return false;
@@ -44,6 +45,7 @@ bool PerfBuffer::useFd(const int cpu, const int fd, const int groupFd) {
logg->logMessage("%s(%s:%i): mmap failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
+ mFds[cpu] = fd;
// Check the version
struct perf_event_mmap_page *pemp = static_cast<struct perf_event_mmap_page *>(mBuf[cpu]);
@@ -57,7 +59,7 @@ bool PerfBuffer::useFd(const int cpu, const int fd, const int groupFd) {
return false;
}
- if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, groupFd) < 0) {
+ if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, mFds[cpu]) < 0) {
logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
@@ -89,6 +91,41 @@ bool PerfBuffer::isEmpty() {
return true;
}
+static void compressAndSend(const int cpu, const __u64 head, __u64 tail, const uint8_t *const b, Sender *const sender) {
+ // Pick a big size but something smaller than the chunkSize in Sender::writeData which is 100k
+ char buf[1<<16];
+ int writePos = 0;
+ const int typeLength = gSessionData->mLocalCapture ? 0 : 1;
+
+ while (head > tail) {
+ writePos = 0;
+ if (!gSessionData->mLocalCapture) {
+ buf[writePos++] = RESPONSE_APC_DATA;
+ }
+ // Reserve space for size
+ writePos += sizeof(uint32_t);
+ Buffer::packInt(buf, sizeof(buf), writePos, FRAME_PERF);
+ Buffer::packInt(buf, sizeof(buf), writePos, cpu);
+
+ while (head > tail) {
+ const int count = reinterpret_cast<const struct perf_event_header *>(b + (tail & BUF_MASK))->size/sizeof(uint64_t);
+ // Can this whole message be written as Streamline assumes events are not split between frames
+ if (sizeof(buf) <= writePos + count*Buffer::MAXSIZE_PACK64) {
+ break;
+ }
+ for (int i = 0; i < count; ++i) {
+ // Must account for message size
+ Buffer::packInt64(buf, sizeof(buf), writePos, *reinterpret_cast<const uint64_t *>(b + (tail & BUF_MASK)));
+ tail += sizeof(uint64_t);
+ }
+ }
+
+ // Write size
+ Buffer::writeLEInt(reinterpret_cast<unsigned char *>(buf + typeLength), writePos - typeLength - sizeof(uint32_t));
+ sender->writeData(buf, writePos, RESPONSE_APC_DATA);
+ }
+}
+
bool PerfBuffer::send(Sender *const sender) {
for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
if (mBuf[cpu] == MAP_FAILED) {
@@ -102,26 +139,7 @@ bool PerfBuffer::send(Sender *const sender) {
if (head > tail) {
const uint8_t *const b = static_cast<uint8_t *>(mBuf[cpu]) + gSessionData->mPageSize;
- const int offset = gSessionData->mLocalCapture ? 1 : 0;
- unsigned char header[7];
- header[0] = RESPONSE_APC_DATA;
- Buffer::writeLEInt(header + 1, head - tail + sizeof(header) - 5);
- // Should use real packing functions
- header[5] = FRAME_PERF;
- header[6] = cpu;
-
- // Write header
- sender->writeData(reinterpret_cast<const char *>(&header) + offset, sizeof(header) - offset, RESPONSE_APC_DATA);
-
- // Write data
- if ((head & ~BUF_MASK) == (tail & ~BUF_MASK)) {
- // Not wrapped
- sender->writeData(reinterpret_cast<const char *>(b + (tail & BUF_MASK)), head - tail, RESPONSE_APC_DATA);
- } else {
- // Wrapped
- sender->writeData(reinterpret_cast<const char *>(b + (tail & BUF_MASK)), BUF_SIZE - (tail & BUF_MASK), RESPONSE_APC_DATA);
- sender->writeData(reinterpret_cast<const char *>(b), head & BUF_MASK, RESPONSE_APC_DATA);
- }
+ compressAndSend(cpu, head, tail, b, sender);
// Update tail with the data read
pemp->data_tail = head;
@@ -131,6 +149,7 @@ bool PerfBuffer::send(Sender *const sender) {
munmap(mBuf[cpu], gSessionData->mPageSize + BUF_SIZE);
mBuf[cpu] = MAP_FAILED;
mDiscard[cpu] = false;
+ mFds[cpu] = -1;
logg->logMessage("%s(%s:%i): Unmaped cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);
}
}