From 1b621a4c70954bba19f77922a177146dff21e6f1 Mon Sep 17 00:00:00 2001 From: Jon Medhurst Date: Tue, 11 Jun 2013 09:49:00 +0100 Subject: gator: Version 5.15 Signed-off-by: Jon Medhurst --- README_Streamline.txt | 4 +- daemon/Android.mk | 1 + daemon/Buffer.cpp | 199 ++++---------------- daemon/CapturedXML.cpp | 22 +-- daemon/Child.cpp | 11 +- daemon/ConfigurationXML.cpp | 48 ++--- daemon/Counter.h | 36 ---- daemon/EventsXML.cpp | 70 ++++++++ daemon/EventsXML.h | 18 ++ daemon/Fifo.cpp | 149 +++++++-------- daemon/Fifo.h | 39 ++-- daemon/Hwmon.cpp | 61 ++++++- daemon/KMod.cpp | 22 ++- daemon/LocalCapture.cpp | 5 + daemon/OlySocket.cpp | 4 +- daemon/OlyUtility.cpp | 4 +- daemon/OlyUtility.h | 2 + daemon/SessionData.h | 4 +- daemon/StreamlineSetup.cpp | 74 +++----- daemon/StreamlineSetup.h | 2 +- daemon/common.mk | 2 +- daemon/configuration.xml | 102 ++++++----- daemon/escape.c | 10 +- daemon/events-ARM11.xml | 2 +- daemon/events-ARM11MPCore.xml | 2 +- daemon/events-CCI-400.xml | 2 +- daemon/events-Cortex-A15.xml | 2 +- daemon/events-Cortex-A5.xml | 2 +- daemon/events-Cortex-A53.xml | 152 ++++++++-------- daemon/events-Cortex-A57.xml | 154 ++++++++-------- daemon/events-Cortex-A7.xml | 2 +- daemon/events-Cortex-A8.xml | 4 +- daemon/events-Cortex-A9.xml | 2 +- daemon/events-Krait-architected.xml | 2 +- daemon/events-Linux.xml | 6 +- daemon/events-Mali-T6xx.xml | 30 ++-- daemon/events-Mali-T6xx_hw.xml | 349 ++++++++++-------------------------- daemon/events-Scorpion.xml | 2 +- daemon/events-ScorpionMP.xml | 2 +- driver/gator_backtrace.c | 76 +++++--- driver/gator_events_l2c-310.c | 21 ++- driver/gator_events_mali_400.c | 8 - driver/gator_events_mali_t6xx_hw.c | 40 ++++- driver/gator_events_perf_pmu.c | 18 +- driver/gator_iks.c | 2 +- driver/gator_main.c | 130 +++++++------- driver/gator_marshaling.c | 12 +- driver/gator_pack.c | 195 ++++---------------- driver/gator_trace_gpu.c | 5 +- driver/gator_trace_sched.c | 48 ++++- 50 files changed, 969 insertions(+), 1190 deletions(-) mode change 100644 => 100755 README_Streamline.txt create mode 100644 daemon/EventsXML.cpp create mode 100644 daemon/EventsXML.h diff --git a/README_Streamline.txt b/README_Streamline.txt old mode 100644 new mode 100755 index 5472c07..6a55f60 --- a/README_Streamline.txt +++ b/README_Streamline.txt @@ -30,7 +30,6 @@ menuconfig options (depending on the kernel version, the location of these confi - CPU Frequency scaling - [*] CPU Frequency scaling (enables CONFIG_CPU_FREQ) - Kernel hacking - - [*] Mutex debugging: basic checks (optional, enables CONFIG_DEBUG_MUTEXES) - [*] Compile the kernel with debug info (optional, enables CONFIG_DEBUG_INFO) - [*] Tracers - [*] Trace process context switches and events (#) @@ -43,7 +42,6 @@ CONFIG_PROFILING CONFIG_HIGH_RES_TIMERS CONFIG_LOCAL_TIMERS (for SMP systems) CONFIG_PERF_EVENTS and CONFIG_HW_PERF_EVENTS (kernel versions 3.0 and greater) -CONFIG_DEBUG_MUTEXES (optional, provides 'mutex' as a reason code when a thread stops running) CONFIG_DEBUG_INFO (optional, used for analyzing the kernel) CONFIG_CPU_FREQ (optional, provides frequency setting of the CPU) @@ -101,7 +99,7 @@ Further, the l2c-310 counter can be disabled by providing an offset of zero, ex: *** Compiling an application or shared library *** Recommended compiler settings: - "-g": Debug symbols needed for best analysis results. + "-g": Debug information, such as line numbers, needed for best analysis results. "-fno-inline": Speed improvement when processing the image files and most accurate analysis results. "-fno-omit-frame-pointer": ARM EABI frame pointers (Code Sourcery cross compiler) allow recording of the call stack with each sample taken when in ARM state (i.e. not -mthumb). "-marm": This option is required if your compiler is configured with --with-mode=thumb, otherwise call stack unwinding will not work. diff --git a/daemon/Android.mk b/daemon/Android.mk index 86483f3..4798a0a 100644 --- a/daemon/Android.mk +++ b/daemon/Android.mk @@ -12,6 +12,7 @@ LOCAL_SRC_FILES := \ Collector.cpp \ ConfigurationXML.cpp \ Driver.cpp \ + EventsXML.cpp \ Fifo.cpp \ Hwmon.cpp \ KMod.cpp \ diff --git a/daemon/Buffer.cpp b/daemon/Buffer.cpp index ee391bc..56cf42c 100644 --- a/daemon/Buffer.cpp +++ b/daemon/Buffer.cpp @@ -140,173 +140,46 @@ void Buffer::check (const uint64_t time) { } } -void Buffer::packInt (const int32_t x) { - const int write0 = (writePos + 0) & mask; - const int write1 = (writePos + 1) & mask; - - if ((x & 0xffffff80) == 0) { - buf[write0] = x & 0x7f; - writePos = write1; - } else if ((x & 0xffffc000) == 0) { - const int write2 = (writePos + 2) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) & 0x7f; - writePos = write2; - } else if ((x & 0xffe00000) == 0) { - const int write2 = (writePos + 2) & mask; - const int write3 = (writePos + 3) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) | 0x80; - buf[write2] = (x >> 14) & 0x7f; - writePos = write3; - } else if ((x & 0xf0000000) == 0) { - const int write2 = (writePos + 2) & mask; - const int write3 = (writePos + 3) & mask; - const int write4 = (writePos + 4) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) | 0x80; - buf[write2] = (x >> 14) | 0x80; - buf[write3] = (x >> 21) & 0x7f; - writePos = write4; - } else { - const int write2 = (writePos + 2) & mask; - const int write3 = (writePos + 3) & mask; - const int write4 = (writePos + 4) & mask; - const int write5 = (writePos + 5) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) | 0x80; - buf[write2] = (x >> 14) | 0x80; - buf[write3] = (x >> 21) | 0x80; - buf[write4] = (x >> 28) & 0x0f; - writePos = write5; +void Buffer::packInt (int32_t x) { + int packedBytes = 0; + int more = true; + while (more) { + // low order 7 bits of x + char b = x & 0x7f; + x >>= 7; + + if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) { + more = false; + } else { + b |= 0x80; + } + + buf[(writePos + packedBytes) & mask] = b; + packedBytes++; } + + writePos = (writePos + packedBytes) & mask; } -void Buffer::packInt64 (const int64_t x) { - const int write0 = (writePos + 0) & mask; - const int write1 = (writePos + 1) & mask; - - if ((x & 0xffffffffffffff80LL) == 0) { - buf[write0] = x & 0x7f; - writePos = write1; - } else if ((x & 0xffffffffffffc000LL) == 0) { - const int write2 = (writePos + 2) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) & 0x7f; - writePos = write2; - } else if ((x & 0xffffffffffe00000LL) == 0) { - const int write2 = (writePos + 2) & mask; - const int write3 = (writePos + 3) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) | 0x80; - buf[write2] = (x >> 14) & 0x7f; - writePos = write3; - } else if ((x & 0xfffffffff0000000LL) == 0) { - const int write2 = (writePos + 2) & mask; - const int write3 = (writePos + 3) & mask; - const int write4 = (writePos + 4) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) | 0x80; - buf[write2] = (x >> 14) | 0x80; - buf[write3] = (x >> 21) & 0x7f; - writePos = write4; - } else if ((x & 0xfffffff800000000LL) == 0) { - const int write2 = (writePos + 2) & mask; - const int write3 = (writePos + 3) & mask; - const int write4 = (writePos + 4) & mask; - const int write5 = (writePos + 5) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) | 0x80; - buf[write2] = (x >> 14) | 0x80; - buf[write3] = (x >> 21) | 0x80; - buf[write4] = (x >> 28) & 0x7f; - writePos = write5; - } else if ((x & 0xfffffc0000000000LL) == 0) { - const int write2 = (writePos + 2) & mask; - const int write3 = (writePos + 3) & mask; - const int write4 = (writePos + 4) & mask; - const int write5 = (writePos + 5) & mask; - const int write6 = (writePos + 6) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) | 0x80; - buf[write2] = (x >> 14) | 0x80; - buf[write3] = (x >> 21) | 0x80; - buf[write4] = (x >> 28) | 0x80; - buf[write5] = (x >> 35) & 0x7f; - writePos = write6; - } else if ((x & 0xfffe000000000000LL) == 0) { - const int write2 = (writePos + 2) & mask; - const int write3 = (writePos + 3) & mask; - const int write4 = (writePos + 4) & mask; - const int write5 = (writePos + 5) & mask; - const int write6 = (writePos + 6) & mask; - const int write7 = (writePos + 7) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) | 0x80; - buf[write2] = (x >> 14) | 0x80; - buf[write3] = (x >> 21) | 0x80; - buf[write4] = (x >> 28) | 0x80; - buf[write5] = (x >> 35) | 0x80; - buf[write6] = (x >> 42) & 0x7f; - writePos = write7; - } else if ((x & 0xff00000000000000LL) == 0) { - const int write2 = (writePos + 2) & mask; - const int write3 = (writePos + 3) & mask; - const int write4 = (writePos + 4) & mask; - const int write5 = (writePos + 5) & mask; - const int write6 = (writePos + 6) & mask; - const int write7 = (writePos + 7) & mask; - const int write8 = (writePos + 8) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) | 0x80; - buf[write2] = (x >> 14) | 0x80; - buf[write3] = (x >> 21) | 0x80; - buf[write4] = (x >> 28) | 0x80; - buf[write5] = (x >> 35) | 0x80; - buf[write6] = (x >> 42) | 0x80; - buf[write7] = (x >> 49) & 0x7f; - writePos = write8; - } else if ((x & 0x8000000000000000LL) == 0) { - const int write2 = (writePos + 2) & mask; - const int write3 = (writePos + 3) & mask; - const int write4 = (writePos + 4) & mask; - const int write5 = (writePos + 5) & mask; - const int write6 = (writePos + 6) & mask; - const int write7 = (writePos + 7) & mask; - const int write8 = (writePos + 8) & mask; - const int write9 = (writePos + 9) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) | 0x80; - buf[write2] = (x >> 14) | 0x80; - buf[write3] = (x >> 21) | 0x80; - buf[write4] = (x >> 28) | 0x80; - buf[write5] = (x >> 35) | 0x80; - buf[write6] = (x >> 42) | 0x80; - buf[write7] = (x >> 49) | 0x80; - buf[write8] = (x >> 56) & 0x7f; - writePos = write9; - } else { - const int write2 = (writePos + 2) & mask; - const int write3 = (writePos + 3) & mask; - const int write4 = (writePos + 4) & mask; - const int write5 = (writePos + 5) & mask; - const int write6 = (writePos + 6) & mask; - const int write7 = (writePos + 7) & mask; - const int write8 = (writePos + 8) & mask; - const int write9 = (writePos + 9) & mask; - const int write10 = (writePos + 10) & mask; - buf[write0] = x | 0x80; - buf[write1] = (x >> 7) | 0x80; - buf[write2] = (x >> 14) | 0x80; - buf[write3] = (x >> 21) | 0x80; - buf[write4] = (x >> 28) | 0x80; - buf[write5] = (x >> 35) | 0x80; - buf[write6] = (x >> 42) | 0x80; - buf[write7] = (x >> 49) | 0x80; - buf[write8] = (x >> 56) | 0x80; - buf[write9] = (x >> 63) & 0x7f; - writePos = write10; +void Buffer::packInt64 (int64_t x) { + int packedBytes = 0; + int more = true; + while (more) { + // low order 7 bits of x + char b = x & 0x7f; + x >>= 7; + + if ((x == 0 && (b & 0x40) == 0) || (x == -1 && (b & 0x40) != 0)) { + more = false; + } else { + b |= 0x80; + } + + buf[(writePos + packedBytes) & mask] = b; + packedBytes++; } + + writePos = (writePos + packedBytes) & mask; } void Buffer::frame () { diff --git a/daemon/CapturedXML.cpp b/daemon/CapturedXML.cpp index 8b037cb..af726df 100644 --- a/daemon/CapturedXML.cpp +++ b/daemon/CapturedXML.cpp @@ -51,30 +51,12 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) { counters = mxmlNewElement(captured, "counters"); } mxml_node_t *const node = mxmlNewElement(counters, "counter"); - mxmlElementSetAttr(node, "title", counter.getTitle()); - mxmlElementSetAttr(node, "name", counter.getName()); - mxmlElementSetAttrf(node, "key", "0x%08x", counter.getKey()); + mxmlElementSetAttrf(node, "key", "0x%x", counter.getKey()); mxmlElementSetAttr(node, "type", counter.getType()); - mxmlElementSetAttrf(node, "event", "0x%08x", counter.getEvent()); - if (counter.isPerCPU()) { - mxmlElementSetAttr(node, "per_cpu", "yes"); - } + mxmlElementSetAttrf(node, "event", "0x%x", counter.getEvent()); if (counter.getCount() > 0) { mxmlElementSetAttrf(node, "count", "%d", counter.getCount()); } - if (strlen(counter.getDisplay()) > 0) { - mxmlElementSetAttr(node, "display", counter.getDisplay()); - } - if (strlen(counter.getUnits()) > 0) { - mxmlElementSetAttr(node, "units", counter.getUnits()); - } - if (counter.getModifier() != 1) { - mxmlElementSetAttrf(node, "modifier", "%d", counter.getModifier()); - } - if (counter.isAverageSelection()) { - mxmlElementSetAttr(node, "average_selection", "yes"); - } - mxmlElementSetAttr(node, "description", counter.getDescription()); } } diff --git a/daemon/Child.cpp b/daemon/Child.cpp index c784847..286c7e7 100644 --- a/daemon/Child.cpp +++ b/daemon/Child.cpp @@ -100,14 +100,15 @@ static void* durationThread(void* pVoid) { } static void* stopThread(void* pVoid) { - int length; - char type; OlySocket* socket = child->socket; prctl(PR_SET_NAME, (unsigned long)&"gatord-stopper", 0, 0, 0); while (gSessionData->mSessionIsActive) { // This thread will stall until the APC_STOP or PING command is received over the socket or the socket is disconnected - const int result = socket->receiveNBytes(&type, sizeof(type)); + unsigned char header[5]; + const int result = socket->receiveNBytes((char*)&header, sizeof(header)); + const char type = header[0]; + const int length = (header[1] << 0) | (header[2] << 8) | (header[3] << 16) | (header[4] << 24); if (result == -1) { child->endSession(); } else if (result > 0) { @@ -115,10 +116,6 @@ static void* stopThread(void* pVoid) { logg->logMessage("INVESTIGATE: Received unknown command type %d", type); } else { // verify a length of zero - if (socket->receiveNBytes((char*)&length, sizeof(length)) < 0) { - break; - } - if (length == 0) { if (type == COMMAND_APC_STOP) { logg->logMessage("Stop command received."); diff --git a/daemon/ConfigurationXML.cpp b/daemon/ConfigurationXML.cpp index 9d51f26..fb00202 100644 --- a/daemon/ConfigurationXML.cpp +++ b/daemon/ConfigurationXML.cpp @@ -15,19 +15,10 @@ #include "OlyUtility.h" #include "SessionData.h" -static const char* ATTR_COUNTER = "counter"; -static const char* ATTR_REVISION = "revision"; -static const char* ATTR_TITLE = "title"; -static const char* ATTR_NAME = "name"; -static const char* ATTR_EVENT = "event"; -static const char* ATTR_COUNT = "count"; -static const char* ATTR_PER_CPU = "per_cpu"; -static const char* ATTR_DESCRIPTION = "description"; -static const char* ATTR_EBS = "supports_event_based_sampling"; -static const char* ATTR_DISPLAY = "display"; -static const char* ATTR_UNITS = "units"; -static const char* ATTR_MODIFIER = "modifier"; -static const char* ATTR_AVERAGE_SELECTION = "average_selection"; +static const char* ATTR_COUNTER = "counter"; +static const char* ATTR_REVISION = "revision"; +static const char* ATTR_EVENT = "event"; +static const char* ATTR_COUNT = "count"; ConfigurationXML::ConfigurationXML() { const char * configuration_xml; @@ -87,7 +78,7 @@ int ConfigurationXML::parse(const char* configurationXML) { int ret; // clear counter overflow - gSessionData->mCounterOverflow = false; + gSessionData->mCounterOverflow = 0; mIndex = 0; // disable all counters prior to parsing the configuration xml @@ -123,7 +114,7 @@ void ConfigurationXML::validate(void) { const Counter & counter = gSessionData->mCounters[i]; if (counter.isEnabled()) { if (strcmp(counter.getType(), "") == 0) { - logg->logError(__FILE__, __LINE__, "Invalid required attribute in configuration.xml:\n counter=\"%s\"\n title=\"%s\"\n name=\"%s\"\n event=%d\n", counter.getType(), counter.getTitle(), counter.getName(), counter.getEvent()); + logg->logError(__FILE__, __LINE__, "Invalid required attribute in configuration.xml:\n counter=\"%s\"\n event=%d\n", counter.getType(), counter.getEvent()); handleException(); } @@ -142,7 +133,7 @@ void ConfigurationXML::validate(void) { } } -#define CONFIGURATION_REVISION 2 +#define CONFIGURATION_REVISION 3 int ConfigurationXML::configurationsTag(mxml_node_t *node) { const char* revision_string; @@ -156,13 +147,17 @@ int ConfigurationXML::configurationsTag(mxml_node_t *node) { return 1; // revision issue } + // A revision >= CONFIGURATION_REVISION is okay + // Greater than can occur when Streamline is newer than gator + return 0; } void ConfigurationXML::configurationTag(mxml_node_t *node) { // handle all other performance counters if (mIndex >= MAX_PERFORMANCE_COUNTERS) { - gSessionData->mCounterOverflow = true; + mIndex++; + gSessionData->mCounterOverflow = mIndex; return; } @@ -170,24 +165,15 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) { Counter & counter = gSessionData->mCounters[mIndex]; counter.clear(); if (mxmlElementGetAttr(node, ATTR_COUNTER)) counter.setType(mxmlElementGetAttr(node, ATTR_COUNTER)); - if (mxmlElementGetAttr(node, ATTR_TITLE)) counter.setTitle(mxmlElementGetAttr(node, ATTR_TITLE)); - if (mxmlElementGetAttr(node, ATTR_NAME)) counter.setName(mxmlElementGetAttr(node, ATTR_NAME)); - if (mxmlElementGetAttr(node, ATTR_DESCRIPTION)) counter.setDescription(mxmlElementGetAttr(node, ATTR_DESCRIPTION)); if (mxmlElementGetAttr(node, ATTR_EVENT)) counter.setEvent(strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16)); if (mxmlElementGetAttr(node, ATTR_COUNT)) counter.setCount(strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10)); - if (mxmlElementGetAttr(node, ATTR_PER_CPU)) counter.setPerCPU(util->stringToBool(mxmlElementGetAttr(node, ATTR_PER_CPU), false)); - if (mxmlElementGetAttr(node, ATTR_EBS)) counter.setEBSCapable(util->stringToBool(mxmlElementGetAttr(node, ATTR_EBS), false)); - if (mxmlElementGetAttr(node, ATTR_DISPLAY)) counter.setDisplay(mxmlElementGetAttr(node, ATTR_DISPLAY)); - if (mxmlElementGetAttr(node, ATTR_UNITS)) counter.setUnits(mxmlElementGetAttr(node, ATTR_UNITS)); - if (mxmlElementGetAttr(node, ATTR_MODIFIER)) counter.setModifier(strtol(mxmlElementGetAttr(node, ATTR_MODIFIER), NULL, 10)); - if (mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION)) counter.setAverageSelection(util->stringToBool(mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION), false)); counter.setEnabled(true); // Associate a driver with each counter for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) { if (driver->claimCounter(counter)) { if (counter.getDriver() != NULL) { - logg->logError(__FILE__, __LINE__, "More than one driver has claimed %s: %s", counter.getTitle(), counter.getName()); + logg->logError(__FILE__, __LINE__, "More than one driver has claimed %s:%i", counter.getType(), counter.getEvent()); handleException(); } counter.setDriver(driver); @@ -196,12 +182,14 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) { // If no driver is associated with the counter, disable it if (counter.getDriver() == NULL) { - logg->logMessage("No driver has claimed %s (%s: %s)", counter.getType(), counter.getTitle(), counter.getName()); + logg->logMessage("No driver has claimed %s:%i", counter.getType(), counter.getEvent()); counter.setEnabled(false); } - // update counter index - mIndex++; + if (counter.isEnabled()) { + // update counter index + mIndex++; + } } void ConfigurationXML::getDefaultConfigurationXml(const char * & xml, unsigned int & len) { diff --git a/daemon/Counter.h b/daemon/Counter.h index 041020b..231a85d 100644 --- a/daemon/Counter.h +++ b/daemon/Counter.h @@ -24,52 +24,25 @@ public: void clear () { mType[0] = '\0'; - mTitle[0] = '\0'; - mName[0] = '\0'; - mDescription[0] = '\0'; - mDisplay[0] = '\0'; - mUnits[0] = '\0'; - mModifier = 1; mEnabled = false; mEvent = 0; mCount = 0; mKey = 0; - mPerCPU = false; - mEBSCapable = false; - mAverageSelection = false; mDriver = NULL; } void setType(const char *const type) { strncpy(mType, type, sizeof(mType)); mType[sizeof(mType) - 1] = '\0'; } - void setTitle(const char *const title) { strncpy(mTitle, title, sizeof(mTitle)); mTitle[sizeof(mTitle) - 1] = '\0'; } - void setName(const char *const name) { strncpy(mName, name, sizeof(mName)); mName[sizeof(mName) - 1] = '\0'; } - void setDescription(const char *const description) { strncpy(mDescription, description, sizeof(mDescription)); mDescription[sizeof(mDescription) - 1] = '\0'; } - void setDisplay(const char *const display) { strncpy(mDisplay, display, sizeof(mDisplay)); mDisplay[sizeof(mDisplay) - 1] = '\0'; } - void setUnits(const char *const units) { strncpy(mUnits, units, sizeof(mUnits)); mUnits[sizeof(mUnits) - 1] = '\0'; } - void setModifier(const int modifier) { mModifier = modifier; } void setEnabled(const bool enabled) { mEnabled = enabled; } void setEvent(const int event) { mEvent = event; } void setCount(const int count) { mCount = count; } void setKey(const int key) { mKey = key; } - void setPerCPU(const bool perCPU) { mPerCPU = perCPU; } - void setEBSCapable(const bool ebsCapable) { mEBSCapable = ebsCapable; } - void setAverageSelection(const bool averageSelection) { mAverageSelection = averageSelection; } void setDriver(Driver *const driver) { mDriver = driver; } const char *getType() const { return mType;} - const char *getTitle() const { return mTitle; } - const char *getName() const { return mName; } - const char *getDescription() const { return mDescription; } - const char *getDisplay() const { return mDisplay; } - const char *getUnits() const { return mUnits; } - int getModifier() const { return mModifier; } bool isEnabled() const { return mEnabled; } int getEvent() const { return mEvent; } int getCount() const { return mCount; } int getKey() const { return mKey; } - bool isPerCPU() const { return mPerCPU; } - bool isEBSCapable() const { return mEBSCapable; } - bool isAverageSelection() const { return mAverageSelection; } Driver *getDriver() const { return mDriver; } private: @@ -78,19 +51,10 @@ private: Counter & operator=(const Counter &); char mType[MAX_STRING_LEN]; - char mTitle[MAX_STRING_LEN]; - char mName[MAX_STRING_LEN]; - char mDescription[MAX_DESCRIPTION_LEN]; - char mDisplay[MAX_STRING_LEN]; - char mUnits[MAX_STRING_LEN]; - int mModifier; bool mEnabled; int mEvent; int mCount; int mKey; - bool mPerCPU; - bool mEBSCapable; - bool mAverageSelection; Driver *mDriver; }; diff --git a/daemon/EventsXML.cpp b/daemon/EventsXML.cpp new file mode 100644 index 0000000..2a80482 --- /dev/null +++ b/daemon/EventsXML.cpp @@ -0,0 +1,70 @@ +/** + * Copyright (C) ARM Limited 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 + * published by the Free Software Foundation. + */ + +#include "EventsXML.h" + +#include "CapturedXML.h" +#include "Logging.h" +#include "OlyUtility.h" +#include "SessionData.h" + +char* EventsXML::getXML() { +#include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len + char path[PATH_MAX]; + mxml_node_t *xml; + FILE *fl; + + // Avoid unused variable warning + (void)events_xml_len; + + // Load the provided or default events xml + if (gSessionData->mEventsXMLPath) { + strncpy(path, gSessionData->mEventsXMLPath, PATH_MAX); + } else { + util->getApplicationFullPath(path, PATH_MAX); + strncat(path, "events.xml", PATH_MAX - strlen(path) - 1); + } + fl = fopen(path, "r"); + if (fl) { + xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); + fclose(fl); + } else { + logg->logMessage("Unable to locate events.xml, using default"); + xml = mxmlLoadString(NULL, (char *)events_xml, MXML_NO_CALLBACK); + } + + // Add dynamic events from the drivers + mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); + if (!events) { + logg->logMessage("Unable to find node in the events.xml"); + handleException(); + } + for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) { + driver->writeEvents(events); + } + + char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB); + mxmlDelete(xml); + + return string; +} + +void EventsXML::write(const char* path) { + char file[PATH_MAX]; + + // Set full path + snprintf(file, PATH_MAX, "%s/events.xml", path); + + char* buf = getXML(); + if (util->writeToDisk(file, buf) < 0) { + logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); + handleException(); + } + + free(buf); +} diff --git a/daemon/EventsXML.h b/daemon/EventsXML.h new file mode 100644 index 0000000..8e693ef --- /dev/null +++ b/daemon/EventsXML.h @@ -0,0 +1,18 @@ +/** + * Copyright (C) ARM Limited 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 + * published by the Free Software Foundation. + */ + +#ifndef EVENTS_XML +#define EVENTS_XML + +class EventsXML { +public: + char* getXML(); + void write(const char* path); +}; + +#endif // EVENTS_XML diff --git a/daemon/Fifo.cpp b/daemon/Fifo.cpp index f0b0178..250a4d0 100644 --- a/daemon/Fifo.cpp +++ b/daemon/Fifo.cpp @@ -6,122 +6,125 @@ * published by the Free Software Foundation. */ -#include -#include -#include #include "Fifo.h" + +#include +#ifdef WIN32 +#define valloc malloc +#endif + #include "Logging.h" // bufferSize is the amount of data to be filled // singleBufferSize is the maximum size that may be filled during a single write // (bufferSize + singleBufferSize) will be allocated Fifo::Fifo(int singleBufferSize, int bufferSize, sem_t* readerSem) { - mWrite = mRead = mReadCommit = mRaggedEnd = 0; - mWrapThreshold = bufferSize; - mSingleBufferSize = singleBufferSize; - mReaderSem = readerSem; - mBuffer = (char*)valloc(bufferSize + singleBufferSize); - mEnd = false; - - if (mBuffer == NULL) { - logg->logError(__FILE__, __LINE__, "failed to allocate %d bytes", bufferSize + singleBufferSize); - handleException(); - } - - if (sem_init(&mWaitForSpaceSem, 0, 0)) { - logg->logError(__FILE__, __LINE__, "sem_init() failed"); - handleException(); - } + mWrite = mRead = mReadCommit = mRaggedEnd = 0; + mWrapThreshold = bufferSize; + mSingleBufferSize = singleBufferSize; + mReaderSem = readerSem; + mBuffer = (char*)valloc(bufferSize + singleBufferSize); + mEnd = false; + + if (mBuffer == NULL) { + logg->logError(__FILE__, __LINE__, "failed to allocate %d bytes", bufferSize + singleBufferSize); + handleException(); + } + + if (sem_init(&mWaitForSpaceSem, 0, 0)) { + logg->logError(__FILE__, __LINE__, "sem_init() failed"); + handleException(); + } } Fifo::~Fifo() { - free(mBuffer); - sem_destroy(&mWaitForSpaceSem); + free(mBuffer); + sem_destroy(&mWaitForSpaceSem); } int Fifo::numBytesFilled() const { - return mWrite - mRead + mRaggedEnd; + return mWrite - mRead + mRaggedEnd; } char* Fifo::start() const { - return mBuffer; + return mBuffer; } bool Fifo::isEmpty() const { - return mRead == mWrite && mRaggedEnd == 0; + return mRead == mWrite && mRaggedEnd == 0; } bool Fifo::isFull() const { - return willFill(0); + return willFill(0); } // Determines if the buffer will fill assuming 'additional' bytes will be added to the buffer // 'full' means there is less than singleBufferSize bytes available contiguously; it does not mean there are zero bytes available bool Fifo::willFill(int additional) const { - if (mWrite > mRead) { - if (numBytesFilled() + additional < mWrapThreshold) { - return false; - } - } else { - if (numBytesFilled() + additional < mWrapThreshold - mSingleBufferSize) { - return false; - } - } - return true; + if (mWrite > mRead) { + if (numBytesFilled() + additional < mWrapThreshold) { + return false; + } + } else { + if (numBytesFilled() + additional < mWrapThreshold - mSingleBufferSize) { + return false; + } + } + return true; } // This function will stall until contiguous singleBufferSize bytes are available char* Fifo::write(int length) { - if (length <= 0) { - length = 0; - mEnd = true; - } + if (length <= 0) { + length = 0; + mEnd = true; + } - // update the write pointer - mWrite += length; + // update the write pointer + mWrite += length; - // handle the wrap-around - if (mWrite >= mWrapThreshold) { - mRaggedEnd = mWrite; - mWrite = 0; - } + // handle the wrap-around + if (mWrite >= mWrapThreshold) { + mRaggedEnd = mWrite; + mWrite = 0; + } - // send a notification that data is ready - sem_post(mReaderSem); + // send a notification that data is ready + sem_post(mReaderSem); - // wait for space - while (isFull()) { - sem_wait(&mWaitForSpaceSem); - } + // wait for space + while (isFull()) { + sem_wait(&mWaitForSpaceSem); + } - return &mBuffer[mWrite]; + return &mBuffer[mWrite]; } void Fifo::release() { - // update the read pointer now that the data has been handled - mRead = mReadCommit; + // update the read pointer now that the data has been handled + mRead = mReadCommit; - // handle the wrap-around - if (mRead >= mWrapThreshold) { - mRaggedEnd = mRead = mReadCommit = 0; - } + // handle the wrap-around + if (mRead >= mWrapThreshold) { + mRaggedEnd = mRead = mReadCommit = 0; + } - // send a notification that data is free (space is available) - sem_post(&mWaitForSpaceSem); + // send a notification that data is free (space is available) + sem_post(&mWaitForSpaceSem); } // This function will return null if no data is available char* Fifo::read(int *const length) { - // wait for data - if (isEmpty() && !mEnd) { - return NULL; - } - - // obtain the length - do { - mReadCommit = mRaggedEnd ? mRaggedEnd : mWrite; - *length = mReadCommit - mRead; - } while (*length < 0); // plugs race condition without using semaphores - - return &mBuffer[mRead]; + // wait for data + if (isEmpty() && !mEnd) { + return NULL; + } + + // obtain the length + do { + mReadCommit = mRaggedEnd ? mRaggedEnd : mWrite; + *length = mReadCommit - mRead; + } while (*length < 0); // plugs race condition without using semaphores + + return &mBuffer[mRead]; } diff --git a/daemon/Fifo.h b/daemon/Fifo.h index d46e1af..ada42b9 100644 --- a/daemon/Fifo.h +++ b/daemon/Fifo.h @@ -9,27 +9,36 @@ #ifndef __FIFO_H__ #define __FIFO_H__ +#ifdef WIN32 +#include +#define sem_t HANDLE +#define sem_init(sem, pshared, value) ((*(sem) = CreateSemaphore(NULL, value, INFINITE, NULL)) == NULL) +#define sem_wait(sem) WaitForSingleObject(*(sem), INFINITE) +#define sem_post(sem) ReleaseSemaphore(*(sem), 1, NULL) +#define sem_destroy(sem) CloseHandle(*(sem)) +#else #include +#endif class Fifo { public: - Fifo(int singleBufferSize, int totalBufferSize, sem_t* readerSem); - ~Fifo(); - int numBytesFilled() const; - bool isEmpty() const; - bool isFull() const; - bool willFill(int additional) const; - char* start() const; - char* write(int length); - void release(); - char* read(int *const length); + Fifo(int singleBufferSize, int totalBufferSize, sem_t* readerSem); + ~Fifo(); + int numBytesFilled() const; + bool isEmpty() const; + bool isFull() const; + bool willFill(int additional) const; + char* start() const; + char* write(int length); + void release(); + char* read(int *const length); private: - int mSingleBufferSize, mWrite, mRead, mReadCommit, mRaggedEnd, mWrapThreshold; - sem_t mWaitForSpaceSem; - sem_t* mReaderSem; - char* mBuffer; - bool mEnd; + int mSingleBufferSize, mWrite, mRead, mReadCommit, mRaggedEnd, mWrapThreshold; + sem_t mWaitForSpaceSem; + sem_t* mReaderSem; + char* mBuffer; + bool mEnd; }; #endif //__FIFO_H__ diff --git a/daemon/Hwmon.cpp b/daemon/Hwmon.cpp index 9603411..9475215 100644 --- a/daemon/Hwmon.cpp +++ b/daemon/Hwmon.cpp @@ -26,20 +26,30 @@ public: const char *getName() const { return name; } const char *getLabel() const { return label; } const char *getTitle() const { return title; } + bool isDuplicate() const { return duplicate; } const char *getDisplay() const { return display; } const char *getUnit() const { return unit; } int getModifier() const { return modifier; } - void setEnabled(const bool enabled) { this->enabled = enabled; } + void setEnabled(const bool enabled) { + this->enabled = enabled; + // canRead will clear enabled if the counter is not readable + canRead(); + } double read(); + bool canRead(); private: void init(const sensors_chip_name *chip, const sensors_feature *feature); HwmonCounter *const next; const int key; - bool enabled; + int polled : 1, + readable : 1, + enabled : 1, + monotonic: 1, + duplicate : 1; const sensors_chip_name *chip; const sensors_feature *feature; @@ -50,13 +60,12 @@ private: const char *display; const char *unit; int modifier; - bool monotonic; double previous_value; sensors_subfeature_type input; }; -HwmonCounter::HwmonCounter(HwmonCounter *next, int key, const sensors_chip_name *chip, const sensors_feature *feature) : next(next), key(key), enabled(false), chip(chip), feature(feature) { +HwmonCounter::HwmonCounter(HwmonCounter *next, int key, const sensors_chip_name *chip, const sensors_feature *feature) : next(next), key(key), polled(false), readable(false), enabled(false), duplicate(false), chip(chip), feature(feature) { int len = sensors_snprintf_chip_name(NULL, 0, chip) + 1; char *chip_name = new char[len]; @@ -131,6 +140,14 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, int key, const sensors_chip_name logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", feature->type); handleException(); } + + for (HwmonCounter * counter = next; counter != NULL; counter = counter->getNext()) { + if (strcmp(label, counter->getLabel()) == 0 && strcmp(title, counter->getTitle()) == 0) { + duplicate = true; + counter->duplicate = true; + break; + } + } } HwmonCounter::~HwmonCounter() { @@ -143,6 +160,7 @@ double HwmonCounter::read() { double result; const sensors_subfeature *subfeature; + // Keep in sync with canRead subfeature = sensors_get_subfeature(chip, feature, input); if (!subfeature) { logg->logError(__FILE__, __LINE__, "No input value for hwmon sensor %s", label); @@ -160,6 +178,27 @@ double HwmonCounter::read() { return result; } +bool HwmonCounter::canRead() { + if (!polled) { + double value; + const sensors_subfeature *subfeature; + bool result = true; + + subfeature = sensors_get_subfeature(chip, feature, input); + if (!subfeature) { + result = false; + } else { + result = sensors_get_value(chip, subfeature->number, &value) == 0; + } + + polled = true; + readable = result; + } + + enabled &= readable; + + return readable; +} Hwmon::Hwmon() : counters(NULL) { int err = sensors_init(NULL); @@ -191,7 +230,7 @@ Hwmon::~Hwmon() { HwmonCounter *Hwmon::findCounter(const Counter &counter) const { for (HwmonCounter * hwmonCounter = counters; hwmonCounter != NULL; hwmonCounter = hwmonCounter->getNext()) { - if (strcmp(hwmonCounter->getName(), counter.getType()) == 0) { + if (hwmonCounter->canRead() && strcmp(hwmonCounter->getName(), counter.getType()) == 0) { return hwmonCounter; } } @@ -230,6 +269,9 @@ void Hwmon::setupCounter(Counter &counter) { void Hwmon::writeCounters(mxml_node_t *root) const { for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) { + if (!counter->canRead()) { + continue; + } mxml_node_t *node = mxmlNewElement(root, "counter"); mxmlElementSetAttr(node, "name", counter->getName()); } @@ -241,10 +283,17 @@ void Hwmon::writeEvents(mxml_node_t *root) const { char buf[1024]; for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) { + if (!counter->canRead()) { + continue; + } mxml_node_t *node = mxmlNewElement(root, "event"); mxmlElementSetAttr(node, "counter", counter->getName()); mxmlElementSetAttr(node, "title", counter->getTitle()); - mxmlElementSetAttr(node, "name", counter->getLabel()); + if (counter->isDuplicate()) { + mxmlElementSetAttrf(node, "name", "%s (0x%x)", counter->getLabel(), counter->getKey()); + } else { + mxmlElementSetAttr(node, "name", counter->getLabel()); + } mxmlElementSetAttr(node, "display", counter->getDisplay()); mxmlElementSetAttr(node, "units", counter->getUnit()); if (counter->getModifier() != 1) { diff --git a/daemon/KMod.cpp b/daemon/KMod.cpp index 5f12046..04f3330 100644 --- a/daemon/KMod.cpp +++ b/daemon/KMod.cpp @@ -58,25 +58,23 @@ void KMod::setupCounter(Counter &counter) { } snprintf(text, sizeof(text), "%s/key", base); - int key; + int key = 0; Collector::readIntDriver(text, &key); counter.setKey(key); snprintf(text, sizeof(text), "%s/event", base); Collector::writeDriver(text, counter.getEvent()); - if (counter.isEBSCapable()) { - snprintf(text, sizeof(text), "%s/count", base); - if (access(text, F_OK) == 0) { - int count = counter.getCount(); - if (Collector::writeReadDriver(text, &count) && counter.getCount() > 0) { - logg->logError(__FILE__, __LINE__, "Cannot enable EBS for %s:%s with a count of %d\n", counter.getTitle(), counter.getName(), counter.getCount()); - handleException(); - } - counter.setCount(count); - } else if (counter.getCount() > 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"); + snprintf(text, sizeof(text), "%s/count", base); + if (access(text, F_OK) == 0) { + int count = counter.getCount(); + if (Collector::writeReadDriver(text, &count) && counter.getCount() > 0) { + logg->logError(__FILE__, __LINE__, "Cannot enable EBS for %s:%i with a count of %d\n", counter.getType(), counter.getEvent(), counter.getCount()); handleException(); } + counter.setCount(count); + } else if (counter.getCount() > 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(); } } diff --git a/daemon/LocalCapture.cpp b/daemon/LocalCapture.cpp index baa3dd9..3235a34 100644 --- a/daemon/LocalCapture.cpp +++ b/daemon/LocalCapture.cpp @@ -16,6 +16,7 @@ #include "SessionData.h" #include "Logging.h" #include "OlyUtility.h" +#include "EventsXML.h" LocalCapture::LocalCapture() {} @@ -40,6 +41,10 @@ void LocalCapture::write(char* string) { logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); handleException(); } + + // Write events XML + EventsXML eventsXML; + eventsXML.write(gSessionData->mAPCDir); } char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* ending) { diff --git a/daemon/OlySocket.cpp b/daemon/OlySocket.cpp index 499f68c..132510d 100644 --- a/daemon/OlySocket.cpp +++ b/daemon/OlySocket.cpp @@ -6,6 +6,8 @@ * published by the Free Software Foundation. */ +#include "OlySocket.h" + #include #ifdef WIN32 #include @@ -15,7 +17,7 @@ #include #include #endif -#include "OlySocket.h" + #include "Logging.h" #ifdef WIN32 diff --git a/daemon/OlyUtility.cpp b/daemon/OlyUtility.cpp index 2f85131..b29a1e9 100644 --- a/daemon/OlyUtility.cpp +++ b/daemon/OlyUtility.cpp @@ -6,6 +6,8 @@ * published by the Free Software Foundation. */ +#include "OlyUtility.h" + #include #include #include @@ -19,8 +21,6 @@ #include #endif -#include "OlyUtility.h" - OlyUtility* util = NULL; bool OlyUtility::stringToBool(const char* string, bool defValue) { diff --git a/daemon/OlyUtility.h b/daemon/OlyUtility.h index 5c68a58..abab0a5 100644 --- a/daemon/OlyUtility.h +++ b/daemon/OlyUtility.h @@ -9,6 +9,8 @@ #ifndef OLY_UTILITY_H #define OLY_UTILITY_H +#include + #ifdef WIN32 #define PATH_SEPARATOR '\\' #define CAIMAN_PATH_MAX MAX_PATH diff --git a/daemon/SessionData.h b/daemon/SessionData.h index 5b6899b..22a8af0 100644 --- a/daemon/SessionData.h +++ b/daemon/SessionData.h @@ -16,7 +16,7 @@ #define MAX_PERFORMANCE_COUNTERS 50 -#define PROTOCOL_VERSION 13 +#define PROTOCOL_VERSION 14 #define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions struct ImageLinkList { @@ -57,7 +57,7 @@ public: int mCpuId; // PMU Counters - bool mCounterOverflow; + int mCounterOverflow; Counter mCounters[MAX_PERFORMANCE_COUNTERS]; private: diff --git a/daemon/StreamlineSetup.cpp b/daemon/StreamlineSetup.cpp index 88c07a6..e196a7d 100644 --- a/daemon/StreamlineSetup.cpp +++ b/daemon/StreamlineSetup.cpp @@ -20,6 +20,7 @@ #include "StreamlineSetup.h" #include "ConfigurationXML.h" #include "Driver.h" +#include "EventsXML.h" static const char* TAG_SESSION = "session"; static const char* TAG_REQUEST = "request"; @@ -77,8 +78,8 @@ StreamlineSetup::StreamlineSetup(OlySocket* s) { free(data); } - if (gSessionData->mCounterOverflow) { - logg->logError(__FILE__, __LINE__, "Exceeded maximum number of %d performance counters", MAX_PERFORMANCE_COUNTERS); + if (gSessionData->mCounterOverflow > 0) { + logg->logError(__FILE__, __LINE__, "Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow); handleException(); } } @@ -87,12 +88,12 @@ StreamlineSetup::~StreamlineSetup() { } char* StreamlineSetup::readCommand(int* command) { - char type; + unsigned char header[5]; char* data; - int response, length; + int response; - // receive type - response = mSocket->receiveNBytes(&type, sizeof(type)); + // receive type and length + response = mSocket->receiveNBytes((char*)&header, sizeof(header)); // After receiving a single byte, we are no longer waiting on a command gSessionData->mWaitingOnCommand = false; @@ -102,12 +103,8 @@ char* StreamlineSetup::readCommand(int* command) { handleException(); } - // receive length - response = mSocket->receiveNBytes((char*)&length, sizeof(length)); - if (response < 0) { - logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect"); - handleException(); - } + const char type = header[0]; + const int length = (header[1] << 0) | (header[2] << 8) | (header[3] << 16) | (header[4] << 24); // add artificial limit if ((length < 0) || length > 1024 * 1024) { @@ -198,51 +195,22 @@ void StreamlineSetup::handleDeliver(char* xml) { mxmlDelete(tree); } -void StreamlineSetup::sendData(const char* data, int length, int type) { - mSocket->send((char*)&type, 1); - mSocket->send((char*)&length, sizeof(length)); +void StreamlineSetup::sendData(const char* data, uint32_t length, char type) { + unsigned char header[5]; + header[0] = type; + header[1] = (length >> 0) & 0xff; + header[2] = (length >> 8) & 0xff; + header[3] = (length >> 16) & 0xff; + header[4] = (length >> 24) & 0xff; + mSocket->send((char*)&header, sizeof(header)); mSocket->send((char*)data, length); } void StreamlineSetup::sendEvents() { -#include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len - char path[PATH_MAX]; - mxml_node_t *xml; - FILE *fl; - - // Avoid unused variable warning - (void)events_xml_len; - - // Load the provided or default events xml - if (gSessionData->mEventsXMLPath) { - strncpy(path, gSessionData->mEventsXMLPath, PATH_MAX); - } else { - util->getApplicationFullPath(path, PATH_MAX); - strncat(path, "events.xml", PATH_MAX - strlen(path) - 1); - } - fl = fopen(path, "r"); - if (fl) { - xml = mxmlLoadFile(NULL, fl, MXML_NO_CALLBACK); - fclose(fl); - } else { - logg->logMessage("Unable to locate events.xml, using default"); - xml = mxmlLoadString(NULL, (char *)events_xml, MXML_NO_CALLBACK); - } - - // Add dynamic events from the drivers - mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); - if (!events) { - logg->logMessage("Unable to find node in the events.xml"); - handleException(); - } - for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) { - driver->writeEvents(events); - } - - char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB); + EventsXML eventsXML; + char* string = eventsXML.getXML(); sendString(string, RESPONSE_XML); free(string); - mxmlDelete(xml); } void StreamlineSetup::sendConfiguration() { @@ -302,8 +270,8 @@ void StreamlineSetup::writeConfiguration(char* xml) { // Re-populate gSessionData with the configuration, as it has now changed { ConfigurationXML configuration; } - if (gSessionData->mCounterOverflow) { - logg->logError(__FILE__, __LINE__, "Exceeded maximum number of %d performance counters", MAX_PERFORMANCE_COUNTERS); + if (gSessionData->mCounterOverflow > 0) { + logg->logError(__FILE__, __LINE__, "Only %i performance counters counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow); handleException(); } } diff --git a/daemon/StreamlineSetup.h b/daemon/StreamlineSetup.h index 841735d..a27a7ac 100644 --- a/daemon/StreamlineSetup.h +++ b/daemon/StreamlineSetup.h @@ -32,7 +32,7 @@ private: char* readCommand(int*); void handleRequest(char* xml); void handleDeliver(char* xml); - void sendData(const char* data, int length, int type); + void sendData(const char* data, uint32_t length, char type); void sendString(const char* string, int type) {sendData(string, strlen(string), type);} void sendEvents(); void sendConfiguration(); diff --git a/daemon/common.mk b/daemon/common.mk index 112b990..ee2415b 100644 --- a/daemon/common.mk +++ b/daemon/common.mk @@ -24,7 +24,7 @@ events.xml: events_header.xml $(wildcard events-*.xml) events_footer.xml include $(wildcard *.d) include $(wildcard mxml/*.d) -StreamlineSetup.cpp: events_xml.h +EventsXML.cpp: events_xml.h ConfigurationXML.cpp: configuration_xml.h # Don't regenerate conf-lex.c or conf-parse.c diff --git a/daemon/configuration.xml b/daemon/configuration.xml index 62ccd08..b44c00a 100644 --- a/daemon/configuration.xml +++ b/daemon/configuration.xml @@ -1,47 +1,57 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/daemon/escape.c b/daemon/escape.c index a154515..3eec1f8 100644 --- a/daemon/escape.c +++ b/daemon/escape.c @@ -50,14 +50,20 @@ int main(int argc, char *argv[]) { printf("static const unsigned char "); print_escaped_path(path); printf("[] = {"); - for (; (ch = fgetc(in)) != EOF; ++len) { + for (;;) { + ch = fgetc(in); if (len != 0) { printf(","); } if (len % 12 == 0) { printf("\n "); } - printf(" 0x%.2x", ch); + // Write out a null character after the contents of the file but do not increment len + printf(" 0x%.2x", (ch == EOF ? 0 : ch)); + if (ch == EOF) { + break; + } + ++len; } printf("\n};\nstatic const unsigned int "); print_escaped_path(path); diff --git a/daemon/events-ARM11.xml b/daemon/events-ARM11.xml index 9f31313..57e3235 100644 --- a/daemon/events-ARM11.xml +++ b/daemon/events-ARM11.xml @@ -1,6 +1,6 @@ - + diff --git a/daemon/events-ARM11MPCore.xml b/daemon/events-ARM11MPCore.xml index 68ca9a5..2d5c5e1 100644 --- a/daemon/events-ARM11MPCore.xml +++ b/daemon/events-ARM11MPCore.xml @@ -1,6 +1,6 @@ - + diff --git a/daemon/events-CCI-400.xml b/daemon/events-CCI-400.xml index 2be0df3..86db208 100644 --- a/daemon/events-CCI-400.xml +++ b/daemon/events-CCI-400.xml @@ -1,6 +1,6 @@ - +