summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Medhurst2012-05-16 08:34:10 -0500
committerJon Medhurst2012-05-16 08:34:10 -0500
commitcf81facb732aa92b23e5bba77a9b711fdfb73297 (patch)
tree0d56e46ba2cd84e5abcdcedf4b1f634389aee0ab
parent097d741a276a55d6f89bb5e65439b95f9abedaf5 (diff)
parent401972d0edd099668c8ea86bb6db71c4067a2dfb (diff)
downloadarm-ds5-gator-cf81facb732aa92b23e5bba77a9b711fdfb73297.tar.gz
arm-ds5-gator-cf81facb732aa92b23e5bba77a9b711fdfb73297.tar.xz
arm-ds5-gator-cf81facb732aa92b23e5bba77a9b711fdfb73297.zip
Merge branch 'master' into android
-rwxr-xr-x[-rw-r--r--]daemon/Android.mk15
-rw-r--r--daemon/CapturedXML.cpp92
-rw-r--r--daemon/CapturedXML.h8
-rw-r--r--daemon/Child.cpp56
-rw-r--r--daemon/Child.h8
-rw-r--r--daemon/Collector.cpp98
-rw-r--r--daemon/Collector.h8
-rw-r--r--daemon/ConfigurationXML.cpp136
-rw-r--r--daemon/ConfigurationXML.h10
-rw-r--r--daemon/Fifo.cpp229
-rw-r--r--daemon/Fifo.h74
-rw-r--r--daemon/LocalCapture.cpp30
-rw-r--r--daemon/LocalCapture.h4
-rw-r--r--daemon/Makefile14
-rwxr-xr-x[-rw-r--r--]daemon/OlySocket.cpp30
-rwxr-xr-x[-rw-r--r--]daemon/OlySocket.h4
-rwxr-xr-x[-rw-r--r--]daemon/OlyUtility.cpp111
-rwxr-xr-x[-rw-r--r--]daemon/OlyUtility.h5
-rw-r--r--daemon/RequestXML.cpp61
-rw-r--r--daemon/RequestXML.h33
-rw-r--r--daemon/Sender.cpp56
-rw-r--r--daemon/Sender.h8
-rw-r--r--daemon/SessionData.cpp23
-rw-r--r--daemon/SessionData.h25
-rw-r--r--daemon/SessionXML.cpp107
-rw-r--r--daemon/SessionXML.h8
-rw-r--r--daemon/StreamlineSetup.cpp166
-rw-r--r--daemon/StreamlineSetup.h4
-rw-r--r--daemon/XMLOut.cpp175
-rw-r--r--daemon/XMLOut.h45
-rw-r--r--daemon/XMLReader.cpp164
-rw-r--r--daemon/XMLReader.h27
-rw-r--r--daemon/configuration.xml86
-rw-r--r--daemon/events-ARM11.xml8
-rw-r--r--daemon/events-ARM11MPCore.xml10
-rw-r--r--daemon/events-Cortex-A15.xml65
-rw-r--r--daemon/events-Cortex-A5.xml14
-rwxr-xr-x[-rw-r--r--]daemon/events-Cortex-A7.xml31
-rw-r--r--daemon/events-Cortex-A8.xml19
-rw-r--r--daemon/events-Cortex-A9.xml39
-rwxr-xr-x[-rw-r--r--]daemon/events-Krait-architected.xml15
-rw-r--r--daemon/events-L2C-310.xml30
-rw-r--r--daemon/events-Linux.xml21
-rw-r--r--daemon/events-Mali-400.xml4
-rw-r--r--daemon/events-Scorpion.xml185
-rw-r--r--daemon/events-ScorpionMP.xml151
-rw-r--r--daemon/main.cpp95
-rw-r--r--daemon/mxml/COPYING507
-rw-r--r--daemon/mxml/config.h96
-rw-r--r--daemon/mxml/mxml-attr.c319
-rw-r--r--daemon/mxml/mxml-entity.c460
-rw-r--r--daemon/mxml/mxml-file.c3080
-rw-r--r--daemon/mxml/mxml-get.c471
-rw-r--r--daemon/mxml/mxml-index.c662
-rw-r--r--daemon/mxml/mxml-node.c807
-rw-r--r--daemon/mxml/mxml-private.c331
-rw-r--r--daemon/mxml/mxml-private.h50
-rw-r--r--daemon/mxml/mxml-search.c287
-rw-r--r--daemon/mxml/mxml-set.c349
-rw-r--r--daemon/mxml/mxml-string.c476
-rw-r--r--daemon/mxml/mxml.h329
-rw-r--r--driver/Makefile1
-rw-r--r--driver/gator.h1
-rw-r--r--driver/gator_annotate.c184
-rw-r--r--driver/gator_backtrace.c6
-rw-r--r--driver/gator_cookies.c10
-rw-r--r--driver/gator_ebs.c64
-rw-r--r--driver/gator_events_armv6.c16
-rw-r--r--driver/gator_events_armv7.c15
-rw-r--r--driver/gator_events_block.c6
-rw-r--r--driver/gator_events_irq.c19
-rwxr-xr-x[-rw-r--r--]driver/gator_events_mali.c173
-rw-r--r--driver/gator_events_meminfo.c9
-rw-r--r--driver/gator_events_mmaped.c77
-rw-r--r--driver/gator_events_net.c17
-rwxr-xr-x[-rw-r--r--]driver/gator_events_perf_pmu.c16
-rw-r--r--driver/gator_events_power.c178
-rw-r--r--driver/gator_events_scorpion.c18
-rw-r--r--driver/gator_fs.c2
-rwxr-xr-x[-rw-r--r--]driver/gator_hrtimer_gator.c23
-rw-r--r--driver/gator_main.c471
-rwxr-xr-xdriver/gator_marshaling.c239
-rw-r--r--driver/gator_pack.c98
-rw-r--r--driver/gator_trace_gpu.c164
-rwxr-xr-xdriver/gator_trace_power.c160
-rw-r--r--driver/gator_trace_sched.c182
86 files changed, 10508 insertions, 2472 deletions
diff --git a/daemon/Android.mk b/daemon/Android.mk
index 14aeda2..715e5b6 100644..100755
--- a/daemon/Android.mk
+++ b/daemon/Android.mk
@@ -3,7 +3,7 @@ include $(CLEAR_VARS)
3 3
4$(shell cd $(LOCAL_PATH);cat events_header.xml events-*\.xml events_footer.xml > events.xml;xxd -i events.xml > events_xml.h;xxd -i configuration.xml > configuration_xml.h) 4$(shell cd $(LOCAL_PATH);cat events_header.xml events-*\.xml events_footer.xml > events.xml;xxd -i events.xml > events_xml.h;xxd -i configuration.xml > configuration_xml.h)
5 5
6LOCAL_CFLAGS += -Wall -O3 -ftree-vectorize 6LOCAL_CFLAGS += -Wall -O3 -ftree-vectorize -Wno-error=sequence-point
7 7
8LOCAL_SRC_FILES:= \ 8LOCAL_SRC_FILES:= \
9 CapturedXML.cpp \ 9 CapturedXML.cpp \
@@ -16,13 +16,20 @@ LOCAL_SRC_FILES:= \
16 main.cpp \ 16 main.cpp \
17 OlySocket.cpp \ 17 OlySocket.cpp \
18 OlyUtility.cpp \ 18 OlyUtility.cpp \
19 RequestXML.cpp \
20 Sender.cpp \ 19 Sender.cpp \
21 SessionData.cpp \ 20 SessionData.cpp \
22 SessionXML.cpp \ 21 SessionXML.cpp \
23 StreamlineSetup.cpp \ 22 StreamlineSetup.cpp \
24 XMLOut.cpp \ 23 mxml/mxml-attr.c \
25 XMLReader.cpp 24 mxml/mxml-entity.c \
25 mxml/mxml-file.c \
26 mxml/mxml-get.c \
27 mxml/mxml-index.c \
28 mxml/mxml-node.c \
29 mxml/mxml-private.c \
30 mxml/mxml-search.c \
31 mxml/mxml-set.c \
32 mxml/mxml-string.c
26 33
27LOCAL_C_INCLUDES := $(LOCAL_PATH) 34LOCAL_C_INCLUDES := $(LOCAL_PATH)
28 35
diff --git a/daemon/CapturedXML.cpp b/daemon/CapturedXML.cpp
index 51076dd..f02ed2a 100644
--- a/daemon/CapturedXML.cpp
+++ b/daemon/CapturedXML.cpp
@@ -22,13 +22,15 @@ CapturedXML::CapturedXML() {
22CapturedXML::~CapturedXML() { 22CapturedXML::~CapturedXML() {
23} 23}
24 24
25const char* CapturedXML::getXML() { 25mxml_node_t* CapturedXML::getTree() {
26 bool perfCounters = false; 26 bool perfCounters = false;
27 mxml_node_t *xml;
28 mxml_node_t *captured;
29 mxml_node_t *target;
30 mxml_node_t *counters;
31 mxml_node_t *counter;
27 int x; 32 int x;
28 33
29 clearXmlString();
30 xmlHeader();
31
32 for (x=0; x<MAX_PERFORMANCE_COUNTERS; x++) { 34 for (x=0; x<MAX_PERFORMANCE_COUNTERS; x++) {
33 if (gSessionData->mPerfCounterEnabled[x]) { 35 if (gSessionData->mPerfCounterEnabled[x]) {
34 perfCounters = true; 36 perfCounters = true;
@@ -36,62 +38,86 @@ const char* CapturedXML::getXML() {
36 } 38 }
37 } 39 }
38 40
39 startElement("captured"); 41 xml = mxmlNewXML("1.0");
40 attributeInt("version", 1); 42
41 attributeInt("protocol", PROTOCOL_VERSION); 43 captured = mxmlNewElement(xml, "captured");
44 mxmlElementSetAttr(captured, "version", "1");
45 mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION);
42 if (gSessionData->mBytes > 0) { // Send the following only after the capture is complete 46 if (gSessionData->mBytes > 0) { // Send the following only after the capture is complete
43 if (time(NULL) > 1267000000) { // If the time is reasonable (after Feb 23, 2010) 47 if (time(NULL) > 1267000000) { // If the time is reasonable (after Feb 23, 2010)
44 attributeUInt("created", time(NULL)); // Valid until the year 2038 48 mxmlElementSetAttrf(captured, "created", "%lu", time(NULL)); // Valid until the year 2038
45 } 49 }
46 attributeUInt("bytes", gSessionData->mBytes); 50 mxmlElementSetAttrf(captured, "bytes", "%d", gSessionData->mBytes);
47 } 51 }
48 startElement("target"); 52
49 attributeString("name", gSessionData->mCoreName); 53 target = mxmlNewElement(captured, "target");
50 attributeInt("sample_rate", gSessionData->mSampleRate); 54 mxmlElementSetAttr(target, "name", gSessionData->mCoreName);
51 attributeInt("cores", gSessionData->mCores); 55 mxmlElementSetAttrf(target, "sample_rate", "%d", gSessionData->mSampleRate);
52 endElement("target"); 56 mxmlElementSetAttrf(target, "cores", "%d", gSessionData->mCores);
57
53 if (perfCounters) { 58 if (perfCounters) {
54 startElement("counters"); 59 counters = mxmlNewElement(captured, "counters");
55 for (x = 0; x < MAX_PERFORMANCE_COUNTERS; x++) { 60 for (x = 0; x < MAX_PERFORMANCE_COUNTERS; x++) {
56 if (gSessionData->mPerfCounterEnabled[x]) { 61 if (gSessionData->mPerfCounterEnabled[x]) {
57 startElement("counter"); 62 counter = mxmlNewElement(counters, "counter");
58 attributeString("title", gSessionData->mPerfCounterTitle[x]); 63 mxmlElementSetAttr(counter, "title", gSessionData->mPerfCounterTitle[x]);
59 attributeString("name", gSessionData->mPerfCounterName[x]); 64 mxmlElementSetAttr(counter, "name", gSessionData->mPerfCounterName[x]);
60 attributeHex8("color", gSessionData->mPerfCounterColor[x]); 65 mxmlElementSetAttrf(counter, "color", "0x%08x", gSessionData->mPerfCounterColor[x]);
61 attributeHex8("key", gSessionData->mPerfCounterKey[x]); 66 mxmlElementSetAttrf(counter, "key", "0x%08x", gSessionData->mPerfCounterKey[x]);
62 attributeString("type", gSessionData->mPerfCounterType[x]); 67 mxmlElementSetAttr(counter, "type", gSessionData->mPerfCounterType[x]);
63 attributeHex8("event", gSessionData->mPerfCounterEvent[x]); 68 mxmlElementSetAttrf(counter, "event", "0x%08x", gSessionData->mPerfCounterEvent[x]);
64 if (gSessionData->mPerfCounterPerCPU[x]) { 69 if (gSessionData->mPerfCounterPerCPU[x]) {
65 attributeBool("per_cpu", true); 70 mxmlElementSetAttr(counter, "per_cpu", "yes");
66 } 71 }
67 if (strlen(gSessionData->mPerfCounterOperation[x]) > 0) { 72 if (strlen(gSessionData->mPerfCounterOperation[x]) > 0) {
68 attributeString("operation", gSessionData->mPerfCounterOperation[x]); 73 mxmlElementSetAttr(counter, "operation", gSessionData->mPerfCounterOperation[x]);
69 } 74 }
70 if (gSessionData->mPerfCounterCount[x] > 0) { 75 if (gSessionData->mPerfCounterCount[x] > 0) {
71 attributeInt("count", gSessionData->mPerfCounterCount[x]); 76 mxmlElementSetAttrf(counter, "count", "%d", gSessionData->mPerfCounterCount[x]);
77 }
78 if (gSessionData->mPerfCounterLevel[x]) {
79 mxmlElementSetAttr(counter, "level", "yes");
80 }
81 if (strlen(gSessionData->mPerfCounterAlias[x]) > 0) {
82 mxmlElementSetAttr(counter, "alias", gSessionData->mPerfCounterAlias[x]);
72 } 83 }
73 attributeString("description", gSessionData->mPerfCounterDescription[x]); 84 if (strlen(gSessionData->mPerfCounterDisplay[x]) > 0) {
74 endElement("counter"); 85 mxmlElementSetAttr(counter, "display", gSessionData->mPerfCounterDisplay[x]);
86 }
87 if (strlen(gSessionData->mPerfCounterUnits[x]) > 0) {
88 mxmlElementSetAttr(counter, "units", gSessionData->mPerfCounterUnits[x]);
89 }
90 if (gSessionData->mPerfCounterAverageSelection[x]) {
91 mxmlElementSetAttr(counter, "average_selection", "yes");
92 }
93 mxmlElementSetAttr(counter, "description", gSessionData->mPerfCounterDescription[x]);
75 } 94 }
76 } 95 }
77 endElement("counters");
78 } 96 }
79 endElement("captured"); 97
80 return getXmlString(); 98 return xml;
99}
100
101char* CapturedXML::getXML() {
102 char* xml_string;
103 mxml_node_t *xml = getTree();
104 xml_string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
105 mxmlDelete(xml);
106 return xml_string;
81} 107}
82 108
83void CapturedXML::write(char* path) { 109void CapturedXML::write(char* path) {
84 char* file = (char*)malloc(PATH_MAX); 110 char *file = (char*)malloc(PATH_MAX);
85 111
86 // Set full path 112 // Set full path
87 snprintf(file, PATH_MAX, "%s/captured.xml", path); 113 snprintf(file, PATH_MAX, "%s/captured.xml", path);
88 114
89 // Write the file 115 char* xml = getXML();
90 const char* xml = getXML();
91 if (util->writeToDisk(file, xml) < 0) { 116 if (util->writeToDisk(file, xml) < 0) {
92 logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); 117 logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
93 handleException(); 118 handleException();
94 } 119 }
95 120
121 free(xml);
96 free(file); 122 free(file);
97} 123}
diff --git a/daemon/CapturedXML.h b/daemon/CapturedXML.h
index d37c59e..984d1f2 100644
--- a/daemon/CapturedXML.h
+++ b/daemon/CapturedXML.h
@@ -10,14 +10,16 @@
10#ifndef __CAPTURED_XML_H__ 10#ifndef __CAPTURED_XML_H__
11#define __CAPTURED_XML_H__ 11#define __CAPTURED_XML_H__
12 12
13#include "XMLOut.h" 13#include "mxml/mxml.h"
14 14
15class CapturedXML : XMLOut { 15class CapturedXML {
16public: 16public:
17 CapturedXML(); 17 CapturedXML();
18 ~CapturedXML(); 18 ~CapturedXML();
19 const char* getXML(); 19 char* getXML(); // the string should be freed by the caller
20 void write(char* path); 20 void write(char* path);
21private:
22 mxml_node_t* getTree();
21}; 23};
22 24
23#endif //__CAPTURED_XML_H__ 25#endif //__CAPTURED_XML_H__
diff --git a/daemon/Child.cpp b/daemon/Child.cpp
index ddf105b..bcc868a 100644
--- a/daemon/Child.cpp
+++ b/daemon/Child.cpp
@@ -134,6 +134,7 @@ void* stopThread(void* pVoid) {
134void* senderThread(void* pVoid) { 134void* senderThread(void* pVoid) {
135 int length; 135 int length;
136 char* data; 136 char* data;
137 char end_sequence[] = {RESPONSE_APC_DATA, 0, 0, 0, 0};
137 138
138 sem_post(&senderThreadStarted); 139 sem_post(&senderThreadStarted);
139 prctl(PR_SET_NAME, (unsigned int)&"gatord-sender", 0, 0, 0); 140 prctl(PR_SET_NAME, (unsigned int)&"gatord-sender", 0, 0, 0);
@@ -143,20 +144,25 @@ void* senderThread(void* pVoid) {
143 data = collectorFifo->read(&length); 144 data = collectorFifo->read(&length);
144 sender->writeData(data, length, RESPONSE_APC_DATA); 145 sender->writeData(data, length, RESPONSE_APC_DATA);
145 } while (length > 0); 146 } while (length > 0);
147
148 // write end-of-capture sequence
149 if (!gSessionData->mLocalCapture) {
150 sender->writeData(end_sequence, sizeof(end_sequence), RESPONSE_APC_DATA);
151 }
152
146 logg->logMessage("Exit sender thread"); 153 logg->logMessage("Exit sender thread");
147 return 0; 154 return 0;
148} 155}
149 156
150Child::Child(char* path) { 157Child::Child() {
151 initialization(); 158 initialization();
152 sessionXMLPath = path;
153 gSessionData->mLocalCapture = true; 159 gSessionData->mLocalCapture = true;
154} 160}
155 161
156Child::Child(OlySocket* sock, int conn) { 162Child::Child(OlySocket* sock, int conn) {
157 initialization(); 163 initialization();
158 socket = sock; 164 socket = sock;
159 numConnections = conn; 165 mNumConnections = conn;
160} 166}
161 167
162Child::~Child() { 168Child::~Child() {
@@ -171,8 +177,7 @@ void Child::initialization() {
171 signal(SIGALRM, child_handler); 177 signal(SIGALRM, child_handler);
172 socket = NULL; 178 socket = NULL;
173 numExceptions = 0; 179 numExceptions = 0;
174 numConnections = 0; 180 mNumConnections = 0;
175 sessionXMLPath = 0;
176 181
177 // Initialize semaphores 182 // Initialize semaphores
178 sem_init(&senderThreadStarted, 0, 0); 183 sem_init(&senderThreadStarted, 0, 0);
@@ -189,13 +194,17 @@ void Child::run() {
189 char* collectBuffer; 194 char* collectBuffer;
190 int bytesCollected = 0; 195 int bytesCollected = 0;
191 LocalCapture* localCapture = NULL; 196 LocalCapture* localCapture = NULL;
197 pthread_t durationThreadID, stopThreadID, senderThreadID;
192 198
193 prctl(PR_SET_NAME, (unsigned int)&"gatord-child", 0, 0, 0); 199 prctl(PR_SET_NAME, (unsigned int)&"gatord-child", 0, 0, 0);
194 200
201 // Disable line wrapping when generating xml files; carriage returns and indentation to be added manually
202 mxmlSetWrapMargin(0);
203
195 // Instantiate the Sender - must be done first, after which error messages can be sent 204 // Instantiate the Sender - must be done first, after which error messages can be sent
196 sender = new Sender(socket); 205 sender = new Sender(socket);
197 206
198 if (numConnections > 1) { 207 if (mNumConnections > 1) {
199 logg->logError(__FILE__, __LINE__, "Session already in progress"); 208 logg->logError(__FILE__, __LINE__, "Session already in progress");
200 handleException(); 209 handleException();
201 } 210 }
@@ -211,29 +220,27 @@ void Child::run() {
211 // Respond to Streamline requests 220 // Respond to Streamline requests
212 StreamlineSetup ss(socket); 221 StreamlineSetup ss(socket);
213 } else { 222 } else {
214 xmlString = util->readFromDisk(sessionXMLPath); 223 char* xmlString;
224 xmlString = util->readFromDisk(gSessionData->mSessionXMLPath);
215 if (xmlString == 0) { 225 if (xmlString == 0) {
216 logg->logError(__FILE__, __LINE__, "Unable to read session xml file: %s", sessionXMLPath); 226 logg->logError(__FILE__, __LINE__, "Unable to read session xml file: %s", gSessionData->mSessionXMLPath);
217 handleException(); 227 handleException();
218 } 228 }
219 gSessionData->parseSessionXML(xmlString); 229 gSessionData->parseSessionXML(xmlString);
220 localCapture = new LocalCapture(); 230 localCapture = new LocalCapture();
221 localCapture->createAPCDirectory(gSessionData->target_path, gSessionData->title); 231 localCapture->createAPCDirectory(gSessionData->mTargetPath, gSessionData->mTitle);
222 localCapture->copyImages(gSessionData->images); 232 localCapture->copyImages(gSessionData->mImages);
223 localCapture->write(xmlString); 233 localCapture->write(xmlString);
224 sender->createDataFile(gSessionData->apcDir); 234 sender->createDataFile(gSessionData->mAPCDir);
225 delete xmlString; 235 free(xmlString);
226 } 236 }
227 237
228 // Write configuration into the driver 238 // Write configuration into the driver
229 collector->setupPerfCounters(); 239 collector->setupPerfCounters();
230 240
231 // Create user-space buffers 241 // Create user-space buffers, add 5 to the size to account for the 1-byte type and 4-byte length
232 int fifoBufferSize = collector->getBufferSize(); 242 logg->logMessage("Created %d MB collector buffer with a %d-byte ragged end", gSessionData->mTotalBufferSize, collector->getBufferSize());
233 int numCollectorBuffers = (gSessionData->mTotalBufferSize * 1024 * 1024 + fifoBufferSize - 1) / fifoBufferSize; 243 collectorFifo = new Fifo(collector->getBufferSize() + 5, gSessionData->mTotalBufferSize* 1024 * 1024);
234 numCollectorBuffers = (numCollectorBuffers < 4) ? 4 : numCollectorBuffers;
235 logg->logMessage("Created %d %d-byte collector buffers", numCollectorBuffers, fifoBufferSize);
236 collectorFifo = new Fifo(numCollectorBuffers, fifoBufferSize);
237 244
238 // Get the initial pointer to the collect buffer 245 // Get the initial pointer to the collect buffer
239 collectBuffer = collectorFifo->start(); 246 collectBuffer = collectorFifo->start();
@@ -243,12 +250,14 @@ void Child::run() {
243 250
244 // Create the duration, stop, and sender threads 251 // Create the duration, stop, and sender threads
245 bool thread_creation_success = true; 252 bool thread_creation_success = true;
246 if (gSessionData->mDuration > 0 && pthread_create(&durationThreadID, NULL, durationThread, NULL)) 253 if (gSessionData->mDuration > 0 && pthread_create(&durationThreadID, NULL, durationThread, NULL)) {
247 thread_creation_success = false; 254 thread_creation_success = false;
248 else if (socket && pthread_create(&stopThreadID, NULL, stopThread, NULL)) 255 } else if (socket && pthread_create(&stopThreadID, NULL, stopThread, NULL)) {
249 thread_creation_success = false; 256 thread_creation_success = false;
250 else if (pthread_create(&senderThreadID, NULL, senderThread, NULL)) 257 } else if (pthread_create(&senderThreadID, NULL, senderThread, NULL)){
251 thread_creation_success = false; 258 thread_creation_success = false;
259 }
260
252 if (!thread_creation_success) { 261 if (!thread_creation_success) {
253 logg->logError(__FILE__, __LINE__, "Failed to create gator threads"); 262 logg->logError(__FILE__, __LINE__, "Failed to create gator threads");
254 handleException(); 263 handleException();
@@ -269,8 +278,7 @@ void Child::run() {
269 278
270 // In one shot mode, stop collection once all the buffers are filled 279 // In one shot mode, stop collection once all the buffers are filled
271 if (gSessionData->mOneShot && gSessionData->mSessionIsActive) { 280 if (gSessionData->mOneShot && gSessionData->mSessionIsActive) {
272 // Depth minus 1 because write() has not yet been called 281 if (bytesCollected == -1 || collectorFifo->willFill(bytesCollected)) {
273 if ((bytesCollected == -1) || (collectorFifo->numWriteToReadBuffersFilled() == collectorFifo->depth() - 1)) {
274 logg->logMessage("One shot"); 282 logg->logMessage("One shot");
275 endSession(); 283 endSession();
276 } 284 }
@@ -292,7 +300,7 @@ void Child::run() {
292 // Write the captured xml file 300 // Write the captured xml file
293 if (gSessionData->mLocalCapture) { 301 if (gSessionData->mLocalCapture) {
294 CapturedXML capturedXML; 302 CapturedXML capturedXML;
295 capturedXML.write(gSessionData->apcDir); 303 capturedXML.write(gSessionData->mAPCDir);
296 } 304 }
297 305
298 logg->logMessage("Profiling ended."); 306 logg->logMessage("Profiling ended.");
diff --git a/daemon/Child.h b/daemon/Child.h
index eee5ac7..612ca7c 100644
--- a/daemon/Child.h
+++ b/daemon/Child.h
@@ -15,7 +15,7 @@
15 15
16class Child { 16class Child {
17public: 17public:
18 Child(char* sessionXMLPath); 18 Child();
19 Child(OlySocket* sock, int numConnections); 19 Child(OlySocket* sock, int numConnections);
20 ~Child(); 20 ~Child();
21 void run(); 21 void run();
@@ -23,11 +23,7 @@ public:
23 void endSession(); 23 void endSession();
24 int numExceptions; 24 int numExceptions;
25private: 25private:
26 char* xmlString; 26 int mNumConnections;
27 char* sessionXMLPath;
28 int numConnections;
29 time_t timeStart;
30 pthread_t durationThreadID, stopThreadID, senderThreadID;
31 27
32 void initialization(); 28 void initialization();
33}; 29};
diff --git a/daemon/Collector.cpp b/daemon/Collector.cpp
index 7a41198..db7b9c0 100644
--- a/daemon/Collector.cpp
+++ b/daemon/Collector.cpp
@@ -16,31 +16,32 @@
16#include "Collector.h" 16#include "Collector.h"
17#include "SessionData.h" 17#include "SessionData.h"
18#include "Logging.h" 18#include "Logging.h"
19#include "Sender.h"
19 20
20extern void handleException(); 21extern void handleException();
21 22
22// Driver initialization independent of session settings 23// Driver initialization independent of session settings
23Collector::Collector() { 24Collector::Collector() {
24 char text[sizeof(gSessionData->mPerfCounterType[0]) + 20]; // sufficiently large to hold all events/<types>/<file> 25 char text[sizeof(gSessionData->mPerfCounterType[0]) + 30]; // sufficiently large to hold all /dev/gator/events/<types>/<file>
25 26
26 bufferFD = 0; 27 mBufferFD = 0;
27 28
28 checkVersion(); 29 checkVersion();
29 30
30 int enable = -1; 31 int enable = -1;
31 if (readIntDriver("enable", &enable) != 0 || enable != 0) { 32 if (readIntDriver("/dev/gator/enable", &enable) != 0 || enable != 0) {
32 logg->logError(__FILE__, __LINE__, "Driver already enabled, possibly a session is already in progress."); 33 logg->logError(__FILE__, __LINE__, "Driver already enabled, possibly a session is already in progress.");
33 handleException(); 34 handleException();
34 } 35 }
35 36
36 readIntDriver("cpu_cores", &gSessionData->mCores); 37 readIntDriver("/dev/gator/cpu_cores", &gSessionData->mCores);
37 if (gSessionData->mCores == 0) { 38 if (gSessionData->mCores == 0) {
38 gSessionData->mCores = 1; 39 gSessionData->mCores = 1;
39 } 40 }
40 41
41 bufferSize = 512 * 1024; 42 mBufferSize = 0;
42 if (writeReadDriver("buffer_size", &bufferSize) || bufferSize <= 0) { 43 if (readIntDriver("/dev/gator/buffer_size", &mBufferSize) || mBufferSize <= 0) {
43 logg->logError(__FILE__, __LINE__, "Unable to set the driver buffer size"); 44 logg->logError(__FILE__, __LINE__, "Unable to read the driver buffer size");
44 handleException(); 45 handleException();
45 } 46 }
46 47
@@ -51,7 +52,7 @@ Collector::Collector() {
51 // Read unchanging keys from driver which are created at insmod'ing of gator.ko 52 // Read unchanging keys from driver which are created at insmod'ing of gator.ko
52 for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) { 53 for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
53 if (gSessionData->mPerfCounterEnabled[i]) { 54 if (gSessionData->mPerfCounterEnabled[i]) {
54 snprintf(text, sizeof(text), "events/%s/key", gSessionData->mPerfCounterType[i]); 55 snprintf(text, sizeof(text), "/dev/gator/events/%s/key", gSessionData->mPerfCounterType[i]);
55 readIntDriver(text, &gSessionData->mPerfCounterKey[i]); 56 readIntDriver(text, &gSessionData->mPerfCounterKey[i]);
56 } 57 }
57 } 58 }
@@ -59,21 +60,37 @@ Collector::Collector() {
59 60
60Collector::~Collector() { 61Collector::~Collector() {
61 // Write zero for safety, as a zero should have already been written 62 // Write zero for safety, as a zero should have already been written
62 writeDriver("enable", "0"); 63 writeDriver("/dev/gator/enable", "0");
63 64
64 // Calls event_buffer_release in the driver 65 // Calls event_buffer_release in the driver
65 if (bufferFD) { 66 if (mBufferFD) {
66 close(bufferFD); 67 close(mBufferFD);
67 } 68 }
68} 69}
69 70
71#include <dirent.h>
70void Collector::enablePerfCounters() { 72void Collector::enablePerfCounters() {
71 char text[sizeof(gSessionData->mPerfCounterType[0]) + 30]; // sufficiently large to hold all /dev/gator/events/<types>/enabled 73 char text[sizeof(gSessionData->mPerfCounterType[0]) + 30]; // sufficiently large to hold all /dev/gator/events/<types>/enabled
74
75 // Initialize all perf counters in the driver, i.e. set enabled to zero
76 struct dirent *ent;
77 DIR* dir = opendir("/dev/gator/events");
78 if (dir) {
79 while ((ent = readdir(dir)) != NULL) {
80 // skip hidden files, current dir, and parent dir
81 if (ent->d_name[0] == '.')
82 continue;
83 snprintf(text, sizeof(text), "/dev/gator/events/%s/enabled", ent->d_name);
84 writeDriver(text, 0);
85 }
86 closedir (dir);
87 }
88
72 for (int i=0; i<MAX_PERFORMANCE_COUNTERS; i++) { 89 for (int i=0; i<MAX_PERFORMANCE_COUNTERS; i++) {
73 if (!gSessionData->mPerfCounterEnabled[i]) { 90 if (!gSessionData->mPerfCounterEnabled[i]) {
74 continue; 91 continue;
75 } 92 }
76 snprintf(text, sizeof(text), "events/%s/enabled", gSessionData->mPerfCounterType[i]); 93 snprintf(text, sizeof(text), "/dev/gator/events/%s/enabled", gSessionData->mPerfCounterType[i]);
77 if (writeReadDriver(text, &gSessionData->mPerfCounterEnabled[i])) { 94 if (writeReadDriver(text, &gSessionData->mPerfCounterEnabled[i])) {
78 // Disable those events that don't exist on this hardware platform even though they exist in configuration.xml 95 // Disable those events that don't exist on this hardware platform even though they exist in configuration.xml
79 gSessionData->mPerfCounterEnabled[i] = 0; 96 gSessionData->mPerfCounterEnabled[i] = 0;
@@ -83,21 +100,21 @@ void Collector::enablePerfCounters() {
83} 100}
84 101
85void Collector::setupPerfCounters() { 102void Collector::setupPerfCounters() {
86 char base[sizeof(gSessionData->mPerfCounterType[0]) + 10]; // sufficiently large to hold all events/<types> 103 char base[sizeof(gSessionData->mPerfCounterType[0]) + 20]; // sufficiently large to hold all /dev/gator/events/<types>
87 char text[sizeof(gSessionData->mPerfCounterType[0]) + 20]; // sufficiently large to hold all events/<types>/<file> 104 char text[sizeof(gSessionData->mPerfCounterType[0]) + 30]; // sufficiently large to hold all /dev/gator/events/<types>/<file>
88 105
89 for (int i=0; i<MAX_PERFORMANCE_COUNTERS; i++) { 106 for (int i=0; i<MAX_PERFORMANCE_COUNTERS; i++) {
90 if (!gSessionData->mPerfCounterEnabled[i]) { 107 if (!gSessionData->mPerfCounterEnabled[i]) {
91 continue; 108 continue;
92 } 109 }
93 snprintf(base, sizeof(base), "events/%s", gSessionData->mPerfCounterType[i]); 110 snprintf(base, sizeof(base), "/dev/gator/events/%s", gSessionData->mPerfCounterType[i]);
94 snprintf(text, sizeof(text), "%s/event", base); 111 snprintf(text, sizeof(text), "%s/event", base);
95 writeDriver(text, gSessionData->mPerfCounterEvent[i]); 112 writeDriver(text, gSessionData->mPerfCounterEvent[i]);
96 if (gSessionData->mPerfCounterEBSCapable[i]) { 113 if (gSessionData->mPerfCounterEBSCapable[i]) {
97 snprintf(text, sizeof(text), "%s/count", base); 114 snprintf(text, sizeof(text), "%s/count", base);
98 if (access(resolvePath(text), F_OK) == 0) { 115 if (access(text, F_OK) == 0) {
99 if (writeReadDriver(text, &gSessionData->mPerfCounterCount[i]) && gSessionData->mPerfCounterCount[i] > 0) { 116 if (writeReadDriver(text, &gSessionData->mPerfCounterCount[i]) && gSessionData->mPerfCounterCount[i] > 0) {
100 logg->logError(__FILE__, __LINE__, "Cannot enable EBS for %s with a count of %d\n", gSessionData->mPerfCounterName[i], gSessionData->mPerfCounterCount[i]); 117 logg->logError(__FILE__, __LINE__, "Cannot enable EBS for %s:%s with a count of %d\n", gSessionData->mPerfCounterTitle[i], gSessionData->mPerfCounterName[i], gSessionData->mPerfCounterCount[i]);
101 handleException(); 118 handleException();
102 } 119 }
103 } else if (gSessionData->mPerfCounterCount[i] > 0) { 120 } else if (gSessionData->mPerfCounterCount[i] > 0) {
@@ -111,7 +128,7 @@ void Collector::setupPerfCounters() {
111void Collector::checkVersion() { 128void Collector::checkVersion() {
112 int driver_version = 0; 129 int driver_version = 0;
113 130
114 if (readIntDriver("version", &driver_version) == -1) { 131 if (readIntDriver("/dev/gator/version", &driver_version) == -1) {
115 logg->logError(__FILE__, __LINE__, "Error reading gator driver version"); 132 logg->logError(__FILE__, __LINE__, "Error reading gator driver version");
116 handleException(); 133 handleException();
117 } 134 }
@@ -139,61 +156,61 @@ void Collector::checkVersion() {
139 156
140void Collector::start() { 157void Collector::start() {
141 // Set the maximum backtrace depth 158 // Set the maximum backtrace depth
142 if (writeReadDriver("backtrace_depth", &gSessionData->mBacktraceDepth)) { 159 if (writeReadDriver("/dev/gator/backtrace_depth", &gSessionData->mBacktraceDepth)) {
143 logg->logError(__FILE__, __LINE__, "Unable to set the driver backtrace depth"); 160 logg->logError(__FILE__, __LINE__, "Unable to set the driver backtrace depth");
144 handleException(); 161 handleException();
145 } 162 }
146 163
147 // open the buffer which calls userspace_buffer_open() in the driver 164 // open the buffer which calls userspace_buffer_open() in the driver
148 bufferFD = open(resolvePath("buffer"), O_RDONLY); 165 mBufferFD = open("/dev/gator/buffer", O_RDONLY);
149 if (bufferFD < 0) { 166 if (mBufferFD < 0) {
150 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."); 167 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.");
151 handleException(); 168 handleException();
152 } 169 }
153 170
154 // set the tick rate of the profiling timer 171 // set the tick rate of the profiling timer
155 if (writeReadDriver("tick", &gSessionData->mSampleRate) != 0) { 172 if (writeReadDriver("/dev/gator/tick", &gSessionData->mSampleRate) != 0) {
156 logg->logError(__FILE__, __LINE__, "Unable to set the driver tick"); 173 logg->logError(__FILE__, __LINE__, "Unable to set the driver tick");
157 handleException(); 174 handleException();
158 } 175 }
159 176
160 // notify the kernel of the streaming mode, currently used for network stats 177 // notify the kernel of the response type
161 int streaming = (int)!gSessionData->mOneShot; 178 int response_type = gSessionData->mLocalCapture ? 0 : RESPONSE_APC_DATA;
162 if (writeReadDriver("streaming", &streaming) != 0) { 179 if (writeDriver("/dev/gator/response_type", response_type)) {
163 logg->logError(__FILE__, __LINE__, "Unable to set streaming"); 180 logg->logError(__FILE__, __LINE__, "Unable to write the response type");
164 handleException(); 181 handleException();
165 } 182 }
166 183
167 logg->logMessage("Start the driver"); 184 logg->logMessage("Start the driver");
168 185
169 // This command makes the driver start profiling by calling gator_op_start() in the driver 186 // This command makes the driver start profiling by calling gator_op_start() in the driver
170 if (writeDriver("enable", "1") != 0) { 187 if (writeDriver("/dev/gator/enable", "1") != 0) {
171 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."); 188 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.");
172 handleException(); 189 handleException();
173 } 190 }
174 191
175 lseek(bufferFD, 0, SEEK_SET); 192 lseek(mBufferFD, 0, SEEK_SET);
176} 193}
177 194
178// These commands should cause the read() function in collect() to return 195// These commands should cause the read() function in collect() to return
179void Collector::stop() { 196void Collector::stop() {
180 // This will stop the driver from profiling 197 // This will stop the driver from profiling
181 if (writeDriver("enable", "0") != 0) { 198 if (writeDriver("/dev/gator/enable", "0") != 0) {
182 logg->logMessage("Stopping kernel failed"); 199 logg->logMessage("Stopping kernel failed");
183 } 200 }
184} 201}
185 202
186int Collector::collect(char* buffer) { 203int Collector::collect(char* buffer) {
187 // Calls event_buffer_read in the driver 204 // Calls event_buffer_read in the driver
188 int bytesRead = read(bufferFD, buffer, bufferSize); 205 int bytesRead = read(mBufferFD, buffer, mBufferSize);
189 206
190 // If read() returned due to an interrupt signal, re-read to obtain the last bit of collected data 207 // If read() returned due to an interrupt signal, re-read to obtain the last bit of collected data
191 if (bytesRead == -1 && errno == EINTR) { 208 if (bytesRead == -1 && errno == EINTR) {
192 bytesRead = read(bufferFD, buffer, bufferSize); 209 bytesRead = read(mBufferFD, buffer, mBufferSize);
193 } 210 }
194 211
212 // return the total bytes written
195 logg->logMessage("Driver read of %d bytes", bytesRead); 213 logg->logMessage("Driver read of %d bytes", bytesRead);
196
197 return bytesRead; 214 return bytesRead;
198} 215}
199 216
@@ -209,8 +226,9 @@ void Collector::getCoreName() {
209 } 226 }
210 227
211 while (fgets(temp, sizeof(temp), f)) { 228 while (fgets(temp, sizeof(temp), f)) {
212 if (strlen(temp) > 0) 229 if (strlen(temp) > 0) {
213 temp[strlen(temp) - 1] = 0; // Replace the line feed with a null 230 temp[strlen(temp) - 1] = 0; // Replace the line feed with a null
231 }
214 232
215 if (strstr(temp, "Hardware") != 0) { 233 if (strstr(temp, "Hardware") != 0) {
216 char* position = strchr(temp, ':'); 234 char* position = strchr(temp, ':');
@@ -219,7 +237,7 @@ void Collector::getCoreName() {
219 "The core name in the captured xml file will be 'unknown'."); 237 "The core name in the captured xml file will be 'unknown'.");
220 return; 238 return;
221 } 239 }
222 strncpy(gSessionData->mCoreName, (char *)((int)position + 2), sizeof(gSessionData->mCoreName)); 240 strncpy(gSessionData->mCoreName, (char*)((int)position + 2), sizeof(gSessionData->mCoreName));
223 gSessionData->mCoreName[sizeof(gSessionData->mCoreName) - 1] = 0; // strncpy does not guarantee a null-terminated string 241 gSessionData->mCoreName[sizeof(gSessionData->mCoreName) - 1] = 0; // strncpy does not guarantee a null-terminated string
224 fclose(f); 242 fclose(f);
225 return; 243 return;
@@ -231,14 +249,7 @@ void Collector::getCoreName() {
231 fclose(f); 249 fclose(f);
232} 250}
233 251
234char* Collector::resolvePath(const char* file) { 252int Collector::readIntDriver(const char* fullpath, int* value) {
235 static char fullpath[100]; // Sufficiently large to hold any path within /dev/gator
236 snprintf(fullpath, sizeof(fullpath), "/dev/gator/%s", file);
237 return fullpath;
238}
239
240int Collector::readIntDriver(const char* path, int* value) {
241 char* fullpath = resolvePath(path);
242 FILE* file = fopen(fullpath, "r"); 253 FILE* file = fopen(fullpath, "r");
243 if (file == NULL) { 254 if (file == NULL) {
244 return -1; 255 return -1;
@@ -258,8 +269,7 @@ int Collector::writeDriver(const char* path, int value) {
258 return writeDriver(path, data); 269 return writeDriver(path, data);
259} 270}
260 271
261int Collector::writeDriver(const char* path, const char* data) { 272int Collector::writeDriver(const char* fullpath, const char* data) {
262 char* fullpath = resolvePath(path);
263 int fd = open(fullpath, O_WRONLY); 273 int fd = open(fullpath, O_WRONLY);
264 if (fd < 0) { 274 if (fd < 0) {
265 return -1; 275 return -1;
diff --git a/daemon/Collector.h b/daemon/Collector.h
index 6c80725..5977a72 100644
--- a/daemon/Collector.h
+++ b/daemon/Collector.h
@@ -20,16 +20,14 @@ public:
20 int collect(char* buffer); 20 int collect(char* buffer);
21 void enablePerfCounters(); 21 void enablePerfCounters();
22 void setupPerfCounters(); 22 void setupPerfCounters();
23 int getBufferSize() {return bufferSize;} 23 int getBufferSize() {return mBufferSize;}
24private: 24private:
25 int bufferSize; 25 int mBufferSize;
26 int bufferFD; 26 int mBufferFD;
27 char * buffer;
28 27
29 void checkVersion(); 28 void checkVersion();
30 void getCoreName(); 29 void getCoreName();
31 30
32 char* resolvePath(const char* file);
33 int readIntDriver(const char* path, int* value); 31 int readIntDriver(const char* path, int* value);
34 int writeDriver(const char* path, int value); 32 int writeDriver(const char* path, int value);
35 int writeDriver(const char* path, const char* data); 33 int writeDriver(const char* path, const char* data);
diff --git a/daemon/ConfigurationXML.cpp b/daemon/ConfigurationXML.cpp
index e1bec0f..145ddbd 100644
--- a/daemon/ConfigurationXML.cpp
+++ b/daemon/ConfigurationXML.cpp
@@ -17,7 +17,7 @@
17extern void handleException(); 17extern void handleException();
18 18
19static const char* ATTR_COUNTER = "counter"; 19static const char* ATTR_COUNTER = "counter";
20static const char* ATTR_VERSION = "version"; 20static const char* ATTR_REVISION = "revision";
21static const char* ATTR_TITLE = "title"; 21static const char* ATTR_TITLE = "title";
22static const char* ATTR_NAME = "name"; 22static const char* ATTR_NAME = "name";
23static const char* ATTR_EVENT = "event"; 23static const char* ATTR_EVENT = "event";
@@ -27,14 +27,19 @@ static const char* ATTR_OPERATION = "operation";
27static const char* ATTR_PER_CPU = "per_cpu"; 27static const char* ATTR_PER_CPU = "per_cpu";
28static const char* ATTR_DESCRIPTION = "description"; 28static const char* ATTR_DESCRIPTION = "description";
29static const char* ATTR_EBS = "event_based_sampling"; 29static const char* ATTR_EBS = "event_based_sampling";
30static const char* ATTR_LEVEL = "level";
31static const char* ATTR_ALIAS = "alias";
32static const char* ATTR_DISPLAY = "display";
33static const char* ATTR_UNITS = "units";
34static const char* ATTR_AVERAGE_SELECTION = "average_selection";
30 35
31ConfigurationXML::ConfigurationXML() { 36ConfigurationXML::ConfigurationXML() {
32#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len 37#include "configuration_xml.h" // defines and initializes char configuration_xml[] and int configuration_xml_len
33 index = 0; 38 mIndex = 0;
34 char* path = (char *)malloc(PATH_MAX); 39 char* path = (char*)malloc(PATH_MAX);
35 40
36 if (gSessionData->configurationXMLPath) { 41 if (gSessionData->mConfigurationXMLPath) {
37 strncpy(path, gSessionData->configurationXMLPath, PATH_MAX); 42 strncpy(path, gSessionData->mConfigurationXMLPath, PATH_MAX);
38 } else { 43 } else {
39 if (util->getApplicationFullPath(path, PATH_MAX) != 0) { 44 if (util->getApplicationFullPath(path, PATH_MAX) != 0) {
40 logg->logMessage("Unable to determine the full path of gatord, the cwd will be used"); 45 logg->logMessage("Unable to determine the full path of gatord, the cwd will be used");
@@ -63,10 +68,10 @@ ConfigurationXML::ConfigurationXML() {
63 logg->logError(__FILE__, __LINE__, "Invalid configuration.xml file detected and unable to delete it. To resolve, delete configuration.xml on disk"); 68 logg->logError(__FILE__, __LINE__, "Invalid configuration.xml file detected and unable to delete it. To resolve, delete configuration.xml on disk");
64 handleException(); 69 handleException();
65 } 70 }
66 } else if (ret < 0 || isValid() == false) { 71 logg->logMessage("Invalid configuration.xml file detected and removed");
67 logg->logError(__FILE__, __LINE__, "Parsing of the configuration.xml file failed. Please verify configuration.xml on the target filesystem is valid or delete it to use the default.");
68 handleException();
69 } 72 }
73
74 validate();
70 75
71 free(path); 76 free(path);
72} 77}
@@ -78,79 +83,106 @@ ConfigurationXML::~ConfigurationXML() {
78} 83}
79 84
80int ConfigurationXML::parse(const char* configurationXML) { 85int ConfigurationXML::parse(const char* configurationXML) {
81 int ret = 0; 86 mxml_node_t *tree, *node;
82 XMLReader reader(configurationXML); 87 int ret;
83 char * tag = reader.nextTag(); 88
84 while(tag != 0 && ret == 0) { 89 tree = mxmlLoadString(NULL, configurationXML, MXML_NO_CALLBACK);
85 if (strcmp(tag, "configurations") == 0) { 90
86 ret = configurationsTag(&reader); 91 node = mxmlGetFirstChild(tree);
87 } else if (strcmp(tag, "configuration") == 0) { 92 while (node && mxmlGetType(node) != MXML_ELEMENT)
88 ret = configurationTag(&reader); 93 node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
94
95 ret = configurationsTag(node);
96
97 node = mxmlGetFirstChild(node);
98 while (node) {
99 if (mxmlGetType(node) != MXML_ELEMENT) {
100 node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
101 continue;
89 } 102 }
90 tag = reader.nextTag(); 103 configurationTag(node);
104 node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
91 } 105 }
92 106
107 mxmlDelete(tree);
108
93 return ret; 109 return ret;
94} 110}
95 111
96bool ConfigurationXML::isValid(void) { 112void ConfigurationXML::validate(void) {
97 for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) { 113 for (int i = 0; i < MAX_PERFORMANCE_COUNTERS; i++) {
98 if (gSessionData->mPerfCounterEnabled[i]) { 114 if (gSessionData->mPerfCounterEnabled[i]) {
99 if (strcmp(gSessionData->mPerfCounterType[i], "") == 0 || 115 if (strcmp(gSessionData->mPerfCounterType[i], "") == 0) {
100 strcmp(gSessionData->mPerfCounterTitle[i], "") == 0 || 116 logg->logError(__FILE__, __LINE__, "Invalid required attribute in configuration.xml:\n counter=\"%s\"\n title=\"%s\"\n name=\"%s\"\n event=%d\n", gSessionData->mPerfCounterType[i], gSessionData->mPerfCounterTitle[i], gSessionData->mPerfCounterName[i], gSessionData->mPerfCounterEvent[i]);
101 strcmp(gSessionData->mPerfCounterName[i], "") == 0) { 117 handleException();
102 logg->logMessage("Invalid required attribute\n counter=\"%s\"\n title=\"%s\"\n name=\"%s\"\n event=%d\n", gSessionData->mPerfCounterType[i], gSessionData->mPerfCounterTitle[i], gSessionData->mPerfCounterName[i], gSessionData->mPerfCounterEvent[i]);
103 return false; // failure
104 } 118 }
105 119
106 // iterate through the remaining enabled performance counters 120 // iterate through the remaining enabled performance counters
107 for (int j = i + 1; j < MAX_PERFORMANCE_COUNTERS; j++) { 121 for (int j = i + 1; j < MAX_PERFORMANCE_COUNTERS; j++) {
108 if (gSessionData->mPerfCounterEnabled[j]) { 122 if (gSessionData->mPerfCounterEnabled[j]) {
109 // check if the type or device are the same 123 // check if the types are the same
110 if (strcmp(gSessionData->mPerfCounterType[i], gSessionData->mPerfCounterType[j]) == 0) { 124 if (strcmp(gSessionData->mPerfCounterType[i], gSessionData->mPerfCounterType[j]) == 0) {
111 logg->logMessage("Duplicate performance counter type: %s", gSessionData->mPerfCounterType[i]); 125 logg->logError(__FILE__, __LINE__, "Duplicate performance counter type in configuration.xml: %s", gSessionData->mPerfCounterType[i]);
112 return false; // failure 126 handleException();
113 } 127 }
114 } 128 }
115 } 129 }
116 } 130 }
117 } 131 }
118
119 return true; // success
120} 132}
121 133
122#define CONFIGURATION_VERSION 1 134#define CONFIGURATION_REVISION 1
123int ConfigurationXML::configurationsTag(XMLReader *in) { 135int ConfigurationXML::configurationsTag(mxml_node_t *node) {
124 int version = in->getAttributeAsInteger(ATTR_VERSION, 0); 136 const char* revision_string;
125 if (version != CONFIGURATION_VERSION) { 137
126 logg->logMessage("Incompatible configuration.xml version (%d) detected. The version needs to be %d.", version, CONFIGURATION_VERSION); 138 revision_string = mxmlElementGetAttr(node, ATTR_REVISION);
127 return 1; // version issue 139 if (!revision_string) {
140 return 1; //revision issue;
141 }
142
143 int revision = strtol(revision_string, NULL, 10);
144 if (revision < CONFIGURATION_REVISION) {
145 return 1; // revision issue
128 } 146 }
147
129 return 0; 148 return 0;
130} 149}
131 150
132int ConfigurationXML::configurationTag(XMLReader* in) { 151void ConfigurationXML::configurationTag(mxml_node_t *node) {
133 // handle all other performance counters 152 // handle all other performance counters
134 if (index >= MAX_PERFORMANCE_COUNTERS) { 153 if (mIndex >= MAX_PERFORMANCE_COUNTERS) {
135 logg->logMessage("Invalid performance counter index: %d", index); 154 logg->logError(__FILE__, __LINE__, "Exceeded maximum number of %d performance counters", MAX_PERFORMANCE_COUNTERS);
136 return -1; // failure 155 handleException();
137 } 156 }
138 157
139 // read attributes 158 // read attributes
140 in->getAttribute(ATTR_COUNTER, gSessionData->mPerfCounterType[index], sizeof(gSessionData->mPerfCounterType[index]), ""); 159 if (mxmlElementGetAttr(node, ATTR_COUNTER)) strncpy(gSessionData->mPerfCounterType[mIndex], mxmlElementGetAttr(node, ATTR_COUNTER), sizeof(gSessionData->mPerfCounterType[mIndex]));
141 in->getAttribute(ATTR_TITLE, gSessionData->mPerfCounterTitle[index], sizeof(gSessionData->mPerfCounterTitle[index]), ""); 160 if (mxmlElementGetAttr(node, ATTR_TITLE)) strncpy(gSessionData->mPerfCounterTitle[mIndex], mxmlElementGetAttr(node, ATTR_TITLE), sizeof(gSessionData->mPerfCounterTitle[mIndex]));
142 in->getAttribute(ATTR_NAME, gSessionData->mPerfCounterName[index], sizeof(gSessionData->mPerfCounterName[index]), ""); 161 if (mxmlElementGetAttr(node, ATTR_NAME)) strncpy(gSessionData->mPerfCounterName[mIndex], mxmlElementGetAttr(node, ATTR_NAME), sizeof(gSessionData->mPerfCounterName[mIndex]));
143 in->getAttribute(ATTR_DESCRIPTION, gSessionData->mPerfCounterDescription[index], sizeof(gSessionData->mPerfCounterDescription[index]), ""); 162 if (mxmlElementGetAttr(node, ATTR_DESCRIPTION)) strncpy(gSessionData->mPerfCounterDescription[mIndex], mxmlElementGetAttr(node, ATTR_DESCRIPTION), sizeof(gSessionData->mPerfCounterDescription[mIndex]));
144 gSessionData->mPerfCounterEvent[index] = in->getAttributeAsInteger(ATTR_EVENT, 0); 163 if (mxmlElementGetAttr(node, ATTR_EVENT)) gSessionData->mPerfCounterEvent[mIndex] = strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16);
145 gSessionData->mPerfCounterCount[index] = in->getAttributeAsInteger(ATTR_COUNT, 0); 164 if (mxmlElementGetAttr(node, ATTR_COUNT)) gSessionData->mPerfCounterCount[mIndex] = strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10);
146 gSessionData->mPerfCounterColor[index] = in->getAttributeAsInteger(ATTR_COLOR, 0); 165 if (mxmlElementGetAttr(node, ATTR_COLOR)) gSessionData->mPerfCounterColor[mIndex] = strtol(mxmlElementGetAttr(node, ATTR_COLOR), NULL, 16);
147 gSessionData->mPerfCounterPerCPU[index] = in->getAttributeAsBoolean(ATTR_PER_CPU, false); 166 if (mxmlElementGetAttr(node, ATTR_PER_CPU)) gSessionData->mPerfCounterPerCPU[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_PER_CPU), false);
148 gSessionData->mPerfCounterEBSCapable[index] = in->getAttributeAsBoolean(ATTR_EBS, false); 167 if (mxmlElementGetAttr(node, ATTR_EBS)) gSessionData->mPerfCounterEBSCapable[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_EBS), false);
149 in->getAttribute(ATTR_OPERATION, gSessionData->mPerfCounterOperation[index], sizeof(gSessionData->mPerfCounterOperation[index]), ""); 168 if (mxmlElementGetAttr(node, ATTR_OPERATION)) strncpy(gSessionData->mPerfCounterOperation[mIndex], mxmlElementGetAttr(node, ATTR_OPERATION), sizeof(gSessionData->mPerfCounterOperation[mIndex]));
150 gSessionData->mPerfCounterEnabled[index] = true; 169 if (mxmlElementGetAttr(node, ATTR_LEVEL)) gSessionData->mPerfCounterLevel[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_LEVEL), false);
170 if (mxmlElementGetAttr(node, ATTR_ALIAS)) strncpy(gSessionData->mPerfCounterAlias[mIndex], mxmlElementGetAttr(node, ATTR_ALIAS), sizeof(gSessionData->mPerfCounterAlias[mIndex]));
171 if (mxmlElementGetAttr(node, ATTR_DISPLAY)) strncpy(gSessionData->mPerfCounterDisplay[mIndex], mxmlElementGetAttr(node, ATTR_DISPLAY), sizeof(gSessionData->mPerfCounterDisplay[mIndex]));
172 if (mxmlElementGetAttr(node, ATTR_UNITS)) strncpy(gSessionData->mPerfCounterUnits[mIndex], mxmlElementGetAttr(node, ATTR_UNITS), sizeof(gSessionData->mPerfCounterUnits[mIndex]));
173 if (mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION)) gSessionData->mPerfCounterAverageSelection[mIndex] = util->stringToBool(mxmlElementGetAttr(node, ATTR_AVERAGE_SELECTION), false);
174 gSessionData->mPerfCounterEnabled[mIndex] = true;
175
176 // strncpy does not guarantee a null-termianted string
177 gSessionData->mPerfCounterType[mIndex][sizeof(gSessionData->mPerfCounterType[mIndex]) - 1] = 0;
178 gSessionData->mPerfCounterTitle[mIndex][sizeof(gSessionData->mPerfCounterTitle[mIndex]) - 1] = 0;
179 gSessionData->mPerfCounterName[mIndex][sizeof(gSessionData->mPerfCounterName[mIndex]) - 1] = 0;
180 gSessionData->mPerfCounterDescription[mIndex][sizeof(gSessionData->mPerfCounterDescription[mIndex]) - 1] = 0;
181 gSessionData->mPerfCounterOperation[mIndex][sizeof(gSessionData->mPerfCounterOperation[mIndex]) - 1] = 0;
182 gSessionData->mPerfCounterAlias[mIndex][sizeof(gSessionData->mPerfCounterAlias[mIndex]) - 1] = 0;
183 gSessionData->mPerfCounterDisplay[mIndex][sizeof(gSessionData->mPerfCounterDisplay[mIndex]) - 1] = 0;
184 gSessionData->mPerfCounterUnits[mIndex][sizeof(gSessionData->mPerfCounterUnits[mIndex]) - 1] = 0;
151 185
152 // update counter index 186 // update counter index
153 index++; 187 mIndex++;
154
155 return 0; // success
156} 188}
diff --git a/daemon/ConfigurationXML.h b/daemon/ConfigurationXML.h
index 047c4b0..b48d32f 100644
--- a/daemon/ConfigurationXML.h
+++ b/daemon/ConfigurationXML.h
@@ -9,21 +9,21 @@
9#ifndef COUNTERS_H 9#ifndef COUNTERS_H
10#define COUNTERS_H 10#define COUNTERS_H
11 11
12#include "XMLReader.h" 12#include "mxml/mxml.h"
13 13
14class ConfigurationXML { 14class ConfigurationXML {
15public: 15public:
16 ConfigurationXML(); 16 ConfigurationXML();
17 ~ConfigurationXML(); 17 ~ConfigurationXML();
18 const char* getConfigurationXML() {return mConfigurationXML;} 18 const char* getConfigurationXML() {return mConfigurationXML;}
19 void validate(void);
19private: 20private:
20 char* mConfigurationXML; 21 char* mConfigurationXML;
22 int mIndex;
21 23
22 int parse(const char* xmlFile); 24 int parse(const char* xmlFile);
23 bool isValid(void); 25 int configurationsTag(mxml_node_t *node);
24 int configurationsTag(XMLReader *in); 26 void configurationTag(mxml_node_t *node);
25 int configurationTag(XMLReader* in);
26 int index;
27}; 27};
28 28
29#endif // COUNTERS_H 29#endif // COUNTERS_H
diff --git a/daemon/Fifo.cpp b/daemon/Fifo.cpp
index 1456183..bbfc919 100644
--- a/daemon/Fifo.cpp
+++ b/daemon/Fifo.cpp
@@ -1,103 +1,126 @@
1/** 1/**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved. 2 * Copyright (C) ARM Limited 2010-2012. 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 <stdlib.h> 9#include <stdlib.h>
10#include <string.h> 10#include <string.h>
11#include <unistd.h> 11#include <unistd.h>
12#include "Fifo.h" 12#include "Fifo.h"
13#include "Logging.h" 13#include "Logging.h"
14 14
15extern void handleException(); 15extern void handleException();
16 16
17Fifo::Fifo(int numBuffers, int bufferSize) { 17// bufferSize is the amount of data to be filled
18 int which; 18// singleBufferSize is the maximum size that may be filled during a single write
19 19// (bufferSize + singleBufferSize) will be allocated
20 if (numBuffers > FIFO_BUFFER_LIMIT) { 20Fifo::Fifo(int singleBufferSize, int bufferSize) {
21 logg->logError(__FILE__, __LINE__, "Number of fifo buffers exceeds maximum"); 21 mWrite = mRead = mReadCommit = mRaggedEnd = 0;
22 handleException(); 22 mWrapThreshold = bufferSize;
23 } 23 mSingleBufferSize = singleBufferSize;
24 mNumBuffers = numBuffers; 24 mBuffer = (char*)valloc(bufferSize + singleBufferSize);
25 mBufferSize = bufferSize; 25 mEnd = false;
26 mWriteCurrent = 0; 26
27 mReadCurrent = mNumBuffers - 1; // (n-1) pipelined 27 if (mBuffer == NULL) {
28 28 logg->logError(__FILE__, __LINE__, "failed to allocate %d bytes", bufferSize + singleBufferSize);
29 for (which=0; which<mNumBuffers; which++) { 29 handleException();
30 // initialized read-to-write sem to 1, so that first wait goes through; write-to-read init'd to 0 30 }
31 if (sem_init(&mReadToWriteSem[which], 0, 1) || 31
32 sem_init(&mWriteToReadSem[which], 0, 0)) { 32 if (sem_init(&mWaitForSpaceSem, 0, 0) || sem_init(&mWaitForDataSem, 0, 0)) {
33 logg->logError(__FILE__, __LINE__, "sem_init(%d) failed", which); 33 logg->logError(__FILE__, __LINE__, "sem_init() failed");
34 handleException(); 34 handleException();
35 } 35 }
36 // page-align allocate buffers 36}
37 mBuffer[which] = (char*)valloc(bufferSize); 37
38 if (mBuffer[which] == NULL) { 38Fifo::~Fifo() {
39 logg->logError(__FILE__, __LINE__, "failed to allocate %d bytes", bufferSize); 39 free(mBuffer);
40 handleException(); 40}
41 } 41
42 // touch each page to fault it in 42int Fifo::numBytesFilled() {
43 for (int i=0; i<bufferSize; i+= getpagesize()) { 43 return mWrite - mRead + mRaggedEnd;
44 *mBuffer[which] = 0; 44}
45 } 45
46 } 46char* Fifo::start() {
47} 47 return mBuffer;
48 48}
49Fifo::~Fifo() { 49
50 for (int which=0; which<mNumBuffers; which++) { 50bool Fifo::isEmpty() {
51 if (mBuffer[which] != NULL) { 51 return mRead == mWrite;
52 free(mBuffer[which]); 52}
53 mBuffer[which] = NULL; 53
54 } 54bool Fifo::isFull() {
55 } 55 return willFill(0);
56} 56}
57 57
58int Fifo::depth(void) { 58// Determines if the buffer will fill assuming 'additional' bytes will be added to the buffer
59 return mNumBuffers; 59// comparisons use '<', read and write pointers must never equal when not empty
60} 60// 'full' means there is less than singleBufferSize bytes available; it does not mean there are zero bytes available
61 61bool Fifo::willFill(int additional) {
62int Fifo::numReadToWriteBuffersFilled() { 62 if (mWrite > mRead) {
63 int value; 63 if (numBytesFilled() + additional < mWrapThreshold) {
64 int numFilled = 0; 64 return false;
65 for (int which=0; which<mNumBuffers; which++) { 65 }
66 if (sem_getvalue(&mReadToWriteSem[which], &value) == 0) numFilled += value; 66 } else {
67 } 67 if (numBytesFilled() + additional < mWrapThreshold - mSingleBufferSize) {
68 return numFilled; 68 return false;
69} 69 }
70 70 }
71int Fifo::numWriteToReadBuffersFilled() { 71 return true;
72 int value; 72}
73 int numFilled = 0; 73
74 for (int which=0; which<mNumBuffers; which++) { 74// This function will stall until contiguous singleBufferSize bytes are available
75 if (sem_getvalue(&mWriteToReadSem[which], &value) == 0) numFilled += value; 75char* Fifo::write(int length) {
76 } 76 if (length <= 0) {
77 return numFilled; 77 length = 0;
78} 78 mEnd = true;
79 79 }
80char* Fifo::start() { 80
81 sem_wait(&mReadToWriteSem[mWriteCurrent]); 81 // update the write pointer
82 return mBuffer[mWriteCurrent]; 82 mWrite += length;
83} 83
84 84 // handle the wrap-around
85char* Fifo::write(int length) { 85 if (mWrite >= mWrapThreshold) {
86 mLength[mWriteCurrent] = length; 86 mRaggedEnd = mWrite;
87 sem_post(&mWriteToReadSem[mWriteCurrent]); 87 mWrite = 0;
88 mWriteCurrent = (mWriteCurrent + 1) % mNumBuffers; 88 }
89 sem_wait(&mReadToWriteSem[mWriteCurrent]); 89
90 return mBuffer[mWriteCurrent]; 90 // send a notification that data is ready
91} 91 sem_post(&mWaitForDataSem);
92 92
93char* Fifo::read(int* length) { 93 // wait for space
94 static bool firstTime = true; 94 while (isFull()) {
95 if (!firstTime) { 95 sem_wait(&mWaitForSpaceSem);
96 sem_post(&mReadToWriteSem[mReadCurrent]); 96 }
97 } 97
98 firstTime = false; 98 return &mBuffer[mWrite];
99 mReadCurrent = (mReadCurrent + 1) % mNumBuffers; 99}
100 sem_wait(&mWriteToReadSem[mReadCurrent]); 100
101 *length = mLength[mReadCurrent]; 101// This function will stall until data is available
102 return mBuffer[mReadCurrent]; 102char* Fifo::read(int* length) {
103} 103 // update the read pointer now that the data has been handled
104 mRead = mReadCommit;
105
106 // handle the wrap-around
107 if (mRead >= mWrapThreshold) {
108 mRaggedEnd = mRead = mReadCommit = 0;
109 }
110
111 // send a notification that data is free (space is available)
112 sem_post(&mWaitForSpaceSem);
113
114 // wait for data
115 while (isEmpty() && !mEnd) {
116 sem_wait(&mWaitForDataSem);
117 }
118
119 // obtain the length
120 do {
121 mReadCommit = mRaggedEnd ? mRaggedEnd : mWrite;
122 *length = mReadCommit - mRead;
123 } while (*length < 0); // plugs race condition without using semaphores
124
125 return &mBuffer[mRead];
126}
diff --git a/daemon/Fifo.h b/daemon/Fifo.h
index 51e2bcd..548ba27 100644
--- a/daemon/Fifo.h
+++ b/daemon/Fifo.h
@@ -1,41 +1,33 @@
1/** 1/**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved. 2 * Copyright (C) ARM Limited 2010-2012. 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#ifndef __FIFO_H__ 9#ifndef __FIFO_H__
10#define __FIFO_H__ 10#define __FIFO_H__
11 11
12#include <semaphore.h> 12#include <semaphore.h>
13 13
14// Number of buffers allowed with large buffer mode 14class Fifo {
15#define FIFO_BUFFER_LIMIT 64 15public:
16 16 Fifo(int singleBufferSize, int totalBufferSize);
17class Fifo { 17 ~Fifo();
18public: 18 int numBytesFilled();
19 Fifo(int numBuffers, int bufferSize); 19 bool isEmpty();
20 ~Fifo(); 20 bool isFull();
21 int depth(void); 21 bool willFill(int additional);
22 int numReadToWriteBuffersFilled(); 22 char* start();
23 int numWriteToReadBuffersFilled(); 23 char* write(int length);
24 int numReadToWriteBuffersEmpty() {return depth() - numReadToWriteBuffersFilled();} 24 char* read(int* length);
25 int numWriteToReadBuffersEmpty() {return depth() - numWriteToReadBuffersFilled();} 25
26 char* start(); 26private:
27 char* write(int length); 27 int mSingleBufferSize, mWrite, mRead, mReadCommit, mRaggedEnd, mWrapThreshold;
28 char* read(int* length); 28 sem_t mWaitForSpaceSem, mWaitForDataSem;
29 29 char* mBuffer;
30private: 30 bool mEnd;
31 int mNumBuffers; 31};
32 int mBufferSize; 32
33 int mWriteCurrent; 33#endif //__FIFO_H__
34 int mReadCurrent;
35 sem_t mReadToWriteSem[FIFO_BUFFER_LIMIT];
36 sem_t mWriteToReadSem[FIFO_BUFFER_LIMIT];
37 char* mBuffer[FIFO_BUFFER_LIMIT];
38 int mLength[FIFO_BUFFER_LIMIT];
39};
40
41#endif //__FIFO_H__
diff --git a/daemon/LocalCapture.cpp b/daemon/LocalCapture.cpp
index 4a2d6d7..6449d03 100644
--- a/daemon/LocalCapture.cpp
+++ b/daemon/LocalCapture.cpp
@@ -24,9 +24,9 @@ LocalCapture::LocalCapture() {}
24LocalCapture::~LocalCapture() {} 24LocalCapture::~LocalCapture() {}
25 25
26void LocalCapture::createAPCDirectory(char* target_path, char* name) { 26void LocalCapture::createAPCDirectory(char* target_path, char* name) {
27 gSessionData->apcDir = createUniqueDirectory(target_path, ".apc", name); 27 gSessionData->mAPCDir = createUniqueDirectory(target_path, ".apc", name);
28 if ((removeDirAndAllContents(gSessionData->apcDir) != 0 || mkdir(gSessionData->apcDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)) { 28 if ((removeDirAndAllContents(gSessionData->mAPCDir) != 0 || mkdir(gSessionData->mAPCDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)) {
29 logg->logError(__FILE__, __LINE__, "Unable to create directory %s", gSessionData->apcDir); 29 logg->logError(__FILE__, __LINE__, "Unable to create directory %s", gSessionData->mAPCDir);
30 handleException(); 30 handleException();
31 } 31 }
32} 32}
@@ -35,7 +35,7 @@ void LocalCapture::write(char* string) {
35 char* file = (char*)malloc(PATH_MAX); 35 char* file = (char*)malloc(PATH_MAX);
36 36
37 // Set full path 37 // Set full path
38 snprintf(file, PATH_MAX, "%s/session.xml", gSessionData->apcDir); 38 snprintf(file, PATH_MAX, "%s/session.xml", gSessionData->mAPCDir);
39 39
40 // Write the file 40 // Write the file
41 if (util->writeToDisk(file, string) < 0) { 41 if (util->writeToDisk(file, string) < 0) {
@@ -53,12 +53,14 @@ char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* e
53 53
54 // Ensure the path is an absolute path, i.e. starts with a slash 54 // Ensure the path is an absolute path, i.e. starts with a slash
55 if (initialPath == 0 || strlen(initialPath) == 0) { 55 if (initialPath == 0 || strlen(initialPath) == 0) {
56 if (getcwd(path, PATH_MAX) == 0) 56 if (getcwd(path, PATH_MAX) == 0) {
57 logg->logMessage("Unable to retrive the current working directory"); 57 logg->logMessage("Unable to retrive the current working directory");
58 }
58 strncat(path, "/@F_@N", PATH_MAX - strlen(path) - 1); 59 strncat(path, "/@F_@N", PATH_MAX - strlen(path) - 1);
59 } else if (initialPath[0] != '/') { 60 } else if (initialPath[0] != '/') {
60 if (getcwd(path, PATH_MAX) == 0) 61 if (getcwd(path, PATH_MAX) == 0) {
61 logg->logMessage("Unable to retrive the current working directory"); 62 logg->logMessage("Unable to retrive the current working directory");
63 }
62 strncat(path, "/", PATH_MAX - strlen(path) - 1); 64 strncat(path, "/", PATH_MAX - strlen(path) - 1);
63 strncat(path, initialPath, PATH_MAX - strlen(path) - 1); 65 strncat(path, initialPath, PATH_MAX - strlen(path) - 1);
64 } else { 66 } else {
@@ -158,7 +160,7 @@ void LocalCapture::replaceAll(char* target, const char* find, const char* replac
158 free(original); 160 free(original);
159} 161}
160 162
161int LocalCapture::removeDirAndAllContents(char *path) { 163int LocalCapture::removeDirAndAllContents(char* path) {
162 int error = 0; 164 int error = 0;
163 struct stat mFileInfo; 165 struct stat mFileInfo;
164 // Does the path exist? 166 // Does the path exist?
@@ -173,7 +175,9 @@ int LocalCapture::removeDirAndAllContents(char *path) {
173 sprintf(newpath, "%s/%s", path, entry->d_name); 175 sprintf(newpath, "%s/%s", path, entry->d_name);
174 error = removeDirAndAllContents(newpath); 176 error = removeDirAndAllContents(newpath);
175 free(newpath); 177 free(newpath);
176 if (error) break; 178 if (error) {
179 break;
180 }
177 } 181 }
178 entry = readdir(dir); 182 entry = readdir(dir);
179 } 183 }
@@ -192,15 +196,17 @@ void LocalCapture::copyImages(ImageLinkList* ptr) {
192 char* dstfilename = (char*)malloc(PATH_MAX); 196 char* dstfilename = (char*)malloc(PATH_MAX);
193 197
194 while (ptr) { 198 while (ptr) {
195 strncpy(dstfilename, gSessionData->apcDir, PATH_MAX); 199 strncpy(dstfilename, gSessionData->mAPCDir, PATH_MAX);
196 dstfilename[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string 200 dstfilename[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string
197 if (gSessionData->apcDir[strlen(gSessionData->apcDir) - 1] != '/') 201 if (gSessionData->mAPCDir[strlen(gSessionData->mAPCDir) - 1] != '/') {
198 strncat(dstfilename, "/", PATH_MAX - strlen(dstfilename) - 1); 202 strncat(dstfilename, "/", PATH_MAX - strlen(dstfilename) - 1);
203 }
199 strncat(dstfilename, util->getFilePart(ptr->path), PATH_MAX - strlen(dstfilename) - 1); 204 strncat(dstfilename, util->getFilePart(ptr->path), PATH_MAX - strlen(dstfilename) - 1);
200 if (util->copyFile(ptr->path, dstfilename)) 205 if (util->copyFile(ptr->path, dstfilename)) {
201 logg->logMessage("copied file %s to %s", ptr->path, dstfilename); 206 logg->logMessage("copied file %s to %s", ptr->path, dstfilename);
202 else 207 } else {
203 logg->logMessage("copy of file %s to %s failed", ptr->path, dstfilename); 208 logg->logMessage("copy of file %s to %s failed", ptr->path, dstfilename);
209 }
204 210
205 ptr = ptr->next; 211 ptr = ptr->next;
206 } 212 }
diff --git a/daemon/LocalCapture.h b/daemon/LocalCapture.h
index 4f5f818..ca37f6e 100644
--- a/daemon/LocalCapture.h
+++ b/daemon/LocalCapture.h
@@ -15,13 +15,13 @@ class LocalCapture {
15public: 15public:
16 LocalCapture(); 16 LocalCapture();
17 ~LocalCapture(); 17 ~LocalCapture();
18 void write(char *string); 18 void write(char* string);
19 void copyImages(ImageLinkList* ptr); 19 void copyImages(ImageLinkList* ptr);
20 void createAPCDirectory(char* target_path, char* name); 20 void createAPCDirectory(char* target_path, char* name);
21private: 21private:
22 char* createUniqueDirectory(const char* path, const char* ending, char* title); 22 char* createUniqueDirectory(const char* path, const char* ending, char* title);
23 void replaceAll(char* target, const char* find, const char* replace, unsigned int size); 23 void replaceAll(char* target, const char* find, const char* replace, unsigned int size);
24 int removeDirAndAllContents(char *path); 24 int removeDirAndAllContents(char* path);
25}; 25};
26 26
27#endif //__LOCAL_CAPTURE_H__ 27#endif //__LOCAL_CAPTURE_H__
diff --git a/daemon/Makefile b/daemon/Makefile
index 4aaf219..300c3e9 100644
--- a/daemon/Makefile
+++ b/daemon/Makefile
@@ -7,6 +7,7 @@
7ARCH=arm 7ARCH=arm
8 8
9CPP=$(CROSS_COMPILE)g++ 9CPP=$(CROSS_COMPILE)g++
10GCC=$(CROSS_COMPILE)gcc
10 11
11# -g produces debugging information 12# -g produces debugging information
12# -O3 maximum optimization 13# -O3 maximum optimization
@@ -17,13 +18,18 @@ CPP=$(CROSS_COMPILE)g++
17# -std=c++98 is the 1998 c++ standard 18# -std=c++98 is the 1998 c++ standard
18# -march=armv5t is required to set the minimum architecture 19# -march=armv5t is required to set the minimum architecture
19# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc 20# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc
20CFLAGS=-O3 -Wall -Werror -march=armv5t -mthumb-interwork 21CFLAGS=-O3 -Wall -Werror -Wno-error=sequence-point -march=armv5t -mthumb-interwork
21TARGET=gatord 22TARGET=gatord
22CPP_SRC = $(wildcard *.cpp) 23C_SRC = $(wildcard mxml/*.c)
23TGT_OBJS = $(CPP_SRC:%.cpp=%.o) 24CPP_SRC = $(wildcard *.cpp)
25TGT_OBJS = $(CPP_SRC:%.cpp=%.o) \
26 $(C_SRC:%.c=%.o)
24 27
25all: $(TARGET) 28all: $(TARGET)
26 29
30%.o: %.c *.h
31 $(GCC) -c $(CFLAGS) -o $@ $<
32
27%.o: %.cpp *.h 33%.o: %.cpp *.h
28 $(CPP) -c $(CFLAGS) -o $@ $< 34 $(CPP) -c $(CFLAGS) -o $@ $<
29 35
@@ -37,4 +43,4 @@ convert:
37 xxd -i configuration.xml > configuration_xml.h 43 xxd -i configuration.xml > configuration_xml.h
38 44
39clean: 45clean:
40 rm -f *.o $(TARGET) events.xml events_xml.h configuration_xml.h 46 rm -f *.o mxml/*.o $(TARGET) events.xml events_xml.h configuration_xml.h
diff --git a/daemon/OlySocket.cpp b/daemon/OlySocket.cpp
index 8a9ca97..a3bf746 100644..100755
--- a/daemon/OlySocket.cpp
+++ b/daemon/OlySocket.cpp
@@ -46,7 +46,7 @@ OlySocket::OlySocket(int port, bool multiple) {
46} 46}
47 47
48OlySocket::OlySocket(int port, char* host) { 48OlySocket::OlySocket(int port, char* host) {
49 fdServer = 0; 49 mFDServer = 0;
50 createClientSocket(host, port); 50 createClientSocket(host, port);
51} 51}
52 52
@@ -70,11 +70,11 @@ void OlySocket::closeSocket() {
70} 70}
71 71
72void OlySocket::closeServerSocket() { 72void OlySocket::closeServerSocket() {
73 if (CLOSE_SOCKET(fdServer) != 0) { 73 if (CLOSE_SOCKET(mFDServer) != 0) {
74 logg->logError(__FILE__, __LINE__, "Failed to close server socket."); 74 logg->logError(__FILE__, __LINE__, "Failed to close server socket.");
75 handleException(); 75 handleException();
76 } 76 }
77 fdServer = 0; 77 mFDServer = 0;
78} 78}
79 79
80void OlySocket::createClientSocket(char* hostname, int portno) { 80void OlySocket::createClientSocket(char* hostname, int portno) {
@@ -95,8 +95,9 @@ void OlySocket::createClientSocket(char* hostname, int portno) {
95 handleException(); 95 handleException();
96 } 96 }
97 for (res=res0; res!=NULL; res = res->ai_next) { 97 for (res=res0; res!=NULL; res = res->ai_next) {
98 if ( res->ai_family != PF_INET || res->ai_socktype != SOCK_STREAM ) 98 if ( res->ai_family != PF_INET || res->ai_socktype != SOCK_STREAM ) {
99 continue; 99 continue;
100 }
100 mSocketID = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 101 mSocketID = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
101 if (mSocketID < 0) { 102 if (mSocketID < 0) {
102 continue; 103 continue;
@@ -105,7 +106,9 @@ void OlySocket::createClientSocket(char* hostname, int portno) {
105 close(mSocketID); 106 close(mSocketID);
106 mSocketID = -1; 107 mSocketID = -1;
107 } 108 }
108 if (mSocketID > 0) break; 109 if (mSocketID > 0) {
110 break;
111 }
109 } 112 }
110 freeaddrinfo(res0); 113 freeaddrinfo(res0);
111 if (mSocketID <= 0) { 114 if (mSocketID <= 0) {
@@ -124,15 +127,15 @@ void OlySocket::createSingleServerConnection(int port) {
124 127
125void OlySocket::createServerSocket(int port) { 128void OlySocket::createServerSocket(int port) {
126 // Create socket 129 // Create socket
127 fdServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); 130 mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
128 if (fdServer < 0) { 131 if (mFDServer < 0) {
129 logg->logError(__FILE__, __LINE__, "Error creating server socket"); 132 logg->logError(__FILE__, __LINE__, "Error creating server socket");
130 handleException(); 133 handleException();
131 } 134 }
132 135
133 // Enable address reuse, another solution would be to create the server socket once and only close it when the object exits 136 // Enable address reuse, another solution would be to create the server socket once and only close it when the object exits
134 int on = 1; 137 int on = 1;
135 if (setsockopt(fdServer, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on)) != 0) { 138 if (setsockopt(mFDServer, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) != 0) {
136 logg->logError(__FILE__, __LINE__, "Setting server socket options failed"); 139 logg->logError(__FILE__, __LINE__, "Setting server socket options failed");
137 handleException(); 140 handleException();
138 } 141 }
@@ -145,13 +148,13 @@ void OlySocket::createServerSocket(int port) {
145 sockaddr.sin_addr.s_addr = INADDR_ANY; 148 sockaddr.sin_addr.s_addr = INADDR_ANY;
146 149
147 // Bind the socket to an address 150 // Bind the socket to an address
148 if (bind(fdServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) { 151 if (bind(mFDServer, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) {
149 logg->logError(__FILE__, __LINE__, "Binding of server socket failed.\nIs an instance already running?"); 152 logg->logError(__FILE__, __LINE__, "Binding of server socket failed.\nIs an instance already running?");
150 handleException(); 153 handleException();
151 } 154 }
152 155
153 // Listen for connections on this socket 156 // Listen for connections on this socket
154 if (listen(fdServer, 1) < 0) { 157 if (listen(mFDServer, 1) < 0) {
155 logg->logError(__FILE__, __LINE__, "Listening of server socket failed"); 158 logg->logError(__FILE__, __LINE__, "Listening of server socket failed");
156 handleException(); 159 handleException();
157 } 160 }
@@ -160,13 +163,13 @@ void OlySocket::createServerSocket(int port) {
160// mSocketID is always set to the most recently accepted connection 163// mSocketID is always set to the most recently accepted connection
161// The user of this class should maintain the different socket connections, e.g. by forking the process 164// The user of this class should maintain the different socket connections, e.g. by forking the process
162int OlySocket::acceptConnection() { 165int OlySocket::acceptConnection() {
163 if (fdServer <= 0) { 166 if (mFDServer <= 0) {
164 logg->logError(__FILE__, __LINE__, "Attempting multiple connections on a single connection server socket or attempting to accept on a client socket"); 167 logg->logError(__FILE__, __LINE__, "Attempting multiple connections on a single connection server socket or attempting to accept on a client socket");
165 handleException(); 168 handleException();
166 } 169 }
167 170
168 // Accept a connection, note that this call blocks until a client connects 171 // Accept a connection, note that this call blocks until a client connects
169 mSocketID = accept(fdServer, NULL, NULL); 172 mSocketID = accept(mFDServer, NULL, NULL);
170 if (mSocketID < 0) { 173 if (mSocketID < 0) {
171 logg->logError(__FILE__, __LINE__, "Socket acceptance failed"); 174 logg->logError(__FILE__, __LINE__, "Socket acceptance failed");
172 handleException(); 175 handleException();
@@ -230,8 +233,9 @@ int OlySocket::receiveString(char* buffer, int size) {
230 int bytes_received = 0; 233 int bytes_received = 0;
231 bool found = false; 234 bool found = false;
232 235
233 if (buffer == 0) 236 if (buffer == 0) {
234 return 0; 237 return 0;
238 }
235 239
236 while (!found && bytes_received < size) { 240 while (!found && bytes_received < size) {
237 // Receive a single character 241 // Receive a single character
diff --git a/daemon/OlySocket.h b/daemon/OlySocket.h
index 2fe6e59..266a831 100644..100755
--- a/daemon/OlySocket.h
+++ b/daemon/OlySocket.h
@@ -25,11 +25,9 @@ public:
25 int receive(char* buffer, int size); 25 int receive(char* buffer, int size);
26 int receiveNBytes(char* buffer, int size); 26 int receiveNBytes(char* buffer, int size);
27 int receiveString(char* buffer, int size); 27 int receiveString(char* buffer, int size);
28 char* getLastError() {return strError;}
29 int getSocketID() {return mSocketID;} 28 int getSocketID() {return mSocketID;}
30private: 29private:
31 char* strError; 30 int mSocketID, mFDServer;
32 int mSocketID, fdServer;
33 void createClientSocket(char* hostname, int port); 31 void createClientSocket(char* hostname, int port);
34 void createSingleServerConnection(int port); 32 void createSingleServerConnection(int port);
35 void createServerSocket(int port); 33 void createServerSocket(int port);
diff --git a/daemon/OlyUtility.cpp b/daemon/OlyUtility.cpp
index 1b15d33..ec852df 100644..100755
--- a/daemon/OlyUtility.cpp
+++ b/daemon/OlyUtility.cpp
@@ -21,9 +21,35 @@
21 21
22OlyUtility* util = NULL; 22OlyUtility* util = NULL;
23 23
24bool OlyUtility::stringToBool(const char* string, bool defValue) {
25 char value[32];
26
27 strncpy(value, string, sizeof(value));
28 if (value[0] == 0) {
29 return defValue;
30 }
31 value[sizeof(value) - 1] = 0; // strncpy does not guarantee a null-terminated string
32
33 // Convert to lowercase
34 int i = 0;
35 while (value[i]) {
36 value[i] = tolower(value[i]);
37 i++;
38 }
39
40 if (strcmp(value, "true") == 0 || strcmp(value, "yes") == 0 || strcmp(value, "1") == 0 || strcmp(value, "on") == 0) {
41 return true;
42 } else if (strcmp(value, "false") == 0 || strcmp(value, "no") == 0 || strcmp(value, "0") == 0 || strcmp(value, "off") == 0) {
43 return false;
44 } else {
45 return defValue;
46 }
47}
48
24void OlyUtility::stringToLower(char* string) { 49void OlyUtility::stringToLower(char* string) {
25 if (string == NULL) 50 if (string == NULL) {
26 return; 51 return;
52 }
27 53
28 while (*string) { 54 while (*string) {
29 *string = tolower(*string); 55 *string = tolower(*string);
@@ -40,8 +66,9 @@ int OlyUtility::getApplicationFullPath(char* fullpath, int sizeOfPath) {
40 int length = readlink("/proc/self/exe", fullpath, sizeOfPath); 66 int length = readlink("/proc/self/exe", fullpath, sizeOfPath);
41#endif 67#endif
42 68
43 if (length == sizeOfPath) 69 if (length == sizeOfPath) {
44 return -1; 70 return -1;
71 }
45 72
46 fullpath[length] = 0; 73 fullpath[length] = 0;
47 fullpath = getPathPart(fullpath); 74 fullpath = getPathPart(fullpath);
@@ -52,7 +79,9 @@ int OlyUtility::getApplicationFullPath(char* fullpath, int sizeOfPath) {
52char* OlyUtility::readFromDisk(const char* file, unsigned int *size, bool appendNull) { 79char* OlyUtility::readFromDisk(const char* file, unsigned int *size, bool appendNull) {
53 // Open the file 80 // Open the file
54 FILE* pFile = fopen(file, "rb"); 81 FILE* pFile = fopen(file, "rb");
55 if (pFile==NULL) return NULL; 82 if (pFile==NULL) {
83 return NULL;
84 }
56 85
57 // Obtain file size 86 // Obtain file size
58 fseek(pFile , 0 , SEEK_END); 87 fseek(pFile , 0 , SEEK_END);
@@ -61,19 +90,28 @@ char* OlyUtility::readFromDisk(const char* file, unsigned int *size, bool append
61 90
62 // Allocate memory to contain the whole file 91 // Allocate memory to contain the whole file
63 char* buffer = (char*)malloc(lSize + (int)appendNull); 92 char* buffer = (char*)malloc(lSize + (int)appendNull);
64 if (buffer == NULL) return NULL; 93 if (buffer == NULL) {
94 fclose(pFile);
95 return NULL;
96 }
65 97
66 // Copy the file into the buffer 98 // Copy the file into the buffer
67 if (fread(buffer, 1, lSize, pFile) != lSize) return NULL; 99 if (fread(buffer, 1, lSize, pFile) != lSize) {
100 free(buffer);
101 fclose(pFile);
102 return NULL;
103 }
68 104
69 // Terminate 105 // Terminate
70 fclose(pFile); 106 fclose(pFile);
71 107
72 if (appendNull) 108 if (appendNull) {
73 buffer[lSize] = 0; 109 buffer[lSize] = 0;
110 }
74 111
75 if (size) 112 if (size) {
76 *size = lSize; 113 *size = lSize;
114 }
77 115
78 return buffer; 116 return buffer;
79} 117}
@@ -81,10 +119,15 @@ char* OlyUtility::readFromDisk(const char* file, unsigned int *size, bool append
81int OlyUtility::writeToDisk(const char* path, const char* data) { 119int OlyUtility::writeToDisk(const char* path, const char* data) {
82 // Open the file 120 // Open the file
83 FILE* pFile = fopen(path, "wb"); 121 FILE* pFile = fopen(path, "wb");
84 if (pFile == NULL) return -1; 122 if (pFile == NULL) {
123 return -1;
124 }
85 125
86 // Write the data to disk 126 // Write the data to disk
87 if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) return -1; 127 if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) {
128 fclose(pFile);
129 return -1;
130 }
88 131
89 // Terminate 132 // Terminate
90 fclose(pFile); 133 fclose(pFile);
@@ -94,10 +137,15 @@ int OlyUtility::writeToDisk(const char* path, const char* data) {
94int OlyUtility::appendToDisk(const char* path, const char* data) { 137int OlyUtility::appendToDisk(const char* path, const char* data) {
95 // Open the file 138 // Open the file
96 FILE* pFile = fopen(path, "a"); 139 FILE* pFile = fopen(path, "a");
97 if (pFile == NULL) return -1; 140 if (pFile == NULL) {
141 return -1;
142 }
98 143
99 // Write the data to disk 144 // Write the data to disk
100 if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) return -1; 145 if (fwrite(data, 1, strlen(data), pFile) != strlen(data)) {
146 fclose(pFile);
147 return -1;
148 }
101 149
102 // Terminate 150 // Terminate
103 fclose(pFile); 151 fclose(pFile);
@@ -110,7 +158,7 @@ int OlyUtility::appendToDisk(const char* path, const char* data) {
110 * 0 is returned on an error; otherwise 1. 158 * 0 is returned on an error; otherwise 1.
111 */ 159 */
112#define TRANSFER_SIZE 1024 160#define TRANSFER_SIZE 1024
113int OlyUtility::copyFile(const char * srcFile, const char * dstFile) { 161int OlyUtility::copyFile(const char* srcFile, const char* dstFile) {
114 char* buffer = (char*)malloc(TRANSFER_SIZE); 162 char* buffer = (char*)malloc(TRANSFER_SIZE);
115 FILE * f_src = fopen(srcFile,"rb"); 163 FILE * f_src = fopen(srcFile,"rb");
116 if (!f_src) { 164 if (!f_src) {
@@ -165,3 +213,42 @@ char* OlyUtility::getPathPart(char* path) {
165 213
166 return (path); 214 return (path);
167} 215}
216
217// whitespace callback utility function used with mini-xml
218const char * mxmlWhitespaceCB(mxml_node_t *node, int loc) {
219 const char *name;
220
221 name = mxmlGetElement(node);
222
223 if (loc == MXML_WS_BEFORE_OPEN) {
224 // Single indentation
225 if (!strcmp(name, "target") || !strcmp(name, "counters"))
226 return("\n ");
227
228 // Double indentation
229 if (!strcmp(name, "counter"))
230 return("\n ");
231
232 // Avoid a carriage return on the first line of the xml file
233 if (!strncmp(name, "?xml", 4))
234 return(NULL);
235
236 // Default - no indentation
237 return("\n");
238 }
239
240 if (loc == MXML_WS_BEFORE_CLOSE) {
241 // No indentation
242 if (!strcmp(name, "captured"))
243 return("\n");
244
245 // Single indentation
246 if (!strcmp(name, "counters"))
247 return("\n ");
248
249 // Default - no carriage return
250 return(NULL);
251 }
252
253 return(NULL);
254}
diff --git a/daemon/OlyUtility.h b/daemon/OlyUtility.h
index 0fa021d..793a733 100644..100755
--- a/daemon/OlyUtility.h
+++ b/daemon/OlyUtility.h
@@ -19,17 +19,20 @@ class OlyUtility {
19public: 19public:
20 OlyUtility() {}; 20 OlyUtility() {};
21 ~OlyUtility() {}; 21 ~OlyUtility() {};
22 bool stringToBool(const char* string, bool defValue);
22 void stringToLower(char* string); 23 void stringToLower(char* string);
23 int getApplicationFullPath(char* path, int sizeOfPath); 24 int getApplicationFullPath(char* path, int sizeOfPath);
24 char* readFromDisk(const char* file, unsigned int *size = NULL, bool appendNull = true); 25 char* readFromDisk(const char* file, unsigned int *size = NULL, bool appendNull = true);
25 int writeToDisk(const char* path, const char* file); 26 int writeToDisk(const char* path, const char* file);
26 int appendToDisk(const char* path, const char* file); 27 int appendToDisk(const char* path, const char* file);
27 int copyFile(const char * srcFile, const char * dstFile); 28 int copyFile(const char* srcFile, const char* dstFile);
28 const char* getFilePart(const char* path); 29 const char* getFilePart(const char* path);
29 char* getPathPart(char* path); 30 char* getPathPart(char* path);
30private: 31private:
31}; 32};
32 33
34#include "mxml/mxml.h"
35const char * mxmlWhitespaceCB(mxml_node_t *node, int where);
33extern OlyUtility* util; 36extern OlyUtility* util;
34 37
35#endif // OLY_UTILITY_H 38#endif // OLY_UTILITY_H
diff --git a/daemon/RequestXML.cpp b/daemon/RequestXML.cpp
deleted file mode 100644
index e8f24d2..0000000
--- a/daemon/RequestXML.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
1/**
2 * Copyright (C) ARM Limited 2011-2012. All rights reserved.
3 *
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 <string.h>
10#include <stdlib.h>
11#include <limits.h>
12#include "RequestXML.h"
13#include "Logging.h"
14
15extern void handleException();
16
17static const char* TAG_REQUEST = "request";
18
19static const char* ATTR_PROTOCOL = "protocol";
20static const char* ATTR_EVENTS = "events";
21static const char* ATTR_CONFIGURATION = "configuration";
22static const char* ATTR_COUNTERS = "counters";
23static const char* ATTR_SESSION = "session";
24static const char* ATTR_CAPTURED = "captured";
25static const char* ATTR_DEFAULTS = "defaults";
26
27RequestXML::RequestXML(const char * str) {
28 parameters.protocol = false;
29 parameters.events = false;
30 parameters.configuration = false;
31 parameters.counters = false;
32 parameters.session = false;
33 parameters.captured = false;
34 parameters.defaults = false;
35
36 XMLReader reader(str);
37 char * tag = reader.nextTag();
38 while(tag != 0) {
39 if (strcmp(tag, TAG_REQUEST) == 0) {
40 requestTag(&reader);
41 return;
42 }
43 tag = reader.nextTag();
44 }
45
46 logg->logError(__FILE__, __LINE__, "No request tag found in the request.xml file");
47 handleException();
48}
49
50RequestXML::~RequestXML() {
51}
52
53void RequestXML::requestTag(XMLReader* in) {
54 parameters.protocol = in->getAttributeAsBoolean(ATTR_PROTOCOL, false);
55 parameters.events = in->getAttributeAsBoolean(ATTR_EVENTS, false);
56 parameters.configuration = in->getAttributeAsBoolean(ATTR_CONFIGURATION, false);
57 parameters.counters = in->getAttributeAsBoolean(ATTR_COUNTERS, false);
58 parameters.session = in->getAttributeAsBoolean(ATTR_SESSION, false);
59 parameters.captured = in->getAttributeAsBoolean(ATTR_CAPTURED, false);
60 parameters.defaults = in->getAttributeAsBoolean(ATTR_DEFAULTS, false);
61}
diff --git a/daemon/RequestXML.h b/daemon/RequestXML.h
deleted file mode 100644
index bebd048..0000000
--- a/daemon/RequestXML.h
+++ /dev/null
@@ -1,33 +0,0 @@
1/**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved.
3 *
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#ifndef REQUEST_XML_H
10#define REQUEST_XML_H
11
12#include "XMLReader.h"
13
14struct ConfigParameters {
15 bool protocol;
16 bool events;
17 bool configuration;
18 bool counters;
19 bool session;
20 bool captured;
21 bool defaults;
22};
23
24class RequestXML {
25public:
26 RequestXML(const char * str);
27 ~RequestXML();
28 ConfigParameters parameters;
29private:
30 void requestTag(XMLReader* in);
31};
32
33#endif // REQUEST_XML_H
diff --git a/daemon/Sender.cpp b/daemon/Sender.cpp
index 9792c36..efff753 100644
--- a/daemon/Sender.cpp
+++ b/daemon/Sender.cpp
@@ -20,18 +20,18 @@
20extern void handleException(); 20extern void handleException();
21 21
22Sender::Sender(OlySocket* socket) { 22Sender::Sender(OlySocket* socket) {
23 dataFile = NULL; 23 mDataFile = NULL;
24 dataSocket = NULL; 24 mDataSocket = NULL;
25 25
26 // Set up the socket connection 26 // Set up the socket connection
27 if (socket) { 27 if (socket) {
28 char streamline[64] = {0}; 28 char streamline[64] = {0};
29 dataSocket = socket; 29 mDataSocket = socket;
30 30
31 // Receive magic sequence - can wait forever 31 // Receive magic sequence - can wait forever
32 // Streamline will send data prior to the magic sequence for legacy support, which should be ignored for v4+ 32 // Streamline will send data prior to the magic sequence for legacy support, which should be ignored for v4+
33 while (strcmp("STREAMLINE", streamline) != 0) { 33 while (strcmp("STREAMLINE", streamline) != 0) {
34 if (dataSocket->receiveString(streamline, sizeof(streamline)) == -1) { 34 if (mDataSocket->receiveString(streamline, sizeof(streamline)) == -1) {
35 logg->logError(__FILE__, __LINE__, "Socket disconnected"); 35 logg->logError(__FILE__, __LINE__, "Socket disconnected");
36 handleException(); 36 handleException();
37 } 37 }
@@ -39,32 +39,33 @@ Sender::Sender(OlySocket* socket) {
39 39
40 // Send magic sequence - must be done first, afterwhich error messages can be sent 40 // Send magic sequence - must be done first, afterwhich error messages can be sent
41 char magic[] = {'G', 'A', 'T', 'O', 'R', '\n'}; 41 char magic[] = {'G', 'A', 'T', 'O', 'R', '\n'};
42 dataSocket->send(magic, sizeof(magic)); 42 mDataSocket->send(magic, sizeof(magic));
43 43
44 gSessionData->mWaitingOnCommand = true; 44 gSessionData->mWaitingOnCommand = true;
45 logg->logMessage("Completed magic sequence"); 45 logg->logMessage("Completed magic sequence");
46 } 46 }
47 47
48 pthread_mutex_init(&sendMutex, NULL); 48 pthread_mutex_init(&mSendMutex, NULL);
49} 49}
50 50
51Sender::~Sender() { 51Sender::~Sender() {
52 delete dataSocket; 52 delete mDataSocket;
53 dataSocket = NULL; 53 mDataSocket = NULL;
54 if (dataFile) { 54 if (mDataFile) {
55 fclose(dataFile); 55 fclose(mDataFile);
56 } 56 }
57} 57}
58 58
59void Sender::createDataFile(char* apcDir) { 59void Sender::createDataFile(char* apcDir) {
60 if (apcDir == NULL) 60 if (apcDir == NULL) {
61 return; 61 return;
62 }
62 63
63 dataFileName = (char*)malloc(strlen(apcDir) + 12); 64 mDataFileName = (char*)malloc(strlen(apcDir) + 12);
64 sprintf(dataFileName, "%s/0000000000", apcDir); 65 sprintf(mDataFileName, "%s/0000000000", apcDir);
65 dataFile = fopen(dataFileName, "wb"); 66 mDataFile = fopen(mDataFileName, "wb");
66 if (!dataFile) { 67 if (!mDataFile) {
67 logg->logError(__FILE__, __LINE__, "Failed to open binary file: %s", dataFileName); 68 logg->logError(__FILE__, __LINE__, "Failed to open binary file: %s", mDataFileName);
68 handleException(); 69 handleException();
69 } 70 }
70} 71}
@@ -75,32 +76,35 @@ void Sender::writeData(const char* data, int length, int type) {
75 } 76 }
76 77
77 // Multiple threads call writeData() 78 // Multiple threads call writeData()
78 pthread_mutex_lock(&sendMutex); 79 pthread_mutex_lock(&mSendMutex);
79 80
80 // Send data over the socket connection 81 // Send data over the socket connection
81 if (dataSocket) { 82 if (mDataSocket) {
82 // Start alarm 83 // Start alarm
83 alarm(8); 84 alarm(8);
84 85
85 // Send data over the socket, sending the type and size first 86 // Send data over the socket, sending the type and size first
86 logg->logMessage("Sending data with length %d", length); 87 logg->logMessage("Sending data with length %d", length);
87 dataSocket->send((char*)&type, 1); 88 if (type != RESPONSE_APC_DATA) {
88 dataSocket->send((char*)&length, sizeof(length)); 89 // type and length already added by the Collector for apc data
89 dataSocket->send((char*)data, length); 90 mDataSocket->send((char*)&type, 1);
91 mDataSocket->send((char*)&length, sizeof(length));
92 }
93 mDataSocket->send((char*)data, length);
90 94
91 // Stop alarm 95 // Stop alarm
92 alarm(0); 96 alarm(0);
93 } 97 }
94 98
95 // Write data to disk as long as it is not meta data 99 // Write data to disk as long as it is not meta data
96 if (dataFile && type == RESPONSE_APC_DATA) { 100 if (mDataFile && type == RESPONSE_APC_DATA) {
97 logg->logMessage("Writing data with length %d", length); 101 logg->logMessage("Writing data with length %d", length);
98 // Send data to the data file, storing the size first 102 // Send data to the data file
99 if ((fwrite((char*)&length, 1, sizeof(length), dataFile) != sizeof(length)) || (fwrite(data, 1, length, dataFile) != (unsigned int)length)) { 103 if (fwrite(data, 1, length, mDataFile) != (unsigned int)length) {
100 logg->logError(__FILE__, __LINE__, "Failed writing binary file %s", dataFileName); 104 logg->logError(__FILE__, __LINE__, "Failed writing binary file %s", mDataFileName);
101 handleException(); 105 handleException();
102 } 106 }
103 } 107 }
104 108
105 pthread_mutex_unlock(&sendMutex); 109 pthread_mutex_unlock(&mSendMutex);
106} 110}
diff --git a/daemon/Sender.h b/daemon/Sender.h
index 3444b85..98467e0 100644
--- a/daemon/Sender.h
+++ b/daemon/Sender.h
@@ -29,10 +29,10 @@ public:
29 void writeData(const char* data, int length, int type); 29 void writeData(const char* data, int length, int type);
30 void createDataFile(char* apcDir); 30 void createDataFile(char* apcDir);
31private: 31private:
32 OlySocket* dataSocket; 32 OlySocket* mDataSocket;
33 FILE* dataFile; 33 FILE* mDataFile;
34 char* dataFileName; 34 char* mDataFileName;
35 pthread_mutex_t sendMutex; 35 pthread_mutex_t mSendMutex;
36}; 36};
37 37
38#endif //__SENDER_H__ 38#endif //__SENDER_H__
diff --git a/daemon/SessionData.cpp b/daemon/SessionData.cpp
index 4adcfcd..a245369 100644
--- a/daemon/SessionData.cpp
+++ b/daemon/SessionData.cpp
@@ -27,8 +27,10 @@ void SessionData::initialize() {
27 mLocalCapture = false; 27 mLocalCapture = false;
28 mOneShot = false; 28 mOneShot = false;
29 strcpy(mCoreName, "unknown"); 29 strcpy(mCoreName, "unknown");
30 configurationXMLPath = NULL; 30 mConfigurationXMLPath = NULL;
31 apcDir = NULL; 31 mSessionXMLPath = NULL;
32 mEventsXMLPath = NULL;
33 mAPCDir = NULL;
32 mSampleRate = 0; 34 mSampleRate = 0;
33 mDuration = 0; 35 mDuration = 0;
34 mBytes = 0; 36 mBytes = 0;
@@ -46,14 +48,19 @@ void SessionData::initializeCounters() {
46 mPerfCounterTitle[i][0] = 0; 48 mPerfCounterTitle[i][0] = 0;
47 mPerfCounterName[i][0] = 0; 49 mPerfCounterName[i][0] = 0;
48 mPerfCounterDescription[i][0] = 0; 50 mPerfCounterDescription[i][0] = 0;
51 mPerfCounterOperation[i][0] = 0;
52 mPerfCounterAlias[i][0] = 0;
53 mPerfCounterDisplay[i][0] = 0;
54 mPerfCounterUnits[i][0] = 0;
49 mPerfCounterEnabled[i] = 0; 55 mPerfCounterEnabled[i] = 0;
50 mPerfCounterEvent[i] = 0; 56 mPerfCounterEvent[i] = 0;
51 mPerfCounterColor[i] = 0; 57 mPerfCounterColor[i] = 0;
52 mPerfCounterKey[i] = 0; 58 mPerfCounterKey[i] = 0;
53 mPerfCounterCount[i] = 0; 59 mPerfCounterCount[i] = 0;
54 mPerfCounterOperation[i][0] = 0;
55 mPerfCounterPerCPU[i] = false; 60 mPerfCounterPerCPU[i] = false;
56 mPerfCounterEBSCapable[i] = false; 61 mPerfCounterEBSCapable[i] = false;
62 mPerfCounterLevel[i] = false;
63 mPerfCounterAverageSelection[i] = false;
57 } 64 }
58} 65}
59 66
@@ -75,8 +82,10 @@ void SessionData::parseSessionXML(char* xmlString) {
75 gSessionData->mSampleRate = 10000; 82 gSessionData->mSampleRate = 10000;
76 } else if (strcmp(session.parameters.sample_rate, "normal") == 0) { 83 } else if (strcmp(session.parameters.sample_rate, "normal") == 0) {
77 gSessionData->mSampleRate = 1000; 84 gSessionData->mSampleRate = 1000;
78 } else { // "low" 85 } else if (strcmp(session.parameters.sample_rate, "low") == 0) {
79 gSessionData->mSampleRate = 100; 86 gSessionData->mSampleRate = 100;
87 } else {
88 gSessionData->mSampleRate = 0;
80 } 89 }
81 gSessionData->mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0; 90 gSessionData->mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0;
82 gSessionData->mDuration = session.parameters.duration; 91 gSessionData->mDuration = session.parameters.duration;
@@ -97,7 +106,7 @@ void SessionData::parseSessionXML(char* xmlString) {
97 handleException(); 106 handleException();
98 } 107 }
99 108
100 gSessionData->images = session.parameters.images; 109 gSessionData->mImages = session.parameters.images;
101 gSessionData->target_path = session.parameters.target_path; 110 gSessionData->mTargetPath = session.parameters.target_path;
102 gSessionData->title = session.parameters.title; 111 gSessionData->mTitle = session.parameters.title;
103} 112}
diff --git a/daemon/SessionData.h b/daemon/SessionData.h
index cc188f8..7daee72 100644
--- a/daemon/SessionData.h
+++ b/daemon/SessionData.h
@@ -13,11 +13,11 @@
13#define MAX_STRING_LEN 80 13#define MAX_STRING_LEN 80
14#define MAX_DESCRIPTION_LEN 400 14#define MAX_DESCRIPTION_LEN 400
15 15
16#define PROTOCOL_VERSION 8 16#define PROTOCOL_VERSION 9
17#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions 17#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
18 18
19struct ImageLinkList { 19struct ImageLinkList {
20 char *path; 20 char* path;
21 struct ImageLinkList *next; 21 struct ImageLinkList *next;
22}; 22};
23 23
@@ -30,11 +30,13 @@ public:
30 void parseSessionXML(char* xmlString); 30 void parseSessionXML(char* xmlString);
31 31
32 char mCoreName[MAX_STRING_LEN]; 32 char mCoreName[MAX_STRING_LEN];
33 struct ImageLinkList *images; 33 struct ImageLinkList *mImages;
34 char* configurationXMLPath; 34 char* mConfigurationXMLPath;
35 char* target_path; 35 char* mSessionXMLPath;
36 char* apcDir; 36 char* mEventsXMLPath;
37 char* title; 37 char* mTargetPath;
38 char* mAPCDir;
39 char* mTitle;
38 40
39 bool mWaitingOnCommand; 41 bool mWaitingOnCommand;
40 bool mSessionIsActive; 42 bool mSessionIsActive;
@@ -42,7 +44,7 @@ public:
42 bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled 44 bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled
43 45
44 int mBacktraceDepth; 46 int mBacktraceDepth;
45 int mTotalBufferSize; // approximate number of MB to use for the entire collection buffer, the actual amount is a multiple based on a buffer size retrieved from the driver 47 int mTotalBufferSize; // number of MB to use for the entire collection buffer
46 int mSampleRate; 48 int mSampleRate;
47 int mDuration; 49 int mDuration;
48 int mCores; 50 int mCores;
@@ -53,6 +55,10 @@ public:
53 char mPerfCounterTitle[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN]; 55 char mPerfCounterTitle[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
54 char mPerfCounterName[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN]; 56 char mPerfCounterName[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
55 char mPerfCounterDescription[MAX_PERFORMANCE_COUNTERS][MAX_DESCRIPTION_LEN]; 57 char mPerfCounterDescription[MAX_PERFORMANCE_COUNTERS][MAX_DESCRIPTION_LEN];
58 char mPerfCounterOperation[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
59 char mPerfCounterAlias[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
60 char mPerfCounterDisplay[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
61 char mPerfCounterUnits[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN];
56 int mPerfCounterEnabled[MAX_PERFORMANCE_COUNTERS]; 62 int mPerfCounterEnabled[MAX_PERFORMANCE_COUNTERS];
57 int mPerfCounterEvent[MAX_PERFORMANCE_COUNTERS]; 63 int mPerfCounterEvent[MAX_PERFORMANCE_COUNTERS];
58 int mPerfCounterColor[MAX_PERFORMANCE_COUNTERS]; 64 int mPerfCounterColor[MAX_PERFORMANCE_COUNTERS];
@@ -60,7 +66,8 @@ public:
60 int mPerfCounterKey[MAX_PERFORMANCE_COUNTERS]; 66 int mPerfCounterKey[MAX_PERFORMANCE_COUNTERS];
61 bool mPerfCounterPerCPU[MAX_PERFORMANCE_COUNTERS]; 67 bool mPerfCounterPerCPU[MAX_PERFORMANCE_COUNTERS];
62 bool mPerfCounterEBSCapable[MAX_PERFORMANCE_COUNTERS]; 68 bool mPerfCounterEBSCapable[MAX_PERFORMANCE_COUNTERS];
63 char mPerfCounterOperation[MAX_PERFORMANCE_COUNTERS][MAX_STRING_LEN]; 69 bool mPerfCounterLevel[MAX_PERFORMANCE_COUNTERS];
70 bool mPerfCounterAverageSelection[MAX_PERFORMANCE_COUNTERS];
64}; 71};
65 72
66extern SessionData* gSessionData; 73extern SessionData* gSessionData;
diff --git a/daemon/SessionXML.cpp b/daemon/SessionXML.cpp
index 4604d7c..f1a8258 100644
--- a/daemon/SessionXML.cpp
+++ b/daemon/SessionXML.cpp
@@ -11,6 +11,7 @@
11#include <limits.h> 11#include <limits.h>
12#include "SessionXML.h" 12#include "SessionXML.h"
13#include "Logging.h" 13#include "Logging.h"
14#include "OlyUtility.h"
14 15
15extern void handleException(); 16extern void handleException();
16 17
@@ -28,7 +29,7 @@ static const char* ATTR_OUTPUT_PATH = "output_path";
28static const char* ATTR_DURATION = "duration"; 29static const char* ATTR_DURATION = "duration";
29static const char* ATTR_PATH = "path"; 30static const char* ATTR_PATH = "path";
30 31
31SessionXML::SessionXML(const char * str) { 32SessionXML::SessionXML(const char* str) {
32 parameters.title = 0; 33 parameters.title = 0;
33 parameters.uuid[0] = 0; 34 parameters.uuid[0] = 0;
34 parameters.target_path = 0; 35 parameters.target_path = 0;
@@ -50,70 +51,92 @@ SessionXML::~SessionXML() {
50} 51}
51 52
52void SessionXML::parse() { 53void SessionXML::parse() {
53 XMLReader reader(mSessionXML); 54 mxml_node_t *tree;
54 char * tag = reader.nextTag(); 55 mxml_node_t *node;
55 while(tag != 0) { 56
56 if (strcmp(tag, TAG_SESSION) == 0) { 57 tree = mxmlLoadString(NULL, mSessionXML, MXML_NO_CALLBACK);
57 sessionTag(&reader); 58 node = mxmlFindElement(tree, tree, TAG_SESSION, NULL, NULL, MXML_DESCEND);
58 return; 59
59 } 60 if (node) {
60 tag = reader.nextTag(); 61 sessionTag(tree, node);
62 mxmlDelete(tree);
63 return;
61 } 64 }
62 65
63 logg->logError(__FILE__, __LINE__, "No session tag found in the session.xml file"); 66 logg->logError(__FILE__, __LINE__, "No session tag found in the session.xml file");
64 handleException(); 67 handleException();
65} 68}
66 69
67void SessionXML::sessionTag(XMLReader* in) { 70void SessionXML::sessionTag(mxml_node_t *tree, mxml_node_t *node) {
68 char* tempBuffer = (char*)malloc(PATH_MAX); 71 int version = 0;
69 int version = in->getAttributeAsInteger(ATTR_VERSION, 0); 72 if (mxmlElementGetAttr(node, ATTR_VERSION)) version = strtol(mxmlElementGetAttr(node, ATTR_VERSION), NULL, 10);
70 if (version != 1) { 73 if (version != 1) {
71 logg->logError(__FILE__, __LINE__, "Invalid session.xml version: %d", version); 74 logg->logError(__FILE__, __LINE__, "Invalid session.xml version: %d", version);
72 handleException(); 75 handleException();
73 } 76 }
74 77
75 in->getAttribute(ATTR_TITLE, tempBuffer, PATH_MAX, "unnamed"); 78 // allocate strings
76 parameters.title = strdup(tempBuffer); // freed when the child process exits 79 if (mxmlElementGetAttr(node, ATTR_TITLE)) {
77 if (parameters.title == NULL) { 80 parameters.title = strdup(mxmlElementGetAttr(node, ATTR_TITLE)); // freed when the child process exits
78 logg->logError(__FILE__, __LINE__, "failed to allocate parameters.title (%d bytes)", strlen(tempBuffer)); 81 if (parameters.title == NULL) {
79 handleException(); 82 logg->logError(__FILE__, __LINE__, "failed to allocate parameters.title");
83 handleException();
84 }
80 } 85 }
81 in->getAttribute(ATTR_UUID, parameters.uuid, sizeof(parameters.uuid), ""); 86 if (mxmlElementGetAttr(node, ATTR_TARGET_PATH)) {
82 parameters.duration = in->getAttributeAsInteger(ATTR_DURATION, 0); 87 parameters.target_path = strdup(mxmlElementGetAttr(node, ATTR_TARGET_PATH)); // freed when the child process exits
83 parameters.call_stack_unwinding = in->getAttributeAsBoolean(ATTR_CALL_STACK_UNWINDING, true); 88 if (parameters.target_path == NULL) {
84 in->getAttribute(ATTR_BUFFER_MODE, parameters.buffer_mode, sizeof(parameters.buffer_mode), "normal"); 89 logg->logError(__FILE__, __LINE__, "failed to allocate parameters.target_path");
85 in->getAttribute(ATTR_SAMPLE_RATE, parameters.sample_rate, sizeof(parameters.sample_rate), ""); 90 handleException();
86 in->getAttribute(ATTR_TARGET_PATH, tempBuffer, PATH_MAX, ""); 91 }
87 parameters.target_path = strdup(tempBuffer); // freed when the child process exits
88 if (parameters.target_path == NULL) {
89 logg->logError(__FILE__, __LINE__, "failed to allocate parameters.target_path (%d bytes)", strlen(tempBuffer));
90 handleException();
91 } 92 }
92 in->getAttribute(ATTR_OUTPUT_PATH, tempBuffer, PATH_MAX, ""); 93 if (mxmlElementGetAttr(node, ATTR_OUTPUT_PATH)) {
93 parameters.output_path = strdup(tempBuffer); // freed when the child process exits 94 parameters.output_path = strdup(mxmlElementGetAttr(node, ATTR_OUTPUT_PATH)); // freed when the child process exits
94 if (parameters.output_path == NULL) { 95 if (parameters.output_path == NULL) {
95 logg->logError(__FILE__, __LINE__, "failed to allocate parameters.output_path (%d bytes)", strlen(tempBuffer)); 96 logg->logError(__FILE__, __LINE__, "failed to allocate parameters.output_path");
96 handleException(); 97 handleException();
98 }
97 } 99 }
98 100
99 free(tempBuffer); 101 // copy to pre-allocated strings
102 if (mxmlElementGetAttr(node, ATTR_UUID)) {
103 strncpy(parameters.uuid, mxmlElementGetAttr(node, ATTR_UUID), sizeof(parameters.uuid));
104 parameters.uuid[sizeof(parameters.uuid) - 1] = 0; // strncpy does not guarantee a null-terminated string
105 }
106 if (mxmlElementGetAttr(node, ATTR_BUFFER_MODE)) {
107 strncpy(parameters.buffer_mode, mxmlElementGetAttr(node, ATTR_BUFFER_MODE), sizeof(parameters.buffer_mode));
108 parameters.buffer_mode[sizeof(parameters.buffer_mode) - 1] = 0; // strncpy does not guarantee a null-terminated string
109 }
110 if (mxmlElementGetAttr(node, ATTR_SAMPLE_RATE)) {
111 strncpy(parameters.sample_rate, mxmlElementGetAttr(node, ATTR_SAMPLE_RATE), sizeof(parameters.sample_rate));
112 parameters.sample_rate[sizeof(parameters.sample_rate) - 1] = 0; // strncpy does not guarantee a null-terminated string
113 }
114
115 // integers/bools
116 parameters.call_stack_unwinding = util->stringToBool(mxmlElementGetAttr(node, ATTR_CALL_STACK_UNWINDING), false);
117 if (mxmlElementGetAttr(node, ATTR_DURATION)) parameters.duration = strtol(mxmlElementGetAttr(node, ATTR_DURATION), NULL, 10);
100 118
101 char * tag = in->nextTag(); 119 // parse subtags
102 while(tag != 0) { 120 node = mxmlGetFirstChild(node);
103 if (strcmp(tag, TAG_IMAGE) == 0) { 121 while (node) {
104 sessionImage(in); 122 if (mxmlGetType(node) != MXML_ELEMENT) {
123 node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
124 continue;
125 }
126 if (strcmp(TAG_IMAGE, mxmlGetElement(node)) == 0) {
127 sessionImage(node);
105 } 128 }
106 tag = in->nextTag(); 129 node = mxmlWalkNext(node, tree, MXML_NO_DESCEND);
107 } 130 }
108} 131}
109 132
110void SessionXML::sessionImage(XMLReader* in) { 133void SessionXML::sessionImage(mxml_node_t *node) {
111 int length = in->getAttributeLength(ATTR_PATH); 134 int length = strlen(mxmlElementGetAttr(node, ATTR_PATH));
112 struct ImageLinkList *image; 135 struct ImageLinkList *image;
113 136
114 image = (struct ImageLinkList *)malloc(sizeof(struct ImageLinkList)); 137 image = (struct ImageLinkList *)malloc(sizeof(struct ImageLinkList));
115 image->path = (char *)malloc(length + 1); 138 image->path = (char*)malloc(length + 1);
116 in->getAttribute(ATTR_PATH, image->path, length + 1, ""); 139 image->path = strdup(mxmlElementGetAttr(node, ATTR_PATH));
117 image->next = parameters.images; 140 image->next = parameters.images;
118 parameters.images = image; 141 parameters.images = image;
119} 142}
diff --git a/daemon/SessionXML.h b/daemon/SessionXML.h
index 4649685..c2b5489 100644
--- a/daemon/SessionXML.h
+++ b/daemon/SessionXML.h
@@ -9,7 +9,7 @@
9#ifndef SESSION_XML_H 9#ifndef SESSION_XML_H
10#define SESSION_XML_H 10#define SESSION_XML_H
11 11
12#include "XMLReader.h" 12#include "mxml/mxml.h"
13#include "SessionData.h" 13#include "SessionData.h"
14 14
15struct ConfigParameters { 15struct ConfigParameters {
@@ -26,15 +26,15 @@ struct ConfigParameters {
26 26
27class SessionXML { 27class SessionXML {
28public: 28public:
29 SessionXML(const char * str); 29 SessionXML(const char* str);
30 ~SessionXML(); 30 ~SessionXML();
31 void parse(); 31 void parse();
32 ConfigParameters parameters; 32 ConfigParameters parameters;
33private: 33private:
34 char* mSessionXML; 34 char* mSessionXML;
35 char* mPath; 35 char* mPath;
36 void sessionTag(XMLReader* in); 36 void sessionTag(mxml_node_t *tree, mxml_node_t *node);
37 void sessionImage(XMLReader* in); 37 void sessionImage(mxml_node_t *node);
38}; 38};
39 39
40#endif // SESSION_XML_H 40#endif // SESSION_XML_H
diff --git a/daemon/StreamlineSetup.cpp b/daemon/StreamlineSetup.cpp
index 5662ee8..53729ab 100644
--- a/daemon/StreamlineSetup.cpp
+++ b/daemon/StreamlineSetup.cpp
@@ -14,11 +14,8 @@
14#include <arpa/inet.h> 14#include <arpa/inet.h>
15#include <sys/socket.h> 15#include <sys/socket.h>
16#include <netinet/in.h> 16#include <netinet/in.h>
17#include "XMLOut.h"
18#include "Sender.h" 17#include "Sender.h"
19#include "Logging.h" 18#include "Logging.h"
20#include "XMLReader.h"
21#include "RequestXML.h"
22#include "OlyUtility.h" 19#include "OlyUtility.h"
23#include "SessionData.h" 20#include "SessionData.h"
24#include "CapturedXML.h" 21#include "CapturedXML.h"
@@ -27,15 +24,24 @@
27 24
28extern void handleException(); 25extern void handleException();
29 26
30static const char* TAG_SESSION = "session"; 27static const char* TAG_SESSION = "session";
31static const char* TAG_CONFIGURATIONS = "configurations"; 28static const char* TAG_REQUEST = "request";
29static const char* TAG_CONFIGURATIONS = "configurations";
30
31static const char* ATTR_PROTOCOL = "protocol";
32static const char* ATTR_EVENTS = "events";
33static const char* ATTR_CONFIGURATION = "configuration";
34static const char* ATTR_COUNTERS = "counters";
35static const char* ATTR_SESSION = "session";
36static const char* ATTR_CAPTURED = "captured";
37static const char* ATTR_DEFAULTS = "defaults";
32 38
33StreamlineSetup::StreamlineSetup(OlySocket* s) { 39StreamlineSetup::StreamlineSetup(OlySocket* s) {
34 bool ready = false; 40 bool ready = false;
35 char *data = NULL; 41 char* data = NULL;
36 int type; 42 int type;
37 43
38 socket = s; 44 mSocket = s;
39 mSessionXML = NULL; 45 mSessionXML = NULL;
40 46
41 // Receive commands from Streamline (master) 47 // Receive commands from Streamline (master)
@@ -73,13 +79,14 @@ StreamlineSetup::StreamlineSetup(OlySocket* s) {
73 handleException(); 79 handleException();
74 } 80 }
75 81
76 delete(data); 82 free(data);
77 } 83 }
78} 84}
79 85
80StreamlineSetup::~StreamlineSetup() { 86StreamlineSetup::~StreamlineSetup() {
81 if (mSessionXML) 87 if (mSessionXML) {
82 free(mSessionXML); 88 free(mSessionXML);
89 }
83} 90}
84 91
85char* StreamlineSetup::readCommand(int* command) { 92char* StreamlineSetup::readCommand(int* command) {
@@ -88,7 +95,7 @@ char* StreamlineSetup::readCommand(int* command) {
88 int response, length; 95 int response, length;
89 96
90 // receive type 97 // receive type
91 response = socket->receiveNBytes(&type, sizeof(type)); 98 response = mSocket->receiveNBytes(&type, sizeof(type));
92 99
93 // After receiving a single byte, we are no longer waiting on a command 100 // After receiving a single byte, we are no longer waiting on a command
94 gSessionData->mWaitingOnCommand = false; 101 gSessionData->mWaitingOnCommand = false;
@@ -99,7 +106,7 @@ char* StreamlineSetup::readCommand(int* command) {
99 } 106 }
100 107
101 // receive length 108 // receive length
102 response = socket->receiveNBytes((char*)&length, sizeof(length)); 109 response = mSocket->receiveNBytes((char*)&length, sizeof(length));
103 if (response < 0) { 110 if (response < 0) {
104 logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect"); 111 logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
105 handleException(); 112 handleException();
@@ -119,7 +126,7 @@ char* StreamlineSetup::readCommand(int* command) {
119 } 126 }
120 127
121 // receive data 128 // receive data
122 response = socket->receiveNBytes(data, length); 129 response = mSocket->receiveNBytes(data, length);
123 if (response < 0) { 130 if (response < 0) {
124 logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect"); 131 logg->logError(__FILE__, __LINE__, "Target error: Unexpected socket disconnect");
125 handleException(); 132 handleException();
@@ -135,29 +142,31 @@ char* StreamlineSetup::readCommand(int* command) {
135} 142}
136 143
137void StreamlineSetup::handleRequest(char* xml) { 144void StreamlineSetup::handleRequest(char* xml) {
138 RequestXML request(xml); 145 mxml_node_t *tree, *node;
139 146
140 if (request.parameters.protocol) { 147 tree = mxmlLoadString(NULL, xml, MXML_NO_CALLBACK);
148 if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_PROTOCOL, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_PROTOCOL), false)) {
141 sendProtocol(); 149 sendProtocol();
142 logg->logMessage("Sent protocol xml response"); 150 logg->logMessage("Sent protocol xml response");
143 } else if (request.parameters.events) { 151 } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_EVENTS, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_EVENTS), false)) {
144 sendEvents(); 152 sendEvents();
145 logg->logMessage("Sent events xml response"); 153 logg->logMessage("Sent events xml response");
146 } else if (request.parameters.configuration) { 154 } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_CONFIGURATION, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_CONFIGURATION), false)) {
147 sendConfiguration(); 155 sendConfiguration();
148 logg->logMessage("Sent configuration xml response"); 156 logg->logMessage("Sent configuration xml response");
149 } else if (request.parameters.counters) { 157 } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_COUNTERS, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_COUNTERS), false)) {
150 sendCounters(); 158 sendCounters();
151 logg->logMessage("Sent counters xml response"); 159 logg->logMessage("Sent counters xml response");
152 } else if (request.parameters.session) { 160 } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_SESSION, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_SESSION), false)) {
153 sendData(mSessionXML, strlen(mSessionXML), RESPONSE_XML); 161 sendData(mSessionXML, strlen(mSessionXML), RESPONSE_XML);
154 logg->logMessage("Sent session xml response"); 162 logg->logMessage("Sent session xml response");
155 } else if (request.parameters.captured) { 163 } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_CAPTURED, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_CAPTURED), false)) {
156 CapturedXML capturedXML; 164 CapturedXML capturedXML;
157 const char* capturedText = capturedXML.getXML(); 165 char* capturedText = capturedXML.getXML();
158 sendData(capturedText, strlen(capturedText), RESPONSE_XML); 166 sendData(capturedText, strlen(capturedText), RESPONSE_XML);
167 free(capturedText);
159 logg->logMessage("Sent captured xml response"); 168 logg->logMessage("Sent captured xml response");
160 } else if (request.parameters.defaults) { 169 } else if ((node = mxmlFindElement(tree, tree, TAG_REQUEST, ATTR_DEFAULTS, NULL, MXML_DESCEND_FIRST)) && util->stringToBool(mxmlElementGetAttr(node, ATTR_DEFAULTS), false)) {
161 sendDefaults(); 170 sendDefaults();
162 logg->logMessage("Sent default configuration xml response"); 171 logg->logMessage("Sent default configuration xml response");
163 } else { 172 } else {
@@ -165,67 +174,60 @@ void StreamlineSetup::handleRequest(char* xml) {
165 sendData(error, strlen(error), RESPONSE_NAK); 174 sendData(error, strlen(error), RESPONSE_NAK);
166 logg->logMessage("Received unknown request:\n%s", xml); 175 logg->logMessage("Received unknown request:\n%s", xml);
167 } 176 }
177
178 mxmlDelete(tree);
168} 179}
169 180
170typedef enum {UNKNOWN, SESSION_XML, CONFIGURATION_XML} delivery_type_t;
171void StreamlineSetup::handleDeliver(char* xml) { 181void StreamlineSetup::handleDeliver(char* xml) {
172 delivery_type_t type = UNKNOWN; 182 mxml_node_t *tree;
173 183
174 // Determine xml type 184 // Determine xml type
175 XMLReader reader(xml); 185 tree = mxmlLoadString(NULL, xml, MXML_NO_CALLBACK);
176 char * tag = reader.nextTag(); 186 if (mxmlFindElement(tree, tree, TAG_SESSION, NULL, NULL, MXML_DESCEND_FIRST)) {
177 while(tag != 0) { 187 // Session XML
178 if (strcmp(tag, TAG_SESSION) == 0) { 188 gSessionData->parseSessionXML(xml);
179 type = SESSION_XML; 189
180 break; 190 // Save xml
181 } else if (strcmp(tag, TAG_CONFIGURATIONS) == 0) { 191 mSessionXML = strdup(xml);
182 type = CONFIGURATION_XML; 192 if (mSessionXML == NULL) {
183 break; 193 logg->logError(__FILE__, __LINE__, "malloc failed for size %d", strlen(xml) + 1);
194 handleException();
184 } 195 }
185 tag = reader.nextTag(); 196 sendData(NULL, 0, RESPONSE_ACK);
197 logg->logMessage("Received session xml");
198 } else if (mxmlFindElement(tree, tree, TAG_CONFIGURATIONS, NULL, NULL, MXML_DESCEND_FIRST)) {
199 // Configuration XML
200 writeConfiguration(xml);
201 sendData(NULL, 0, RESPONSE_ACK);
202 logg->logMessage("Received configuration xml");
203 } else {
204 // Unknown XML
205 logg->logMessage("Received unknown XML delivery type");
206 sendData(NULL, 0, RESPONSE_NAK);
186 } 207 }
187 208
188 switch (type) { 209 mxmlDelete(tree);
189 case UNKNOWN:
190 logg->logMessage("Received unknown delivery type: %d", type);
191 sendData(NULL, 0, RESPONSE_NAK);
192 break;
193 case SESSION_XML:
194 // Parse the session xml
195 gSessionData->parseSessionXML(xml);
196
197 // Save xml
198 mSessionXML = strdup(xml);
199 if (mSessionXML == NULL) {
200 logg->logError(__FILE__, __LINE__, "malloc failed for size %d", strlen(xml) + 1);
201 handleException();
202 }
203 sendData(NULL, 0, RESPONSE_ACK);
204 logg->logMessage("Received session xml");
205 break;
206 case CONFIGURATION_XML:
207 writeConfiguration(xml);
208 sendData(NULL, 0, RESPONSE_ACK);
209 logg->logMessage("Received configuration xml");
210 break;
211 }
212} 210}
213 211
214void StreamlineSetup::sendData(const char* data, int length, int type) { 212void StreamlineSetup::sendData(const char* data, int length, int type) {
215 socket->send((char*)&type, 1); 213 mSocket->send((char*)&type, 1);
216 socket->send((char*)&length, sizeof(length)); 214 mSocket->send((char*)&length, sizeof(length));
217 socket->send((char*)data, length); 215 mSocket->send((char*)data, length);
218} 216}
219 217
220void StreamlineSetup::sendProtocol() { 218void StreamlineSetup::sendProtocol() {
221 XMLOut out; 219 mxml_node_t *xml;
222 out.xmlHeader(); 220 mxml_node_t *protocol;
223 221
224 out.startElement("protocol"); 222 xml = mxmlNewXML("1.0");
225 out.attributeInt("version", PROTOCOL_VERSION); 223 protocol = mxmlNewElement(xml, "protocol");
226 out.endElement("protocol"); 224 mxmlElementSetAttrf(protocol, "version", "%d", PROTOCOL_VERSION);
227 225
228 sendString(out.getXmlString(), RESPONSE_XML); 226 char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
227 sendString(string, RESPONSE_XML);
228
229 free(string);
230 mxmlDelete(xml);
229} 231}
230 232
231void StreamlineSetup::sendEvents() { 233void StreamlineSetup::sendEvents() {
@@ -234,8 +236,12 @@ void StreamlineSetup::sendEvents() {
234 char* buffer; 236 char* buffer;
235 unsigned int size = 0; 237 unsigned int size = 0;
236 238
237 util->getApplicationFullPath(path, PATH_MAX); 239 if (gSessionData->mEventsXMLPath) {
238 strncat(path, "events.xml", PATH_MAX - strlen(path) - 1); 240 strncpy(path, gSessionData->mEventsXMLPath, PATH_MAX);
241 } else {
242 util->getApplicationFullPath(path, PATH_MAX);
243 strncat(path, "events.xml", PATH_MAX - strlen(path) - 1);
244 }
239 buffer = util->readFromDisk(path, &size); 245 buffer = util->readFromDisk(path, &size);
240 if (buffer == NULL) { 246 if (buffer == NULL) {
241 logg->logMessage("Unable to locate events.xml, using default"); 247 logg->logMessage("Unable to locate events.xml, using default");
@@ -274,8 +280,10 @@ void StreamlineSetup::sendDefaults() {
274 280
275#include <dirent.h> 281#include <dirent.h>
276void StreamlineSetup::sendCounters() { 282void StreamlineSetup::sendCounters() {
277 XMLOut out;
278 struct dirent *ent; 283 struct dirent *ent;
284 mxml_node_t *xml;
285 mxml_node_t *counters;
286 mxml_node_t *counter;
279 287
280 // counters.xml is simply a file listing of /dev/gator/events 288 // counters.xml is simply a file listing of /dev/gator/events
281 DIR* dir = opendir("/dev/gator/events"); 289 DIR* dir = opendir("/dev/gator/events");
@@ -284,27 +292,29 @@ void StreamlineSetup::sendCounters() {
284 handleException(); 292 handleException();
285 } 293 }
286 294
287 out.xmlHeader(); 295 xml = mxmlNewXML("1.0");
288 out.startElement("counters"); 296 counters = mxmlNewElement(xml, "counters");
289 while ((ent = readdir(dir)) != NULL) { 297 while ((ent = readdir(dir)) != NULL) {
290 // skip hidden files, current dir, and parent dir 298 // skip hidden files, current dir, and parent dir
291 if (ent->d_name[0] == '.') 299 if (ent->d_name[0] == '.')
292 continue; 300 continue;
293 out.startElement("counter"); 301 counter = mxmlNewElement(counters, "counter");
294 out.attributeString("name", ent->d_name); 302 mxmlElementSetAttr(counter, "name", ent->d_name);
295 out.endElement("counter");
296 } 303 }
297 out.endElement("counters");
298 closedir (dir); 304 closedir (dir);
299 305
300 sendString(out.getXmlString(), RESPONSE_XML); 306 char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB);
307 sendString(string, RESPONSE_XML);
308
309 free(string);
310 mxmlDelete(xml);
301} 311}
302 312
303void StreamlineSetup::writeConfiguration(char* xml) { 313void StreamlineSetup::writeConfiguration(char* xml) {
304 char* path = (char*)malloc(PATH_MAX); 314 char* path = (char*)malloc(PATH_MAX);
305 315
306 if (gSessionData->configurationXMLPath) { 316 if (gSessionData->mConfigurationXMLPath) {
307 strncpy(path, gSessionData->configurationXMLPath, PATH_MAX); 317 strncpy(path, gSessionData->mConfigurationXMLPath, PATH_MAX);
308 } else { 318 } else {
309 util->getApplicationFullPath(path, PATH_MAX); 319 util->getApplicationFullPath(path, PATH_MAX);
310 strncat(path, "configuration.xml", PATH_MAX - strlen(path) - 1); 320 strncat(path, "configuration.xml", PATH_MAX - strlen(path) - 1);
diff --git a/daemon/StreamlineSetup.h b/daemon/StreamlineSetup.h
index 10327e0..c46ae08 100644
--- a/daemon/StreamlineSetup.h
+++ b/daemon/StreamlineSetup.h
@@ -26,8 +26,8 @@ public:
26 StreamlineSetup(OlySocket *socket); 26 StreamlineSetup(OlySocket *socket);
27 ~StreamlineSetup(); 27 ~StreamlineSetup();
28private: 28private:
29 int numConnections; 29 int mNumConnections;
30 OlySocket* socket; 30 OlySocket* mSocket;
31 char* mSessionXML; 31 char* mSessionXML;
32 32
33 char* readCommand(int*); 33 char* readCommand(int*);
diff --git a/daemon/XMLOut.cpp b/daemon/XMLOut.cpp
deleted file mode 100644
index c194fc0..0000000
--- a/daemon/XMLOut.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
1/**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved.
3 *
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 <stdio.h>
10#include <string.h>
11#include <stdarg.h>
12#include "XMLOut.h"
13
14XMLOut::XMLOut() {
15 indent = 0;
16 incomplete = false;
17 xml_string[0] = 0;
18}
19
20XMLOut::~XMLOut() {
21}
22
23void XMLOut::writeTabs() {
24 for (int i = 0; i < indent; i++) {
25 writeData(" ");
26 }
27}
28
29void XMLOut::encodeAttributeData(const char* data) {
30 if (data) {
31 while (*data) {
32 char ch = *data++;
33
34 if (ch == '<') {
35 writeData("&lt;");
36 } else if (ch == '>') {
37 writeData("&gt;");
38 } else if (ch == '&') {
39 writeData("&amp;");
40 } else if (ch == '"') {
41 writeData("&quot;");
42 } else if (ch == '\'') {
43 writeData("&apos;");
44 } else if (ch >= ' ' && ch <= '~') {
45 writeData("%c",ch);
46 } else {
47 writeData("&#%u;",(unsigned int)ch);
48 }
49 }
50 }
51}
52
53void XMLOut::writeData(const char *format, ...) {
54 va_list ap;
55
56 va_start(ap, format);
57 vsnprintf(temp_buffer, sizeof(temp_buffer), format, ap);
58 va_end(ap);
59
60 strncat(xml_string, temp_buffer, sizeof(xml_string) - strlen(xml_string) - 1);
61}
62
63const XMLOut & XMLOut::xmlHeader(void) {
64 writeData("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
65 incomplete = false;
66 return *this;
67}
68
69const XMLOut & XMLOut::comment(const char* text, const bool newline) {
70 if (incomplete) {
71 writeData(">\n");
72 }
73 writeTabs();
74 writeData("<!-- %s -->", text);
75 if (newline) {
76 writeData("\n");
77 }
78 incomplete = false;
79 return *this;
80}
81
82const XMLOut & XMLOut::startElement(const char* tag) {
83 if (incomplete) {
84 writeData(">\n");
85 }
86 writeTabs();
87 writeData("<%s", tag);
88 incomplete = true;
89 indent++;
90 return *this;
91}
92
93const XMLOut & XMLOut::startElement(const char* tag, int index) {
94 if (incomplete) {
95 writeData(">\n");
96 }
97 writeTabs();
98 writeData("<!-- %d -->", index);
99 writeData("<%s", tag);
100 incomplete = true;
101 indent++;
102 return *this;
103}
104
105const XMLOut & XMLOut::endElement(const char* tag) {
106 indent--;
107 if (indent < 0) {
108 indent = 0;
109 }
110 if (incomplete) {
111 writeData("/>\n");
112 incomplete = false;
113 } else {
114 writeTabs();
115 writeData("</%s>\n", tag);
116 }
117 return *this;
118}
119
120const XMLOut & XMLOut::attributeString(const char* name, const char* value) {
121 writeData(" %s=\"", name);
122 encodeAttributeData(value);
123 writeData("\"");
124 return *this;
125}
126
127const XMLOut & XMLOut::attributeInt(const char* name, int value) {
128 writeData(" %s=\"%d\"", name, value);
129 return *this;
130}
131
132const XMLOut & XMLOut::attributeUInt(const char* name, unsigned int value) {
133 writeData(" %s=\"%u\"", name, value);
134 return *this;
135}
136
137const XMLOut & XMLOut::attributeLong(const char* name, long value) {
138 writeData(" %s=\"%ld\"", name, value);
139 return *this;
140}
141
142const XMLOut & XMLOut::attributeULong(const char* name, unsigned long value) {
143 writeData(" %s=\"%lu\"", name, value);
144 return *this;
145}
146
147const XMLOut & XMLOut::attributeLongLong(const char* name, long long value) {
148 writeData(" %s=\"%lld\"", name, value);
149 return *this;
150}
151
152const XMLOut & XMLOut::attributeULongLong(const char* name, unsigned long long value) {
153 writeData(" %s=\"%llu\"", name, value);
154 return *this;
155}
156
157const XMLOut & XMLOut::attributeDouble(const char* name, double value) {
158 writeData(" %s=\"%f\"", name, value);
159 return *this;
160}
161
162const XMLOut & XMLOut::attributeBool(const char* name, bool value) {
163 writeData(" %s=\"%s\"", name, value ? "yes" : "no");
164 return *this;
165}
166
167const XMLOut & XMLOut::attributeHex4(const char* name, int value) {
168 writeData(" %s=\"0x%04x\"", name, value);
169 return *this;
170}
171
172const XMLOut & XMLOut::attributeHex8(const char* name, int value) {
173 writeData(" %s=\"0x%08x\"", name, value);
174 return *this;
175}
diff --git a/daemon/XMLOut.h b/daemon/XMLOut.h
deleted file mode 100644
index 3af253d..0000000
--- a/daemon/XMLOut.h
+++ /dev/null
@@ -1,45 +0,0 @@
1/**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved.
3 *
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#ifndef __XMLOUT_H
10#define __XMLOUT_H
11
12class XMLOut {
13 int indent;
14 bool incomplete;
15 char temp_buffer[4096]; // arbitrarilly large buffer to hold variable arguments
16 char xml_string[64*1024]; // arbitrarilly large buffer to hold an xml file output by the daemon
17
18 void writeTabs();
19 void encodeAttributeData(const char* data);
20 void writeData(const char *format, ...);
21
22public:
23 XMLOut();
24 ~XMLOut();
25 char* getXmlString() {return xml_string;}
26 void clearXmlString() {xml_string[0]=0;}
27 const XMLOut & xmlHeader(void);
28 const XMLOut & comment(const char* text, const bool newline);
29 const XMLOut & startElement(const char* tag);
30 const XMLOut & startElement(const char* tag, int index);
31 const XMLOut & endElement(const char* tag);
32 const XMLOut & attributeString(const char* name, const char* value);
33 const XMLOut & attributeInt(const char* name, int value);
34 const XMLOut & attributeUInt(const char* name, unsigned int value);
35 const XMLOut & attributeLong(const char* name, long value);
36 const XMLOut & attributeULong(const char* name, unsigned long value);
37 const XMLOut & attributeLongLong(const char* name, long long value);
38 const XMLOut & attributeULongLong(const char* name, unsigned long long value);
39 const XMLOut & attributeDouble(const char* name, double value);
40 const XMLOut & attributeBool(const char* name, bool value);
41 const XMLOut & attributeHex4(const char* name, int value);
42 const XMLOut & attributeHex8(const char* name, int value);
43};
44
45#endif // __XMLOUT_H
diff --git a/daemon/XMLReader.cpp b/daemon/XMLReader.cpp
deleted file mode 100644
index 77c76e2..0000000
--- a/daemon/XMLReader.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
1/**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved.
3 *
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 <string.h>
10#include <stdlib.h>
11#include <ctype.h>
12#include "XMLReader.h"
13extern void handleException();
14
15XMLReader::XMLReader(const char* xmlstring) {
16 mPtr = (char*)xmlstring;
17 mNoMore = false;
18 mFirstTime = true;
19}
20
21XMLReader::~XMLReader() {
22}
23
24char* XMLReader::nextTag() {
25 static char tag[128]; // arbitrarily set max tag size to 127 characters + nul
26
27 // Check if past the end of the root tag
28 if (mNoMore) return NULL;
29
30 // Find start character
31 mPtr = strchr(mPtr, '<');
32
33 if (mPtr == NULL) return mPtr;
34
35 // Skip tag if it begins with <?
36 if (mPtr[1] == '?') {
37 mPtr++;
38 return nextTag();
39 }
40
41 // Find end of tag name
42 mPtr++;
43 char* end = strchr(mPtr, ' ');
44 if (end == NULL)
45 end = strchr(mPtr, '>');
46 if (end == NULL)
47 return 0;
48
49 // Check if tag has no attributes
50 char* tagend = strchr(mPtr, '>');
51 if (tagend < end) end = tagend;
52
53 // Check the tag name length
54 unsigned int length = (int)end - (int)mPtr;
55 if (length > sizeof(tag) - 1) {
56 // tag name too long, skip it
57 return nextTag();
58 }
59
60 // Return the tag name
61 strncpy(tag, mPtr, length);
62 tag[length] = 0;
63
64 // Mark the root tag
65 if (mFirstTime) {
66 mEndXML[0] = '/';
67 strcpy(&mEndXML[1], tag);
68 mFirstTime = false;
69 } else if (strcmp(tag, mEndXML) == 0) {
70 // End of root tag found
71 mNoMore = true;
72 }
73
74 return tag;
75}
76
77void XMLReader::getAttribute(const char* name, char* value, int maxSize, const char* defValue) {
78 char searchString[128];
79
80 // Set up default
81 strncpy(value, defValue, maxSize - 1);
82 value[maxSize - 1] = 0;
83
84 // Determine search string by ending the name with ="
85 if (strlen(name) > sizeof(searchString) - 3) return;
86 strcpy(searchString, name);
87 strcat(searchString, "=\"");
88
89 // Find the beginning of the attribute's search string
90 char* begin = strstr(mPtr, searchString);
91 if (begin == NULL) return;
92
93 // Find the beginning of the attribute's value
94 begin += strlen(searchString);
95
96 // Find the end of the current tag to make sure the attribute exists within the tag
97 char* endtag = strchr(mPtr, '>');
98 if (endtag < begin) return;
99
100 // Find the end of the attribute's value
101 char* end = strchr(begin, '"');
102 if (end == NULL) return;
103
104 // Determine length
105 int length = (int)end - (int)begin;
106 if (length > maxSize - 1) return;
107
108 strncpy(value, begin, length);
109 value[length] = 0;
110}
111
112int XMLReader::getAttributeAsInteger(const char* name, int defValue) {
113 char value[32];
114 getAttribute(name, value, sizeof(value), "");
115 if (value[0] == 0) return defValue;
116 if (value[0] == '0' && value[1] == 'x') {
117 return (int) strtoul(&value[2], (char**)NULL, 16);
118 }
119 return strtol(value, NULL, 10);
120}
121
122bool XMLReader::getAttributeAsBoolean(const char* name, bool defValue) {
123 char value[32];
124 getAttribute(name, value, sizeof(value), "");
125 if (value[0] == 0) return defValue;
126
127 // Convert to lowercase
128 int i = 0;
129 while (value[i]) {
130 value[i] = tolower(value[i]);
131 i++;
132 }
133
134 if (strcmp(value, "true") == 0 || strcmp(value, "yes") == 0 || strcmp(value, "1") == 0 || strcmp(value, "on") == 0) return true;
135 else if (strcmp(value, "false") == 0 || strcmp(value, "no") == 0 || strcmp(value, "0") == 0 || strcmp(value, "off") == 0) return false;
136 else return defValue;
137}
138
139int XMLReader::getAttributeLength(const char* name) {
140 char searchString[128]; // arbitrarily large amount
141
142 // Determine search string by ending the name with ="
143 if (strlen(name) > sizeof(searchString) - 3) return 0;
144 strcpy(searchString, name);
145 strcat(searchString, "=\"");
146
147 // Find the beginning of the attribute's search string
148 char* begin = strstr(mPtr, searchString);
149 if (begin == NULL) return 0;
150
151 // Find the beginning of the attribute's value
152 begin += strlen(searchString);
153
154 // Find the end of the current tag to make sure the attribute exists within the tag
155 char* endtag = strchr(mPtr, '>');
156 if (endtag < begin) return 0;
157
158 // Find the end of the attribute's value
159 char* end = strchr(begin, '"');
160 if (end == NULL) return 0;
161
162 // Determine length
163 return (int)end - (int)begin;
164}
diff --git a/daemon/XMLReader.h b/daemon/XMLReader.h
deleted file mode 100644
index ac0098a..0000000
--- a/daemon/XMLReader.h
+++ /dev/null
@@ -1,27 +0,0 @@
1/**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved.
3 *
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#ifndef _XMLREADER_H
10#define _XMLREADER_H
11
12class XMLReader {
13public:
14 XMLReader(const char* xmlstring);
15 ~XMLReader();
16 char* nextTag();
17 void getAttribute(const char* name, char* value, int maxSize, const char* defValue);
18 int getAttributeAsInteger(const char* name, int defValue);
19 bool getAttributeAsBoolean(const char* name, bool defValue);
20 int getAttributeLength(const char* name);
21private:
22 char* mPtr;
23 bool mFirstTime, mNoMore;
24 char mEndXML[128];
25};
26
27#endif // _XMLREADER_H
diff --git a/daemon/configuration.xml b/daemon/configuration.xml
index 0f91065..9d083d5 100644
--- a/daemon/configuration.xml
+++ b/daemon/configuration.xml
@@ -1,39 +1,51 @@
1<?xml version="1.0" encoding='UTF-8'?> 1<?xml version="1.0" encoding='UTF-8'?>
2<configurations version="1"> 2<configurations version="1" revision="1">
3 <configuration counter="ARM_ARM11_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" description="The number of core clock cycles"/> 3 <configuration counter="ARM_ARM11_ccnt" title="Clock" name="Cycles" per_cpu="yes" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
4 <configuration counter="ARM_ARM11_cnt0" event="0x7" title="Instruction" name="Executed" color="0x80008000" per_cpu="yes" description="Instructions executed"/> 4 <configuration counter="ARM_ARM11_cnt0" event="0x7" title="Instruction" name="Executed" per_cpu="yes" alias="InstructionsExecuted" description="Instructions executed"/>
5 <configuration counter="ARM_ARM11_cnt1" event="0xa" title="Cache" name="Data miss" color="0x80C92211" per_cpu="yes" description="Data cache miss, not including Cache Operations"/> 5 <configuration counter="ARM_ARM11_cnt1" event="0xb" title="Cache" name="Data miss" per_cpu="yes" alias="L1Miss" description="Data cache miss, not including Cache Operations"/>
6 <configuration counter="ARM_ARM11MPCore_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" description="The number of core clock cycles"/> 6 <configuration counter="ARM_ARM11MPCore_ccnt" title="Clock" name="Cycles" per_cpu="yes" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
7 <configuration counter="ARM_ARM11MPCore_cnt0" event="0x08" title="Core" name="Instructions" color="0x80008000" per_cpu="yes" description="Instructions executed"/> 7 <configuration counter="ARM_ARM11MPCore_cnt0" event="0x08" title="Core" name="Instructions" per_cpu="yes" alias="InstructionsExecuted" description="Instructions executed"/>
8 <configuration counter="ARM_ARM11MPCore_cnt1" event="0x0b" title="Cache" name="Data read miss" color="0x000080FF" per_cpu="yes" description="Data cache miss, not including Cache Operations"/> 8 <configuration counter="ARM_ARM11MPCore_cnt1" event="0x0b" title="Cache" name="Data read miss" per_cpu="yes" alias="L1Miss" description="Data cache miss, not including Cache Operations"/>
9 <configuration counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" event_based_sampling="yes" description="The number of core clock cycles"/> 9 <configuration counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
10 <configuration counter="ARM_Cortex-A5_cnt0" event="0x8" title="Instruction" name="Executed" color="0x80008000" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/> 10 <configuration counter="ARM_Cortex-A5_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" alias="InstructionsExecuted" description="Instruction architecturally executed"/>
11 <configuration counter="ARM_Cortex-A5_cnt1" event="0x1" title="Cache" name="Instruction refill" color="0x80C92211" per_cpu="yes" event_based_sampling="yes" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/> 11 <configuration counter="ARM_Cortex-A5_cnt1" event="0x1" title="Cache" name="Instruction refill" per_cpu="yes" event_based_sampling="yes" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
12 <configuration counter="ARM_Cortex-A8_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" event_based_sampling="yes" description="The number of core clock cycles"/> 12 <configuration counter="ARM_Cortex-A7_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
13 <configuration counter="ARM_Cortex-A8_cnt0" event="0x8" title="Instruction" name="Executed" color="0x80008000" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/> 13 <configuration counter="ARM_Cortex-A7_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" alias="InstructionsExecuted" description="Instruction architecturally executed"/>
14 <configuration counter="ARM_Cortex-A8_cnt1" event="0x44" title="Cache" name="L2 miss" color="0x80C92211" per_cpu="yes" event_based_sampling="yes" description="Any cacheable miss in the L2 cache"/> 14 <configuration counter="ARM_Cortex-A7_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" alias="BranchMispredicted" description="Branch mispredicted or not predicted"/>
15 <configuration counter="ARM_Cortex-A8_cnt2" event="0x43" title="Cache" name="L1 miss" color="0x80FFC000" per_cpu="yes" event_based_sampling="yes" description="Any accesses to the L2 cache"/> 15 <configuration counter="ARM_Cortex-A7_cnt2" event="0x16" title="Cache" name="L2 data access" per_cpu="yes" event_based_sampling="yes" alias="L1Miss" description="Level 2 data cache access"/>
16 <configuration counter="ARM_Cortex-A8_cnt3" event="0x10" title="Branch" name="Mispredicted" color="0x80FFFF33" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/> 16 <configuration counter="ARM_Cortex-A8_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
17 <configuration counter="ARM_Cortex-A9_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" event_based_sampling="yes" description="The number of core clock cycles"/> 17 <configuration counter="ARM_Cortex-A8_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" alias="InstructionsExecuted" description="Instruction architecturally executed"/>
18 <configuration counter="ARM_Cortex-A9_cnt0" event="0x68" title="Instruction" name="Executed" color="0x80008000" per_cpu="yes" event_based_sampling="yes" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/> 18 <configuration counter="ARM_Cortex-A8_cnt1" event="0x44" title="Cache" name="L2 miss" per_cpu="yes" event_based_sampling="yes" alias="L2Miss" description="Any cacheable miss in the L2 cache"/>
19 <configuration counter="ARM_Cortex-A9_cnt1" event="0x50" title="Cache" name="Coherency miss" color="0x80C92211" per_cpu="yes" event_based_sampling="yes" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor which also miss in all the other Cortex-A9 processors, meaning that the request is sent to the external memory"/> 19 <configuration counter="ARM_Cortex-A8_cnt2" event="0x43" title="Cache" name="L1 miss" per_cpu="yes" event_based_sampling="yes" alias="L1Miss" description="Any accesses to the L2 cache"/>
20 <configuration counter="ARM_Cortex-A9_cnt2" event="0x51" title="Cache" name="Coherency hit" color="0x80FFC000" per_cpu="yes" event_based_sampling="yes" description="Counts the number of coherent linefill requests performed by the Cortex-A9 processor which hit in another Cortex-A9 processor, meaning that the linefill data is fetched directly from the relevant Cortex-A9 cache"/> 20 <configuration counter="ARM_Cortex-A8_cnt3" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" alias="BranchMispredicted" description="Branch mispredicted or not predicted"/>
21 <configuration counter="ARM_Cortex-A9_cnt3" event="0x0c" title="Branch" name="PC change" color="0x809900FF" per_cpu="yes" event_based_sampling="yes" description="Software change of Program Counter, except by an exception, architecturally executed"/> 21 <configuration counter="ARM_Cortex-A9_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
22 <configuration counter="ARM_Cortex-A9_cnt4" event="0x10" title="Branch" name="Mispredicted" color="0x80FFFF33" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/> 22 <configuration counter="ARM_Cortex-A9_cnt0" event="0x68" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" alias="InstructionsExecuted" description="Counts the number of instructions going through the Register Renaming stage. This number is an approximate number of the total number of instructions speculatively executed, and even more approximate of the total number of instructions architecturally executed"/>
23 <configuration counter="ARM_Cortex-A9_cnt5" event="0x0f" title="Fault" name="Unaligned access" color="0x666666" per_cpu="yes" event_based_sampling="yes" description="Unaligned access architecturally executed"/> 23 <configuration counter="ARM_Cortex-A9_cnt1" event="0x06" title="Instruction" name="Memory read" per_cpu="yes" event_based_sampling="yes" alias="MemoryRead" description="Memory-reading instruction architecturally executed"/>
24 <configuration counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" color="0x800084AB" per_cpu="yes" event_based_sampling="yes" description="The number of core clock cycles"/> 24 <configuration counter="ARM_Cortex-A9_cnt2" event="0x07" title="Instruction" name="Memory write" per_cpu="yes" event_based_sampling="yes" alias="MemoryWrite" description="Memory-writing instruction architecturally executed"/>
25 <configuration counter="ARM_Cortex-A15_cnt0" event="0x8" title="Instruction" name="Executed" color="0x80008000" per_cpu="yes" event_based_sampling="yes" description="Instruction architecturally executed"/> 25 <configuration counter="ARM_Cortex-A9_cnt3" event="0x03" title="Cache" name="Data refill" per_cpu="yes" event_based_sampling="yes" alias="DataRefill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
26 <configuration counter="ARM_Cortex-A15_cnt1" event="0x16" title="Cache" name="L2 data access" color="0x80C92211" per_cpu="yes" event_based_sampling="yes" description="Level 2 data cache access"/> 26 <configuration counter="ARM_Cortex-A9_cnt4" event="0x04" title="Cache" name="Data access" per_cpu="yes" event_based_sampling="yes" alias="DataAccess" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
27 <configuration counter="ARM_Cortex-A15_cnt2" event="0x10" title="Branch" name="Mispredicted" color="0x80FFFF33" per_cpu="yes" event_based_sampling="yes" description="Branch mispredicted or not predicted"/> 27 <configuration counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
28 <configuration counter="ARM_Cortex-A15_cnt3" event="0x19" title="Bus" name="Access" color="0x809900FF" per_cpu="yes" event_based_sampling="yes" description=""/> 28 <configuration counter="ARM_Cortex-A15_cnt0" event="0x8" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" alias="InstructionsExecuted" description="Instruction architecturally executed"/>
29 <configuration counter="Linux_irq_irq" title="Interrupts" name="IRQ" color="0x805050F4" per_cpu="yes" description="Linux IRQ taken"/> 29 <configuration counter="ARM_Cortex-A15_cnt1" event="0x16" title="Cache" name="L2 data access" per_cpu="yes" event_based_sampling="yes" alias="L1Miss" description="Level 2 data cache access"/>
30 <configuration counter="Linux_irq_softirq" title="Interrupts" name="SoftIRQ" color="0x80FF9000" per_cpu="yes" description="Linux SoftIRQ taken"/> 30 <configuration counter="ARM_Cortex-A15_cnt2" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" alias="BranchMispredicted" description="Branch mispredicted or not predicted"/>
31 <configuration counter="Linux_block_rq_wr" title="Disk IO" name="Write" color="0x80FF4020" description="Disk IO Bytes Written"/> 31 <configuration counter="ARM_Cortex-A15_cnt3" event="0x19" title="Bus" name="Access" per_cpu="yes" event_based_sampling="yes" description=""/>
32 <configuration counter="Linux_block_rq_rd" title="Disk IO" name="Read" color="0x800090FF" description="Disk IO Bytes Read"/> 32 <configuration counter="Scorpion_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
33 <configuration counter="Linux_meminfo_memused" title="Memory" name="Used" color="0x800084ab" operation="maximum" description="Total used memory size"/> 33 <configuration counter="Scorpion_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" alias="InstructionsExecuted" description="Instruction architecturally executed"/>
34 <configuration counter="Linux_meminfo_memfree" title="Memory" name="Free" color="0x80e9e9e9" operation="maximum" description="Available memory size"/> 34 <configuration counter="Scorpion_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" alias="BranchMispredicted" description="Branch mispredicted or not predicted"/>
35 <configuration counter="Linux_net_rx" title="Network" name="Receive" color="0x805050F4" description="Receive network traffic, excluding effect from Streamline"/> 35 <configuration counter="ScorpionMP_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
36 <configuration counter="Linux_net_tx" title="Network" name="Transmit" color="0x80FF9000" description="Transmit network traffic, excluding effect from Streamline"/> 36 <configuration counter="ScorpionMP_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" alias="InstructionsExecuted" description="Instruction architecturally executed"/>
37 <configuration counter="Linux_cpuload_system" title="CPU Load" name="System" color="0x80FF0000" description="Scheduler CPU Load of System Behavior"/> 37 <configuration counter="ScorpionMP_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" alias="BranchMispredicted" description="Branch mispredicted or not predicted"/>
38 <configuration counter="Linux_cpuload_user" title="CPU Load" name="User" color="0x8000FF00" description="Scheduler CPU Load of User Application"/> 38 <configuration counter="Krait_ccnt" title="Clock" name="Cycles" per_cpu="yes" event_based_sampling="yes" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
39 <configuration counter="Krait_cnt0" event="0x08" title="Instruction" name="Executed" per_cpu="yes" event_based_sampling="yes" alias="InstructionsExecuted" description="Instruction architecturally executed"/>
40 <configuration counter="Krait_cnt1" event="0x10" title="Branch" name="Mispredicted" per_cpu="yes" event_based_sampling="yes" alias="BranchMispredicted" description="Branch mispredicted or not predicted"/>
41 <configuration counter="Linux_block_rq_wr" title="Disk IO" name="Write" units="B" description="Disk IO Bytes Written"/>
42 <configuration counter="Linux_block_rq_rd" title="Disk IO" name="Read" units="B" description="Disk IO Bytes Read"/>
43 <configuration counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, excluding effect from Streamline"/>
44 <configuration counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, excluding effect from Streamline"/>
45 <configuration counter="Linux_cpuload_system" title="CPU Load" name="System" description="Scheduler CPU Load of System Behavior"/>
46 <configuration counter="Linux_cpuload_user" title="CPU Load" name="User" description="Scheduler CPU Load of User Application"/>
47 <configuration counter="Linux_meminfo_memused" title="Memory" name="Used" display="maximum" units="B" average_selection="yes" description="Total used memory size"/>
48 <configuration counter="Linux_meminfo_memfree" title="Memory" name="Free" display="minimum" units="B" average_selection="yes" description="Available memory size"/>
49 <configuration counter="Linux_power_cpu_freq" title="Clock" name="DVFS" per_cpu="yes" display="maximum" units="Hz" average_selection="yes" description="Target frequency of the CPU"/>
50 <configuration counter="L2C-310_cnt0" event="0x1" title="L2 Cache" name="CO" description="Eviction, CastOut, of a line from the L2 cache"/>
39</configurations> 51</configurations>
diff --git a/daemon/events-ARM11.xml b/daemon/events-ARM11.xml
index 5742271..c9d188f 100644
--- a/daemon/events-ARM11.xml
+++ b/daemon/events-ARM11.xml
@@ -4,18 +4,18 @@
4 <counter name="ARM_ARM11_cnt2"/> 4 <counter name="ARM_ARM11_cnt2"/>
5 </counter_set> 5 </counter_set>
6 <category name="ARM11" counter_set="ARM_ARM11_cntX" per_cpu="yes"> 6 <category name="ARM11" counter_set="ARM_ARM11_cntX" per_cpu="yes">
7 <event counter="ARM_ARM11_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/> 7 <event counter="ARM_ARM11_ccnt" title="Clock" name="Cycles" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
8 <event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/> 8 <event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/>
9 <event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/> 9 <event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/>
10 <event event="0x02" title="Pipeline" name="Data stall" description="Stall because of a data dependency"/> 10 <event event="0x02" title="Pipeline" name="Data stall" description="Stall because of a data dependency"/>
11 <event event="0x03" title="Cache" name="Inst micro TLB miss" description="Instruction MicroTLB miss (unused on ARM1156)"/> 11 <event event="0x03" title="Cache" name="Inst micro TLB miss" description="Instruction MicroTLB miss (unused on ARM1156)"/>
12 <event event="0x04" title="Cache" name="Data micro TLB miss" description="Data MicroTLB miss (unused on ARM1156)"/> 12 <event event="0x04" title="Cache" name="Data micro TLB miss" description="Data MicroTLB miss (unused on ARM1156)"/>
13 <event event="0x05" title="Branch" name="Instruction executed" description="Branch instruction executed, branch might or might not have changed program flow"/> 13 <event event="0x05" title="Branch" name="Instruction executed" description="Branch instruction executed, branch might or might not have changed program flow"/>
14 <event event="0x06" title="Branch" name="Mispredicted" description="Branch mis-predicted"/> 14 <event event="0x06" title="Branch" name="Mispredicted" alias="BranchMispredicted" description="Branch mis-predicted"/>
15 <event event="0x07" title="Instruction" name="Executed" description="Instructions executed"/> 15 <event event="0x07" title="Instruction" name="Executed" alias="InstructionsExecuted" description="Instructions executed"/>
16 <event event="0x09" title="Cache" name="Data access" description="Data cache access, not including Cache operations"/> 16 <event event="0x09" title="Cache" name="Data access" description="Data cache access, not including Cache operations"/>
17 <event event="0x0a" title="Cache" name="Data all access" description="Data cache access, not including Cache Operations regardless of whether or not the location is cacheable"/> 17 <event event="0x0a" title="Cache" name="Data all access" description="Data cache access, not including Cache Operations regardless of whether or not the location is cacheable"/>
18 <event event="0x0b" title="Cache" name="Data miss" description="Data cache miss, not including Cache Operations"/> 18 <event event="0x0b" title="Cache" name="Data miss" alias="L1Miss" description="Data cache miss, not including Cache Operations"/>
19 <event event="0x0c" title="Cache" name="Write-back" description="Data cache write-back"/> 19 <event event="0x0c" title="Cache" name="Write-back" description="Data cache write-back"/>
20 <event event="0x0d" title="Program Counter" name="SW change" description="Software changed the PC"/> 20 <event event="0x0d" title="Program Counter" name="SW change" description="Software changed the PC"/>
21 <event event="0x0f" title="Cache " name="TLB miss" description="Main TLB miss (unused on ARM1156)"/> 21 <event event="0x0f" title="Cache " name="TLB miss" description="Main TLB miss (unused on ARM1156)"/>
diff --git a/daemon/events-ARM11MPCore.xml b/daemon/events-ARM11MPCore.xml
index 6da9ecb..74a29e6 100644
--- a/daemon/events-ARM11MPCore.xml
+++ b/daemon/events-ARM11MPCore.xml
@@ -4,7 +4,7 @@
4 <counter name="ARM_ARM11MPCore_cnt2"/> 4 <counter name="ARM_ARM11MPCore_cnt2"/>
5 </counter_set> 5 </counter_set>
6 <category name="ARM11MPCore" counter_set="ARM_ARM11MPCore_cntX" per_cpu="yes"> 6 <category name="ARM11MPCore" counter_set="ARM_ARM11MPCore_cntX" per_cpu="yes">
7 <event counter="ARM_ARM11MPCore_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/> 7 <event counter="ARM_ARM11MPCore_ccnt" title="Clock" name="Cycles" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
8 <event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/> 8 <event event="0x00" title="Cache" name="Inst miss" description="Instruction cache miss to a cacheable location, which requires a fetch from external memory"/>
9 <event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/> 9 <event event="0x01" title="Pipeline" name="Instruction stall" description="Stall because instruction buffer cannot deliver an instruction"/>
10 <event event="0x02" title="Pipeline" name="Data stall" description="Stall because of a data dependency"/> 10 <event event="0x02" title="Pipeline" name="Data stall" description="Stall because of a data dependency"/>
@@ -12,11 +12,11 @@
12 <event event="0x04" title="Cache" name="Data micro TLB miss" description="Data MicroTLB miss (unused on ARM1156)"/> 12 <event event="0x04" title="Cache" name="Data micro TLB miss" description="Data MicroTLB miss (unused on ARM1156)"/>
13 <event event="0x05" title="Branch" name="Instruction executed" description="Branch instructions executed, branch might or might not have changed program flow"/> 13 <event event="0x05" title="Branch" name="Instruction executed" description="Branch instructions executed, branch might or might not have changed program flow"/>
14 <event event="0x06" title="Branch" name="Not predicted" description="Branch not predicted"/> 14 <event event="0x06" title="Branch" name="Not predicted" description="Branch not predicted"/>
15 <event event="0x07" title="Branch" name="Mispredicted" description="Branch mispredicted"/> 15 <event event="0x07" title="Branch" name="Mispredicted" alias="BranchMispredicted" description="Branch mispredicted"/>
16 <event event="0x08" title="Core" name="Instructions" description="Instructions executed"/> 16 <event event="0x08" title="Core" name="Instructions" alias="InstructionsExecuted" description="Instructions executed"/>
17 <event event="0x09" title="Core" name="Folded Instructions" description="Folded instructions executed"/> 17 <event event="0x09" title="Core" name="Folded Instructions" description="Folded instructions executed"/>
18 <event event="0x0a" title="Cache" name="Data read access" description="Data cache read access, not including cache operations"/> 18 <event event="0x0a" title="Cache" name="Data read access" description="Data cache read access, not including cache operations"/>
19 <event event="0x0b" title="Cache" name="Data read miss" description="Data cache miss, not including Cache Operations"/> 19 <event event="0x0b" title="Cache" name="Data read miss" alias="L1Miss" description="Data cache miss, not including Cache Operations"/>
20 <event event="0x0c" title="Cache" name="Data write access" description="Data cache write access"/> 20 <event event="0x0c" title="Cache" name="Data write access" description="Data cache write access"/>
21 <event event="0x0d" title="Cache" name="Data write miss" description="Data cache write miss"/> 21 <event event="0x0d" title="Cache" name="Data write miss" description="Data cache write miss"/>
22 <event event="0x0e" title="Cache" name="Data line eviction" description="Data cache line eviction, not including cache operations"/> 22 <event event="0x0e" title="Cache" name="Data line eviction" description="Data cache line eviction, not including cache operations"/>
@@ -27,4 +27,4 @@
27 <event event="0x13" title="Write Buffer" name="Drains" description="The number of times the Write Buffer was drained because of LSU ordering constraints or CP15 operations (Data Synchronization Barrier command) or Strongly Ordered operation"/> 27 <event event="0x13" title="Write Buffer" name="Drains" description="The number of times the Write Buffer was drained because of LSU ordering constraints or CP15 operations (Data Synchronization Barrier command) or Strongly Ordered operation"/>
28 <event event="0x14" title="Write Buffer" name="Write Merges" description="Buffered write merged in a store buffer slot"/> 28 <event event="0x14" title="Write Buffer" name="Write Merges" description="Buffered write merged in a store buffer slot"/>
29 <event event="0xFF" title="Core" name="Cycle counter" description="An increment each cycle"/> 29 <event event="0xFF" title="Core" name="Cycle counter" description="An increment each cycle"/>
30 </category> \ No newline at end of file 30 </category>
diff --git a/daemon/events-Cortex-A15.xml b/daemon/events-Cortex-A15.xml
index 86a3d17..74c7290 100644
--- a/daemon/events-Cortex-A15.xml
+++ b/daemon/events-Cortex-A15.xml
@@ -7,31 +7,31 @@
7 <counter name="ARM_Cortex-A15_cnt5"/> 7 <counter name="ARM_Cortex-A15_cnt5"/>
8 </counter_set> 8 </counter_set>
9 <category name="Cortex-A15" counter_set="ARM_Cortex-A15_cntX" per_cpu="yes" event_based_sampling="yes"> 9 <category name="Cortex-A15" counter_set="ARM_Cortex-A15_cntX" per_cpu="yes" event_based_sampling="yes">
10 <event counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/> 10 <event counter="ARM_Cortex-A15_ccnt" title="Clock" name="Cycles" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
11 <event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/> 11 <event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/>
12 <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/> 12 <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
13 <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/> 13 <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
14 <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/> 14 <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
15 <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/> 15 <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
16 <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/> 16 <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
17 <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/> 17 <event event="0x08" title="Instruction" name="Executed" alias="InstructionsExecuted" description="Instruction architecturally executed"/>
18 <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/> 18 <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
19 <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/> 19 <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
20 <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/> 20 <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
21 <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/> 21 <event event="0x10" title="Branch" name="Mispredicted" alias="BranchMispredicted" description="Branch mispredicted or not predicted"/>
22 <event event="0x11" title="Cycle" name="Cycle" description=""/> 22 <event event="0x11" title="Cycle" name="Cycle" description=""/>
23 <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/> 23 <event event="0x12" title="Branch" name="Potential prediction" alias="PotentialPrediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
24 <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/> 24 <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
25 <event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/> 25 <event event="0x14" title="Cache" name="L1 inst access" description="Instruction cache access"/>
26 <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/> 26 <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/>
27 <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/> 27 <event event="0x16" title="Cache" name="L2 data access" alias="L1Miss" description="Level 2 data cache access"/>
28 <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/> 28 <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/>
29 <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/> 29 <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/>
30 <event event="0x19" title="Bus" name="Access" description=""/> 30 <event event="0x19" title="Bus" name="Access" description=""/>
31 <event event="0x1a" title="Memory" name="Error" description="Local memory error"/> 31 <event event="0x1a" title="Memory" name="Error" description="Local memory error"/>
32 <event event="0x1b" title="Instruction" name="Speculative" description="Instruction speculatively executed"/> 32 <event event="0x1b" title="Instruction" name="Speculative" description="Instruction speculatively executed"/>
33 <event event="0x1c" title="Memory" name="Translation table" description="Write to translation table base architecturally executed"/> 33 <event event="0x1c" title="Memory" name="Translation table" description="Write to translation table base architecturally executed"/>
34 <event event="0x1d" title="Bus" name="Cycle" description=""/> 34 <event event="0x1d" title="Bus" name="Cycle" description=""/>
35 <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/> 35 <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/>
36 <event event="0x41" title="Cache" name="L1 data write" description="Level 1 data cache access - Write"/> 36 <event event="0x41" title="Cache" name="L1 data write" description="Level 1 data cache access - Write"/>
37 <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/> 37 <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/>
@@ -52,26 +52,25 @@
52 <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/> 52 <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/>
53 <event event="0x64" title="Bus" name="Access" description="Bus access - Normal"/> 53 <event event="0x64" title="Bus" name="Access" description="Bus access - Normal"/>
54 <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/> 54 <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/>
55 <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/> 55 <event event="0x66" title="Memory" name="Read" alias="MemoryRead" description="Data memory access - Read"/>
56 <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/> 56 <event event="0x67" title="Memory" name="Write" alias="MemoryWrite" description="Data memory access - Write"/>
57 <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/> 57 <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/>
58 <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/> 58 <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/>
59 <event event="0x6a" title="Memory" name="Unaligned" description="Unaligned access"/> 59 <event event="0x6a" title="Memory" name="Unaligned" alias="UnalignedAccess" description="Unaligned access"/>
60 <event event="0x6c" title="Intrinsic" name="LDREX" description="Exclusive instruction speculatively executed - LDREX"/> 60 <event event="0x6c" title="Intrinsic" name="LDREX" description="Exclusive instruction speculatively executed - LDREX"/>
61 <event event="0x6d" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/> 61 <event event="0x6d" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/>
62 <event event="0x6e" title="Intrinsic" name="STREX fail" description="Exclusive instruction speculatively executed - STREX fail"/> 62 <event event="0x6e" title="Intrinsic" name="STREX fail" description="Exclusive instruction speculatively executed - STREX fail"/>
63 <event event="0x70" title="Instructions" name="Load" description="Instruction speculatively executed - Load"/> 63 <event event="0x70" title="Instruction" name="Load" description="Instruction speculatively executed - Load"/>
64 <event event="0x71" title="Instructions" name="Store" description="Instruction speculatively executed - Store"/> 64 <event event="0x71" title="Instruction" name="Store" description="Instruction speculatively executed - Store"/>
65 <event event="0x72" title="Instructions" name="Load/Store" description="Instruction speculatively executed - Load or store"/> 65 <event event="0x72" title="Instruction" name="Load/Store" description="Instruction speculatively executed - Load or store"/>
66 <event event="0x73" title="Instructions" name="Integer" description="Instruction speculatively executed - Integer data processing"/> 66 <event event="0x73" title="Instruction" name="Integer" description="Instruction speculatively executed - Integer data processing"/>
67 <event event="0x74" title="Instructions" name="Advanced SIMD" description="Instruction speculatively executed - Advanced SIMD"/> 67 <event event="0x74" title="Instruction" name="Advanced SIMD" description="Instruction speculatively executed - Advanced SIMD"/>
68 <event event="0x75" title="Instructions" name="VFP" description="Instruction speculatively executed - VFP"/> 68 <event event="0x75" title="Instruction" name="VFP" description="Instruction speculatively executed - VFP"/>
69 <event event="0x76" title="Instructions" name="Software change" description="Instruction speculatively executed - Software change of the PC"/> 69 <event event="0x76" title="Instruction" name="Software change" description="Instruction speculatively executed - Software change of the PC"/>
70 <event event="0x78" title="Instructions" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/> 70 <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/>
71 <event event="0x79" title="Instructions" name="Procedure return" description="Branch speculatively executed - Procedure return"/> 71 <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/>
72 <event event="0x7a" title="Instructions" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/> 72 <event event="0x7a" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/>
73 <event event="0x7c" title="Instructions" name="ISB" description="Barrier speculatively executed - ISB"/> 73 <event event="0x7c" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/>
74 <event event="0x7d" title="Instructions" name="DSB" description="Barrier speculatively executed - DSB"/> 74 <event event="0x7d" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/>
75 <event event="0x7e" title="Instructions" name="DMB" description="Barrier speculatively executed - DMB"/> 75 <event event="0x7e" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/>
76 </category> 76 </category>
77 \ No newline at end of file
diff --git a/daemon/events-Cortex-A5.xml b/daemon/events-Cortex-A5.xml
index 3683947..0a70a62 100644
--- a/daemon/events-Cortex-A5.xml
+++ b/daemon/events-Cortex-A5.xml
@@ -3,25 +3,25 @@
3 <counter name="ARM_Cortex-A5_cnt1"/> 3 <counter name="ARM_Cortex-A5_cnt1"/>
4 </counter_set> 4 </counter_set>
5 <category name="Cortex-A5" counter_set="ARM_Cortex-A5_cntX" per_cpu="yes" event_based_sampling="yes"> 5 <category name="Cortex-A5" counter_set="ARM_Cortex-A5_cntX" per_cpu="yes" event_based_sampling="yes">
6 <event counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/> 6 <event counter="ARM_Cortex-A5_ccnt" title="Clock" name="Cycles" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
7 <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/> 7 <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/>
8 <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/> 8 <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
9 <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/> 9 <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
10 <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/> 10 <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
11 <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/> 11 <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
12 <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/> 12 <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
13 <event event="0x06" title="Instruction" name="Memory read" description="Memory-reading instruction architecturally executed"/> 13 <event event="0x06" title="Instruction" name="Memory read" alias="MemoryRead" description="Memory-reading instruction architecturally executed"/>
14 <event event="0x07" title="Instruction" name="Memory write" description="Memory-writing instruction architecturally executed"/> 14 <event event="0x07" title="Instruction" name="Memory write" alias="MemoryWrite" description="Memory-writing instruction architecturally executed"/>
15 <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/> 15 <event event="0x08" title="Instruction" name="Executed" alias="InstructionsExecuted" description="Instruction architecturally executed"/>
16 <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/> 16 <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
17 <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/> 17 <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
18 <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/> 18 <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
19 <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/> 19 <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
20 <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/> 20 <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
21 <event event="0x0e" title="Procedure" name="Return" description="Procedure return, other than exception return, architecturally executed"/> 21 <event event="0x0e" title="Procedure" name="Return" description="Procedure return, other than exception return, architecturally executed"/>
22 <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/> 22 <event event="0x0f" title="Memory" name="Unaligned access" alias="UnalignedAccess" description="Unaligned access architecturally executed"/>
23 <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/> 23 <event event="0x10" title="Branch" name="Mispredicted" alias="BranchMispredicted" description="Branch mispredicted or not predicted"/>
24 <event event="0x12" title="Branch" name="Potential prediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/> 24 <event event="0x12" title="Branch" name="Potential prediction" alias="PotentialPrediction" description="Branch or other change in program flow that could have been predicted by the branch prediction resources of the processor"/>
25 <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/> 25 <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/>
26 <event event="0x14" title="Cache" name="Instruction access" description="Instruction cache access"/> 26 <event event="0x14" title="Cache" name="Instruction access" description="Instruction cache access"/>
27 <event event="0x15" title="Cache" name="Data eviction" description="Data cache eviction"/> 27 <event event="0x15" title="Cache" name="Data eviction" description="Data cache eviction"/>
diff --git a/daemon/events-Cortex-A7.xml b/daemon/events-Cortex-A7.xml
index db9f180..1a55817 100644..100755
--- a/daemon/events-Cortex-A7.xml
+++ b/daemon/events-Cortex-A7.xml
@@ -5,37 +5,37 @@
5 <counter name="ARM_Cortex-A7_cnt3"/> 5 <counter name="ARM_Cortex-A7_cnt3"/>
6 </counter_set> 6 </counter_set>
7 <category name="Cortex-A7" counter_set="ARM_Cortex-A7_cntX" per_cpu="yes" event_based_sampling="yes"> 7 <category name="Cortex-A7" counter_set="ARM_Cortex-A7_cntX" per_cpu="yes" event_based_sampling="yes">
8 <event counter="ARM_Cortex-A7_ccnt" title="Clock" name="Cycles" description="The number of core clock cycles"/> 8 <event counter="ARM_Cortex-A7_ccnt" title="Clock" name="Cycles" alias="ClockCycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/>
9 <event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/> 9 <event event="0x00" title="Software" name="Increment" description="Software increment architecturally executed"/>
10 <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/> 10 <event event="0x01" title="Cache" name="Instruction refill" description="Instruction fetch that causes a refill of at least the level of instruction or unified cache closest to the processor"/>
11 <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/> 11 <event event="0x02" title="Cache" name="Inst TLB refill" description="Instruction fetch that causes a TLB refill of at least the level of TLB closest to the processor"/>
12 <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/> 12 <event event="0x03" title="Cache" name="Data refill" description="Memory Read or Write operation that causes a refill of at least the level of data or unified cache closest to the processor"/>
13 <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/> 13 <event event="0x04" title="Cache" name="Data access" description="Memory Read or Write operation that causes a cache access to at least the level of data or unified cache closest to the processor"/>
14 <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/> 14 <event event="0x05" title="Cache" name="Data TLB refill" description="Memory Read or Write operation that causes a TLB refill of at least the level of TLB closest to the processor"/>
15 <event event="0x06" title="Memory" name="Data Read" description="Data read architecturally executed"/> 15 <event event="0x06" title="Memory" name="Data Read" alias="MemoryRead" description="Data read architecturally executed"/>
16 <event event="0x07" title="Memory" name="Data Write" description="Data write architecturally executed"/> 16 <event event="0x07" title="Memory" name="Data Write" alias="MemoryWrite" description="Data write architecturally executed"/>
17 <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/> 17 <event event="0x08" title="Instruction" name="Executed" alias="InstructionsExecuted" description="Instruction architecturally executed"/>
18 <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/> 18 <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/>
19 <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/> 19 <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/>
20 <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/> 20 <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/>
21 <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/> 21 <event event="0x0c" title="Branch" name="PC change" description="Software change of the Program Counter, except by an exception, architecturally executed"/>
22 <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/> 22 <event event="0x0d" title="Branch" name="Immediate" description="Immediate branch architecturally executed"/>
23 <event event="0x0f" title="Memory" name="Unaligned access" description="Unaligned access architecturally executed"/> 23 <event event="0x0f" title="Memory" name="Unaligned access" alias="UnalignedAccess" description="Unaligned access architecturally executed"/>