diff options
author | Jon Medhurst | 2014-08-01 07:32:58 -0500 |
---|---|---|
committer | Jon Medhurst | 2014-08-01 07:33:21 -0500 |
commit | bc8a84cf0b138a2951679581453da7bd93003db6 (patch) | |
tree | b94eb00f90c24063053d99bea588fbbd493076ef /daemon | |
parent | ba783f1443773505231ac2808c9a3716c3c2f3ae (diff) | |
download | arm-ds5-gator-DS-5.19.tar.gz arm-ds5-gator-DS-5.19.tar.xz arm-ds5-gator-DS-5.19.zip |
gator: Version 5.19DS-5.19-tiDS-5.19
Signed-off-by: Jon Medhurst <tixy@linaro.org>
On branch master
Changes not staged for commit:
modified: README_Streamline.txt
no changes added to commit (use "git add" and/or "git commit -a")
Signed-off-by: Jon Medhurst <tixy@linaro.org>
Diffstat (limited to 'daemon')
63 files changed, 1563 insertions, 685 deletions
diff --git a/daemon/Android.mk b/daemon/Android.mk index 045d028..44c069c 100644 --- a/daemon/Android.mk +++ b/daemon/Android.mk | |||
@@ -3,7 +3,7 @@ include $(CLEAR_VARS) | |||
3 | 3 | ||
4 | XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h) | 4 | XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h) |
5 | 5 | ||
6 | LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions -DETCDIR=\"/etc\" -Ilibsensors | 6 | LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions -pthread -DETCDIR=\"/etc\" -Ilibsensors |
7 | 7 | ||
8 | LOCAL_SRC_FILES := \ | 8 | LOCAL_SRC_FILES := \ |
9 | Buffer.cpp \ | 9 | Buffer.cpp \ |
@@ -15,12 +15,14 @@ LOCAL_SRC_FILES := \ | |||
15 | DynBuf.cpp \ | 15 | DynBuf.cpp \ |
16 | EventsXML.cpp \ | 16 | EventsXML.cpp \ |
17 | ExternalSource.cpp \ | 17 | ExternalSource.cpp \ |
18 | FSDriver.cpp \ | ||
18 | Fifo.cpp \ | 19 | Fifo.cpp \ |
19 | Hwmon.cpp \ | 20 | Hwmon.cpp \ |
20 | KMod.cpp \ | 21 | KMod.cpp \ |
21 | LocalCapture.cpp \ | 22 | LocalCapture.cpp \ |
22 | Logging.cpp \ | 23 | Logging.cpp \ |
23 | main.cpp \ | 24 | main.cpp \ |
25 | MaliVideoDriver.cpp \ | ||
24 | Monitor.cpp \ | 26 | Monitor.cpp \ |
25 | OlySocket.cpp \ | 27 | OlySocket.cpp \ |
26 | OlyUtility.cpp \ | 28 | OlyUtility.cpp \ |
@@ -55,7 +57,7 @@ LOCAL_SRC_FILES := \ | |||
55 | mxml/mxml-set.c \ | 57 | mxml/mxml-set.c \ |
56 | mxml/mxml-string.c | 58 | mxml/mxml-string.c |
57 | 59 | ||
58 | LOCAL_C_INCLUDES := $(LOCAL_PATH) | 60 | LOCAL_C_INCLUDES := $(LOCAL_PATH) |
59 | 61 | ||
60 | LOCAL_MODULE := gatord | 62 | LOCAL_MODULE := gatord |
61 | LOCAL_MODULE_TAGS := optional | 63 | LOCAL_MODULE_TAGS := optional |
diff --git a/daemon/Application.mk b/daemon/Application.mk new file mode 100644 index 0000000..631ba54 --- /dev/null +++ b/daemon/Application.mk | |||
@@ -0,0 +1 @@ | |||
APP_PLATFORM := android-8 | |||
diff --git a/daemon/Buffer.cpp b/daemon/Buffer.cpp index 93557da..dd19f7f 100644 --- a/daemon/Buffer.cpp +++ b/daemon/Buffer.cpp | |||
@@ -15,11 +15,12 @@ | |||
15 | #define mask (mSize - 1) | 15 | #define mask (mSize - 1) |
16 | 16 | ||
17 | enum { | 17 | enum { |
18 | CODE_PEA = 1, | 18 | CODE_PEA = 1, |
19 | CODE_KEYS = 2, | 19 | CODE_KEYS = 2, |
20 | CODE_FORMAT = 3, | 20 | CODE_FORMAT = 3, |
21 | CODE_MAPS = 4, | 21 | CODE_MAPS = 4, |
22 | CODE_COMM = 5, | 22 | CODE_COMM = 5, |
23 | CODE_KEYS_OLD = 6, | ||
23 | }; | 24 | }; |
24 | 25 | ||
25 | // Summary Frame Messages | 26 | // Summary Frame Messages |
@@ -167,7 +168,7 @@ void Buffer::check(const uint64_t time) { | |||
167 | } | 168 | } |
168 | } | 169 | } |
169 | 170 | ||
170 | void Buffer::packInt(int32_t x) { | 171 | void Buffer::packInt(char *const buf, const int size, int &writePos, int32_t x) { |
171 | int packedBytes = 0; | 172 | int packedBytes = 0; |
172 | int more = true; | 173 | int more = true; |
173 | while (more) { | 174 | while (more) { |
@@ -181,11 +182,15 @@ void Buffer::packInt(int32_t x) { | |||
181 | b |= 0x80; | 182 | b |= 0x80; |
182 | } | 183 | } |
183 | 184 | ||
184 | mBuf[(mWritePos + packedBytes) & mask] = b; | 185 | buf[(writePos + packedBytes) & /*mask*/(size - 1)] = b; |
185 | packedBytes++; | 186 | packedBytes++; |
186 | } | 187 | } |
187 | 188 | ||
188 | mWritePos = (mWritePos + packedBytes) & mask; | 189 | writePos = (writePos + packedBytes) & /*mask*/(size - 1); |
190 | } | ||
191 | |||
192 | void Buffer::packInt(int32_t x) { | ||
193 | packInt(mBuf, mSize, mWritePos, x); | ||
189 | } | 194 | } |
190 | 195 | ||
191 | void Buffer::packInt64(int64_t x) { | 196 | void Buffer::packInt64(int64_t x) { |
@@ -320,6 +325,21 @@ void Buffer::keys(const int count, const __u64 *const ids, const int *const keys | |||
320 | check(1); | 325 | check(1); |
321 | } | 326 | } |
322 | 327 | ||
328 | void Buffer::keysOld(const int keyCount, const int *const keys, const int bytes, const char *const buf) { | ||
329 | if (checkSpace((2 + keyCount) * MAXSIZE_PACK32 + bytes)) { | ||
330 | packInt(CODE_KEYS_OLD); | ||
331 | packInt(keyCount); | ||
332 | for (int i = 0; i < keyCount; ++i) { | ||
333 | packInt(keys[i]); | ||
334 | } | ||
335 | writeBytes(buf, bytes); | ||
336 | } else { | ||
337 | logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs"); | ||
338 | handleException(); | ||
339 | } | ||
340 | check(1); | ||
341 | } | ||
342 | |||
323 | void Buffer::format(const int length, const char *const format) { | 343 | void Buffer::format(const int length, const char *const format) { |
324 | if (checkSpace(MAXSIZE_PACK32 + length + 1)) { | 344 | if (checkSpace(MAXSIZE_PACK32 + length + 1)) { |
325 | packInt(CODE_FORMAT); | 345 | packInt(CODE_FORMAT); |
diff --git a/daemon/Buffer.h b/daemon/Buffer.h index 5023777..2de1b97 100644 --- a/daemon/Buffer.h +++ b/daemon/Buffer.h | |||
@@ -54,6 +54,7 @@ public: | |||
54 | // Perf Attrs messages | 54 | // Perf Attrs messages |
55 | void pea(const struct perf_event_attr *const pea, int key); | 55 | void pea(const struct perf_event_attr *const pea, int key); |
56 | void keys(const int count, const __u64 *const ids, const int *const keys); | 56 | void keys(const int count, const __u64 *const ids, const int *const keys); |
57 | void keysOld(const int keyCount, const int *const keys, const int bytes, const char *const buf); | ||
57 | void format(const int length, const char *const format); | 58 | void format(const int length, const char *const format); |
58 | void maps(const int pid, const int tid, const char *const maps); | 59 | void maps(const int pid, const int tid, const char *const maps); |
59 | void comm(const int pid, const int tid, const char *const image, const char *const comm); | 60 | void comm(const int pid, const int tid, const char *const image, const char *const comm); |
@@ -64,6 +65,11 @@ public: | |||
64 | // Prefer a new member to using these functions if possible | 65 | // Prefer a new member to using these functions if possible |
65 | char *getWritePos() { return mBuf + mWritePos; } | 66 | char *getWritePos() { return mBuf + mWritePos; } |
66 | void advanceWrite(int bytes) { mWritePos = (mWritePos + bytes) & /*mask*/(mSize - 1); } | 67 | void advanceWrite(int bytes) { mWritePos = (mWritePos + bytes) & /*mask*/(mSize - 1); } |
68 | static void packInt(char *const buf, const int size, int &writePos, int32_t x); | ||
69 | void packInt(int32_t x); | ||
70 | void packInt64(int64_t x); | ||
71 | void writeBytes(const void *const data, size_t count); | ||
72 | void writeString(const char *const str); | ||
67 | 73 | ||
68 | static void writeLEInt(unsigned char *buf, int v) { | 74 | static void writeLEInt(unsigned char *buf, int v) { |
69 | buf[0] = (v >> 0) & 0xFF; | 75 | buf[0] = (v >> 0) & 0xFF; |
@@ -76,11 +82,6 @@ private: | |||
76 | bool commitReady() const; | 82 | bool commitReady() const; |
77 | bool checkSpace(int bytes); | 83 | bool checkSpace(int bytes); |
78 | 84 | ||
79 | void packInt(int32_t x); | ||
80 | void packInt64(int64_t x); | ||
81 | void writeBytes(const void *const data, size_t count); | ||
82 | void writeString(const char *const str); | ||
83 | |||
84 | const int32_t mCore; | 85 | const int32_t mCore; |
85 | const int32_t mBufType; | 86 | const int32_t mBufType; |
86 | const int mSize; | 87 | const int mSize; |
diff --git a/daemon/CapturedXML.cpp b/daemon/CapturedXML.cpp index cf79b72..4a11415 100644 --- a/daemon/CapturedXML.cpp +++ b/daemon/CapturedXML.cpp | |||
@@ -33,7 +33,7 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) { | |||
33 | captured = mxmlNewElement(xml, "captured"); | 33 | captured = mxmlNewElement(xml, "captured"); |
34 | mxmlElementSetAttr(captured, "version", "1"); | 34 | mxmlElementSetAttr(captured, "version", "1"); |
35 | if (gSessionData->perf.isSetup()) { | 35 | if (gSessionData->perf.isSetup()) { |
36 | mxmlElementSetAttr(captured, "type", "Perf"); | 36 | mxmlElementSetAttr(captured, "type", "Perf"); |
37 | } | 37 | } |
38 | mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION); | 38 | mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION); |
39 | if (includeTime) { // Send the following only after the capture is complete | 39 | if (includeTime) { // Send the following only after the capture is complete |
@@ -66,10 +66,15 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) { | |||
66 | mxml_node_t *const node = mxmlNewElement(counters, "counter"); | 66 | mxml_node_t *const node = mxmlNewElement(counters, "counter"); |
67 | mxmlElementSetAttrf(node, "key", "0x%x", counter.getKey()); | 67 | mxmlElementSetAttrf(node, "key", "0x%x", counter.getKey()); |
68 | mxmlElementSetAttr(node, "type", counter.getType()); | 68 | mxmlElementSetAttr(node, "type", counter.getType()); |
69 | mxmlElementSetAttrf(node, "event", "0x%x", counter.getEvent()); | 69 | if (counter.getEvent() != -1) { |
70 | mxmlElementSetAttrf(node, "event", "0x%x", counter.getEvent()); | ||
71 | } | ||
70 | if (counter.getCount() > 0) { | 72 | if (counter.getCount() > 0) { |
71 | mxmlElementSetAttrf(node, "count", "%d", counter.getCount()); | 73 | mxmlElementSetAttrf(node, "count", "%d", counter.getCount()); |
72 | } | 74 | } |
75 | if (counter.getCores() > 0) { | ||
76 | mxmlElementSetAttrf(node, "cores", "%d", counter.getCores()); | ||
77 | } | ||
73 | } | 78 | } |
74 | } | 79 | } |
75 | 80 | ||
@@ -89,7 +94,7 @@ void CapturedXML::write(char* path) { | |||
89 | 94 | ||
90 | // Set full path | 95 | // Set full path |
91 | snprintf(file, PATH_MAX, "%s/captured.xml", path); | 96 | snprintf(file, PATH_MAX, "%s/captured.xml", path); |
92 | 97 | ||
93 | char* xml = getXML(true); | 98 | char* xml = getXML(true); |
94 | if (util->writeToDisk(file, xml) < 0) { | 99 | if (util->writeToDisk(file, xml) < 0) { |
95 | logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); | 100 | logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); |
diff --git a/daemon/CapturedXML.h b/daemon/CapturedXML.h index efc1e52..ed08c44 100644 --- a/daemon/CapturedXML.h +++ b/daemon/CapturedXML.h | |||
@@ -23,4 +23,4 @@ private: | |||
23 | 23 | ||
24 | const char * mxmlWhitespaceCB(mxml_node_t *node, int where); | 24 | const char * mxmlWhitespaceCB(mxml_node_t *node, int where); |
25 | 25 | ||
26 | #endif //__CAPTURED_XML_H__ | 26 | #endif //__CAPTURED_XML_H__ |
diff --git a/daemon/Child.cpp b/daemon/Child.cpp index ca33561..1901ecc 100644 --- a/daemon/Child.cpp +++ b/daemon/Child.cpp | |||
@@ -26,13 +26,13 @@ | |||
26 | #include "Driver.h" | 26 | #include "Driver.h" |
27 | #include "PerfSource.h" | 27 | #include "PerfSource.h" |
28 | #include "DriverSource.h" | 28 | #include "DriverSource.h" |
29 | #include "UserSpaceSource.h" | ||
30 | #include "ExternalSource.h" | 29 | #include "ExternalSource.h" |
30 | #include "UserSpaceSource.h" | ||
31 | 31 | ||
32 | static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads | 32 | static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads |
33 | static Source *primarySource = NULL; | 33 | static Source *primarySource = NULL; |
34 | static Source *userSpaceSource = NULL; | ||
35 | static Source *externalSource = NULL; | 34 | static Source *externalSource = NULL; |
35 | static Source *userSpaceSource = NULL; | ||
36 | static Sender* sender = NULL; // Shared by Child.cpp and spawned threads | 36 | static Sender* sender = NULL; // Shared by Child.cpp and spawned threads |
37 | Child* child = NULL; // shared by Child.cpp and main.cpp | 37 | Child* child = NULL; // shared by Child.cpp and main.cpp |
38 | 38 | ||
@@ -147,16 +147,16 @@ static void *senderThread(void *) { | |||
147 | prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0); | 147 | prctl(PR_SET_NAME, (unsigned long)&"gatord-sender", 0, 0, 0); |
148 | sem_wait(&haltPipeline); | 148 | sem_wait(&haltPipeline); |
149 | 149 | ||
150 | while (!primarySource->isDone() || (userSpaceSource != NULL && !userSpaceSource->isDone()) || (externalSource != NULL && !externalSource->isDone())) { | 150 | while (!primarySource->isDone() || |
151 | !externalSource->isDone() || | ||
152 | (userSpaceSource != NULL && !userSpaceSource->isDone())) { | ||
151 | sem_wait(&senderSem); | 153 | sem_wait(&senderSem); |
152 | 154 | ||
153 | primarySource->write(sender); | 155 | primarySource->write(sender); |
156 | externalSource->write(sender); | ||
154 | if (userSpaceSource != NULL) { | 157 | if (userSpaceSource != NULL) { |
155 | userSpaceSource->write(sender); | 158 | userSpaceSource->write(sender); |
156 | } | 159 | } |
157 | if (externalSource != NULL) { | ||
158 | externalSource->write(sender); | ||
159 | } | ||
160 | } | 160 | } |
161 | 161 | ||
162 | // write end-of-capture sequence | 162 | // write end-of-capture sequence |
@@ -202,6 +202,10 @@ void Child::initialization() { | |||
202 | void Child::endSession() { | 202 | void Child::endSession() { |
203 | gSessionData->mSessionIsActive = false; | 203 | gSessionData->mSessionIsActive = false; |
204 | primarySource->interrupt(); | 204 | primarySource->interrupt(); |
205 | externalSource->interrupt(); | ||
206 | if (userSpaceSource != NULL) { | ||
207 | userSpaceSource->interrupt(); | ||
208 | } | ||
205 | sem_post(&haltPipeline); | 209 | sem_post(&haltPipeline); |
206 | } | 210 | } |
207 | 211 | ||
@@ -227,9 +231,9 @@ void Child::run() { | |||
227 | 231 | ||
228 | // Set up the driver; must be done after gSessionData->mPerfCounterType[] is populated | 232 | // Set up the driver; must be done after gSessionData->mPerfCounterType[] is populated |
229 | if (!gSessionData->perf.isSetup()) { | 233 | if (!gSessionData->perf.isSetup()) { |
230 | primarySource = new DriverSource(&senderSem, &startProfile); | 234 | primarySource = new DriverSource(&senderSem, &startProfile); |
231 | } else { | 235 | } else { |
232 | primarySource = new PerfSource(&senderSem, &startProfile); | 236 | primarySource = new PerfSource(&senderSem, &startProfile); |
233 | } | 237 | } |
234 | 238 | ||
235 | // Initialize all drivers | 239 | // Initialize all drivers |
@@ -280,11 +284,18 @@ void Child::run() { | |||
280 | thread_creation_success = false; | 284 | thread_creation_success = false; |
281 | } else if (socket && pthread_create(&stopThreadID, NULL, stopThread, NULL)) { | 285 | } else if (socket && pthread_create(&stopThreadID, NULL, stopThread, NULL)) { |
282 | thread_creation_success = false; | 286 | thread_creation_success = false; |
283 | } else if (pthread_create(&senderThreadID, NULL, senderThread, NULL)){ | 287 | } else if (pthread_create(&senderThreadID, NULL, senderThread, NULL)) { |
284 | thread_creation_success = false; | 288 | thread_creation_success = false; |
285 | } | 289 | } |
286 | 290 | ||
287 | if (gSessionData->hwmon.countersEnabled()) { | 291 | externalSource = new ExternalSource(&senderSem); |
292 | if (!externalSource->prepare()) { | ||
293 | logg->logError(__FILE__, __LINE__, "Unable to prepare for capture"); | ||
294 | handleException(); | ||
295 | } | ||
296 | externalSource->start(); | ||
297 | |||
298 | if (gSessionData->hwmon.countersEnabled() || gSessionData->fsDriver.countersEnabled()) { | ||
288 | userSpaceSource = new UserSpaceSource(&senderSem); | 299 | userSpaceSource = new UserSpaceSource(&senderSem); |
289 | if (!userSpaceSource->prepare()) { | 300 | if (!userSpaceSource->prepare()) { |
290 | logg->logError(__FILE__, __LINE__, "Unable to prepare for capture"); | 301 | logg->logError(__FILE__, __LINE__, "Unable to prepare for capture"); |
@@ -292,14 +303,6 @@ void Child::run() { | |||
292 | } | 303 | } |
293 | userSpaceSource->start(); | 304 | userSpaceSource->start(); |
294 | } | 305 | } |
295 | if (access("/tmp/gator", F_OK) == 0) { | ||
296 | externalSource = new ExternalSource(&senderSem); | ||
297 | if (!externalSource->prepare()) { | ||
298 | logg->logError(__FILE__, __LINE__, "Unable to prepare for capture"); | ||
299 | handleException(); | ||
300 | } | ||
301 | externalSource->start(); | ||
302 | } | ||
303 | 306 | ||
304 | if (!thread_creation_success) { | 307 | if (!thread_creation_success) { |
305 | logg->logError(__FILE__, __LINE__, "Failed to create gator threads"); | 308 | logg->logError(__FILE__, __LINE__, "Failed to create gator threads"); |
@@ -312,12 +315,10 @@ void Child::run() { | |||
312 | // Start profiling | 315 | // Start profiling |
313 | primarySource->run(); | 316 | primarySource->run(); |
314 | 317 | ||
315 | if (externalSource != NULL) { | ||
316 | externalSource->join(); | ||
317 | } | ||
318 | if (userSpaceSource != NULL) { | 318 | if (userSpaceSource != NULL) { |
319 | userSpaceSource->join(); | 319 | userSpaceSource->join(); |
320 | } | 320 | } |
321 | externalSource->join(); | ||
321 | 322 | ||
322 | // Wait for the other threads to exit | 323 | // Wait for the other threads to exit |
323 | pthread_join(senderThreadID, NULL); | 324 | pthread_join(senderThreadID, NULL); |
@@ -337,8 +338,8 @@ void Child::run() { | |||
337 | 338 | ||
338 | logg->logMessage("Profiling ended."); | 339 | logg->logMessage("Profiling ended."); |
339 | 340 | ||
340 | delete externalSource; | ||
341 | delete userSpaceSource; | 341 | delete userSpaceSource; |
342 | delete externalSource; | ||
342 | delete primarySource; | 343 | delete primarySource; |
343 | delete sender; | 344 | delete sender; |
344 | delete localCapture; | 345 | delete localCapture; |
diff --git a/daemon/Child.h b/daemon/Child.h index 9e206d7..a306a77 100644 --- a/daemon/Child.h +++ b/daemon/Child.h | |||
@@ -30,4 +30,4 @@ private: | |||
30 | Child &operator=(const Child &); | 30 | Child &operator=(const Child &); |
31 | }; | 31 | }; |
32 | 32 | ||
33 | #endif //__CHILD_H__ | 33 | #endif //__CHILD_H__ |
diff --git a/daemon/ConfigurationXML.cpp b/daemon/ConfigurationXML.cpp index fd479f2..6590dd3 100644 --- a/daemon/ConfigurationXML.cpp +++ b/daemon/ConfigurationXML.cpp | |||
@@ -21,12 +21,13 @@ static const char* ATTR_COUNTER = "counter"; | |||
21 | static const char* ATTR_REVISION = "revision"; | 21 | static const char* ATTR_REVISION = "revision"; |
22 | static const char* ATTR_EVENT = "event"; | 22 | static const char* ATTR_EVENT = "event"; |
23 | static const char* ATTR_COUNT = "count"; | 23 | static const char* ATTR_COUNT = "count"; |
24 | static const char* ATTR_CORES = "cores"; | ||
24 | 25 | ||
25 | ConfigurationXML::ConfigurationXML() { | 26 | ConfigurationXML::ConfigurationXML() { |
26 | const char * configuration_xml; | 27 | const char * configuration_xml; |
27 | unsigned int configuration_xml_len; | 28 | unsigned int configuration_xml_len; |
28 | getDefaultConfigurationXml(configuration_xml, configuration_xml_len); | 29 | getDefaultConfigurationXml(configuration_xml, configuration_xml_len); |
29 | 30 | ||
30 | char path[PATH_MAX]; | 31 | char path[PATH_MAX]; |
31 | 32 | ||
32 | getPath(path); | 33 | getPath(path); |
@@ -53,7 +54,7 @@ ConfigurationXML::ConfigurationXML() { | |||
53 | 54 | ||
54 | break; | 55 | break; |
55 | } | 56 | } |
56 | 57 | ||
57 | validate(); | 58 | validate(); |
58 | } | 59 | } |
59 | 60 | ||
@@ -82,7 +83,7 @@ int ConfigurationXML::parse(const char* configurationXML) { | |||
82 | node = mxmlGetFirstChild(tree); | 83 | node = mxmlGetFirstChild(tree); |
83 | while (node && mxmlGetType(node) != MXML_ELEMENT) | 84 | while (node && mxmlGetType(node) != MXML_ELEMENT) |
84 | node = mxmlWalkNext(node, tree, MXML_NO_DESCEND); | 85 | node = mxmlWalkNext(node, tree, MXML_NO_DESCEND); |
85 | 86 | ||
86 | ret = configurationsTag(node); | 87 | ret = configurationsTag(node); |
87 | 88 | ||
88 | node = mxmlGetFirstChild(node); | 89 | node = mxmlGetFirstChild(node); |
@@ -127,7 +128,7 @@ void ConfigurationXML::validate(void) { | |||
127 | #define CONFIGURATION_REVISION 3 | 128 | #define CONFIGURATION_REVISION 3 |
128 | int ConfigurationXML::configurationsTag(mxml_node_t *node) { | 129 | int ConfigurationXML::configurationsTag(mxml_node_t *node) { |
129 | const char* revision_string; | 130 | const char* revision_string; |
130 | 131 | ||
131 | revision_string = mxmlElementGetAttr(node, ATTR_REVISION); | 132 | revision_string = mxmlElementGetAttr(node, ATTR_REVISION); |
132 | if (!revision_string) { | 133 | if (!revision_string) { |
133 | return 1; //revision issue; | 134 | return 1; //revision issue; |
@@ -158,6 +159,7 @@ void ConfigurationXML::configurationTag(mxml_node_t *node) { | |||
158 | if (mxmlElementGetAttr(node, ATTR_COUNTER)) counter.setType(mxmlElementGetAttr(node, ATTR_COUNTER)); | 159 | if (mxmlElementGetAttr(node, ATTR_COUNTER)) counter.setType(mxmlElementGetAttr(node, ATTR_COUNTER)); |
159 | if (mxmlElementGetAttr(node, ATTR_EVENT)) counter.setEvent(strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16)); | 160 | if (mxmlElementGetAttr(node, ATTR_EVENT)) counter.setEvent(strtol(mxmlElementGetAttr(node, ATTR_EVENT), NULL, 16)); |
160 | if (mxmlElementGetAttr(node, ATTR_COUNT)) counter.setCount(strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10)); | 161 | if (mxmlElementGetAttr(node, ATTR_COUNT)) counter.setCount(strtol(mxmlElementGetAttr(node, ATTR_COUNT), NULL, 10)); |
162 | if (mxmlElementGetAttr(node, ATTR_CORES)) counter.setCores(strtol(mxmlElementGetAttr(node, ATTR_CORES), NULL, 10)); | ||
161 | if (counter.getCount() > 0) { | 163 | if (counter.getCount() > 0) { |
162 | gSessionData->mIsEBS = true; | 164 | gSessionData->mIsEBS = true; |
163 | } | 165 | } |
diff --git a/daemon/Counter.h b/daemon/Counter.h index 6891745..5202aa0 100644 --- a/daemon/Counter.h +++ b/daemon/Counter.h | |||
@@ -27,6 +27,7 @@ public: | |||
27 | mEnabled = false; | 27 | mEnabled = false; |
28 | mEvent = -1; | 28 | mEvent = -1; |
29 | mCount = 0; | 29 | mCount = 0; |
30 | mCores = -1; | ||
30 | mKey = 0; | 31 | mKey = 0; |
31 | mDriver = NULL; | 32 | mDriver = NULL; |
32 | } | 33 | } |
@@ -35,6 +36,7 @@ public: | |||
35 | void setEnabled(const bool enabled) { mEnabled = enabled; } | 36 | void setEnabled(const bool enabled) { mEnabled = enabled; } |
36 | void setEvent(const int event) { mEvent = event; } | 37 | void setEvent(const int event) { mEvent = event; } |
37 | void setCount(const int count) { mCount = count; } | 38 | void setCount(const int count) { mCount = count; } |
39 | void setCores(const int cores) { mCores = cores; } | ||
38 | void setKey(const int key) { mKey = key; } | 40 | void setKey(const int key) { mKey = key; } |
39 | void setDriver(Driver *const driver) { mDriver = driver; } | 41 | void setDriver(Driver *const driver) { mDriver = driver; } |
40 | 42 | ||
@@ -42,6 +44,7 @@ public: | |||
42 | bool isEnabled() const { return mEnabled; } | 44 | bool isEnabled() const { return mEnabled; } |
43 | int getEvent() const { return mEvent; } | 45 | int getEvent() const { return mEvent; } |
44 | int getCount() const { return mCount; } | 46 | int getCount() const { return mCount; } |
47 | int getCores() const { return mCores; } | ||
45 | int getKey() const { return mKey; } | 48 | int getKey() const { return mKey; } |
46 | Driver *getDriver() const { return mDriver; } | 49 | Driver *getDriver() const { return mDriver; } |
47 | 50 | ||
@@ -54,6 +57,7 @@ private: | |||
54 | bool mEnabled; | 57 | bool mEnabled; |
55 | int mEvent; | 58 | int mEvent; |
56 | int mCount; | 59 | int mCount; |
60 | int mCores; | ||
57 | int mKey; | 61 | int mKey; |
58 | Driver *mDriver; | 62 | Driver *mDriver; |
59 | }; | 63 | }; |
diff --git a/daemon/DriverSource.cpp b/daemon/DriverSource.cpp index f78ec6b..11d3095 100644 --- a/daemon/DriverSource.cpp +++ b/daemon/DriverSource.cpp | |||
@@ -12,19 +12,24 @@ | |||
12 | 12 | ||
13 | #include <fcntl.h> | 13 | #include <fcntl.h> |
14 | #include <inttypes.h> | 14 | #include <inttypes.h> |
15 | #include <sys/prctl.h> | ||
15 | #include <unistd.h> | 16 | #include <unistd.h> |
16 | 17 | ||
18 | #include "Buffer.h" | ||
17 | #include "Child.h" | 19 | #include "Child.h" |
20 | #include "DynBuf.h" | ||
18 | #include "Fifo.h" | 21 | #include "Fifo.h" |
19 | #include "Logging.h" | 22 | #include "Logging.h" |
23 | #include "Proc.h" | ||
20 | #include "Sender.h" | 24 | #include "Sender.h" |
21 | #include "SessionData.h" | 25 | #include "SessionData.h" |
22 | 26 | ||
23 | extern Child *child; | 27 | extern Child *child; |
24 | 28 | ||
25 | DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mFifo(NULL), mSenderSem(senderSem), mStartProfile(startProfile), mBufferSize(0), mBufferFD(0), mLength(1) { | 29 | DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mBuffer(NULL), mFifo(NULL), mSenderSem(senderSem), mStartProfile(startProfile), mBufferSize(0), mBufferFD(0), mLength(1) { |
26 | int driver_version = 0; | 30 | int driver_version = 0; |
27 | 31 | ||
32 | mBuffer = new Buffer(0, FRAME_PERF_ATTRS, 4*1024*1024, senderSem); | ||
28 | if (readIntDriver("/dev/gator/version", &driver_version) == -1) { | 33 | if (readIntDriver("/dev/gator/version", &driver_version) == -1) { |
29 | logg->logError(__FILE__, __LINE__, "Error reading gator driver version"); | 34 | logg->logError(__FILE__, __LINE__, "Error reading gator driver version"); |
30 | handleException(); | 35 | handleException(); |
@@ -43,7 +48,7 @@ DriverSource::DriverSource(sem_t *senderSem, sem_t *startProfile) : mFifo(NULL), | |||
43 | handleException(); | 48 | handleException(); |
44 | } else { | 49 | } else { |
45 | // Release version mismatch | 50 | // Release version mismatch |
46 | logg->logError(__FILE__, __LINE__, | 51 | logg->logError(__FILE__, __LINE__, |
47 | "gator driver version \"%d\" is different than gator daemon version \"%d\".\n" | 52 | "gator driver version \"%d\" is different than gator daemon version \"%d\".\n" |
48 | ">> Please upgrade the driver and daemon to the latest versions.", driver_version, PROTOCOL_VERSION); | 53 | ">> Please upgrade the driver and daemon to the latest versions.", driver_version, PROTOCOL_VERSION); |
49 | handleException(); | 54 | handleException(); |
@@ -87,6 +92,28 @@ bool DriverSource::prepare() { | |||
87 | return true; | 92 | return true; |
88 | } | 93 | } |
89 | 94 | ||
95 | void DriverSource::bootstrapThread() { | ||
96 | prctl(PR_SET_NAME, (unsigned long)&"gatord-bootstrap", 0, 0, 0); | ||
97 | |||
98 | DynBuf printb; | ||
99 | DynBuf b1; | ||
100 | DynBuf b2; | ||
101 | DynBuf b3; | ||
102 | |||
103 | if (!readProc(mBuffer, false, &printb, &b1, &b2, &b3)) { | ||
104 | logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__); | ||
105 | handleException(); | ||
106 | } | ||
107 | |||
108 | mBuffer->commit(1); | ||
109 | mBuffer->setDone(); | ||
110 | } | ||
111 | |||
112 | void *DriverSource::bootstrapThreadStatic(void *arg) { | ||
113 | static_cast<DriverSource *>(arg)->bootstrapThread(); | ||
114 | return NULL; | ||
115 | } | ||
116 | |||
90 | void DriverSource::run() { | 117 | void DriverSource::run() { |
91 | // Get the initial pointer to the collect buffer | 118 | // Get the initial pointer to the collect buffer |
92 | char *collectBuffer = mFifo->start(); | 119 | char *collectBuffer = mFifo->start(); |
@@ -138,6 +165,12 @@ void DriverSource::run() { | |||
138 | 165 | ||
139 | sem_post(mStartProfile); | 166 | sem_post(mStartProfile); |
140 | 167 | ||
168 | pthread_t bootstrapThreadID; | ||
169 | if (pthread_create(&bootstrapThreadID, NULL, bootstrapThreadStatic, this) != 0) { | ||
170 | logg->logError(__FILE__, __LINE__, "Unable to start the gator_bootstrap thread"); | ||
171 | handleException(); | ||
172 | } | ||
173 | |||
141 | // Collect Data | 174 | // Collect Data |
142 | do { | 175 | do { |
143 | // This command will stall until data is received from the driver | 176 | // This command will stall until data is received from the driver |
@@ -164,6 +197,8 @@ void DriverSource::run() { | |||
164 | } while (bytesCollected > 0); | 197 | } while (bytesCollected > 0); |
165 | 198 | ||
166 | logg->logMessage("Exit collect data loop"); | 199 | logg->logMessage("Exit collect data loop"); |
200 | |||
201 | pthread_join(bootstrapThreadID, NULL); | ||
167 | } | 202 | } |
168 | 203 | ||
169 | void DriverSource::interrupt() { | 204 | void DriverSource::interrupt() { |
@@ -174,7 +209,7 @@ void DriverSource::interrupt() { | |||
174 | } | 209 | } |
175 | 210 | ||
176 | bool DriverSource::isDone() { | 211 | bool DriverSource::isDone() { |
177 | return mLength <= 0; | 212 | return mLength <= 0 && (mBuffer == NULL || mBuffer->isDone()); |
178 | } | 213 | } |
179 | 214 | ||
180 | void DriverSource::write(Sender *sender) { | 215 | void DriverSource::write(Sender *sender) { |
@@ -182,6 +217,16 @@ void DriverSource::write(Sender *sender) { | |||
182 | if (data != NULL) { | 217 | if (data != NULL) { |
183 | sender->writeData(data, mLength, RESPONSE_APC_DATA); | 218 | sender->writeData(data, mLength, RESPONSE_APC_DATA); |
184 | mFifo->release(); | 219 | mFifo->release(); |
220 | // Assume the summary packet is in the first block received from the driver | ||
221 | gSessionData->mSentSummary = true; | ||
222 | } | ||
223 | if (mBuffer != NULL && !mBuffer->isDone()) { | ||
224 | mBuffer->write(sender); | ||
225 | if (mBuffer->isDone()) { | ||
226 | Buffer *buf = mBuffer; | ||
227 | mBuffer = NULL; | ||
228 | delete buf; | ||
229 | } | ||
185 | } | 230 | } |
186 | } | 231 | } |
187 | 232 | ||
@@ -227,7 +272,7 @@ int DriverSource::readInt64Driver(const char *fullpath, int64_t *value) { | |||
227 | char *endptr; | 272 | char *endptr; |
228 | errno = 0; | 273 | errno = 0; |
229 | *value = strtoll(data, &endptr, 10); | 274 | *value = strtoll(data, &endptr, 10); |
230 | if (errno != 0 || *endptr != '\n') { | 275 | if (errno != 0 || (*endptr != '\n' && *endptr != '\0')) { |
231 | logg->logMessage("Invalid value in file %s", fullpath); | 276 | logg->logMessage("Invalid value in file %s", fullpath); |
232 | return -1; | 277 | return -1; |
233 | } | 278 | } |
diff --git a/daemon/DriverSource.h b/daemon/DriverSource.h index dcf1078..ec27b08 100644 --- a/daemon/DriverSource.h +++ b/daemon/DriverSource.h | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include "Source.h" | 15 | #include "Source.h" |
16 | 16 | ||
17 | class Buffer; | ||
17 | class Fifo; | 18 | class Fifo; |
18 | 19 | ||
19 | class DriverSource : public Source { | 20 | class DriverSource : public Source { |
@@ -37,6 +38,10 @@ public: | |||
37 | static int writeReadDriver(const char *path, int64_t *value); | 38 | static int writeReadDriver(const char *path, int64_t *value); |
38 | 39 | ||
39 | private: | 40 | private: |
41 | static void *bootstrapThreadStatic(void *arg); | ||
42 | void bootstrapThread(); | ||
43 | |||
44 | Buffer *mBuffer; | ||
40 | Fifo *mFifo; | 45 | Fifo *mFifo; |
41 | sem_t *const mSenderSem; | 46 | sem_t *const mSenderSem; |
42 | sem_t *const mStartProfile; | 47 | sem_t *const mStartProfile; |
diff --git a/daemon/EventsXML.cpp b/daemon/EventsXML.cpp index a07a046..cf0192e 100644 --- a/daemon/EventsXML.cpp +++ b/daemon/EventsXML.cpp | |||
@@ -13,7 +13,7 @@ | |||
13 | #include "OlyUtility.h" | 13 | #include "OlyUtility.h" |
14 | #include "SessionData.h" | 14 | #include "SessionData.h" |
15 | 15 | ||
16 | char* EventsXML::getXML() { | 16 | mxml_node_t *EventsXML::getTree() { |
17 | #include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len | 17 | #include "events_xml.h" // defines and initializes char events_xml[] and int events_xml_len |
18 | char path[PATH_MAX]; | 18 | char path[PATH_MAX]; |
19 | mxml_node_t *xml; | 19 | mxml_node_t *xml; |
@@ -38,6 +38,12 @@ char* EventsXML::getXML() { | |||
38 | xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK); | 38 | xml = mxmlLoadString(NULL, (const char *)events_xml, MXML_NO_CALLBACK); |
39 | } | 39 | } |
40 | 40 | ||
41 | return xml; | ||
42 | } | ||
43 | |||
44 | char *EventsXML::getXML() { | ||
45 | mxml_node_t *xml = getTree(); | ||
46 | |||
41 | // Add dynamic events from the drivers | 47 | // Add dynamic events from the drivers |
42 | mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); | 48 | mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND); |
43 | if (!events) { | 49 | if (!events) { |
@@ -48,19 +54,19 @@ char* EventsXML::getXML() { | |||
48 | driver->writeEvents(events); | 54 | driver->writeEvents(events); |
49 | } | 55 | } |
50 | 56 | ||
51 | char* string = mxmlSaveAllocString(xml, mxmlWhitespaceCB); | 57 | char *string = mxmlSaveAllocString(xml, mxmlWhitespaceCB); |
52 | mxmlDelete(xml); | 58 | mxmlDelete(xml); |
53 | 59 | ||
54 | return string; | 60 | return string; |
55 | } | 61 | } |
56 | 62 | ||
57 | void EventsXML::write(const char* path) { | 63 | void EventsXML::write(const char *path) { |
58 | char file[PATH_MAX]; | 64 | char file[PATH_MAX]; |
59 | 65 | ||
60 | // Set full path | 66 | // Set full path |
61 | snprintf(file, PATH_MAX, "%s/events.xml", path); | 67 | snprintf(file, PATH_MAX, "%s/events.xml", path); |
62 | 68 | ||
63 | char* buf = getXML(); | 69 | char *buf = getXML(); |
64 | if (util->writeToDisk(file, buf) < 0) { | 70 | if (util->writeToDisk(file, buf) < 0) { |
65 | logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); | 71 | logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file); |
66 | handleException(); | 72 | handleException(); |
diff --git a/daemon/EventsXML.h b/daemon/EventsXML.h index 6cd1560..ff7a02f 100644 --- a/daemon/EventsXML.h +++ b/daemon/EventsXML.h | |||
@@ -9,9 +9,12 @@ | |||
9 | #ifndef EVENTS_XML | 9 | #ifndef EVENTS_XML |
10 | #define EVENTS_XML | 10 | #define EVENTS_XML |
11 | 11 | ||
12 | #include "mxml/mxml.h" | ||
13 | |||
12 | class EventsXML { | 14 | class EventsXML { |
13 | public: | 15 | public: |
14 | char* getXML(); | 16 | mxml_node_t *getTree(); |
17 | char *getXML(); | ||
15 | void write(const char* path); | 18 | void write(const char* path); |
16 | }; | 19 | }; |
17 | 20 | ||
diff --git a/daemon/ExternalSource.cpp b/daemon/ExternalSource.cpp index fe5824b..b6ec301 100644 --- a/daemon/ExternalSource.cpp +++ b/daemon/ExternalSource.cpp | |||
@@ -8,41 +8,195 @@ | |||
8 | 8 | ||
9 | #include "ExternalSource.h" | 9 | #include "ExternalSource.h" |
10 | 10 | ||
11 | #include <fcntl.h> | ||
11 | #include <sys/prctl.h> | 12 | #include <sys/prctl.h> |
13 | #include <unistd.h> | ||
12 | 14 | ||
13 | #include "Logging.h" | 15 | #include "Logging.h" |
14 | #include "OlySocket.h" | 16 | #include "OlySocket.h" |
15 | #include "SessionData.h" | 17 | #include "SessionData.h" |
16 | 18 | ||
17 | ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 1024, senderSem), mSock("/tmp/gator") { | 19 | static const char MALI_VIDEO[] = "\0mali-video"; |
20 | static const char MALI_VIDEO_STARTUP[] = "\0mali-video-startup"; | ||
21 | static const char MALI_VIDEO_V1[] = "MALI_VIDEO 1\n"; | ||
22 | |||
23 | static bool setNonblock(const int fd) { | ||
24 | int flags; | ||
25 | |||
26 | flags = fcntl(fd, F_GETFL); | ||
27 | if (flags < 0) { | ||
28 | logg->logMessage("fcntl getfl failed"); | ||
29 | return false; | ||
30 | } | ||
31 | |||
32 | if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) { | ||
33 | logg->logMessage("fcntl setfl failed"); | ||
34 | return false; | ||
35 | } | ||
36 | |||
37 | return true; | ||
38 | } | ||
39 | |||
40 | ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 128*1024, senderSem), mMonitor(), mMveStartupUds(MALI_VIDEO_STARTUP, sizeof(MALI_VIDEO_STARTUP)), mInterruptFd(-1), mMveUds(-1) { | ||
41 | sem_init(&mBufferSem, 0, 0); | ||
18 | } | 42 | } |
19 | 43 | ||
20 | ExternalSource::~ExternalSource() { | 44 | ExternalSource::~ExternalSource() { |
21 | } | 45 | } |
22 | 46 | ||
47 | void ExternalSource::waitFor(const uint64_t currTime, const int bytes) { | ||
48 | while (mBuffer.bytesAvailable() <= bytes) { | ||
49 | mBuffer.check(currTime); | ||
50 | sem_wait(&mBufferSem); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | void ExternalSource::configureConnection(const int fd, const char *const handshake, size_t size) { | ||
55 | if (!setNonblock(fd)) { | ||
56 | logg->logError(__FILE__, __LINE__, "Unable to set nonblock on fh"); | ||
57 | handleException(); | ||
58 | } | ||
59 | |||
60 | if (!mMonitor.add(fd)) { | ||
61 | logg->logError(__FILE__, __LINE__, "Unable to add fh to monitor"); | ||
62 | handleException(); | ||
63 | } | ||
64 | |||
65 | // Write the handshake to the circular buffer | ||
66 | waitFor(1, Buffer::MAXSIZE_PACK32 + 4 + size - 1); | ||
67 | mBuffer.packInt(fd); | ||
68 | mBuffer.writeLEInt((unsigned char *)mBuffer.getWritePos(), size - 1); | ||
69 | mBuffer.advanceWrite(4); | ||
70 | mBuffer.writeBytes(handshake, size - 1); | ||
71 | } | ||
72 | |||
73 | bool ExternalSource::connectMve() { | ||
74 | if (!gSessionData->maliVideo.countersEnabled()) { | ||
75 | return true; | ||
76 | } | ||
77 | |||
78 | mMveUds = OlySocket::connect(MALI_VIDEO, sizeof(MALI_VIDEO)); | ||
79 | if (mMveUds < 0) { | ||
80 | return false; | ||
81 | } | ||
82 | |||
83 | if (!gSessionData->maliVideo.start(mMveUds)) { | ||
84 | return false; | ||
85 | } | ||
86 | |||
87 | configureConnection(mMveUds, MALI_VIDEO_V1, sizeof(MALI_VIDEO_V1)); | ||
88 | |||
89 | return true; | ||
90 | } | ||
91 | |||
23 | bool ExternalSource::prepare() { | 92 | bool ExternalSource::prepare() { |
93 | if (!mMonitor.init() || !setNonblock(mMveStartupUds.getFd()) || !mMonitor.add(mMveStartupUds.getFd())) { | ||
94 | return false; | ||
95 | } | ||
96 | |||
97 | connectMve(); | ||
98 | |||
24 | return true; | 99 | return true; |
25 | } | 100 | } |
26 | 101 | ||
27 | void ExternalSource::run() { | 102 | void ExternalSource::run() { |
28 | prctl(PR_SET_NAME, (unsigned long)&"gatord-uds", 0, 0, 0); | 103 | int pipefd[2]; |
104 | |||
105 | prctl(PR_SET_NAME, (unsigned long)&"gatord-external", 0, 0, 0); | ||
106 | |||
107 | if (pipe(pipefd) != 0) { | ||
108 | logg->logError(__FILE__, __LINE__, "pipe failed"); | ||
109 | handleException(); | ||
110 | } | ||
111 | mInterruptFd = pipefd[1]; | ||
112 | |||
113 | if (!mMonitor.add(pipefd[0])) { | ||
114 | logg->logError(__FILE__, __LINE__, "Monitor::add failed"); | ||
115 | handleException(); | ||
116 | } | ||
29 | 117 | ||
30 | while (gSessionData->mSessionIsActive) { | 118 | while (gSessionData->mSessionIsActive) { |
31 | // Will be aborted when the socket is closed at the end of the capture | 119 | struct epoll_event events[16]; |
32 | int length = mSock.receive(mBuffer.getWritePos(), mBuffer.contiguousSpaceAvailable()); | 120 | // Clear any pending sem posts |
33 | if (length <= 0) { | 121 | while (sem_trywait(&mBufferSem) == 0); |
34 | break; | 122 | int ready = mMonitor.wait(events, ARRAY_LENGTH(events), -1); |
123 | if (ready < 0) { | ||
124 | logg->logError(__FILE__, __LINE__, "Monitor::wait failed"); | ||
125 | handleException(); | ||
35 | } | 126 | } |
36 | 127 | ||
37 | mBuffer.advanceWrite(length); | 128 | const uint64_t currTime = getTime(); |
38 | mBuffer.check(0); | 129 | |
130 | for (int i = 0; i < ready; ++i) { | ||
131 | const int fd = events[i].data.fd; | ||
132 | if (fd == mMveStartupUds.getFd()) { | ||
133 | // Mali Video Engine says it's alive | ||
134 | int client = mMveStartupUds.acceptConnection(); | ||
135 | // Don't read from this connection, establish a new connection to Mali-V500 | ||
136 | close(client); | ||
137 | if (!connectMve()) { | ||
138 | logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali video connection"); | ||
139 | handleException(); | ||
140 | } | ||
141 | } else if (fd == pipefd[0]) { | ||
142 | // Means interrupt has been called and mSessionIsActive should be reread | ||
143 | } else { | ||
144 | while (true) { | ||
145 | waitFor(currTime, Buffer::MAXSIZE_PACK32 + 4); | ||
146 | |||
147 | mBuffer.packInt(fd); | ||
148 | char *const bytesPos = mBuffer.getWritePos(); | ||
149 | mBuffer.advanceWrite(4); | ||
150 | const int contiguous = mBuffer.contiguousSpaceAvailable(); | ||
151 | const int bytes = read(fd, mBuffer.getWritePos(), contiguous); | ||
152 | if (bytes < 0) { | ||
153 | if (errno == EAGAIN) { | ||
154 | // Nothing left to read, and Buffer convention dictates that writePos can't go backwards | ||
155 | mBuffer.writeLEInt((unsigned char *)bytesPos, 0); | ||
156 | break; | ||
157 | } | ||
158 | // Something else failed, close the socket | ||
159 | mBuffer.writeLEInt((unsigned char *)bytesPos, -1); | ||
160 | close(fd); | ||
161 | break; | ||
162 | } else if (bytes == 0) { | ||
163 | // The other side is closed | ||
164 | mBuffer.writeLEInt((unsigned char *)bytesPos, -1); | ||
165 | close(fd); | ||
166 | break; | ||
167 | } | ||
168 | |||
169 | mBuffer.writeLEInt((unsigned char *)bytesPos, bytes); | ||
170 | mBuffer.advanceWrite(bytes); | ||
171 | |||
172 | // Short reads also mean nothing is left to read | ||
173 | if (bytes < contiguous) { | ||
174 | break; | ||
175 | } | ||
176 | } | ||
177 | } | ||
178 | } | ||
179 | |||
180 | // Only call mBufferCheck once per iteration | ||
181 | mBuffer.check(currTime); | ||
39 | } | 182 | } |
40 | 183 | ||
41 | mBuffer.setDone(); | 184 | mBuffer.setDone(); |
185 | |||
186 | mInterruptFd = -1; | ||
187 | close(pipefd[0]); | ||
188 | close(pipefd[1]); | ||
42 | } | 189 | } |
43 | 190 | ||
44 | void ExternalSource::interrupt() { | 191 | void ExternalSource::interrupt() { |
45 | // Do nothing | 192 | if (mInterruptFd >= 0) { |
193 | int8_t c = 0; | ||
194 | // Write to the pipe to wake the monitor which will cause mSessionIsActive to be reread | ||
195 | if (::write(mInterruptFd, &c, sizeof(c)) != sizeof(c)) { | ||
196 | logg->logError(__FILE__, __LINE__, "write failed"); | ||
197 | handleException(); | ||
198 | } | ||
199 | } | ||
46 | } | 200 | } |
47 | 201 | ||
48 | bool ExternalSource::isDone() { | 202 | bool ExternalSource::isDone() { |
@@ -50,7 +204,12 @@ bool ExternalSource::isDone() { | |||
50 | } | 204 | } |
51 | 205 | ||
52 | void ExternalSource::write(Sender *sender) { | 206 | void ExternalSource::write(Sender *sender) { |
207 | // Don't send external data until the summary packet is sent so that monotonic delta is available | ||
208 | if (!gSessionData->mSentSummary) { | ||
209 | return; | ||
210 | } | ||
53 | if (!mBuffer.isDone()) { | 211 | if (!mBuffer.isDone()) { |
54 | mBuffer.write(sender); | 212 | mBuffer.write(sender); |
213 | sem_post(&mBufferSem); | ||
55 | } | 214 | } |
56 | } | 215 | } |
diff --git a/daemon/ExternalSource.h b/daemon/ExternalSource.h index 2052bdf..2e7ed27 100644 --- a/daemon/ExternalSource.h +++ b/daemon/ExternalSource.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <semaphore.h> | 12 | #include <semaphore.h> |
13 | 13 | ||
14 | #include "Buffer.h" | 14 | #include "Buffer.h" |
15 | #include "Monitor.h" | ||
15 | #include "OlySocket.h" | 16 | #include "OlySocket.h" |
16 | #include "Source.h" | 17 | #include "Source.h" |
17 | 18 | ||
@@ -29,8 +30,16 @@ public: | |||
29 | void write(Sender *sender); | 30 | void write(Sender *sender); |
30 | 31 | ||
31 | private: | 32 | private: |
33 | void waitFor(const uint64_t currTime, const int bytes); | ||
34 | void configureConnection(const int fd, const char *const handshake, size_t size); | ||
35 | bool connectMve(); | ||
36 | |||
37 | sem_t mBufferSem; | ||
32 | Buffer mBuffer; | 38 | Buffer mBuffer; |
33 | OlySocket mSock; | 39 | Monitor mMonitor; |
40 | OlyServerSocket mMveStartupUds; | ||
41 | int mInterruptFd; | ||
42 | int mMveUds; | ||
34 | 43 | ||
35 | // Intentionally unimplemented | 44 | // Intentionally unimplemented |
36 | ExternalSource(const ExternalSource &); | 45 | ExternalSource(const ExternalSource &); |
diff --git a/daemon/FSDriver.cpp b/daemon/FSDriver.cpp new file mode 100644 index 0000000..40c8df1 --- /dev/null +++ b/daemon/FSDriver.cpp | |||
@@ -0,0 +1,212 @@ | |||
1 | /** | ||
2 | * Copyright (C) ARM Limited 2014. 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 "FSDriver.h" | ||
10 | |||
11 | #include <fcntl.h> | ||
12 | #include <regex.h> | ||
13 | #include <sys/stat.h> | ||
14 | #include <sys/types.h> | ||
15 | #include <unistd.h> | ||
16 | |||
17 | #include "Buffer.h" | ||
18 | #include "Counter.h" | ||
19 | #include "DriverSource.h" | ||
20 | #include "Logging.h" | ||
21 | #include "SessionData.h" | ||
22 | |||
23 | class FSCounter { | ||
24 | public: | ||
25 | FSCounter(FSCounter *next, char *name, const char *regex); | ||
26 | ~FSCounter(); | ||
27 | |||
28 | FSCounter *getNext() const { return next; } | ||
29 | int getKey() const { return key; } | ||
30 | bool isEnabled() const { return enabled; } | ||
31 | void setEnabled(const bool enabled) { this->enabled = enabled; } | ||
32 | const char *getName() const { return name; } | ||
33 | int64_t read(); | ||
34 | |||
35 | private: | ||
36 | FSCounter *const next; | ||
37 | regex_t reg; | ||
38 | char *name; | ||
39 | const int key; | ||
40 | int enabled : 1, | ||
41 | useRegex : 1; | ||
42 | |||
43 | // Intentionally unimplemented | ||
44 | FSCounter(const FSCounter &); | ||
45 | FSCounter &operator=(const FSCounter &); | ||
46 | }; | ||
47 | |||
48 | FSCounter::FSCounter(FSCounter *next, char *name, const char *regex) : next(next), name(name), key(getEventKey()), enabled(false), useRegex(regex != NULL) { | ||
49 | if (useRegex) { | ||
50 | int result = regcomp(®, regex, REG_EXTENDED); | ||
51 | if (result != 0) { | ||
52 | char buf[128]; | ||
53 | regerror(result, ®, buf, sizeof(buf)); | ||
54 | logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf); | ||
55 | handleException(); | ||
56 | } | ||
57 | } | ||
58 | } | ||
59 | |||
60 | FSCounter::~FSCounter() { | ||
61 | free(name); | ||
62 | if (useRegex) { | ||
63 | regfree(®); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | int64_t FSCounter::read() { | ||
68 | int64_t value; | ||
69 | if (useRegex) { | ||
70 | char buf[4096]; | ||
71 | size_t pos = 0; | ||
72 | const int fd = open(name, O_RDONLY); | ||
73 | if (fd < 0) { | ||
74 | goto fail; | ||
75 | } | ||
76 | while (pos < sizeof(buf) - 1) { | ||
77 | const ssize_t bytes = ::read(fd, buf + pos, sizeof(buf) - pos - 1); | ||
78 | if (bytes < 0) { | ||
79 | goto fail; | ||
80 | } else if (bytes == 0) { | ||
81 | break; | ||
82 | } | ||
83 | pos += bytes; | ||
84 | } | ||
85 | close(fd); | ||
86 | buf[pos] = '\0'; | ||
87 | |||
88 | regmatch_t match[2]; | ||
89 | int result = regexec(®, buf, 2, match, 0); | ||
90 | if (result != 0) { | ||
91 | regerror(result, ®, buf, sizeof(buf)); | ||
92 | logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, buf); | ||
93 | handleException(); | ||
94 | } | ||
95 | |||
96 | if (match[1].rm_so < 0) { | ||
97 | logg->logError(__FILE__, __LINE__, "Parsing %s failed", name); | ||
98 | handleException(); | ||
99 | } | ||
100 | char *endptr; | ||
101 | errno = 0; | ||
102 | value = strtoll(buf + match[1].rm_so, &endptr, 0); | ||
103 | if (errno != 0) { | ||
104 | logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, strerror(errno)); | ||
105 | handleException(); | ||
106 | } | ||
107 | } else { | ||
108 | if (DriverSource::readInt64Driver(name, &value) != 0) { | ||
109 | goto fail; | ||
110 | } | ||
111 | } | ||
112 | return value; | ||
113 | |||
114 | fail: | ||
115 | logg->logError(__FILE__, __LINE__, "Unable to read %s", name); | ||
116 | handleException(); | ||
117 | } | ||
118 | |||
119 | FSDriver::FSDriver() : counters(NULL) { | ||
120 | } | ||
121 | |||
122 | FSDriver::~FSDriver() { | ||
123 | while (counters != NULL) { | ||
124 | FSCounter * counter = counters; | ||
125 | counters = counter->getNext(); | ||
126 | delete counter; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | void FSDriver::setup(mxml_node_t *const xml) { | ||
131 | // fs driver does not currently work with perf | ||
132 | if (gSessionData->perf.isSetup()) { | ||
133 | return; | ||
134 | } | ||
135 | |||
136 | mxml_node_t *node = xml; | ||
137 | while (true) { | ||
138 | node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND); | ||
139 | if (node == NULL) { | ||
140 | break; | ||
141 | } | ||
142 | const char *counter = mxmlElementGetAttr(node, "counter"); | ||
143 | if ((counter != NULL) && (counter[0] == '/')) { | ||
144 | const char *regex = mxmlElementGetAttr(node, "regex"); | ||
145 | counters = new FSCounter(counters, strdup(counter), regex); | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | |||
150 | FSCounter *FSDriver::findCounter(const Counter &counter) const { | ||
151 | for (FSCounter * fsCounter = counters; fsCounter != NULL; fsCounter = fsCounter->getNext()) { | ||
152 | if (strcmp(fsCounter->getName(), counter.getType()) == 0) { | ||
153 | return fsCounter; | ||
154 | } | ||
155 | } | ||
156 | |||
157 | return NULL; | ||
158 | } | ||
159 | |||
160 | bool FSDriver::claimCounter(const Counter &counter) const { | ||
161 | return findCounter(counter) != NULL; | ||
162 | } | ||
163 | |||
164 | bool FSDriver::countersEnabled() const { | ||
165 | for (FSCounter *counter = counters; counter != NULL; counter = counter->getNext()) { | ||
166 | if (counter->isEnabled()) { | ||
167 | return true; | ||
168 | } | ||
169 | } | ||
170 | return false; | ||
171 | } | ||
172 | |||
173 | void FSDriver::resetCounters() { | ||
174 | for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) { | ||
175 | counter->setEnabled(false); | ||
176 | } | ||
177 | } | ||
178 | |||
179 | void FSDriver::setupCounter(Counter &counter) { | ||
180 | FSCounter *const fsCounter = findCounter(counter); | ||
181 | if (fsCounter == NULL) { | ||
182 | counter.setEnabled(false); | ||
183 | return; | ||
184 | } | ||
185 | fsCounter->setEnabled(true); | ||
186 | counter.setKey(fsCounter->getKey()); | ||
187 | } | ||
188 | |||
189 | int FSDriver::writeCounters(mxml_node_t *root) const { | ||
190 | int count = 0; | ||
191 | for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) { | ||
192 | if (access(counter->getName(), R_OK) == 0) { | ||
193 | mxml_node_t *node = mxmlNewElement(root, "counter"); | ||
194 | mxmlElementSetAttr(node, "name", counter->getName()); | ||
195 | ++count; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | return count; | ||
200 | } | ||
201 | |||
202 | void FSDriver::start() { | ||
203 | } | ||
204 | |||
205 | void FSDriver::read(Buffer * const buffer) { | ||
206 | for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) { | ||
207 | if (!counter->isEnabled()) { | ||
208 | continue; | ||
209 | } | ||
210 | buffer->event(counter->getKey(), counter->read()); | ||
211 | } | ||
212 | } | ||
diff --git a/daemon/FSDriver.h b/daemon/FSDriver.h new file mode 100644 index 0000000..ef39553 --- /dev/null +++ b/daemon/FSDriver.h | |||
@@ -0,0 +1,44 @@ | |||
1 | /** | ||
2 | * Copyright (C) ARM Limited 2014. 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 FSDRIVER_H | ||
10 | #define FSDRIVER_H | ||
11 | |||
12 | #include "Driver.h" | ||
13 | |||
14 | class Buffer; | ||
15 | class FSCounter; | ||
16 | |||
17 | class FSDriver : public Driver { | ||
18 | public: | ||
19 | FSDriver(); | ||
20 | ~FSDriver(); | ||
21 | |||
22 | void setup(mxml_node_t *const xml); | ||
23 | |||
24 | bool claimCounter(const Counter &counter) const; | ||
25 | bool countersEnabled() const; | ||
26 | void resetCounters(); | ||
27 | void setupCounter(Counter &counter); | ||
28 | |||
29 | int writeCounters(mxml_node_t *root) const; | ||
30 | |||
31 | void start(); | ||
32 | void read(Buffer * buffer); | ||
33 | |||
34 | private: | ||
35 | FSCounter *findCounter(const Counter &counter) const; | ||
36 | |||
37 | FSCounter *counters; | ||
38 | |||
39 | // Intentionally unimplemented | ||
40 | FSDriver(const FSDriver &); | ||
41 | FSDriver &operator=(const FSDriver &); | ||
42 | }; | ||
43 | |||
44 | #endif // FSDRIVER_H | ||
diff --git a/daemon/Fifo.h b/daemon/Fifo.h index 7dd7426..bdda3f5 100644 --- a/daemon/Fifo.h +++ b/daemon/Fifo.h | |||
@@ -45,4 +45,4 @@ private: | |||
45 | Fifo &operator=(const Fifo &); | 45 | Fifo &operator=(const Fifo &); |
46 | }; | 46 | }; |
47 | 47 | ||
48 | #endif //__FIFO_H__ | 48 | #endif //__FIFO_H__ |
diff --git a/daemon/Hwmon.cpp b/daemon/Hwmon.cpp index 778f307..e444247 100644 --- a/daemon/Hwmon.cpp +++ b/daemon/Hwmon.cpp | |||
@@ -28,6 +28,7 @@ public: | |||
28 | const char *getTitle() const { return title; } | 28 | const char *getTitle() const { return title; } |
29 | bool isDuplicate() const { return duplicate; } | 29 | bool isDuplicate() const { return duplicate; } |
30 | const char *getDisplay() const { return display; } | 30 | const char *getDisplay() const { return display; } |
31 | const char *getCounterClass() const { return counter_class; } | ||
31 | const char *getUnit() const { return unit; } | 32 | const char *getUnit() const { return unit; } |
32 | int getModifier() const { return modifier; } | 33 | int getModifier() const { return modifier; } |
33 | 34 | ||
@@ -58,6 +59,7 @@ private: | |||
58 | char *label; | 59 | char *label; |
59 | const char *title; | 60 | const char *title; |
60 | const char *display; | 61 | const char *display; |
62 | const char *counter_class; | ||
61 | const char *unit; | 63 | const char *unit; |
62 | int modifier; | 64 | int modifier; |
63 | double previous_value; | 65 | double previous_value; |
@@ -87,7 +89,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co | |||
87 | case SENSORS_FEATURE_IN: | 89 | case SENSORS_FEATURE_IN: |
88 | title = "Voltage"; | 90 | title = "Voltage"; |
89 | input = SENSORS_SUBFEATURE_IN_INPUT; | 91 | input = SENSORS_SUBFEATURE_IN_INPUT; |
90 | display = "average"; | 92 | display = "maximum"; |
93 | counter_class = "absolute"; | ||
91 | unit = "V"; | 94 | unit = "V"; |
92 | modifier = 1000; | 95 | modifier = 1000; |
93 | monotonic = false; | 96 | monotonic = false; |
@@ -96,6 +99,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co | |||
96 | title = "Fan"; | 99 | title = "Fan"; |
97 | input = SENSORS_SUBFEATURE_FAN_INPUT; | 100 | input = SENSORS_SUBFEATURE_FAN_INPUT; |
98 | display = "average"; | 101 | display = "average"; |
102 | counter_class = "absolute"; | ||
99 | unit = "RPM"; | 103 | unit = "RPM"; |
100 | modifier = 1; | 104 | modifier = 1; |
101 | monotonic = false; | 105 | monotonic = false; |
@@ -104,6 +108,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co | |||
104 | title = "Temperature"; | 108 | title = "Temperature"; |
105 | input = SENSORS_SUBFEATURE_TEMP_INPUT; | 109 | input = SENSORS_SUBFEATURE_TEMP_INPUT; |
106 | display = "maximum"; | 110 | display = "maximum"; |
111 | counter_class = "absolute"; | ||
107 | unit = "°C"; | 112 | unit = "°C"; |
108 | modifier = 1000; | 113 | modifier = 1000; |
109 | monotonic = false; | 114 | monotonic = false; |
@@ -111,7 +116,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co | |||
111 | case SENSORS_FEATURE_POWER: | 116 | case SENSORS_FEATURE_POWER: |
112 | title = "Power"; | 117 | title = "Power"; |
113 | input = SENSORS_SUBFEATURE_POWER_INPUT; | 118 | input = SENSORS_SUBFEATURE_POWER_INPUT; |
114 | display = "average"; | 119 | display = "maximum"; |
120 | counter_class = "absolute"; | ||
115 | unit = "W"; | 121 | unit = "W"; |
116 | modifier = 1000000; | 122 | modifier = 1000000; |
117 | monotonic = false; | 123 | monotonic = false; |
@@ -120,6 +126,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co | |||
120 | title = "Energy"; | 126 | title = "Energy"; |
121 | input = SENSORS_SUBFEATURE_ENERGY_INPUT; | 127 | input = SENSORS_SUBFEATURE_ENERGY_INPUT; |
122 | display = "accumulate"; | 128 | display = "accumulate"; |
129 | counter_class = "delta"; | ||
123 | unit = "J"; | 130 | unit = "J"; |
124 | modifier = 1000000; | 131 | modifier = 1000000; |
125 | monotonic = true; | 132 | monotonic = true; |
@@ -127,7 +134,8 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co | |||
127 | case SENSORS_FEATURE_CURR: | 134 | case SENSORS_FEATURE_CURR: |
128 | title = "Current"; | 135 | title = "Current"; |
129 | input = SENSORS_SUBFEATURE_CURR_INPUT; | 136 | input = SENSORS_SUBFEATURE_CURR_INPUT; |
130 | display = "average"; | 137 | display = "maximum"; |
138 | counter_class = "absolute"; | ||
131 | unit = "A"; | 139 | unit = "A"; |
132 | modifier = 1000; | 140 | modifier = 1000; |
133 | monotonic = false; | 141 | monotonic = false; |
@@ -136,6 +144,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co | |||
136 | title = "Humidity"; | 144 | title = "Humidity"; |
137 | input = SENSORS_SUBFEATURE_HUMIDITY_INPUT; | 145 | input = SENSORS_SUBFEATURE_HUMIDITY_INPUT; |
138 | display = "average"; | 146 | display = "average"; |
147 | counter_class = "absolute"; | ||
139 | unit = "%"; | 148 | unit = "%"; |
140 | modifier = 1000; | 149 | modifier = 1000; |
141 | monotonic = false; | 150 | monotonic = false; |
@@ -311,6 +320,7 @@ void Hwmon::writeEvents(mxml_node_t *root) const { | |||
311 | mxmlElementSetAttr(node, "name", counter->getLabel()); | 320 | mxmlElementSetAttr(node, "name", counter->getLabel()); |
312 | } | 321 | } |
313 | mxmlElementSetAttr(node, "display", counter->getDisplay()); | 322 | mxmlElementSetAttr(node, "display", counter->getDisplay()); |
323 | mxmlElementSetAttr(node, "class", counter->getCounterClass()); | ||
314 | mxmlElementSetAttr(node, "units", counter->getUnit()); | 324 | mxmlElementSetAttr(node, "units", counter->getUnit()); |
315 | if (counter->getModifier() != 1) { | 325 | if (counter->getModifier() != 1) { |
316 | mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier()); | 326 | mxmlElementSetAttrf(node, "modifier", "%d", counter->getModifier()); |
diff --git a/daemon/KMod.cpp b/daemon/KMod.cpp index 9300002..73e123d 100644 --- a/daemon/KMod.cpp +++ b/daemon/KMod.cpp | |||
@@ -58,10 +58,15 @@ void KMod::setupCounter(Counter &counter) { | |||
58 | return; | 58 | return; |
59 | } | 59 | } |
60 | 60 | ||
61 | int value = 0; | ||
61 | snprintf(text, sizeof(text), "%s/key", base); | 62 | snprintf(text, sizeof(text), "%s/key", base); |
62 | int key = 0; | 63 | DriverSource::readIntDriver(text, &value); |
63 | DriverSource::readIntDriver(text, &key); | 64 | counter.setKey(value); |
64 | counter.setKey(key); | 65 | |
66 | snprintf(text, sizeof(text), "%s/cores", base); | ||
67 | if (DriverSource::readIntDriver(text, &value) == 0) { | ||
68 | counter.setCores(value); | ||
69 | } | ||
65 | 70 | ||
66 | snprintf(text, sizeof(text), "%s/event", base); | 71 | snprintf(text, sizeof(text), "%s/event", base); |
67 | DriverSource::writeDriver(text, counter.getEvent()); | 72 | DriverSource::writeDriver(text, counter.getEvent()); |
diff --git a/daemon/LocalCapture.h b/daemon/LocalCapture.h index aadecce..b1e7219 100644 --- a/daemon/LocalCapture.h +++ b/daemon/LocalCapture.h | |||
@@ -23,4 +23,4 @@ private: | |||
23 | int removeDirAndAllContents(char* path); | 23 | int removeDirAndAllContents(char* path); |
24 | }; | 24 | }; |
25 | 25 | ||
26 | #endif //__LOCAL_CAPTURE_H__ | 26 | #endif //__LOCAL_CAPTURE_H__ |
diff --git a/daemon/Logging.h b/daemon/Logging.h index 6ae3280..4934bb0 100644 --- a/daemon/Logging.h +++ b/daemon/Logging.h | |||
@@ -33,4 +33,4 @@ extern Logging* logg; | |||
33 | 33 | ||
34 | extern void handleException() __attribute__ ((noreturn)); | 34 | extern void handleException() __attribute__ ((noreturn)); |
35 | 35 | ||
36 | #endif //__LOGGING_H__ | 36 | #endif //__LOGGING_H__ |
diff --git a/daemon/Makefile b/daemon/Makefile index 24ee940..2ed49fd 100644 --- a/daemon/Makefile +++ b/daemon/Makefile | |||
@@ -8,14 +8,14 @@ | |||
8 | # targets run 'make SOFTFLOAT=1 SYSROOT=/path/to/sysroot', see | 8 | # targets run 'make SOFTFLOAT=1 SYSROOT=/path/to/sysroot', see |
9 | # README_Streamline.txt for more details | 9 | # README_Streamline.txt for more details |
10 | 10 | ||
11 | CPP = $(CROSS_COMPILE)g++ | 11 | CC = $(CROSS_COMPILE)gcc |
12 | GCC = $(CROSS_COMPILE)gcc | 12 | CXX = $(CROSS_COMPILE)g++ |
13 | 13 | ||
14 | # -mthumb-interwork is required for interworking to ARM or Thumb stdlibc | 14 | # -mthumb-interwork is required for interworking to ARM or Thumb stdlibc |
15 | CFLAGS += -mthumb-interwork | 15 | CPPFLAGS += -mthumb-interwork |
16 | 16 | ||
17 | ifeq ($(SOFTFLOAT),1) | 17 | ifeq ($(SOFTFLOAT),1) |
18 | CFLAGS += -marm -march=armv4t -mfloat-abi=soft | 18 | CPPFLAGS += -marm -march=armv4t -mfloat-abi=soft |
19 | LDFLAGS += -marm -march=armv4t -mfloat-abi=soft | 19 | LDFLAGS += -marm -march=armv4t -mfloat-abi=soft |
20 | endif | 20 | endif |
21 | ifneq ($(SYSROOT),) | 21 | ifneq ($(SYSROOT),) |
diff --git a/daemon/Makefile_aarch64 b/daemon/Makefile_aarch64 index 10b4b4a..efd1fa0 100644 --- a/daemon/Makefile_aarch64 +++ b/daemon/Makefile_aarch64 | |||
@@ -4,12 +4,9 @@ | |||
4 | # | 4 | # |
5 | 5 | ||
6 | # Uncomment and define CROSS_COMPILE if it is not already defined | 6 | # Uncomment and define CROSS_COMPILE if it is not already defined |
7 | # CROSS_COMPILE=/path/to/cross-compiler/arm-linux-gnueabihf- | 7 | # CROSS_COMPILE=/path/to/cross-compiler/aarch64-linux-gnu- |
8 | # NOTE: This toolchain uses the hardfloat abi by default. For non-hardfloat | ||
9 | # targets it is necessary to add options | ||
10 | # '-marm -march=armv4t -mfloat-abi=soft'. | ||
11 | 8 | ||
12 | CPP = $(CROSS_COMPILE)g++ | 9 | CC = $(CROSS_COMPILE)gcc |
13 | GCC = $(CROSS_COMPILE)gcc | 10 | CXX = $(CROSS_COMPILE)g++ |
14 | 11 | ||
15 | include common.mk | 12 | include common.mk |
diff --git a/daemon/MaliVideoDriver.cpp b/daemon/MaliVideoDriver.cpp new file mode 100644 index 0000000..18b413b --- /dev/null +++ b/daemon/MaliVideoDriver.cpp | |||
@@ -0,0 +1,253 @@ | |||
1 | /** | ||
2 | * Copyright (C) ARM Limited 2014. 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 "MaliVideoDriver.h" | ||
10 | |||
11 | #include <unistd.h> | ||
12 | |||
13 | #include "Buffer.h" | ||
14 | #include "Counter.h" | ||
15 | #include "Logging.h" | ||
16 | #include "SessionData.h" | ||
17 | |||
18 | // From instr/src/mve_instr_comm_protocol.h | ||
19 | typedef enum mve_instr_configuration_type { | ||
20 | MVE_INSTR_RAW = 1 << 0, | ||
21 | MVE_INSTR_COUNTERS = 1 << 1, | ||
22 | MVE_INSTR_EVENTS = 1 << 2, | ||
23 | MVE_INSTR_ACTIVITIES = 1 << 3, | ||
24 | |||
25 | // Raw always pushed regardless | ||
26 | MVE_INSTR_PULL = 1 << 12, | ||
27 | // Raw always unpacked regardless | ||
28 | MVE_INSTR_PACKED_COMM = 1 << 13, | ||
29 | // Don’t send ACKt response | ||
30 | MVE_INSTR_NO_AUTO_ACK = 1 << 14, | ||
31 | } mve_instr_configuration_type_t; | ||
32 | |||
33 | static const char COUNTER[] = "ARM_Mali-V500_cnt"; | ||
34 | static const char EVENT[] = "ARM_Mali-V500_evn"; | ||
35 | static const char ACTIVITY[] = "ARM_Mali-V500_act"; | ||
36 | |||
37 | class MaliVideoCounter { | ||
38 | public: | ||
39 | MaliVideoCounter(MaliVideoCounter *next, const char *name, const MaliVideoCounterType type, const int id) : mNext(next), mName(name), mType(type), mId(id), mKey(getEventKey()), mEnabled(false) { | ||
40 | } | ||
41 | |||
42 | ~MaliVideoCounter() { | ||
43 | delete mName; | ||
44 | } | ||
45 | |||
46 | MaliVideoCounter *getNext() const { return mNext; } | ||
47 | const char *getName() const { return mName; } | ||
48 | MaliVideoCounterType getType() const { return mType; } | ||
49 | int getId() const { return mId; } | ||
50 | int getKey() const { return mKey; } | ||
51 | bool isEnabled() const { return mEnabled; } | ||
52 | void setEnabled(const bool enabled) { mEnabled = enabled; } | ||
53 | |||
54 | private: | ||
55 | MaliVideoCounter *const mNext; | ||
56 | const char *const mName; | ||
57 | const MaliVideoCounterType mType; | ||
58 | // Mali Video id | ||
59 | const int mId; | ||
60 | // Streamline key | ||
61 | const int mKey; | ||
62 | bool mEnabled; | ||
63 | }; | ||
64 | |||
65 | MaliVideoDriver::MaliVideoDriver() : mCounters(NULL), mActivityCount(0) { | ||
66 | } | ||
67 | |||
68 | MaliVideoDriver::~MaliVideoDriver() { | ||
69 | while (mCounters != NULL) { | ||
70 | MaliVideoCounter *counter = mCounters; | ||
71 | mCounters = counter->getNext(); | ||
72 | delete counter; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | void MaliVideoDriver::setup(mxml_node_t *const xml) { | ||
77 | // hwmon does not currently work with perf | ||
78 | if (gSessionData->perf.isSetup()) { | ||
79 | return; | ||
80 | } | ||
81 | |||
82 | mxml_node_t *node = xml; | ||
83 | while (true) { | ||
84 | node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND); | ||
85 | if (node == NULL) { | ||
86 | break; | ||
87 | } | ||
88 | const char *counter = mxmlElementGetAttr(node, "counter"); | ||
89 | if (counter == NULL) { | ||
90 | // Ignore | ||
91 | } else if (strncmp(counter, COUNTER, sizeof(COUNTER) - 1) == 0) { | ||
92 | const int i = strtol(counter + sizeof(COUNTER) - 1, NULL, 10); | ||
93 | mCounters = new MaliVideoCounter(mCounters, strdup(counter), MVCT_COUNTER, i); | ||
94 | } else if (strncmp(counter, EVENT, sizeof(EVENT) - 1) == 0) { | ||
95 | const int i = strtol(counter + sizeof(EVENT) - 1, NULL, 10); | ||
96 | mCounters = new MaliVideoCounter(mCounters, strdup(counter), MVCT_EVENT, i); | ||
97 | } else if (strcmp(counter, ACTIVITY) == 0) { | ||
98 | mCounters = new MaliVideoCounter(mCounters, strdup(ACTIVITY), MVCT_ACTIVITY, 0); | ||
99 | mActivityCount = 0; | ||
100 | while (true) { | ||
101 | char buf[32]; | ||
102 | snprintf(buf, sizeof(buf), "activity%i", mActivityCount + 1); | ||
103 | if (mxmlElementGetAttr(node, buf) == NULL) { | ||
104 | break; | ||
105 | } | ||
106 | ++mActivityCount; | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | |||
112 | MaliVideoCounter *MaliVideoDriver::findCounter(const Counter &counter) const { | ||
113 | for (MaliVideoCounter *maliVideoCounter = mCounters; maliVideoCounter != NULL; maliVideoCounter = maliVideoCounter->getNext()) { | ||
114 | if (strcmp(maliVideoCounter->getName(), counter.getType()) == 0) { | ||
115 | return maliVideoCounter; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | return NULL; | ||
120 | } | ||
121 | |||
122 | bool MaliVideoDriver::claimCounter(const Counter &counter) const { | ||
123 | return findCounter(counter) != NULL; | ||
124 | } | ||
125 | |||
126 | bool MaliVideoDriver::countersEnabled() const { | ||
127 | for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { | ||
128 | if (counter->isEnabled()) { | ||
129 | return true; | ||
130 | } | ||
131 | } | ||
132 | return false; | ||
133 | } | ||
134 | |||
135 | void MaliVideoDriver::resetCounters() { | ||
136 | for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { | ||
137 | counter->setEnabled(false); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | void MaliVideoDriver::setupCounter(Counter &counter) { | ||
142 | MaliVideoCounter *const maliVideoCounter = findCounter(counter); | ||
143 | if (maliVideoCounter == NULL) { | ||
144 | counter.setEnabled(false); | ||
145 | return; | ||
146 | } | ||
147 | maliVideoCounter->setEnabled(true); | ||
148 | counter.setKey(maliVideoCounter->getKey()); | ||
149 | } | ||
150 | |||
151 | int MaliVideoDriver::writeCounters(mxml_node_t *root) const { | ||
152 | if (access("/dev/mv500", F_OK) != 0) { | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | int count = 0; | ||
157 | for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { | ||
158 | mxml_node_t *node = mxmlNewElement(root, "counter"); | ||
159 | mxmlElementSetAttr(node, "name", counter->getName()); | ||
160 | ++count; | ||
161 | } | ||
162 | |||
163 | return count; | ||
164 | } | ||
165 | |||
166 | void MaliVideoDriver::marshalEnable(const MaliVideoCounterType type, char *const buf, const size_t bufsize, int &pos) { | ||
167 | // size | ||
168 | int numEnabled = 0; | ||
169 | for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { | ||
170 | if (counter->isEnabled() && (counter->getType() == type)) { | ||
171 | ++numEnabled; | ||
172 | } | ||
173 | } | ||
174 | Buffer::packInt(buf, bufsize, pos, numEnabled*sizeof(uint32_t)); | ||
175 | for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { | ||
176 | if (counter->isEnabled() && (counter->getType() == type)) { | ||
177 | Buffer::packInt(buf, bufsize, pos, counter->getId()); | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | bool MaliVideoDriver::start(const int mveUds) { | ||
183 | char buf[256]; | ||
184 | int pos = 0; | ||
185 | |||
186 | // code - MVE_INSTR_STARTUP | ||
187 | buf[pos++] = 'C'; | ||
188 | buf[pos++] = 'L'; | ||
189 | buf[pos++] = 'N'; | ||
190 | buf[pos++] = 'T'; | ||
191 | // size | ||
192 | Buffer::packInt(buf, sizeof(buf), pos, sizeof(uint32_t)); | ||
193 | // client_version_number | ||
194 | Buffer::packInt(buf, sizeof(buf), pos, 1); | ||
195 | |||
196 | // code - MVE_INSTR_CONFIGURE | ||
197 | buf[pos++] = 'C'; | ||
198 | buf[pos++] = 'N'; | ||
199 | buf[pos++] = 'F'; | ||
200 | buf[pos++] = 'G'; | ||
201 | // size | ||
202 | Buffer::packInt(buf, sizeof(buf), pos, 5*sizeof(uint32_t)); | ||
203 | // configuration | ||
204 | Buffer::packInt(buf, sizeof(buf), pos, MVE_INSTR_COUNTERS | MVE_INSTR_EVENTS | MVE_INSTR_ACTIVITIES | MVE_INSTR_PACKED_COMM); | ||
205 | // communication_protocol_version | ||
206 | Buffer::packInt(buf, sizeof(buf), pos, 1); | ||
207 | // data_protocol_version | ||
208 | Buffer::packInt(buf, sizeof(buf), pos, 1); | ||
209 | // sample_rate - convert samples/second to ms/sample | ||
210 | Buffer::packInt(buf, sizeof(buf), pos, 1000/gSessionData->mSampleRate); | ||
211 | // live_rate - convert ns/flush to ms/flush | ||
212 | Buffer::packInt(buf, sizeof(buf), pos, gSessionData->mLiveRate/1000000); | ||
213 | |||
214 | // code - MVE_INSTR_ENABLE_COUNTERS | ||
215 | buf[pos++] = 'C'; | ||
216 | buf[pos++] = 'F'; | ||
217 | buf[pos++] = 'G'; | ||
218 | buf[pos++] = 'c'; | ||
219 | marshalEnable(MVCT_COUNTER, buf, sizeof(buf), pos); | ||
220 | |||
221 | // code - MVE_INSTR_ENABLE_EVENTS | ||
222 | buf[pos++] = 'C'; | ||
223 | buf[pos++] = 'F'; | ||
224 | buf[pos++] = 'G'; | ||
225 | buf[pos++] = 'e'; | ||
226 | marshalEnable(MVCT_EVENT, buf, sizeof(buf), pos); | ||
227 | |||
228 | /* | ||
229 | // code - MVE_INSTR_ENABLE_ACTIVITIES | ||
230 | buf[pos++] = 'C'; | ||
231 | buf[pos++] = 'F'; | ||
232 | buf[pos++] = 'G'; | ||
233 | buf[pos++] = 'a'; | ||
234 | // size | ||
235 | Buffer::packInt(buf, sizeof(buf), pos, mActivityCount*sizeof(uint32_t)); | ||
236 | for (int i = 0; i < mActivityCount; ++i) { | ||
237 | // activity_id | ||
238 | Buffer::packInt(buf, sizeof(buf), pos, i); | ||
239 | } | ||
240 | */ | ||
241 | |||
242 | int written = 0; | ||
243 | while (written < pos) { | ||
244 | size_t bytes = ::write(mveUds, buf + written, pos - written); | ||
245 | if (bytes <= 0) { | ||
246 | logg->logMessage("%s(%s:%i): write failed", __FUNCTION__, __FILE__, __LINE__); | ||
247 | return false; | ||
248 | } | ||
249 | written += bytes; | ||
250 | } | ||
251 | |||
252 | return true; | ||
253 | } | ||
diff --git a/daemon/MaliVideoDriver.h b/daemon/MaliVideoDriver.h new file mode 100644 index 0000000..00cb808 --- /dev/null +++ b/daemon/MaliVideoDriver.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /** | ||
2 | * Copyright (C) ARM Limited 2014. 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 MALIVIDEODRIVER_H | ||
10 | #define MALIVIDEODRIVER_H | ||
11 | |||
12 | #include "Driver.h" | ||
13 | |||
14 | class MaliVideoCounter; | ||
15 | |||
16 | enum MaliVideoCounterType { | ||
17 | MVCT_COUNTER, | ||
18 | MVCT_EVENT, | ||
19 | MVCT_ACTIVITY, | ||
20 | }; | ||
21 | |||
22 | class MaliVideoDriver : public Driver { | ||
23 | public: | ||
24 | MaliVideoDriver(); | ||
25 | ~MaliVideoDriver(); | ||
26 | |||
27 | void setup(mxml_node_t *const xml); | ||
28 | |||
29 | bool claimCounter(const Counter &counter) const; | ||
30 | bool countersEnabled() const; | ||
31 | void resetCounters(); | ||
32 | void setupCounter(Counter &counter); | ||
33 | |||
34 | int writeCounters(mxml_node_t *root) const; | ||
35 | |||
36 | bool start(const int mveUds); | ||
37 | |||
38 | private: | ||
39 | MaliVideoCounter *findCounter(const Counter &counter) const; | ||
40 | void marshalEnable(const MaliVideoCounterType type, char *const buf, const size_t bufsize, int &pos); | ||
41 | |||
42 | MaliVideoCounter *mCounters; | ||
43 | int mActivityCount; | ||
44 | |||
45 | // Intentionally unimplemented | ||
46 | MaliVideoDriver(const MaliVideoDriver &); | ||
47 | MaliVideoDriver &operator=(const MaliVideoDriver &); | ||
48 | }; | ||
49 | |||
50 | #endif // MALIVIDEODRIVER_H | ||
diff --git a/daemon/Monitor.cpp b/daemon/Monitor.cpp index 90d5c47..b34a15f 100644 --- a/daemon/Monitor.cpp +++ b/daemon/Monitor.cpp | |||
@@ -18,8 +18,15 @@ Monitor::Monitor() : mFd(-1) { | |||
18 | } | 18 | } |
19 | 19 | ||
20 | Monitor::~Monitor() { | 20 | Monitor::~Monitor() { |
21 | if (mFd >= -1) { | 21 | if (mFd >= 0) { |
22 | close(mFd); | 22 | ::close(mFd); |
23 | } | ||
24 | } | ||
25 | |||
26 | void Monitor::close() { | ||
27 | if (mFd >= 0) { | ||
28 | ::close(mFd); | ||
29 | mFd = -1; | ||
23 | } | 30 | } |
24 | } | 31 | } |
25 | 32 | ||
diff --git a/daemon/Monitor.h b/daemon/Monitor.h index 6e268b6..7194e0e 100644 --- a/daemon/Monitor.h +++ b/daemon/Monitor.h | |||
@@ -16,6 +16,7 @@ public: | |||
16 | Monitor(); | 16 | Monitor(); |
17 | ~Monitor(); | 17 | ~Monitor(); |
18 | 18 | ||
19 | void close(); | ||
19 | bool init(); | 20 | bool init(); |
20 | bool add(const int fd); | 21 | bool add(const int fd); |
21 | int wait(struct epoll_event *const events, int maxevents, int timeout); | 22 | int wait(struct epoll_event *const events, int maxevents, int timeout); |
diff --git a/daemon/OlySocket.cpp b/daemon/OlySocket.cpp index 26e4768..28774e3 100644 --- a/daemon/OlySocket.cpp +++ b/daemon/OlySocket.cpp | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "OlySocket.h" | 9 | #include "OlySocket.h" |
10 | 10 | ||
11 | #include <stdio.h> | 11 | #include <stdio.h> |
12 | #include <string.h> | ||
12 | #ifdef WIN32 | 13 | #ifdef WIN32 |
13 | #include <Winsock2.h> | 14 | #include <Winsock2.h> |
14 | #include <ws2tcpip.h> | 15 | #include <ws2tcpip.h> |
@@ -43,16 +44,18 @@ OlyServerSocket::OlyServerSocket(int port) { | |||
43 | createServerSocket(port); | 44 | createServerSocket(port); |
44 | } | 45 | } |
45 | 46 | ||
46 | OlySocket::OlySocket(int port, const char* host) { | ||
47 | createClientSocket(host, port); | ||
48 | } | ||
49 | |||
50 | OlySocket::OlySocket(int socketID) : mSocketID(socketID) { | 47 | OlySocket::OlySocket(int socketID) : mSocketID(socketID) { |
51 | } | 48 | } |
52 | 49 | ||
53 | #ifndef WIN32 | 50 | #ifndef WIN32 |
54 | 51 | ||
55 | OlyServerSocket::OlyServerSocket(const char* path) { | 52 | #define MIN(A, B) ({ \ |
53 | const __typeof__(A) __a = A; \ | ||
54 | const __typeof__(B) __b = B; \ | ||
55 | __a > __b ? __b : __a; \ | ||
56 | }) | ||
57 | |||
58 | OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) { | ||
56 | // Create socket | 59 | // Create socket |
57 | mFDServer = socket(PF_UNIX, SOCK_STREAM, 0); | 60 | mFDServer = socket(PF_UNIX, SOCK_STREAM, 0); |
58 | if (mFDServer < 0) { | 61 | if (mFDServer < 0) { |
@@ -60,13 +63,11 @@ OlyServerSocket::OlyServerSocket(const char* path) { | |||
60 | handleException(); | 63 | handleException(); |
61 | } | 64 | } |
62 | 65 | ||
63 | unlink(path); | ||
64 | |||
65 | // Create sockaddr_in structure, ensuring non-populated fields are zero | 66 | // Create sockaddr_in structure, ensuring non-populated fields are zero |
66 | struct sockaddr_un sockaddr; | 67 | struct sockaddr_un sockaddr; |
67 | memset((void*)&sockaddr, 0, sizeof(sockaddr)); | 68 | memset((void*)&sockaddr, 0, sizeof(sockaddr)); |
68 | sockaddr.sun_family = AF_UNIX; | 69 | sockaddr.sun_family = AF_UNIX; |
69 | strncpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1); | 70 | memcpy(sockaddr.sun_path, path, MIN(pathSize, sizeof(sockaddr.sun_path))); |
70 | sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0'; | 71 | sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0'; |
71 | 72 | ||
72 | // Bind the socket to an address | 73 | // Bind the socket to an address |
@@ -82,24 +83,25 @@ OlyServerSocket::OlyServerSocket(const char* path) { | |||
82 | } | 83 | } |
83 | } | 84 | } |
84 | 85 | ||
85 | OlySocket::OlySocket(const char* path) { | 86 | int OlySocket::connect(const char* path, const size_t pathSize) { |
86 | mSocketID = socket(PF_UNIX, SOCK_STREAM, 0); | 87 | int fd = socket(PF_UNIX, SOCK_STREAM, 0); |
87 | if (mSocketID < 0) { | 88 | if (fd < 0) { |
88 | return; | 89 | return -1; |
89 | } | 90 | } |
90 | 91 | ||
91 | // Create sockaddr_in structure, ensuring non-populated fields are zero | 92 | // Create sockaddr_in structure, ensuring non-populated fields are zero |
92 | struct sockaddr_un sockaddr; | 93 | struct sockaddr_un sockaddr; |
93 | memset((void*)&sockaddr, 0, sizeof(sockaddr)); | 94 | memset((void*)&sockaddr, 0, sizeof(sockaddr)); |
94 | sockaddr.sun_family = AF_UNIX; | 95 | sockaddr.sun_family = AF_UNIX; |
95 | strncpy(sockaddr.sun_path, path, sizeof(sockaddr.sun_path) - 1); | 96 | memcpy(sockaddr.sun_path, path, MIN(pathSize, sizeof(sockaddr.sun_path))); |
96 | sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0'; | 97 | sockaddr.sun_path[sizeof(sockaddr.sun_path) - 1] = '\0'; |
97 | 98 | ||
98 | if (connect(mSocketID, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) { | 99 | if (::connect(fd, (const struct sockaddr*)&sockaddr, sizeof(sockaddr)) < 0) { |
99 | close(mSocketID); | 100 | close(fd); |
100 | mSocketID = -1; | 101 | return -1; |
101 | return; | ||
102 | } | 102 | } |
103 | |||
104 | return fd; | ||
103 | } | 105 | } |
104 | 106 | ||
105 | #endif | 107 | #endif |
@@ -137,47 +139,6 @@ void OlyServerSocket::closeServerSocket() { | |||
137 | mFDServer = 0; | 139 | mFDServer = 0; |
138 | } | 140 | } |
139 | 141 | ||
140 | void OlySocket::createClientSocket(const char* hostname, int portno) { | ||
141 | #ifdef WIN32 | ||
142 | // TODO: Implement for Windows | ||
143 | #else | ||
144 | char buf[32]; | ||
145 | struct addrinfo hints, *res, *res0; | ||
146 | |||
147 | snprintf(buf, sizeof(buf), "%d", portno); | ||
148 | mSocketID = -1; | ||
149 | memset((void*)&hints, 0, sizeof(hints)); | ||
150 | hints.ai_family = PF_UNSPEC; | ||
151 | hints.ai_socktype = SOCK_STREAM; | ||
152 | |||
153 | if (getaddrinfo(hostname, buf, &hints, &res0)) { | ||
154 | logg->logError(__FILE__, __LINE__, "Client socket failed to get address info for %s", hostname); | ||
155 | handleException(); | ||
156 | } | ||
157 | for (res=res0; res!=NULL; res = res->ai_next) { | ||
158 | if ( res->ai_family != PF_INET || res->ai_socktype != SOCK_STREAM ) { | ||
159 | continue; | ||
160 | } | ||
161 | mSocketID = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | ||
162 | if (mSocketID < 0) { | ||
163 | continue; | ||
164 | } | ||
165 | if (connect(mSocketID, res->ai_addr, res->ai_addrlen) < 0) { | ||
166 | close(mSocketID); | ||
167 | mSocketID = -1; | ||
168 | } | ||
169 | if (mSocketID > 0) { | ||
170 | break; | ||
171 | } | ||
172 | } | ||
173 | freeaddrinfo(res0); | ||
174 | if (mSocketID <= 0) { | ||
175 | logg->logError(__FILE__, __LINE__, "Could not connect to client socket. Ensure ARM Streamline is running."); | ||
176 | handleException(); | ||
177 | } | ||
178 | #endif | ||
179 | } | ||
180 | |||
181 | void OlyServerSocket::createServerSocket(int port) { | 142 | void OlyServerSocket::createServerSocket(int port) { |
182 | int family = AF_INET6; | 143 | int family = AF_INET6; |
183 | 144 | ||
diff --git a/daemon/OlySocket.h b/daemon/OlySocket.h index eab786b..20c67cc 100644 --- a/daemon/OlySocket.h +++ b/daemon/OlySocket.h | |||
@@ -9,13 +9,15 @@ | |||
9 | #ifndef __OLY_SOCKET_H__ | 9 | #ifndef __OLY_SOCKET_H__ |
10 | #define __OLY_SOCKET_H__ | 10 | #define __OLY_SOCKET_H__ |
11 | 11 | ||
12 | #include <stddef.h> | ||
13 | |||
12 | class OlySocket { | 14 | class OlySocket { |
13 | public: | 15 | public: |
14 | OlySocket(int port, const char* hostname); | ||
15 | OlySocket(int socketID); | ||
16 | #ifndef WIN32 | 16 | #ifndef WIN32 |
17 | OlySocket(const char* path); | 17 | static int connect(const char* path, const size_t pathSize); |
18 | #endif | 18 | #endif |
19 | |||
20 | OlySocket(int socketID); | ||
19 | ~OlySocket(); | 21 | ~OlySocket(); |
20 | 22 | ||
21 | void closeSocket(); | 23 | void closeSocket(); |
@@ -29,21 +31,21 @@ public: | |||
29 | 31 | ||
30 | private: | 32 | private: |
31 | int mSocketID; | 33 | int mSocketID; |
32 | |||
33 | void createClientSocket(const char* hostname, int port); | ||
34 | }; | 34 | }; |
35 | 35 | ||
36 | class OlyServerSocket { | 36 | class OlyServerSocket { |
37 | public: | 37 | public: |
38 | OlyServerSocket(int port); | 38 | OlyServerSocket(int port); |
39 | #ifndef WIN32 | 39 | #ifndef WIN32 |
40 | OlyServerSocket(const char* path); | 40 | OlyServerSocket(const char* path, const size_t pathSize); |
41 | #endif | 41 | #endif |
42 | ~OlyServerSocket(); | 42 | ~OlyServerSocket(); |
43 | 43 | ||
44 | int acceptConnection(); | 44 | int acceptConnection(); |
45 | void closeServerSocket(); | 45 | void closeServerSocket(); |
46 | 46 | ||
47 | int getFd() { return mFDServer; } | ||
48 | |||
47 | private: | 49 | private: |
48 | int mFDServer; | 50 | int mFDServer; |
49 | 51 | ||
diff --git a/daemon/PerfDriver.cpp b/daemon/PerfDriver.cpp index 8e25c22..ac97a07 100644 --- a/daemon/PerfDriver.cpp +++ b/daemon/PerfDriver.cpp | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <dirent.h> | 11 | #include <dirent.h> |
12 | #include <sys/utsname.h> | 12 | #include <sys/utsname.h> |
13 | #include <time.h> | 13 | #include <time.h> |
14 | #include <unistd.h> | ||
14 | 15 | ||
15 | #include "Buffer.h" | 16 | #include "Buffer.h" |
16 | #include "Config.h" | 17 | #include "Config.h" |
@@ -30,7 +31,7 @@ | |||
30 | struct gator_cpu { | 31 | struct gator_cpu { |
31 | const int cpuid; | 32 | const int cpuid; |
32 | // Human readable name | 33 | // Human readable name |
33 | const char core_name[32]; | 34 | const char *const core_name; |
34 | // gatorfs event and Perf PMU name | 35 | // gatorfs event and Perf PMU name |
35 | const char *const pmnc_name; | 36 | const char *const pmnc_name; |
36 | const int pmnc_counters; | 37 | const int pmnc_counters; |
@@ -62,9 +63,20 @@ static const struct gator_cpu gator_cpus[] = { | |||
62 | static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-"; | 63 | static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-"; |
63 | static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_"; | 64 | static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_"; |
64 | 65 | ||
66 | struct uncore_counter { | ||
67 | // gatorfs event and Perf PMU name | ||
68 | const char *const name; | ||
69 | const int count; | ||
70 | }; | ||
71 | |||
72 | static const struct uncore_counter uncore_counters[] = { | ||
73 | { "CCI_400", 4 }, | ||
74 | { "CCI_400-r1", 4 }, | ||
75 | }; | ||
76 | |||
65 | class PerfCounter { | 77 | class PerfCounter { |
66 | public: | 78 | public: |
67 | PerfCounter(PerfCounter *next, const char *name, uint32_t type, uint64_t config) : mNext(next), mName(name), mType(type), mCount(0), mKey(getEventKey()), mConfig(config), mEnabled(false) {} | 79 | PerfCounter(PerfCounter *next, const char *name, uint32_t type, uint64_t config, bool perCpu) : mNext(next), mName(name), mType(type), mCount(0), mKey(getEventKey()), mConfig(config), mEnabled(false), mPerCpu(perCpu) {} |
68 | ~PerfCounter() { | 80 | ~PerfCounter() { |
69 | delete [] mName; | 81 | delete [] mName; |
70 | } | 82 | } |
@@ -79,6 +91,7 @@ public: | |||
79 | void setConfig(const uint64_t config) { mConfig = config; } | 91 | void setConfig(const uint64_t config) { mConfig = config; } |
80 | bool isEnabled() const { return mEnabled; } | 92 | bool isEnabled() const { return mEnabled; } |
81 | void setEnabled(const bool enabled) { mEnabled = enabled; } | 93 | void setEnabled(const bool enabled) { mEnabled = enabled; } |
94 | bool isPerCpu() const { return mPerCpu; } | ||
82 | 95 | ||
83 | private: | 96 | private: |
84 | PerfCounter *const mNext; | 97 | PerfCounter *const mNext; |
@@ -87,10 +100,11 @@ private: | |||
87 | int mCount; | 100 | int mCount; |
88 | const int mKey; | 101 | const int mKey; |
89 | uint64_t mConfig; | 102 | uint64_t mConfig; |
90 | bool mEnabled; | 103 | int mEnabled : 1, |
104 | mPerCpu : 1; | ||
91 | }; | 105 | }; |
92 | 106 | ||
93 | PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false) { | 107 | PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false), mLegacySupport(false) { |
94 | } | 108 | } |
95 | 109 | ||
96 | PerfDriver::~PerfDriver() { | 110 | PerfDriver::~PerfDriver() { |
@@ -105,13 +119,27 @@ void PerfDriver::addCpuCounters(const char *const counterName, const int type, c | |||
105 | int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1; | 119 | int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1; |
106 | char *name = new char[len]; | 120 | char *name = new char[len]; |
107 | snprintf(name, len, "%s_ccnt", counterName); | 121 | snprintf(name, len, "%s_ccnt", counterName); |
108 | mCounters = new PerfCounter(mCounters, name, type, -1); | 122 | mCounters = new PerfCounter(mCounters, name, type, -1, true); |
109 | 123 | ||
110 | for (int j = 0; j < numCounters; ++j) { | 124 | for (int j = 0; j < numCounters; ++j) { |
111 | len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1; | 125 | len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1; |
112 | name = new char[len]; | 126 | name = new char[len]; |
113 | snprintf(name, len, "%s_cnt%d", counterName, j); | 127 | snprintf(name, len, "%s_cnt%d", counterName, j); |
114 | mCounters = new PerfCounter(mCounters, name, type, -1); | 128 | mCounters = new PerfCounter(mCounters, name, type, -1, true); |
129 | } | ||
130 | } | ||
131 | |||
132 | void PerfDriver::addUncoreCounters(const char *const counterName, const int type, const int numCounters) { | ||
133 | int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1; | ||
134 | char *name = new char[len]; | ||
135 | snprintf(name, len, "%s_ccnt", counterName); | ||
136 | mCounters = new PerfCounter(mCounters, name, type, -1, false); | ||
137 | |||
138 | for (int j = 0; j < numCounters; ++j) { | ||
139 | len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1; | ||
140 | name = new char[len]; | ||
141 | snprintf(name, len, "%s_cnt%d", counterName, j); | ||
142 | mCounters = new PerfCounter(mCounters, name, type, -1, false); | ||
115 | } | 143 | } |
116 | } | 144 | } |
117 | 145 | ||
@@ -139,10 +167,16 @@ bool PerfDriver::setup() { | |||
139 | } | 167 | } |
140 | } | 168 | } |
141 | 169 | ||
142 | if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0)) { | 170 | if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 4, 0)) { |
143 | logg->logMessage("%s(%s:%i): Unsupported kernel version", __FUNCTION__, __FILE__, __LINE__); | 171 | logg->logMessage("%s(%s:%i): Unsupported kernel version", __FUNCTION__, __FILE__, __LINE__); |
144 | return false; | 172 | return false; |
145 | } | 173 | } |
174 | mLegacySupport = KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0); | ||
175 | |||
176 | if (access(EVENTS_PATH, R_OK) != 0) { | ||
177 | logg->logMessage("%s(%s:%i): " EVENTS_PATH " does not exist, is CONFIG_TRACING enabled?", __FUNCTION__, __FILE__, __LINE__); | ||
178 | return false; | ||
179 | } | ||
146 | 180 | ||
147 | // Add supported PMUs | 181 | // Add supported PMUs |
148 | bool foundCpu = false; | 182 | bool foundCpu = false; |
@@ -174,6 +208,21 @@ bool PerfDriver::setup() { | |||
174 | foundCpu = true; | 208 | foundCpu = true; |
175 | addCpuCounters(gator_cpus[i].pmnc_name, type, gator_cpus[i].pmnc_counters); | 209 | addCpuCounters(gator_cpus[i].pmnc_name, type, gator_cpus[i].pmnc_counters); |
176 | } | 210 | } |
211 | |||
212 | for (int i = 0; i < ARRAY_LENGTH(uncore_counters); ++i) { | ||
213 | if (strcmp(dirent->d_name, uncore_counters[i].name) != 0) { | ||
214 | continue; | ||
215 | } | ||
216 | |||
217 | int type; | ||
218 | char buf[256]; | ||
219 | snprintf(buf, sizeof(buf), PERF_DEVICES "/%s/type", dirent->d_name); | ||
220 | if (DriverSource::readIntDriver(buf, &type) != 0) { | ||
221 | continue; | ||
222 | } | ||
223 | |||
224 | addUncoreCounters(uncore_counters[i].name, type, uncore_counters[i].count); | ||
225 | } | ||
177 | } | 226 | } |
178 | closedir(dir); | 227 | closedir(dir); |
179 | 228 | ||
@@ -203,12 +252,12 @@ bool PerfDriver::setup() { | |||
203 | 252 | ||
204 | id = getTracepointId("irq/softirq_exit", &printb); | 253 | id = getTracepointId("irq/softirq_exit", &printb); |
205 | if (id >= 0) { | 254 | if (id >= 0) { |
206 | mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id); | 255 | mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, true); |
207 | } | 256 | } |
208 | 257 | ||
209 | id = getTracepointId("irq/irq_handler_exit", &printb); | 258 | id = getTracepointId("irq/irq_handler_exit", &printb); |
210 | if (id >= 0) { | 259 | if (id >= 0) { |
211 | mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id); | 260 | mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, true); |
212 | } | 261 | } |
213 | 262 | ||
214 | //Linux_block_rq_wr | 263 | //Linux_block_rq_wr |
@@ -218,7 +267,7 @@ bool PerfDriver::setup() { | |||
218 | 267 | ||
219 | id = getTracepointId(SCHED_SWITCH, &printb); | 268 | id = getTracepointId(SCHED_SWITCH, &printb); |
220 | if (id >= 0) { | 269 | if (id >= 0) { |
221 | mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id); | 270 | mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true); |
222 | } | 271 | } |
223 | 272 | ||
224 | //Linux_meminfo_memused | 273 | //Linux_meminfo_memused |
@@ -227,7 +276,7 @@ bool PerfDriver::setup() { | |||
227 | //Linux_power_cpu_freq | 276 | //Linux_power_cpu_freq |
228 | //Linux_power_cpu_idle | 277 | //Linux_power_cpu_idle |
229 | 278 | ||
230 | mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1); | 279 | mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false); |
231 | 280 | ||
232 | //Linux_cpu_wait_io | 281 | //Linux_cpu_wait_io |
233 | 282 | ||
@@ -252,15 +301,16 @@ bool PerfDriver::summary(Buffer *const buffer) { | |||
252 | } | 301 | } |
253 | const int64_t timestamp = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec; | 302 | const int64_t timestamp = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec; |
254 | 303 | ||
255 | if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) { | 304 | const int64_t uptime = getTime(); |
256 | logg->logMessage("%s(%s:%i): clock_gettime failed", __FUNCTION__, __FILE__, __LINE__); | ||
257 | return false; | ||
258 | } | ||
259 | const int64_t uptime = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec; | ||
260 | 305 | ||
261 | buffer->summary(timestamp, uptime, 0, buf); | 306 | buffer->summary(timestamp, uptime, 0, buf); |
262 | 307 | ||
263 | for (int i = 0; i < gSessionData->mCores; ++i) { | 308 | for (int i = 0; i < gSessionData->mCores; ++i) { |
309 | // Don't send information on a cpu we know nothing about | ||
310 | if (gSessionData->mCpuIds[i] == -1) { | ||
311 | continue; | ||
312 | } | ||
313 | |||
264 | int j; | 314 | int j; |
265 | for (j = 0; j < ARRAY_LENGTH(gator_cpus); ++j) { | 315 | for (j = 0; j < ARRAY_LENGTH(gator_cpus); ++j) { |
266 | if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) { | 316 | if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) { |
@@ -270,7 +320,11 @@ bool PerfDriver::summary(Buffer *const buffer) { | |||
270 | if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) { | 320 | if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) { |
271 | buffer->coreName(i, gSessionData->mCpuIds[i], gator_cpus[j].core_name); | 321 | buffer->coreName(i, gSessionData->mCpuIds[i], gator_cpus[j].core_name); |
272 | } else { | 322 | } else { |
273 | snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[i]); | 323 | if (gSessionData->mCpuIds[i] == -1) { |
324 | snprintf(buf, sizeof(buf), "Unknown"); | ||
325 | } else { | ||
326 | snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[i]); | ||
327 | } | ||
274 | buffer->coreName(i, gSessionData->mCpuIds[i], buf); | 328 | buffer->coreName(i, gSessionData->mCpuIds[i], buf); |
275 | } | 329 | } |
276 | } | 330 | } |
@@ -326,10 +380,10 @@ int PerfDriver::writeCounters(mxml_node_t *root) const { | |||
326 | return count; | 380 | return count; |
327 | } | 381 | } |
328 | 382 | ||
329 | bool PerfDriver::enable(PerfGroup *group, Buffer *const buffer) const { | 383 | bool PerfDriver::enable(PerfGroup *const group, Buffer *const buffer) const { |
330 | for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { | 384 | for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) { |
331 | if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) { | 385 | if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) { |
332 | if (!group->add(buffer, counter->getKey(), counter->getType(), counter->getConfig(), counter->getCount(), 0, 0)) { | 386 | if (!group->add(buffer, counter->getKey(), counter->getType(), counter->getConfig(), counter->getCount(), counter->getCount() > 0 ? PERF_SAMPLE_TID | PERF_SAMPLE_IP : 0, counter->isPerCpu() ? PERF_GROUP_PER_CPU : 0)) { |
333 | logg->logMessage("%s(%s:%i): PerfGroup::add failed", __FUNCTION__, __FILE__, __LINE__); | 387 | logg->logMessage("%s(%s:%i): PerfGroup::add failed", __FUNCTION__, __FILE__, __LINE__); |
334 | return false; | 388 | return false; |
335 | } | 389 | } |
diff --git a/daemon/PerfDriver.h b/daemon/PerfDriver.h index 3181b74..2cae575 100644 --- a/daemon/PerfDriver.h +++ b/daemon/PerfDriver.h | |||
@@ -27,6 +27,8 @@ public: | |||
27 | PerfDriver(); | 27 | PerfDriver(); |
28 | ~PerfDriver(); | 28 | ~PerfDriver(); |
29 | 29 | ||
30 | bool getLegacySupport() const { return mLegacySupport; } | ||
31 | |||
30 | bool setup(); | 32 | bool setup(); |
31 | bool summary(Buffer *const buffer); | 33 | bool summary(Buffer *const buffer); |
32 | bool isSetup() const { return mIsSetup; } | 34 | bool isSetup() const { return mIsSetup; } |
@@ -37,16 +39,18 @@ public: | |||
37 | 39 | ||
38 | int writeCounters(mxml_node_t *root) const; | 40 | int writeCounters(mxml_node_t *root) const; |
39 | 41 | ||
40 | bool enable(PerfGroup *group, Buffer *const buffer) const; | 42 | bool enable(PerfGroup *const group, Buffer *const buffer) const; |
41 | 43 | ||
42 | static long long getTracepointId(const char *const name, DynBuf *const printb); | 44 | static long long getTracepointId(const char *const name, DynBuf *const printb); |
43 | 45 | ||
44 | private: | 46 | private: |
45 | PerfCounter *findCounter(const Counter &counter) const; | 47 | PerfCounter *findCounter(const Counter &counter) const; |
46 | void addCpuCounters(const char *const counterName, const int type, const int numCounters); | 48 | void addCpuCounters(const char *const counterName, const int type, const int numCounters); |
49 | void addUncoreCounters(const char *const counterName, const int type, const int numCounters); | ||
47 | 50 | ||
48 | PerfCounter *mCounters; | 51 | PerfCounter *mCounters; |
49 | bool mIsSetup; | 52 | bool mIsSetup; |
53 | bool mLegacySupport; | ||
50 | 54 | ||
51 | // Intentionally undefined | 55 | // Intentionally undefined |
52 | PerfDriver(const PerfDriver &); | 56 | PerfDriver(const PerfDriver &); |
diff --git a/daemon/PerfGroup.cpp b/daemon/PerfGroup.cpp index faf5fca..2a0239f 100644 --- a/daemon/PerfGroup.cpp +++ b/daemon/PerfGroup.cpp | |||
@@ -23,7 +23,9 @@ | |||
23 | #define DEFAULT_PEA_ARGS(pea, additionalSampleType) \ | 23 | #define DEFAULT_PEA_ARGS(pea, additionalSampleType) \ |
24 | pea.size = sizeof(pea); \ | 24 | pea.size = sizeof(pea); \ |
25 | /* Emit time, read_format below, group leader id, and raw tracepoint info */ \ | 25 | /* Emit time, read_format below, group leader id, and raw tracepoint info */ \ |
26 | pea.sample_type = PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_IDENTIFIER | additionalSampleType; \ | 26 | pea.sample_type = (gSessionData->perf.getLegacySupport() \ |
27 | ? PERF_SAMPLE_TID | PERF_SAMPLE_IP | PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_ID \ | ||
28 | : PERF_SAMPLE_TIME | PERF_SAMPLE_READ | PERF_SAMPLE_IDENTIFIER ) | additionalSampleType; \ | ||
27 | /* Emit emit value in group format */ \ | 29 | /* Emit emit value in group format */ \ |
28 | pea.read_format = PERF_FORMAT_ID | PERF_FORMAT_GROUP; \ | 30 | pea.read_format = PERF_FORMAT_ID | PERF_FORMAT_GROUP; \ |
29 | /* start out disabled */ \ | 31 | /* start out disabled */ \ |
@@ -39,6 +41,7 @@ static int sys_perf_event_open(struct perf_event_attr *const attr, const pid_t p | |||
39 | 41 | ||
40 | PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb) { | 42 | PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb) { |
41 | memset(&mAttrs, 0, sizeof(mAttrs)); | 43 | memset(&mAttrs, 0, sizeof(mAttrs)); |
44 | memset(&mPerCpu, 0, sizeof(mPerCpu)); | ||
42 | memset(&mKeys, -1, sizeof(mKeys)); | 45 | memset(&mKeys, -1, sizeof(mKeys)); |
43 | memset(&mFds, -1, sizeof(mFds)); | 46 | memset(&mFds, -1, sizeof(mFds)); |
44 | } | 47 | } |
@@ -75,6 +78,7 @@ bool PerfGroup::add(Buffer *const buffer, const int key, const __u32 type, const | |||
75 | mAttrs[i].freq = (flags & PERF_GROUP_FREQ ? 1 : 0); | 78 | mAttrs[i].freq = (flags & PERF_GROUP_FREQ ? 1 : 0); |
76 | mAttrs[i].task = (flags & PERF_GROUP_TASK ? 1 : 0); | 79 | mAttrs[i].task = (flags & PERF_GROUP_TASK ? 1 : 0); |
77 | mAttrs[i].sample_id_all = (flags & PERF_GROUP_SAMPLE_ID_ALL ? 1 : 0); | 80 | mAttrs[i].sample_id_all = (flags & PERF_GROUP_SAMPLE_ID_ALL ? 1 : 0); |
81 | mPerCpu[i] = (flags & PERF_GROUP_PER_CPU); | ||
78 | 82 | ||
79 | mKeys[i] = key; | 83 | mKeys[i] = key; |
80 | 84 | ||
@@ -91,13 +95,17 @@ bool PerfGroup::prepareCPU(const int cpu) { | |||
91 | continue; | 95 | continue; |
92 | } | 96 | } |
93 | 97 | ||
98 | if ((cpu != 0) && !mPerCpu[i]) { | ||
99 | continue; | ||
100 | } | ||
101 | |||
94 | const int offset = i * gSessionData->mCores; | 102 | const int offset = i * gSessionData->mCores; |
95 | if (mFds[cpu + offset] >= 0) { | 103 | if (mFds[cpu + offset] >= 0) { |
96 | logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__); | 104 | logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__); |
97 | return false; | 105 | return false; |
98 | } | 106 | } |
99 | 107 | ||
100 | logg->logMessage("%s(%s:%i): perf_event_open cpu: %i type: %lli config: %lli sample: %lli sample_type: %lli", __FUNCTION__, __FILE__, __LINE__, cpu, (long long)mAttrs[i].type, (long long)mAttrs[i].config, (long long)mAttrs[i].sample_period, (long long)mAttrs[i].sample_type); | 108 | logg->logMessage("%s(%s:%i): perf_event_open cpu: %i type: %lli config: %lli sample: %lli sample_type: 0x%llx pinned: %i mmap: %i comm: %i freq: %i task: %i sample_id_all: %i", __FUNCTION__, __FILE__, __LINE__, cpu, (long long)mAttrs[i].type, (long long)mAttrs[i].config, (long long)mAttrs[i].sample_period, (long long)mAttrs[i].sample_type, mAttrs[i].pinned, mAttrs[i].mmap, mAttrs[i].comm, mAttrs[i].freq, mAttrs[i].task, mAttrs[i].sample_id_all); |
101 | mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT); | 109 | mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT); |
102 | if (mFds[cpu + offset] < 0) { | 110 | if (mFds[cpu + offset] < 0) { |
103 | logg->logMessage("%s(%s:%i): failed %s", __FUNCTION__, __FILE__, __LINE__, strerror(errno)); | 111 | logg->logMessage("%s(%s:%i): failed %s", __FUNCTION__, __FILE__, __LINE__, strerror(errno)); |
@@ -125,7 +133,9 @@ int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer, | |||
125 | } | 133 | } |
126 | 134 | ||
127 | coreKeys[idCount] = mKeys[i]; | 135 | coreKeys[idCount] = mKeys[i]; |
128 | if (ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0) { | 136 | if (!gSessionData->perf.getLegacySupport() && ioctl(fd, PERF_EVENT_IOC_ID, &ids[idCount]) != 0 && |
137 | // Workaround for running 32-bit gatord on 64-bit systems, kernel patch in the works | ||
138 | ioctl(fd, (PERF_EVENT_IOC_ID & ~IOCSIZE_MASK) | (8 << _IOC_SIZESHIFT), &ids[idCount]) != 0) { | ||
129 | logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__); | 139 | logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__); |
130 | return false; | 140 | return false; |
131 | } | 141 | } |
@@ -137,7 +147,17 @@ int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer, | |||
137 | return false; | 147 | return false; |
138 | } | 148 | } |
139 | 149 | ||
140 | buffer->keys(idCount, ids, coreKeys); | 150 | if (!gSessionData->perf.getLegacySupport()) { |
151 | buffer->keys(idCount, ids, coreKeys); | ||
152 | } else { | ||
153 | char buf[1024]; | ||
154 | ssize_t bytes = read(mFds[cpu], buf, sizeof(buf)); | ||
155 | if (bytes < 0) { | ||
156 | logg->logMessage("read failed"); | ||
157 | return false; | ||
158 | } | ||
159 | buffer->keysOld(idCount, coreKeys, bytes, buf); | ||
160 | } | ||
141 | 161 | ||
142 | if (start) { | 162 | if (start) { |
143 | for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { | 163 | for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) { |
diff --git a/daemon/PerfGroup.h b/daemon/PerfGroup.h index af496d4..3f1e2bb 100644 --- a/daemon/PerfGroup.h +++ b/daemon/PerfGroup.h | |||
@@ -24,6 +24,7 @@ enum PerfGroupFlags { | |||
24 | PERF_GROUP_FREQ = 1 << 2, | 24 | PERF_GROUP_FREQ = 1 << 2, |
25 | PERF_GROUP_TASK = 1 << 3, | 25 | PERF_GROUP_TASK = 1 << 3, |
26 | PERF_GROUP_SAMPLE_ID_ALL = 1 << 4, | 26 | PERF_GROUP_SAMPLE_ID_ALL = 1 << 4, |
27 | PERF_GROUP_PER_CPU = 1 << 5, | ||
27 | }; | 28 | }; |
28 | 29 | ||
29 | class PerfGroup { | 30 | class PerfGroup { |
@@ -43,6 +44,7 @@ public: | |||
43 | private: | 44 | private: |
44 | // +1 for the group leader | 45 | // +1 for the group leader |
45 | struct perf_event_attr mAttrs[MAX_PERFORMANCE_COUNTERS + 1]; | 46 | struct perf_event_attr mAttrs[MAX_PERFORMANCE_COUNTERS + 1]; |
47 | bool mPerCpu[MAX_PERFORMANCE_COUNTERS + 1]; | ||
46 | int mKeys[MAX_PERFORMANCE_COUNTERS + 1]; | 48 | int mKeys[MAX_PERFORMANCE_COUNTERS + 1]; |
47 | int mFds[NR_CPUS * (MAX_PERFORMANCE_COUNTERS + 1)]; | 49 | int mFds[NR_CPUS * (MAX_PERFORMANCE_COUNTERS + 1)]; |
48 | PerfBuffer *const mPb; | 50 | PerfBuffer *const mPb; |
diff --git a/daemon/PerfSource.cpp b/daemon/PerfSource.cpp index 1f1cb19..ecfaa66 100644 --- a/daemon/PerfSource.cpp +++ b/daemon/PerfSource.cpp | |||
@@ -37,7 +37,7 @@ static bool sendTracepointFormat(Buffer *const buffer, const char *const name, D | |||
37 | return true; | 37 | return true; |
38 | } | 38 | } |
39 | 39 | ||
40 | PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(0, FRAME_PERF_ATTRS, 1024*1024, senderSem), mCountersBuf(), mCountersGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) { | 40 | PerfSource::PerfSource(sem_t *senderSem, sem_t *startProfile) : mSummary(0, FRAME_SUMMARY, 1024, senderSem), mBuffer(0, FRAME_PERF_ATTRS, 4*1024*1024, senderSem), mCountersBuf(), mCountersGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) { |
41 | long l = sysconf(_SC_PAGE_SIZE); | 41 | long l = sysconf(_SC_PAGE_SIZE); |
42 | if (l < 0) { | 42 | if (l < 0) { |
43 | logg->logError(__FILE__, __LINE__, "Unable to obtain the page size"); | 43 | logg->logError(__FILE__, __LINE__, "Unable to obtain the page size"); |
@@ -74,6 +74,9 @@ bool PerfSource::prepare() { | |||
74 | DynBuf b3; | 74 | DynBuf b3; |
75 | long long schedSwitchId; | 75 | long long schedSwitchId; |
76 | 76 | ||
77 | // Reread cpuinfo since cores may have changed since startup | ||
78 | gSessionData->readCpuInfo(); | ||
79 | |||
77 | if (0 | 80 | if (0 |
78 | || !mMonitor.init() | 81 | || !mMonitor.init() |
79 | || !mUEvent.init() | 82 | || !mUEvent.init() |
@@ -83,14 +86,14 @@ bool PerfSource::prepare() { | |||
83 | || !sendTracepointFormat(&mBuffer, SCHED_SWITCH, &printb, &b1) | 86 | || !sendTracepointFormat(&mBuffer, SCHED_SWITCH, &printb, &b1) |
84 | 87 | ||
85 | // Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID | 88 | // Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID |
86 | || !mCountersGroup.add(&mBuffer, 100/**/, PERF_TYPE_TRACEPOINT, schedSwitchId, 1, PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL) | 89 | || !mCountersGroup.add(&mBuffer, 100/**/, PERF_TYPE_TRACEPOINT, schedSwitchId, 1, PERF_SAMPLE_RAW, PERF_GROUP_MMAP | PERF_GROUP_COMM | PERF_GROUP_TASK | PERF_GROUP_SAMPLE_ID_ALL | PERF_GROUP_PER_CPU) |
87 | 90 | ||
88 | // Only want TID and IP but not RAW on timer | 91 | // Only want TID and IP but not RAW on timer |
89 | || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(&mBuffer, 99/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, 0)) | 92 | || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(&mBuffer, 99/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, PERF_GROUP_PER_CPU)) |
90 | 93 | ||
91 | || !gSessionData->perf.enable(&mCountersGroup, &mBuffer) | 94 | || !gSessionData->perf.enable(&mCountersGroup, &mBuffer) |
92 | || 0) { | 95 | || 0) { |
93 | logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.12 or later?", __FUNCTION__, __FILE__, __LINE__); | 96 | logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.4 or later?", __FUNCTION__, __FILE__, __LINE__); |
94 | return false; | 97 | return false; |
95 | } | 98 | } |
96 | 99 | ||
@@ -134,7 +137,7 @@ bool PerfSource::prepare() { | |||
134 | return false; | 137 | return false; |
135 | } | 138 | } |
136 | 139 | ||
137 | if (!readProc(&mBuffer, &printb, &b1, &b2, &b3)) { | 140 | if (!readProc(&mBuffer, true, &printb, &b1, &b2, &b3)) { |
138 | logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__); | 141 | logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__); |
139 | return false; | 142 | return false; |
140 | } | 143 | } |
@@ -260,6 +263,7 @@ bool PerfSource::isDone () { | |||
260 | void PerfSource::write (Sender *sender) { | 263 | void PerfSource::write (Sender *sender) { |
261 | if (!mSummary.isDone()) { | 264 | if (!mSummary.isDone()) { |
262 | mSummary.write(sender); | 265 | mSummary.write(sender); |
266 | gSessionData->mSentSummary = true; | ||
263 | } | 267 | } |
264 | if (!mBuffer.isDone()) { | 268 | if (!mBuffer.isDone()) { |
265 | mBuffer.write(sender); | 269 | mBuffer.write(sender); |
diff --git a/daemon/Proc.cpp b/daemon/Proc.cpp index e0b9e22..9f01770 100644 --- a/daemon/Proc.cpp +++ b/daemon/Proc.cpp | |||
@@ -57,14 +57,57 @@ static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf | |||
57 | return true; | 57 | return true; |
58 | } | 58 | } |
59 | 59 | ||
60 | static bool readProcTask(Buffer *const buffer, const int pid, const char *const image, DynBuf *const printb, DynBuf *const b) { | 60 | static const char *readProcExe(DynBuf *const printb, const int pid, const int tid, DynBuf *const b) { |
61 | if (tid == -1 ? !printb->printf("/proc/%i/exe", pid) | ||
62 | : !printb->printf("/proc/%i/task/%i/exe", pid, tid)) { | ||
63 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); | ||
64 | return NULL; | ||
65 | } | ||
66 | |||
67 | const int err = b->readlink(printb->getBuf()); | ||
68 | const char *image; | ||
69 | if (err == 0) { | ||
70 | image = strrchr(b->getBuf(), '/'); | ||
71 | if (image == NULL) { | ||
72 | image = b->getBuf(); | ||
73 | } else { | ||
74 | ++image; | ||
75 | } | ||
76 | } else if (err == -ENOENT) { | ||
77 | // readlink /proc/[pid]/exe returns ENOENT for kernel threads | ||
78 | image = "\0"; | ||
79 | } else { | ||
80 | logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__); | ||
81 | return NULL; | ||
82 | } | ||
83 | |||
84 | // Android apps are run by app_process but the cmdline is changed to reference the actual app name | ||
85 | if (strcmp(image, "app_process") != 0) { | ||
86 | return image; | ||
87 | } | ||
88 | |||
89 | if (tid == -1 ? !printb->printf("/proc/%i/cmdline", pid) | ||
90 | : !printb->printf("/proc/%i/task/%i/cmdline", pid, tid)) { | ||
91 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | if (!b->read(printb->getBuf())) { | ||
96 | logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the thread exited", __FUNCTION__, __FILE__, __LINE__); | ||
97 | return NULL; | ||
98 | } | ||
99 | |||
100 | return b->getBuf(); | ||
101 | } | ||
102 | |||
103 | static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) { | ||
61 | bool result = false; | 104 | bool result = false; |
62 | 105 | ||
63 | if (!b->printf("/proc/%i/task", pid)) { | 106 | if (!b1->printf("/proc/%i/task", pid)) { |
64 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); | 107 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); |
65 | return result; | 108 | return result; |
66 | } | 109 | } |
67 | DIR *task = opendir(b->getBuf()); | 110 | DIR *task = opendir(b1->getBuf()); |
68 | if (task == NULL) { | 111 | if (task == NULL) { |
69 | logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__); | 112 | logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__); |
70 | return result; | 113 | return result; |
@@ -84,11 +127,17 @@ static bool readProcTask(Buffer *const buffer, const int pid, const char *const | |||
84 | goto fail; | 127 | goto fail; |
85 | } | 128 | } |
86 | ProcStat ps; | 129 | ProcStat ps; |
87 | if (!readProcStat(&ps, printb->getBuf(), b)) { | 130 | if (!readProcStat(&ps, printb->getBuf(), b1)) { |
88 | logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__); | 131 | logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__); |
89 | goto fail; | 132 | goto fail; |
90 | } | 133 | } |
91 | 134 | ||
135 | const char *const image = readProcExe(printb, pid, tid, b2); | ||
136 | if (image == NULL) { | ||
137 | logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__); | ||
138 | goto fail; | ||
139 | } | ||
140 | |||
92 | buffer->comm(pid, tid, image, ps.comm); | 141 | buffer->comm(pid, tid, image, ps.comm); |
93 | } | 142 | } |
94 | 143 | ||
@@ -100,7 +149,7 @@ static bool readProcTask(Buffer *const buffer, const int pid, const char *const | |||
100 | return result; | 149 | return result; |
101 | } | 150 | } |
102 | 151 | ||
103 | bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) { | 152 | bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) { |
104 | bool result = false; | 153 | bool result = false; |
105 | 154 | ||
106 | DIR *proc = opendir("/proc"); | 155 | DIR *proc = opendir("/proc"); |
@@ -128,42 +177,29 @@ bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynB | |||
128 | goto fail; | 177 | goto fail; |
129 | } | 178 | } |
130 | 179 | ||
131 | if (!printb->printf("/proc/%i/exe", pid)) { | 180 | if (sendMaps) { |
132 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); | 181 | if (!printb->printf("/proc/%i/maps", pid)) { |
133 | goto fail; | 182 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); |
134 | } | 183 | goto fail; |
135 | const int err = b1->readlink(printb->getBuf()); | 184 | } |
136 | const char *image; | 185 | if (!b2->read(printb->getBuf())) { |
137 | if (err == 0) { | 186 | logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__); |
138 | image = strrchr(b1->getBuf(), '/'); | 187 | // This is not a fatal error - the process just doesn't exist any more |
139 | if (image == NULL) { | 188 | continue; |
140 | image = b1->getBuf(); | ||
141 | } else { | ||
142 | ++image; | ||
143 | } | 189 | } |
144 | } else if (err == -ENOENT) { | ||
145 | // readlink /proc/[pid]/exe returns ENOENT for kernel threads | ||
146 | image = "\0"; | ||
147 | } else { | ||
148 | logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__); | ||
149 | goto fail; | ||
150 | } | ||
151 | 190 | ||
152 | if (!printb->printf("/proc/%i/maps", pid)) { | 191 | buffer->maps(pid, pid, b2->getBuf()); |
153 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); | ||
154 | goto fail; | ||
155 | } | 192 | } |
156 | if (!b2->read(printb->getBuf())) { | ||
157 | logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__); | ||
158 | // This is not a fatal error - the process just doesn't exist any more | ||
159 | continue; | ||
160 | } | ||
161 | |||
162 | buffer->maps(pid, pid, b2->getBuf()); | ||
163 | if (ps.numThreads <= 1) { | 193 | if (ps.numThreads <= 1) { |
194 | const char *const image = readProcExe(printb, pid, -1, b1); | ||
195 | if (image == NULL) { | ||
196 | logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__); | ||
197 | goto fail; | ||
198 | } | ||
199 | |||
164 | buffer->comm(pid, pid, image, ps.comm); | 200 | buffer->comm(pid, pid, image, ps.comm); |
165 | } else { | 201 | } else { |
166 | if (!readProcTask(buffer, pid, image, printb, b3)) { | 202 | if (!readProcTask(buffer, pid, printb, b1, b3)) { |
167 | logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__); | 203 | logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__); |
168 | goto fail; | 204 | goto fail; |
169 | } | 205 | } |
diff --git a/daemon/Proc.h b/daemon/Proc.h index 057b610..31c2eec 100644 --- a/daemon/Proc.h +++ b/daemon/Proc.h | |||
@@ -12,6 +12,6 @@ | |||
12 | class Buffer; | 12 | class Buffer; |
13 | class DynBuf; | 13 | class DynBuf; |
14 | 14 | ||
15 | bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3); | 15 | bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3); |
16 | 16 | ||
17 | #endif // PROC_H | 17 | #endif // PROC_H |
diff --git a/daemon/Sender.h b/daemon/Sender.h index 4c359db..33b6cc3 100644 --- a/daemon/Sender.h +++ b/daemon/Sender.h | |||
@@ -39,4 +39,4 @@ private: | |||
39 | Sender &operator=(const Sender &); | 39 | Sender &operator=(const Sender &); |
40 | }; | 40 | }; |
41 | 41 | ||
42 | #endif //__SENDER_H__ | 42 | #endif //__SENDER_H__ |
diff --git a/daemon/SessionData.cpp b/daemon/SessionData.cpp index c169299..14d995f 100644 --- a/daemon/SessionData.cpp +++ b/daemon/SessionData.cpp | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "SessionData.h" | 9 | #include "SessionData.h" |
10 | 10 | ||
11 | #include <string.h> | 11 | #include <string.h> |
12 | #include <sys/mman.h> | ||
12 | 13 | ||
13 | #include "SessionXML.h" | 14 | #include "SessionXML.h" |
14 | #include "Logging.h" | 15 | #include "Logging.h" |
@@ -27,6 +28,15 @@ void SessionData::initialize() { | |||
27 | mSessionIsActive = false; | 28 | mSessionIsActive = false; |
28 | mLocalCapture = false; | 29 | mLocalCapture = false; |
29 | mOneShot = false; | 30 | mOneShot = false; |
31 | mSentSummary = false; | ||
32 | const size_t cpuIdSize = sizeof(int)*NR_CPUS; | ||
33 | // Share mCpuIds across all instances of gatord | ||
34 | mCpuIds = (int *)mmap(NULL, cpuIdSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); | ||
35 | if (mCpuIds == MAP_FAILED) { | ||
36 | logg->logError(__FILE__, __LINE__, "Unable to mmap shared memory for cpuids"); | ||
37 | handleException(); | ||
38 | } | ||
39 | memset(mCpuIds, -1, cpuIdSize); | ||
30 | readCpuInfo(); | 40 | readCpuInfo(); |
31 | mConfigurationXMLPath = NULL; | 41 | mConfigurationXMLPath = NULL; |
32 | mSessionXMLPath = NULL; | 42 | mSessionXMLPath = NULL; |
@@ -91,10 +101,9 @@ void SessionData::parseSessionXML(char* xmlString) { | |||
91 | void SessionData::readCpuInfo() { | 101 | void SessionData::readCpuInfo() { |
92 | char temp[256]; // arbitrarily large amount | 102 | char temp[256]; // arbitrarily large amount |
93 | strcpy(mCoreName, "unknown"); | 103 | strcpy(mCoreName, "unknown"); |
94 | memset(&mCpuIds, -1, sizeof(mCpuIds)); | ||
95 | mMaxCpuId = -1; | 104 | mMaxCpuId = -1; |
96 | 105 | ||
97 | FILE* f = fopen("/proc/cpuinfo", "r"); | 106 | FILE* f = fopen("/proc/cpuinfo", "r"); |
98 | if (f == NULL) { | 107 | if (f == NULL) { |
99 | logg->logMessage("Error opening /proc/cpuinfo\n" | 108 | logg->logMessage("Error opening /proc/cpuinfo\n" |
100 | "The core name in the captured xml file will be 'unknown'."); | 109 | "The core name in the captured xml file will be 'unknown'."); |
@@ -102,10 +111,18 @@ void SessionData::readCpuInfo() { | |||
102 | } | 111 | } |
103 | 112 | ||
104 | bool foundCoreName = false; | 113 | bool foundCoreName = false; |
105 | int processor = 0; | 114 | int processor = -1; |
106 | while (fgets(temp, sizeof(temp), f)) { | 115 | while (fgets(temp, sizeof(temp), f)) { |
107 | if (strlen(temp) > 0) { | 116 | const size_t len = strlen(temp); |
108 | temp[strlen(temp) - 1] = 0; // Replace the line feed with a null | 117 | |
118 | if (len == 1) { | ||
119 | // New section, clear the processor. Streamline will not know the cpus if the pre Linux 3.8 format of cpuinfo is encountered but also that no incorrect information will be transmitted. | ||
120 | processor = -1; | ||
121 | continue; | ||
122 | } | ||
123 | |||
124 | if (len > 0) { | ||
125 | temp[len - 1] = '\0'; // Replace the line feed with a null | ||
109 | } | 126 | } |
110 | 127 | ||
111 | const bool foundHardware = strstr(temp, "Hardware") != 0; | 128 | const bool foundHardware = strstr(temp, "Hardware") != 0; |
@@ -127,10 +144,15 @@ void SessionData::readCpuInfo() { | |||
127 | } | 144 | } |
128 | 145 | ||
129 | if (foundCPUPart) { | 146 | if (foundCPUPart) { |
130 | mCpuIds[processor] = strtol(position, NULL, 0); | 147 | const int cpuId = strtol(position, NULL, 0); |
131 | // If this does not have the full topology in /proc/cpuinfo, mCpuIds[0] may not have the 1 CPU part emitted - this guarantees it's in mMaxCpuId | 148 | // If this does not have the full topology in /proc/cpuinfo, mCpuIds[0] may not have the 1 CPU part emitted - this guarantees it's in mMaxCpuId |
132 | if (mCpuIds[processor] > mMaxCpuId) { | 149 | if (cpuId > mMaxCpuId) { |
133 | mMaxCpuId = mCpuIds[processor]; | 150 | mMaxCpuId = cpuId; |
151 | } | ||
152 | if (processor >= NR_CPUS) { | ||
153 | logg->logMessage("Too many processors, please increase NR_CPUS"); | ||
154 | } else if (processor >= 0) { | ||
155 | mCpuIds[processor] = cpuId; | ||
134 | } | 156 | } |
135 | } | 157 | } |
136 | 158 | ||
@@ -142,10 +164,23 @@ void SessionData::readCpuInfo() { | |||
142 | 164 | ||
143 | if (!foundCoreName) { | 165 | if (!foundCoreName) { |
144 | logg->logMessage("Could not determine core name from /proc/cpuinfo\n" | 166 | logg->logMessage("Could not determine core name from /proc/cpuinfo\n" |
145 | "The core name in the captured xml file will be 'unknown'."); | 167 | "The core name in the captured xml file will be 'unknown'."); |
146 | } | 168 | } |
147 | fclose(f); | 169 | fclose(f); |
148 | } | 170 | } |
171 | |||
172 | uint64_t getTime() { | ||
173 | struct timespec ts; | ||
174 | #ifndef CLOCK_MONOTONIC_RAW | ||
175 | // Android doesn't have this defined but it was added in Linux 2.6.28 | ||
176 | #define CLOCK_MONOTONIC_RAW 4 | ||
177 | #endif | ||
178 | if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) { | ||
179 | logg->logError(__FILE__, __LINE__, "Failed to get uptime"); | ||
180 | handleException(); | ||
181 | } | ||
182 | return (NS_PER_S*ts.tv_sec + ts.tv_nsec); | ||
183 | } | ||
149 | 184 | ||
150 | int getEventKey() { | 185 | int getEventKey() { |
151 | // key 0 is reserved as a timestamp | 186 | // key 0 is reserved as a timestamp |
diff --git a/daemon/SessionData.h b/daemon/SessionData.h index ea34240..835082d 100644 --- a/daemon/SessionData.h +++ b/daemon/SessionData.h | |||
@@ -13,12 +13,16 @@ | |||
13 | 13 | ||
14 | #include "Config.h" | 14 | #include "Config.h" |
15 | #include "Counter.h" | 15 | #include "Counter.h" |
16 | #include "FSDriver.h" | ||
16 | #include "Hwmon.h" | 17 | #include "Hwmon.h" |
18 | #include "MaliVideoDriver.h" | ||
17 | #include "PerfDriver.h" | 19 | #include "PerfDriver.h" |
18 | 20 | ||
19 | #define PROTOCOL_VERSION 18 | 21 | #define PROTOCOL_VERSION 19 |
20 | #define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions | 22 | #define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions |
21 | 23 | ||
24 | #define NS_PER_S ((uint64_t)1000000000) | ||
25 | |||
22 | struct ImageLinkList { | 26 | struct ImageLinkList { |
23 | char* path; | 27 | char* path; |
24 | struct ImageLinkList *next; | 28 | struct ImageLinkList *next; |
@@ -32,9 +36,12 @@ public: | |||
32 | ~SessionData(); | 36 | ~SessionData(); |
33 | void initialize(); | 37 | void initialize(); |
34 | void parseSessionXML(char* xmlString); | 38 | void parseSessionXML(char* xmlString); |
39 | void readCpuInfo(); | ||
35 | 40 | ||
36 | Hwmon hwmon; | 41 | Hwmon hwmon; |
42 | FSDriver fsDriver; | ||
37 | PerfDriver perf; | 43 | PerfDriver perf; |
44 | MaliVideoDriver maliVideo; | ||
38 | 45 | ||
39 | char mCoreName[MAX_STRING_LEN]; | 46 | char mCoreName[MAX_STRING_LEN]; |
40 | struct ImageLinkList *mImages; | 47 | struct ImageLinkList *mImages; |
@@ -49,7 +56,8 @@ public: | |||
49 | bool mLocalCapture; | 56 | bool mLocalCapture; |
50 | bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled | 57 | bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled |
51 | bool mIsEBS; | 58 | bool mIsEBS; |
52 | 59 | bool mSentSummary; | |
60 | |||
53 | int mBacktraceDepth; | 61 | int mBacktraceDepth; |
54 | int mTotalBufferSize; // number of MB to use for the entire collection buffer | 62 | int mTotalBufferSize; // number of MB to use for the entire collection buffer |
55 | int mSampleRate; | 63 | int mSampleRate; |
@@ -57,7 +65,7 @@ public: | |||
57 | int mDuration; | 65 | int mDuration; |
58 | int mCores; | 66 | int mCores; |
59 | int mPageSize; | 67 | int mPageSize; |
60 | int mCpuIds[NR_CPUS]; | 68 | int *mCpuIds; |
61 | int mMaxCpuId; | 69 | int mMaxCpuId; |
62 | 70 | ||
63 | // PMU Counters | 71 | // PMU Counters |
@@ -65,8 +73,6 @@ public: | |||
65 | Counter mCounters[MAX_PERFORMANCE_COUNTERS]; | 73 | Counter mCounters[MAX_PERFORMANCE_COUNTERS]; |
66 | 74 | ||
67 | private: | 75 | private: |
68 | void readCpuInfo(); | ||
69 | |||
70 | // Intentionally unimplemented | 76 | // Intentionally unimplemented |
71 | SessionData(const SessionData &); | 77 | SessionData(const SessionData &); |
72 | SessionData &operator=(const SessionData &); | 78 | SessionData &operator=(const SessionData &); |
@@ -74,6 +80,7 @@ private: | |||
74 | 80 | ||
75 | extern SessionData* gSessionData; | 81 | extern SessionData* gSessionData; |
76 | 82 | ||
83 | uint64_t getTime(); | ||
77 | int getEventKey(); | 84 | int getEventKey(); |
78 | 85 | ||
79 | #endif // SESSION_DATA_H | 86 | #endif // SESSION_DATA_H |
diff --git a/daemon/SessionXML.cpp b/daemon/SessionXML.cpp index 55b2f92..8cdc940 100644 --- a/daemon/SessionXML.cpp +++ b/daemon/SessionXML.cpp | |||
@@ -17,15 +17,15 @@ | |||
17 | #include "SessionData.h" | 17 | #include "SessionData.h" |
18 | 18 | ||
19 | static const char* TAG_SESSION = "session"; | 19 | static const char* TAG_SESSION = "session"; |
20 | static const char* TAG_IMAGE = "image"; | 20 | static const char* TAG_IMAGE = "image"; |
21 | 21 | ||
22 | static const char* ATTR_VERSION = "version"; | 22 | static const char* ATTR_VERSION = "version"; |
23 | static const char* ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding"; | 23 | static const char* ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding"; |
24 | static const char* ATTR_BUFFER_MODE = "buffer_mode"; | 24 | static const char* ATTR_BUFFER_MODE = "buffer_mode"; |
25 | static const char* ATTR_SAMPLE_RATE = "sample_rate"; | 25 | static const char* ATTR_SAMPLE_RATE = "sample_rate"; |
26 | static const char* ATTR_DURATION = "duration"; | 26 | static const char* ATTR_DURATION = "duration"; |
27 | static const char* ATTR_PATH = "path"; | 27 | static const char* ATTR_PATH = "path"; |
28 | static const char* ATTR_LIVE_RATE = "live_rate"; | 28 | static const char* ATTR_LIVE_RATE = "live_rate"; |
29 | 29 | ||
30 | SessionXML::SessionXML(const char *str) { | 30 | SessionXML::SessionXML(const char *str) { |
31 | parameters.buffer_mode[0] = 0; | 31 | parameters.buffer_mode[0] = 0; |
diff --git a/daemon/StreamlineSetup.cpp b/daemon/StreamlineSetup.cpp index caa665e..2b61eae 100644 --- a/daemon/StreamlineSetup.cpp +++ b/daemon/StreamlineSetup.cpp | |||
@@ -266,7 +266,7 @@ void StreamlineSetup::writeConfiguration(char* xml) { | |||
266 | { ConfigurationXML configuration; } | 266 | { ConfigurationXML configuration; } |
267 | 267 | ||
268 | if (gSessionData->mCounterOverflow > 0) { | 268 | if (gSessionData->mCounterOverflow > 0) { |
269 | logg->logError(__FILE__, __LINE__, "Only %i performance counters counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow); | 269 | logg->logError(__FILE__, __LINE__, "Only %i performance counters are permitted, %i are selected", MAX_PERFORMANCE_COUNTERS, gSessionData->mCounterOverflow); |
270 | handleException(); | 270 | handleException(); |
271 | } | 271 | } |
272 | } | 272 | } |
diff --git a/daemon/StreamlineSetup.h b/daemon/StreamlineSetup.h index 74bb197..b380f46 100644 --- a/daemon/StreamlineSetup.h +++ b/daemon/StreamlineSetup.h | |||
@@ -21,7 +21,7 @@ enum { | |||
21 | COMMAND_APC_START = 2, | 21 | COMMAND_APC_START = 2, |
22 | COMMAND_APC_STOP = 3, | 22 | COMMAND_APC_STOP = 3, |
23 | COMMAND_DISCONNECT = 4, | 23 | COMMAND_DISCONNECT = 4, |
24 | COMMAND_PING = 5 | 24 | COMMAND_PING = 5 |
25 | }; | 25 | }; |
26 | 26 | ||
27 | class StreamlineSetup { | 27 | class StreamlineSetup { |
@@ -47,4 +47,4 @@ private: | |||
47 | StreamlineSetup &operator=(const StreamlineSetup &); | 47 | StreamlineSetup &operator=(const StreamlineSetup &); |
48 | }; | 48 | }; |
49 | 49 | ||
50 | #endif //__STREAMLINE_SETUP_H__ | 50 | #endif //__STREAMLINE_SETUP_H__ |
diff --git a/daemon/UEvent.cpp b/daemon/UEvent.cpp index d977cd0..54d4575 100644 --- a/daemon/UEvent.cpp +++ b/daemon/UEvent.cpp | |||
@@ -8,12 +8,12 @@ | |||
8 | 8 | ||
9 | #include "UEvent.h" | 9 | #include "UEvent.h" |
10 | 10 | ||
11 | #include <sys/socket.h> | ||
12 | #include <linux/netlink.h> | ||
13 | #include <string.h> | 11 | #include <string.h> |
14 | 12 | #include <sys/socket.h> | |
15 | #include <unistd.h> | 13 | #include <unistd.h> |
16 | 14 | ||
15 | #include <linux/netlink.h> | ||
16 | |||
17 | #include "Logging.h" | 17 | #include "Logging.h" |
18 | 18 | ||
19 | static const char EMPTY[] = ""; | 19 | static const char EMPTY[] = ""; |
diff --git a/daemon/UserSpaceSource.cpp b/daemon/UserSpaceSource.cpp index debe696..8c328e0 100644 --- a/daemon/UserSpaceSource.cpp +++ b/daemon/UserSpaceSource.cpp | |||
@@ -16,7 +16,6 @@ | |||
16 | #include "Logging.h" | 16 | #include "Logging.h" |
17 | #include "SessionData.h" | 17 | #include "SessionData.h" |
18 | 18 | ||
19 | #define NS_PER_S ((uint64_t)1000000000) | ||
20 | #define NS_PER_US 1000 | 19 | #define NS_PER_US 1000 |
21 | 20 | ||
22 | extern Child *child; | 21 | extern Child *child; |
@@ -35,6 +34,7 @@ void UserSpaceSource::run() { | |||
35 | prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0); | 34 | prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0); |
36 | 35 | ||
37 | gSessionData->hwmon.start(); | 36 | gSessionData->hwmon.start(); |
37 | gSessionData->fsDriver.start(); | ||
38 | 38 | ||
39 | int64_t monotonic_started = 0; | 39 | int64_t monotonic_started = 0; |
40 | while (monotonic_started <= 0) { | 40 | while (monotonic_started <= 0) { |
@@ -48,16 +48,7 @@ void UserSpaceSource::run() { | |||
48 | 48 | ||
49 | uint64_t next_time = 0; | 49 | uint64_t next_time = 0; |
50 | while (gSessionData->mSessionIsActive) { | 50 | while (gSessionData->mSessionIsActive) { |
51 | struct timespec ts; | 51 | const uint64_t curr_time = getTime() - monotonic_started; |
52 | #ifndef CLOCK_MONOTONIC_RAW | ||
53 | // Android doesn't have this defined but it was added in Linux 2.6.28 | ||
54 | #define CLOCK_MONOTONIC_RAW 4 | ||
55 | #endif | ||
56 | if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) { | ||
57 | logg->logError(__FILE__, __LINE__, "Failed to get uptime"); | ||
58 | handleException(); | ||
59 | } | ||
60 | const uint64_t curr_time = (NS_PER_S*ts.tv_sec + ts.tv_nsec) - monotonic_started; | ||
61 | // Sample ten times a second ignoring gSessionData->mSampleRate | 52 | // Sample ten times a second ignoring gSessionData->mSampleRate |
62 | next_time += NS_PER_S/10;//gSessionData->mSampleRate; | 53 | next_time += NS_PER_S/10;//gSessionData->mSampleRate; |
63 | if (next_time < curr_time) { | 54 | if (next_time < curr_time) { |
@@ -67,6 +58,7 @@ void UserSpaceSource::run() { | |||
67 | 58 | ||
68 | if (mBuffer.eventHeader(curr_time)) { | 59 | if (mBuffer.eventHeader(curr_time)) { |
69 | gSessionData->hwmon.read(&mBuffer); | 60 | gSessionData->hwmon.read(&mBuffer); |
61 | gSessionData->fsDriver.read(&mBuffer); | ||
70 | // Only check after writing all counters so that time and corresponding counters appear in the same frame | 62 | // Only check after writing all counters so that time and corresponding counters appear in the same frame |
71 | mBuffer.check(curr_time); | 63 | mBuffer.check(curr_time); |
72 | } | 64 | } |
diff --git a/daemon/UserSpaceSource.h b/daemon/UserSpaceSource.h index fb5889d..9b36660 100644 --- a/daemon/UserSpaceSource.h +++ b/daemon/UserSpaceSource.h | |||
@@ -14,7 +14,7 @@ | |||
14 | #include "Buffer.h" | 14 | #include "Buffer.h" |
15 | #include "Source.h" | 15 | #include "Source.h" |
16 | 16 | ||
17 | // User space counters - currently just hwmon | 17 | // User space counters |
18 | class UserSpaceSource : public Source { | 18 | class UserSpaceSource : public Source { |
19 | public: | 19 | public: |
20 | UserSpaceSource(sem_t *senderSem); | 20 | UserSpaceSource(sem_t *senderSem); |
diff --git a/daemon/c++.cpp b/daemon/c++.cpp new file mode 100644 index 0000000..6041e5e --- /dev/null +++ b/daemon/c++.cpp | |||
@@ -0,0 +1,40 @@ | |||
1 | /** | ||
2 | * Minimal set of C++ functions so that libstdc++ is not required | ||
3 | * | ||
4 | * Copyright (C) ARM Limited 2010-2014. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <stdio.h> | ||
12 | #include <stdlib.h> | ||
13 | |||
14 | void operator delete(void *ptr) { | ||
15 | if (ptr != NULL) { | ||
16 | free(ptr); | ||
17 | } | ||
18 | } | ||
19 | |||
20 | void operator delete[](void *ptr) { | ||
21 | operator delete(ptr); | ||
22 | } | ||
23 | |||
24 | void *operator new(size_t size) { | ||
25 | void *ptr = malloc(size == 0 ? 1 : size); | ||
26 | if (ptr == NULL) { | ||
27 | abort(); | ||
28 | } | ||
29 | return ptr; | ||
30 | } | ||
31 | |||
32 | void *operator new[](size_t size) { | ||
33 | return operator new(size); | ||
34 | } | ||
35 | |||
36 | extern "C" | ||
37 | void __cxa_pure_virtual() { | ||
38 | printf("pure virtual method called\n"); | ||
39 | abort(); | ||
40 | } | ||
diff --git a/daemon/common.mk b/daemon/common.mk index d9dc146..769a92e 100644 --- a/daemon/common.mk +++ b/daemon/common.mk | |||
@@ -5,16 +5,17 @@ | |||
5 | # -Werror treats warnings as errors | 5 | # -Werror treats warnings as errors |
6 | # -std=c++0x is the planned new c++ standard | 6 | # -std=c++0x is the planned new c++ standard |
7 | # -std=c++98 is the 1998 c++ standard | 7 | # -std=c++98 is the 1998 c++ standard |
8 | CFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors | 8 | CPPFLAGS += -O3 -Wall -fno-exceptions -pthread -MMD -DETCDIR=\"/etc\" -Ilibsensors |
9 | CXXFLAGS += -fno-rtti -Wextra # -Weffc++ | 9 | CXXFLAGS += -fno-rtti -Wextra # -Weffc++ |
10 | ifeq ($(WERROR),1) | 10 | ifeq ($(WERROR),1) |
11 | CFLAGS += -Werror | 11 | CPPFLAGS += -Werror |
12 | endif | 12 | endif |
13 | # -s strips the binary of debug info | 13 | # -s strips the binary of debug info |
14 | LDFLAGS += -s | 14 | LDFLAGS += -s |
15 | LDLIBS += -lrt -lm -pthread | ||
15 | TARGET = gatord | 16 | TARGET = gatord |
16 | C_SRC = $(wildcard mxml/*.c) $(wildcard libsensors/*.c) | 17 | C_SRC = $(wildcard mxml/*.c) $(wildcard libsensors/*.c) |
17 | CPP_SRC = $(wildcard *.cpp) | 18 | CXX_SRC = $(wildcard *.cpp) |
18 | 19 | ||
19 | all: $(TARGET) | 20 | all: $(TARGET) |
20 | 21 | ||
@@ -35,14 +36,15 @@ libsensors/conf-parse.c: ; | |||
35 | ./escape $< > $@ | 36 | ./escape $< > $@ |
36 | 37 | ||
37 | %.o: %.c | 38 | %.o: %.c |
38 | $(GCC) -c $(CFLAGS) -o $@ $< | 39 | $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< |
39 | 40 | ||
40 | %.o: %.cpp | 41 | %.o: %.cpp |
41 | $(CPP) -c $(CFLAGS) $(CXXFLAGS) -o $@ $< | 42 | $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< |
42 | 43 | ||
43 | $(TARGET): $(CPP_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o) | 44 | $(TARGET): $(CXX_SRC:%.cpp=%.o) $(C_SRC:%.c=%.o) |
44 | $(CPP) $(LDFLAGS) -o $@ $^ -lrt -pthread | 45 | $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ |
45 | 46 | ||
47 | # Intentionally ignore CC as a native binary is required | ||
46 | escape: escape.c | 48 | escape: escape.c |
47 | gcc $^ -o $@ | 49 | gcc $^ -o $@ |
48 | 50 | ||
diff --git a/daemon/defaults.xml b/daemon/defaults.xml index 5bf096c..39a0f65 100644 --- a/daemon/defaults.xml +++ b/daemon/defaults.xml | |||
@@ -58,5 +58,10 @@ | |||
58 | <configuration counter="Linux_meminfo_memused"/> | 58 | <configuration counter="Linux_meminfo_memused"/> |
59 | <configuration counter="Linux_meminfo_memfree"/> | 59 | <configuration counter="Linux_meminfo_memfree"/> |
60 | <configuration counter="Linux_power_cpu_freq"/> | 60 | <configuration counter="Linux_power_cpu_freq"/> |
61 | <configuration counter="ARM_Mali-4xx_fragment"/> | ||
62 | <configuration counter="ARM_Mali-4xx_vertex"/> | ||
63 | <configuration counter="ARM_Mali-T6xx_fragment" cores="1"/> | ||
64 | <configuration counter="ARM_Mali-T6xx_vertex" cores="1"/> | ||
65 | <configuration counter="ARM_Mali-T6xx_opencl" cores="1"/> | ||
61 | <configuration counter="L2C-310_cnt0" event="0x1"/> | 66 | <configuration counter="L2C-310_cnt0" event="0x1"/> |
62 | </configurations> | 67 | </configurations> |
diff --git a/daemon/escape.c b/daemon/escape.c index c54aa1c..2b0863a 100644 --- a/daemon/escape.c +++ b/daemon/escape.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* | 9 | /* |
10 | * The Makefile in the daemon folder builds and executes 'escape' | 10 | * The Makefile in the daemon folder builds and executes 'escape' |
11 | * 'escape' creates configuration_xml.h from configuration.xml and events_xml.h from events-*.xml | 11 | * 'escape' creates configuration_xml.h from configuration.xml and events_xml.h from events-*.xml |
12 | * these genereated xml files are then #included and built as part of the gatord binary | 12 | * these genereated xml files are then #included and built as part of the gatord binary |
diff --git a/daemon/events-CCI-400.xml b/daemon/events-CCI-400.xml index 4fa7711..20002ef 100644 --- a/daemon/events-CCI-400.xml +++ b/daemon/events-CCI-400.xml | |||
@@ -1,7 +1,6 @@ | |||
1 | <counter_set name="cci-400_cnt" count="4"/> | 1 | <counter_set name="CCI_400_cnt" count="4"/> |
2 | <category name="CCI-400" counter_set="cci-400_cnt" per_cpu="no" supports_event_based_sampling="yes"> | 2 | <category name="CCI-400" counter_set="CCI_400_cnt" per_cpu="no" supports_event_based_sampling="yes"> |
3 | <event counter="cci-400_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/> | 3 | <event counter="CCI_400_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/> |
4 | |||
5 | <option_set name="Slave"> | 4 | <option_set name="Slave"> |
6 | <option event_delta="0x00" name="S0" description="Slave interface 0"/> | 5 | <option event_delta="0x00" name="S0" description="Slave interface 0"/> |
7 | <option event_delta="0x20" name="S1" description="Slave interface 1"/> | 6 | <option event_delta="0x20" name="S1" description="Slave interface 1"/> |
@@ -9,7 +8,6 @@ | |||
9 | <option event_delta="0x60" name="S3" description="Slave interface 3"/> | 8 | <option event_delta="0x60" name="S3" description="Slave interface 3"/> |
10 | <option event_delta="0x80" name="S4" description="Slave interface 4"/> | 9 | <option event_delta="0x80" name="S4" description="Slave interface 4"/> |
11 | </option_set> | 10 | </option_set> |
12 | |||
13 | <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/> | 11 | <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/> |
14 | <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/> | 12 | <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/> |
15 | <event event="0x02" option_set="Slave" title="CCI-400" name="Read: normal" description="Read request handshake: normal, non-shareable or system-shareable, but not barrier or cache maintenance operation"/> | 13 | <event event="0x02" option_set="Slave" title="CCI-400" name="Read: normal" description="Read request handshake: normal, non-shareable or system-shareable, but not barrier or cache maintenance operation"/> |
@@ -30,13 +28,11 @@ | |||
30 | <event event="0x11" option_set="Slave" title="CCI-400" name="Write: WriteLineUnique" description="Write request handshake: WriteLineUnique"/> | 28 | <event event="0x11" option_set="Slave" title="CCI-400" name="Write: WriteLineUnique" description="Write request handshake: WriteLineUnique"/> |
31 | <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/> | 29 | <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/> |
32 | <event event="0x13" option_set="Slave" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase SIx_W_MAX to avoid this stall"/> | 30 | <event event="0x13" option_set="Slave" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase SIx_W_MAX to avoid this stall"/> |
33 | |||
34 | <option_set name="Master"> | 31 | <option_set name="Master"> |
35 | <option event_delta="0xa0" name="M0" description="Master interface 0"/> | 32 | <option event_delta="0xa0" name="M0" description="Master interface 0"/> |
36 | <option event_delta="0xc0" name="M1" description="Master interface 1"/> | 33 | <option event_delta="0xc0" name="M1" description="Master interface 1"/> |
37 | <option event_delta="0xe0" name="M2" description="Master interface 2"/> | 34 | <option event_delta="0xe0" name="M2" description="Master interface 2"/> |
38 | </option_set> | 35 | </option_set> |
39 | |||
40 | <event event="0x14" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/> | 36 | <event event="0x14" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/> |
41 | <event event="0x15" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Read request stall cycle because of an address hazard"/> | 37 | <event event="0x15" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Read request stall cycle because of an address hazard"/> |
42 | <event event="0x16" option_set="Master" title="CCI-400" name="Read stall: ID hazard" description="Read request stall cycle because of an ID hazard"/> | 38 | <event event="0x16" option_set="Master" title="CCI-400" name="Read stall: ID hazard" description="Read request stall cycle because of an ID hazard"/> |
@@ -45,11 +41,9 @@ | |||
45 | <event event="0x19" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/> | 41 | <event event="0x19" option_set="Master" title="CCI-400" name="Write stall: barrier hazard" description="Write request stall cycle because of a barrier hazard"/> |
46 | <event event="0x1a" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase MIx_W_MAX to avoid this stall. See the CoreLink CCI-400 Cache Coherent Interconnect Integration Manual"/> | 42 | <event event="0x1a" option_set="Master" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase MIx_W_MAX to avoid this stall. See the CoreLink CCI-400 Cache Coherent Interconnect Integration Manual"/> |
47 | </category> | 43 | </category> |
48 | 44 | <counter_set name="CCI_400-r1_cnt" count="4"/> | |
49 | <counter_set name="cci-400-r1_cnt" count="4"/> | 45 | <category name="CCI-400" counter_set="CCI_400-r1_cnt" per_cpu="no" supports_event_based_sampling="yes"> |
50 | <category name="CCI-400" counter_set="cci-400-r1_cnt" per_cpu="no" supports_event_based_sampling="yes"> | 46 | <event counter="CCI_400-r1_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/> |
51 | <event counter="cci-400-r1_ccnt" event="0xff" title="CCI-400 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/> | ||
52 | |||
53 | <option_set name="Slave"> | 47 | <option_set name="Slave"> |
54 | <option event_delta="0x00" name="S0" description="Slave interface 0"/> | 48 | <option event_delta="0x00" name="S0" description="Slave interface 0"/> |
55 | <option event_delta="0x20" name="S1" description="Slave interface 1"/> | 49 | <option event_delta="0x20" name="S1" description="Slave interface 1"/> |
@@ -57,7 +51,6 @@ | |||
57 | <option event_delta="0x60" name="S3" description="Slave interface 3"/> | 51 | <option event_delta="0x60" name="S3" description="Slave interface 3"/> |
58 | <option event_delta="0x80" name="S4" description="Slave interface 4"/> | 52 | <option event_delta="0x80" name="S4" description="Slave interface 4"/> |
59 | </option_set> | 53 | </option_set> |
60 | |||
61 | <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/> | 54 | <event event="0x00" option_set="Slave" title="CCI-400" name="Read: any" description="Read request handshake: any"/> |
62 | <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/> | 55 | <event event="0x01" option_set="Slave" title="CCI-400" name="Read: transaction" description="Read request handshake: device transaction"/> |
63 | <event event="0x02" option_set="Slave" title="CCI-400" name="Read: normal" description="Read request handshake: normal, non-shareable or system-shareable, but not barrier or cache maintenance operation"/> | 56 | <event event="0x02" option_set="Slave" title="CCI-400" name="Read: normal" description="Read request handshake: normal, non-shareable or system-shareable, but not barrier or cache maintenance operation"/> |
@@ -79,13 +72,11 @@ | |||
79 | <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/> | 72 | <event event="0x12" option_set="Slave" title="CCI-400" name="Write: Evict" description="Write request handshake: Evict"/> |
80 | <event event="0x13" option_set="Slave" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase SIx_W_MAX to avoid this stall"/> | 73 | <event event="0x13" option_set="Slave" title="CCI-400" name="Write stall: tracker full" description="Write request stall cycle because the transaction tracker is full. Increase SIx_W_MAX to avoid this stall"/> |
81 | <event event="0x14" option_set="Slave" title="CCI-400" name="Read stall: slave hazard" description="Read request stall cycle because of a slave interface ID hazard"/> | 74 | <event event="0x14" option_set="Slave" title="CCI-400" name="Read stall: slave hazard" description="Read request stall cycle because of a slave interface ID hazard"/> |
82 | |||
83 | <option_set name="Master"> | 75 | <option_set name="Master"> |
84 | <option event_delta="0xa0" name="M0" description="Master interface 0"/> | 76 | <option event_delta="0xa0" name="M0" description="Master interface 0"/> |
85 | <option event_delta="0xc0" name="M1" description="Master interface 1"/> | 77 | <option event_delta="0xc0" name="M1" description="Master interface 1"/> |
86 | <option event_delta="0xe0" name="M2" description="Master interface 2"/> | 78 | <option event_delta="0xe0" name="M2" description="Master interface 2"/> |
87 | </option_set> | 79 | </option_set> |
88 | |||
89 | <event event="0x00" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/> | 80 | <event event="0x00" option_set="Master" title="CCI-400" name="Retry fetch" description="RETRY of speculative fetch transaction"/> |
90 | <event event="0x01" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Stall cycle because of an address hazard. A read or write invalidation is stalled because of an outstanding transaction to an overlapping address"/> | 81 | <event event="0x01" option_set="Master" title="CCI-400" name="Read stall: address hazard" description="Stall cycle because of an address hazard. A read or write invalidation is stalled because of an outstanding transaction to an overlapping address"/> |
91 | <event event="0x02" option_set="Master" title="CCI-400" name="Read stall: ID hazard" description="Read request stall cycle because of a master interface ID hazard"/> | 82 | <event event="0x02" option_set="Master" title="CCI-400" name="Read stall: ID hazard" description="Read request stall cycle because of a master interface ID hazard"/> |
diff --git a/daemon/events-CCN-504.xml b/daemon/events-CCN-504.xml index cfabf65..6ef3e64 100644 --- a/daemon/events-CCN-504.xml +++ b/daemon/events-CCN-504.xml | |||
@@ -1,7 +1,6 @@ | |||
1 | <counter_set name="CCN-504_cnt" count="4"/> | 1 | <counter_set name="CCN-504_cnt" count="4"/> |
2 | <category name="CCN-504" counter_set="CCN-504_cnt"> | 2 | <category name="CCN-504" counter_set="CCN-504_cnt"> |
3 | <event counter="CCN-504_ccnt" title="CCN-504 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/> | 3 | <event counter="CCN-504_ccnt" title="CCN-504 Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" description="The number of core clock cycles"/> |
4 | |||
5 | <option_set name="XP_Region"> | 4 | <option_set name="XP_Region"> |
6 | <option event_delta="0x400000" name="XP 0" description="Crosspoint 0"/> | 5 | <option event_delta="0x400000" name="XP 0" description="Crosspoint 0"/> |
7 | <option event_delta="0x410000" name="XP 1" description="Crosspoint 1"/> | 6 | <option event_delta="0x410000" name="XP 1" description="Crosspoint 1"/> |
@@ -15,7 +14,6 @@ | |||
15 | <option event_delta="0x490000" name="XP 9" description="Crosspoint 9"/> | 14 | <option event_delta="0x490000" name="XP 9" description="Crosspoint 9"/> |
16 | <option event_delta="0x4A0000" name="XP 10" description="Crosspoint 10"/> | 15 | <option event_delta="0x4A0000" name="XP 10" description="Crosspoint 10"/> |
17 | </option_set> | 16 | </option_set> |
18 | |||
19 | <event event="0x0801" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: H-bit" description="Bus 0: REQ: Set H-bit, signaled when this XP sets the H-bit."/> | 17 | <event event="0x0801" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: H-bit" description="Bus 0: REQ: Set H-bit, signaled when this XP sets the H-bit."/> |
20 | <event event="0x0802" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: S-bit" description="Bus 0: REQ: Set S-bit, signaled when this XP sets the S-bit."/> | 18 | <event event="0x0802" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: S-bit" description="Bus 0: REQ: Set S-bit, signaled when this XP sets the S-bit."/> |
21 | <event event="0x0803" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: P-Cnt" description="Bus 0: REQ: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/> | 19 | <event event="0x0803" option_set="XP_Region" title="CCN-504" name="Bus 0: REQ: P-Cnt" description="Bus 0: REQ: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/> |
@@ -56,7 +54,6 @@ | |||
56 | <event event="0x087A" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: S-bit" description="Bus 1: DATB: Set S-bit, signaled when this XP sets the S-bit."/> | 54 | <event event="0x087A" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: S-bit" description="Bus 1: DATB: Set S-bit, signaled when this XP sets the S-bit."/> |
57 | <event event="0x087B" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: P-Cnt" description="Bus 1: DATB: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/> | 55 | <event event="0x087B" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: P-Cnt" description="Bus 1: DATB: Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC."/> |
58 | <event event="0x087C" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: TknV" description="Bus 1: DATB: No TknV, signaled when this XP transmits a valid packet."/> | 56 | <event event="0x087C" option_set="XP_Region" title="CCN-504" name="Bus 1: DATB: TknV" description="Bus 1: DATB: No TknV, signaled when this XP transmits a valid packet."/> |
59 | |||
60 | <option_set name="HN-F_Region"> | 57 | <option_set name="HN-F_Region"> |
61 | <option event_delta="0x200000" name="HN-F 3" description="Fully-coherent Home Node 3"/> | 58 | <option event_delta="0x200000" name="HN-F 3" description="Fully-coherent Home Node 3"/> |
62 | <option event_delta="0x210000" name="HN-F 5" description="Fully-coherent Home Node 5"/> | 59 | <option event_delta="0x210000" name="HN-F 5" description="Fully-coherent Home Node 5"/> |
@@ -67,7 +64,6 @@ | |||
67 | <option event_delta="0x260000" name="HN-F 17" description="Fully-coherent Home Node 17"/> | 64 | <option event_delta="0x260000" name="HN-F 17" description="Fully-coherent Home Node 17"/> |
68 | <option event_delta="0x270000" name="HN-F 18" description="Fully-coherent Home Node 18"/> | 65 | <option event_delta="0x270000" name="HN-F 18" description="Fully-coherent Home Node 18"/> |
69 | </option_set> | 66 | </option_set> |
70 | |||
71 | <event event="0x0401" option_set="HN-F_Region" title="CCN-504" name="Cache Miss" description="Counts the total cache misses. This is the first time lookup result, and is high priority."/> | 67 | <event event="0x0401" option_set="HN-F_Region" title="CCN-504" name="Cache Miss" description="Counts the total cache misses. This is the first time lookup result, and is high priority."/> |
72 | <event event="0x0402" option_set="HN-F_Region" title="CCN-504" name="L3 SF Cache Access" description="Counts the number of cache accesses. This is the first time access, and is high priority."/> | 68 | <event event="0x0402" option_set="HN-F_Region" title="CCN-504" name="L3 SF Cache Access" description="Counts the number of cache accesses. This is the first time access, and is high priority."/> |
73 | <event event="0x0403" option_set="HN-F_Region" title="CCN-504" name="Cache Fill" description="Counts the total allocations in the HN L3 cache, and all cache line allocations to the L3 cache."/> | 69 | <event event="0x0403" option_set="HN-F_Region" title="CCN-504" name="Cache Fill" description="Counts the total allocations in the HN L3 cache, and all cache line allocations to the L3 cache."/> |
@@ -82,7 +78,6 @@ | |||
82 | <event event="0x040C" option_set="HN-F_Region" title="CCN-504" name="MC Retries" description="Counts the number of transactions retried by the memory controller."/> | 78 | <event event="0x040C" option_set="HN-F_Region" title="CCN-504" name="MC Retries" description="Counts the number of transactions retried by the memory controller."/> |
83 | <event event="0x040D" option_set="HN-F_Region" title="CCN-504" name="MC Reqs" description="Counts the number of requests to the memory controller."/> | 79 | <event event="0x040D" option_set="HN-F_Region" title="CCN-504" name="MC Reqs" description="Counts the number of requests to the memory controller."/> |
84 | <event event="0x040E" option_set="HN-F_Region" title="CCN-504" name="QOS HH Retry" description="Counts the number of times a highest-priority QoS class was retried at the HN-F."/> | 80 | <event event="0x040E" option_set="HN-F_Region" title="CCN-504" name="QOS HH Retry" description="Counts the number of times a highest-priority QoS class was retried at the HN-F."/> |
85 | |||
86 | <option_set name="RN-I_Region"> | 81 | <option_set name="RN-I_Region"> |
87 | <option event_delta="0x800000" name="RN-I 0" description="I/O-coherent Requesting Node 0"/> | 82 | <option event_delta="0x800000" name="RN-I 0" description="I/O-coherent Requesting Node 0"/> |
88 | <option event_delta="0x820000" name="RN-I 2" description="I/O-coherent Requesting Node 2"/> | 83 | <option event_delta="0x820000" name="RN-I 2" description="I/O-coherent Requesting Node 2"/> |
@@ -91,7 +86,6 @@ | |||
91 | <option event_delta="0x900000" name="RN-I 16" description="I/O-coherent Requesting Node 16"/> | 86 | <option event_delta="0x900000" name="RN-I 16" description="I/O-coherent Requesting Node 16"/> |
92 | <option event_delta="0x940000" name="RN-I 20" description="I/O-coherent Requesting Node 20"/> | 87 | <option event_delta="0x940000" name="RN-I 20" description="I/O-coherent Requesting Node 20"/> |
93 | </option_set> | 88 | </option_set> |
94 | |||
95 | <event event="0x1601" option_set="RN-I_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/> | 89 | <event event="0x1601" option_set="RN-I_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/> |
96 | <event event="0x1602" option_set="RN-I_Region" title="CCN-504" name="S1 RDataBeats" description="S1 RDataBeats."/> | 90 | <event event="0x1602" option_set="RN-I_Region" title="CCN-504" name="S1 RDataBeats" description="S1 RDataBeats."/> |
97 | <event event="0x1603" option_set="RN-I_Region" title="CCN-504" name="S2 RDataBeats" description="S2 RDataBeats."/> | 91 | <event event="0x1603" option_set="RN-I_Region" title="CCN-504" name="S2 RDataBeats" description="S2 RDataBeats."/> |
@@ -102,14 +96,12 @@ | |||
102 | <event event="0x1608" option_set="RN-I_Region" title="CCN-504" name="RRT full" description="RRT full."/> | 96 | <event event="0x1608" option_set="RN-I_Region" title="CCN-504" name="RRT full" description="RRT full."/> |
103 | <event event="0x1609" option_set="RN-I_Region" title="CCN-504" name="WRT full" description="WRT full."/> | 97 | <event event="0x1609" option_set="RN-I_Region" title="CCN-504" name="WRT full" description="WRT full."/> |
104 | <event event="0x160A" option_set="RN-I_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/> | 98 | <event event="0x160A" option_set="RN-I_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/> |
105 | |||
106 | <option_set name="SBAS_Region"> | 99 | <option_set name="SBAS_Region"> |
107 | <option event_delta="0x810000" name="SBAS 1" description="ACE master to CHI protocol bridge 1"/> | 100 | <option event_delta="0x810000" name="SBAS 1" description="ACE master to CHI protocol bridge 1"/> |
108 | <option event_delta="0x890000" name="SBAS 9" description="ACE master to CHI protocol bridge 9"/> | 101 | <option event_delta="0x890000" name="SBAS 9" description="ACE master to CHI protocol bridge 9"/> |
109 | <option event_delta="0x8B0000" name="SBAS 11" description="ACE master to CHI protocol bridge 11"/> | 102 | <option event_delta="0x8B0000" name="SBAS 11" description="ACE master to CHI protocol bridge 11"/> |
110 | <option event_delta="0x930000" name="SBAS 19" description="ACE master to CHI protocol bridge 19"/> | 103 | <option event_delta="0x930000" name="SBAS 19" description="ACE master to CHI protocol bridge 19"/> |
111 | </option_set> | 104 | </option_set> |
112 | |||
113 | <event event="0x1001" option_set="SBAS_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/> | 105 | <event event="0x1001" option_set="SBAS_Region" title="CCN-504" name="S0 RDataBeats" description="S0 RDataBeats."/> |
114 | <event event="0x1004" option_set="SBAS_Region" title="CCN-504" name="RXDAT Flits received" description="RXDAT Flits received."/> | 106 | <event event="0x1004" option_set="SBAS_Region" title="CCN-504" name="RXDAT Flits received" description="RXDAT Flits received."/> |
115 | <event event="0x1005" option_set="SBAS_Region" title="CCN-504" name="TXDAT Flits sent" description="TXDAT Flits sent."/> | 107 | <event event="0x1005" option_set="SBAS_Region" title="CCN-504" name="TXDAT Flits sent" description="TXDAT Flits sent."/> |
@@ -118,5 +110,4 @@ | |||
118 | <event event="0x1008" option_set="SBAS_Region" title="CCN-504" name="RRT full" description="RRT full."/> | 110 | <event event="0x1008" option_set="SBAS_Region" title="CCN-504" name="RRT full" description="RRT full."/> |
119 | <event event="0x1009" option_set="SBAS_Region" title="CCN-504" name="WRT full" description="WRT full."/> | 111 | <event event="0x1009" option_set="SBAS_Region" title="CCN-504" name="WRT full" description="WRT full."/> |
120 | <event event="0x100A" option_set="SBAS_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/> | 112 | <event event="0x100A" option_set="SBAS_Region" title="CCN-504" name="Replayed TXREQ Flits" description="Replayed TXREQ Flits."/> |
121 | |||
122 | </category> | 113 | </category> |
diff --git a/daemon/events-Cortex-A53.xml b/daemon/events-Cortex-A53.xml index 577dcd9..5ba1790 100644 --- a/daemon/events-Cortex-A53.xml +++ b/daemon/events-Cortex-A53.xml | |||
@@ -1,171 +1,87 @@ | |||
1 | <counter_set name="ARM_Cortex-A53_cnt" count="6"/> | 1 | <counter_set name="ARM_Cortex-A53_cnt" count="6"/> |
2 | <category name="Cortex-A53" counter_set="ARM_Cortex-A53_cnt" per_cpu="yes" supports_event_based_sampling="yes"> | 2 | <category name="Cortex-A53" counter_set="ARM_Cortex-A53_cnt" per_cpu="yes" supports_event_based_sampling="yes"> |
3 | <!-- 0x11 CPU_CYCLES - Cycle --> | ||
4 | <event counter="ARM_Cortex-A53_ccnt" event="0x11" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/> | 3 | <event counter="ARM_Cortex-A53_ccnt" event="0x11" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/> |
5 | <!-- 0x00 SW_INCR - Instruction architecturally executed (condition check pass) - Software increment --> | ||
6 | <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/> | 4 | <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/> |
7 | <!-- 0x01 L1I_CACHE_REFILL - Level 1 instruction cache refill --> | ||
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"/> | 5 | <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 | <!-- 0x02 L1I_TLB_REFILL - Level 1 instruction TLB refill --> | ||
10 | <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"/> | 6 | <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 | <!-- 0x03 L1D_CACHE_REFILL - Level 1 data cache refill --> | ||
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"/> | 7 | <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 | <!-- 0x04 L1D_CACHE - Level 1 data cache access --> | ||
14 | <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"/> | 8 | <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 | <!-- 0x05 L1D_TLB_REFILL - Level 1 data TLB refill --> | ||
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"/> | 9 | <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 | <!-- 0x08 INST_RETIRED - Instruction architecturally executed --> | ||
18 | <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/> | 10 | <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/> |
19 | <!-- 0x09 EXC_TAKEN - Exception taken --> | ||
20 | <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/> | 11 | <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/> |
21 | <!-- 0x0A EXC_RETURN - Instruction architecturally executed (condition check pass) - Exception return --> | ||
22 | <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/> | 12 | <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/> |
23 | <!-- 0x0B CID_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to CONTEXTIDR --> | ||
24 | <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/> | 13 | <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/> |
25 | <!-- 0x10 BR_MIS_PRED - Mispredicted or not predicted branch speculatively executed --> | ||
26 | <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/> | 14 | <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/> |
27 | <!-- 0x12 BR_PRED - Predictable branch speculatively executed --> | ||
28 | <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"/> | 15 | <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"/> |
29 | <!-- 0x13 MEM_ACCESS - Data memory access --> | ||
30 | <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/> | 16 | <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/> |
31 | <!-- 0x14 L1I_CACHE - Level 1 instruction cache access --> | ||
32 | <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/> | 17 | <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/> |
33 | <!-- 0x15 L1D_CACHE_WB - Level 1 data cache Write-Back --> | ||
34 | <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/> | 18 | <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/> |
35 | <!-- 0x16 L2D_CACHE - Level 2 data cache access --> | ||
36 | <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/> | 19 | <event event="0x16" title="Cache" name="L2 data access" description="Level 2 data cache access"/> |
37 | <!-- 0x17 L2D_CACHE_REFILL - Level 2 data cache refill --> | ||
38 | <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/> | 20 | <event event="0x17" title="Cache" name="L2 data refill" description="Level 2 data cache refill"/> |
39 | <!-- 0x18 L2D_CACHE_WB - Level 2 data cache Write-Back --> | ||
40 | <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/> | 21 | <event event="0x18" title="Cache" name="L2 data write" description="Level 2 data cache Write-Back"/> |
41 | <!-- 0x19 BUS_ACCESS - Bus access --> | ||
42 | <event event="0x19" title="Bus" name="Access" description="Bus access"/> | 22 | <event event="0x19" title="Bus" name="Access" description="Bus access"/> |
43 | <!-- 0x1A MEMORY_ERROR - Local memory error --> | ||
44 | <event event="0x1A" title="Memory" name="Error" description="Local memory error"/> | 23 | <event event="0x1A" title="Memory" name="Error" description="Local memory error"/> |
45 | <!-- 0x1B INST_SPEC - Operation speculatively executed --> | ||
46 | <event event="0x1B" title="Instruction" name="Speculative" description="Operation speculatively executed"/> | 24 | <event event="0x1B" title="Instruction" name="Speculative" description="Operation speculatively executed"/> |
47 | <!-- 0x1C TTBR_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to translation table base --> | ||
48 | <event event="0x1C" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/> | 25 | <event event="0x1C" title="Memory" name="Translation table" description="Instruction architecturally executed (condition check pass) - Write to translation table base"/> |
49 | <!-- 0x1D BUS_CYCLES - Bus cycle --> | ||
50 | <event event="0x1D" title="Bus" name="Cycle" description="Bus cycle"/> | 26 | <event event="0x1D" title="Bus" name="Cycle" description="Bus cycle"/> |
51 | <!-- 0x1E CHAIN - Odd performance counter chain mode --> | ||
52 | <event event="0x1E" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/> | 27 | <event event="0x1E" title="Counter chain" name="Odd Performance" description="Odd performance counter chain mode"/> |
53 | <!-- 0x40 L1D_CACHE_LD - Level 1 data cache access - Read --> | ||
54 | <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/> | 28 | <event event="0x40" title="Cache" name="L1 data read" description="Level 1 data cache access - Read"/> |
55 | <!-- 0x41 L1D_CACHE_ST - Level 1 data cache access - Write --> | ||
56 | <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/> | 29 | <event event="0x41" title="Cache" name="L1 data access write" description="Level 1 data cache access - Write"/> |
57 | <!-- 0x42 L1D_CACHE_REFILL_LD - Level 1 data cache refill - Read --> | ||
58 | <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/> | 30 | <event event="0x42" title="Cache" name="L1 data refill read" description="Level 1 data cache refill - Read"/> |
59 | <!-- 0x43 L1D_CACHE_REFILL_ST - Level 1 data cache refill - Write --> | ||
60 | <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/> | 31 | <event event="0x43" title="Cache" name="L1 data refill write" description="Level 1 data cache refill - Write"/> |
61 | <!-- 0x46 L1D_CACHE_WB_VICTIM - Level 1 data cache Write-back - Victim --> | ||
62 | <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-back - Victim"/> | 32 | <event event="0x46" title="Cache" name="L1 data victim" description="Level 1 data cache Write-back - Victim"/> |
63 | <!-- 0x47 L1D_CACHE_WB_CLEAN - Level 1 data cache Write-back - Cleaning and coherency --> | ||
64 | <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-back - Cleaning and coherency"/> | 33 | <event event="0x47" title="Cache" name="L1 data clean" description="Level 1 data cache Write-back - Cleaning and coherency"/> |
65 | <!-- 0x48 L1D_CACHE_INVAL - Level 1 data cache invalidate --> | ||
66 | <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/> | 34 | <event event="0x48" title="Cache" name="L1 data invalidate" description="Level 1 data cache invalidate"/> |
67 | <!-- 0x4C L1D_TLB_REFILL_LD - Level 1 data TLB refill - Read --> | ||
68 | <event event="0x4C" title="Cache" name="L1 data refill read" description="Level 1 data TLB refill - Read"/> | 35 | <event event="0x4C" title="Cache" name="L1 data refill read" description="Level 1 data TLB refill - Read"/> |
69 | <!-- 0x4D L1D_TLB_REFILL_ST - Level 1 data TLB refill - Write --> | ||
70 | <event event="0x4D" title="Cache" name="L1 data refill write" description="Level 1 data TLB refill - Write"/> | 36 | <event event="0x4D" title="Cache" name="L1 data refill write" description="Level 1 data TLB refill - Write"/> |
71 | <!-- 0x50 L2D_CACHE_LD - Level 2 data cache access - Read --> | ||
72 | <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/> | 37 | <event event="0x50" title="Cache" name="L2 data read" description="Level 2 data cache access - Read"/> |
73 | <!-- 0x51 L2D_CACHE_ST - Level 2 data cache access - Write --> | ||
74 | <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/> | 38 | <event event="0x51" title="Cache" name="L2 data access write" description="Level 2 data cache access - Write"/> |
75 | <!-- 0x52 L2D_CACHE_REFILL_LD - Level 2 data cache refill - Read --> | ||
76 | <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/> | 39 | <event event="0x52" title="Cache" name="L2 data refill read" description="Level 2 data cache refill - Read"/> |
77 | <!-- 0x53 L2D_CACHE_REFILL_ST - Level 2 data cache refill - Write --> | ||
78 | <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/> | 40 | <event event="0x53" title="Cache" name="L2 data refill write" description="Level 2 data cache refill - Write"/> |
79 | <!-- 0x56 L2D_CACHE_WB_VICTIM - Level 2 data cache Write-back - Victim --> | ||
80 | <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-back - Victim"/> | 41 | <event event="0x56" title="Cache" name="L2 data victim" description="Level 2 data cache Write-back - Victim"/> |
81 | <!-- 0x57 L2D_CACHE_WB_CLEAN - Level 2 data cache Write-back - Cleaning and coherency --> | ||
82 | <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-back - Cleaning and coherency"/> | 42 | <event event="0x57" title="Cache" name="L2 data clean" description="Level 2 data cache Write-back - Cleaning and coherency"/> |
83 | <!-- 0x58 L2D_CACHE_INVAL - Level 2 data cache invalidate --> | ||
84 | <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/> | 43 | <event event="0x58" title="Cache" name="L2 data invalidate" description="Level 2 data cache invalidate"/> |
85 | <!-- 0x60 BUS_ACCESS_LD - Bus access - Read --> | ||
86 | <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/> | 44 | <event event="0x60" title="Bus" name="Read" description="Bus access - Read"/> |
87 | <!-- 0x61 BUS_ACCESS_ST - Bus access - Write --> | ||
88 | <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/> | 45 | <event event="0x61" title="Bus" name="Write" description="Bus access - Write"/> |
89 | <!-- 0x62 BUS_ACCESS_SHARED - Bus access - Normal --> | ||
90 | <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/> | 46 | <event event="0x62" title="Bus" name="Access shared" description="Bus access - Normal"/> |
91 | <!-- 0x63 BUS_ACCESS_NOT_SHARED - Bus access - Not normal --> | ||
92 | <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/> | 47 | <event event="0x63" title="Bus" name="Access not shared" description="Bus access - Not normal"/> |
93 | <!-- 0x64 BUS_ACCESS_NORMAL - Bus access - Normal --> | ||
94 | <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/> | 48 | <event event="0x64" title="Bus" name="Access normal" description="Bus access - Normal"/> |
95 | <!-- 0x65 BUS_ACCESS_PERIPH - Bus access - Peripheral --> | ||
96 | <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/> | 49 | <event event="0x65" title="Bus" name="Peripheral" description="Bus access - Peripheral"/> |
97 | <!-- 0x66 MEM_ACCESS_LD - Data memory access - Read --> | ||
98 | <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/> | 50 | <event event="0x66" title="Memory" name="Read" description="Data memory access - Read"/> |
99 | <!-- 0x67 MEM_ACCESS_ST - Data memory access - Write --> | ||
100 | <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/> | 51 | <event event="0x67" title="Memory" name="Write" description="Data memory access - Write"/> |
101 | <!-- 0x68 UNALIGNED_LD_SPEC - Unaligned access - Read --> | ||
102 | <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/> | 52 | <event event="0x68" title="Memory" name="Unaligned Read" description="Unaligned access - Read"/> |
103 | <!-- 0x69 UNALIGNED_ST_SPEC - Unaligned access - Write --> | ||
104 | <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/> | 53 | <event event="0x69" title="Memory" name="Unaligned Write" description="Unaligned access - Write"/> |
105 | <!-- 0x6A UNALIGNED_LDST_SPEC - Unaligned access --> | ||
106 | <event event="0x6A" title="Memory" name="Unaligned" description="Unaligned access"/> | 54 | <event event="0x6A" title="Memory" name="Unaligned" description="Unaligned access"/> |
107 | <!-- 0x6C LDREX_SPEC - Exclusive operation speculatively executed - LDREX --> | ||
108 | <event event="0x6C" title="Intrinsic" name="LDREX" description="Exclusive operation speculatively executed - LDREX"/> | 55 | <event event="0x6C" title="Intrinsic" name="LDREX" description="Exclusive operation speculatively executed - LDREX"/> |
109 | <!-- 0x6D STREX_PASS_SPEC - Exclusive instruction speculatively executed - STREX pass --> | ||
110 | <event event="0x6D" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/> | 56 | <event event="0x6D" title="Intrinsic" name="STREX pass" description="Exclusive instruction speculatively executed - STREX pass"/> |
111 | <!-- 0x6E STREX_FAIL_SPEC - Exclusive operation speculatively executed - STREX fail --> | ||
112 | <event event="0x6E" title="Intrinsic" name="STREX fail" description="Exclusive operation speculatively executed - STREX fail"/> | 57 | <event event="0x6E" title="Intrinsic" name="STREX fail" description="Exclusive operation speculatively executed - STREX fail"/> |
113 | <!-- 0x70 LD_SPEC - Operation speculatively executed - Load --> | ||
114 | <event event="0x70" title="Instruction" name="Load" description="Operation speculatively executed - Load"/> | 58 | <event event="0x70" title="Instruction" name="Load" description="Operation speculatively executed - Load"/> |
115 | <!-- 0x71 ST_SPEC - Operation speculatively executed - Store --> | ||
116 | <event event="0x71" title="Instruction" name="Store" description="Operation speculatively executed - Store"/> | 59 | <event event="0x71" title="Instruction" name="Store" description="Operation speculatively executed - Store"/> |
117 | <!-- 0x72 LDST_SPEC - Operation speculatively executed - Load or store --> | ||
118 | <event event="0x72" title="Instruction" name="Load/Store" description="Operation speculatively executed - Load or store"/> | 60 | <event event="0x72" title="Instruction" name="Load/Store" description="Operation speculatively executed - Load or store"/> |
119 | <!-- 0x73 DP_SPEC - Operation speculatively executed - Integer data processing --> | ||
120 | <event event="0x73" title="Instruction" name="Integer" description="Operation speculatively executed - Integer data processing"/> | 61 | <event event="0x73" title="Instruction" name="Integer" description="Operation speculatively executed - Integer data processing"/> |
121 | <!-- 0x74 ASE_SPEC - Operation speculatively executed - Advanced SIMD --> | ||
122 | <event event="0x74" title="Instruction" name="Advanced SIMD" description="Operation speculatively executed - Advanced SIMD"/> | 62 | <event event="0x74" title="Instruction" name="Advanced SIMD" description="Operation speculatively executed - Advanced SIMD"/> |
123 | <!-- 0x75 VFP_SPEC - Operation speculatively executed - VFP --> | ||
124 | <event event="0x75" title="Instruction" name="VFP" description="Operation speculatively executed - VFP"/> | 63 | <event event="0x75" title="Instruction" name="VFP" description="Operation speculatively executed - VFP"/> |
125 | <!-- 0x76 PC_WRITE_SPEC - Operation speculatively executed - Software change of the PC --> | ||
126 | <event event="0x76" title="Instruction" name="Software change" description="Operation speculatively executed - Software change of the PC"/> | 64 | <event event="0x76" title="Instruction" name="Software change" description="Operation speculatively executed - Software change of the PC"/> |
127 | <!-- 0x77 CRYPTO_SPEC - Operation speculatively executed, crypto data processing --> | ||
128 | <event event="0x77" title="Instruction" name="Crypto" description="Operation speculatively executed, crypto data processing"/> | 65 | <event event="0x77" title="Instruction" name="Crypto" description="Operation speculatively executed, crypto data processing"/> |
129 | <!-- 0x78 BR_IMMED_SPEC - Branch speculatively executed - Immediate branch --> | ||
130 | <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/> | 66 | <event event="0x78" title="Instruction" name="Immediate branch" description="Branch speculatively executed - Immediate branch"/> |
131 | <!-- 0x79 BR_RETURN_SPEC - Branch speculatively executed - Procedure return --> | ||
132 | <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/> | 67 | <event event="0x79" title="Instruction" name="Procedure return" description="Branch speculatively executed - Procedure return"/> |
133 | <!-- 0x7A BR_INDIRECT_SPEC - Branch speculatively executed - Indirect branch --> | ||
134 | <event event="0x7A" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/> | 68 | <event event="0x7A" title="Instruction" name="Indirect branch" description="Branch speculatively executed - Indirect branch"/> |
135 | <!-- 0x7C ISB_SPEC - Barrier speculatively executed - ISB --> | ||
136 | <event event="0x7C" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/> | 69 | <event event="0x7C" title="Instruction" name="ISB" description="Barrier speculatively executed - ISB"/> |
137 | <!-- 0x7D DSB_SPEC - Barrier speculatively executed - DSB --> | ||
138 | <event event="0x7D" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/> | 70 | <event event="0x7D" title="Instruction" name="DSB" description="Barrier speculatively executed - DSB"/> |
139 | <!-- 0x7E DMB_SPEC - Barrier speculatively executed - DMB --> | ||
140 | <event event="0x7E" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/> | 71 | <event event="0x7E" title="Instruction" name="DMB" description="Barrier speculatively executed - DMB"/> |
141 | <!-- 0x81 EXC_UNDEF - Exception taken, other synchronous --> | ||
142 | <event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/> | 72 | <event event="0x81" title="Exception" name="Undefined" description="Exception taken, other synchronous"/> |
143 | <!-- 0x82 EXC_SVC - Exception taken, Supervisor Call --> | ||
144 | <event event="0x82" title="Exception" name="Supervisor" description="Exception taken, Supervisor Call"/> | 73 | <event event="0x82" title="Exception" name="Supervisor" description="Exception taken, Supervisor Call"/> |
145 | <!-- 0x83 EXC_PABORT - Exception taken, Instruction Abort --> | ||
146 | <event event="0x83" title="Exception" name="Instruction abort" description="Exception taken, Instruction Abort"/> | 74 | <event event="0x83" title="Exception" name="Instruction abort" description="Exception taken, Instruction Abort"/> |
147 | <!-- 0x84 EXC_DABORT - Exception taken, Data Abort or SError --> | ||
148 | <event event="0x84" title="Exception" name="Data abort" description="Exception taken, Data Abort or SError"/> | 75 | <event event="0x84" title="Exception" name="Data abort" description="Exception taken, Data Abort or SError"/> |
149 | <!-- 0x86 EXC_IRQ - Exception taken, IRQ --> | ||
150 | <event event="0x86" title="Interrupts" name="IRQ" description="Exception taken, IRQ"/> | 76 | <event event="0x86" title="Interrupts" name="IRQ" description="Exception taken, IRQ"/> |
151 | <!-- 0x87 EXC_FIQ - Exception taken, FIQ --> | ||
152 | <event event="0x87" title="Interrupts" name="FIQ" description="Exception taken, FIQ"/> | 77 | <event event="0x87" title="Interrupts" name="FIQ" description="Exception taken, FIQ"/> |
153 | <!-- 0x88 EXC_SMC - Exception taken, Secure Monitor Call --> | ||
154 | <event event="0x88" title="Exception" name="Secure monitor call" description="Exception taken, Secure Monitor Call"/> | 78 | <event event="0x88" title="Exception" name="Secure monitor call" description="Exception taken, Secure Monitor Call"/> |
155 | <!-- 0x8A EXC_HVC - Exception taken, Hypervisor Call --> | ||
156 | <event event="0x8A" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/> | 79 | <event event="0x8A" title="Exception" name="Hypervisor call" description="Exception taken, Hypervisor Call"/> |
157 | <!-- 0x8B EXC_TRAP_PABORT - Exception taken, Instruction Abort not taken locally --> | ||
158 | <event event="0x8B" title="Exception" name="Instruction abort non-local" description="Exception taken, Instruction Abort not taken locally"/> | 80 | <event event="0x8B" title="Exception" name="Instruction abort non-local" description="Exception taken, Instruction Abort not taken locally"/> |
159 | <!-- 0x8C EXC_TRAP_DABORT - Exception taken, Data Abort or SError not taken locally --> | ||
160 | <event event="0x8C" title="Exception" name="Data abort non-local" description="Exception taken, Data Abort or SError not taken locally"/> | 81 | <event event="0x8C" title="Exception" name="Data abort non-local" description="Exception taken, Data Abort or SError not taken locally"/> |
161 | <!-- 0x8D EXC_TRAP_OTHER - Exception taken - Other traps not taken locally --> | ||
162 | <event event="0x8D" title="Exception" name="Other non-local" description="Exception taken - Other traps not taken locally"/> | 82 | <event event="0x8D" title="Exception" name="Other non-local" description="Exception taken - Other traps not taken locally"/> |
163 | <!-- 0x8E EXC_TRAP_IRQ - Exception taken, IRQ not taken locally --> | ||
164 | <event event="0x8E" title="Exception" name="IRQ non-local" description="Exception taken, IRQ not taken locally"/> | 83 | <event event="0x8E" title="Exception" name="IRQ non-local" description="Exception taken, IRQ not taken locally"/> |
165 | <!-- 0x8F EXC_TRAP_FIQ - Exception taken, FIQ not taken locally --> | ||
166 | <event event="0x8F" title="Exception" name="FIQ non-local" description="Exception taken, FIQ not taken locally"/> | 84 | <event event="0x8F" title="Exception" name="FIQ non-local" description="Exception taken, FIQ not taken locally"/> |
167 | <!-- 0x90 RC_LD_SPEC - Release consistency instruction speculatively executed - Load Acquire --> | ||
168 | <event event="0x90" title="Release Consistency" name="Load" description="Release consistency instruction speculatively executed - Load Acquire"/> | 85 | <event event="0x90" title="Release Consistency" name="Load" description="Release consistency instruction speculatively executed - Load Acquire"/> |
169 | <!-- 0x91 RC_ST_SPEC - Release consistency instruction speculatively executed - Store Release --> | ||
170 | <event event="0x91" title="Release Consistency" name="Store" description="Release consistency instruction speculatively executed - Store Release"/> | 86 | <event event="0x91" title="Release Consistency" name="Store" description="Release consistency instruction speculatively executed - Store Release"/> |
171 | </category> | 87 | </category> |
diff --git a/daemon/events-Cortex-A57.xml b/daemon/events-Cortex-A57.xml index b7178c0..fbe96c2 100644 --- a/daemon/events-Cortex-A57.xml +++ b/daemon/events-Cortex-A57.xml | |||
@@ -1,171 +1,87 @@ | |||
1 | <counter_set name="ARM_Cortex-A57_cnt" count="6"/> | 1 | <counter_set name="ARM_Cortex-A57_cnt" count="6"/> |
2 | <category name="Cortex-A57" counter_set="ARM_Cortex-A57_cnt" per_cpu="yes" supports_event_based_sampling="yes"> | 2 | <category name="Cortex-A57" counter_set="ARM_Cortex-A57_cnt" per_cpu="yes" supports_event_based_sampling="yes"> |
3 | <!-- 0x11 CPU_CYCLES - Cycle --> | ||
4 | <event counter="ARM_Cortex-A57_ccnt" event="0x11" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/> | 3 | <event counter="ARM_Cortex-A57_ccnt" event="0x11" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/> |
5 | <!-- 0x00 SW_INCR - Instruction architecturally executed (condition check pass) - Software increment --> | ||
6 | <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/> | 4 | <event event="0x00" title="Software" name="Increment" description="Incremented only on writes to the Software Increment Register"/> |
7 | <!-- 0x01 L1I_CACHE_REFILL - Level 1 instruction cache refill --> | ||
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"/> | 5 | <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 | <!-- 0x02 L1I_TLB_REFILL - Level 1 instruction TLB refill --> | ||
10 | <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"/> | 6 | <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 | <!-- 0x03 L1D_CACHE_REFILL - Level 1 data cache refill --> | ||
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"/> | 7 | <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 | <!-- 0x04 L1D_CACHE - Level 1 data cache access --> | ||
14 | <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"/> | 8 | <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 | <!-- 0x05 L1D_TLB_REFILL - Level 1 data TLB refill --> | ||
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"/> | 9 | <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 | <!-- 0x08 INST_RETIRED - Instruction architecturally executed --> | ||
18 | <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/> | 10 | <event event="0x08" title="Instruction" name="Executed" description="Instruction architecturally executed"/> |
19 | <!-- 0x09 EXC_TAKEN - Exception taken --> | ||
20 | <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/> | 11 | <event event="0x09" title="Exception" name="Taken" description="Exceptions taken"/> |
21 | <!-- 0x0A EXC_RETURN - Instruction architecturally executed (condition check pass) - Exception return --> | ||
22 | <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/> | 12 | <event event="0x0a" title="Exception" name="Return" description="Exception return architecturally executed"/> |
23 | <!-- 0x0B CID_WRITE_RETIRED - Instruction architecturally executed (condition check pass) - Write to CONTEXTIDR --> | ||
24 | <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/> | 13 | <event event="0x0b" title="Instruction" name="CONTEXTIDR" description="Instruction that writes to the CONTEXTIDR architecturally executed"/> |
25 | <!-- 0x10 BR_MIS_PRED - Mispredicted or not predicted branch speculatively executed --> | ||
26 | <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/> | 14 | <event event="0x10" title="Branch" name="Mispredicted" description="Branch mispredicted or not predicted"/> |
27 | <!-- 0x12 BR_PRED - Predictable branch speculatively executed --> | ||
28 | <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"/> | 15 | <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"/> |
29 | <!-- 0x13 MEM_ACCESS - Data memory access --> | ||
30 | <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/> | 16 | <event event="0x13" title="Memory" name="Memory access" description="Data memory access"/> |
31 | <!-- 0x14 L1I_CACHE - Level 1 instruction cache access --> | ||
32 | <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/> | 17 | <event event="0x14" title="Cache" name="L1 inst access" description="Level 1 instruction cache access"/> |
33 | <!-- 0x15 L1D_CACHE_WB - Level 1 data cache Write-Back --> | ||
34 | <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/> | 18 | <event event="0x15" title="Cache" name="L1 data write" description="Level 1 data cache Write-Back"/> |
35 | <!-- 0x16 L2D_CACHE - Level 2 data cache access --> |