aboutsummaryrefslogtreecommitdiff
path: root/daemon/Child.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/Child.cpp')
-rw-r--r--daemon/Child.cpp131
1 files changed, 112 insertions, 19 deletions
diff --git a/daemon/Child.cpp b/daemon/Child.cpp
index b97e0db..c784847 100644
--- a/daemon/Child.cpp
+++ b/daemon/Child.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) ARM Limited 2010-2012. All rights reserved.
+ * Copyright (C) ARM Limited 2010-2013. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -9,8 +9,6 @@
#include <stdlib.h>
#include <string.h>
#include <signal.h>
-#include <sys/syscall.h>
-#include <sys/resource.h>
#include <unistd.h>
#include <sys/prctl.h>
#include "Logging.h"
@@ -23,11 +21,18 @@
#include "OlyUtility.h"
#include "StreamlineSetup.h"
#include "ConfigurationXML.h"
+#include "Driver.h"
+#include "Fifo.h"
+#include "Buffer.h"
-static sem_t haltPipeline, senderThreadStarted, startProfile; // Shared by Child and spawned threads
+#define NS_PER_S ((uint64_t)1000000000)
+#define NS_PER_US 1000
+
+static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads
static Fifo* collectorFifo = NULL; // Shared by Child.cpp and spawned threads
+static Buffer* buffer = NULL;
static Sender* sender = NULL; // Shared by Child.cpp and spawned threads
-Collector* collector = NULL;
+static Collector* collector = NULL;
Child* child = NULL; // shared by Child.cpp and main.cpp
extern void cleanUp();
@@ -62,7 +67,7 @@ void handleException() {
}
// CTRL C Signal Handler for child process
-void child_handler(int signum) {
+static void child_handler(int signum) {
static bool beenHere = false;
if (beenHere == true) {
logg->logMessage("Gator is being forced to shut down.");
@@ -78,7 +83,7 @@ void child_handler(int signum) {
}
}
-void* durationThread(void* pVoid) {
+static void* durationThread(void* pVoid) {
prctl(PR_SET_NAME, (unsigned long)&"gatord-duration", 0, 0, 0);
sem_wait(&startProfile);
if (gSessionData->mSessionIsActive) {
@@ -94,7 +99,7 @@ void* durationThread(void* pVoid) {
return 0;
}
-void* stopThread(void* pVoid) {
+static void* stopThread(void* pVoid) {
int length;
char type;
OlySocket* socket = child->socket;
@@ -134,8 +139,61 @@ void* stopThread(void* pVoid) {
return 0;
}
-void* senderThread(void* pVoid) {
- int length;
+void* countersThread(void* pVoid) {
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0);
+
+ gSessionData->hwmon.start();
+
+ int64_t monotonic_started = 0;
+ while (monotonic_started <= 0) {
+ usleep(10);
+
+ if (Collector::readInt64Driver("/dev/gator/started", &monotonic_started) == -1) {
+ logg->logError(__FILE__, __LINE__, "Error reading gator driver start time");
+ handleException();
+ }
+ }
+
+ uint64_t next_time = 0;
+ while (gSessionData->mSessionIsActive) {
+ struct timespec ts;
+#ifndef CLOCK_MONOTONIC_RAW
+ // Android doesn't have this defined but it was added in Linux 2.6.28
+#define CLOCK_MONOTONIC_RAW 4
+#endif
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
+ logg->logError(__FILE__, __LINE__, "Failed to get uptime");
+ handleException();
+ }
+ const uint64_t curr_time = (NS_PER_S*ts.tv_sec + ts.tv_nsec) - monotonic_started;
+ // Sample ten times a second ignoring gSessionData->mSampleRate
+ next_time += NS_PER_S/10;//gSessionData->mSampleRate;
+ if (next_time < curr_time) {
+ logg->logMessage("Too slow, curr_time: %lli next_time: %lli", curr_time, next_time);
+ next_time = curr_time;
+ }
+
+ if (buffer->eventHeader(curr_time)) {
+ gSessionData->hwmon.read(buffer);
+ // Only check after writing all counters so that time and corresponding counters appear in the same frame
+ buffer->check(curr_time);
+ }
+
+ if (buffer->bytesAvailable() <= 0) {
+ logg->logMessage("One shot (counters)");
+ child->endSession();
+ }
+
+ usleep((next_time - curr_time)/NS_PER_US);
+ }
+
+ buffer->setDone();
+
+ return NULL;
+}
+
+static void* senderThread(void* pVoid) {
+ int length = 1;
char* data;
char end_sequence[] = {RESPONSE_APC_DATA, 0, 0, 0, 0};
@@ -143,10 +201,17 @@ void* senderThread(void* pVoid) {
prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0);
sem_wait(&haltPipeline);
- do {
+ while (length > 0 || !buffer->isDone()) {
+ sem_wait(&senderSem);
data = collectorFifo->read(&length);
- sender->writeData(data, length, RESPONSE_APC_DATA);
- } while (length > 0);
+ if (data != NULL) {
+ sender->writeData(data, length, RESPONSE_APC_DATA);
+ collectorFifo->release();
+ }
+ if (!buffer->isDone()) {
+ buffer->write(sender);
+ }
+ }
// write end-of-capture sequence
if (!gSessionData->mLocalCapture) {
@@ -185,6 +250,7 @@ void Child::initialization() {
// Initialize semaphores
sem_init(&senderThreadStarted, 0, 0);
sem_init(&startProfile, 0, 0);
+ sem_init(&senderSem, 0, 0);
}
void Child::endSession() {
@@ -197,7 +263,7 @@ void Child::run() {
char* collectBuffer;
int bytesCollected = 0;
LocalCapture* localCapture = NULL;
- pthread_t durationThreadID, stopThreadID, senderThreadID;
+ pthread_t durationThreadID, stopThreadID, senderThreadID, countersThreadID;
prctl(PR_SET_NAME, (unsigned long)&"gatord-child", 0, 0, 0);
@@ -213,11 +279,24 @@ void Child::run() {
}
// Populate gSessionData with the configuration
- new ConfigurationXML();
+ { ConfigurationXML configuration; }
// Set up the driver; must be done after gSessionData->mPerfCounterType[] is populated
collector = new Collector();
+ // Initialize all drivers
+ for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
+ driver->resetCounters();
+ }
+
+ // Set up counters using the associated driver's setup function
+ for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
+ Counter & counter = gSessionData->mCounters[i];
+ if (counter.isEnabled()) {
+ counter.getDriver()->setupCounter(counter);
+ }
+ }
+
// Start up and parse session xml
if (socket) {
// Respond to Streamline requests
@@ -238,16 +317,16 @@ void Child::run() {
free(xmlString);
}
- // Write configuration into the driver
- collector->setupPerfCounters();
-
// Create user-space buffers, add 5 to the size to account for the 1-byte type and 4-byte length
logg->logMessage("Created %d MB collector buffer with a %d-byte ragged end", gSessionData->mTotalBufferSize, collector->getBufferSize());
- collectorFifo = new Fifo(collector->getBufferSize() + 5, gSessionData->mTotalBufferSize* 1024 * 1024);
+ collectorFifo = new Fifo(collector->getBufferSize() + 5, gSessionData->mTotalBufferSize*1024*1024, &senderSem);
// Get the initial pointer to the collect buffer
collectBuffer = collectorFifo->start();
+ // Create a new Block Counter Buffer
+ buffer = new Buffer(0, 5, gSessionData->mTotalBufferSize*1024*1024, &senderSem);
+
// Sender thread shall be halted until it is signaled for one shot mode
sem_init(&haltPipeline, 0, gSessionData->mOneShot ? 0 : 2);
@@ -261,6 +340,15 @@ void Child::run() {
thread_creation_success = false;
}
+ if (gSessionData->hwmon.countersEnabled()) {
+ if (pthread_create(&countersThreadID, NULL, countersThread, this)) {
+ thread_creation_success = false;
+ }
+ } else {
+ // Let senderThread know there is no buffer data to send
+ buffer->setDone();
+ }
+
if (!thread_creation_success) {
logg->logError(__FILE__, __LINE__, "Failed to create gator threads");
handleException();
@@ -290,6 +378,10 @@ void Child::run() {
} while (bytesCollected > 0);
logg->logMessage("Exit collect data loop");
+ if (gSessionData->hwmon.countersEnabled()) {
+ pthread_join(countersThreadID, NULL);
+ }
+
// Wait for the other threads to exit
pthread_join(senderThreadID, NULL);
@@ -308,6 +400,7 @@ void Child::run() {
logg->logMessage("Profiling ended.");
+ delete buffer;
delete collectorFifo;
delete sender;
delete collector;