summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/Child.cpp')
-rw-r--r--daemon/Child.cpp174
1 files changed, 55 insertions, 119 deletions
diff --git a/daemon/Child.cpp b/daemon/Child.cpp
index 9ee2ef8..ca33561 100644
--- a/daemon/Child.cpp
+++ b/daemon/Child.cpp
@@ -1,38 +1,39 @@
1/** 1/**
2 * Copyright (C) ARM Limited 2010-2013. All rights reserved. 2 * Copyright (C) ARM Limited 2010-2014. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 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 5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation. 6 * published by the Free Software Foundation.
7 */ 7 */
8 8
9#include "Child.h"
10
9#include <stdlib.h> 11#include <stdlib.h>
10#include <string.h> 12#include <string.h>
11#include <signal.h> 13#include <signal.h>
12#include <unistd.h> 14#include <unistd.h>
13#include <sys/prctl.h> 15#include <sys/prctl.h>
16
14#include "Logging.h" 17#include "Logging.h"
15#include "CapturedXML.h" 18#include "CapturedXML.h"
16#include "SessionData.h" 19#include "SessionData.h"
17#include "Child.h"
18#include "LocalCapture.h" 20#include "LocalCapture.h"
19#include "Collector.h"
20#include "Sender.h" 21#include "Sender.h"
21#include "OlyUtility.h" 22#include "OlyUtility.h"
23#include "OlySocket.h"
22#include "StreamlineSetup.h" 24#include "StreamlineSetup.h"
23#include "ConfigurationXML.h" 25#include "ConfigurationXML.h"
24#include "Driver.h" 26#include "Driver.h"
25#include "Fifo.h" 27#include "PerfSource.h"
26#include "Buffer.h" 28#include "DriverSource.h"
27 29#include "UserSpaceSource.h"
28#define NS_PER_S ((uint64_t)1000000000) 30#include "ExternalSource.h"
29#define NS_PER_US 1000
30 31
31static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads 32static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads
32static Fifo* collectorFifo = NULL; // Shared by Child.cpp and spawned threads 33static Source *primarySource = NULL;
33static Buffer* buffer = NULL; 34static Source *userSpaceSource = NULL;
35static Source *externalSource = NULL;
34static Sender* sender = NULL; // Shared by Child.cpp and spawned threads 36static Sender* sender = NULL; // Shared by Child.cpp and spawned threads
35static Collector* collector = NULL;
36Child* child = NULL; // shared by Child.cpp and main.cpp 37Child* child = NULL; // shared by Child.cpp and main.cpp
37 38
38extern void cleanUp(); 39extern void cleanUp();
@@ -78,7 +79,7 @@ static void child_handler(int signum) {
78 } 79 }
79 beenHere = true; 80 beenHere = true;
80 logg->logMessage("Gator is shutting down."); 81 logg->logMessage("Gator is shutting down.");
81 if (signum == SIGALRM || !collector) { 82 if (signum == SIGALRM || !primarySource) {
82 exit(1); 83 exit(1);
83 } else { 84 } else {
84 child->endSession(); 85 child->endSession();
@@ -139,77 +140,22 @@ static void *stopThread(void *) {
139 return 0; 140 return 0;
140} 141}
141 142
142static void *countersThread(void *) {
143 prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0);
144
145 gSessionData->hwmon.start();
146
147 int64_t monotonic_started = 0;
148 while (monotonic_started <= 0) {
149 usleep(10);
150
151 if (Collector::readInt64Driver("/dev/gator/started", &monotonic_started) == -1) {
152 logg->logError(__FILE__, __LINE__, "Error reading gator driver start time");
153 handleException();
154 }
155 }
156
157 uint64_t next_time = 0;
158 while (gSessionData->mSessionIsActive) {
159 struct timespec ts;
160#ifndef CLOCK_MONOTONIC_RAW
161 // Android doesn't have this defined but it was added in Linux 2.6.28
162#define CLOCK_MONOTONIC_RAW 4
163#endif
164 if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
165 logg->logError(__FILE__, __LINE__, "Failed to get uptime");
166 handleException();
167 }
168 const uint64_t curr_time = (NS_PER_S*ts.tv_sec + ts.tv_nsec) - monotonic_started;
169 // Sample ten times a second ignoring gSessionData->mSampleRate
170 next_time += NS_PER_S/10;//gSessionData->mSampleRate;
171 if (next_time < curr_time) {
172 logg->logMessage("Too slow, curr_time: %lli next_time: %lli", curr_time, next_time);
173 next_time = curr_time;
174 }
175
176 if (buffer->eventHeader(curr_time)) {
177 gSessionData->hwmon.read(buffer);
178 // Only check after writing all counters so that time and corresponding counters appear in the same frame
179 buffer->check(curr_time);
180 }
181
182 if (buffer->bytesAvailable() <= 0) {
183 logg->logMessage("One shot (counters)");
184 child->endSession();
185 }
186
187 usleep((next_time - curr_time)/NS_PER_US);
188 }
189
190 buffer->setDone();
191
192 return NULL;
193}
194
195static void *senderThread(void *) { 143static void *senderThread(void *) {
196 int length = 1;
197 char* data;
198 char end_sequence[] = {RESPONSE_APC_DATA, 0, 0, 0, 0}; 144 char end_sequence[] = {RESPONSE_APC_DATA, 0, 0, 0, 0};
199 145
200 sem_post(&senderThreadStarted); 146 sem_post(&senderThreadStarted);
201 prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0); 147 prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0);
202 sem_wait(&haltPipeline); 148 sem_wait(&haltPipeline);
203 149
204 while (length > 0 || !buffer->isDone()) { 150 while (!primarySource->isDone() || (userSpaceSource != NULL && !userSpaceSource->isDone()) || (externalSource != NULL && !externalSource->isDone())) {
205 sem_wait(&senderSem); 151 sem_wait(&senderSem);
206 data = collectorFifo->read(&length); 152
207 if (data != NULL) { 153 primarySource->write(sender);
208 sender->writeData(data, length, RESPONSE_APC_DATA); 154 if (userSpaceSource != NULL) {
209 collectorFifo->release(); 155 userSpaceSource->write(sender);
210 } 156 }
211 if (!buffer->isDone()) { 157 if (externalSource != NULL) {
212 buffer->write(sender); 158 externalSource->write(sender);
213 } 159 }
214 } 160 }
215 161
@@ -255,15 +201,13 @@ void Child::initialization() {
255 201
256void Child::endSession() { 202void Child::endSession() {
257 gSessionData->mSessionIsActive = false; 203 gSessionData->mSessionIsActive = false;
258 collector->stop(); 204 primarySource->interrupt();
259 sem_post(&haltPipeline); 205 sem_post(&haltPipeline);
260} 206}
261 207
262void Child::run() { 208void Child::run() {
263 char* collectBuffer;
264 int bytesCollected = 0;
265 LocalCapture* localCapture = NULL; 209 LocalCapture* localCapture = NULL;
266 pthread_t durationThreadID, stopThreadID, senderThreadID, countersThreadID; 210 pthread_t durationThreadID, stopThreadID, senderThreadID;
267 211
268 prctl(PR_SET_NAME, (unsigned long)&"gatord-child", 0, 0, 0); 212 prctl(PR_SET_NAME, (unsigned long)&"gatord-child", 0, 0, 0);
269 213
@@ -282,7 +226,11 @@ void Child::run() {
282 { ConfigurationXML configuration; } 226 { ConfigurationXML configuration; }
283 227
284 // Set up the driver; must be done after gSessionData->mPerfCounterType[] is populated 228 // Set up the driver; must be done after gSessionData->mPerfCounterType[] is populated
285 collector = new Collector(); 229 if (!gSessionData->perf.isSetup()) {
230 primarySource = new DriverSource(&senderSem, &startProfile);
231 } else {
232 primarySource = new PerfSource(&senderSem, &startProfile);
233 }
286 234
287 // Initialize all drivers 235 // Initialize all drivers
288 for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) { 236 for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
@@ -317,15 +265,11 @@ void Child::run() {
317 free(xmlString); 265 free(xmlString);
318 } 266 }
319 267
320 // Create user-space buffers, add 5 to the size to account for the 1-byte type and 4-byte length 268 // Must be after session XML is parsed
321 logg->logMessage("Created %d MB collector buffer with a %d-byte ragged end", gSessionData->mTotalBufferSize, collector->getBufferSize()); 269 if (!primarySource->prepare()) {
322 collectorFifo = new Fifo(collector->getBufferSize() + 5, gSessionData->mTotalBufferSize*1024*1024, &senderSem); 270 logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
323 271 handleException();
324 // Get the initial pointer to the collect buffer 272 }
325 collectBuffer = collectorFifo->start();
326
327 // Create a new Block Counter Buffer
328 buffer = new Buffer(0, 5, gSessionData->mTotalBufferSize*1024*1024, &senderSem);
329 273
330 // Sender thread shall be halted until it is signaled for one shot mode 274 // Sender thread shall be halted until it is signaled for one shot mode
331 sem_init(&haltPipeline, 0, gSessionData->mOneShot ? 0 : 2); 275 sem_init(&haltPipeline, 0, gSessionData->mOneShot ? 0 : 2);
@@ -340,14 +284,21 @@ void Child::run() {
340 thread_creation_success = false; 284 thread_creation_success = false;
341 } 285 }
342 286
343 bool startcountersThread = gSessionData->hwmon.countersEnabled(); 287 if (gSessionData->hwmon.countersEnabled()) {
344 if (startcountersThread) { 288 userSpaceSource = new UserSpaceSource(&senderSem);
345 if (pthread_create(&countersThreadID, NULL, countersThread, this)) { 289 if (!userSpaceSource->prepare()) {
346 thread_creation_success = false; 290 logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
291 handleException();
347 } 292 }
348 } else { 293 userSpaceSource->start();
349 // Let senderThread know there is no buffer data to send 294 }
350 buffer->setDone(); 295 if (access("/tmp/gator", F_OK) == 0) {
296 externalSource = new ExternalSource(&senderSem);
297 if (!externalSource->prepare()) {
298 logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
299 handleException();
300 }
301 externalSource->start();
351 } 302 }
352 303
353 if (!thread_creation_success) { 304 if (!thread_creation_success) {
@@ -359,28 +310,13 @@ void Child::run() {
359 sem_wait(&senderThreadStarted); 310 sem_wait(&senderThreadStarted);
360 311
361 // Start profiling 312 // Start profiling
362 logg->logMessage("********** Profiling started **********"); 313 primarySource->run();
363 collector->start();
364 sem_post(&startProfile);
365
366 // Collect Data
367 do {
368 // This command will stall until data is received from the driver
369 bytesCollected = collector->collect(collectBuffer);
370
371 // In one shot mode, stop collection once all the buffers are filled
372 if (gSessionData->mOneShot && gSessionData->mSessionIsActive) {
373 if (bytesCollected == -1 || collectorFifo->willFill(bytesCollected)) {
374 logg->logMessage("One shot");
375 endSession();
376 }
377 }
378 collectBuffer = collectorFifo->write(bytesCollected);
379 } while (bytesCollected > 0);
380 logg->logMessage("Exit collect data loop");
381 314
382 if (startcountersThread) { 315 if (externalSource != NULL) {
383 pthread_join(countersThreadID, NULL); 316 externalSource->join();
317 }
318 if (userSpaceSource != NULL) {
319 userSpaceSource->join();
384 } 320 }
385 321
386 // Wait for the other threads to exit 322 // Wait for the other threads to exit
@@ -401,9 +337,9 @@ void Child::run() {
401 337
402 logg->logMessage("Profiling ended."); 338 logg->logMessage("Profiling ended.");
403 339
404 delete buffer; 340 delete externalSource;
405 delete collectorFifo; 341 delete userSpaceSource;
342 delete primarySource;
406 delete sender; 343 delete sender;
407 delete collector;
408 delete localCapture; 344 delete localCapture;
409} 345}