blob: 2c45de8e06e9bdf6beb72130eb74796f184388ea [file] [log] [blame]
Jon Medhurst15ce78d2014-04-10 09:02:02 +01001/**
Jon Medhurstb1d07442015-05-08 12:04:18 +01002 * Copyright (C) ARM Limited 2010-2015. All rights reserved.
Jon Medhurst15ce78d2014-04-10 09:02:02 +01003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include "PerfSource.h"
10
Jon Medhurst96b56152014-10-30 18:01:15 +000011#include <dirent.h>
Jon Medhurst15ce78d2014-04-10 09:02:02 +010012#include <errno.h>
Jon Medhurst96b56152014-10-30 18:01:15 +000013#include <signal.h>
Jon Medhurst15ce78d2014-04-10 09:02:02 +010014#include <string.h>
Jon Medhurst96b56152014-10-30 18:01:15 +000015#include <sys/prctl.h>
16#include <sys/resource.h>
17#include <sys/syscall.h>
18#include <sys/types.h>
Jon Medhurst15ce78d2014-04-10 09:02:02 +010019#include <unistd.h>
20
21#include "Child.h"
22#include "DynBuf.h"
23#include "Logging.h"
24#include "PerfDriver.h"
25#include "Proc.h"
26#include "SessionData.h"
27
Jon Medhurst96b56152014-10-30 18:01:15 +000028#ifndef SCHED_RESET_ON_FORK
29#define SCHED_RESET_ON_FORK 0x40000000
30#endif
Jon Medhurst15ce78d2014-04-10 09:02:02 +010031
32extern Child *child;
33
Jon Medhurstb1d07442015-05-08 12:04:18 +010034static const int cpuIdleKey = getEventKey();
35
Jon Medhurst96b56152014-10-30 18:01:15 +000036static bool sendTracepointFormat(const uint64_t currTime, Buffer *const buffer, const char *const name, DynBuf *const printb, DynBuf *const b) {
Jon Medhurst15ce78d2014-04-10 09:02:02 +010037 if (!printb->printf(EVENTS_PATH "/%s/format", name)) {
Jon Medhurstb1d07442015-05-08 12:04:18 +010038 logg->logMessage("DynBuf::printf failed");
Jon Medhurst15ce78d2014-04-10 09:02:02 +010039 return false;
40 }
41 if (!b->read(printb->getBuf())) {
Jon Medhurstb1d07442015-05-08 12:04:18 +010042 logg->logMessage("DynBuf::read failed");
Jon Medhurst15ce78d2014-04-10 09:02:02 +010043 return false;
44 }
Jon Medhurstb1d07442015-05-08 12:04:18 +010045 buffer->marshalFormat(currTime, b->getLength(), b->getBuf());
Jon Medhurst15ce78d2014-04-10 09:02:02 +010046
47 return true;
48}
49
Jon Medhurst96b56152014-10-30 18:01:15 +000050static void *syncFunc(void *arg)
51{
52 struct timespec ts;
53 int64_t nextTime = gSessionData->mMonotonicStarted;
54 int err;
55 (void)arg;
56
57 prctl(PR_SET_NAME, (unsigned long)&"gatord-sync", 0, 0, 0);
58
59 // Mask all signals so that this thread will not be woken up
60 {
61 sigset_t set;
62 if (sigfillset(&set) != 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +010063 logg->logError("sigfillset failed");
Jon Medhurst96b56152014-10-30 18:01:15 +000064 handleException();
65 }
66 if ((err = pthread_sigmask(SIG_SETMASK, &set, NULL)) != 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +010067 logg->logError("pthread_sigmask failed");
Jon Medhurst96b56152014-10-30 18:01:15 +000068 handleException();
69 }
70 }
71
72 for (;;) {
73 if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +010074 logg->logError("clock_gettime failed");
Jon Medhurst96b56152014-10-30 18:01:15 +000075 handleException();
76 }
77 const int64_t currTime = ts.tv_sec * NS_PER_S + ts.tv_nsec;
78
79 // Wake up once a second
80 nextTime += NS_PER_S;
81
82 // Always sleep more than 1 ms, hopefully things will line up better next time
83 const int64_t sleepTime = max(nextTime - currTime, (int64_t)(NS_PER_MS + 1));
84 ts.tv_sec = sleepTime/NS_PER_S;
85 ts.tv_nsec = sleepTime % NS_PER_S;
86
87 err = nanosleep(&ts, NULL);
88 if (err != 0) {
89 fprintf(stderr, "clock_nanosleep failed: %s\n", strerror(err));
90 return NULL;
91 }
92 }
93
94 return NULL;
95}
96
97static long getMaxCoreNum() {
98 DIR *dir = opendir("/sys/devices/system/cpu");
99 if (dir == NULL) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100100 logg->logError("Unable to determine the number of cores on the target, opendir failed");
Jon Medhurst96b56152014-10-30 18:01:15 +0000101 handleException();
102 }
103
104 long maxCoreNum = -1;
105 struct dirent *dirent;
106 while ((dirent = readdir(dir)) != NULL) {
107 if (strncmp(dirent->d_name, "cpu", 3) == 0) {
108 char *endptr;
109 errno = 0;
110 long coreNum = strtol(dirent->d_name + 3, &endptr, 10);
111 if ((errno == 0) && (*endptr == '\0') && (coreNum >= maxCoreNum)) {
112 maxCoreNum = coreNum + 1;
113 }
114 }
115 }
116 closedir(dir);
117
118 if (maxCoreNum < 1) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100119 logg->logError("Unable to determine the number of cores on the target, no cpu# directories found");
Jon Medhurst96b56152014-10-30 18:01:15 +0000120 handleException();
121 }
122
123 if (maxCoreNum >= NR_CPUS) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100124 logg->logError("Too many cores on the target, please increase NR_CPUS in Config.h");
Jon Medhurst96b56152014-10-30 18:01:15 +0000125 handleException();
126 }
127
128 return maxCoreNum;
129}
130
Jon Medhurstb1d07442015-05-08 12:04:18 +0100131PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(NULL), mCountersBuf(), mCountersGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) {
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100132 long l = sysconf(_SC_PAGE_SIZE);
133 if (l < 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100134 logg->logError("Unable to obtain the page size");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100135 handleException();
136 }
137 gSessionData->mPageSize = static_cast<int>(l);
Jon Medhurst96b56152014-10-30 18:01:15 +0000138 gSessionData->mCores = static_cast<int>(getMaxCoreNum());
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100139}
140
141PerfSource::~PerfSource() {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100142 delete mBuffer;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100143}
144
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100145bool PerfSource::prepare() {
146 DynBuf printb;
147 DynBuf b1;
Jon Medhurst96b56152014-10-30 18:01:15 +0000148 long long cpuIdleId;
149
Jon Medhurstb1d07442015-05-08 12:04:18 +0100150 // MonotonicStarted has not yet been assigned!
151 const uint64_t currTime = 0;//getTime() - gSessionData->mMonotonicStarted;
152
153 mBuffer = new Buffer(0, FRAME_PERF_ATTRS, gSessionData->mTotalBufferSize*1024*1024, mSenderSem);
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100154
Jon Medhurste31266f2014-08-04 15:47:44 +0100155 // Reread cpuinfo since cores may have changed since startup
156 gSessionData->readCpuInfo();
157
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100158 if (0
159 || !mMonitor.init()
160 || !mUEvent.init()
161 || !mMonitor.add(mUEvent.getFd())
162
Jon Medhurstb1d07442015-05-08 12:04:18 +0100163 || !sendTracepointFormat(currTime, mBuffer, SCHED_SWITCH, &printb, &b1)
Jon Medhurst96b56152014-10-30 18:01:15 +0000164
165 || (cpuIdleId = PerfDriver::getTracepointId(CPU_IDLE, &printb)) < 0
Jon Medhurstb1d07442015-05-08 12:04:18 +0100166 || !sendTracepointFormat(currTime, mBuffer, CPU_IDLE, &printb, &b1)
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100167
Jon Medhurstb1d07442015-05-08 12:04:18 +0100168 || !sendTracepointFormat(currTime, mBuffer, CPU_FREQUENCY, &printb, &b1)
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100169
Jon Medhurstb1d07442015-05-08 12:04:18 +0100170 || !mCountersGroup.createCpuGroup(currTime, mBuffer)
171 || !mCountersGroup.add(currTime, mBuffer, cpuIdleKey, PERF_TYPE_TRACEPOINT, cpuIdleId, 1, PERF_SAMPLE_RAW, PERF_GROUP_LEADER | PERF_GROUP_PER_CPU)
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100172
Jon Medhurstb1d07442015-05-08 12:04:18 +0100173 || !gSessionData->perf.enable(currTime, &mCountersGroup, mBuffer)
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100174 || 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100175 logg->logMessage("perf setup failed, are you running Linux 3.4 or later?");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100176 return false;
177 }
178
Jon Medhurst96b56152014-10-30 18:01:15 +0000179 for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
180 const int result = mCountersGroup.prepareCPU(cpu, &mMonitor);
181 if ((result != PG_SUCCESS) && (result != PG_CPU_OFFLINE)) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100182 logg->logError("PerfGroup::prepareCPU on mCountersGroup failed");
Jon Medhurst96b56152014-10-30 18:01:15 +0000183 handleException();
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100184 }
185 }
186
187 int numEvents = 0;
188 for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100189 numEvents += mCountersGroup.onlineCPU(currTime, cpu, false, mBuffer);
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100190 }
191 if (numEvents <= 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100192 logg->logMessage("PerfGroup::onlineCPU failed on all cores");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100193 return false;
194 }
195
Jon Medhurst96b56152014-10-30 18:01:15 +0000196 // Send the summary right before the start so that the monotonic delta is close to the start time
197 if (!gSessionData->perf.summary(&mSummary)) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100198 logg->logError("PerfDriver::summary failed");
199 handleException();
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100200 }
201
Jon Medhurst96b56152014-10-30 18:01:15 +0000202 // Start the timer thread to used to sync perf and monotonic raw times
203 pthread_t syncThread;
204 if (pthread_create(&syncThread, NULL, syncFunc, NULL)) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100205 logg->logError("pthread_create failed");
206 handleException();
Jon Medhurst96b56152014-10-30 18:01:15 +0000207 }
208 struct sched_param param;
209 param.sched_priority = sched_get_priority_max(SCHED_FIFO);
210 if (pthread_setschedparam(syncThread, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100211 logg->logError("pthread_setschedparam failed");
212 handleException();
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100213 }
214
Jon Medhurstb1d07442015-05-08 12:04:18 +0100215 mBuffer->commit(currTime);
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100216
217 return true;
218}
219
Jon Medhurst96b56152014-10-30 18:01:15 +0000220struct ProcThreadArgs {
221 Buffer *mBuffer;
222 uint64_t mCurrTime;
223 bool mIsDone;
224};
225
226void *procFunc(void *arg) {
227 DynBuf printb;
228 DynBuf b;
229 const ProcThreadArgs *const args = (ProcThreadArgs *)arg;
230
231 prctl(PR_SET_NAME, (unsigned long)&"gatord-proc", 0, 0, 0);
232
233 // Gator runs at a high priority, reset the priority to the default
234 if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), 0) == -1) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100235 logg->logError("setpriority failed");
Jon Medhurst96b56152014-10-30 18:01:15 +0000236 handleException();
237 }
238
239 if (!readProcMaps(args->mCurrTime, args->mBuffer, &printb, &b)) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100240 logg->logError("readProcMaps failed");
Jon Medhurst96b56152014-10-30 18:01:15 +0000241 handleException();
242 }
Jon Medhurst96b56152014-10-30 18:01:15 +0000243
244 if (!readKallsyms(args->mCurrTime, args->mBuffer, &args->mIsDone)) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100245 logg->logError("readKallsyms failed");
Jon Medhurst96b56152014-10-30 18:01:15 +0000246 handleException();
247 }
248 args->mBuffer->commit(args->mCurrTime);
249
250 return NULL;
251}
252
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100253static const char CPU_DEVPATH[] = "/devices/system/cpu/cpu";
254
255void PerfSource::run() {
256 int pipefd[2];
Jon Medhurst96b56152014-10-30 18:01:15 +0000257 pthread_t procThread;
258 ProcThreadArgs procThreadArgs;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100259
Jon Medhurst96b56152014-10-30 18:01:15 +0000260 if (pipe_cloexec(pipefd) != 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100261 logg->logError("pipe failed");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100262 handleException();
263 }
264 mInterruptFd = pipefd[1];
265
266 if (!mMonitor.add(pipefd[0])) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100267 logg->logError("Monitor::add failed");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100268 handleException();
269 }
270
Jon Medhurstb1d07442015-05-08 12:04:18 +0100271 {
272 DynBuf printb;
273 DynBuf b1;
274 DynBuf b2;
275
276 const uint64_t currTime = getTime() - gSessionData->mMonotonicStarted;
277
278 // Start events before reading proc to avoid race conditions
279 if (!mCountersGroup.start()) {
280 logg->logError("PerfGroup::start failed");
281 handleException();
282 }
283
284 mBuffer->perfCounterHeader(currTime);
285 for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
286 gSessionData->perf.read(mBuffer, cpu);
287 }
288 mBuffer->perfCounterFooter(currTime);
289
290 if (!readProcComms(currTime, mBuffer, &printb, &b1, &b2)) {
291 logg->logError("readProcComms failed");
292 handleException();
293 }
294 mBuffer->commit(currTime);
295
296 // Postpone reading kallsyms as on android adb gets too backed up and data is lost
297 procThreadArgs.mBuffer = mBuffer;
298 procThreadArgs.mCurrTime = currTime;
299 procThreadArgs.mIsDone = false;
300 if (pthread_create(&procThread, NULL, procFunc, &procThreadArgs)) {
301 logg->logError("pthread_create failed");
302 handleException();
303 }
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100304 }
305
306 sem_post(mStartProfile);
307
Jon Medhurstb1d07442015-05-08 12:04:18 +0100308 const uint64_t NO_RATE = ~0ULL;
309 const uint64_t rate = gSessionData->mLiveRate > 0 && gSessionData->mSampleRate > 0 ? gSessionData->mLiveRate : NO_RATE;
310 uint64_t nextTime = 0;
311 int timeout = rate != NO_RATE ? 0 : -1;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100312 while (gSessionData->mSessionIsActive) {
313 // +1 for uevents, +1 for pipe
314 struct epoll_event events[NR_CPUS + 2];
315 int ready = mMonitor.wait(events, ARRAY_LENGTH(events), timeout);
316 if (ready < 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100317 logg->logError("Monitor::wait failed");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100318 handleException();
319 }
Jon Medhurstb1d07442015-05-08 12:04:18 +0100320 const uint64_t currTime = getTime() - gSessionData->mMonotonicStarted;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100321
322 for (int i = 0; i < ready; ++i) {
323 if (events[i].data.fd == mUEvent.getFd()) {
Jon Medhurst96b56152014-10-30 18:01:15 +0000324 if (!handleUEvent(currTime)) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100325 logg->logError("PerfSource::handleUEvent failed");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100326 handleException();
327 }
328 break;
329 }
330 }
331
332 // send a notification that data is ready
333 sem_post(mSenderSem);
334
335 // In one shot mode, stop collection once all the buffers are filled
Jon Medhurstb1d07442015-05-08 12:04:18 +0100336 if (gSessionData->mOneShot && gSessionData->mSessionIsActive && ((mSummary.bytesAvailable() <= 0) || (mBuffer->bytesAvailable() <= 0) || mCountersBuf.isFull())) {
337 logg->logMessage("One shot (perf)");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100338 child->endSession();
339 }
Jon Medhurstb1d07442015-05-08 12:04:18 +0100340
341 if (rate != NO_RATE) {
342 while (currTime > nextTime) {
343 nextTime += rate;
344 }
345 // + NS_PER_MS - 1 to ensure always rounding up
346 timeout = max(0, (int)((nextTime + NS_PER_MS - 1 - getTime() + gSessionData->mMonotonicStarted)/NS_PER_MS));
347 }
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100348 }
349
Jon Medhurst96b56152014-10-30 18:01:15 +0000350 procThreadArgs.mIsDone = true;
351 pthread_join(procThread, NULL);
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100352 mCountersGroup.stop();
Jon Medhurstb1d07442015-05-08 12:04:18 +0100353 mBuffer->setDone();
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100354 mIsDone = true;
355
356 // send a notification that data is ready
357 sem_post(mSenderSem);
358
359 mInterruptFd = -1;
360 close(pipefd[0]);
361 close(pipefd[1]);
362}
363
Jon Medhurst96b56152014-10-30 18:01:15 +0000364bool PerfSource::handleUEvent(const uint64_t currTime) {
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100365 UEventResult result;
366 if (!mUEvent.read(&result)) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100367 logg->logMessage("UEvent::Read failed");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100368 return false;
369 }
370
371 if (strcmp(result.mSubsystem, "cpu") == 0) {
372 if (strncmp(result.mDevPath, CPU_DEVPATH, sizeof(CPU_DEVPATH) - 1) != 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100373 logg->logMessage("Unexpected cpu DEVPATH format");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100374 return false;
375 }
376 char *endptr;
377 errno = 0;
378 int cpu = strtol(result.mDevPath + sizeof(CPU_DEVPATH) - 1, &endptr, 10);
379 if (errno != 0 || *endptr != '\0') {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100380 logg->logMessage("strtol failed");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100381 return false;
382 }
Jon Medhurst96b56152014-10-30 18:01:15 +0000383
384 if (cpu >= gSessionData->mCores) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100385 logg->logError("Only %i cores are expected but core %i reports %s", gSessionData->mCores, cpu, result.mAction);
Jon Medhurst96b56152014-10-30 18:01:15 +0000386 handleException();
387 }
388
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100389 if (strcmp(result.mAction, "online") == 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100390 mBuffer->onlineCPU(currTime, cpu);
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100391 // Only call onlineCPU if prepareCPU succeeded
Jon Medhurstb1d07442015-05-08 12:04:18 +0100392 bool ret = false;
Jon Medhurst96b56152014-10-30 18:01:15 +0000393 int err = mCountersGroup.prepareCPU(cpu, &mMonitor);
394 if (err == PG_CPU_OFFLINE) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100395 ret = true;
Jon Medhurst96b56152014-10-30 18:01:15 +0000396 } else if (err == PG_SUCCESS) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100397 if (mCountersGroup.onlineCPU(currTime, cpu, true, mBuffer) > 0) {
398 mBuffer->perfCounterHeader(currTime);
399 gSessionData->perf.read(mBuffer, cpu);
400 mBuffer->perfCounterFooter(currTime);
401 ret = true;
Jon Medhurst96b56152014-10-30 18:01:15 +0000402 }
403 }
Jon Medhurstb1d07442015-05-08 12:04:18 +0100404 mBuffer->commit(currTime);
Jon Medhurst96b56152014-10-30 18:01:15 +0000405
406 gSessionData->readCpuInfo();
407 gSessionData->perf.coreName(currTime, &mSummary, cpu);
408 mSummary.commit(currTime);
Jon Medhurstb1d07442015-05-08 12:04:18 +0100409 return ret;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100410 } else if (strcmp(result.mAction, "offline") == 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100411 const bool ret = mCountersGroup.offlineCPU(cpu);
412 mBuffer->offlineCPU(currTime, cpu);
413 return ret;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100414 }
415 }
416
417 return true;
418}
419
420void PerfSource::interrupt() {
421 if (mInterruptFd >= 0) {
422 int8_t c = 0;
423 // Write to the pipe to wake the monitor which will cause mSessionIsActive to be reread
424 if (::write(mInterruptFd, &c, sizeof(c)) != sizeof(c)) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100425 logg->logError("write failed");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100426 handleException();
427 }
428 }
429}
430
431bool PerfSource::isDone () {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100432 return mBuffer->isDone() && mIsDone && mCountersBuf.isEmpty();
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100433}
434
435void PerfSource::write (Sender *sender) {
436 if (!mSummary.isDone()) {
437 mSummary.write(sender);
Jon Medhurste31266f2014-08-04 15:47:44 +0100438 gSessionData->mSentSummary = true;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100439 }
Jon Medhurstb1d07442015-05-08 12:04:18 +0100440 if (!mBuffer->isDone()) {
441 mBuffer->write(sender);
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100442 }
443 if (!mCountersBuf.send(sender)) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100444 logg->logError("PerfBuffer::send failed");
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100445 handleException();
446 }
447}