diff options
Diffstat (limited to 'drivers/gator/daemon/Collector.cpp')
-rw-r--r-- | drivers/gator/daemon/Collector.cpp | 281 |
1 files changed, 0 insertions, 281 deletions
diff --git a/drivers/gator/daemon/Collector.cpp b/drivers/gator/daemon/Collector.cpp deleted file mode 100644 index 7a41198e5cb..00000000000 --- a/drivers/gator/daemon/Collector.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/** - * Copyright (C) ARM Limited 2010-2012. 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 - * published by the Free Software Foundation. - */ - -#include <fcntl.h> -#include <malloc.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <errno.h> -#include <sys/time.h> -#include "Collector.h" -#include "SessionData.h" -#include "Logging.h" - -extern void handleException(); - -// Driver initialization independent of session settings -Collector::Collector() { - char text[sizeof(gSessionData->mPerfCounterType[0]) + 20]; // sufficiently large to hold all events/<types>/<file> - - bufferFD = 0; - - checkVersion(); - - int enable = -1; - if (readIntDriver("enable", &enable) != 0 || enable != 0) { - logg->logError(__FILE__, __LINE__, "Driver already enabled, possibly a session is already in progress."); - handleException(); - } - - readIntDriver("cpu_cores", &gSessionData->mCores); - if (gSessionData->mCores == 0) { - gSessionData->mCores = 1; - } - - bufferSize = 512 * 1024; - if (writeReadDriver("buffer_size", &bufferSize) || bufferSize <= 0) { - logg->logError(__FILE__, __LINE__, "Unable to set the driver buffer size"); - handleException(); - } - - getCoreName(); - - enablePerfCounters(); - - // Read unchanging keys from driver which are created at insmod'ing of gator.ko - for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) { - if (gSessionData->mPerfCounterEnabled[i]) { - snprintf(text, sizeof(text), "events/%s/key", gSessionData->mPerfCounterType[i]); - readIntDriver(text, &gSessionData->mPerfCounterKey[i]); - } - } -} - -Collector::~Collector() { - // Write zero for safety, as a zero should have already been written - writeDriver("enable", "0"); - - // Calls event_buffer_release in the driver - if (bufferFD) { - close(bufferFD); - } -} - -void Collector::enablePerfCounters() { - char text[sizeof(gSessionData->mPerfCounterType[0]) + 30]; // sufficiently large to hold all /dev/gator/events/<types>/enabled - for (int i=0; i<MAX_PERFORMANCE_COUNTERS; i++) { - if (!gSessionData->mPerfCounterEnabled[i]) { - continue; - } - snprintf(text, sizeof(text), "events/%s/enabled", gSessionData->mPerfCounterType[i]); - if (writeReadDriver(text, &gSessionData->mPerfCounterEnabled[i])) { - // Disable those events that don't exist on this hardware platform even though they exist in configuration.xml - gSessionData->mPerfCounterEnabled[i] = 0; - continue; - } - } -} - -void Collector::setupPerfCounters() { - char base[sizeof(gSessionData->mPerfCounterType[0]) + 10]; // sufficiently large to hold all events/<types> - char text[sizeof(gSessionData->mPerfCounterType[0]) + 20]; // sufficiently large to hold all events/<types>/<file> - - for (int i=0; i<MAX_PERFORMANCE_COUNTERS; i++) { - if (!gSessionData->mPerfCounterEnabled[i]) { - continue; - } - snprintf(base, sizeof(base), "events/%s", gSessionData->mPerfCounterType[i]); - snprintf(text, sizeof(text), "%s/event", base); - writeDriver(text, gSessionData->mPerfCounterEvent[i]); - if (gSessionData->mPerfCounterEBSCapable[i]) { - snprintf(text, sizeof(text), "%s/count", base); - if (access(resolvePath(text), F_OK) == 0) { - if (writeReadDriver(text, &gSessionData->mPerfCounterCount[i]) && gSessionData->mPerfCounterCount[i] > 0) { - logg->logError(__FILE__, __LINE__, "Cannot enable EBS for %s with a count of %d\n", gSessionData->mPerfCounterName[i], gSessionData->mPerfCounterCount[i]); - handleException(); - } - } else if (gSessionData->mPerfCounterCount[i] > 0) { - logg->logError(__FILE__, __LINE__, "Event Based Sampling is only supported with kernel versions 3.0.0 and higher with CONFIG_PERF_EVENTS=y, and CONFIG_HW_PERF_EVENTS=y\n"); - handleException(); - } - } - } -} - -void Collector::checkVersion() { - int driver_version = 0; - - if (readIntDriver("version", &driver_version) == -1) { - logg->logError(__FILE__, __LINE__, "Error reading gator driver version"); - handleException(); - } - - // Verify the driver version matches the daemon version - if (driver_version != PROTOCOL_VERSION) { - if ((driver_version > PROTOCOL_DEV) || (PROTOCOL_VERSION > PROTOCOL_DEV)) { - // One of the mismatched versions is development version - logg->logError(__FILE__, __LINE__, - "DEVELOPMENT BUILD MISMATCH: gator driver version \"%d\" is not in sync with gator daemon version \"%d\".\n" - ">> The following must be synchronized from engineering repository:\n" - ">> * gator driver\n" - ">> * gator daemon\n" - ">> * Streamline", driver_version, PROTOCOL_VERSION); - handleException(); - } else { - // Release version mismatch - logg->logError(__FILE__, __LINE__, - "gator driver version \"%d\" is different than gator daemon version \"%d\".\n" - ">> Please upgrade the driver and daemon to the latest versions.", driver_version, PROTOCOL_VERSION); - handleException(); - } - } -} - -void Collector::start() { - // Set the maximum backtrace depth - if (writeReadDriver("backtrace_depth", &gSessionData->mBacktraceDepth)) { - logg->logError(__FILE__, __LINE__, "Unable to set the driver backtrace depth"); - handleException(); - } - - // open the buffer which calls userspace_buffer_open() in the driver - bufferFD = open(resolvePath("buffer"), O_RDONLY); - if (bufferFD < 0) { - logg->logError(__FILE__, __LINE__, "The gator driver did not set up properly. Please view the linux console or dmesg log for more information on the failure."); - handleException(); - } - - // set the tick rate of the profiling timer - if (writeReadDriver("tick", &gSessionData->mSampleRate) != 0) { - logg->logError(__FILE__, __LINE__, "Unable to set the driver tick"); - handleException(); - } - - // notify the kernel of the streaming mode, currently used for network stats - int streaming = (int)!gSessionData->mOneShot; - if (writeReadDriver("streaming", &streaming) != 0) { - logg->logError(__FILE__, __LINE__, "Unable to set streaming"); - handleException(); - } - - logg->logMessage("Start the driver"); - - // This command makes the driver start profiling by calling gator_op_start() in the driver - if (writeDriver("enable", "1") != 0) { - logg->logError(__FILE__, __LINE__, "The gator driver did not start properly. Please view the linux console or dmesg log for more information on the failure."); - handleException(); - } - - lseek(bufferFD, 0, SEEK_SET); -} - -// These commands should cause the read() function in collect() to return -void Collector::stop() { - // This will stop the driver from profiling - if (writeDriver("enable", "0") != 0) { - logg->logMessage("Stopping kernel failed"); - } -} - -int Collector::collect(char* buffer) { - // Calls event_buffer_read in the driver - int bytesRead = read(bufferFD, buffer, bufferSize); - - // If read() returned due to an interrupt signal, re-read to obtain the last bit of collected data - if (bytesRead == -1 && errno == EINTR) { - bytesRead = read(bufferFD, buffer, bufferSize); - } - - logg->logMessage("Driver read of %d bytes", bytesRead); - - return bytesRead; -} - -void Collector::getCoreName() { - char temp[256]; // arbitrarily large amount - strcpy(gSessionData->mCoreName, "unknown"); - - FILE* f = fopen("/proc/cpuinfo", "r"); - if (f == NULL) { - logg->logMessage("Error opening /proc/cpuinfo\n" - "The core name in the captured xml file will be 'unknown'."); - return; - } - - while (fgets(temp, sizeof(temp), f)) { - if (strlen(temp) > 0) - temp[strlen(temp) - 1] = 0; // Replace the line feed with a null - - if (strstr(temp, "Hardware") != 0) { - char* position = strchr(temp, ':'); - if (position == NULL || (unsigned int)(position - temp) + 2 >= strlen(temp)) { - logg->logMessage("Unknown format of /proc/cpuinfo\n" - "The core name in the captured xml file will be 'unknown'."); - return; - } - strncpy(gSessionData->mCoreName, (char *)((int)position + 2), sizeof(gSessionData->mCoreName)); - gSessionData->mCoreName[sizeof(gSessionData->mCoreName) - 1] = 0; // strncpy does not guarantee a null-terminated string - fclose(f); - return; - } - } - - logg->logMessage("Could not determine core name from /proc/cpuinfo\n" - "The core name in the captured xml file will be 'unknown'."); - fclose(f); -} - -char* Collector::resolvePath(const char* file) { - static char fullpath[100]; // Sufficiently large to hold any path within /dev/gator - snprintf(fullpath, sizeof(fullpath), "/dev/gator/%s", file); - return fullpath; -} - -int Collector::readIntDriver(const char* path, int* value) { - char* fullpath = resolvePath(path); - FILE* file = fopen(fullpath, "r"); - if (file == NULL) { - return -1; - } - if (fscanf(file, "%u", value) != 1) { - fclose(file); - logg->logMessage("Invalid value in file %s", fullpath); - return -1; - } - fclose(file); - return 0; -} - -int Collector::writeDriver(const char* path, int value) { - char data[40]; // Sufficiently large to hold any integer - snprintf(data, sizeof(data), "%d", value); - return writeDriver(path, data); -} - -int Collector::writeDriver(const char* path, const char* data) { - char* fullpath = resolvePath(path); - int fd = open(fullpath, O_WRONLY); - if (fd < 0) { - return -1; - } - if (write(fd, data, strlen(data)) < 0) { - close(fd); - logg->logMessage("Opened but could not write to %s", fullpath); - return -1; - } - close(fd); - return 0; -} - -int Collector::writeReadDriver(const char* path, int* value) { - if (writeDriver(path, *value) || readIntDriver(path, value)) { - return -1; - } - return 0; -} |