aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorJon Medhurst <tixy@linaro.org>2014-10-30 18:01:15 +0000
committerJon Medhurst <tixy@linaro.org>2014-11-18 14:26:02 +0000
commit730ab7f66781e433083572fb9000092e172bec3c (patch)
tree3f288815ce3ff5e84fafbe568bb4597b988a8191 /tools
parente49849053ac342ce82c92aa0d2244e4767fd1fbb (diff)
gator: Version 5.20
Signed-off-by: Jon Medhurst <tixy@linaro.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/gator/daemon/Android.mk17
-rw-r--r--tools/gator/daemon/AnnotateListener.cpp69
-rw-r--r--tools/gator/daemon/AnnotateListener.h31
-rw-r--r--tools/gator/daemon/Application.mk2
-rw-r--r--tools/gator/daemon/Buffer.cpp215
-rw-r--r--tools/gator/daemon/Buffer.h38
-rw-r--r--tools/gator/daemon/CCNDriver.cpp295
-rw-r--r--tools/gator/daemon/CCNDriver.h43
-rw-r--r--tools/gator/daemon/CPUFreqDriver.cpp58
-rw-r--r--tools/gator/daemon/CPUFreqDriver.h34
-rw-r--r--tools/gator/daemon/CapturedXML.cpp17
-rw-r--r--tools/gator/daemon/CapturedXML.h4
-rw-r--r--tools/gator/daemon/Child.cpp82
-rw-r--r--tools/gator/daemon/Child.h4
-rw-r--r--tools/gator/daemon/Command.cpp172
-rw-r--r--tools/gator/daemon/Command.h14
-rw-r--r--tools/gator/daemon/Config.h13
-rw-r--r--tools/gator/daemon/DiskIODriver.cpp125
-rw-r--r--tools/gator/daemon/DiskIODriver.h39
-rw-r--r--tools/gator/daemon/Driver.cpp81
-rw-r--r--tools/gator/daemon/Driver.h76
-rw-r--r--tools/gator/daemon/DriverSource.cpp19
-rw-r--r--tools/gator/daemon/DynBuf.cpp2
-rw-r--r--tools/gator/daemon/EventsXML.cpp2
-rw-r--r--tools/gator/daemon/ExternalSource.cpp87
-rw-r--r--tools/gator/daemon/ExternalSource.h8
-rw-r--r--tools/gator/daemon/FSDriver.cpp140
-rw-r--r--tools/gator/daemon/FSDriver.h19
-rw-r--r--tools/gator/daemon/Fifo.cpp5
-rw-r--r--tools/gator/daemon/Fifo.h10
-rw-r--r--tools/gator/daemon/FtraceDriver.cpp118
-rw-r--r--tools/gator/daemon/FtraceDriver.h31
-rw-r--r--tools/gator/daemon/FtraceSource.cpp158
-rw-r--r--tools/gator/daemon/FtraceSource.h43
-rw-r--r--tools/gator/daemon/Hwmon.h45
-rw-r--r--tools/gator/daemon/HwmonDriver.cpp (renamed from tools/gator/daemon/Hwmon.cpp)213
-rw-r--r--tools/gator/daemon/HwmonDriver.h31
-rw-r--r--tools/gator/daemon/KMod.cpp9
-rw-r--r--tools/gator/daemon/KMod.h7
-rw-r--r--tools/gator/daemon/LocalCapture.h4
-rw-r--r--tools/gator/daemon/Logging.cpp18
-rw-r--r--tools/gator/daemon/Logging.h12
-rw-r--r--tools/gator/daemon/Makefile5
-rw-r--r--tools/gator/daemon/MaliVideoDriver.cpp148
-rw-r--r--tools/gator/daemon/MaliVideoDriver.h17
-rw-r--r--tools/gator/daemon/MemInfoDriver.cpp93
-rw-r--r--tools/gator/daemon/MemInfoDriver.h37
-rw-r--r--tools/gator/daemon/Monitor.cpp14
-rw-r--r--tools/gator/daemon/NetDriver.cpp129
-rw-r--r--tools/gator/daemon/NetDriver.h39
-rw-r--r--tools/gator/daemon/OlySocket.cpp54
-rw-r--r--tools/gator/daemon/OlySocket.h9
-rw-r--r--tools/gator/daemon/PerfBuffer.cpp65
-rw-r--r--tools/gator/daemon/PerfBuffer.h4
-rw-r--r--tools/gator/daemon/PerfDriver.cpp194
-rw-r--r--tools/gator/daemon/PerfDriver.h15
-rw-r--r--tools/gator/daemon/PerfGroup.cpp66
-rw-r--r--tools/gator/daemon/PerfGroup.h14
-rw-r--r--tools/gator/daemon/PerfSource.cpp306
-rw-r--r--tools/gator/daemon/PerfSource.h3
-rw-r--r--tools/gator/daemon/Proc.cpp137
-rw-r--r--tools/gator/daemon/Proc.h6
-rw-r--r--tools/gator/daemon/Sender.cpp7
-rw-r--r--tools/gator/daemon/Sender.h4
-rw-r--r--tools/gator/daemon/SessionData.cpp91
-rw-r--r--tools/gator/daemon/SessionData.h44
-rw-r--r--tools/gator/daemon/SessionXML.cpp40
-rw-r--r--tools/gator/daemon/SessionXML.h12
-rw-r--r--tools/gator/daemon/Setup.cpp232
-rw-r--r--tools/gator/daemon/Setup.h18
-rw-r--r--tools/gator/daemon/StreamlineSetup.h4
-rw-r--r--tools/gator/daemon/UEvent.cpp3
-rw-r--r--tools/gator/daemon/UserSpaceSource.cpp23
-rw-r--r--tools/gator/daemon/defaults.xml33
-rw-r--r--tools/gator/daemon/events-Cortex-A17.xml (renamed from tools/gator/daemon/events-Cortex-A12.xml)8
-rw-r--r--tools/gator/daemon/events-Filesystem.xml12
-rw-r--r--tools/gator/daemon/events-Linux.xml11
-rw-r--r--tools/gator/daemon/events-Mali-Midgard.xml46
-rw-r--r--tools/gator/daemon/events-Mali-Midgard_hw.xml91
-rw-r--r--tools/gator/daemon/events-Mali-T60x_hw.xml108
-rw-r--r--tools/gator/daemon/events-Mali-T62x_hw.xml109
-rw-r--r--tools/gator/daemon/events-Mali-T6xx.xml46
-rw-r--r--tools/gator/daemon/events-Mali-T6xx_hw.xml91
-rw-r--r--tools/gator/daemon/events-Mali-T72x_hw.xml95
-rw-r--r--tools/gator/daemon/events-Mali-T76x_hw.xml108
-rw-r--r--tools/gator/daemon/events-Mali-V500.xml55
-rw-r--r--tools/gator/daemon/events-ftrace.xml7
-rw-r--r--tools/gator/daemon/main.cpp95
-rw-r--r--tools/gator/daemon/mxml/config.h10
-rw-r--r--tools/gator/daemon/mxml/mxml-attr.c19
-rw-r--r--tools/gator/daemon/mxml/mxml-entity.c19
-rw-r--r--tools/gator/daemon/mxml/mxml-file.c104
-rw-r--r--tools/gator/daemon/mxml/mxml-get.c27
-rw-r--r--tools/gator/daemon/mxml/mxml-index.c11
-rw-r--r--tools/gator/daemon/mxml/mxml-node.c31
-rw-r--r--tools/gator/daemon/mxml/mxml-private.c42
-rw-r--r--tools/gator/daemon/mxml/mxml-private.h8
-rw-r--r--tools/gator/daemon/mxml/mxml-search.c17
-rw-r--r--tools/gator/daemon/mxml/mxml-set.c20
-rw-r--r--tools/gator/daemon/mxml/mxml-string.c21
-rw-r--r--tools/gator/daemon/mxml/mxml.h17
101 files changed, 4063 insertions, 1441 deletions
diff --git a/tools/gator/daemon/Android.mk b/tools/gator/daemon/Android.mk
index 44c069cc7e24..970ac6946150 100644
--- a/tools/gator/daemon/Android.mk
+++ b/tools/gator/daemon/Android.mk
@@ -3,13 +3,16 @@ include $(CLEAR_VARS)
XML_H := $(shell cd $(LOCAL_PATH) && make events_xml.h defaults_xml.h)
-LOCAL_CFLAGS += -Wall -O3 -mthumb-interwork -fno-exceptions -pthread -DETCDIR=\"/etc\" -Ilibsensors
-
LOCAL_SRC_FILES := \
+ AnnotateListener.cpp \
Buffer.cpp \
+ CCNDriver.cpp \
+ CPUFreqDriver.cpp \
CapturedXML.cpp \
Child.cpp \
+ Command.cpp \
ConfigurationXML.cpp \
+ DiskIODriver.cpp \
Driver.cpp \
DriverSource.cpp \
DynBuf.cpp \
@@ -17,13 +20,17 @@ LOCAL_SRC_FILES := \
ExternalSource.cpp \
FSDriver.cpp \
Fifo.cpp \
- Hwmon.cpp \
+ FtraceDriver.cpp \
+ FtraceSource.cpp \
+ HwmonDriver.cpp \
KMod.cpp \
LocalCapture.cpp \
Logging.cpp \
main.cpp \
MaliVideoDriver.cpp \
+ MemInfoDriver.cpp\
Monitor.cpp \
+ NetDriver.cpp \
OlySocket.cpp \
OlyUtility.cpp \
PerfBuffer.cpp \
@@ -34,6 +41,7 @@ LOCAL_SRC_FILES := \
Sender.cpp \
SessionData.cpp \
SessionXML.cpp \
+ Setup.cpp \
Source.cpp \
StreamlineSetup.cpp \
UEvent.cpp \
@@ -57,6 +65,9 @@ LOCAL_SRC_FILES := \
mxml/mxml-set.c \
mxml/mxml-string.c
+LOCAL_CFLAGS += -Wall -O3 -fno-exceptions -pthread -DETCDIR=\"/etc\" -Ilibsensors -fPIE
+LOCAL_LDFLAGS += -fPIE -pie
+
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_MODULE := gatord
diff --git a/tools/gator/daemon/AnnotateListener.cpp b/tools/gator/daemon/AnnotateListener.cpp
new file mode 100644
index 000000000000..50110b4dc84c
--- /dev/null
+++ b/tools/gator/daemon/AnnotateListener.cpp
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "AnnotateListener.h"
+
+#include <unistd.h>
+
+#include "OlySocket.h"
+
+struct AnnotateClient {
+ AnnotateClient *next;
+ int fd;
+};
+
+AnnotateListener::AnnotateListener() : mClients(NULL), mSock(NULL) {
+}
+
+AnnotateListener::~AnnotateListener() {
+ close();
+ delete mSock;
+}
+
+void AnnotateListener::setup() {
+ mSock = new OlyServerSocket(8082);
+}
+
+int AnnotateListener::getFd() {
+ return mSock->getFd();
+}
+
+void AnnotateListener::handle() {
+ AnnotateClient *const client = new AnnotateClient();
+ client->fd = mSock->acceptConnection();
+ client->next = mClients;
+ mClients = client;
+}
+
+void AnnotateListener::close() {
+ mSock->closeServerSocket();
+ while (mClients != NULL) {
+ ::close(mClients->fd);
+ AnnotateClient *next = mClients->next;
+ delete mClients;
+ mClients = next;
+ }
+}
+
+void AnnotateListener::signal() {
+ const char ch = 0;
+ AnnotateClient **ptr = &mClients;
+ AnnotateClient *client = mClients;
+ while (client != NULL) {
+ if (write(client->fd, &ch, sizeof(ch)) != 1) {
+ ::close(client->fd);
+ AnnotateClient *next = client->next;
+ delete client;
+ *ptr = next;
+ client = next;
+ continue;
+ }
+ ptr = &client->next;
+ client = client->next;
+ }
+}
diff --git a/tools/gator/daemon/AnnotateListener.h b/tools/gator/daemon/AnnotateListener.h
new file mode 100644
index 000000000000..cdefef12db22
--- /dev/null
+++ b/tools/gator/daemon/AnnotateListener.h
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+class AnnotateClient;
+class OlyServerSocket;
+
+class AnnotateListener {
+public:
+ AnnotateListener();
+ ~AnnotateListener();
+
+ void setup();
+ int getFd();
+
+ void handle();
+ void close();
+ void signal();
+
+private:
+ AnnotateClient *mClients;
+ OlyServerSocket *mSock;
+
+ // Intentionally unimplemented
+ AnnotateListener(const AnnotateListener &);
+ AnnotateListener &operator=(const AnnotateListener &);
+};
diff --git a/tools/gator/daemon/Application.mk b/tools/gator/daemon/Application.mk
index 631ba54148d1..3ada471cac19 100644
--- a/tools/gator/daemon/Application.mk
+++ b/tools/gator/daemon/Application.mk
@@ -1 +1,3 @@
APP_PLATFORM := android-8
+# Replace armeabi-v7a with arm64-v8a to build an arm64 gatord or with armeabi to build an ARM11 gatord
+APP_ABI := armeabi-v7a
diff --git a/tools/gator/daemon/Buffer.cpp b/tools/gator/daemon/Buffer.cpp
index dd19f7f8be76..8fa628015069 100644
--- a/tools/gator/daemon/Buffer.cpp
+++ b/tools/gator/daemon/Buffer.cpp
@@ -15,12 +15,15 @@
#define mask (mSize - 1)
enum {
- CODE_PEA = 1,
- CODE_KEYS = 2,
- CODE_FORMAT = 3,
- CODE_MAPS = 4,
- CODE_COMM = 5,
- CODE_KEYS_OLD = 6,
+ CODE_PEA = 1,
+ CODE_KEYS = 2,
+ CODE_FORMAT = 3,
+ CODE_MAPS = 4,
+ CODE_COMM = 5,
+ CODE_KEYS_OLD = 6,
+ CODE_ONLINE_CPU = 7,
+ CODE_OFFLINE_CPU = 8,
+ CODE_KALLSYMS = 9,
};
// Summary Frame Messages
@@ -42,16 +45,18 @@ enum {
/* Add another character so the length isn't 0x0a bytes */ \
"5"
-Buffer::Buffer(const int32_t core, const int32_t buftype, const int size, sem_t *const readerSem) : mCore(core), mBufType(buftype), mSize(size), mReadPos(0), mWritePos(0), mCommitPos(0), mAvailable(true), mIsDone(false), mBuf(new char[mSize]), mCommitTime(gSessionData->mLiveRate), mReaderSem(readerSem) {
+Buffer::Buffer(const int32_t core, const int32_t buftype, const int size, sem_t *const readerSem) : mBuf(new char[size]), mReaderSem(readerSem), mCommitTime(gSessionData->mLiveRate), mSize(size), mReadPos(0), mWritePos(0), mCommitPos(0), mAvailable(true), mIsDone(false), mCore(core), mBufType(buftype) {
if ((mSize & mask) != 0) {
logg->logError(__FILE__, __LINE__, "Buffer size is not a power of 2");
handleException();
}
+ sem_init(&mWriterSem, 0, 0);
frame();
}
Buffer::~Buffer() {
delete [] mBuf;
+ sem_destroy(&mWriterSem);
}
void Buffer::write(Sender *const sender) {
@@ -59,14 +64,18 @@ void Buffer::write(Sender *const sender) {
return;
}
+ // commit and read are updated by the writer, only read them once
+ int commitPos = mCommitPos;
+ int readPos = mReadPos;
+
// determine the size of two halves
- int length1 = mCommitPos - mReadPos;
- char *buffer1 = mBuf + mReadPos;
+ int length1 = commitPos - readPos;
+ char *buffer1 = mBuf + readPos;
int length2 = 0;
char *buffer2 = mBuf;
if (length1 < 0) {
- length1 = mSize - mReadPos;
- length2 = mCommitPos;
+ length1 = mSize - readPos;
+ length2 = commitPos;
}
logg->logMessage("Sending data length1: %i length2: %i", length1, length2);
@@ -81,7 +90,10 @@ void Buffer::write(Sender *const sender) {
sender->writeData(buffer2, length2, RESPONSE_APC_DATA);
}
- mReadPos = mCommitPos;
+ mReadPos = commitPos;
+
+ // send a notification that space is available
+ sem_post(&mWriterSem);
}
bool Buffer::commitReady() const {
@@ -193,7 +205,7 @@ void Buffer::packInt(int32_t x) {
packInt(mBuf, mSize, mWritePos, x);
}
-void Buffer::packInt64(int64_t x) {
+void Buffer::packInt64(char *const buf, const int size, int &writePos, int64_t x) {
int packedBytes = 0;
int more = true;
while (more) {
@@ -207,11 +219,15 @@ void Buffer::packInt64(int64_t x) {
b |= 0x80;
}
- mBuf[(mWritePos + packedBytes) & mask] = b;
+ buf[(writePos + packedBytes) & /*mask*/(size - 1)] = b;
packedBytes++;
}
- mWritePos = (mWritePos + packedBytes) & mask;
+ writePos = (writePos + packedBytes) & /*mask*/(size - 1);
+}
+
+void Buffer::packInt64(int64_t x) {
+ packInt64(mBuf, mSize, mWritePos, x);
}
void Buffer::writeBytes(const void *const data, size_t count) {
@@ -236,10 +252,12 @@ void Buffer::frame() {
// Reserve space for the length
mWritePos += sizeof(int32_t);
packInt(mBufType);
- packInt(mCore);
+ if ((mBufType == FRAME_BLOCK_COUNTER) || (mBufType == FRAME_PERF_ATTRS) || (mBufType == FRAME_PERF)) {
+ packInt(mCore);
+ }
}
-void Buffer::summary(const int64_t timestamp, const int64_t uptime, const int64_t monotonicDelta, const char *const uname) {
+void Buffer::summary(const uint64_t currTime, const int64_t timestamp, const int64_t uptime, const int64_t monotonicDelta, const char *const uname) {
packInt(MESSAGE_SUMMARY);
writeString(NEWLINE_CANARY);
packInt64(timestamp);
@@ -248,23 +266,24 @@ void Buffer::summary(const int64_t timestamp, const int64_t uptime, const int64_
writeString("uname");
writeString(uname);
writeString("");
- check(1);
+ check(currTime);
}
-void Buffer::coreName(const int core, const int cpuid, const char *const name) {
+void Buffer::coreName(const uint64_t currTime, const int core, const int cpuid, const char *const name) {
if (checkSpace(3 * MAXSIZE_PACK32 + 0x100)) {
packInt(MESSAGE_CORE_NAME);
packInt(core);
packInt(cpuid);
writeString(name);
}
- check(1);
+ check(currTime);
}
bool Buffer::eventHeader(const uint64_t curr_time) {
bool retval = false;
if (checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
- packInt(0); // key of zero indicates a timestamp
+ // key of zero indicates a timestamp
+ packInt(0);
packInt64(curr_time);
retval = true;
}
@@ -275,7 +294,8 @@ bool Buffer::eventHeader(const uint64_t curr_time) {
bool Buffer::eventTid(const int tid) {
bool retval = false;
if (checkSpace(2 * MAXSIZE_PACK32)) {
- packInt(1); // key of 1 indicates a tid
+ // key of 1 indicates a tid
+ packInt(1);
packInt(tid);
retval = true;
}
@@ -283,102 +303,119 @@ bool Buffer::eventTid(const int tid) {
return retval;
}
-void Buffer::event(const int32_t key, const int32_t value) {
+void Buffer::event(const int key, const int32_t value) {
if (checkSpace(2 * MAXSIZE_PACK32)) {
packInt(key);
packInt(value);
}
}
-void Buffer::event64(const int64_t key, const int64_t value) {
- if (checkSpace(2 * MAXSIZE_PACK64)) {
- packInt64(key);
+void Buffer::event64(const int key, const int64_t value) {
+ if (checkSpace(MAXSIZE_PACK64 + MAXSIZE_PACK32)) {
+ packInt(key);
packInt64(value);
}
}
-void Buffer::pea(const struct perf_event_attr *const pea, int key) {
- if (checkSpace(2 * MAXSIZE_PACK32 + pea->size)) {
- packInt(CODE_PEA);
- writeBytes(pea, pea->size);
- packInt(key);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
+void Buffer::pea(const uint64_t currTime, const struct perf_event_attr *const pea, int key) {
+ while (!checkSpace(2 * MAXSIZE_PACK32 + pea->size)) {
+ sem_wait(&mWriterSem);
}
- // Don't know the real perf time so use 1 as it will work for now
- check(1);
+ packInt(CODE_PEA);
+ writeBytes(pea, pea->size);
+ packInt(key);
+ check(currTime);
}
-void Buffer::keys(const int count, const __u64 *const ids, const int *const keys) {
- if (checkSpace(2 * MAXSIZE_PACK32 + count * (MAXSIZE_PACK32 + MAXSIZE_PACK64))) {
- packInt(CODE_KEYS);
- packInt(count);
- for (int i = 0; i < count; ++i) {
- packInt64(ids[i]);
- packInt(keys[i]);
- }
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
+void Buffer::keys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys) {
+ while (!checkSpace(2 * MAXSIZE_PACK32 + count * (MAXSIZE_PACK32 + MAXSIZE_PACK64))) {
+ sem_wait(&mWriterSem);
+ }
+ packInt(CODE_KEYS);
+ packInt(count);
+ for (int i = 0; i < count; ++i) {
+ packInt64(ids[i]);
+ packInt(keys[i]);
}
- check(1);
+ check(currTime);
}
-void Buffer::keysOld(const int keyCount, const int *const keys, const int bytes, const char *const buf) {
- if (checkSpace((2 + keyCount) * MAXSIZE_PACK32 + bytes)) {
- packInt(CODE_KEYS_OLD);
- packInt(keyCount);
- for (int i = 0; i < keyCount; ++i) {
- packInt(keys[i]);
- }
- writeBytes(buf, bytes);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
+void Buffer::keysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf) {
+ while (!checkSpace((2 + keyCount) * MAXSIZE_PACK32 + bytes)) {
+ sem_wait(&mWriterSem);
+ }
+ packInt(CODE_KEYS_OLD);
+ packInt(keyCount);
+ for (int i = 0; i < keyCount; ++i) {
+ packInt(keys[i]);
}
- check(1);
+ writeBytes(buf, bytes);
+ check(currTime);
}
-void Buffer::format(const int length, const char *const format) {
- if (checkSpace(MAXSIZE_PACK32 + length + 1)) {
- packInt(CODE_FORMAT);
- writeBytes(format, length + 1);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
+void Buffer::format(const uint64_t currTime, const int length, const char *const format) {
+ while (!checkSpace(MAXSIZE_PACK32 + length + 1)) {
+ sem_wait(&mWriterSem);
}
- check(1);
+ packInt(CODE_FORMAT);
+ writeBytes(format, length + 1);
+ check(currTime);
}
-void Buffer::maps(const int pid, const int tid, const char *const maps) {
+void Buffer::maps(const uint64_t currTime, const int pid, const int tid, const char *const maps) {
const int mapsLen = strlen(maps) + 1;
- if (checkSpace(3 * MAXSIZE_PACK32 + mapsLen)) {
- packInt(CODE_MAPS);
- packInt(pid);
- packInt(tid);
- writeBytes(maps, mapsLen);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
+ while (!checkSpace(3 * MAXSIZE_PACK32 + mapsLen)) {
+ sem_wait(&mWriterSem);
}
- check(1);
+ packInt(CODE_MAPS);
+ packInt(pid);
+ packInt(tid);
+ writeBytes(maps, mapsLen);
+ check(currTime);
}
-void Buffer::comm(const int pid, const int tid, const char *const image, const char *const comm) {
+void Buffer::comm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm) {
const int imageLen = strlen(image) + 1;
const int commLen = strlen(comm) + 1;
- if (checkSpace(3 * MAXSIZE_PACK32 + imageLen + commLen)) {
- packInt(CODE_COMM);
- packInt(pid);
- packInt(tid);
- writeBytes(image, imageLen);
- writeBytes(comm, commLen);
- } else {
- logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
- handleException();
+ while (!checkSpace(3 * MAXSIZE_PACK32 + imageLen + commLen)) {
+ sem_wait(&mWriterSem);
+ }
+ packInt(CODE_COMM);
+ packInt(pid);
+ packInt(tid);
+ writeBytes(image, imageLen);
+ writeBytes(comm, commLen);
+ check(currTime);
+}
+
+void Buffer::onlineCPU(const uint64_t currTime, const uint64_t time, const int cpu) {
+ while (!checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
+ sem_wait(&mWriterSem);
+ }
+ packInt(CODE_ONLINE_CPU);
+ packInt64(time);
+ packInt(cpu);
+ check(currTime);
+}
+
+void Buffer::offlineCPU(const uint64_t currTime, const uint64_t time, const int cpu) {
+ while (!checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
+ sem_wait(&mWriterSem);
+ }
+ packInt(CODE_OFFLINE_CPU);
+ packInt64(time);
+ packInt(cpu);
+ check(currTime);
+}
+
+void Buffer::kallsyms(const uint64_t currTime, const char *const kallsyms) {
+ const int kallsymsLen = strlen(kallsyms) + 1;
+ while (!checkSpace(3 * MAXSIZE_PACK32 + kallsymsLen)) {
+ sem_wait(&mWriterSem);
}
- check(1);
+ packInt(CODE_KALLSYMS);
+ writeBytes(kallsyms, kallsymsLen);
+ check(currTime);
}
void Buffer::setDone() {
diff --git a/tools/gator/daemon/Buffer.h b/tools/gator/daemon/Buffer.h
index 2de1b97ac091..6cffd8e39a36 100644
--- a/tools/gator/daemon/Buffer.h
+++ b/tools/gator/daemon/Buffer.h
@@ -39,25 +39,26 @@ public:
void commit(const uint64_t time);
void check(const uint64_t time);
- void frame();
-
// Summary messages
- void summary(const int64_t timestamp, const int64_t uptime, const int64_t monotonicDelta, const char *const uname);
- void coreName(const int core, const int cpuid, const char *const name);
+ void summary(const uint64_t currTime, const int64_t timestamp, const int64_t uptime, const int64_t monotonicDelta, const char *const uname);
+ void coreName(const uint64_t currTime, const int core, const int cpuid, const char *const name);
// Block Counter messages
bool eventHeader(uint64_t curr_time);
bool eventTid(int tid);
- void event(int32_t key, int32_t value);
- void event64(int64_t key, int64_t value);
+ void event(int key, int32_t value);
+ void event64(int key, int64_t value);
// Perf Attrs messages
- void pea(const struct perf_event_attr *const pea, int key);
- void keys(const int count, const __u64 *const ids, const int *const keys);
- void keysOld(const int keyCount, const int *const keys, const int bytes, const char *const buf);
- void format(const int length, const char *const format);
- void maps(const int pid, const int tid, const char *const maps);
- void comm(const int pid, const int tid, const char *const image, const char *const comm);
+ void pea(const uint64_t currTime, const struct perf_event_attr *const pea, int key);
+ void keys(const uint64_t currTime, const int count, const __u64 *const ids, const int *const keys);
+ void keysOld(const uint64_t currTime, const int keyCount, const int *const keys, const int bytes, const char *const buf);
+ void format(const uint64_t currTime, const int length, const char *const format);
+ void maps(const uint64_t currTime, const int pid, const int tid, const char *const maps);
+ void comm(const uint64_t currTime, const int pid, const int tid, const char *const image, const char *const comm);
+ void onlineCPU(const uint64_t currTime, const uint64_t time, const int cpu);
+ void offlineCPU(const uint64_t currTime, const uint64_t time, const int cpu);
+ void kallsyms(const uint64_t currTime, const char *const kallsyms);
void setDone();
bool isDone() const;
@@ -67,6 +68,7 @@ public:
void advanceWrite(int bytes) { mWritePos = (mWritePos + bytes) & /*mask*/(mSize - 1); }
static void packInt(char *const buf, const int size, int &writePos, int32_t x);
void packInt(int32_t x);
+ static void packInt64(char *const buf, const int size, int &writePos, int64_t x);
void packInt64(int64_t x);
void writeBytes(const void *const data, size_t count);
void writeString(const char *const str);
@@ -79,20 +81,22 @@ public:
}
private:
+ void frame();
bool commitReady() const;
bool checkSpace(int bytes);
- const int32_t mCore;
- const int32_t mBufType;
+ char *const mBuf;
+ sem_t *const mReaderSem;
+ uint64_t mCommitTime;
+ sem_t mWriterSem;
const int mSize;
int mReadPos;
int mWritePos;
int mCommitPos;
bool mAvailable;
bool mIsDone;
- char *const mBuf;
- uint64_t mCommitTime;
- sem_t *const mReaderSem;
+ const int32_t mCore;
+ const int32_t mBufType;
// Intentionally unimplemented
Buffer(const Buffer &);
diff --git a/tools/gator/daemon/CCNDriver.cpp b/tools/gator/daemon/CCNDriver.cpp
new file mode 100644
index 000000000000..dd1a2b133842
--- /dev/null
+++ b/tools/gator/daemon/CCNDriver.cpp
@@ -0,0 +1,295 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "CCNDriver.h"
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "k/perf_event.h"
+
+#include "Config.h"
+#include "DriverSource.h"
+#include "Logging.h"
+
+static const char TAG_CATEGORY[] = "category";
+static const char TAG_COUNTER_SET[] = "counter_set";
+static const char TAG_EVENT[] = "event";
+static const char TAG_OPTION[] = "option";
+static const char TAG_OPTION_SET[] = "option_set";
+
+static const char ATTR_AVERAGE_SELECTION[] = "average_selection";
+static const char ATTR_COUNTER[] = "counter";
+static const char ATTR_COUNTER_SET[] = "counter_set";
+static const char ATTR_COUNT[] = "count";
+static const char ATTR_DESCRIPTION[] = "description";
+static const char ATTR_DISPLAY[] = "display";
+static const char ATTR_EVENT[] = "event";
+static const char ATTR_EVENT_DELTA[] = "event_delta";
+static const char ATTR_NAME[] = "name";
+static const char ATTR_OPTION_SET[] = "option_set";
+static const char ATTR_TITLE[] = "title";
+static const char ATTR_UNITS[] = "units";
+
+static const char XP_REGION[] = "XP_Region";
+static const char HNF_REGION[] = "HN-F_Region";
+static const char RNI_REGION[] = "RN-I_Region";
+static const char SBAS_REGION[] = "SBAS_Region";
+static const char CCN_5XX[] = "CCN-5xx";
+#define ARM_CCN_5XX "ARM_CCN_5XX_"
+
+static const char *const VC_TYPES[] = { "REQ", "RSP", "SNP", "DAT" };
+static const char *const XP_EVENT_NAMES[] = { NULL, "H-bit", "S-bit", "P-Cnt", "TknV" };
+static const char *const XP_EVENT_DESCRIPTIONS[] = { NULL, "Set H-bit, signaled when this XP sets the H-bit.", "Set S-bit, signaled when this XP sets the S-bit.", "Set P-Cnt, signaled when this XP sets the P-Cnt. This is not applicable for the SNP VC.", "No TknV, signaled when this XP transmits a valid packet." };
+static const char *const HNF_EVENT_NAMES[] = { NULL, "Cache Miss", "L3 SF Cache Access", "Cache Fill", "POCQ Retry", "POCQ Reqs Recvd", "SF Hit", "SF Evictions", "Snoops Sent", "Snoops Broadcast", "L3 Eviction", "L3 Fill Invalid Way", "MC Retries", "MC Reqs", "QOS HH Retry" };
+static const char *const HNF_EVENT_DESCRIPTIONS[] = { NULL, "Counts the total cache misses. This is the first time lookup result, and is high priority.", "Counts the number of cache accesses. This is the first time access, and is high priority.", "Counts the total allocations in the HN L3 cache, and all cache line allocations to the L3 cache.", "Counts the number of requests that have been retried.", "Counts the number of requests received by HN.", "Counts the number of snoop filter hits.", "Counts the number of snoop filter evictions. Cache invalidations are initiated.", "Counts the number of snoops sent. Does not differentiate between broadcast or directed snoops.", "Counts the number of snoop broadcasts sent.", "Counts the number of L3 evictions.", "Counts the number of L3 fills to an invalid way.", "Counts the number of transactions retried by the memory controller.", "Counts the number of requests to the memory controller.", "Counts the number of times a highest-priority QoS class was retried at the HN-F." };
+static const char *const RNI_EVENT_NAMES[] = { NULL, "S0 RDataBeats", "S1 RDataBeats", "S2 RDataBeats", "RXDAT Flits received", "TXDAT Flits sent", "Total TXREQ Flits sent", "Retried TXREQ Flits sent", "RRT full", "WRT full", "Replayed TXREQ Flits" };
+static const char *const RNI_EVENT_DESCRIPTIONS[] = { NULL, "S0 RDataBeats.", "S1 RDataBeats.", "S2 RDataBeats.", "RXDAT Flits received.", "TXDAT Flits sent.", "Total TXREQ Flits sent.", "Retried TXREQ Flits sent.", "RRT full.", "WRT full.", "Replayed TXREQ Flits." };
+static const char *const SBAS_EVENT_NAMES[] = { NULL, "S0 RDataBeats", NULL, NULL, "RXDAT Flits received", "TXDAT Flits sent", "Total TXREQ Flits sent", "Retried TXREQ Flits sent", "RRT full", "WRT full", "Replayed TXREQ Flits" };
+static const char *const SBAS_EVENT_DESCRIPTIONS[] = { NULL, "S0 RDataBeats.", NULL, NULL, "RXDAT Flits received.", "TXDAT Flits sent.", "Total TXREQ Flits sent.", "Retried TXREQ Flits sent.", "RRT full.", "WRT full.", "Replayed TXREQ Flits." };
+
+// This class is used only to poll for CCN-5xx configuration and emit events XML for it. All other operations are handled by PerfDriver
+
+static int sys_perf_event_open(struct perf_event_attr *const attr, const pid_t pid, const int cpu, const int group_fd, const unsigned long flags) {
+ return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
+}
+
+static unsigned int getConfig(unsigned int node, unsigned int type, unsigned int event, unsigned int port, unsigned int vc) {
+ return
+ ((node & 0xff) << 0) |
+ ((type & 0xff) << 8) |
+ ((event & 0xff) << 16) |
+ ((port & 0x03) << 24) |
+ ((vc & 0x07) << 26) |
+ 0;
+}
+
+static bool perfPoll(struct perf_event_attr *const pea) {
+ int fd = sys_perf_event_open(pea, -1, 0, -1, 0);
+ if (fd < 0) {
+ return false;
+ }
+ close(fd);
+ return true;
+}
+
+CCNDriver::CCNDriver() : mNodeTypes(NULL), mXpCount(0) {
+}
+
+CCNDriver::~CCNDriver() {
+ delete mNodeTypes;
+}
+
+bool CCNDriver::claimCounter(const Counter &) const {
+ // Handled by PerfDriver
+ return false;
+}
+
+void CCNDriver::resetCounters() {
+ // Handled by PerfDriver
+}
+
+void CCNDriver::setupCounter(Counter &) {
+ // Handled by PerfDriver
+}
+
+void CCNDriver::readEvents(mxml_node_t *const) {
+ struct stat st;
+ if (stat("/sys/bus/event_source/devices/ccn", &st) != 0) {
+ // Not found
+ return;
+ }
+
+ int type;
+ if (DriverSource::readIntDriver("/sys/bus/event_source/devices/ccn/type", &type) != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to read CCN-5xx type");
+ handleException();
+ }
+
+ // Detect number of xps
+ struct perf_event_attr pea;
+ memset(&pea, 0, sizeof(pea));
+ pea.type = type;
+ pea.size = sizeof(pea);
+
+ mXpCount = 1;
+ while (true) {
+ pea.config = getConfig(0, 0x08, 1, 0, 1) | mXpCount;
+ if (!perfPoll(&pea)) {
+ break;
+ }
+ mXpCount *= 2;
+ };
+ {
+ int lower = mXpCount/2 + 1;
+ while (lower < mXpCount) {
+ int mid = (lower + mXpCount)/2;
+ pea.config = getConfig(0, 0x08, 1, 0, 1) | mid;
+ if (perfPoll(&pea)) {
+ lower = mid + 1;
+ } else {
+ mXpCount = mid;
+ }
+ }
+ }
+
+ mNodeTypes = new NodeType[2*mXpCount];
+
+ // Detect node types
+ for (int i = 0; i < 2*mXpCount; ++i) {
+ pea.config = getConfig(0, 0x04, 1, 0, 0) | i;
+ if (perfPoll(&pea)) {
+ mNodeTypes[i] = NT_HNF;
+ continue;
+ }
+
+ pea.config = getConfig(0, 0x16, 1, 0, 0) | i;
+ if (perfPoll(&pea)) {
+ mNodeTypes[i] = NT_RNI;
+ continue;
+ }
+
+ pea.config = getConfig(0, 0x10, 1, 0, 0) | i;
+ if (perfPoll(&pea)) {
+ mNodeTypes[i] = NT_SBAS;
+ continue;
+ }
+
+ mNodeTypes[i] = NT_UNKNOWN;
+ }
+}
+
+int CCNDriver::writeCounters(mxml_node_t *const) const {
+ // Handled by PerfDriver
+ return 0;
+}
+
+void CCNDriver::writeEvents(mxml_node_t *const root) const {
+ mxml_node_t *const counter_set = mxmlNewElement(root, TAG_COUNTER_SET);
+ mxmlElementSetAttr(counter_set, ATTR_NAME, ARM_CCN_5XX "cnt");
+ mxmlElementSetAttr(counter_set, ATTR_COUNT, "8");
+
+ mxml_node_t *const category = mxmlNewElement(root, TAG_CATEGORY);
+ mxmlElementSetAttr(category, ATTR_NAME, CCN_5XX);
+ mxmlElementSetAttr(category, TAG_COUNTER_SET, ARM_CCN_5XX "cnt");
+
+ mxml_node_t *const clock_event = mxmlNewElement(category, TAG_EVENT);
+ mxmlElementSetAttr(clock_event, ATTR_COUNTER, ARM_CCN_5XX "ccnt");
+ mxmlElementSetAttr(clock_event, ATTR_EVENT, "0xff00");
+ mxmlElementSetAttr(clock_event, ATTR_TITLE, "CCN-5xx Clock");
+ mxmlElementSetAttr(clock_event, ATTR_NAME, "Cycles");
+ mxmlElementSetAttr(clock_event, ATTR_DISPLAY, "hertz");
+ mxmlElementSetAttr(clock_event, ATTR_UNITS, "Hz");
+ mxmlElementSetAttr(clock_event, ATTR_AVERAGE_SELECTION, "yes");
+ mxmlElementSetAttr(clock_event, ATTR_DESCRIPTION, "The number of core clock cycles");
+
+ mxml_node_t *const xp_option_set = mxmlNewElement(category, TAG_OPTION_SET);
+ mxmlElementSetAttr(xp_option_set, ATTR_NAME, XP_REGION);
+
+ for (int i = 0; i < mXpCount; ++i) {
+ mxml_node_t *const option = mxmlNewElement(xp_option_set, TAG_OPTION);
+ mxmlElementSetAttrf(option, ATTR_EVENT_DELTA, "0x%x", getConfig(i, 0, 0, 0, 0));
+ mxmlElementSetAttrf(option, ATTR_NAME, "XP %i", i);
+ mxmlElementSetAttrf(option, ATTR_DESCRIPTION, "Crosspoint %i", i);
+ }
+
+ for (int vc = 0; vc < ARRAY_LENGTH(VC_TYPES); ++vc) {
+ if (VC_TYPES[vc] == NULL) {
+ continue;
+ }
+ for (int bus = 0; bus < 2; ++bus) {
+ for (int eventId = 0; eventId < ARRAY_LENGTH(XP_EVENT_NAMES); ++eventId) {
+ if (XP_EVENT_NAMES[eventId] == NULL) {
+ continue;
+ }
+ mxml_node_t *const event = mxmlNewElement(category, TAG_EVENT);
+ mxmlElementSetAttrf(event, ATTR_EVENT, "0x%x", getConfig(0, 0x08, eventId, bus, vc));
+ mxmlElementSetAttr(event, ATTR_OPTION_SET, XP_REGION);
+ mxmlElementSetAttr(event, ATTR_TITLE, CCN_5XX);
+ mxmlElementSetAttrf(event, ATTR_NAME, "Bus %i: %s: %s", bus, VC_TYPES[vc], XP_EVENT_NAMES[eventId]);
+ mxmlElementSetAttrf(event, ATTR_DESCRIPTION, "Bus %i: %s: %s", bus, VC_TYPES[vc], XP_EVENT_DESCRIPTIONS[eventId]);
+ }
+ }
+ }
+
+ mxml_node_t *const hnf_option_set = mxmlNewElement(category, TAG_OPTION_SET);
+ mxmlElementSetAttr(hnf_option_set, ATTR_NAME, HNF_REGION);
+
+ for (int eventId = 0; eventId < ARRAY_LENGTH(HNF_EVENT_NAMES); ++eventId) {
+ if (HNF_EVENT_NAMES[eventId] == NULL) {
+ continue;
+ }
+ mxml_node_t *const event = mxmlNewElement(category, TAG_EVENT);
+ mxmlElementSetAttrf(event, ATTR_EVENT, "0x%x", getConfig(0, 0x04, eventId, 0, 0));
+ mxmlElementSetAttr(event, ATTR_OPTION_SET, HNF_REGION);
+ mxmlElementSetAttr(event, ATTR_TITLE, CCN_5XX);
+ mxmlElementSetAttr(event, ATTR_NAME, HNF_EVENT_NAMES[eventId]);
+ mxmlElementSetAttr(event, ATTR_DESCRIPTION, HNF_EVENT_DESCRIPTIONS[eventId]);
+ }
+
+ mxml_node_t *const rni_option_set = mxmlNewElement(category, TAG_OPTION_SET);
+ mxmlElementSetAttr(rni_option_set, ATTR_NAME, RNI_REGION);
+
+ for (int eventId = 0; eventId < ARRAY_LENGTH(RNI_EVENT_NAMES); ++eventId) {
+ if (RNI_EVENT_NAMES[eventId] == NULL) {
+ continue;
+ }
+ mxml_node_t *const event = mxmlNewElement(category, TAG_EVENT);
+ mxmlElementSetAttrf(event, ATTR_EVENT, "0x%x", getConfig(0, 0x16, eventId, 0, 0));
+ mxmlElementSetAttr(event, ATTR_OPTION_SET, RNI_REGION);
+ mxmlElementSetAttr(event, ATTR_TITLE, CCN_5XX);
+ mxmlElementSetAttr(event, ATTR_NAME, RNI_EVENT_NAMES[eventId]);
+ mxmlElementSetAttr(event, ATTR_DESCRIPTION, RNI_EVENT_DESCRIPTIONS[eventId]);
+ }
+
+ mxml_node_t *const sbas_option_set = mxmlNewElement(category, TAG_OPTION_SET);
+ mxmlElementSetAttr(sbas_option_set, ATTR_NAME, SBAS_REGION);
+
+ for (int eventId = 0; eventId < ARRAY_LENGTH(SBAS_EVENT_NAMES); ++eventId) {
+ if (SBAS_EVENT_NAMES[eventId] == NULL) {
+ continue;
+ }
+ mxml_node_t *const event = mxmlNewElement(category, TAG_EVENT);
+ mxmlElementSetAttrf(event, ATTR_EVENT, "0x%x", getConfig(0, 0x10, eventId, 0, 0));
+ mxmlElementSetAttr(event, ATTR_OPTION_SET, SBAS_REGION);
+ mxmlElementSetAttr(event, ATTR_TITLE, CCN_5XX);
+ mxmlElementSetAttr(event, ATTR_NAME, SBAS_EVENT_NAMES[eventId]);
+ mxmlElementSetAttr(event, ATTR_DESCRIPTION, SBAS_EVENT_DESCRIPTIONS[eventId]);
+ }
+
+ for (int i = 0; i < 2*mXpCount; ++i) {
+ switch (mNodeTypes[i]) {
+ case NT_HNF: {
+ mxml_node_t *const option = mxmlNewElement(hnf_option_set, TAG_OPTION);
+ mxmlElementSetAttrf(option, ATTR_EVENT_DELTA, "0x%x", getConfig(i, 0, 0, 0, 0));
+ mxmlElementSetAttrf(option, ATTR_NAME, "HN-F %i", i);
+ mxmlElementSetAttrf(option, ATTR_DESCRIPTION, "Fully-coherent Home Node %i", i);
+ break;
+ }
+ case NT_RNI: {
+ mxml_node_t *const option = mxmlNewElement(rni_option_set, TAG_OPTION);
+ mxmlElementSetAttrf(option, ATTR_EVENT_DELTA, "0x%x", getConfig(i, 0, 0, 0, 0));
+ mxmlElementSetAttrf(option, ATTR_NAME, "RN-I %i", i);
+ mxmlElementSetAttrf(option, ATTR_DESCRIPTION, "I/O-coherent Requesting Node %i", i);
+ break;
+ }
+ case NT_SBAS: {
+ mxml_node_t *const option = mxmlNewElement(sbas_option_set, TAG_OPTION);
+ mxmlElementSetAttrf(option, ATTR_EVENT_DELTA, "0x%x", getConfig(i, 0, 0, 0, 0));
+ mxmlElementSetAttrf(option, ATTR_NAME, "SBAS %i", i);
+ mxmlElementSetAttrf(option, ATTR_DESCRIPTION, "ACE master to CHI protocol bridge %i", i);
+ break;
+ }
+ default:
+ continue;
+ }
+ }
+}
diff --git a/tools/gator/daemon/CCNDriver.h b/tools/gator/daemon/CCNDriver.h
new file mode 100644
index 000000000000..fb4c717e969a
--- /dev/null
+++ b/tools/gator/daemon/CCNDriver.h
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef CCNDRIVER_H
+#define CCNDRIVER_H
+
+#include "Driver.h"
+
+class CCNDriver : public Driver {
+public:
+ CCNDriver();
+ ~CCNDriver();
+
+ bool claimCounter(const Counter &counter) const;
+ void resetCounters();
+ void setupCounter(Counter &counter);
+
+ void readEvents(mxml_node_t *const);
+ int writeCounters(mxml_node_t *const root) const;
+ void writeEvents(mxml_node_t *const) const;
+
+private:
+ enum NodeType {
+ NT_UNKNOWN,
+ NT_HNF,
+ NT_RNI,
+ NT_SBAS,
+ };
+
+ NodeType *mNodeTypes;
+ int mXpCount;
+
+ // Intentionally unimplemented
+ CCNDriver(const CCNDriver &);
+ CCNDriver &operator=(const CCNDriver &);
+};
+
+#endif // CCNDRIVER_H
diff --git a/tools/gator/daemon/CPUFreqDriver.cpp b/tools/gator/daemon/CPUFreqDriver.cpp
new file mode 100644
index 000000000000..41f9d6f2b3f4
--- /dev/null
+++ b/tools/gator/daemon/CPUFreqDriver.cpp
@@ -0,0 +1,58 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "CPUFreqDriver.h"
+
+#include "Buffer.h"
+#include "DriverSource.h"
+#include "Logging.h"
+#include "SessionData.h"
+
+CPUFreqDriver::CPUFreqDriver() : mPrev() {
+}
+
+CPUFreqDriver::~CPUFreqDriver() {
+}
+
+void CPUFreqDriver::readEvents(mxml_node_t *const) {
+ // Only for use with perf
+ if (!gSessionData->perf.isSetup()) {
+ return;
+ }
+
+ setCounters(new DriverCounter(getCounters(), strdup("Linux_power_cpu_freq")));
+}
+
+void CPUFreqDriver::read(Buffer *const buffer) {
+ char buf[64];
+ const DriverCounter *const counter = getCounters();
+ if ((counter == NULL) || !counter->isEnabled()) {
+ return;
+ }
+
+ const int key = getCounters()->getKey();
+ bool resetCores = false;
+ for (int i = 0; i < gSessionData->mCores; ++i) {
+ snprintf(buf, sizeof(buf), "/sys/devices/system/cpu/cpu%i/cpufreq/cpuinfo_cur_freq", i);
+ int64_t freq;
+ if (DriverSource::readInt64Driver(buf, &freq) != 0) {
+ freq = 0;
+ }
+ if (mPrev[i] != freq) {
+ mPrev[i] = freq;
+ // Change cores
+ buffer->event64(2, i);
+ resetCores = true;
+ buffer->event64(key, 1000*freq);
+ }
+ }
+ if (resetCores) {
+ // Revert cores, UserSpaceSource is all on core 0
+ buffer->event64(2, 0);
+ }
+}
diff --git a/tools/gator/daemon/CPUFreqDriver.h b/tools/gator/daemon/CPUFreqDriver.h
new file mode 100644
index 000000000000..ad8c9aaa9e7d
--- /dev/null
+++ b/tools/gator/daemon/CPUFreqDriver.h
@@ -0,0 +1,34 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef CPUFREQDRIVER_H
+#define CPUFREQDRIVER_H
+
+#include "Config.h"
+#include "Driver.h"
+
+class CPUFreqDriver : public PolledDriver {
+private:
+ typedef PolledDriver super;
+
+public:
+ CPUFreqDriver();
+ ~CPUFreqDriver();
+
+ void readEvents(mxml_node_t *const root);
+ void read(Buffer *const buffer);
+
+private:
+ int64_t mPrev[NR_CPUS];
+
+ // Intentionally unimplemented
+ CPUFreqDriver(const CPUFreqDriver &);
+ CPUFreqDriver &operator=(const CPUFreqDriver &);
+};
+
+#endif // CPUFREQDRIVER_H
diff --git a/tools/gator/daemon/CapturedXML.cpp b/tools/gator/daemon/CapturedXML.cpp
index 4a11415a00c9..0b5802c893bb 100644
--- a/tools/gator/daemon/CapturedXML.cpp
+++ b/tools/gator/daemon/CapturedXML.cpp
@@ -34,6 +34,7 @@ mxml_node_t* CapturedXML::getTree(bool includeTime) {
mxmlElementSetAttr(captured, "version", "1");
if (gSessionData->perf.isSetup()) {
mxmlElementSetAttr(captured, "type", "Perf");
+ mxmlElementSetAttr(captured, "perf_beta", "yes");
}
mxmlElementSetAttrf(captured, "protocol", "%d", PROTOCOL_VERSION);
if (includeTime) { // Send the following only after the capture is complete
@@ -113,32 +114,32 @@ const char * mxmlWhitespaceCB(mxml_node_t *node, int loc) {
if (loc == MXML_WS_BEFORE_OPEN) {
// Single indentation
if (!strcmp(name, "target") || !strcmp(name, "counters"))
- return("\n ");
+ return "\n ";
// Double indentation
if (!strcmp(name, "counter"))
- return("\n ");
+ return "\n ";
// Avoid a carriage return on the first line of the xml file
if (!strncmp(name, "?xml", 4))
- return(NULL);
+ return NULL;
// Default - no indentation
- return("\n");
+ return "\n";
}
if (loc == MXML_WS_BEFORE_CLOSE) {
// No indentation
if (!strcmp(name, "captured"))
- return("\n");
+ return "\n";
// Single indentation
if (!strcmp(name, "counters"))
- return("\n ");
+ return "\n ";
// Default - no carriage return
- return(NULL);
+ return NULL;
}
- return(NULL);
+ return NULL;
}
diff --git a/tools/gator/daemon/CapturedXML.h b/tools/gator/daemon/CapturedXML.h
index ed08c44bc3ff..b704f6e53bb5 100644
--- a/tools/gator/daemon/CapturedXML.h
+++ b/tools/gator/daemon/CapturedXML.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __CAPTURED_XML_H__
-#define __CAPTURED_XML_H__
+#ifndef __CAPTURED_XML_H__
+#define __CAPTURED_XML_H__
#include "mxml/mxml.h"
diff --git a/tools/gator/daemon/Child.cpp b/tools/gator/daemon/Child.cpp
index 1901ecc6a724..6b5bbb3bf6af 100644
--- a/tools/gator/daemon/Child.cpp
+++ b/tools/gator/daemon/Child.cpp
@@ -14,25 +14,28 @@
#include <unistd.h>
#include <sys/prctl.h>
-#include "Logging.h"
#include "CapturedXML.h"
-#include "SessionData.h"
-#include "LocalCapture.h"
-#include "Sender.h"
-#include "OlyUtility.h"
-#include "OlySocket.h"
-#include "StreamlineSetup.h"
+#include "Command.h"
#include "ConfigurationXML.h"
#include "Driver.h"
-#include "PerfSource.h"
#include "DriverSource.h"
#include "ExternalSource.h"
+#include "FtraceSource.h"
+#include "LocalCapture.h"
+#include "Logging.h"
+#include "OlySocket.h"
+#include "OlyUtility.h"
+#include "PerfSource.h"
+#include "Sender.h"
+#include "SessionData.h"
+#include "StreamlineSetup.h"
#include "UserSpaceSource.h"
static sem_t haltPipeline, senderThreadStarted, startProfile, senderSem; // Shared by Child and spawned threads
static Source *primarySource = NULL;
static Source *externalSource = NULL;
static Source *userSpaceSource = NULL;
+static Source *ftraceSource = NULL;
static Sender* sender = NULL; // Shared by Child.cpp and spawned threads
Child* child = NULL; // shared by Child.cpp and main.cpp
@@ -149,7 +152,8 @@ static void *senderThread(void *) {
while (!primarySource->isDone() ||
!externalSource->isDone() ||
- (userSpaceSource != NULL && !userSpaceSource->isDone())) {
+ (userSpaceSource != NULL && !userSpaceSource->isDone()) ||
+ (ftraceSource != NULL && !ftraceSource->isDone())) {
sem_wait(&senderSem);
primarySource->write(sender);
@@ -157,6 +161,9 @@ static void *senderThread(void *) {
if (userSpaceSource != NULL) {
userSpaceSource->write(sender);
}
+ if (ftraceSource != NULL) {
+ ftraceSource->write(sender);
+ }
}
// write end-of-capture sequence
@@ -206,6 +213,9 @@ void Child::endSession() {
if (userSpaceSource != NULL) {
userSpaceSource->interrupt();
}
+ if (ftraceSource != NULL) {
+ ftraceSource->interrupt();
+ }
sem_post(&haltPipeline);
}
@@ -269,15 +279,32 @@ void Child::run() {
free(xmlString);
}
+ if (gSessionData->kmod.isMaliCapture() && (gSessionData->mSampleRate == 0)) {
+ logg->logError(__FILE__, __LINE__, "Mali counters are not supported with Sample Rate: None.");
+ handleException();
+ }
+
// Must be after session XML is parsed
if (!primarySource->prepare()) {
- logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
+ if (gSessionData->perf.isSetup()) {
+ logg->logError(__FILE__, __LINE__, "Unable to prepare gator driver for capture");
+ } else {
+ logg->logError(__FILE__, __LINE__, "Unable to communicate with the perf API, please ensure that CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER are enabled. Please refer to README_Streamline.txt for more information.");
+ }
handleException();
}
// Sender thread shall be halted until it is signaled for one shot mode
sem_init(&haltPipeline, 0, gSessionData->mOneShot ? 0 : 2);
+ // Must be initialized before senderThread is started as senderThread checks externalSource
+ externalSource = new ExternalSource(&senderSem);
+ if (!externalSource->prepare()) {
+ logg->logError(__FILE__, __LINE__, "Unable to prepare external source for capture");
+ handleException();
+ }
+ externalSource->start();
+
// Create the duration, stop, and sender threads
bool thread_creation_success = true;
if (gSessionData->mDuration > 0 && pthread_create(&durationThreadID, NULL, durationThread, NULL)) {
@@ -288,22 +315,37 @@ void Child::run() {
thread_creation_success = false;
}
- externalSource = new ExternalSource(&senderSem);
- if (!externalSource->prepare()) {
- logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
- handleException();
+ bool startUSSource = false;
+ for (int i = 0; i < ARRAY_LENGTH(gSessionData->usDrivers); ++i) {
+ if (gSessionData->usDrivers[i]->countersEnabled()) {
+ startUSSource = true;
+ }
}
- externalSource->start();
-
- if (gSessionData->hwmon.countersEnabled() || gSessionData->fsDriver.countersEnabled()) {
+ if (startUSSource) {
userSpaceSource = new UserSpaceSource(&senderSem);
if (!userSpaceSource->prepare()) {
- logg->logError(__FILE__, __LINE__, "Unable to prepare for capture");
+ logg->logError(__FILE__, __LINE__, "Unable to prepare userspace source for capture");
handleException();
}
userSpaceSource->start();
}
+ if (gSessionData->ftraceDriver.countersEnabled()) {
+ ftraceSource = new FtraceSource(&senderSem);
+ if (!ftraceSource->prepare()) {
+ logg->logError(__FILE__, __LINE__, "Unable to prepare userspace source for capture");
+ handleException();
+ }
+ ftraceSource->start();
+ }
+
+ if (gSessionData->mAllowCommands && (gSessionData->mCaptureCommand != NULL)) {
+ pthread_t thread;
+ if (pthread_create(&thread, NULL, commandThread, NULL)) {
+ thread_creation_success = false;
+ }
+ }
+
if (!thread_creation_success) {
logg->logError(__FILE__, __LINE__, "Failed to create gator threads");
handleException();
@@ -315,6 +357,9 @@ void Child::run() {
// Start profiling
primarySource->run();
+ if (ftraceSource != NULL) {
+ ftraceSource->join();
+ }
if (userSpaceSource != NULL) {
userSpaceSource->join();
}
@@ -338,6 +383,7 @@ void Child::run() {
logg->logMessage("Profiling ended.");
+ delete ftraceSource;
delete userSpaceSource;
delete externalSource;
delete primarySource;
diff --git a/tools/gator/daemon/Child.h b/tools/gator/daemon/Child.h
index a306a7760819..cc78202ceb5c 100644
--- a/tools/gator/daemon/Child.h
+++ b/tools/gator/daemon/Child.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __CHILD_H__
-#define __CHILD_H__
+#ifndef __CHILD_H__
+#define __CHILD_H__
class OlySocket;
diff --git a/tools/gator/daemon/Command.cpp b/tools/gator/daemon/Command.cpp
new file mode 100644
index 000000000000..28d73cf5a905
--- /dev/null
+++ b/tools/gator/daemon/Command.cpp
@@ -0,0 +1,172 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "Command.h"
+
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "Logging.h"
+#include "SessionData.h"
+
+static int getUid(const char *const name, char *const shPath, const char *const tmpDir) {
+ // Lookups may fail when using a different libc or a statically compiled executable
+ char gatorTemp[32];
+ snprintf(gatorTemp, sizeof(gatorTemp), "%s/gator_temp", tmpDir);
+
+ const int fd = open(gatorTemp, 600, O_CREAT | O_CLOEXEC);
+ if (fd < 0) {
+ return -1;
+ }
+ close(fd);
+
+ char cmd[128];
+ snprintf(cmd, sizeof(cmd), "chown %s %s || rm %s", name, gatorTemp, gatorTemp);
+
+ const int pid = fork();
+ if (pid < 0) {
+ logg->logError(__FILE__, __LINE__, "fork failed");
+ handleException();
+ }
+ if (pid == 0) {
+ char cargv1[] = "-c";
+ char *cargv[] = {
+ shPath,
+ cargv1,
+ cmd,
+ NULL,
+ };
+
+ execv(cargv[0], cargv);
+ exit(-1);
+ }
+ while ((waitpid(pid, NULL, 0) < 0) && (errno == EINTR));
+
+ struct stat st;
+ int result = -1;
+ if (stat(gatorTemp, &st) == 0) {
+ result = st.st_uid;
+ }
+ unlink(gatorTemp);
+ return result;
+}
+
+static int getUid(const char *const name) {
+ // Look up the username
+ struct passwd *const user = getpwnam(name);
+ if (user != NULL) {
+ return user->pw_uid;
+ }
+
+
+ // Are we on Linux
+ char cargv0l[] = "/bin/sh";
+ if ((access(cargv0l, X_OK) == 0) && (access("/tmp", W_OK) == 0)) {
+ return getUid(name, cargv0l, "/tmp");
+ }
+
+ // Are we on android
+ char cargv0a[] = "/system/bin/sh";
+ if ((access(cargv0a, X_OK) == 0) && (access("/data", W_OK) == 0)) {
+ return getUid(name, cargv0a, "/data");
+ }
+
+ return -1;
+}
+
+void *commandThread(void *) {
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-command", 0, 0, 0);
+
+ const char *const name = gSessionData->mCaptureUser == NULL ? "nobody" : gSessionData->mCaptureUser;
+ const int uid = getUid(name);
+ if (uid < 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to lookup the user %s, please double check that the user exists", name);
+ handleException();
+ }
+
+ sleep(3);
+
+ char buf[128];
+ int pipefd[2];
+ if (pipe_cloexec(pipefd) != 0) {
+ logg->logError(__FILE__, __LINE__, "pipe failed");
+ handleException();
+ }
+
+ const int pid = fork();
+ if (pid < 0) {
+ logg->logError(__FILE__, __LINE__, "fork failed");
+ handleException();
+ }
+ if (pid == 0) {
+ char cargv0l[] = "/bin/sh";
+ char cargv0a[] = "/system/bin/sh";
+ char cargv1[] = "-c";
+ char *cargv[] = {
+ cargv0l,
+ cargv1,
+ gSessionData->mCaptureCommand,
+ NULL,
+ };
+
+ buf[0] = '\0';
+ close(pipefd[0]);
+
+ // Gator runs at a high priority, reset the priority to the default
+ if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), 0) == -1) {
+ snprintf(buf, sizeof(buf), "setpriority failed");
+ goto fail_exit;
+ }
+
+ if (setuid(uid) != 0) {
+ snprintf(buf, sizeof(buf), "setuid failed");
+ goto fail_exit;
+ }
+
+ {
+ const char *const path = gSessionData->mCaptureWorkingDir == NULL ? "/" : gSessionData->mCaptureWorkingDir;
+ if (chdir(path) != 0) {
+ snprintf(buf, sizeof(buf), "Unable to cd to %s, please verify the directory exists and is accessable to %s", path, name);
+ goto fail_exit;
+ }
+ }
+
+ execv(cargv[0], cargv);
+ cargv[0] = cargv0a;
+ execv(cargv[0], cargv);
+ snprintf(buf, sizeof(buf), "execv failed");
+
+ fail_exit:
+ if (buf[0] != '\0') {
+ const ssize_t bytes = write(pipefd[1], buf, sizeof(buf));
+ // Can't do anything if this fails
+ (void)bytes;
+ }
+
+ exit(-1);
+ }
+
+ close(pipefd[1]);
+ const ssize_t bytes = read(pipefd[0], buf, sizeof(buf));
+ if (bytes > 0) {
+ logg->logError(__FILE__, __LINE__, buf);
+ handleException();
+ }
+ close(pipefd[0]);
+
+ return NULL;
+}
diff --git a/tools/gator/daemon/Command.h b/tools/gator/daemon/Command.h
new file mode 100644
index 000000000000..17244b7aaebc
--- /dev/null
+++ b/tools/gator/daemon/Command.h
@@ -0,0 +1,14 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef COMMAND_H
+#define COMMAND_H
+
+void *commandThread(void *);
+
+#endif // COMMAND_H
diff --git a/tools/gator/daemon/Config.h b/tools/gator/daemon/Config.h
index 6f5e2aae50e1..bee383a1c797 100644
--- a/tools/gator/daemon/Config.h
+++ b/tools/gator/daemon/Config.h
@@ -10,8 +10,19 @@
#define CONFIG_H
#define ARRAY_LENGTH(A) static_cast<int>(sizeof(A)/sizeof((A)[0]))
+#define ACCESS_ONCE(x) (*(volatile typeof(x)*)&(x))
#define MAX_PERFORMANCE_COUNTERS 50
-#define NR_CPUS 16
+#define NR_CPUS 32
+
+template<typename T>
+static inline T min(const T a, const T b) {
+ return (a < b ? a : b);
+}
+
+template<typename T>
+static inline T max(const T a, const T b) {
+ return (a > b ? a : b);
+}
#endif // CONFIG_H
diff --git a/tools/gator/daemon/DiskIODriver.cpp b/tools/gator/daemon/DiskIODriver.cpp
new file mode 100644
index 000000000000..5deb0f375f3a
--- /dev/null
+++ b/tools/gator/daemon/DiskIODriver.cpp
@@ -0,0 +1,125 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+// Define to get format macros from inttypes.h
+#define __STDC_FORMAT_MACROS
+
+#include "DiskIODriver.h"
+
+#include <inttypes.h>
+
+#include "Logging.h"
+#include "SessionData.h"
+
+class DiskIOCounter : public DriverCounter {
+public:
+ DiskIOCounter(DriverCounter *next, char *const name, int64_t *const value);
+ ~DiskIOCounter();
+
+ int64_t read();
+
+private:
+ int64_t *const mValue;
+ int64_t mPrev;
+
+ // Intentionally unimplemented
+ DiskIOCounter(const DiskIOCounter &);
+ DiskIOCounter &operator=(const DiskIOCounter &);
+};
+
+DiskIOCounter::DiskIOCounter(DriverCounter *next, char *const name, int64_t *const value) : DriverCounter(next, name), mValue(value), mPrev(0) {
+}
+
+DiskIOCounter::~DiskIOCounter() {
+}
+
+int64_t DiskIOCounter::read() {
+ int64_t result = *mValue - mPrev;
+ mPrev = *mValue;
+ // Kernel assumes a sector is 512 bytes
+ return result << 9;
+}
+
+DiskIODriver::DiskIODriver() : mBuf(), mReadBytes(0), mWriteBytes(0) {
+}
+
+DiskIODriver::~DiskIODriver() {
+}
+
+void DiskIODriver::readEvents(mxml_node_t *const) {
+ // Only for use with perf
+ if (!gSessionData->perf.isSetup()) {
+ return;
+ }
+
+ setCounters(new DiskIOCounter(getCounters(), strdup("Linux_block_rq_rd"), &mReadBytes));
+ setCounters(new DiskIOCounter(getCounters(), strdup("Linux_block_rq_wr"), &mWriteBytes));
+}
+
+void DiskIODriver::doRead() {
+ if (!countersEnabled()) {
+ return;
+ }
+
+ if (!mBuf.read("/proc/diskstats")) {
+ logg->logError(__FILE__, __LINE__, "Unable to read /proc/diskstats");
+ handleException();
+ }
+
+ mReadBytes = 0;
+ mWriteBytes = 0;
+
+ char *lastName = NULL;
+ int lastNameLen = -1;
+ char *start = mBuf.getBuf();
+ while (*start != '\0') {
+ char *end = strchr(start, '\n');
+ if (end != NULL) {
+ *end = '\0';
+ }
+
+ int nameStart = -1;
+ int nameEnd = -1;
+ int64_t readBytes = -1;
+ int64_t writeBytes = -1;
+ const int count = sscanf(start, "%*d %*d %n%*s%n %*u %*u %" SCNu64 " %*u %*u %*u %" SCNu64, &nameStart, &nameEnd, &readBytes, &writeBytes);
+ if (count != 2) {
+ logg->logError(__FILE__, __LINE__, "Unable to parse /proc/diskstats");
+ handleException();
+ }
+
+ // Skip partitions which are identified if the name is a substring of the last non-partition
+ if ((lastName == NULL) || (strncmp(lastName, start + nameStart, lastNameLen) != 0)) {
+ lastName = start + nameStart;
+ lastNameLen = nameEnd - nameStart;
+ mReadBytes += readBytes;
+ mWriteBytes += writeBytes;
+ }
+
+ if (end == NULL) {
+ break;
+ }
+ start = end + 1;
+ }
+}
+
+void DiskIODriver::start() {
+ doRead();
+ // Initialize previous values
+ for (DriverCounter *counter = getCounters(); counter != NULL; counter = counter->getNext()) {
+ if (!counter->isEnabled()) {
+ continue;
+ }
+ counter->read();
+ }
+}
+
+void DiskIODriver::read(Buffer *const buffer) {
+ doRead();
+ super::read(buffer);
+}
diff --git a/tools/gator/daemon/DiskIODriver.h b/tools/gator/daemon/DiskIODriver.h
new file mode 100644
index 000000000000..d0db18c77d04
--- /dev/null
+++ b/tools/gator/daemon/DiskIODriver.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef DISKIODRIVER_H
+#define DISKIODRIVER_H
+
+#include "Driver.h"
+#include "DynBuf.h"
+
+class DiskIODriver : public PolledDriver {
+private:
+ typedef PolledDriver super;
+
+public:
+ DiskIODriver();
+ ~DiskIODriver();
+
+ void readEvents(mxml_node_t *const root);
+ void start();
+ void read(Buffer *const buffer);
+
+private:
+ void doRead();
+
+ DynBuf mBuf;
+ int64_t mReadBytes;
+ int64_t mWriteBytes;
+
+ // Intentionally unimplemented
+ DiskIODriver(const DiskIODriver &);
+ DiskIODriver &operator=(const DiskIODriver &);
+};
+
+#endif // DISKIODRIVER_H
diff --git a/tools/gator/daemon/Driver.cpp b/tools/gator/daemon/Driver.cpp
index 09e040162912..275da31c7a0d 100644
--- a/tools/gator/daemon/Driver.cpp
+++ b/tools/gator/daemon/Driver.cpp
@@ -8,8 +8,89 @@
#include "Driver.h"
+#include "Buffer.h"
+#include "SessionData.h"
+
+DriverCounter::DriverCounter(DriverCounter *const next, const char *const name) : mNext(next), mName(name), mKey(getEventKey()), mEnabled(false) {
+}
+
+DriverCounter::~DriverCounter() {
+ delete mName;
+}
+
Driver *Driver::head = NULL;
Driver::Driver() : next(head) {
head = this;
}
+
+SimpleDriver::~SimpleDriver() {
+ DriverCounter *counters = mCounters;
+ while (counters != NULL) {
+ DriverCounter *counter = counters;
+ counters = counter->getNext();
+ delete counter;
+ }
+}
+
+DriverCounter *SimpleDriver::findCounter(const Counter &counter) const {
+ for (DriverCounter *driverCounter = mCounters; driverCounter != NULL; driverCounter = driverCounter->getNext()) {
+ if (strcmp(driverCounter->getName(), counter.getType()) == 0) {
+ return driverCounter;
+ }
+ }
+
+ return NULL;
+}
+
+bool SimpleDriver::claimCounter(const Counter &counter) const {
+ return findCounter(counter) != NULL;
+}
+
+bool SimpleDriver::countersEnabled() const {
+ for (DriverCounter *counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ if (counter->isEnabled()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void SimpleDriver::resetCounters() {
+ for (DriverCounter *counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ counter->setEnabled(false);
+ }
+}
+
+void SimpleDriver::setupCounter(Counter &counter) {
+ DriverCounter *const driverCounter = findCounter(counter);
+ if (driverCounter == NULL) {
+ counter.setEnabled(false);
+ return;
+ }
+ driverCounter->setEnabled(true);
+ counter.setKey(driverCounter->getKey());
+}
+
+int SimpleDriver::writeCounters(mxml_node_t *root) const {
+ int count = 0;
+ for (DriverCounter *counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ mxml_node_t *node = mxmlNewElement(root, "counter");
+ mxmlElementSetAttr(node, "name", counter->getName());
+ ++count;
+ }
+
+ return count;
+}
+
+PolledDriver::~PolledDriver() {
+}
+
+void PolledDriver::read(Buffer *const buffer) {
+ for (DriverCounter *counter = getCounters(); counter != NULL; counter = counter->getNext()) {
+ if (!counter->isEnabled()) {
+ continue;
+ }
+ buffer->event64(counter->getKey(), counter->read());
+ }
+}
diff --git a/tools/gator/daemon/Driver.h b/tools/gator/daemon/Driver.h
index e5ed7b6c1295..72870e3dbca1 100644
--- a/tools/gator/daemon/Driver.h
+++ b/tools/gator/daemon/Driver.h
@@ -9,10 +9,36 @@
#ifndef DRIVER_H
#define DRIVER_H
+#include <stdint.h>
+
#include "mxml/mxml.h"
+class Buffer;
class Counter;
+class DriverCounter {
+public:
+ DriverCounter(DriverCounter *const next, const char *const name);
+ virtual ~DriverCounter();
+
+ DriverCounter *getNext() const { return mNext; }
+ const char *getName() const { return mName; }
+ int getKey() const { return mKey; }
+ bool isEnabled() const { return mEnabled; }
+ void setEnabled(const bool enabled) { mEnabled = enabled; }
+ virtual int64_t read() { return -1; }
+
+private:
+ DriverCounter *const mNext;
+ const char *const mName;
+ const int mKey;
+ bool mEnabled;
+
+ // Intentionally unimplemented
+ DriverCounter(const DriverCounter &);
+ DriverCounter &operator=(const DriverCounter &);
+};
+
class Driver {
public:
static Driver *getHead() { return head; }
@@ -26,15 +52,17 @@ public:
// Enables and prepares the counter for capture
virtual void setupCounter(Counter &counter) = 0;
+ // Performs any actions needed for setup or based on eventsXML
+ virtual void readEvents(mxml_node_t *const) {}
// Emits available counters
- virtual int writeCounters(mxml_node_t *root) const = 0;
+ virtual int writeCounters(mxml_node_t *const root) const = 0;
// Emits possible dynamically generated events/counters
- virtual void writeEvents(mxml_node_t *) const {}
+ virtual void writeEvents(mxml_node_t *const) const {}
Driver *getNext() const { return next; }
protected:
- Driver ();
+ Driver();
private:
static Driver *head;
@@ -45,4 +73,46 @@ private:
Driver &operator=(const Driver &);
};
+class SimpleDriver : public Driver {
+public:
+ virtual ~SimpleDriver();
+
+ bool claimCounter(const Counter &counter) const;
+ bool countersEnabled() const;
+ void resetCounters();
+ void setupCounter(Counter &counter);
+ int writeCounters(mxml_node_t *root) const;
+
+protected:
+ SimpleDriver() : mCounters(NULL) {}
+
+ DriverCounter *getCounters() const { return mCounters; }
+ void setCounters(DriverCounter *const counter) { mCounters = counter; }
+
+ DriverCounter *findCounter(const Counter &counter) const;
+
+private:
+ DriverCounter *mCounters;
+
+ // Intentionally unimplemented
+ SimpleDriver(const SimpleDriver &);
+ SimpleDriver &operator=(const SimpleDriver &);
+};
+
+class PolledDriver : public SimpleDriver {
+public:
+ virtual ~PolledDriver();
+
+ virtual void start() {}
+ virtual void read(Buffer *const buffer);
+
+protected:
+ PolledDriver() {}
+
+private:
+ // Intentionally unimplemented
+ PolledDriver(const PolledDriver &);
+ PolledDriver &operator=(const PolledDriver &);
+};
+
#endif // DRIVER_H
diff --git a/tools/gator/daemon/DriverSource.cpp b/tools/gator/daemon/DriverSource.cpp
index 11d3095ef6d2..7f299b646952 100644
--- a/tools/gator/daemon/DriverSource.cpp
+++ b/tools/gator/daemon/DriverSource.cpp
@@ -6,6 +6,7 @@
* published by the Free Software Foundation.
*/
+// Define to get format macros from inttypes.h
#define __STDC_FORMAT_MACROS
#include "DriverSource.h"
@@ -93,19 +94,19 @@ bool DriverSource::prepare() {
}
void DriverSource::bootstrapThread() {
- prctl(PR_SET_NAME, (unsigned long)&"gatord-bootstrap", 0, 0, 0);
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-proc", 0, 0, 0);
DynBuf printb;
DynBuf b1;
DynBuf b2;
- DynBuf b3;
+ const uint64_t currTime = getTime();
- if (!readProc(mBuffer, false, &printb, &b1, &b2, &b3)) {
- logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__);
+ if (!readProcComms(currTime, mBuffer, &printb, &b1, &b2)) {
+ logg->logError(__FILE__, __LINE__, "readProcComms failed");
handleException();
}
- mBuffer->commit(1);
+ mBuffer->commit(currTime);
mBuffer->setDone();
}
@@ -128,7 +129,7 @@ void DriverSource::run() {
}
// open the buffer which calls userspace_buffer_open() in the driver
- mBufferFD = open("/dev/gator/buffer", O_RDONLY);
+ mBufferFD = open("/dev/gator/buffer", O_RDONLY | O_CLOEXEC);
if (mBufferFD < 0) {
logg->logError(__FILE__, __LINE__, "The gator driver did not set up properly. Please view the linux console or dmesg log for more information on the failure.");
handleException();
@@ -232,7 +233,7 @@ void DriverSource::write(Sender *sender) {
int DriverSource::readIntDriver(const char *fullpath, int *value) {
char data[40]; // Sufficiently large to hold any integer
- const int fd = open(fullpath, O_RDONLY);
+ const int fd = open(fullpath, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
return -1;
}
@@ -257,7 +258,7 @@ int DriverSource::readIntDriver(const char *fullpath, int *value) {
int DriverSource::readInt64Driver(const char *fullpath, int64_t *value) {
char data[40]; // Sufficiently large to hold any integer
- const int fd = open(fullpath, O_RDONLY);
+ const int fd = open(fullpath, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
return -1;
}
@@ -281,7 +282,7 @@ int DriverSource::readInt64Driver(const char *fullpath, int64_t *value) {
}
int DriverSource::writeDriver(const char *fullpath, const char *data) {
- int fd = open(fullpath, O_WRONLY);
+ int fd = open(fullpath, O_WRONLY | O_CLOEXEC);
if (fd < 0) {
return -1;
}
diff --git a/tools/gator/daemon/DynBuf.cpp b/tools/gator/daemon/DynBuf.cpp
index 6f92b336ae19..df20713ad63c 100644
--- a/tools/gator/daemon/DynBuf.cpp
+++ b/tools/gator/daemon/DynBuf.cpp
@@ -40,7 +40,7 @@ int DynBuf::resize(const size_t minCapacity) {
bool DynBuf::read(const char *const path) {
int result = false;
- const int fd = open(path, O_RDONLY);
+ const int fd = open(path, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
logg->logMessage("%s(%s:%i): open failed", __FUNCTION__, __FILE__, __LINE__);
return false;
diff --git a/tools/gator/daemon/EventsXML.cpp b/tools/gator/daemon/EventsXML.cpp
index cf0192ef671f..d905bbabe988 100644
--- a/tools/gator/daemon/EventsXML.cpp
+++ b/tools/gator/daemon/EventsXML.cpp
@@ -47,7 +47,7 @@ char *EventsXML::getXML() {
// Add dynamic events from the drivers
mxml_node_t *events = mxmlFindElement(xml, xml, "events", NULL, NULL, MXML_DESCEND);
if (!events) {
- logg->logMessage("Unable to find <events> node in the events.xml");
+ logg->logError(__FILE__, __LINE__, "Unable to find <events> node in the events.xml");
handleException();
}
for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
diff --git a/tools/gator/daemon/ExternalSource.cpp b/tools/gator/daemon/ExternalSource.cpp
index b6ec301d0c08..8f5e6b684c53 100644
--- a/tools/gator/daemon/ExternalSource.cpp
+++ b/tools/gator/daemon/ExternalSource.cpp
@@ -19,6 +19,9 @@
static const char MALI_VIDEO[] = "\0mali-video";
static const char MALI_VIDEO_STARTUP[] = "\0mali-video-startup";
static const char MALI_VIDEO_V1[] = "MALI_VIDEO 1\n";
+static const char MALI_GRAPHICS[] = "\0mali_thirdparty_server";
+static const char MALI_GRAPHICS_STARTUP[] = "\0mali_thirdparty_client";
+static const char MALI_GRAPHICS_V1[] = "MALI_GRAPHICS 1\n";
static bool setNonblock(const int fd) {
int flags;
@@ -37,16 +40,15 @@ static bool setNonblock(const int fd) {
return true;
}
-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) {
+ExternalSource::ExternalSource(sem_t *senderSem) : mBuffer(0, FRAME_EXTERNAL, 128*1024, senderSem), mMonitor(), mMveStartupUds(MALI_VIDEO_STARTUP, sizeof(MALI_VIDEO_STARTUP)), mMaliStartupUds(MALI_GRAPHICS_STARTUP, sizeof(MALI_GRAPHICS_STARTUP)), mAnnotate(8083), mInterruptFd(-1), mMaliUds(-1), mMveUds(-1) {
sem_init(&mBufferSem, 0, 0);
}
ExternalSource::~ExternalSource() {
}
-void ExternalSource::waitFor(const uint64_t currTime, const int bytes) {
+void ExternalSource::waitFor(const int bytes) {
while (mBuffer.bytesAvailable() <= bytes) {
- mBuffer.check(currTime);
sem_wait(&mBufferSem);
}
}
@@ -63,11 +65,21 @@ void ExternalSource::configureConnection(const int fd, const char *const handsha
}
// Write the handshake to the circular buffer
- waitFor(1, Buffer::MAXSIZE_PACK32 + 4 + size - 1);
+ waitFor(Buffer::MAXSIZE_PACK32 + size - 1);
mBuffer.packInt(fd);
- mBuffer.writeLEInt((unsigned char *)mBuffer.getWritePos(), size - 1);
- mBuffer.advanceWrite(4);
mBuffer.writeBytes(handshake, size - 1);
+ mBuffer.commit(1);
+}
+
+bool ExternalSource::connectMali() {
+ mMaliUds = OlySocket::connect(MALI_GRAPHICS, sizeof(MALI_GRAPHICS));
+ if (mMaliUds < 0) {
+ return false;
+ }
+
+ configureConnection(mMaliUds, MALI_GRAPHICS_V1, sizeof(MALI_GRAPHICS_V1));
+
+ return true;
}
bool ExternalSource::connectMve() {
@@ -90,10 +102,15 @@ bool ExternalSource::connectMve() {
}
bool ExternalSource::prepare() {
- if (!mMonitor.init() || !setNonblock(mMveStartupUds.getFd()) || !mMonitor.add(mMveStartupUds.getFd())) {
+ if (!mMonitor.init() ||
+ !setNonblock(mMveStartupUds.getFd()) || !mMonitor.add(mMveStartupUds.getFd()) ||
+ !setNonblock(mMaliStartupUds.getFd()) || !mMonitor.add(mMaliStartupUds.getFd()) ||
+ !setNonblock(mAnnotate.getFd()) || !mMonitor.add(mAnnotate.getFd()) ||
+ false) {
return false;
}
+ connectMali();
connectMve();
return true;
@@ -104,7 +121,7 @@ void ExternalSource::run() {
prctl(PR_SET_NAME, (unsigned long)&"gatord-external", 0, 0, 0);
- if (pipe(pipefd) != 0) {
+ if (pipe_cloexec(pipefd) != 0) {
logg->logError(__FILE__, __LINE__, "pipe failed");
handleException();
}
@@ -115,6 +132,9 @@ void ExternalSource::run() {
handleException();
}
+ // Notify annotate clients to retry connecting to gatord
+ gSessionData->annotateListener.signal();
+
while (gSessionData->mSessionIsActive) {
struct epoll_event events[16];
// Clear any pending sem posts
@@ -138,36 +158,60 @@ void ExternalSource::run() {
logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali video connection");
handleException();
}
+ } else if (fd == mMaliStartupUds.getFd()) {
+ // Mali Graphics says it's alive
+ int client = mMaliStartupUds.acceptConnection();
+ // Don't read from this connection, establish a new connection to Mali Graphics
+ close(client);
+ if (!connectMali()) {
+ logg->logError(__FILE__, __LINE__, "Unable to configure incoming Mali graphics connection");
+ handleException();
+ }
+ } else if (fd == mAnnotate.getFd()) {
+ int client = mAnnotate.acceptConnection();
+ if (!setNonblock(client) || !mMonitor.add(client)) {
+ logg->logError(__FILE__, __LINE__, "Unable to set socket options on incoming annotation connection");
+ handleException();
+ }
} else if (fd == pipefd[0]) {
// Means interrupt has been called and mSessionIsActive should be reread
} else {
- while (true) {
- waitFor(currTime, Buffer::MAXSIZE_PACK32 + 4);
-
+ /* This can result in some starvation if there are multiple
+ * threads which are annotating heavily, but it is not
+ * recommended that threads annotate that much as it can also
+ * starve out the gator data.
+ */
+ while (gSessionData->mSessionIsActive) {
+ // Wait until there is enough room for the fd, two headers and two ints
+ waitFor(7*Buffer::MAXSIZE_PACK32 + 2*sizeof(uint32_t));
mBuffer.packInt(fd);
- char *const bytesPos = mBuffer.getWritePos();
- mBuffer.advanceWrite(4);
const int contiguous = mBuffer.contiguousSpaceAvailable();
const int bytes = read(fd, mBuffer.getWritePos(), contiguous);
if (bytes < 0) {
if (errno == EAGAIN) {
- // Nothing left to read, and Buffer convention dictates that writePos can't go backwards
- mBuffer.writeLEInt((unsigned char *)bytesPos, 0);
+ // Nothing left to read
+ mBuffer.commit(currTime);
break;
}
// Something else failed, close the socket
- mBuffer.writeLEInt((unsigned char *)bytesPos, -1);
+ mBuffer.commit(currTime);
+ mBuffer.packInt(-1);
+ mBuffer.packInt(fd);
+ mBuffer.commit(currTime);
close(fd);
break;
} else if (bytes == 0) {
// The other side is closed
- mBuffer.writeLEInt((unsigned char *)bytesPos, -1);
+ mBuffer.commit(currTime);
+ mBuffer.packInt(-1);
+ mBuffer.packInt(fd);
+ mBuffer.commit(currTime);
close(fd);
break;
}
- mBuffer.writeLEInt((unsigned char *)bytesPos, bytes);
mBuffer.advanceWrite(bytes);
+ mBuffer.commit(currTime);
// Short reads also mean nothing is left to read
if (bytes < contiguous) {
@@ -176,13 +220,14 @@ void ExternalSource::run() {
}
}
}
-
- // Only call mBufferCheck once per iteration
- mBuffer.check(currTime);
}
mBuffer.setDone();
+ if (mMveUds >= 0) {
+ gSessionData->maliVideo.stop(mMveUds);
+ }
+
mInterruptFd = -1;
close(pipefd[0]);
close(pipefd[1]);
diff --git a/tools/gator/daemon/ExternalSource.h b/tools/gator/daemon/ExternalSource.h
index 2e7ed27df255..919e75e8a41a 100644
--- a/tools/gator/daemon/ExternalSource.h
+++ b/tools/gator/daemon/ExternalSource.h
@@ -16,7 +16,7 @@
#include "OlySocket.h"
#include "Source.h"
-// Unix domain socket counters from external sources like graphics drivers
+// Counters from external sources like graphics drivers and annotations
class ExternalSource : public Source {
public:
ExternalSource(sem_t *senderSem);
@@ -30,15 +30,19 @@ public:
void write(Sender *sender);
private:
- void waitFor(const uint64_t currTime, const int bytes);
+ void waitFor(const int bytes);
void configureConnection(const int fd, const char *const handshake, size_t size);
+ bool connectMali();
bool connectMve();
sem_t mBufferSem;
Buffer mBuffer;
Monitor mMonitor;
OlyServerSocket mMveStartupUds;
+ OlyServerSocket mMaliStartupUds;
+ OlyServerSocket mAnnotate;
int mInterruptFd;
+ int mMaliUds;
int mMveUds;
// Intentionally unimplemented
diff --git a/tools/gator/daemon/FSDriver.cpp b/tools/gator/daemon/FSDriver.cpp
index 40c8df1af222..dd8eb804dc99 100644
--- a/tools/gator/daemon/FSDriver.cpp
+++ b/tools/gator/daemon/FSDriver.cpp
@@ -14,43 +14,34 @@
#include <sys/types.h>
#include <unistd.h>
-#include "Buffer.h"
-#include "Counter.h"
#include "DriverSource.h"
#include "Logging.h"
-#include "SessionData.h"
-class FSCounter {
+class FSCounter : public DriverCounter {
public:
- FSCounter(FSCounter *next, char *name, const char *regex);
+ FSCounter(DriverCounter *next, char *name, char *path, const char *regex);
~FSCounter();
- FSCounter *getNext() const { return next; }
- int getKey() const { return key; }
- bool isEnabled() const { return enabled; }
- void setEnabled(const bool enabled) { this->enabled = enabled; }
- const char *getName() const { return name; }
+ const char *getPath() const { return mPath; }
+
int64_t read();
private:
- FSCounter *const next;
- regex_t reg;
- char *name;
- const int key;
- int enabled : 1,
- useRegex : 1;
+ char *const mPath;
+ regex_t mReg;
+ bool mUseRegex;
// Intentionally unimplemented
FSCounter(const FSCounter &);
FSCounter &operator=(const FSCounter &);
};
-FSCounter::FSCounter(FSCounter *next, char *name, const char *regex) : next(next), name(name), key(getEventKey()), enabled(false), useRegex(regex != NULL) {
- if (useRegex) {
- int result = regcomp(&reg, regex, REG_EXTENDED);
+FSCounter::FSCounter(DriverCounter *next, char *name, char *path, const char *regex) : DriverCounter(next, name), mPath(path), mUseRegex(regex != NULL) {
+ if (mUseRegex) {
+ int result = regcomp(&mReg, regex, REG_EXTENDED);
if (result != 0) {
char buf[128];
- regerror(result, &reg, buf, sizeof(buf));
+ regerror(result, &mReg, buf, sizeof(buf));
logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf);
handleException();
}
@@ -58,18 +49,18 @@ FSCounter::FSCounter(FSCounter *next, char *name, const char *regex) : next(next
}
FSCounter::~FSCounter() {
- free(name);
- if (useRegex) {
- regfree(&reg);
+ free(mPath);
+ if (mUseRegex) {
+ regfree(&mReg);
}
}
int64_t FSCounter::read() {
int64_t value;
- if (useRegex) {
+ if (mUseRegex) {
char buf[4096];
size_t pos = 0;
- const int fd = open(name, O_RDONLY);
+ const int fd = open(mPath, O_RDONLY | O_CLOEXEC);
if (fd < 0) {
goto fail;
}
@@ -86,53 +77,43 @@ int64_t FSCounter::read() {
buf[pos] = '\0';
regmatch_t match[2];
- int result = regexec(&reg, buf, 2, match, 0);
+ int result = regexec(&mReg, buf, 2, match, 0);
if (result != 0) {
- regerror(result, &reg, buf, sizeof(buf));
- logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, buf);
+ regerror(result, &mReg, buf, sizeof(buf));
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", mPath, buf);
handleException();
}
if (match[1].rm_so < 0) {
- logg->logError(__FILE__, __LINE__, "Parsing %s failed", name);
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed", mPath);
handleException();
}
- char *endptr;
+
errno = 0;
- value = strtoll(buf + match[1].rm_so, &endptr, 0);
+ value = strtoll(buf + match[1].rm_so, NULL, 0);
if (errno != 0) {
- logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, strerror(errno));
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", mPath, strerror(errno));
handleException();
}
} else {
- if (DriverSource::readInt64Driver(name, &value) != 0) {
+ if (DriverSource::readInt64Driver(mPath, &value) != 0) {
goto fail;
}
}
return value;
fail:
- logg->logError(__FILE__, __LINE__, "Unable to read %s", name);
+ logg->logError(__FILE__, __LINE__, "Unable to read %s", mPath);
handleException();
}
-FSDriver::FSDriver() : counters(NULL) {
+FSDriver::FSDriver() {
}
FSDriver::~FSDriver() {
- while (counters != NULL) {
- FSCounter * counter = counters;
- counters = counter->getNext();
- delete counter;
- }
}
-void FSDriver::setup(mxml_node_t *const xml) {
- // fs driver does not currently work with perf
- if (gSessionData->perf.isSetup()) {
- return;
- }
-
+void FSDriver::readEvents(mxml_node_t *const xml) {
mxml_node_t *node = xml;
while (true) {
node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
@@ -140,56 +121,33 @@ void FSDriver::setup(mxml_node_t *const xml) {
break;
}
const char *counter = mxmlElementGetAttr(node, "counter");
- if ((counter != NULL) && (counter[0] == '/')) {
- const char *regex = mxmlElementGetAttr(node, "regex");
- counters = new FSCounter(counters, strdup(counter), regex);
+ if (counter == NULL) {
+ continue;
}
- }
-}
-FSCounter *FSDriver::findCounter(const Counter &counter) const {
- for (FSCounter * fsCounter = counters; fsCounter != NULL; fsCounter = fsCounter->getNext()) {
- if (strcmp(fsCounter->getName(), counter.getType()) == 0) {
- return fsCounter;
+ if (counter[0] == '/') {
+ logg->logError(__FILE__, __LINE__, "Old style filesystem counter (%s) detected, please create a new unique counter value and move the filename into the path attribute, see events-Filesystem.xml for examples", counter);
+ handleException();
}
- }
-
- return NULL;
-}
-bool FSDriver::claimCounter(const Counter &counter) const {
- return findCounter(counter) != NULL;
-}
-
-bool FSDriver::countersEnabled() const {
- for (FSCounter *counter = counters; counter != NULL; counter = counter->getNext()) {
- if (counter->isEnabled()) {
- return true;
+ if (strncmp(counter, "filesystem_", 11) != 0) {
+ continue;
}
- }
- return false;
-}
-void FSDriver::resetCounters() {
- for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- counter->setEnabled(false);
- }
-}
-
-void FSDriver::setupCounter(Counter &counter) {
- FSCounter *const fsCounter = findCounter(counter);
- if (fsCounter == NULL) {
- counter.setEnabled(false);
- return;
+ const char *path = mxmlElementGetAttr(node, "path");
+ if (path == NULL) {
+ logg->logError(__FILE__, __LINE__, "The filesystem counter %s is missing the required path attribute", counter);
+ handleException();
+ }
+ const char *regex = mxmlElementGetAttr(node, "regex");
+ setCounters(new FSCounter(getCounters(), strdup(counter), strdup(path), regex));
}
- fsCounter->setEnabled(true);
- counter.setKey(fsCounter->getKey());
}
int FSDriver::writeCounters(mxml_node_t *root) const {
int count = 0;
- for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (access(counter->getName(), R_OK) == 0) {
+ for (FSCounter *counter = static_cast<FSCounter *>(getCounters()); counter != NULL; counter = static_cast<FSCounter *>(counter->getNext())) {
+ if (access(counter->getPath(), R_OK) == 0) {
mxml_node_t *node = mxmlNewElement(root, "counter");
mxmlElementSetAttr(node, "name", counter->getName());
++count;
@@ -198,15 +156,3 @@ int FSDriver::writeCounters(mxml_node_t *root) const {
return count;
}
-
-void FSDriver::start() {
-}
-
-void FSDriver::read(Buffer * const buffer) {
- for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (!counter->isEnabled()) {
- continue;
- }
- buffer->event(counter->getKey(), counter->read());
- }
-}
diff --git a/tools/gator/daemon/FSDriver.h b/tools/gator/daemon/FSDriver.h
index ef3955362331..a7dc8b4df9dd 100644
--- a/tools/gator/daemon/FSDriver.h
+++ b/tools/gator/daemon/FSDriver.h
@@ -11,31 +11,16 @@
#include "Driver.h"
-class Buffer;
-class FSCounter;
-
-class FSDriver : public Driver {
+class FSDriver : public PolledDriver {
public:
FSDriver();
~FSDriver();
- void setup(mxml_node_t *const xml);
-
- bool claimCounter(const Counter &counter) const;
- bool countersEnabled() const;
- void resetCounters();
- void setupCounter(Counter &counter);
+ void readEvents(mxml_node_t *const xml);
int writeCounters(mxml_node_t *root) const;
- void start();
- void read(Buffer * buffer);
-
private:
- FSCounter *findCounter(const Counter &counter) const;
-
- FSCounter *counters;
-
// Intentionally unimplemented
FSDriver(const FSDriver &);
FSDriver &operator=(const FSDriver &);
diff --git a/tools/gator/daemon/Fifo.cpp b/tools/gator/daemon/Fifo.cpp
index f672e92a6807..41275fd287b8 100644
--- a/tools/gator/daemon/Fifo.cpp
+++ b/tools/gator/daemon/Fifo.cpp
@@ -9,9 +9,6 @@
#include "Fifo.h"
#include <stdlib.h>
-#ifdef WIN32
-#define valloc malloc
-#endif
#include "Logging.h"
@@ -23,7 +20,7 @@ Fifo::Fifo(int singleBufferSize, int bufferSize, sem_t* readerSem) {
mWrapThreshold = bufferSize;
mSingleBufferSize = singleBufferSize;
mReaderSem = readerSem;
- mBuffer = (char*)valloc(bufferSize + singleBufferSize);
+ mBuffer = (char*)malloc(bufferSize + singleBufferSize);
mEnd = false;
if (mBuffer == NULL) {
diff --git a/tools/gator/daemon/Fifo.h b/tools/gator/daemon/Fifo.h
index bdda3f549b50..21c8d8580391 100644
--- a/tools/gator/daemon/Fifo.h
+++ b/tools/gator/daemon/Fifo.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __FIFO_H__
-#define __FIFO_H__
+#ifndef __FIFO_H__
+#define __FIFO_H__
#ifdef WIN32
#include <windows.h>
@@ -35,10 +35,10 @@ public:
private:
int mSingleBufferSize, mWrite, mRead, mReadCommit, mRaggedEnd, mWrapThreshold;
- sem_t mWaitForSpaceSem;
+ sem_t mWaitForSpaceSem;
sem_t* mReaderSem;
- char* mBuffer;
- bool mEnd;
+ char* mBuffer;
+ bool mEnd;
// Intentionally unimplemented
Fifo(const Fifo &);
diff --git a/tools/gator/daemon/FtraceDriver.cpp b/tools/gator/daemon/FtraceDriver.cpp
new file mode 100644
index 000000000000..b156f1c0b8b4
--- /dev/null
+++ b/tools/gator/daemon/FtraceDriver.cpp
@@ -0,0 +1,118 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "FtraceDriver.h"
+
+#include <regex.h>
+
+#include "Logging.h"
+
+class FtraceCounter : public DriverCounter {
+public:
+ FtraceCounter(DriverCounter *next, char *name, const char *regex);
+ ~FtraceCounter();
+
+ int read(const char *const line, int64_t *values);
+
+private:
+ regex_t reg;
+
+ // Intentionally unimplemented
+ FtraceCounter(const FtraceCounter &);
+ FtraceCounter &operator=(const FtraceCounter &);
+};
+
+FtraceCounter::FtraceCounter(DriverCounter *next, char *name, const char *regex) : DriverCounter(next, name) {
+ int result = regcomp(&reg, regex, REG_EXTENDED);
+ if (result != 0) {
+ char buf[128];
+ regerror(result, &reg, buf, sizeof(buf));
+ logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf);
+ handleException();
+ }
+}
+
+FtraceCounter::~FtraceCounter() {
+ regfree(&reg);
+}
+
+int FtraceCounter::read(const char *const line, int64_t *values) {
+ regmatch_t match[2];
+ int result = regexec(&reg, line, 2, match, 0);
+ if (result != 0) {
+ // No match
+ return 0;
+ }
+
+ if (match[1].rm_so < 0) {
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed", getName());
+ handleException();
+ }
+
+ errno = 0;
+ int64_t value = strtoll(line + match[1].rm_so, NULL, 0);
+ if (errno != 0) {
+ logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", getName(), strerror(errno));
+ handleException();
+ }
+
+ values[0] = getKey();
+ values[1] = value;
+
+ return 1;
+}
+
+FtraceDriver::FtraceDriver() : mValues(NULL) {
+}
+
+FtraceDriver::~FtraceDriver() {
+ delete [] mValues;
+}
+
+void FtraceDriver::readEvents(mxml_node_t *const xml) {
+ mxml_node_t *node = xml;
+ int count = 0;
+ while (true) {
+ node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ break;
+ }
+ const char *counter = mxmlElementGetAttr(node, "counter");
+ if (counter == NULL) {
+ continue;
+ }
+
+ if (strncmp(counter, "ftrace_", 7) != 0) {
+ continue;
+ }
+
+ const char *regex = mxmlElementGetAttr(node, "regex");
+ if (regex == NULL) {
+ logg->logError(__FILE__, __LINE__, "The regex counter %s is missing the required regex attribute", counter);
+ handleException();
+ }
+ setCounters(new FtraceCounter(getCounters(), strdup(counter), regex));
+ ++count;
+ }
+
+ mValues = new int64_t[2*count];
+}
+
+int FtraceDriver::read(const char *line, int64_t **buf) {
+ int count = 0;
+
+ for (FtraceCounter *counter = static_cast<FtraceCounter *>(getCounters()); counter != NULL; counter = static_cast<FtraceCounter *>(counter->getNext())) {
+ if (!counter->isEnabled()) {
+ continue;
+ }
+ count += counter->read(line, mValues + 2*count);
+ }
+
+ *buf = mValues;
+ return count;
+}
diff --git a/tools/gator/daemon/FtraceDriver.h b/tools/gator/daemon/FtraceDriver.h
new file mode 100644
index 000000000000..5f958bec672c
--- /dev/null
+++ b/tools/gator/daemon/FtraceDriver.h
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef FTRACEDRIVER_H
+#define FTRACEDRIVER_H
+
+#include "Driver.h"
+
+class FtraceDriver : public SimpleDriver {
+public:
+ FtraceDriver();
+ ~FtraceDriver();
+
+ void readEvents(mxml_node_t *const xml);
+
+ int read(const char *line, int64_t **buf);
+
+private:
+ int64_t *mValues;
+
+ // Intentionally unimplemented
+ FtraceDriver(const FtraceDriver &);
+ FtraceDriver &operator=(const FtraceDriver &);
+};
+
+#endif // FTRACEDRIVER_H
diff --git a/tools/gator/daemon/FtraceSource.cpp b/tools/gator/daemon/FtraceSource.cpp
new file mode 100644
index 000000000000..521633357417
--- /dev/null
+++ b/tools/gator/daemon/FtraceSource.cpp
@@ -0,0 +1,158 @@
+/**
+ * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "FtraceSource.h"
+
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include "DriverSource.h"
+#include "Logging.h"
+#include "SessionData.h"
+
+static void handler(int signum)
+{
+ (void)signum;
+};
+
+FtraceSource::FtraceSource(sem_t *senderSem) : mFtraceFh(NULL), mBuffer(0, FRAME_BLOCK_COUNTER, 128*1024, senderSem), mTid(-1), mTracingOn(0) {
+}
+
+FtraceSource::~FtraceSource() {
+}
+
+bool FtraceSource::prepare() {
+ {
+ struct sigaction act;
+ act.sa_handler = handler;
+ act.sa_flags = (int)SA_RESETHAND;
+ if (sigaction(SIGUSR1, &act, NULL) != 0) {
+ logg->logError(__FILE__, __LINE__, "sigaction failed: %s\n", strerror(errno));
+ handleException();
+ }
+ }
+
+ if (DriverSource::readIntDriver("/sys/kernel/debug/tracing/tracing_on", &mTracingOn)) {
+ logg->logError(__FILE__, __LINE__, "Unable to read if ftrace is enabled");
+ handleException();
+ }
+
+ if (DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", "0") != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to turn ftrace off before truncating the buffer");
+ handleException();
+ }
+
+ {
+ int fd;
+ fd = open("/sys/kernel/debug/tracing/trace", O_WRONLY | O_TRUNC | O_CLOEXEC, 0666);
+ if (fd < 0) {
+ logg->logError(__FILE__, __LINE__, "Unable truncate ftrace buffer: %s", strerror(errno));
+ handleException();
+ }
+ close(fd);
+ }
+
+ if (DriverSource::writeDriver("/sys/kernel/debug/tracing/trace_clock", "perf") != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to switch ftrace to the perf clock, please ensure you are running Linux 3.10 or later");
+ handleException();
+ }
+
+ mFtraceFh = fopen_cloexec("/sys/kernel/debug/tracing/trace_pipe", "rb");
+ if (mFtraceFh == NULL) {
+ logg->logError(__FILE__, __LINE__, "Unable to open trace_pipe");
+ handleException();
+ }
+
+ return true;
+}
+
+void FtraceSource::run() {
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-ftrace", 0, 0, 0);
+ mTid = syscall(__NR_gettid);
+
+ if (DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", "1") != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to turn ftrace on");
+ handleException();
+ }
+
+ while (gSessionData->mSessionIsActive) {
+ char buf[1<<12];
+
+ if (fgets(buf, sizeof(buf), mFtraceFh) == NULL) {
+ if (errno == EINTR) {
+ // Interrupted by interrupt - likely user request to terminate
+ break;
+ }
+ logg->logError(__FILE__, __LINE__, "Unable read trace data: %s", strerror(errno));
+ handleException();
+ }
+
+ const uint64_t currTime = getTime();
+
+ char *const colon = strstr(buf, ": ");
+ if (colon == NULL) {
+ logg->logError(__FILE__, __LINE__, "Unable find colon: %s", buf);
+ handleException();
+ }
+ *colon = '\0';
+
+ char *const space = strrchr(buf, ' ');
+ if (space == NULL) {
+ logg->logError(__FILE__, __LINE__, "Unable find space: %s", buf);
+ handleException();
+ }
+ *colon = ':';
+
+ int64_t *data = NULL;
+ int count = gSessionData->ftraceDriver.read(colon + 2, &data);
+ if (count > 0) {
+ errno = 0;
+ const long long time = strtod(space, NULL) * 1000000000;
+ if (errno != 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to parse time: %s", strerror(errno));
+ handleException();
+ }
+ mBuffer.event64(-1, time);
+
+ for (int i = 0; i < count; ++i) {
+ mBuffer.event64(data[2*i + 0], data[2*i + 1]);
+ }
+
+ mBuffer.check(currTime);
+ }
+
+ }
+
+ mBuffer.setDone();
+
+ DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", mTracingOn);
+ fclose(mFtraceFh);
+ DriverSource::writeDriver("/sys/kernel/debug/tracing/trace_clock", "local");
+}
+
+void FtraceSource::interrupt() {
+ // Closing the underlying file handle does not result in the read on the ftrace file handle to return, so send a signal to the thread
+ syscall(__NR_tgkill, getpid(), mTid, SIGUSR1);
+}
+
+bool FtraceSource::isDone() {
+ return mBuffer.isDone();
+}
+
+void FtraceSource::write(Sender *sender) {
+ // Don't send ftrace data until the summary packet is sent so that monotonic delta is available
+ if (!gSessionData->mSentSummary) {
+ return;
+ }
+ if (!mBuffer.isDone()) {
+ mBuffer.write(sender);
+ }
+}
diff --git a/tools/gator/daemon/FtraceSource.h b/tools/gator/daemon/FtraceSource.h
new file mode 100644
index 000000000000..2391b881494e
--- /dev/null
+++ b/tools/gator/daemon/FtraceSource.h
@@ -0,0 +1,43 @@
+/**
+ * Copyright (C) ARM Limited 2010-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef FTRACESOURCE_H
+#define FTRACESOURCE_H
+
+#include <semaphore.h>
+#include <stdio.h>
+
+#include "Buffer.h"
+#include "Source.h"
+
+class FtraceSource : public Source {
+public:
+ FtraceSource(sem_t *senderSem);
+ ~FtraceSource();
+
+ bool prepare();
+ void run();
+ void interrupt();
+
+ bool isDone();
+ void write(Sender *sender);
+
+private:
+ void waitFor(const int bytes);
+
+ FILE *mFtraceFh;
+ Buffer mBuffer;
+ int mTid;
+ int mTracingOn;
+
+ // Intentionally unimplemented
+ FtraceSource(const FtraceSource &);
+ FtraceSource &operator=(const FtraceSource &);
+};
+
+#endif // FTRACESOURCE_H
diff --git a/tools/gator/daemon/Hwmon.h b/tools/gator/daemon/Hwmon.h
deleted file mode 100644
index a22a3609f99f..000000000000
--- a/tools/gator/daemon/Hwmon.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Copyright (C) ARM Limited 2013-2014. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef HWMON_H
-#define HWMON_H
-
-#include "Driver.h"
-
-class Buffer;
-class HwmonCounter;
-
-class Hwmon : public Driver {
-public:
- Hwmon();
- ~Hwmon();
-
- void setup();
-
- bool claimCounter(const Counter &counter) const;
- bool countersEnabled() const;
- void resetCounters();
- void setupCounter(Counter &counter);
-
- int writeCounters(mxml_node_t *root) const;
- void writeEvents(mxml_node_t *root) const;
-
- void start();
- void read(Buffer * buffer);
-
-private:
- HwmonCounter *findCounter(const Counter &counter) const;
-
- HwmonCounter *counters;
-
- // Intentionally unimplemented
- Hwmon(const Hwmon &);
- Hwmon &operator=(const Hwmon &);
-};
-
-#endif // HWMON_H
diff --git a/tools/gator/daemon/Hwmon.cpp b/tools/gator/daemon/HwmonDriver.cpp
index e44424743ef0..9d161ae5ac56 100644
--- a/tools/gator/daemon/Hwmon.cpp
+++ b/tools/gator/daemon/HwmonDriver.cpp
@@ -6,24 +6,33 @@
* published by the Free Software Foundation.
*/
-#include "Hwmon.h"
+#include "HwmonDriver.h"
#include "libsensors/sensors.h"
-#include "Buffer.h"
-#include "Counter.h"
#include "Logging.h"
-#include "SessionData.h"
-class HwmonCounter {
+// feature->type to input map
+static sensors_subfeature_type getInput(const sensors_feature_type type) {
+ switch (type) {
+ case SENSORS_FEATURE_IN: return SENSORS_SUBFEATURE_IN_INPUT;
+ case SENSORS_FEATURE_FAN: return SENSORS_SUBFEATURE_FAN_INPUT;
+ case SENSORS_FEATURE_TEMP: return SENSORS_SUBFEATURE_TEMP_INPUT;
+ case SENSORS_FEATURE_POWER: return SENSORS_SUBFEATURE_POWER_INPUT;
+ case SENSORS_FEATURE_ENERGY: return SENSORS_SUBFEATURE_ENERGY_INPUT;
+ case SENSORS_FEATURE_CURR: return SENSORS_SUBFEATURE_CURR_INPUT;
+ case SENSORS_FEATURE_HUMIDITY: return SENSORS_SUBFEATURE_HUMIDITY_INPUT;
+ default:
+ logg->logError(__FILE__, __LINE__, "Unsupported hwmon feature %i", type);
+ handleException();
+ }
+};
+
+class HwmonCounter : public DriverCounter {
public:
- HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, const sensors_feature *feature);
+ HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *chip, const sensors_feature *feature);
~HwmonCounter();
- HwmonCounter *getNext() const { return next; }
- int getKey() const { return key; }
- bool isEnabled() const { return enabled; }
- const char *getName() const { return name; }
const char *getLabel() const { return label; }
const char *getTitle() const { return title; }
bool isDuplicate() const { return duplicate; }
@@ -32,63 +41,34 @@ public:
const char *getUnit() const { return unit; }
int getModifier() const { return modifier; }
- void setEnabled(const bool enabled) {
- this->enabled = enabled;
- // canRead will clear enabled if the counter is not readable
- canRead();
- }
-
- double read();
- bool canRead();
+ int64_t read();
private:
void init(const sensors_chip_name *chip, const sensors_feature *feature);
- HwmonCounter *const next;
- const int key;
- int polled : 1,
- readable : 1,
- enabled : 1,
- monotonic: 1,
- duplicate : 1;
-
const sensors_chip_name *chip;
const sensors_feature *feature;
-
- char *name;
char *label;
const char *title;
const char *display;
const char *counter_class;
const char *unit;
- int modifier;
double previous_value;
-
- sensors_subfeature_type input;
+ int modifier;
+ int monotonic: 1,
+ duplicate : 1;
// Intentionally unimplemented
HwmonCounter(const HwmonCounter &);
HwmonCounter &operator=(const HwmonCounter &);
};
-HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, const sensors_feature *feature) : next(next), key(getEventKey()), polled(false), readable(false), enabled(false), duplicate(false), chip(chip), feature(feature) {
-
- int len = sensors_snprintf_chip_name(NULL, 0, chip) + 1;
- char *chip_name = new char[len];
- sensors_snprintf_chip_name(chip_name, len, chip);
-
- len = snprintf(NULL, 0, "hwmon_%s_%d", chip_name, feature->number) + 1;
- name = new char[len];
- snprintf(name, len, "hwmon_%s_%d", chip_name, feature->number);
-
- delete [] chip_name;
-
+HwmonCounter::HwmonCounter(DriverCounter *next, char *const name, const sensors_chip_name *chip, const sensors_feature *feature) : DriverCounter(next, name), chip(chip), feature(feature), duplicate(false) {
label = sensors_get_label(chip, feature);
switch (feature->type) {
case SENSORS_FEATURE_IN:
title = "Voltage";
- input = SENSORS_SUBFEATURE_IN_INPUT;
display = "maximum";
counter_class = "absolute";
unit = "V";
@@ -97,7 +77,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_FAN:
title = "Fan";
- input = SENSORS_SUBFEATURE_FAN_INPUT;
display = "average";
counter_class = "absolute";
unit = "RPM";
@@ -106,7 +85,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_TEMP:
title = "Temperature";
- input = SENSORS_SUBFEATURE_TEMP_INPUT;
display = "maximum";
counter_class = "absolute";
unit = "°C";
@@ -115,7 +93,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_POWER:
title = "Power";
- input = SENSORS_SUBFEATURE_POWER_INPUT;
display = "maximum";
counter_class = "absolute";
unit = "W";
@@ -124,7 +101,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_ENERGY:
title = "Energy";
- input = SENSORS_SUBFEATURE_ENERGY_INPUT;
display = "accumulate";
counter_class = "delta";
unit = "J";
@@ -133,7 +109,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_CURR:
title = "Current";
- input = SENSORS_SUBFEATURE_CURR_INPUT;
display = "maximum";
counter_class = "absolute";
unit = "A";
@@ -142,7 +117,6 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
break;
case SENSORS_FEATURE_HUMIDITY:
title = "Humidity";
- input = SENSORS_SUBFEATURE_HUMIDITY_INPUT;
display = "average";
counter_class = "absolute";
unit = "%";
@@ -154,7 +128,7 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
handleException();
}
- for (HwmonCounter * counter = next; counter != NULL; counter = counter->getNext()) {
+ for (HwmonCounter * counter = static_cast<HwmonCounter *>(next); counter != NULL; counter = static_cast<HwmonCounter *>(counter->getNext())) {
if (strcmp(label, counter->getLabel()) == 0 && strcmp(title, counter->getTitle()) == 0) {
duplicate = true;
counter->duplicate = true;
@@ -165,16 +139,15 @@ HwmonCounter::HwmonCounter(HwmonCounter *next, const sensors_chip_name *chip, co
HwmonCounter::~HwmonCounter() {
free((void *)label);
- delete [] name;
}
-double HwmonCounter::read() {
+int64_t HwmonCounter::read() {
double value;
double result;
const sensors_subfeature *subfeature;
- // Keep in sync with canRead
- subfeature = sensors_get_subfeature(chip, feature, input);
+ // Keep in sync with the read check in HwmonDriver::readEvents
+ subfeature = sensors_get_subfeature(chip, feature, getInput(feature->type));
if (!subfeature) {
logg->logError(__FILE__, __LINE__, "No input value for hwmon sensor %s", label);
handleException();
@@ -191,46 +164,14 @@ double HwmonCounter::read() {
return result;
}
-bool HwmonCounter::canRead() {
- if (!polled) {
- double value;
- const sensors_subfeature *subfeature;
- bool result = true;
-
- subfeature = sensors_get_subfeature(chip, feature, input);
- if (!subfeature) {
- result = false;
- } else {
- result = sensors_get_value(chip, subfeature->number, &value) == 0;
- }
-
- polled = true;
- readable = result;
- }
-
- enabled &= readable;
-
- return readable;
-}
-
-Hwmon::Hwmon() : counters(NULL) {
+HwmonDriver::HwmonDriver() {
}
-Hwmon::~Hwmon() {
- while (counters != NULL) {
- HwmonCounter * counter = counters;
- counters = counter->getNext();
- delete counter;
- }
+HwmonDriver::~HwmonDriver() {
sensors_cleanup();
}
-void Hwmon::setup() {
- // hwmon does not currently work with perf
- if (gSessionData->perf.isSetup()) {
- return;
- }
-
+void HwmonDriver::readEvents(mxml_node_t *const) {
int err = sensors_init(NULL);
if (err) {
logg->logMessage("Failed to initialize libsensors! (%d)", err);
@@ -244,73 +185,34 @@ void Hwmon::setup() {
int feature_nr = 0;
const sensors_feature *feature;
while ((feature = sensors_get_features(chip, &feature_nr))) {
- counters = new HwmonCounter(counters, chip, feature);
+ // Keep in sync with HwmonCounter::read
+ // Can this counter be read?
+ double value;
+ const sensors_subfeature *const subfeature = sensors_get_subfeature(chip, feature, getInput(feature->type));
+ if ((subfeature == NULL) || (sensors_get_value(chip, subfeature->number, &value) != 0)) {
+ continue;
+ }
+
+ // Get the name of the counter
+ int len = sensors_snprintf_chip_name(NULL, 0, chip) + 1;
+ char *chip_name = new char[len];
+ sensors_snprintf_chip_name(chip_name, len, chip);
+ len = snprintf(NULL, 0, "hwmon_%s_%d_%d", chip_name, chip_nr, feature->number) + 1;
+ char *const name = new char[len];
+ snprintf(name, len, "hwmon_%s_%d_%d", chip_name, chip_nr, feature->number);
+ delete [] chip_name;
+
+ setCounters(new HwmonCounter(getCounters(), name, chip, feature));
}
}
}
-HwmonCounter *Hwmon::findCounter(const Counter &counter) const {
- for (HwmonCounter * hwmonCounter = counters; hwmonCounter != NULL; hwmonCounter = hwmonCounter->getNext()) {
- if (hwmonCounter->canRead() && strcmp(hwmonCounter->getName(), counter.getType()) == 0) {
- return hwmonCounter;
- }
- }
-
- return NULL;
-}
-
-bool Hwmon::claimCounter(const Counter &counter) const {
- return findCounter(counter) != NULL;
-}
-
-bool Hwmon::countersEnabled() const {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (counter->isEnabled()) {
- return true;
- }
- }
- return false;
-}
-
-void Hwmon::resetCounters() {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- counter->setEnabled(false);
- }
-}
-
-void Hwmon::setupCounter(Counter &counter) {
- HwmonCounter *const hwmonCounter = findCounter(counter);
- if (hwmonCounter == NULL) {
- counter.setEnabled(false);
- return;
- }
- hwmonCounter->setEnabled(true);
- counter.setKey(hwmonCounter->getKey());
-}
-
-int Hwmon::writeCounters(mxml_node_t *root) const {
- int count = 0;
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (!counter->canRead()) {
- continue;
- }
- mxml_node_t *node = mxmlNewElement(root, "counter");
- mxmlElementSetAttr(node, "name", counter->getName());
- ++count;
- }
-
- return count;
-}
-
-void Hwmon::writeEvents(mxml_node_t *root) const {
+void HwmonDriver::writeEvents(mxml_node_t *root) const {
root = mxmlNewElement(root, "category");
mxmlElementSetAttr(root, "name", "hwmon");
char buf[1024];
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (!counter->canRead()) {
- continue;
- }
+ for (HwmonCounter *counter = static_cast<HwmonCounter *>(getCounters()); counter != NULL; counter = static_cast<HwmonCounter *>(counter->getNext())) {
mxml_node_t *node = mxmlNewElement(root, "event");
mxmlElementSetAttr(node, "counter", counter->getName());
mxmlElementSetAttr(node, "title", counter->getTitle());
@@ -333,20 +235,11 @@ void Hwmon::writeEvents(mxml_node_t *root) const {
}
}
-void Hwmon::start() {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
+void HwmonDriver::start() {
+ for (DriverCounter *counter = getCounters(); counter != NULL; counter = counter->getNext()) {
if (!counter->isEnabled()) {
continue;
}
counter->read();
}
}
-
-void Hwmon::read(Buffer * const buffer) {
- for (HwmonCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
- if (!counter->isEnabled()) {
- continue;
- }
- buffer->event(counter->getKey(), counter->read());
- }
-}
diff --git a/tools/gator/daemon/HwmonDriver.h b/tools/gator/daemon/HwmonDriver.h
new file mode 100644
index 000000000000..f28d825e3b7b
--- /dev/null
+++ b/tools/gator/daemon/HwmonDriver.h
@@ -0,0 +1,31 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef HWMONDRIVER_H
+#define HWMONDRIVER_H
+
+#include "Driver.h"
+
+class HwmonDriver : public PolledDriver {
+public:
+ HwmonDriver();
+ ~HwmonDriver();
+
+ void readEvents(mxml_node_t *const root);
+
+ void writeEvents(mxml_node_t *root) const;
+
+ void start();
+
+private:
+ // Intentionally unimplemented
+ HwmonDriver(const HwmonDriver &);
+ HwmonDriver &operator=(const HwmonDriver &);
+};
+
+#endif // HWMONDRIVER_H
diff --git a/tools/gator/daemon/KMod.cpp b/tools/gator/daemon/KMod.cpp
index 73e123d2f14e..fe9dc6a7e4f7 100644
--- a/tools/gator/daemon/KMod.cpp
+++ b/tools/gator/daemon/KMod.cpp
@@ -16,6 +16,7 @@
#include "Counter.h"
#include "DriverSource.h"
#include "Logging.h"
+#include "SessionData.h"
// Claim all the counters in /dev/gator/events
bool KMod::claimCounter(const Counter &counter) const {
@@ -46,11 +47,19 @@ void KMod::resetCounters() {
}
}
+static const char ARM_MALI_MIDGARD[] = "ARM_Mali-Midgard_";
+static const char ARM_MALI_T[] = "ARM_Mali-T";
+
void KMod::setupCounter(Counter &counter) {
char base[128];
char text[128];
snprintf(base, sizeof(base), "/dev/gator/events/%s", counter.getType());
+ if ((strncmp(counter.getType(), ARM_MALI_MIDGARD, sizeof(ARM_MALI_MIDGARD) - 1) == 0 ||
+ strncmp(counter.getType(), ARM_MALI_T, sizeof(ARM_MALI_T) - 1) == 0)) {
+ mIsMaliCapture = true;
+ }
+
snprintf(text, sizeof(text), "%s/enabled", base);
int enabled = true;
if (DriverSource::writeReadDriver(text, &enabled) || !enabled) {
diff --git a/tools/gator/daemon/KMod.h b/tools/gator/daemon/KMod.h
index fb7fc8a8f9c6..900a60e87d24 100644
--- a/tools/gator/daemon/KMod.h
+++ b/tools/gator/daemon/KMod.h
@@ -14,7 +14,7 @@
// Driver for the gator kernel module
class KMod : public Driver {
public:
- KMod() {}
+ KMod() : mIsMaliCapture(false) {}
~KMod() {}
bool claimCounter(const Counter &counter) const;
@@ -22,6 +22,11 @@ public:
void setupCounter(Counter &counter);
int writeCounters(mxml_node_t *root) const;
+
+ bool isMaliCapture() const { return mIsMaliCapture; }
+
+private:
+ bool mIsMaliCapture;
};
#endif // KMOD_H
diff --git a/tools/gator/daemon/LocalCapture.h b/tools/gator/daemon/LocalCapture.h
index b1e7219795cf..25d281f8328b 100644
--- a/tools/gator/daemon/LocalCapture.h
+++ b/tools/gator/daemon/LocalCapture.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __LOCAL_CAPTURE_H__
-#define __LOCAL_CAPTURE_H__
+#ifndef __LOCAL_CAPTURE_H__
+#define __LOCAL_CAPTURE_H__
struct ImageLinkList;
diff --git a/tools/gator/daemon/Logging.cpp b/tools/gator/daemon/Logging.cpp
index b8d3178950d6..41ffa1a45151 100644
--- a/tools/gator/daemon/Logging.cpp
+++ b/tools/gator/daemon/Logging.cpp
@@ -14,15 +14,15 @@
#include <string.h>
#ifdef WIN32
-#define MUTEX_INIT() mLoggingMutex = CreateMutex(NULL, false, NULL);
-#define MUTEX_LOCK() WaitForSingleObject(mLoggingMutex, 0xFFFFFFFF);
-#define MUTEX_UNLOCK() ReleaseMutex(mLoggingMutex);
-#define snprintf _snprintf
+#define MUTEX_INIT() mLoggingMutex = CreateMutex(NULL, false, NULL);
+#define MUTEX_LOCK() WaitForSingleObject(mLoggingMutex, 0xFFFFFFFF);
+#define MUTEX_UNLOCK() ReleaseMutex(mLoggingMutex);
+#define snprintf _snprintf
#else
#include <pthread.h>
-#define MUTEX_INIT() pthread_mutex_init(&mLoggingMutex, NULL)
-#define MUTEX_LOCK() pthread_mutex_lock(&mLoggingMutex)
-#define MUTEX_UNLOCK() pthread_mutex_unlock(&mLoggingMutex)
+#define MUTEX_INIT() pthread_mutex_init(&mLoggingMutex, NULL)
+#define MUTEX_LOCK() pthread_mutex_lock(&mLoggingMutex)
+#define MUTEX_UNLOCK() pthread_mutex_unlock(&mLoggingMutex)
#endif
// Global thread-safe logging
@@ -40,7 +40,7 @@ Logging::~Logging() {
}
void Logging::logError(const char* file, int line, const char* fmt, ...) {
- va_list args;
+ va_list args;
MUTEX_LOCK();
if (mDebug) {
@@ -61,7 +61,7 @@ void Logging::logError(const char* file, int line, const char* fmt, ...) {
void Logging::logMessage(const char* fmt, ...) {
if (mDebug) {
- va_list args;
+ va_list args;
MUTEX_LOCK();
strcpy(mLogBuf, "INFO: ");
diff --git a/tools/gator/daemon/Logging.h b/tools/gator/daemon/Logging.h
index 4934bb079754..09e93ff13f7a 100644
--- a/tools/gator/daemon/Logging.h
+++ b/tools/gator/daemon/Logging.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __LOGGING_H__
-#define __LOGGING_H__
+#ifndef __LOGGING_H__
+#define __LOGGING_H__
#include <pthread.h>
@@ -23,10 +23,10 @@ public:
char* getLastMessage() {return mLogBuf;}
private:
- char mErrBuf[4096]; // Arbitrarily large buffer to hold a string
- char mLogBuf[4096]; // Arbitrarily large buffer to hold a string
- bool mDebug;
- pthread_mutex_t mLoggingMutex;
+ char mErrBuf[4096]; // Arbitrarily large buffer to hold a string
+ char mLogBuf[4096]; // Arbitrarily large buffer to hold a string
+ bool mDebug;
+ pthread_mutex_t mLoggingMutex;
};
extern Logging* logg;
diff --git a/tools/gator/daemon/Makefile b/tools/gator/daemon/Makefile
index 2ed49fdb688b..27531b438b63 100644
--- a/tools/gator/daemon/Makefile
+++ b/tools/gator/daemon/Makefile
@@ -11,11 +11,8 @@
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++
-# -mthumb-interwork is required for interworking to ARM or Thumb stdlibc
-CPPFLAGS += -mthumb-interwork
-
ifeq ($(SOFTFLOAT),1)
- CPPFLAGS += -marm -march=armv4t -mfloat-abi=soft
+ CPPFLAGS += -marm -mthumb-interwork -march=armv4t -mfloat-abi=soft
LDFLAGS += -marm -march=armv4t -mfloat-abi=soft
endif
ifneq ($(SYSROOT),)
diff --git a/tools/gator/daemon/MaliVideoDriver.cpp b/tools/gator/daemon/MaliVideoDriver.cpp
index 18b413b01a37..5eef2643ab15 100644
--- a/tools/gator/daemon/MaliVideoDriver.cpp
+++ b/tools/gator/daemon/MaliVideoDriver.cpp
@@ -34,51 +34,30 @@ static const char COUNTER[] = "ARM_Mali-V500_cnt";
static const char EVENT[] = "ARM_Mali-V500_evn";
static const char ACTIVITY[] = "ARM_Mali-V500_act";
-class MaliVideoCounter {
+class MaliVideoCounter : public DriverCounter {
public:
- MaliVideoCounter(MaliVideoCounter *next, const char *name, const MaliVideoCounterType type, const int id) : mNext(next), mName(name), mType(type), mId(id), mKey(getEventKey()), mEnabled(false) {
+ MaliVideoCounter(DriverCounter *next, const char *name, const MaliVideoCounterType type, const int id) : DriverCounter(next, name), mType(type), mId(id) {
}
~MaliVideoCounter() {
- delete mName;
}
- MaliVideoCounter *getNext() const { return mNext; }
- const char *getName() const { return mName; }
MaliVideoCounterType getType() const { return mType; }
int getId() const { return mId; }
- int getKey() const { return mKey; }
- bool isEnabled() const { return mEnabled; }
- void setEnabled(const bool enabled) { mEnabled = enabled; }
private:
- MaliVideoCounter *const mNext;
- const char *const mName;
const MaliVideoCounterType mType;
// Mali Video id
const int mId;
- // Streamline key
- const int mKey;
- bool mEnabled;
};
-MaliVideoDriver::MaliVideoDriver() : mCounters(NULL), mActivityCount(0) {
+MaliVideoDriver::MaliVideoDriver() {
}
MaliVideoDriver::~MaliVideoDriver() {
- while (mCounters != NULL) {
- MaliVideoCounter *counter = mCounters;
- mCounters = counter->getNext();
- delete counter;
- }
}
-void MaliVideoDriver::setup(mxml_node_t *const xml) {
- // hwmon does not currently work with perf
- if (gSessionData->perf.isSetup()) {
- return;
- }
-
+void MaliVideoDriver::readEvents(mxml_node_t *const xml) {
mxml_node_t *node = xml;
while (true) {
node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
@@ -90,62 +69,15 @@ void MaliVideoDriver::setup(mxml_node_t *const xml) {
// Ignore
} else if (strncmp(counter, COUNTER, sizeof(COUNTER) - 1) == 0) {
const int i = strtol(counter + sizeof(COUNTER) - 1, NULL, 10);
- mCounters = new MaliVideoCounter(mCounters, strdup(counter), MVCT_COUNTER, i);
+ setCounters(new MaliVideoCounter(getCounters(), strdup(counter), MVCT_COUNTER, i));
} else if (strncmp(counter, EVENT, sizeof(EVENT) - 1) == 0) {
const int i = strtol(counter + sizeof(EVENT) - 1, NULL, 10);
- mCounters = new MaliVideoCounter(mCounters, strdup(counter), MVCT_EVENT, i);
- } else if (strcmp(counter, ACTIVITY) == 0) {
- mCounters = new MaliVideoCounter(mCounters, strdup(ACTIVITY), MVCT_ACTIVITY, 0);
- mActivityCount = 0;
- while (true) {
- char buf[32];
- snprintf(buf, sizeof(buf), "activity%i", mActivityCount + 1);
- if (mxmlElementGetAttr(node, buf) == NULL) {
- break;
- }
- ++mActivityCount;
- }
- }
- }
-}
-
-MaliVideoCounter *MaliVideoDriver::findCounter(const Counter &counter) const {
- for (MaliVideoCounter *maliVideoCounter = mCounters; maliVideoCounter != NULL; maliVideoCounter = maliVideoCounter->getNext()) {
- if (strcmp(maliVideoCounter->getName(), counter.getType()) == 0) {
- return maliVideoCounter;
- }
- }
-
- return NULL;
-}
-
-bool MaliVideoDriver::claimCounter(const Counter &counter) const {
- return findCounter(counter) != NULL;
-}
-
-bool MaliVideoDriver::countersEnabled() const {
- for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
- if (counter->isEnabled()) {
- return true;
+ setCounters(new MaliVideoCounter(getCounters(), strdup(counter), MVCT_EVENT, i));
+ } else if (strncmp(counter, ACTIVITY, sizeof(ACTIVITY) - 1) == 0) {
+ const int i = strtol(counter + sizeof(ACTIVITY) - 1, NULL, 10);
+ setCounters(new MaliVideoCounter(getCounters(), strdup(counter), MVCT_ACTIVITY, i));
}
}
- return false;
-}
-
-void MaliVideoDriver::resetCounters() {
- for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
- counter->setEnabled(false);
- }
-}
-
-void MaliVideoDriver::setupCounter(Counter &counter) {
- MaliVideoCounter *const maliVideoCounter = findCounter(counter);
- if (maliVideoCounter == NULL) {
- counter.setEnabled(false);
- return;
- }
- maliVideoCounter->setEnabled(true);
- counter.setKey(maliVideoCounter->getKey());
}
int MaliVideoDriver::writeCounters(mxml_node_t *root) const {
@@ -153,32 +85,39 @@ int MaliVideoDriver::writeCounters(mxml_node_t *root) const {
return 0;
}
- int count = 0;
- for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
- mxml_node_t *node = mxmlNewElement(root, "counter");
- mxmlElementSetAttr(node, "name", counter->getName());
- ++count;
- }
-
- return count;
+ return super::writeCounters(root);
}
void MaliVideoDriver::marshalEnable(const MaliVideoCounterType type, char *const buf, const size_t bufsize, int &pos) {
// size
int numEnabled = 0;
- for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ for (MaliVideoCounter *counter = static_cast<MaliVideoCounter *>(getCounters()); counter != NULL; counter = static_cast<MaliVideoCounter *>(counter->getNext())) {
if (counter->isEnabled() && (counter->getType() == type)) {
++numEnabled;
}
}
Buffer::packInt(buf, bufsize, pos, numEnabled*sizeof(uint32_t));
- for (MaliVideoCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
+ for (MaliVideoCounter *counter = static_cast<MaliVideoCounter *>(getCounters()); counter != NULL; counter = static_cast<MaliVideoCounter *>(counter->getNext())) {
if (counter->isEnabled() && (counter->getType() == type)) {
Buffer::packInt(buf, bufsize, pos, counter->getId());
}
}
}
+static bool writeAll(const int mveUds, const char *const buf, const int pos) {
+ int written = 0;
+ while (written < pos) {
+ size_t bytes = ::write(mveUds, buf + written, pos - written);
+ if (bytes <= 0) {
+ logg->logMessage("%s(%s:%i): write failed", __FUNCTION__, __FILE__, __LINE__);
+ return false;
+ }
+ written += bytes;
+ }
+
+ return true;
+}
+
bool MaliVideoDriver::start(const int mveUds) {
char buf[256];
int pos = 0;
@@ -225,29 +164,28 @@ bool MaliVideoDriver::start(const int mveUds) {
buf[pos++] = 'e';
marshalEnable(MVCT_EVENT, buf, sizeof(buf), pos);
- /*
// code - MVE_INSTR_ENABLE_ACTIVITIES
buf[pos++] = 'C';
buf[pos++] = 'F';
buf[pos++] = 'G';
buf[pos++] = 'a';
- // size
- Buffer::packInt(buf, sizeof(buf), pos, mActivityCount*sizeof(uint32_t));
- for (int i = 0; i < mActivityCount; ++i) {
- // activity_id
- Buffer::packInt(buf, sizeof(buf), pos, i);
- }
- */
+ marshalEnable(MVCT_ACTIVITY, buf, sizeof(buf), pos);
- int written = 0;
- while (written < pos) {
- size_t bytes = ::write(mveUds, buf + written, pos - written);
- if (bytes <= 0) {
- logg->logMessage("%s(%s:%i): write failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- written += bytes;
- }
+ return writeAll(mveUds, buf, pos);
+}
- return true;
+void MaliVideoDriver::stop(const int mveUds) {
+ char buf[8];
+ int pos = 0;
+
+ // code - MVE_INSTR_STOP
+ buf[pos++] = 'S';
+ buf[pos++] = 'T';
+ buf[pos++] = 'O';
+ buf[pos++] = 'P';
+ marshalEnable(MVCT_COUNTER, buf, sizeof(buf), pos);
+
+ writeAll(mveUds, buf, pos);
+
+ close(mveUds);
}
diff --git a/tools/gator/daemon/MaliVideoDriver.h b/tools/gator/daemon/MaliVideoDriver.h
index 00cb80889a74..204a57a447ac 100644
--- a/tools/gator/daemon/MaliVideoDriver.h
+++ b/tools/gator/daemon/MaliVideoDriver.h
@@ -19,29 +19,24 @@ enum MaliVideoCounterType {
MVCT_ACTIVITY,
};
-class MaliVideoDriver : public Driver {
+class MaliVideoDriver : public SimpleDriver {
+private:
+ typedef SimpleDriver super;
+
public:
MaliVideoDriver();
~MaliVideoDriver();
- void setup(mxml_node_t *const xml);
-
- bool claimCounter(const Counter &counter) const;
- bool countersEnabled() const;
- void resetCounters();
- void setupCounter(Counter &counter);
+ void readEvents(mxml_node_t *const root);
int writeCounters(mxml_node_t *root) const;
bool start(const int mveUds);
+ void stop(const int mveUds);
private:
- MaliVideoCounter *findCounter(const Counter &counter) const;
void marshalEnable(const MaliVideoCounterType type, char *const buf, const size_t bufsize, int &pos);
- MaliVideoCounter *mCounters;
- int mActivityCount;
-
// Intentionally unimplemented
MaliVideoDriver(const MaliVideoDriver &);
MaliVideoDriver &operator=(const MaliVideoDriver &);
diff --git a/tools/gator/daemon/MemInfoDriver.cpp b/tools/gator/daemon/MemInfoDriver.cpp
new file mode 100644
index 000000000000..cce15c16fcdc
--- /dev/null
+++ b/tools/gator/daemon/MemInfoDriver.cpp
@@ -0,0 +1,93 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "MemInfoDriver.h"
+
+#include "Logging.h"
+#include "SessionData.h"
+
+class MemInfoCounter : public DriverCounter {
+public:
+ MemInfoCounter(DriverCounter *next, char *const name, int64_t *const value);
+ ~MemInfoCounter();
+
+ int64_t read();
+
+private:
+ int64_t *const mValue;
+
+ // Intentionally unimplemented
+ MemInfoCounter(const MemInfoCounter &);
+ MemInfoCounter &operator=(const MemInfoCounter &);
+};
+
+MemInfoCounter::MemInfoCounter(DriverCounter *next, char *const name, int64_t *const value) : DriverCounter(next, name), mValue(value) {
+}
+
+MemInfoCounter::~MemInfoCounter() {
+}
+
+int64_t MemInfoCounter::read() {
+ return *mValue;
+}
+
+MemInfoDriver::MemInfoDriver() : mBuf(), mMemUsed(0), mMemFree(0), mBuffers(0) {
+}
+
+MemInfoDriver::~MemInfoDriver() {
+}
+
+void MemInfoDriver::readEvents(mxml_node_t *const) {
+ // Only for use with perf
+ if (!gSessionData->perf.isSetup()) {
+ return;
+ }
+
+ setCounters(new MemInfoCounter(getCounters(), strdup("Linux_meminfo_memused2"), &mMemUsed));
+ setCounters(new MemInfoCounter(getCounters(), strdup("Linux_meminfo_memfree"), &mMemFree));
+ setCounters(new MemInfoCounter(getCounters(), strdup("Linux_meminfo_bufferram"), &mBuffers));
+}
+
+void MemInfoDriver::read(Buffer *const buffer) {
+ if (!countersEnabled()) {
+ return;
+ }
+
+ if (!mBuf.read("/proc/meminfo")) {
+ logg->logError(__FILE__, __LINE__, "Failed to read /proc/meminfo");
+ handleException();
+ }
+
+ char *key = mBuf.getBuf();
+ char *colon;
+ int64_t memTotal = 0;
+ while ((colon = strchr(key, ':')) != NULL) {
+ char *end = strchr(colon + 1, '\n');
+ if (end != NULL) {
+ *end = '\0';
+ }
+ *colon = '\0';
+
+ if (strcmp(key, "MemTotal") == 0) {
+ memTotal = strtoll(colon + 1, NULL, 10) << 10;
+ } else if (strcmp(key, "MemFree") == 0) {
+ mMemFree = strtoll(colon + 1, NULL, 10) << 10;
+ } else if (strcmp(key, "Buffers") == 0) {
+ mBuffers = strtoll(colon + 1, NULL, 10) << 10;
+ }
+
+ if (end == NULL) {
+ break;
+ }
+ key = end + 1;
+ }
+
+ mMemUsed = memTotal - mMemFree;
+
+ super::read(buffer);
+}
diff --git a/tools/gator/daemon/MemInfoDriver.h b/tools/gator/daemon/MemInfoDriver.h
new file mode 100644
index 000000000000..eb1b0417f309
--- /dev/null
+++ b/tools/gator/daemon/MemInfoDriver.h
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MEMINFODRIVER_H
+#define MEMINFODRIVER_H
+
+#include "Driver.h"
+#include "DynBuf.h"
+
+class MemInfoDriver : public PolledDriver {
+private:
+ typedef PolledDriver super;
+
+public:
+ MemInfoDriver();
+ ~MemInfoDriver();
+
+ void readEvents(mxml_node_t *const root);
+ void read(Buffer *const buffer);
+
+private:
+ DynBuf mBuf;
+ int64_t mMemUsed;
+ int64_t mMemFree;
+ int64_t mBuffers;
+
+ // Intentionally unimplemented
+ MemInfoDriver(const MemInfoDriver &);
+ MemInfoDriver &operator=(const MemInfoDriver &);
+};
+
+#endif // MEMINFODRIVER_H
diff --git a/tools/gator/daemon/Monitor.cpp b/tools/gator/daemon/Monitor.cpp
index b34a15f0eb0c..74f22ee29fec 100644
--- a/tools/gator/daemon/Monitor.cpp
+++ b/tools/gator/daemon/Monitor.cpp
@@ -9,6 +9,7 @@
#include "Monitor.h"
#include <errno.h>
+#include <fcntl.h>
#include <string.h>
#include <unistd.h>
@@ -31,12 +32,25 @@ void Monitor::close() {
}
bool Monitor::init() {
+#ifdef EPOLL_CLOEXEC
+ mFd = epoll_create1(EPOLL_CLOEXEC);
+#else
mFd = epoll_create(16);
+#endif
if (mFd < 0) {
logg->logMessage("%s(%s:%i): epoll_create1 failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
+#ifndef EPOLL_CLOEXEC
+ int fdf = fcntl(mFd, F_GETFD);
+ if ((fdf == -1) || (fcntl(mFd, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ logg->logMessage("%s(%s:%i): fcntl failed", __FUNCTION__, __FILE__, __LINE__);
+ ::close(mFd);
+ return -1;
+ }
+#endif
+
return true;
}
diff --git a/tools/gator/daemon/NetDriver.cpp b/tools/gator/daemon/NetDriver.cpp
new file mode 100644
index 000000000000..e75c0695779a
--- /dev/null
+++ b/tools/gator/daemon/NetDriver.cpp
@@ -0,0 +1,129 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+// Define to get format macros from inttypes.h
+#define __STDC_FORMAT_MACROS
+
+#include "NetDriver.h"
+
+#include <inttypes.h>
+
+#include "Logging.h"
+#include "SessionData.h"
+
+class NetCounter : public DriverCounter {
+public:
+ NetCounter(DriverCounter *next, char *const name, int64_t *const value);
+ ~NetCounter();
+
+ int64_t read();
+
+private:
+ int64_t *const mValue;
+ int64_t mPrev;
+
+ // Intentionally unimplemented
+ NetCounter(const NetCounter &);
+ NetCounter &operator=(const NetCounter &);
+};
+
+NetCounter::NetCounter(DriverCounter *next, char *const name, int64_t *const value) : DriverCounter(next, name), mValue(value), mPrev(0) {
+}
+
+NetCounter::~NetCounter() {
+}
+
+int64_t NetCounter::read() {
+ int64_t result = *mValue - mPrev;
+ mPrev = *mValue;
+ return result;
+}
+
+NetDriver::NetDriver() : mBuf(), mReceiveBytes(0), mTransmitBytes(0) {
+}
+
+NetDriver::~NetDriver() {
+}
+
+void NetDriver::readEvents(mxml_node_t *const) {
+ // Only for use with perf
+ if (!gSessionData->perf.isSetup()) {
+ return;
+ }
+
+ setCounters(new NetCounter(getCounters(), strdup("Linux_net_rx"), &mReceiveBytes));
+ setCounters(new NetCounter(getCounters(), strdup("Linux_net_tx"), &mTransmitBytes));
+}
+
+bool NetDriver::doRead() {
+ if (!countersEnabled()) {
+ return true;
+ }
+
+ if (!mBuf.read("/proc/net/dev")) {
+ return false;
+ }
+
+ // Skip the header
+ char *key;
+ if (((key = strchr(mBuf.getBuf(), '\n')) == NULL) ||
+ ((key = strchr(key + 1, '\n')) == NULL)) {
+ return false;
+ }
+ key = key + 1;
+
+ mReceiveBytes = 0;
+ mTransmitBytes = 0;
+
+ char *colon;
+ while ((colon = strchr(key, ':')) != NULL) {
+ char *end = strchr(colon + 1, '\n');
+ if (end != NULL) {
+ *end = '\0';
+ }
+ *colon = '\0';
+
+ int64_t receiveBytes;
+ int64_t transmitBytes;
+ const int count = sscanf(colon + 1, " %" SCNu64 " %*u %*u %*u %*u %*u %*u %*u %" SCNu64, &receiveBytes, &transmitBytes);
+ if (count != 2) {
+ return false;
+ }
+ mReceiveBytes += receiveBytes;
+ mTransmitBytes += transmitBytes;
+
+ if (end == NULL) {
+ break;
+ }
+ key = end + 1;
+ }
+
+ return true;
+}
+
+void NetDriver::start() {
+ if (!doRead()) {
+ logg->logError(__FILE__, __LINE__, "Unable to read network stats");
+ handleException();
+ }
+ // Initialize previous values
+ for (DriverCounter *counter = getCounters(); counter != NULL; counter = counter->getNext()) {
+ if (!counter->isEnabled()) {
+ continue;
+ }
+ counter->read();
+ }
+}
+
+void NetDriver::read(Buffer *const buffer) {
+ if (!doRead()) {
+ logg->logError(__FILE__, __LINE__, "Unable to read network stats");
+ handleException();
+ }
+ super::read(buffer);
+}
diff --git a/tools/gator/daemon/NetDriver.h b/tools/gator/daemon/NetDriver.h
new file mode 100644
index 000000000000..50ff850bfc6d
--- /dev/null
+++ b/tools/gator/daemon/NetDriver.h
@@ -0,0 +1,39 @@
+/**
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef NETDRIVER_H
+#define NETDRIVER_H
+
+#include "Driver.h"
+#include "DynBuf.h"
+
+class NetDriver : public PolledDriver {
+private:
+ typedef PolledDriver super;
+
+public:
+ NetDriver();
+ ~NetDriver();
+
+ void readEvents(mxml_node_t *const root);
+ void start();
+ void read(Buffer *const buffer);
+
+private:
+ bool doRead();
+
+ DynBuf mBuf;
+ int64_t mReceiveBytes;
+ int64_t mTransmitBytes;
+
+ // Intentionally unimplemented
+ NetDriver(const NetDriver &);
+ NetDriver &operator=(const NetDriver &);
+};
+
+#endif // NETDRIVER_H
diff --git a/tools/gator/daemon/OlySocket.cpp b/tools/gator/daemon/OlySocket.cpp
index 28774e36e510..aa0ce4929916 100644
--- a/tools/gator/daemon/OlySocket.cpp
+++ b/tools/gator/daemon/OlySocket.cpp
@@ -15,10 +15,10 @@
#include <ws2tcpip.h>
#else
#include <netinet/in.h>
-#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <netdb.h>
+#include <fcntl.h>
#endif
#include "Logging.h"
@@ -32,6 +32,48 @@
#define SHUTDOWN_RX_TX SHUT_RDWR
#endif
+int socket_cloexec(int domain, int type, int protocol) {
+#ifdef SOCK_CLOEXEC
+ return socket(domain, type | SOCK_CLOEXEC, protocol);
+#else
+ int sock = socket(domain, type, protocol);
+#ifdef FD_CLOEXEC
+ if (sock < 0) {
+ return -1;
+ }
+ int fdf = fcntl(sock, F_GETFD);
+ if ((fdf == -1) || (fcntl(sock, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ close(sock);
+ return -1;
+ }
+#endif
+ return sock;
+#endif
+}
+
+int accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
+ int sock;
+#ifdef SOCK_CLOEXEC
+ sock = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
+ if (sock >= 0) {
+ return sock;
+ }
+ // accept4 with SOCK_CLOEXEC may not work on all kernels, so fallback
+#endif
+ sock = accept(sockfd, addr, addrlen);
+#ifdef FD_CLOEXEC
+ if (sock < 0) {
+ return -1;
+ }
+ int fdf = fcntl(sock, F_GETFD);
+ if ((fdf == -1) || (fcntl(sock, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ close(sock);
+ return -1;
+ }
+#endif
+ return sock;
+}
+
OlyServerSocket::OlyServerSocket(int port) {
#ifdef WIN32
WSADATA wsaData;
@@ -57,7 +99,7 @@ OlySocket::OlySocket(int socketID) : mSocketID(socketID) {
OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) {
// Create socket
- mFDServer = socket(PF_UNIX, SOCK_STREAM, 0);
+ mFDServer = socket_cloexec(PF_UNIX, SOCK_STREAM, 0);
if (mFDServer < 0) {
logg->logError(__FILE__, __LINE__, "Error creating server socket");
handleException();
@@ -84,7 +126,7 @@ OlyServerSocket::OlyServerSocket(const char* path, const size_t pathSize) {
}
int OlySocket::connect(const char* path, const size_t pathSize) {
- int fd = socket(PF_UNIX, SOCK_STREAM, 0);
+ int fd = socket_cloexec(PF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
return -1;
}
@@ -143,10 +185,10 @@ void OlyServerSocket::createServerSocket(int port) {
int family = AF_INET6;
// Create socket
- mFDServer = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
+ mFDServer = socket_cloexec(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
if (mFDServer < 0) {
family = AF_INET;
- mFDServer = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ mFDServer = socket_cloexec(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (mFDServer < 0) {
logg->logError(__FILE__, __LINE__, "Error creating server socket");
handleException();
@@ -190,7 +232,7 @@ int OlyServerSocket::acceptConnection() {
}
// Accept a connection, note that this call blocks until a client connects
- socketID = accept(mFDServer, NULL, NULL);
+ socketID = accept_cloexec(mFDServer, NULL, NULL);
if (socketID < 0) {
logg->logError(__FILE__, __LINE__, "Socket acceptance failed");
handleException();
diff --git a/tools/gator/daemon/OlySocket.h b/tools/gator/daemon/OlySocket.h
index 20c67cc695e1..6b53b01fc3ee 100644
--- a/tools/gator/daemon/OlySocket.h
+++ b/tools/gator/daemon/OlySocket.h
@@ -11,6 +11,12 @@
#include <stddef.h>
+#ifdef WIN32
+typedef socklen_t int;
+#else
+#include <sys/socket.h>
+#endif
+
class OlySocket {
public:
#ifndef WIN32
@@ -52,4 +58,7 @@ private:
void createServerSocket(int port);
};
+int socket_cloexec(int domain, int type, int protocol);
+int accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
+
#endif //__OLY_SOCKET_H__
diff --git a/tools/gator/daemon/PerfBuffer.cpp b/tools/gator/daemon/PerfBuffer.cpp
index 5fad583f7bd0..f127c996d43b 100644
--- a/tools/gator/daemon/PerfBuffer.cpp
+++ b/tools/gator/daemon/PerfBuffer.cpp
@@ -20,6 +20,7 @@ PerfBuffer::PerfBuffer() {
for (int cpu = 0; cpu < ARRAY_LENGTH(mBuf); ++cpu) {
mBuf[cpu] = MAP_FAILED;
mDiscard[cpu] = false;
+ mFds[cpu] = -1;
}
}
@@ -31,8 +32,8 @@ PerfBuffer::~PerfBuffer() {
}
}
-bool PerfBuffer::useFd(const int cpu, const int fd, const int groupFd) {
- if (fd == groupFd) {
+bool PerfBuffer::useFd(const int cpu, const int fd) {
+ if (mFds[cpu] < 0) {
if (mBuf[cpu] != MAP_FAILED) {
logg->logMessage("%s(%s:%i): cpu %i already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__, cpu);
return false;
@@ -44,6 +45,7 @@ bool PerfBuffer::useFd(const int cpu, const int fd, const int groupFd) {
logg->logMessage("%s(%s:%i): mmap failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
+ mFds[cpu] = fd;
// Check the version
struct perf_event_mmap_page *pemp = static_cast<struct perf_event_mmap_page *>(mBuf[cpu]);
@@ -57,7 +59,7 @@ bool PerfBuffer::useFd(const int cpu, const int fd, const int groupFd) {
return false;
}
- if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, groupFd) < 0) {
+ if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, mFds[cpu]) < 0) {
logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
@@ -89,6 +91,41 @@ bool PerfBuffer::isEmpty() {
return true;
}
+static void compressAndSend(const int cpu, const __u64 head, __u64 tail, const uint8_t *const b, Sender *const sender) {
+ // Pick a big size but something smaller than the chunkSize in Sender::writeData which is 100k
+ char buf[1<<16];
+ int writePos = 0;
+ const int typeLength = gSessionData->mLocalCapture ? 0 : 1;
+
+ while (head > tail) {
+ writePos = 0;
+ if (!gSessionData->mLocalCapture) {
+ buf[writePos++] = RESPONSE_APC_DATA;
+ }
+ // Reserve space for size
+ writePos += sizeof(uint32_t);
+ Buffer::packInt(buf, sizeof(buf), writePos, FRAME_PERF);
+ Buffer::packInt(buf, sizeof(buf), writePos, cpu);
+
+ while (head > tail) {
+ const int count = reinterpret_cast<const struct perf_event_header *>(b + (tail & BUF_MASK))->size/sizeof(uint64_t);
+ // Can this whole message be written as Streamline assumes events are not split between frames
+ if (sizeof(buf) <= writePos + count*Buffer::MAXSIZE_PACK64) {
+ break;
+ }
+ for (int i = 0; i < count; ++i) {
+ // Must account for message size
+ Buffer::packInt64(buf, sizeof(buf), writePos, *reinterpret_cast<const uint64_t *>(b + (tail & BUF_MASK)));
+ tail += sizeof(uint64_t);
+ }
+ }
+
+ // Write size
+ Buffer::writeLEInt(reinterpret_cast<unsigned char *>(buf + typeLength), writePos - typeLength - sizeof(uint32_t));
+ sender->writeData(buf, writePos, RESPONSE_APC_DATA);
+ }
+}
+
bool PerfBuffer::send(Sender *const sender) {
for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
if (mBuf[cpu] == MAP_FAILED) {
@@ -102,26 +139,7 @@ bool PerfBuffer::send(Sender *const sender) {
if (head > tail) {
const uint8_t *const b = static_cast<uint8_t *>(mBuf[cpu]) + gSessionData->mPageSize;
- const int offset = gSessionData->mLocalCapture ? 1 : 0;
- unsigned char header[7];
- header[0] = RESPONSE_APC_DATA;
- Buffer::writeLEInt(header + 1, head - tail + sizeof(header) - 5);
- // Should use real packing functions
- header[5] = FRAME_PERF;
- header[6] = cpu;
-
- // Write header
- sender->writeData(reinterpret_cast<const char *>(&header) + offset, sizeof(header) - offset, RESPONSE_APC_DATA);
-
- // Write data
- if ((head & ~BUF_MASK) == (tail & ~BUF_MASK)) {
- // Not wrapped
- sender->writeData(reinterpret_cast<const char *>(b + (tail & BUF_MASK)), head - tail, RESPONSE_APC_DATA);
- } else {
- // Wrapped
- sender->writeData(reinterpret_cast<const char *>(b + (tail & BUF_MASK)), BUF_SIZE - (tail & BUF_MASK), RESPONSE_APC_DATA);
- sender->writeData(reinterpret_cast<const char *>(b), head & BUF_MASK, RESPONSE_APC_DATA);
- }
+ compressAndSend(cpu, head, tail, b, sender);
// Update tail with the data read
pemp->data_tail = head;
@@ -131,6 +149,7 @@ bool PerfBuffer::send(Sender *const sender) {
munmap(mBuf[cpu], gSessionData->mPageSize + BUF_SIZE);
mBuf[cpu] = MAP_FAILED;
mDiscard[cpu] = false;
+ mFds[cpu] = -1;
logg->logMessage("%s(%s:%i): Unmaped cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);
}
}
diff --git a/tools/gator/daemon/PerfBuffer.h b/tools/gator/daemon/PerfBuffer.h
index 278a3b9d6db7..25a10625a9e8 100644
--- a/tools/gator/daemon/PerfBuffer.h
+++ b/tools/gator/daemon/PerfBuffer.h
@@ -21,7 +21,7 @@ public:
PerfBuffer();
~PerfBuffer();
- bool useFd(const int cpu, const int fd, const int groupFd);
+ bool useFd(const int cpu, const int fd);
void discard(const int cpu);
bool isEmpty();
bool send(Sender *const sender);
@@ -30,6 +30,8 @@ private:
void *mBuf[NR_CPUS];
// After the buffer is flushed it should be unmaped
bool mDiscard[NR_CPUS];
+ // fd that corresponds to the mBuf
+ int mFds[NR_CPUS];
// Intentionally undefined
PerfBuffer(const PerfBuffer &);
diff --git a/tools/gator/daemon/PerfDriver.cpp b/tools/gator/daemon/PerfDriver.cpp
index ac97a077d266..ee90284cee41 100644
--- a/tools/gator/daemon/PerfDriver.cpp
+++ b/tools/gator/daemon/PerfDriver.cpp
@@ -22,6 +22,7 @@
#include "Logging.h"
#include "PerfGroup.h"
#include "SessionData.h"
+#include "Setup.h"
#define PERF_DEVICES "/sys/bus/event_source/devices"
@@ -47,7 +48,6 @@ static const struct gator_cpu gator_cpus[] = {
{ 0xc07, "Cortex-A7", "ARMv7_Cortex_A7", 4 },
{ 0xc08, "Cortex-A8", "ARMv7_Cortex_A8", 4 },
{ 0xc09, "Cortex-A9", "ARMv7_Cortex_A9", 6 },
- { 0xc0d, "Cortex-A12", "ARMv7_Cortex_A12", 6 },
{ 0xc0f, "Cortex-A15", "ARMv7_Cortex_A15", 6 },
{ 0xc0e, "Cortex-A17", "ARMv7_Cortex_A17", 6 },
{ 0x00f, "Scorpion", "Scorpion", 4 },
@@ -64,68 +64,57 @@ static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-";
static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_";
struct uncore_counter {
- // gatorfs event and Perf PMU name
- const char *const name;
+ // Perf PMU name
+ const char *const perfName;
+ // gatorfs event name
+ const char *const gatorName;
const int count;
};
static const struct uncore_counter uncore_counters[] = {
- { "CCI_400", 4 },
- { "CCI_400-r1", 4 },
+ { "CCI_400", "CCI_400", 4 },
+ { "CCI_400-r1", "CCI_400-r1", 4 },
+ { "ccn", "ARM_CCN_5XX", 8 },
};
-class PerfCounter {
+class PerfCounter : public DriverCounter {
public:
- 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) {}
+ PerfCounter(DriverCounter *next, const char *name, uint32_t type, uint64_t config, bool perCpu) : DriverCounter(next, name), mType(type), mCount(0), mConfig(config), mPerCpu(perCpu) {}
+
~PerfCounter() {
- delete [] mName;
}
- PerfCounter *getNext() const { return mNext; }
- const char *getName() const { return mName; }
uint32_t getType() const { return mType; }
int getCount() const { return mCount; }
void setCount(const int count) { mCount = count; }
- int getKey() const { return mKey; }
uint64_t getConfig() const { return mConfig; }
void setConfig(const uint64_t config) { mConfig = config; }
- bool isEnabled() const { return mEnabled; }
- void setEnabled(const bool enabled) { mEnabled = enabled; }
bool isPerCpu() const { return mPerCpu; }
private:
- PerfCounter *const mNext;
- const char *const mName;
const uint32_t mType;
int mCount;
- const int mKey;
uint64_t mConfig;
- int mEnabled : 1,
- mPerCpu : 1;
+ bool mPerCpu;
};
-PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false), mLegacySupport(false) {
+PerfDriver::PerfDriver() : mIsSetup(false), mLegacySupport(false) {
}
PerfDriver::~PerfDriver() {
- while (mCounters != NULL) {
- PerfCounter *counter = mCounters;
- mCounters = counter->getNext();
- delete counter;
- }
}
void PerfDriver::addCpuCounters(const char *const counterName, const int type, const int numCounters) {
int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1;
char *name = new char[len];
snprintf(name, len, "%s_ccnt", counterName);
- mCounters = new PerfCounter(mCounters, name, type, -1, true);
+ setCounters(new PerfCounter(getCounters(), name, type, -1, true));
for (int j = 0; j < numCounters; ++j) {
len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1;
name = new char[len];
snprintf(name, len, "%s_cnt%d", counterName, j);
- mCounters = new PerfCounter(mCounters, name, type, -1, true);
+ setCounters(new PerfCounter(getCounters(), name, type, -1, true));
}
}
@@ -133,40 +122,24 @@ void PerfDriver::addUncoreCounters(const char *const counterName, const int type
int len = snprintf(NULL, 0, "%s_ccnt", counterName) + 1;
char *name = new char[len];
snprintf(name, len, "%s_ccnt", counterName);
- mCounters = new PerfCounter(mCounters, name, type, -1, false);
+ setCounters(new PerfCounter(getCounters(), name, type, -1, false));
for (int j = 0; j < numCounters; ++j) {
len = snprintf(NULL, 0, "%s_cnt%d", counterName, j) + 1;
name = new char[len];
snprintf(name, len, "%s_cnt%d", counterName, j);
- mCounters = new PerfCounter(mCounters, name, type, -1, false);
+ setCounters(new PerfCounter(getCounters(), name, type, -1, false));
}
}
-// From include/generated/uapi/linux/version.h
-#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
-
bool PerfDriver::setup() {
// Check the kernel version
- struct utsname utsname;
- if (uname(&utsname) != 0) {
- logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__);
+ int release[3];
+ if (!getLinuxVersion(release)) {
+ logg->logMessage("%s(%s:%i): getLinuxVersion failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
- int release[3] = { 0, 0, 0 };
- int part = 0;
- char *ch = utsname.release;
- while (*ch >= '0' && *ch <= '9' && part < ARRAY_LENGTH(release)) {
- release[part] = 10*release[part] + *ch - '0';
-
- ++ch;
- if (*ch == '.') {
- ++part;
- ++ch;
- }
- }
-
if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 4, 0)) {
logg->logMessage("%s(%s:%i): Unsupported kernel version", __FUNCTION__, __FILE__, __LINE__);
return false;
@@ -174,7 +147,7 @@ bool PerfDriver::setup() {
mLegacySupport = KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0);
if (access(EVENTS_PATH, R_OK) != 0) {
- logg->logMessage("%s(%s:%i): " EVENTS_PATH " does not exist, is CONFIG_TRACING enabled?", __FUNCTION__, __FILE__, __LINE__);
+ logg->logMessage("%s(%s:%i): " EVENTS_PATH " does not exist, is CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER enabled?", __FUNCTION__, __FILE__, __LINE__);
return false;
}
@@ -189,12 +162,14 @@ bool PerfDriver::setup() {
struct dirent *dirent;
while ((dirent = readdir(dir)) != NULL) {
for (int i = 0; i < ARRAY_LENGTH(gator_cpus); ++i) {
+ const struct gator_cpu *const gator_cpu = &gator_cpus[i];
+
// Do the names match exactly?
- if (strcmp(dirent->d_name, gator_cpus[i].pmnc_name) != 0 &&
- // Do these names match but have the old vs new prefix?
- (strncmp(dirent->d_name, OLD_PMU_PREFIX, sizeof(OLD_PMU_PREFIX) - 1) != 0 ||
- strncmp(gator_cpus[i].pmnc_name, NEW_PMU_PREFIX, sizeof(NEW_PMU_PREFIX) - 1) != 0 ||
- strcmp(dirent->d_name + sizeof(OLD_PMU_PREFIX) - 1, gator_cpus[i].pmnc_name + sizeof(NEW_PMU_PREFIX) - 1) != 0)) {
+ if (strcasecmp(gator_cpu->pmnc_name, dirent->d_name) != 0 &&
+ // Do these names match but have the old vs new prefix?
+ ((strncasecmp(dirent->d_name, OLD_PMU_PREFIX, sizeof(OLD_PMU_PREFIX) - 1) != 0 ||
+ strncasecmp(gator_cpu->pmnc_name, NEW_PMU_PREFIX, sizeof(NEW_PMU_PREFIX) - 1) != 0 ||
+ strcasecmp(dirent->d_name + sizeof(OLD_PMU_PREFIX) - 1, gator_cpu->pmnc_name + sizeof(NEW_PMU_PREFIX) - 1) != 0))) {
continue;
}
@@ -206,11 +181,12 @@ bool PerfDriver::setup() {
}
foundCpu = true;
- addCpuCounters(gator_cpus[i].pmnc_name, type, gator_cpus[i].pmnc_counters);
+ logg->logMessage("Adding cpu counters for %s", gator_cpu->pmnc_name);
+ addCpuCounters(gator_cpu->pmnc_name, type, gator_cpu->pmnc_counters);
}
for (int i = 0; i < ARRAY_LENGTH(uncore_counters); ++i) {
- if (strcmp(dirent->d_name, uncore_counters[i].name) != 0) {
+ if (strcmp(dirent->d_name, uncore_counters[i].perfName) != 0) {
continue;
}
@@ -221,7 +197,8 @@ bool PerfDriver::setup() {
continue;
}
- addUncoreCounters(uncore_counters[i].name, type, uncore_counters[i].count);
+ logg->logMessage("Adding uncore counters for %s", uncore_counters[i].gatorName);
+ addUncoreCounters(uncore_counters[i].gatorName, type, uncore_counters[i].count);
}
}
closedir(dir);
@@ -234,6 +211,7 @@ bool PerfDriver::setup() {
}
foundCpu = true;
+ logg->logMessage("Adding cpu counters (based on cpuid) for %s", gator_cpus[i].pmnc_name);
addCpuCounters(gator_cpus[i].pmnc_name, PERF_TYPE_RAW, gator_cpus[i].pmnc_counters);
}
}
@@ -252,31 +230,20 @@ bool PerfDriver::setup() {
id = getTracepointId("irq/softirq_exit", &printb);
if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, true);
+ setCounters(new PerfCounter(getCounters(), "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id, true));
}
id = getTracepointId("irq/irq_handler_exit", &printb);
if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, true);
+ setCounters(new PerfCounter(getCounters(), "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, true));
}
- //Linux_block_rq_wr
- //Linux_block_rq_rd
- //Linux_net_rx
- //Linux_net_tx
-
id = getTracepointId(SCHED_SWITCH, &printb);
if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true);
+ setCounters(new PerfCounter(getCounters(), "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true));
}
- //Linux_meminfo_memused
- //Linux_meminfo_memfree
- //Linux_meminfo_bufferram
- //Linux_power_cpu_freq
- //Linux_power_cpu_idle
-
- mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false);
+ setCounters(new PerfCounter(getCounters(), "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false));
//Linux_cpu_wait_io
@@ -299,62 +266,48 @@ bool PerfDriver::summary(Buffer *const buffer) {
logg->logMessage("%s(%s:%i): clock_gettime failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
- const int64_t timestamp = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec;
+ const int64_t timestamp = (int64_t)ts.tv_sec * NS_PER_S + ts.tv_nsec;
- const int64_t uptime = getTime();
+ const uint64_t monotonicStarted = getTime();
+ gSessionData->mMonotonicStarted = monotonicStarted;
- buffer->summary(timestamp, uptime, 0, buf);
+ buffer->summary(monotonicStarted, timestamp, monotonicStarted, monotonicStarted, buf);
for (int i = 0; i < gSessionData->mCores; ++i) {
- // Don't send information on a cpu we know nothing about
- if (gSessionData->mCpuIds[i] == -1) {
- continue;
- }
-
- int j;
- for (j = 0; j < ARRAY_LENGTH(gator_cpus); ++j) {
- if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) {
- break;
- }
- }
- if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) {
- buffer->coreName(i, gSessionData->mCpuIds[i], gator_cpus[j].core_name);
- } else {
- if (gSessionData->mCpuIds[i] == -1) {
- snprintf(buf, sizeof(buf), "Unknown");
- } else {
- snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[i]);
- }
- buffer->coreName(i, gSessionData->mCpuIds[i], buf);
- }
+ coreName(monotonicStarted, buffer, i);
}
- buffer->commit(1);
+ buffer->commit(monotonicStarted);
return true;
}
-PerfCounter *PerfDriver::findCounter(const Counter &counter) const {
- for (PerfCounter * perfCounter = mCounters; perfCounter != NULL; perfCounter = perfCounter->getNext()) {
- if (strcmp(perfCounter->getName(), counter.getType()) == 0) {
- return perfCounter;
- }
+void PerfDriver::coreName(const uint32_t startTime, Buffer *const buffer, const int cpu) {
+ // Don't send information on a cpu we know nothing about
+ if (gSessionData->mCpuIds[cpu] == -1) {
+ return;
}
- return NULL;
-}
-
-bool PerfDriver::claimCounter(const Counter &counter) const {
- return findCounter(counter) != NULL;
-}
-
-void PerfDriver::resetCounters() {
- for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
- counter->setEnabled(false);
+ int j;
+ for (j = 0; j < ARRAY_LENGTH(gator_cpus); ++j) {
+ if (gator_cpus[j].cpuid == gSessionData->mCpuIds[cpu]) {
+ break;
+ }
+ }
+ if (gator_cpus[j].cpuid == gSessionData->mCpuIds[cpu]) {
+ buffer->coreName(startTime, cpu, gSessionData->mCpuIds[cpu], gator_cpus[j].core_name);
+ } else {
+ char buf[32];
+ if (gSessionData->mCpuIds[cpu] == -1) {
+ snprintf(buf, sizeof(buf), "Unknown");
+ } else {
+ snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[cpu]);
+ }
+ buffer->coreName(startTime, cpu, gSessionData->mCpuIds[cpu], buf);
}
}
void PerfDriver::setupCounter(Counter &counter) {
- PerfCounter *const perfCounter = findCounter(counter);
+ PerfCounter *const perfCounter = static_cast<PerfCounter *>(findCounter(counter));
if (perfCounter == NULL) {
counter.setEnabled(false);
return;
@@ -369,21 +322,10 @@ void PerfDriver::setupCounter(Counter &counter) {
counter.setKey(perfCounter->getKey());
}
-int PerfDriver::writeCounters(mxml_node_t *root) const {
- int count = 0;
- for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
- mxml_node_t *node = mxmlNewElement(root, "counter");
- mxmlElementSetAttr(node, "name", counter->getName());
- ++count;
- }
-
- return count;
-}
-
-bool PerfDriver::enable(PerfGroup *const group, Buffer *const buffer) const {
- for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
+bool PerfDriver::enable(const uint64_t currTime, PerfGroup *const group, Buffer *const buffer) const {
+ for (PerfCounter *counter = static_cast<PerfCounter *>(getCounters()); counter != NULL; counter = static_cast<PerfCounter *>(counter->getNext())) {
if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) {
- 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)) {
+ if (!group->add(currTime, 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)) {
logg->logMessage("%s(%s:%i): PerfGroup::add failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
diff --git a/tools/gator/daemon/PerfDriver.h b/tools/gator/daemon/PerfDriver.h
index 2cae575a7059..846203a9e18b 100644
--- a/tools/gator/daemon/PerfDriver.h
+++ b/tools/gator/daemon/PerfDriver.h
@@ -9,6 +9,8 @@
#ifndef PERFDRIVER_H
#define PERFDRIVER_H
+#include <stdint.h>
+
#include "Driver.h"
// If debugfs is not mounted at /sys/kernel/debug, update DEBUGFS_PATH
@@ -16,13 +18,13 @@
#define EVENTS_PATH DEBUGFS_PATH "/tracing/events"
#define SCHED_SWITCH "sched/sched_switch"
+#define CPU_IDLE "power/cpu_idle"
class Buffer;
class DynBuf;
-class PerfCounter;
class PerfGroup;
-class PerfDriver : public Driver {
+class PerfDriver : public SimpleDriver {
public:
PerfDriver();
~PerfDriver();
@@ -31,24 +33,19 @@ public:
bool setup();
bool summary(Buffer *const buffer);
+ void coreName(const uint32_t startTime, Buffer *const buffer, const int cpu);
bool isSetup() const { return mIsSetup; }
- bool claimCounter(const Counter &counter) const;
- void resetCounters();
void setupCounter(Counter &counter);
- int writeCounters(mxml_node_t *root) const;
-
- bool enable(PerfGroup *const group, Buffer *const buffer) const;
+ bool enable(const uint64_t currTime, PerfGroup *const group, Buffer *const buffer) const;
static long long getTracepointId(const char *const name, DynBuf *const printb);
private:
- PerfCounter *findCounter(const Counter &counter) const;
void addCpuCounters(const char *const counterName, const int type, const int numCounters);
void addUncoreCounters(const char *const counterName, const int type, const int numCounters);
- PerfCounter *mCounters;
bool mIsSetup;
bool mLegacySupport;
diff --git a/tools/gator/daemon/PerfGroup.cpp b/tools/gator/daemon/PerfGroup.cpp
index 2a0239f7c348..4fd960a9058c 100644
--- a/tools/gator/daemon/PerfGroup.cpp
+++ b/tools/gator/daemon/PerfGroup.cpp
@@ -9,6 +9,7 @@
#include "PerfGroup.h"
#include <errno.h>
+#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
@@ -33,10 +34,19 @@
/* have a sampling interrupt happen when we cross the wakeup_watermark boundary */ \
pea.watermark = 1; \
/* Be conservative in flush size as only one buffer set is monitored */ \
- pea.wakeup_watermark = 3 * BUF_SIZE / 4
+ pea.wakeup_watermark = BUF_SIZE / 2
static int sys_perf_event_open(struct perf_event_attr *const attr, const pid_t pid, const int cpu, const int group_fd, const unsigned long flags) {
- return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
+ int fd = syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
+ if (fd < 0) {
+ return -1;
+ }
+ int fdf = fcntl(fd, F_GETFD);
+ if ((fdf == -1) || (fcntl(fd, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ close(fd);
+ return -1;
+ }
+ return fd;
}
PerfGroup::PerfGroup(PerfBuffer *const pb) : mPb(pb) {
@@ -54,7 +64,7 @@ PerfGroup::~PerfGroup() {
}
}
-bool PerfGroup::add(Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags) {
+bool PerfGroup::add(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags) {
int i;
for (i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
if (mKeys[i] < 0) {
@@ -82,12 +92,12 @@ bool PerfGroup::add(Buffer *const buffer, const int key, const __u32 type, const
mKeys[i] = key;
- buffer->pea(&mAttrs[i], key);
+ buffer->pea(currTime, &mAttrs[i], key);
return true;
}
-bool PerfGroup::prepareCPU(const int cpu) {
+int PerfGroup::prepareCPU(const int cpu, Monitor *const monitor) {
logg->logMessage("%s(%s:%i): Onlining cpu %i", __FUNCTION__, __FILE__, __LINE__, cpu);
for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
@@ -102,26 +112,35 @@ bool PerfGroup::prepareCPU(const int cpu) {
const int offset = i * gSessionData->mCores;
if (mFds[cpu + offset] >= 0) {
logg->logMessage("%s(%s:%i): cpu already online or not correctly cleaned up", __FUNCTION__, __FILE__, __LINE__);
- return false;
+ return PG_FAILURE;
}
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);
mFds[cpu + offset] = sys_perf_event_open(&mAttrs[i], -1, cpu, i == 0 ? -1 : mFds[cpu], i == 0 ? 0 : PERF_FLAG_FD_OUTPUT);
if (mFds[cpu + offset] < 0) {
logg->logMessage("%s(%s:%i): failed %s", __FUNCTION__, __FILE__, __LINE__, strerror(errno));
+ if (errno == ENODEV) {
+ return PG_CPU_OFFLINE;
+ }
continue;
}
- if (!mPb->useFd(cpu, mFds[cpu + offset], mFds[cpu])) {
+ if (!mPb->useFd(cpu, mFds[cpu + offset])) {
logg->logMessage("%s(%s:%i): PerfBuffer::useFd failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
+ return PG_FAILURE;
+ }
+
+
+ if (!monitor->add(mFds[cpu + offset])) {
+ logg->logMessage("%s(%s:%i): Monitor::add failed", __FUNCTION__, __FILE__, __LINE__);
+ return PG_FAILURE;
}
}
- return true;
+ return PG_SUCCESS;
}
-int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer, Monitor *const monitor) {
+int PerfGroup::onlineCPU(const uint64_t currTime, const int cpu, const bool start, Buffer *const buffer) {
__u64 ids[ARRAY_LENGTH(mKeys)];
int coreKeys[ARRAY_LENGTH(mKeys)];
int idCount = 0;
@@ -137,38 +156,37 @@ int PerfGroup::onlineCPU(const int cpu, const bool start, Buffer *const buffer,
// Workaround for running 32-bit gatord on 64-bit systems, kernel patch in the works
ioctl(fd, (PERF_EVENT_IOC_ID & ~IOCSIZE_MASK) | (8 << _IOC_SIZESHIFT), &ids[idCount]) != 0) {
logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
+ return 0;
}
++idCount;
}
- if (!monitor->add(mFds[cpu])) {
- logg->logMessage("%s(%s:%i): Monitor::add failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
if (!gSessionData->perf.getLegacySupport()) {
- buffer->keys(idCount, ids, coreKeys);
+ buffer->keys(currTime, idCount, ids, coreKeys);
} else {
char buf[1024];
ssize_t bytes = read(mFds[cpu], buf, sizeof(buf));
if (bytes < 0) {
logg->logMessage("read failed");
- return false;
+ return 0;
}
- buffer->keysOld(idCount, coreKeys, bytes, buf);
+ buffer->keysOld(currTime, idCount, coreKeys, bytes, buf);
}
if (start) {
for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
int offset = i * gSessionData->mCores + cpu;
- if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_ENABLE) < 0) {
+ if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_ENABLE, 0) < 0) {
logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
+ return 0;
}
}
}
+ if (idCount == 0) {
+ logg->logMessage("%s(%s:%i): no events came online", __FUNCTION__, __FILE__, __LINE__);
+ }
+
return idCount;
}
@@ -177,7 +195,7 @@ bool PerfGroup::offlineCPU(const int cpu) {
for (int i = 0; i < ARRAY_LENGTH(mKeys); ++i) {
int offset = i * gSessionData->mCores + cpu;
- if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_DISABLE) < 0) {
+ if (mFds[offset] >= 0 && ioctl(mFds[offset], PERF_EVENT_IOC_DISABLE, 0) < 0) {
logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
@@ -203,7 +221,7 @@ bool PerfGroup::offlineCPU(const int cpu) {
bool PerfGroup::start() {
for (int pos = 0; pos < ARRAY_LENGTH(mFds); ++pos) {
- if (mFds[pos] >= 0 && ioctl(mFds[pos], PERF_EVENT_IOC_ENABLE) < 0) {
+ if (mFds[pos] >= 0 && ioctl(mFds[pos], PERF_EVENT_IOC_ENABLE, 0) < 0) {
logg->logMessage("%s(%s:%i): ioctl failed", __FUNCTION__, __FILE__, __LINE__);
goto fail;
}
@@ -220,7 +238,7 @@ bool PerfGroup::start() {
void PerfGroup::stop() {
for (int pos = ARRAY_LENGTH(mFds) - 1; pos >= 0; --pos) {
if (mFds[pos] >= 0) {
- ioctl(mFds[pos], PERF_EVENT_IOC_DISABLE);
+ ioctl(mFds[pos], PERF_EVENT_IOC_DISABLE, 0);
}
}
}
diff --git a/tools/gator/daemon/PerfGroup.h b/tools/gator/daemon/PerfGroup.h
index 3f1e2bb4d1c8..f7b3d725bac7 100644
--- a/tools/gator/daemon/PerfGroup.h
+++ b/tools/gator/daemon/PerfGroup.h
@@ -9,6 +9,8 @@
#ifndef PERF_GROUP
#define PERF_GROUP
+#include <stdint.h>
+
// Use a snapshot of perf_event.h as it may be more recent than what is on the target and if not newer features won't be supported anyways
#include "k/perf_event.h"
@@ -27,16 +29,22 @@ enum PerfGroupFlags {
PERF_GROUP_PER_CPU = 1 << 5,
};
+enum {
+ PG_SUCCESS = 0,
+ PG_FAILURE,
+ PG_CPU_OFFLINE,
+};
+
class PerfGroup {
public:
PerfGroup(PerfBuffer *const pb);
~PerfGroup();
- bool add(Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags);
+ bool add(const uint64_t currTime, Buffer *const buffer, const int key, const __u32 type, const __u64 config, const __u64 sample, const __u64 sampleType, const int flags);
// Safe to call concurrently
- bool prepareCPU(const int cpu);
+ int prepareCPU(const int cpu, Monitor *const monitor);
// Not safe to call concurrently. Returns the number of events enabled
- int onlineCPU(const int cpu, const bool start, Buffer *const buffer, Monitor *const monitor);
+ int onlineCPU(const uint64_t currTime, const int cpu, const bool start, Buffer *const buffer);
bool offlineCPU(int cpu);
bool start();
void stop();
diff --git a/tools/gator/daemon/PerfSource.cpp b/tools/gator/daemon/PerfSource.cpp
index ecfaa66832bd..193b7789a290 100644
--- a/tools/gator/daemon/PerfSource.cpp
+++ b/tools/gator/daemon/PerfSource.cpp
@@ -8,8 +8,14 @@
#include "PerfSource.h"
+#include <dirent.h>
#include <errno.h>
+#include <signal.h>
#include <string.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
#include <unistd.h>
#include "Child.h"
@@ -19,11 +25,13 @@
#include "Proc.h"
#include "SessionData.h"
-#define MS_PER_US 1000000
+#ifndef SCHED_RESET_ON_FORK
+#define SCHED_RESET_ON_FORK 0x40000000
+#endif
extern Child *child;
-static bool sendTracepointFormat(Buffer *const buffer, const char *const name, DynBuf *const printb, DynBuf *const b) {
+static bool sendTracepointFormat(const uint64_t currTime, Buffer *const buffer, const char *const name, DynBuf *const printb, DynBuf *const b) {
if (!printb->printf(EVENTS_PATH "/%s/format", name)) {
logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
return false;
@@ -32,47 +40,112 @@ static bool sendTracepointFormat(Buffer *const buffer, const char *const name, D
logg->logMessage("%s(%s:%i): DynBuf::read failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
- buffer->format(b->getLength(), b->getBuf());
+ buffer->format(currTime, b->getLength(), b->getBuf());
return true;
}
-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) {
- long l = sysconf(_SC_PAGE_SIZE);
- if (l < 0) {
- logg->logError(__FILE__, __LINE__, "Unable to obtain the page size");
+static void *syncFunc(void *arg)
+{
+ struct timespec ts;
+ int64_t nextTime = gSessionData->mMonotonicStarted;
+ int err;
+ (void)arg;
+
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-sync", 0, 0, 0);
+
+ // Mask all signals so that this thread will not be woken up
+ {
+ sigset_t set;
+ if (sigfillset(&set) != 0) {
+ logg->logError(__FILE__, __LINE__, "sigfillset failed");
+ handleException();
+ }
+ if ((err = pthread_sigmask(SIG_SETMASK, &set, NULL)) != 0) {
+ logg->logError(__FILE__, __LINE__, "pthread_sigmask failed");
+ handleException();
+ }
+ }
+
+ for (;;) {
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
+ logg->logError(__FILE__, __LINE__, "clock_gettime failed");
+ handleException();
+ }
+ const int64_t currTime = ts.tv_sec * NS_PER_S + ts.tv_nsec;
+
+ // Wake up once a second
+ nextTime += NS_PER_S;
+
+ // Always sleep more than 1 ms, hopefully things will line up better next time
+ const int64_t sleepTime = max(nextTime - currTime, (int64_t)(NS_PER_MS + 1));
+ ts.tv_sec = sleepTime/NS_PER_S;
+ ts.tv_nsec = sleepTime % NS_PER_S;
+
+ err = nanosleep(&ts, NULL);
+ if (err != 0) {
+ fprintf(stderr, "clock_nanosleep failed: %s\n", strerror(err));
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+static long getMaxCoreNum() {
+ DIR *dir = opendir("/sys/devices/system/cpu");
+ if (dir == NULL) {
+ logg->logError(__FILE__, __LINE__, "Unable to determine the number of cores on the target, opendir failed");
handleException();
}
- gSessionData->mPageSize = static_cast<int>(l);
- l = sysconf(_SC_NPROCESSORS_CONF);
- if (l < 0) {
- logg->logError(__FILE__, __LINE__, "Unable to obtain the number of cores");
+ long maxCoreNum = -1;
+ struct dirent *dirent;
+ while ((dirent = readdir(dir)) != NULL) {
+ if (strncmp(dirent->d_name, "cpu", 3) == 0) {
+ char *endptr;
+ errno = 0;
+ long coreNum = strtol(dirent->d_name + 3, &endptr, 10);
+ if ((errno == 0) && (*endptr == '\0') && (coreNum >= maxCoreNum)) {
+ maxCoreNum = coreNum + 1;
+ }
+ }
+ }
+ closedir(dir);
+
+ if (maxCoreNum < 1) {
+ logg->logError(__FILE__, __LINE__, "Unable to determine the number of cores on the target, no cpu# directories found");
handleException();
}
- gSessionData->mCores = static_cast<int>(l);
-}
-PerfSource::~PerfSource() {
+ if (maxCoreNum >= NR_CPUS) {
+ logg->logError(__FILE__, __LINE__, "Too many cores on the target, please increase NR_CPUS in Config.h");
+ handleException();
+ }
+
+ return maxCoreNum;
}
-struct PrepareParallelArgs {
- PerfGroup *pg;
- int cpu;
-};
+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), mIdleGroup(&mCountersBuf), mMonitor(), mUEvent(), mSenderSem(senderSem), mStartProfile(startProfile), mInterruptFd(-1), mIsDone(false) {
+ long l = sysconf(_SC_PAGE_SIZE);
+ if (l < 0) {
+ logg->logError(__FILE__, __LINE__, "Unable to obtain the page size");
+ handleException();
+ }
+ gSessionData->mPageSize = static_cast<int>(l);
+ gSessionData->mCores = static_cast<int>(getMaxCoreNum());
+}
-void *prepareParallel(void *arg) {
- const PrepareParallelArgs *const args = (PrepareParallelArgs *)arg;
- args->pg->prepareCPU(args->cpu);
- return NULL;
+PerfSource::~PerfSource() {
}
bool PerfSource::prepare() {
DynBuf printb;
DynBuf b1;
- DynBuf b2;
- DynBuf b3;
long long schedSwitchId;
+ long long cpuIdleId;
+
+ const uint64_t currTime = getTime();
// Reread cpuinfo since cores may have changed since startup
gSessionData->readCpuInfo();
@@ -83,76 +156,146 @@ bool PerfSource::prepare() {
|| !mMonitor.add(mUEvent.getFd())
|| (schedSwitchId = PerfDriver::getTracepointId(SCHED_SWITCH, &printb)) < 0
- || !sendTracepointFormat(&mBuffer, SCHED_SWITCH, &printb, &b1)
+ || !sendTracepointFormat(currTime, &mBuffer, SCHED_SWITCH, &printb, &b1)
+
+ || (cpuIdleId = PerfDriver::getTracepointId(CPU_IDLE, &printb)) < 0
+ || !sendTracepointFormat(currTime, &mBuffer, CPU_IDLE, &printb, &b1)
// Only want RAW but not IP on sched_switch and don't want TID on SAMPLE_ID
- || !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)
+ || !mCountersGroup.add(currTime, &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)
+ || !mIdleGroup.add(currTime, &mBuffer, 101/**/, PERF_TYPE_TRACEPOINT, cpuIdleId, 1, PERF_SAMPLE_RAW, PERF_GROUP_PER_CPU)
// Only want TID and IP but not RAW on timer
- || (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))
+ || (gSessionData->mSampleRate > 0 && !gSessionData->mIsEBS && !mCountersGroup.add(currTime, &mBuffer, 102/**/, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, 1000000000UL / gSessionData->mSampleRate, PERF_SAMPLE_TID | PERF_SAMPLE_IP, PERF_GROUP_PER_CPU))
- || !gSessionData->perf.enable(&mCountersGroup, &mBuffer)
+ || !gSessionData->perf.enable(currTime, &mCountersGroup, &mBuffer)
|| 0) {
logg->logMessage("%s(%s:%i): perf setup failed, are you running Linux 3.4 or later?", __FUNCTION__, __FILE__, __LINE__);
return false;
}
- if (!gSessionData->perf.summary(&mSummary)) {
- logg->logMessage("%s(%s:%i): PerfDriver::summary failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
-
- {
- // Run prepareCPU in parallel as perf_event_open can take more than 1 sec in some cases
- pthread_t threads[NR_CPUS];
- PrepareParallelArgs args[NR_CPUS];
- for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
- args[cpu].pg = &mCountersGroup;
- args[cpu].cpu = cpu;
- if (pthread_create(&threads[cpu], NULL, prepareParallel, &args[cpu]) != 0) {
- logg->logMessage("%s(%s:%i): pthread_create failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
+ for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
+ const int result = mCountersGroup.prepareCPU(cpu, &mMonitor);
+ if ((result != PG_SUCCESS) && (result != PG_CPU_OFFLINE)) {
+ logg->logError(__FILE__, __LINE__, "PerfGroup::prepareCPU on mCountersGroup failed");
+ handleException();
}
- for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
- if (pthread_join(threads[cpu], NULL) != 0) {
- logg->logMessage("%s(%s:%i): pthread_join failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
+ }
+ for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
+ const int result = mIdleGroup.prepareCPU(cpu, &mMonitor);
+ if ((result != PG_SUCCESS) && (result != PG_CPU_OFFLINE)) {
+ logg->logError(__FILE__, __LINE__, "PerfGroup::prepareCPU on mIdleGroup failed");
+ handleException();
}
}
int numEvents = 0;
for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
- numEvents += mCountersGroup.onlineCPU(cpu, false, &mBuffer, &mMonitor);
+ numEvents += mCountersGroup.onlineCPU(currTime, cpu, false, &mBuffer);
+ }
+ for (int cpu = 0; cpu < gSessionData->mCores; ++cpu) {
+ numEvents += mIdleGroup.onlineCPU(currTime, cpu, false, &mBuffer);
}
if (numEvents <= 0) {
logg->logMessage("%s(%s:%i): PerfGroup::onlineCPU failed on all cores", __FUNCTION__, __FILE__, __LINE__);
return false;
}
- // Start events before reading proc to avoid race conditions
- if (!mCountersGroup.start()) {
- logg->logMessage("%s(%s:%i): PerfGroup::start failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
+ // Send the summary right before the start so that the monotonic delta is close to the start time
+ if (!gSessionData->perf.summary(&mSummary)) {
+ logg->logError(__FILE__, __LINE__, "PerfDriver::summary failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
}
- if (!readProc(&mBuffer, true, &printb, &b1, &b2, &b3)) {
- logg->logMessage("%s(%s:%i): readProc failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
+ // Start the timer thread to used to sync perf and monotonic raw times
+ pthread_t syncThread;
+ if (pthread_create(&syncThread, NULL, syncFunc, NULL)) {
+ logg->logError(__FILE__, __LINE__, "pthread_create failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
+ }
+ struct sched_param param;
+ param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+ if (pthread_setschedparam(syncThread, SCHED_FIFO | SCHED_RESET_ON_FORK, &param) != 0) {
+ logg->logError(__FILE__, __LINE__, "pthread_setschedparam failed");
+ handleException();
}
- mBuffer.commit(1);
+ mBuffer.commit(currTime);
return true;
}
+struct ProcThreadArgs {
+ Buffer *mBuffer;
+ uint64_t mCurrTime;
+ bool mIsDone;
+};
+
+void *procFunc(void *arg) {
+ DynBuf printb;
+ DynBuf b;
+ const ProcThreadArgs *const args = (ProcThreadArgs *)arg;
+
+ prctl(PR_SET_NAME, (unsigned long)&"gatord-proc", 0, 0, 0);
+
+ // Gator runs at a high priority, reset the priority to the default
+ if (setpriority(PRIO_PROCESS, syscall(__NR_gettid), 0) == -1) {
+ logg->logError(__FILE__, __LINE__, "setpriority failed");
+ handleException();
+ }
+
+ if (!readProcMaps(args->mCurrTime, args->mBuffer, &printb, &b)) {
+ logg->logError(__FILE__, __LINE__, "readProcMaps failed");
+ handleException();
+ }
+ args->mBuffer->commit(args->mCurrTime);
+
+ if (!readKallsyms(args->mCurrTime, args->mBuffer, &args->mIsDone)) {
+ logg->logError(__FILE__, __LINE__, "readKallsyms failed");
+ handleException();
+ }
+ args->mBuffer->commit(args->mCurrTime);
+
+ return NULL;
+}
+
static const char CPU_DEVPATH[] = "/devices/system/cpu/cpu";
void PerfSource::run() {
int pipefd[2];
+ pthread_t procThread;
+ ProcThreadArgs procThreadArgs;
+
+ {
+ DynBuf printb;
+ DynBuf b1;
+ DynBuf b2;
- if (pipe(pipefd) != 0) {
+ const uint64_t currTime = getTime();
+
+ // Start events before reading proc to avoid race conditions
+ if (!mCountersGroup.start() || !mIdleGroup.start()) {
+ logg->logError(__FILE__, __LINE__, "PerfGroup::start failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
+ }
+
+ if (!readProcComms(currTime, &mBuffer, &printb, &b1, &b2)) {
+ logg->logError(__FILE__, __LINE__, "readProcComms failed");
+ handleException();
+ }
+ mBuffer.commit(currTime);
+
+ // Postpone reading kallsyms as on android adb gets too backed up and data is lost
+ procThreadArgs.mBuffer = &mBuffer;
+ procThreadArgs.mCurrTime = currTime;
+ procThreadArgs.mIsDone = false;
+ if (pthread_create(&procThread, NULL, procFunc, &procThreadArgs)) {
+ logg->logError(__FILE__, __LINE__, "pthread_create failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
+ }
+ }
+
+ if (pipe_cloexec(pipefd) != 0) {
logg->logError(__FILE__, __LINE__, "pipe failed");
handleException();
}
@@ -165,7 +308,7 @@ void PerfSource::run() {
int timeout = -1;
if (gSessionData->mLiveRate > 0) {
- timeout = gSessionData->mLiveRate/MS_PER_US;
+ timeout = gSessionData->mLiveRate/NS_PER_MS;
}
sem_post(mStartProfile);
@@ -178,10 +321,11 @@ void PerfSource::run() {
logg->logError(__FILE__, __LINE__, "Monitor::wait failed");
handleException();
}
+ const uint64_t currTime = getTime();
for (int i = 0; i < ready; ++i) {
if (events[i].data.fd == mUEvent.getFd()) {
- if (!handleUEvent()) {
+ if (!handleUEvent(currTime)) {
logg->logError(__FILE__, __LINE__, "PerfSource::handleUEvent failed");
handleException();
}
@@ -200,6 +344,9 @@ void PerfSource::run() {
}
}
+ procThreadArgs.mIsDone = true;
+ pthread_join(procThread, NULL);
+ mIdleGroup.stop();
mCountersGroup.stop();
mBuffer.setDone();
mIsDone = true;
@@ -212,7 +359,7 @@ void PerfSource::run() {
close(pipefd[1]);
}
-bool PerfSource::handleUEvent() {
+bool PerfSource::handleUEvent(const uint64_t currTime) {
UEventResult result;
if (!mUEvent.read(&result)) {
logg->logMessage("%s(%s:%i): UEvent::Read failed", __FUNCTION__, __FILE__, __LINE__);
@@ -231,14 +378,41 @@ bool PerfSource::handleUEvent() {
logg->logMessage("%s(%s:%i): strtol failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}
+
+ if (cpu >= gSessionData->mCores) {
+ logg->logError(__FILE__, __LINE__, "Only %i cores are expected but core %i reports %s", gSessionData->mCores, cpu, result.mAction);
+ handleException();
+ }
+
if (strcmp(result.mAction, "online") == 0) {
+ mBuffer.onlineCPU(currTime, currTime - gSessionData->mMonotonicStarted, cpu);
// Only call onlineCPU if prepareCPU succeeded
- const bool result = mCountersGroup.prepareCPU(cpu) &&
- mCountersGroup.onlineCPU(cpu, true, &mBuffer, &mMonitor);
- mBuffer.commit(1);
+ bool result = false;
+ int err = mCountersGroup.prepareCPU(cpu, &mMonitor);
+ if (err == PG_CPU_OFFLINE) {
+ result = true;
+ } else if (err == PG_SUCCESS) {
+ if (mCountersGroup.onlineCPU(currTime, cpu, true, &mBuffer)) {
+ err = mIdleGroup.prepareCPU(cpu, &mMonitor);
+ if (err == PG_CPU_OFFLINE) {
+ result = true;
+ } else if (err == PG_SUCCESS) {
+ if (mIdleGroup.onlineCPU(currTime, cpu, true, &mBuffer)) {
+ result = true;
+ }
+ }
+ }
+ }
+ mBuffer.commit(currTime);
+
+ gSessionData->readCpuInfo();
+ gSessionData->perf.coreName(currTime, &mSummary, cpu);
+ mSummary.commit(currTime);
return result;
} else if (strcmp(result.mAction, "offline") == 0) {
- return mCountersGroup.offlineCPU(cpu);
+ const bool result = mCountersGroup.offlineCPU(cpu) && mIdleGroup.offlineCPU(cpu);
+ mBuffer.offlineCPU(currTime, currTime - gSessionData->mMonotonicStarted, cpu);
+ return result;
}
}
diff --git a/tools/gator/daemon/PerfSource.h b/tools/gator/daemon/PerfSource.h
index 3f471c8de414..ce1eafe8e953 100644
--- a/tools/gator/daemon/PerfSource.h
+++ b/tools/gator/daemon/PerfSource.h
@@ -33,12 +33,13 @@ public:
void write(Sender *sender);
private:
- bool handleUEvent();
+ bool handleUEvent(const uint64_t currTime);
Buffer mSummary;
Buffer mBuffer;
PerfBuffer mCountersBuf;
PerfGroup mCountersGroup;
+ PerfGroup mIdleGroup;
Monitor mMonitor;
UEvent mUEvent;
sem_t *const mSenderSem;
diff --git a/tools/gator/daemon/Proc.cpp b/tools/gator/daemon/Proc.cpp
index 9f01770d6609..e6b26b1199fa 100644
--- a/tools/gator/daemon/Proc.cpp
+++ b/tools/gator/daemon/Proc.cpp
@@ -10,13 +10,16 @@
#include <dirent.h>
#include <errno.h>
+#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "Buffer.h"
#include "DynBuf.h"
#include "Logging.h"
+#include "SessionData.h"
struct ProcStat {
// From linux-dev/include/linux/sched.h
@@ -57,6 +60,8 @@ static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf
return true;
}
+static const char APP_PROCESS[] = "app_process";
+
static const char *readProcExe(DynBuf *const printb, const int pid, const int tid, DynBuf *const b) {
if (tid == -1 ? !printb->printf("/proc/%i/exe", pid)
: !printb->printf("/proc/%i/task/%i/exe", pid, tid)) {
@@ -82,7 +87,8 @@ static const char *readProcExe(DynBuf *const printb, const int pid, const int ti
}
// Android apps are run by app_process but the cmdline is changed to reference the actual app name
- if (strcmp(image, "app_process") != 0) {
+ // On 64-bit android app_process can be app_process32 or app_process64
+ if (strncmp(image, APP_PROCESS, sizeof(APP_PROCESS) - 1) != 0) {
return image;
}
@@ -100,7 +106,7 @@ static const char *readProcExe(DynBuf *const printb, const int pid, const int ti
return b->getBuf();
}
-static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) {
+static bool readProcTask(const uint64_t currTime, Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) {
bool result = false;
if (!b1->printf("/proc/%i/task", pid)) {
@@ -110,7 +116,8 @@ static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const prin
DIR *task = opendir(b1->getBuf());
if (task == NULL) {
logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
- return result;
+ // This is not a fatal error - the thread just doesn't exist any more
+ return true;
}
struct dirent *dirent;
@@ -138,7 +145,7 @@ static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const prin
goto fail;
}
- buffer->comm(pid, tid, image, ps.comm);
+ buffer->comm(currTime, pid, tid, image, ps.comm);
}
result = true;
@@ -149,7 +156,7 @@ static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const prin
return result;
}
-bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) {
+bool readProcComms(const uint64_t currTime, Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) {
bool result = false;
DIR *proc = opendir("/proc");
@@ -177,19 +184,6 @@ bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf
goto fail;
}
- if (sendMaps) {
- if (!printb->printf("/proc/%i/maps", pid)) {
- logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
- goto fail;
- }
- if (!b2->read(printb->getBuf())) {
- logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__);
- // This is not a fatal error - the process just doesn't exist any more
- continue;
- }
-
- buffer->maps(pid, pid, b2->getBuf());
- }
if (ps.numThreads <= 1) {
const char *const image = readProcExe(printb, pid, -1, b1);
if (image == NULL) {
@@ -197,9 +191,9 @@ bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf
goto fail;
}
- buffer->comm(pid, pid, image, ps.comm);
+ buffer->comm(currTime, pid, pid, image, ps.comm);
} else {
- if (!readProcTask(buffer, pid, printb, b1, b3)) {
+ if (!readProcTask(currTime, buffer, pid, printb, b1, b2)) {
logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__);
goto fail;
}
@@ -213,3 +207,106 @@ bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf
return result;
}
+
+bool readProcMaps(const uint64_t currTime, Buffer *const buffer, DynBuf *const printb, DynBuf *const b) {
+ bool result = false;
+
+ DIR *proc = opendir("/proc");
+ if (proc == NULL) {
+ logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__);
+ return result;
+ }
+
+ struct dirent *dirent;
+ while ((dirent = readdir(proc)) != NULL) {
+ char *endptr;
+ const int pid = strtol(dirent->d_name, &endptr, 10);
+ if (*endptr != '\0') {
+ // Ignore proc items that are not integers like ., cpuinfo, etc...
+ continue;
+ }
+
+ if (!printb->printf("/proc/%i/maps", pid)) {
+ logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__);
+ goto fail;
+ }
+ if (!b->read(printb->getBuf())) {
+ logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__);
+ // This is not a fatal error - the process just doesn't exist any more
+ continue;
+ }
+
+ buffer->maps(currTime, pid, pid, b->getBuf());
+ }
+
+ result = true;
+
+ fail:
+ closedir(proc);
+
+ return result;
+}
+
+bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *const isDone) {
+ int fd = ::open("/proc/kallsyms", O_RDONLY | O_CLOEXEC);
+
+ if (fd < 0) {
+ logg->logMessage("%s(%s:%i): open failed", __FUNCTION__, __FILE__, __LINE__);
+ return true;
+ };
+
+ char buf[1<<12];
+ ssize_t pos = 0;
+ while (gSessionData->mSessionIsActive && !ACCESS_ONCE(*isDone)) {
+ // Assert there is still space in the buffer
+ if (sizeof(buf) - pos - 1 == 0) {
+ logg->logError(__FILE__, __LINE__, "no space left in buffer");
+ handleException();
+ }
+
+ {
+ // -1 to reserve space for \0
+ const ssize_t bytes = ::read(fd, buf + pos, sizeof(buf) - pos - 1);
+ if (bytes < 0) {
+ logg->logError(__FILE__, __LINE__, "read failed", __FUNCTION__, __FILE__, __LINE__);
+ handleException();
+ }
+ if (bytes == 0) {
+ // Assert the buffer is empty
+ if (pos != 0) {
+ logg->logError(__FILE__, __LINE__, "buffer not empty on eof");
+ handleException();
+ }
+ break;
+ }
+ pos += bytes;
+ }
+
+ ssize_t newline;
+ // Find the last '\n'
+ for (newline = pos - 1; newline >= 0; --newline) {
+ if (buf[newline] == '\n') {
+ const char was = buf[newline + 1];
+ buf[newline + 1] = '\0';
+ buffer->kallsyms(currTime, buf);
+ // Sleep 3 ms to avoid sending out too much data too quickly
+ usleep(3000);
+ buf[0] = was;
+ // Assert the memory regions do not overlap
+ if (pos - newline >= newline + 1) {
+ logg->logError(__FILE__, __LINE__, "memcpy src and dst overlap");
+ handleException();
+ }
+ if (pos - newline - 2 > 0) {
+ memcpy(buf + 1, buf + newline + 2, pos - newline - 2);
+ }
+ pos -= newline + 1;
+ break;
+ }
+ }
+ }
+
+ close(fd);
+
+ return true;
+}
diff --git a/tools/gator/daemon/Proc.h b/tools/gator/daemon/Proc.h
index 31c2eecb7aeb..2a1a7cbc1e99 100644
--- a/tools/gator/daemon/Proc.h
+++ b/tools/gator/daemon/Proc.h
@@ -9,9 +9,13 @@
#ifndef PROC_H
#define PROC_H
+#include <stdint.h>
+
class Buffer;
class DynBuf;
-bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3);
+bool readProcComms(const uint64_t currTime, Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2);
+bool readProcMaps(const uint64_t currTime, Buffer *const buffer, DynBuf *const printb, DynBuf *const b);
+bool readKallsyms(const uint64_t currTime, Buffer *const buffer, const bool *const isDone);
#endif // PROC_H
diff --git a/tools/gator/daemon/Sender.cpp b/tools/gator/daemon/Sender.cpp
index 3a981a6427be..8a54a6678974 100644
--- a/tools/gator/daemon/Sender.cpp
+++ b/tools/gator/daemon/Sender.cpp
@@ -65,18 +65,13 @@ void Sender::createDataFile(char* apcDir) {
mDataFileName = (char*)malloc(strlen(apcDir) + 12);
sprintf(mDataFileName, "%s/0000000000", apcDir);
- mDataFile = fopen(mDataFileName, "wb");
+ mDataFile = fopen_cloexec(mDataFileName, "wb");
if (!mDataFile) {
logg->logError(__FILE__, __LINE__, "Failed to open binary file: %s", mDataFileName);
handleException();
}
}
-template<typename T>
-inline T min(const T a, const T b) {
- return (a < b ? a : b);
-}
-
void Sender::writeData(const char* data, int length, int type) {
if (length < 0 || (data == NULL && length > 0)) {
return;
diff --git a/tools/gator/daemon/Sender.h b/tools/gator/daemon/Sender.h
index 33b6cc3c5d8d..5aa911713820 100644
--- a/tools/gator/daemon/Sender.h
+++ b/tools/gator/daemon/Sender.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __SENDER_H__
-#define __SENDER_H__
+#ifndef __SENDER_H__
+#define __SENDER_H__
#include <stdio.h>
#include <pthread.h>
diff --git a/tools/gator/daemon/SessionData.cpp b/tools/gator/daemon/SessionData.cpp
index 14d995fc39fa..0e65d7842647 100644
--- a/tools/gator/daemon/SessionData.cpp
+++ b/tools/gator/daemon/SessionData.cpp
@@ -8,15 +8,31 @@
#include "SessionData.h"
+#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
+#include <unistd.h>
-#include "SessionXML.h"
+#include "CPUFreqDriver.h"
+#include "DiskIODriver.h"
+#include "FSDriver.h"
+#include "HwmonDriver.h"
#include "Logging.h"
+#include "MemInfoDriver.h"
+#include "NetDriver.h"
+#include "SessionXML.h"
+
+#define CORE_NAME_UNKNOWN "unknown"
SessionData* gSessionData = NULL;
SessionData::SessionData() {
+ usDrivers[0] = new HwmonDriver();
+ usDrivers[1] = new FSDriver();
+ usDrivers[2] = new MemInfoDriver();
+ usDrivers[3] = new NetDriver();
+ usDrivers[4] = new CPUFreqDriver();
+ usDrivers[5] = new DiskIODriver();
initialize();
}
@@ -29,6 +45,7 @@ void SessionData::initialize() {
mLocalCapture = false;
mOneShot = false;
mSentSummary = false;
+ mAllowCommands = false;
const size_t cpuIdSize = sizeof(int)*NR_CPUS;
// Share mCpuIds across all instances of gatord
mCpuIds = (int *)mmap(NULL, cpuIdSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
@@ -37,15 +54,22 @@ void SessionData::initialize() {
handleException();
}
memset(mCpuIds, -1, cpuIdSize);
+ strcpy(mCoreName, CORE_NAME_UNKNOWN);
+ readModel();
readCpuInfo();
+ mImages = NULL;
mConfigurationXMLPath = NULL;
mSessionXMLPath = NULL;
mEventsXMLPath = NULL;
mTargetPath = NULL;
mAPCDir = NULL;
+ mCaptureWorkingDir = NULL;
+ mCaptureCommand = NULL;
+ mCaptureUser = NULL;
mSampleRate = 0;
mLiveRate = 0;
mDuration = 0;
+ mMonotonicStarted = -1;
mBacktraceDepth = 0;
mTotalBufferSize = 0;
// sysconf(_SC_NPROCESSORS_CONF) is unreliable on 2.6 Android, get the value from the kernel module
@@ -71,7 +95,6 @@ void SessionData::parseSessionXML(char* xmlString) {
handleException();
}
mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0;
- mDuration = session.parameters.duration;
// Determine buffer size (in MB) based on buffer mode
mOneShot = true;
@@ -89,21 +112,38 @@ void SessionData::parseSessionXML(char* xmlString) {
handleException();
}
- mImages = session.parameters.images;
// Convert milli- to nanoseconds
mLiveRate = session.parameters.live_rate * (int64_t)1000000;
if (mLiveRate > 0 && mLocalCapture) {
logg->logMessage("Local capture is not compatable with live, disabling live");
mLiveRate = 0;
}
+
+ if (!mAllowCommands && (mCaptureCommand != NULL)) {
+ logg->logError(__FILE__, __LINE__, "Running a command during a capture is not currently allowed. Please restart gatord with the -a flag.");
+ handleException();
+ }
+}
+
+void SessionData::readModel() {
+ FILE *fh = fopen("/proc/device-tree/model", "rb");
+ if (fh == NULL) {
+ return;
+ }
+
+ char buf[256];
+ if (fgets(buf, sizeof(buf), fh) != NULL) {
+ strcpy(mCoreName, buf);
+ }
+
+ fclose(fh);
}
void SessionData::readCpuInfo() {
char temp[256]; // arbitrarily large amount
- strcpy(mCoreName, "unknown");
mMaxCpuId = -1;
- FILE* f = fopen("/proc/cpuinfo", "r");
+ FILE *f = fopen("/proc/cpuinfo", "r");
if (f == NULL) {
logg->logMessage("Error opening /proc/cpuinfo\n"
"The core name in the captured xml file will be 'unknown'.");
@@ -122,7 +162,8 @@ void SessionData::readCpuInfo() {
}
if (len > 0) {
- temp[len - 1] = '\0'; // Replace the line feed with a null
+ // Replace the line feed with a null
+ temp[len - 1] = '\0';
}
const bool foundHardware = strstr(temp, "Hardware") != 0;
@@ -137,7 +178,7 @@ void SessionData::readCpuInfo() {
}
position += 2;
- if (foundHardware) {
+ if (foundHardware && (strcmp(mCoreName, CORE_NAME_UNKNOWN) == 0)) {
strncpy(mCoreName, position, sizeof(mCoreName));
mCoreName[sizeof(mCoreName) - 1] = 0; // strncpy does not guarantee a null-terminated string
foundCoreName = true;
@@ -171,10 +212,6 @@ void SessionData::readCpuInfo() {
uint64_t getTime() {
struct timespec ts;
-#ifndef CLOCK_MONOTONIC_RAW
- // Android doesn't have this defined but it was added in Linux 2.6.28
-#define CLOCK_MONOTONIC_RAW 4
-#endif
if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
logg->logError(__FILE__, __LINE__, "Failed to get uptime");
handleException();
@@ -185,10 +222,40 @@ uint64_t getTime() {
int getEventKey() {
// key 0 is reserved as a timestamp
// key 1 is reserved as the marker for thread specific counters
+ // key 2 is reserved as the marker for core
// Odd keys are assigned by the driver, even keys by the daemon
- static int key = 2;
+ static int key = 4;
const int ret = key;
key += 2;
return ret;
}
+
+int pipe_cloexec(int pipefd[2]) {
+ if (pipe(pipefd) != 0) {
+ return -1;
+ }
+
+ int fdf;
+ if (((fdf = fcntl(pipefd[0], F_GETFD)) == -1) || (fcntl(pipefd[0], F_SETFD, fdf | FD_CLOEXEC) != 0) ||
+ ((fdf = fcntl(pipefd[1], F_GETFD)) == -1) || (fcntl(pipefd[1], F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return -1;
+ }
+ return 0;
+}
+
+FILE *fopen_cloexec(const char *path, const char *mode) {
+ FILE *fh = fopen(path, mode);
+ if (fh == NULL) {
+ return NULL;
+ }
+ int fd = fileno(fh);
+ int fdf = fcntl(fd, F_GETFD);
+ if ((fdf == -1) || (fcntl(fd, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
+ fclose(fh);
+ return NULL;
+ }
+ return fh;
+}
diff --git a/tools/gator/daemon/SessionData.h b/tools/gator/daemon/SessionData.h
index 835082d86c4b..ed282af4a869 100644
--- a/tools/gator/daemon/SessionData.h
+++ b/tools/gator/daemon/SessionData.h
@@ -11,17 +11,21 @@
#include <stdint.h>
+#include "AnnotateListener.h"
#include "Config.h"
#include "Counter.h"
-#include "FSDriver.h"
-#include "Hwmon.h"
+#include "FtraceDriver.h"
+#include "KMod.h"
#include "MaliVideoDriver.h"
#include "PerfDriver.h"
-#define PROTOCOL_VERSION 19
-#define PROTOCOL_DEV 1000 // Differentiates development versions (timestamp) from release versions
+#define PROTOCOL_VERSION 20
+// Differentiates development versions (timestamp) from release versions
+#define PROTOCOL_DEV 1000
-#define NS_PER_S ((uint64_t)1000000000)
+#define NS_PER_S 1000000000LL
+#define NS_PER_MS 1000000LL
+#define NS_PER_US 1000LL
struct ImageLinkList {
char* path;
@@ -36,30 +40,40 @@ public:
~SessionData();
void initialize();
void parseSessionXML(char* xmlString);
+ void readModel();
void readCpuInfo();
- Hwmon hwmon;
- FSDriver fsDriver;
+ PolledDriver *usDrivers[6];
+ KMod kmod;
PerfDriver perf;
MaliVideoDriver maliVideo;
+ FtraceDriver ftraceDriver;
+ AnnotateListener annotateListener;
char mCoreName[MAX_STRING_LEN];
struct ImageLinkList *mImages;
- char* mConfigurationXMLPath;
- char* mSessionXMLPath;
- char* mEventsXMLPath;
- char* mTargetPath;
- char* mAPCDir;
+ char *mConfigurationXMLPath;
+ char *mSessionXMLPath;
+ char *mEventsXMLPath;
+ char *mTargetPath;
+ char *mAPCDir;
+ char *mCaptureWorkingDir;
+ char *mCaptureCommand;
+ char *mCaptureUser;
bool mWaitingOnCommand;
bool mSessionIsActive;
bool mLocalCapture;
- bool mOneShot; // halt processing of the driver data until profiling is complete or the buffer is filled
+ // halt processing of the driver data until profiling is complete or the buffer is filled
+ bool mOneShot;
bool mIsEBS;
bool mSentSummary;
+ bool mAllowCommands;
+ int64_t mMonotonicStarted;
int mBacktraceDepth;
- int mTotalBufferSize; // number of MB to use for the entire collection buffer
+ // number of MB to use for the entire collection buffer
+ int mTotalBufferSize;
int mSampleRate;
int64_t mLiveRate;
int mDuration;
@@ -82,5 +96,7 @@ extern SessionData* gSessionData;
uint64_t getTime();
int getEventKey();
+int pipe_cloexec(int pipefd[2]);
+FILE *fopen_cloexec(const char *path, const char *mode);
#endif // SESSION_DATA_H
diff --git a/tools/gator/daemon/SessionXML.cpp b/tools/gator/daemon/SessionXML.cpp
index 8cdc9409ca21..dea4c8f299ec 100644
--- a/tools/gator/daemon/SessionXML.cpp
+++ b/tools/gator/daemon/SessionXML.cpp
@@ -16,33 +16,30 @@
#include "OlyUtility.h"
#include "SessionData.h"
-static const char* TAG_SESSION = "session";
-static const char* TAG_IMAGE = "image";
-
-static const char* ATTR_VERSION = "version";
-static const char* ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding";
-static const char* ATTR_BUFFER_MODE = "buffer_mode";
-static const char* ATTR_SAMPLE_RATE = "sample_rate";
-static const char* ATTR_DURATION = "duration";
-static const char* ATTR_PATH = "path";
-static const char* ATTR_LIVE_RATE = "live_rate";
+static const char *TAG_SESSION = "session";
+static const char *TAG_IMAGE = "image";
+
+static const char *ATTR_VERSION = "version";
+static const char *ATTR_CALL_STACK_UNWINDING = "call_stack_unwinding";
+static const char *ATTR_BUFFER_MODE = "buffer_mode";
+static const char *ATTR_SAMPLE_RATE = "sample_rate";
+static const char *ATTR_DURATION = "duration";
+static const char *ATTR_PATH = "path";
+static const char *ATTR_LIVE_RATE = "live_rate";
+static const char *ATTR_CAPTURE_WORKING_DIR = "capture_working_dir";
+static const char *ATTR_CAPTURE_COMMAND = "capture_command";
+static const char *ATTR_CAPTURE_USER = "capture_user";
SessionXML::SessionXML(const char *str) {
parameters.buffer_mode[0] = 0;
parameters.sample_rate[0] = 0;
- parameters.duration = 0;
parameters.call_stack_unwinding = false;
parameters.live_rate = 0;
- parameters.images = NULL;
- mPath = 0;
- mSessionXML = (const char *)str;
+ mSessionXML = str;
logg->logMessage(mSessionXML);
}
SessionXML::~SessionXML() {
- if (mPath != 0) {
- free((char *)mSessionXML);
- }
}
void SessionXML::parse() {
@@ -79,10 +76,13 @@ void SessionXML::sessionTag(mxml_node_t *tree, mxml_node_t *node) {
strncpy(parameters.sample_rate, mxmlElementGetAttr(node, ATTR_SAMPLE_RATE), sizeof(parameters.sample_rate));
parameters.sample_rate[sizeof(parameters.sample_rate) - 1] = 0; // strncpy does not guarantee a null-terminated string
}
+ if (mxmlElementGetAttr(node, ATTR_CAPTURE_WORKING_DIR)) gSessionData->mCaptureWorkingDir = strdup(mxmlElementGetAttr(node, ATTR_CAPTURE_WORKING_DIR));
+ if (mxmlElementGetAttr(node, ATTR_CAPTURE_COMMAND)) gSessionData->mCaptureCommand = strdup(mxmlElementGetAttr(node, ATTR_CAPTURE_COMMAND));
+ if (mxmlElementGetAttr(node, ATTR_CAPTURE_USER)) gSessionData->mCaptureUser = strdup(mxmlElementGetAttr(node, ATTR_CAPTURE_USER));
// integers/bools
parameters.call_stack_unwinding = util->stringToBool(mxmlElementGetAttr(node, ATTR_CALL_STACK_UNWINDING), false);
- if (mxmlElementGetAttr(node, ATTR_DURATION)) parameters.duration = strtol(mxmlElementGetAttr(node, ATTR_DURATION), NULL, 10);
+ if (mxmlElementGetAttr(node, ATTR_DURATION)) gSessionData->mDuration = strtol(mxmlElementGetAttr(node, ATTR_DURATION), NULL, 10);
if (mxmlElementGetAttr(node, ATTR_LIVE_RATE)) parameters.live_rate = strtol(mxmlElementGetAttr(node, ATTR_LIVE_RATE), NULL, 10);
// parse subtags
@@ -106,6 +106,6 @@ void SessionXML::sessionImage(mxml_node_t *node) {
image = (struct ImageLinkList *)malloc(sizeof(struct ImageLinkList));
image->path = (char*)malloc(length + 1);
image->path = strdup(mxmlElementGetAttr(node, ATTR_PATH));
- image->next = parameters.images;
- parameters.images = image;
+ image->next = gSessionData->mImages;
+ gSessionData->mImages = image;
}
diff --git a/tools/gator/daemon/SessionXML.h b/tools/gator/daemon/SessionXML.h
index e146094a4d17..53965749c74b 100644
--- a/tools/gator/daemon/SessionXML.h
+++ b/tools/gator/daemon/SessionXML.h
@@ -14,12 +14,13 @@
struct ImageLinkList;
struct ConfigParameters {
- char buffer_mode[64]; // buffer mode, "streaming", "low", "normal", "high" defines oneshot and buffer size
- char sample_rate[64]; // capture mode, "high", "normal", or "low"
- int duration; // length of profile in seconds
- bool call_stack_unwinding; // whether stack unwinding is performed
+ // buffer mode, "streaming", "low", "normal", "high" defines oneshot and buffer size
+ char buffer_mode[64];
+ // capture mode, "high", "normal", or "low"
+ char sample_rate[64];
+ // whether stack unwinding is performed
+ bool call_stack_unwinding;
int live_rate;
- struct ImageLinkList *images; // linked list of image strings
};
class SessionXML {
@@ -30,7 +31,6 @@ public:
ConfigParameters parameters;
private:
const char *mSessionXML;
- const char *mPath;
void sessionTag(mxml_node_t *tree, mxml_node_t *node);
void sessionImage(mxml_node_t *node);
diff --git a/tools/gator/daemon/Setup.cpp b/tools/gator/daemon/Setup.cpp
new file mode 100644
index 000000000000..d4ce0328c633
--- /dev/null
+++ b/tools/gator/daemon/Setup.cpp
@@ -0,0 +1,232 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "Setup.h"
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "Config.h"
+#include "DynBuf.h"
+#include "Logging.h"
+
+bool getLinuxVersion(int version[3]) {
+ // Check the kernel version
+ struct utsname utsname;
+ if (uname(&utsname) != 0) {
+ logg->logMessage("%s(%s:%i): uname failed", __FUNCTION__, __FILE__, __LINE__);
+ return false;
+ }
+
+ version[0] = 0;
+ version[1] = 0;
+ version[2] = 0;
+
+ int part = 0;
+ char *ch = utsname.release;
+ while (*ch >= '0' && *ch <= '9' && part < 3) {
+ version[part] = 10*version[part] + *ch - '0';
+
+ ++ch;
+ if (*ch == '.') {
+ ++part;
+ ++ch;
+ }
+ }
+
+ return true;
+}
+
+static int pgrep_gator(DynBuf *const printb) {
+ DynBuf b;
+
+ DIR *proc = opendir("/proc");
+ if (proc == NULL) {
+ logg->logError(__FILE__, __LINE__, "gator: error: opendir failed");
+ handleException();
+ }
+
+ int self = getpid();
+
+ struct dirent *dirent;
+ while ((dirent = readdir(proc)) != NULL) {
+ char *endptr;
+ const int pid = strtol(dirent->d_name, &endptr, 10);
+ if (*endptr != '\0' || (pid == self)) {
+ // Ignore proc items that are not integers like ., cpuinfo, etc...
+ continue;
+ }
+
+ if (!printb->printf("/proc/%i/stat", pid)) {
+ logg->logError(__FILE__, __LINE__, "gator: error: DynBuf::printf failed");
+ handleException();
+ }
+
+ if (!b.read(printb->getBuf())) {
+ // This is not a fatal error - the thread just doesn't exist any more
+ continue;
+ }
+
+ char *comm = strchr(b.getBuf(), '(');
+ if (comm == NULL) {
+ logg->logError(__FILE__, __LINE__, "gator: error: parsing stat begin failed");
+ handleException();
+ }
+ ++comm;
+ char *const str = strrchr(comm, ')');
+ if (str == NULL) {
+ logg->logError(__FILE__, __LINE__, "gator: error: parsing stat end failed");
+ handleException();
+ }
+ *str = '\0';
+
+ if (strncmp(comm, "gator", 5) == 0) {
+ // Assume there is only one gator process
+ return pid;
+ }
+ }
+
+ closedir(proc);
+
+ return -1;
+}
+
+int update(const char *const gatorPath) {
+ printf("gator: starting\n");
+
+ int version[3];
+ if (!getLinuxVersion(version)) {
+ logg->logError(__FILE__, __LINE__, "gator: error: getLinuxVersion failed");
+ handleException();
+ }
+
+ if (KERNEL_VERSION(version[0], version[1], version[2]) < KERNEL_VERSION(2, 6, 32)) {
+ logg->logError(__FILE__, __LINE__, "gator: error: Streamline can't automatically setup gator as this kernel version is not supported. Please upgrade the kernel on your device.");
+ handleException();
+ }
+
+ if (KERNEL_VERSION(version[0], version[1], version[2]) < KERNEL_VERSION(3, 4, 0)) {
+ logg->logError(__FILE__, __LINE__, "gator: error: Streamline can't automatically setup gator as gator.ko is required for this version of Linux. Please build gator.ko and gatord and install them on your device.");
+ handleException();
+ }
+
+ if (access("/sys/module/gator", F_OK) == 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: Streamline has detected that the gator kernel module is loaded on your device. Please build an updated version of gator.ko and gatord and install them on your device.");
+ handleException();
+ }
+
+ if (geteuid() != 0) {
+ printf("gator: trying sudo\n");
+ execlp("sudo", "sudo", gatorPath, "-u", NULL);
+ // Streamline will provide the password if needed
+
+ printf("gator: trying su\n");
+ char buf[1<<10];
+ snprintf(buf, sizeof(buf), "%s -u", gatorPath);
+ execlp("su", "su", "-", "-c", buf, NULL);
+ // Streamline will provide the password if needed
+
+ logg->logError(__FILE__, __LINE__, "gator: error: Streamline was unable to sudo to root on your device. Please double check passwords, ensure sudo or su work with this user or try a different username.");
+ handleException();
+ }
+ printf("gator: now root\n");
+
+ // setenforce 0 not needed for userspace gator
+
+ // Kill existing gator
+ DynBuf gatorStatPath;
+ int gator_main = pgrep_gator(&gatorStatPath);
+ if (gator_main > 0) {
+ if (kill(gator_main, SIGTERM) != 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: kill SIGTERM failed");
+ handleException();
+ }
+ for (int i = 0; ; ++i) {
+ if (access(gatorStatPath.getBuf(), F_OK) != 0) {
+ break;
+ }
+ if (i == 5) {
+ if (kill(gator_main, SIGKILL) != 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: kill SIGKILL failed");
+ handleException();
+ }
+ } else if (i >= 10) {
+ logg->logError(__FILE__, __LINE__, "gator: error: unable to kill running gator");
+ handleException();
+ }
+ sleep(1);
+ }
+ }
+ printf("gator: no gatord running\n");
+
+ rename("gatord", "gatord.old");
+ rename("gator.ko", "gator.ko.old");
+
+ // Rename gatord.YYYYMMDDHHMMSSMMMM to gatord
+ char *newGatorPath = strdup(gatorPath);
+ char *dot = strrchr(newGatorPath, '.');
+ if (dot != NULL) {
+ *dot = '\0';
+ if (rename(gatorPath, newGatorPath) != 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: rename failed");
+ handleException();
+ }
+ }
+
+ // Fork and start gatord (redirect stdout and stderr)
+ int child = fork();
+ if (child < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: fork failed");
+ handleException();
+ } else if (child == 0) {
+ int inFd = open("/dev/null", O_RDONLY | O_CLOEXEC);
+ if (inFd < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: open of /dev/null failed");
+ handleException();
+ }
+ int outFd = open("gatord.out", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
+ if (outFd < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: open of gatord.out failed");
+ handleException();
+ }
+ int errFd = open("gatord.err", O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0600);
+ if (errFd < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: open of gatord.err failed");
+ handleException();
+ }
+ if (dup2(inFd, STDIN_FILENO) < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stdin failed");
+ handleException();
+ }
+ if (dup2(outFd, STDOUT_FILENO) < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stdout failed");
+ handleException();
+ }
+ if (dup2(errFd, STDERR_FILENO) < 0) {
+ logg->logError(__FILE__, __LINE__, "gator: error: dup2 for stderr failed");
+ handleException();
+ }
+ execlp(newGatorPath, newGatorPath, "-a", NULL);
+ logg->logError(__FILE__, __LINE__, "gator: error: execlp failed");
+ handleException();
+ }
+
+ printf("gator: done\n");
+
+ return 0;
+}
diff --git a/tools/gator/daemon/Setup.h b/tools/gator/daemon/Setup.h
new file mode 100644
index 000000000000..280d61139784
--- /dev/null
+++ b/tools/gator/daemon/Setup.h
@@ -0,0 +1,18 @@
+/**
+ * Copyright (C) ARM Limited 2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef SETUP_H
+#define SETUP_H
+
+// From include/generated/uapi/linux/version.h
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+
+bool getLinuxVersion(int version[3]);
+int update(const char *const gatorPath);
+
+#endif // SETUP_H
diff --git a/tools/gator/daemon/StreamlineSetup.h b/tools/gator/daemon/StreamlineSetup.h
index b380f46b98f0..623e14f2b64a 100644
--- a/tools/gator/daemon/StreamlineSetup.h
+++ b/tools/gator/daemon/StreamlineSetup.h
@@ -6,8 +6,8 @@
* published by the Free Software Foundation.
*/
-#ifndef __STREAMLINE_SETUP_H__
-#define __STREAMLINE_SETUP_H__
+#ifndef __STREAMLINE_SETUP_H__
+#define __STREAMLINE_SETUP_H__
#include <stdint.h>
#include <string.h>
diff --git a/tools/gator/daemon/UEvent.cpp b/tools/gator/daemon/UEvent.cpp
index 54d45751e3c9..f94a995393e8 100644
--- a/tools/gator/daemon/UEvent.cpp
+++ b/tools/gator/daemon/UEvent.cpp
@@ -15,6 +15,7 @@
#include <linux/netlink.h>
#include "Logging.h"
+#include "OlySocket.h"
static const char EMPTY[] = "";
static const char ACTION[] = "ACTION=";
@@ -31,7 +32,7 @@ UEvent::~UEvent() {
}
bool UEvent::init() {
- mFd = socket(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
+ mFd = socket_cloexec(PF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);
if (mFd < 0) {
logg->logMessage("%s(%s:%i): socket failed", __FUNCTION__, __FILE__, __LINE__);
return false;
diff --git a/tools/gator/daemon/UserSpaceSource.cpp b/tools/gator/daemon/UserSpaceSource.cpp
index 8c328e0e0fb5..4a9b22f4b555 100644
--- a/tools/gator/daemon/UserSpaceSource.cpp
+++ b/tools/gator/daemon/UserSpaceSource.cpp
@@ -16,8 +16,6 @@
#include "Logging.h"
#include "SessionData.h"
-#define NS_PER_US 1000
-
extern Child *child;
UserSpaceSource::UserSpaceSource(sem_t *senderSem) : mBuffer(0, FRAME_BLOCK_COUNTER, gSessionData->mTotalBufferSize*1024*1024, senderSem) {
@@ -33,16 +31,22 @@ bool UserSpaceSource::prepare() {
void UserSpaceSource::run() {
prctl(PR_SET_NAME, (unsigned long)&"gatord-counters", 0, 0, 0);
- gSessionData->hwmon.start();
- gSessionData->fsDriver.start();
+ for (int i = 0; i < ARRAY_LENGTH(gSessionData->usDrivers); ++i) {
+ gSessionData->usDrivers[i]->start();
+ }
int64_t monotonic_started = 0;
while (monotonic_started <= 0) {
usleep(10);
- if (DriverSource::readInt64Driver("/dev/gator/started", &monotonic_started) == -1) {
- logg->logError(__FILE__, __LINE__, "Error reading gator driver start time");
- handleException();
+ if (gSessionData->perf.isSetup()) {
+ monotonic_started = gSessionData->mMonotonicStarted;
+ } else {
+ if (DriverSource::readInt64Driver("/dev/gator/started", &monotonic_started) == -1) {
+ logg->logError(__FILE__, __LINE__, "Error reading gator driver start time");
+ handleException();
+ }
+ gSessionData->mMonotonicStarted = monotonic_started;
}
}
@@ -57,8 +61,9 @@ void UserSpaceSource::run() {
}
if (mBuffer.eventHeader(curr_time)) {
- gSessionData->hwmon.read(&mBuffer);
- gSessionData->fsDriver.read(&mBuffer);
+ for (int i = 0; i < ARRAY_LENGTH(gSessionData->usDrivers); ++i) {
+ gSessionData->usDrivers[i]->read(&mBuffer);
+ }
// Only check after writing all counters so that time and corresponding counters appear in the same frame
mBuffer.check(curr_time);
}
diff --git a/tools/gator/daemon/defaults.xml b/tools/gator/daemon/defaults.xml
index 39a0f656f7e6..086eca1e804e 100644
--- a/tools/gator/daemon/defaults.xml
+++ b/tools/gator/daemon/defaults.xml
@@ -24,16 +24,16 @@
<configuration counter="ARMv7_Cortex_A9_cnt2" event="0x07"/>
<configuration counter="ARMv7_Cortex_A9_cnt3" event="0x03"/>
<configuration counter="ARMv7_Cortex_A9_cnt4" event="0x04"/>
- <configuration counter="ARMv7_Cortex_A12_ccnt" event="0xff"/>
- <configuration counter="ARMv7_Cortex_A12_cnt0" event="0x08"/>
- <configuration counter="ARMv7_Cortex_A12_cnt1" event="0x16"/>
- <configuration counter="ARMv7_Cortex_A12_cnt2" event="0x10"/>
- <configuration counter="ARMv7_Cortex_A12_cnt3" event="0x19"/>
<configuration counter="ARMv7_Cortex_A15_ccnt" event="0xff"/>
<configuration counter="ARMv7_Cortex_A15_cnt0" event="0x8"/>
<configuration counter="ARMv7_Cortex_A15_cnt1" event="0x16"/>
<configuration counter="ARMv7_Cortex_A15_cnt2" event="0x10"/>
<configuration counter="ARMv7_Cortex_A15_cnt3" event="0x19"/>
+ <configuration counter="ARMv7_Cortex_A17_ccnt" event="0xff"/>
+ <configuration counter="ARMv7_Cortex_A17_cnt0" event="0x08"/>
+ <configuration counter="ARMv7_Cortex_A17_cnt1" event="0x16"/>
+ <configuration counter="ARMv7_Cortex_A17_cnt2" event="0x10"/>
+ <configuration counter="ARMv7_Cortex_A17_cnt3" event="0x19"/>
<configuration counter="ARM_Cortex-A53_ccnt" event="0x11"/>
<configuration counter="ARM_Cortex-A53_cnt0" event="0x8"/>
<configuration counter="ARM_Cortex-A53_cnt1" event="0x16"/>
@@ -56,12 +56,29 @@
<configuration counter="Linux_block_rq_wr"/>
<configuration counter="Linux_block_rq_rd"/>
<configuration counter="Linux_meminfo_memused"/>
+ <configuration counter="Linux_meminfo_memused2"/>
<configuration counter="Linux_meminfo_memfree"/>
<configuration counter="Linux_power_cpu_freq"/>
<configuration counter="ARM_Mali-4xx_fragment"/>
<configuration counter="ARM_Mali-4xx_vertex"/>
- <configuration counter="ARM_Mali-T6xx_fragment" cores="1"/>
- <configuration counter="ARM_Mali-T6xx_vertex" cores="1"/>
- <configuration counter="ARM_Mali-T6xx_opencl" cores="1"/>
+ <configuration counter="ARM_Mali-Midgard_fragment" cores="1"/>
+ <configuration counter="ARM_Mali-Midgard_vertex" cores="1"/>
+ <configuration counter="ARM_Mali-Midgard_opencl" cores="1"/>
+ <configuration counter="ARM_Mali-T60x_GPU_ACTIVE"/>
+ <configuration counter="ARM_Mali-T60x_JS0_ACTIVE"/>
+ <configuration counter="ARM_Mali-T60x_JS1_ACTIVE"/>
+ <configuration counter="ARM_Mali-T60x_JS2_ACTIVE"/>
+ <configuration counter="ARM_Mali-T62x_GPU_ACTIVE"/>
+ <configuration counter="ARM_Mali-T62x_JS0_ACTIVE"/>
+ <configuration counter="ARM_Mali-T62x_JS1_ACTIVE"/>
+ <configuration counter="ARM_Mali-T62x_JS2_ACTIVE"/>
+ <configuration counter="ARM_Mali-T72x_GPU_ACTIVE"/>
+ <configuration counter="ARM_Mali-T72x_JS0_ACTIVE"/>
+ <configuration counter="ARM_Mali-T72x_JS1_ACTIVE"/>
+ <configuration counter="ARM_Mali-T72x_JS2_ACTIVE"/>
+ <configuration counter="ARM_Mali-T76x_GPU_ACTIVE"/>
+ <configuration counter="ARM_Mali-T76x_JS0_ACTIVE"/>
+ <configuration counter="ARM_Mali-T76x_JS1_ACTIVE"/>
+ <configuration counter="ARM_Mali-T76x_JS2_ACTIVE"/>
<configuration counter="L2C-310_cnt0" event="0x1"/>
</configurations>
diff --git a/tools/gator/daemon/events-Cortex-A12.xml b/tools/gator/daemon/events-Cortex-A17.xml
index 9c04354ad137..4dd08c1f203d 100644
--- a/tools/gator/daemon/events-Cortex-A12.xml
+++ b/tools/gator/daemon/events-Cortex-A17.xml
@@ -1,6 +1,6 @@
- <counter_set name="ARMv7_Cortex_A12_cnt" count="6"/>
- <category name="Cortex-A12" counter_set="ARMv7_Cortex_A12_cnt" per_cpu="yes" supports_event_based_sampling="yes">
- <event counter="ARMv7_Cortex_A12_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
+ <counter_set name="ARMv7_Cortex_A17_cnt" count="6"/>
+ <category name="Cortex-A17" counter_set="ARMv7_Cortex_A17_cnt" per_cpu="yes" supports_event_based_sampling="yes">
+ <event counter="ARMv7_Cortex_A17_ccnt" event="0xff" title="Clock" name="Cycles" display="hertz" units="Hz" average_selection="yes" average_cores="yes" description="The number of core clock cycles"/>
<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"/>
<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"/>
<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"/>
@@ -62,7 +62,7 @@
<event event="0xc2" title="Cache" name="4 Ways Read" description="Number of set of 4 ways read in the instruction cache - Tag RAM"/>
<event event="0xc3" title="Cache" name="Ways Read" description="Number of ways read in the instruction cache - Data RAM"/>
<event event="0xc4" title="Cache" name="BATC Read" description="Number of ways read in the instruction BTAC RAM"/>
- <event event="0xca" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local Cortex-A12 cluster, rather than accessing the L2 cache or issuing an external read. It increments on each transaction, rather than on each beat of data"/>
+ <event event="0xca" title="Memory" name="Snoop" description="Data snooped from other processor. This event counts memory-read operations that read data from another processor within the local Cortex-A17 cluster, rather than accessing the L2 cache or issuing an external read. It increments on each transaction, rather than on each beat of data"/>
<event event="0xd3" title="Slots" name="Load-Store Unit" description="Duration during which all slots in the Load-Store Unit are busy"/>
<event event="0xd8" title="Slots" name="Load-Store Issue Queue" description="Duration during which all slots in the Load-Store Issue queue are busy"/>
<event event="0xd9" title="Slots" name="Data Processing Issue Queue" description="Duration during which all slots in the Data Processing issue queue are busy"/>
diff --git a/tools/gator/daemon/events-Filesystem.xml b/tools/gator/daemon/events-Filesystem.xml
index 5feeb9014a63..9ef61ddac811 100644
--- a/tools/gator/daemon/events-Filesystem.xml
+++ b/tools/gator/daemon/events-Filesystem.xml
@@ -1,11 +1,11 @@
<category name="Filesystem">
- <!-- counter attributes must be unique -->
+ <!-- counter attribute must start with filesystem_ and be unique -->
<!-- regex item in () is the value shown -->
- <!-- these counters are not compatible with userspace gator, i.e. gator.ko must be loaded -->
<!--
- <event counter="/sys/devices/system/cpu/cpu1/online" title="online" name="cpu 1" class="absolute" description="If cpu 1 is online"/>
- <event counter="/proc/self/loginuid" title="loginuid" name="loginuid" class="absolute" description="loginuid"/>
- <event counter="/proc/self/stat" title="stat" name="rss" class="absolute" regex="-?[0-9]+ \(.*\) . -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ (-?[0-9]+)" units="pages" description="resident set size"/>
- <event counter="/proc/stat" title="proc-stat" name="processes" class="absolute" regex="processes ([0-9]+)" description="Number of processes and threads created"/>
+ <event counter="filesystem_cpu1_online" path="/sys/devices/system/cpu/cpu1/online" title="online" name="cpu 1" class="absolute" description="If cpu 1 is online"/>
+ <event counter="filesystem_loginuid" path="/proc/self/loginuid" title="loginuid" name="loginuid" class="absolute" description="loginuid"/>
+ <event counter="filesystem_gatord_rss" path="/proc/self/stat" title="stat" name="rss" class="absolute" regex="-?[0-9]+ \(.*\) . -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ -?[0-9]+ (-?[0-9]+)" units="pages" description="resident set size"/>
+ <event counter="filesystem_processes" path="/proc/stat" title="proc-stat" name="processes" class="absolute" regex="processes ([0-9]+)" description="Number of processes and threads created"/>
+ <event counter="filesystem_context_switches" path="/proc/stat" title="proc-stat" name="context switches" class="absolute" regex="ctxt ([0-9]+)" description="Number of processes and threads created"/>
-->
</category>
diff --git a/tools/gator/daemon/events-Linux.xml b/tools/gator/daemon/events-Linux.xml
index c306dd62208e..62a7018d038f 100644
--- a/tools/gator/daemon/events-Linux.xml
+++ b/tools/gator/daemon/events-Linux.xml
@@ -1,16 +1,17 @@
<category name="Linux">
<event counter="Linux_irq_softirq" title="Interrupts" name="SoftIRQ" per_cpu="yes" description="Linux SoftIRQ taken"/>
<event counter="Linux_irq_irq" title="Interrupts" name="IRQ" per_cpu="yes" description="Linux IRQ taken"/>
- <event counter="Linux_block_rq_wr" title="Disk IO" name="Write" units="B" description="Disk IO Bytes Written"/>
- <event counter="Linux_block_rq_rd" title="Disk IO" name="Read" units="B" description="Disk IO Bytes Read"/>
+ <event counter="Linux_block_rq_wr" title="Disk I/O" name="Write" units="B" description="Disk I/O Bytes Written"/>
+ <event counter="Linux_block_rq_rd" title="Disk I/O" name="Read" units="B" description="Disk I/O Bytes Read"/>
<event counter="Linux_net_rx" title="Network" name="Receive" units="B" description="Receive network traffic, including effect from Streamline"/>
<event counter="Linux_net_tx" title="Network" name="Transmit" units="B" description="Transmit network traffic, including effect from Streamline"/>
<event counter="Linux_sched_switch" title="Scheduler" name="Switch" per_cpu="yes" description="Context switch events"/>
<event counter="Linux_meminfo_memused" title="Memory" name="Used" class="absolute" units="B" proc="yes" description="Total used memory size. Note: a process' used memory includes shared memory that may be counted more than once (equivalent to RES from top). Kernel threads are not filterable."/>
+ <event counter="Linux_meminfo_memused2" title="Memory" name="Used" class="absolute" units="B" description="Total used memory size"/>
<event counter="Linux_meminfo_memfree" title="Memory" name="Free" class="absolute" display="minimum" units="B" description="Available memory size"/>
<event counter="Linux_meminfo_bufferram" title="Memory" name="Buffer" class="absolute" units="B" description="Memory used by OS disk buffers"/>
<event counter="Linux_power_cpu_freq" title="Clock" name="Frequency" per_cpu="yes" class="absolute" units="Hz" series_composition="overlay" average_cores="yes" description="Frequency setting of the CPU"/>
- <event counter="Linux_power_cpu_idle" title="Idle" name="State" per_cpu="yes" class="absolute" description="CPU Idle State + 1, set the Sample Rate to None to prevent the hrtimer from interrupting the system"/>
- <event counter="Linux_cpu_wait_contention" title="CPU Contention" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x003c96fb" description="Thread waiting on contended resource"/>
- <event counter="Linux_cpu_wait_io" title="CPU I/O" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x00b30000" description="Thread waiting on I/O resource"/>
+ <event counter="Linux_cpu_wait_contention" title="CPU Contention" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x003c96fb" description="One or more threads are runnable but waiting due to CPU contention"/>
+ <event counter="Linux_cpu_wait_io" title="CPU I/O" name="Wait" per_cpu="no" class="activity" derived="yes" rendering_type="bar" average_selection="yes" percentage="yes" modifier="10000" color="0x00b30000" description="One or more threads are blocked on an I/O resource"/>
+ <event counter="Linux_power_cpu" title="CPU Status" name="Activity" class="activity" activity1="Off" activity_color1="0x0000ff00" activity2="WFI" activity_color2="0x000000ff" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" description="CPU Status"/>
</category>
diff --git a/tools/gator/daemon/events-Mali-Midgard.xml b/tools/gator/daemon/events-Mali-Midgard.xml
new file mode 100644
index 000000000000..b6ab4b88cd2e
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-Midgard.xml
@@ -0,0 +1,46 @@
+ <category name="Mali-Midgard Software Counters" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_TOTAL_ALLOC_PAGES" title="Mali Total Alloc Pages" name="Total number of allocated pages" description="Mali total number of allocated pages."/>
+ </category>
+ <category name="Mali-Midgard PM Shader" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_PM_SHADER_0" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 0" description="Mali PM Shader: PM Shader Core 0."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_1" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 1" description="Mali PM Shader: PM Shader Core 1."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_2" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 2" description="Mali PM Shader: PM Shader Core 2."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_3" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 3" description="Mali PM Shader: PM Shader Core 3."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_4" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 4" description="Mali PM Shader: PM Shader Core 4."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_5" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 5" description="Mali PM Shader: PM Shader Core 5."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_6" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 6" description="Mali PM Shader: PM Shader Core 6."/>
+ <event counter="ARM_Mali-Midgard_PM_SHADER_7" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 7" description="Mali PM Shader: PM Shader Core 7."/>
+ </category>
+ <category name="Mali-Midgard PM Tiler" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_PM_TILER_0" display="average" average_selection="yes" percentage="yes" title="Mali PM Tiler" name="PM Tiler Core 0" description="Mali PM Tiler: PM Tiler Core 0."/>
+ </category>
+ <category name="Mali-Midgard PM L2" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_PM_L2_0" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 0" description="Mali PM L2: PM L2 Core 0."/>
+ <event counter="ARM_Mali-Midgard_PM_L2_1" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 1" description="Mali PM L2: PM L2 Core 1."/>
+ </category>
+ <category name="Mali-Midgard MMU Address Space" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_MMU_AS_0" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 0" description="Mali MMU Address Space 0 usage."/>
+ <event counter="ARM_Mali-Midgard_MMU_AS_1" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 1" description="Mali MMU Address Space 1 usage."/>
+ <event counter="ARM_Mali-Midgard_MMU_AS_2" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 2" description="Mali MMU Address Space 2 usage."/>
+ <event counter="ARM_Mali-Midgard_MMU_AS_3" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 3" description="Mali MMU Address Space 3 usage."/>
+ </category>
+ <category name="Mali-Midgard MMU Page Fault" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_MMU_PAGE_FAULT_0" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 0" description="Reports the number of newly allocated pages after a MMU page fault in address space 0."/>
+ <event counter="ARM_Mali-Midgard_MMU_PAGE_FAULT_1" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 1" description="Reports the number of newly allocated pages after a MMU page fault in address space 1."/>
+ <event counter="ARM_Mali-Midgard_MMU_PAGE_FAULT_2" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 2" description="Reports the number of newly allocated pages after a MMU page fault in address space 2."/>
+ <event counter="ARM_Mali-Midgard_MMU_PAGE_FAULT_3" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 3" description="Reports the number of newly allocated pages after a MMU page fault in address space 3."/>
+ </category>
+ <counter_set name="ARM_Mali-Midgard_Filmstrip_cnt" count="1"/>
+ <category name="Mali-Midgard Filmstrip" counter_set="ARM_Mali-Midgard_Filmstrip_cnt" per_cpu="no">
+ <option_set name="fs">
+ <option event_delta="0x3c" name="1:60" description="captures every 60th frame"/>
+ <option event_delta="0x1e" name="1:30" description="captures every 30th frame"/>
+ <option event_delta="0xa" name="1:10" description="captures every 10th frame"/>
+ </option_set>
+ <event event="0x0400" option_set="fs" title="ARM Mali-Midgard" name="Filmstrip" description="Scaled framebuffer"/>
+ </category>
+ <category name="Mali-Midgard Activity" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_fragment" title="GPU Fragment" name="Activity" class="activity" activity1="Activity" activity_color1="0x00006fcc" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 0 Activity"/>
+ <event counter="ARM_Mali-Midgard_vertex" title="GPU Vertex-Tiling-Compute" name="Activity" class="activity" activity1="Activity" activity_color1="0x00eda000" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 1 Activity"/>
+ <event counter="ARM_Mali-Midgard_opencl" title="GPU Vertex-Compute" name="Activity" class="activity" activity1="Activity" activity_color1="0x00ef022f" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 2 Activity"/>
+ </category>
diff --git a/tools/gator/daemon/events-Mali-Midgard_hw.xml b/tools/gator/daemon/events-Mali-Midgard_hw.xml
new file mode 100644
index 000000000000..4f3323f197d7
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-Midgard_hw.xml
@@ -0,0 +1,91 @@
+ <category name="Mali-Midgard Job Manager" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles the GPU was active"/>
+ <event counter="ARM_Mali-Midgard_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles the GPU had a pending interrupt"/>
+ <event counter="ARM_Mali-Midgard_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) was active"/>
+ <event counter="ARM_Mali-Midgard_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) was active"/>
+ <event counter="ARM_Mali-Midgard_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) was active"/>
+ <event counter="ARM_Mali-Midgard_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+ <event counter="ARM_Mali-Midgard_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+ <event counter="ARM_Mali-Midgard_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+ <event counter="ARM_Mali-Midgard_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+ <event counter="ARM_Mali-Midgard_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+ <event counter="ARM_Mali-Midgard_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+ </category>
+ <category name="Mali-Midgard Tiler" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+ <event counter="ARM_Mali-Midgard_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+ <event counter="ARM_Mali-Midgard_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+ <event counter="ARM_Mali-Midgard_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+ <event counter="ARM_Mali-Midgard_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+ <event counter="ARM_Mali-Midgard_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+ <event counter="ARM_Mali-Midgard_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+ <event counter="ARM_Mali-Midgard_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+ <event counter="ARM_Mali-Midgard_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+ <event counter="ARM_Mali-Midgard_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+ <event counter="ARM_Mali-Midgard_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
+ <event counter="ARM_Mali-Midgard_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
+ <event counter="ARM_Mali-Midgard_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
+ <event counter="ARM_Mali-Midgard_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
+ <event counter="ARM_Mali-Midgard_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
+ <event counter="ARM_Mali-Midgard_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
+ <event counter="ARM_Mali-Midgard_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
+ <event counter="ARM_Mali-Midgard_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_1" title="Mali Tiler Commands" name="Prims in 1 command" description="Number of primitives producing 1 command"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_2" title="Mali Tiler Commands" name="Prims in 2 command" description="Number of primitives producing 2 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_3" title="Mali Tiler Commands" name="Prims in 3 command" description="Number of primitives producing 3 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_4" title="Mali Tiler Commands" name="Prims in 4 command" description="Number of primitives producing 4 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_4_7" title="Mali Tiler Commands" name="Prims in 4-7 commands" description="Number of primitives producing 4-7 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_5_7" title="Mali Tiler Commands" name="Prims in 5-7 commands" description="Number of primitives producing 5-7 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_8_15" title="Mali Tiler Commands" name="Prims in 8-15 commands" description="Number of primitives producing 8-15 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_16_63" title="Mali Tiler Commands" name="Prims in 16-63 commands" description="Number of primitives producing 16-63 commands"/>
+ <event counter="ARM_Mali-Midgard_COMMAND_64" title="Mali Tiler Commands" name="Prims in &gt;= 64 commands" description="Number of primitives producing &gt;= 64 commands"/>
+ </category>
+ <category name="Mali-Midgard Shader Core" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles the Tripipe was active"/>
+ <event counter="ARM_Mali-Midgard_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+ <event counter="ARM_Mali-Midgard_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+ <event counter="ARM_Mali-Midgard_FRAG_CYCLE_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+ <event counter="ARM_Mali-Midgard_FRAG_THREADS" title="Mali Core Threads" name="Fragment threads" description="Number of fragment threads started"/>
+ <event counter="ARM_Mali-Midgard_FRAG_DUMMY_THREADS" title="Mali Core Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+ <event counter="ARM_Mali-Midgard_FRAG_QUADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-Midgard_FRAG_QUADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
+ <event counter="ARM_Mali-Midgard_FRAG_THREADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-Midgard_FRAG_THREADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
+ <event counter="ARM_Mali-Midgard_COMPUTE_TASKS" title="Mali Compute Threads" name="Compute tasks" description="Number of compute tasks"/>
+ <event counter="ARM_Mali-Midgard_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads started" description="Number of compute threads started"/>
+ <event counter="ARM_Mali-Midgard_COMPUTE_CYCLES_DESC" title="Mali Compute Threads" name="Compute cycles awaiting descriptors" description="Number of compute cycles spent waiting for descriptors"/>
+ <event counter="ARM_Mali-Midgard_FRAG_PRIMATIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-Midgard_FRAG_PRIMATIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+ <event counter="ARM_Mali-Midgard_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-Midgard_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+ <event counter="ARM_Mali-Midgard_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+ <event counter="ARM_Mali-Midgard_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+ <event counter="ARM_Mali-Midgard_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+ <event counter="ARM_Mali-Midgard_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+ <event counter="ARM_Mali-Midgard_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+ <event counter="ARM_Mali-Midgard_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
+ <event counter="ARM_Mali-Midgard_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+ <event counter="ARM_Mali-Midgard_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+ <event counter="ARM_Mali-Midgard_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+ <event counter="ARM_Mali-Midgard_TEX_THREADS" title="Mali Texture Pipe" name="T instruction issues" description="Number of instructions issused to the T-pipe, including restarts"/>
+ <event counter="ARM_Mali-Midgard_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
+ <event counter="ARM_Mali-Midgard_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+ <event counter="ARM_Mali-Midgard_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+ </category>
+ <category name="Mali-Midgard L2 and MMU" per_cpu="no">
+ <event counter="ARM_Mali-Midgard_L2_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
+ <event counter="ARM_Mali-Midgard_L2_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
+ <event counter="ARM_Mali-Midgard_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
+ <event counter="ARM_Mali-Midgard_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+ <event counter="ARM_Mali-Midgard_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
+ <event counter="ARM_Mali-Midgard_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+ <event counter="ARM_Mali-Midgard_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-Midgard_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+ </category>
diff --git a/tools/gator/daemon/events-Mali-T60x_hw.xml b/tools/gator/daemon/events-Mali-T60x_hw.xml
new file mode 100644
index 000000000000..50797e6492ad
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-T60x_hw.xml
@@ -0,0 +1,108 @@
+
+ <category name="Mali Job Manager" per_cpu="no">
+
+ <event counter="ARM_Mali-T60x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>
+ <event counter="ARM_Mali-T60x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>
+ <event counter="ARM_Mali-T60x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>
+ <event counter="ARM_Mali-T60x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
+ <event counter="ARM_Mali-T60x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
+
+ <event counter="ARM_Mali-T60x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+ <event counter="ARM_Mali-T60x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+ <event counter="ARM_Mali-T60x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+ <event counter="ARM_Mali-T60x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+ <event counter="ARM_Mali-T60x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+ <event counter="ARM_Mali-T60x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+ </category>
+
+ <category name="Mali Tiler" per_cpu="no">
+
+ <event counter="ARM_Mali-T60x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>
+
+ <event counter="ARM_Mali-T60x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+ <event counter="ARM_Mali-T60x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+ <event counter="ARM_Mali-T60x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+ <event counter="ARM_Mali-T60x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+ <event counter="ARM_Mali-T60x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
+ <event counter="ARM_Mali-T60x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+ <event counter="ARM_Mali-T60x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+ <event counter="ARM_Mali-T60x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+ <event counter="ARM_Mali-T60x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+ <event counter="ARM_Mali-T60x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
+ <event counter="ARM_Mali-T60x_TI_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
+ <event counter="ARM_Mali-T60x_TI_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
+
+ </category>
+
+ <category name="Mali Shader Core" per_cpu="no">
+
+ <event counter="ARM_Mali-T60x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>
+ <event counter="ARM_Mali-T60x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+ <event counter="ARM_Mali-T60x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+ <event counter="ARM_Mali-T60x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+
+ <event counter="ARM_Mali-T60x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>
+ <event counter="ARM_Mali-T60x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+ <event counter="ARM_Mali-T60x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-T60x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
+ <event counter="ARM_Mali-T60x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>
+ <event counter="ARM_Mali-T60x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>
+
+ <event counter="ARM_Mali-T60x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-T60x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
+ <event counter="ARM_Mali-T60x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+ <event counter="ARM_Mali-T60x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+ <event counter="ARM_Mali-T60x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
+ <event counter="ARM_Mali-T60x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+ <event counter="ARM_Mali-T60x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
+ <event counter="ARM_Mali-T60x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
+
+ <event counter="ARM_Mali-T60x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+ <event counter="ARM_Mali-T60x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+
+ <event counter="ARM_Mali-T60x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+ <event counter="ARM_Mali-T60x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
+ <event counter="ARM_Mali-T60x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
+
+ <event counter="ARM_Mali-T60x_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+ <event counter="ARM_Mali-T60x_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+ </category>
+
+ <category name="Mali L2 Cache" per_cpu="no">
+
+ <event counter="ARM_Mali-T60x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
+ <event counter="ARM_Mali-T60x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
+ <event counter="ARM_Mali-T60x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T60x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
+ <event counter="ARM_Mali-T60x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
+ <event counter="ARM_Mali-T60x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
+ <event counter="ARM_Mali-T60x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+ <event counter="ARM_Mali-T60x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+ </category>
diff --git a/tools/gator/daemon/events-Mali-T62x_hw.xml b/tools/gator/daemon/events-Mali-T62x_hw.xml
new file mode 100644
index 000000000000..6ecc53c2ada1
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-T62x_hw.xml
@@ -0,0 +1,109 @@
+
+ <category name="Mali Job Manager" per_cpu="no">
+
+ <event counter="ARM_Mali-T62x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>
+ <event counter="ARM_Mali-T62x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>
+ <event counter="ARM_Mali-T62x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>
+ <event counter="ARM_Mali-T62x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
+ <event counter="ARM_Mali-T62x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
+
+ <event counter="ARM_Mali-T62x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+ <event counter="ARM_Mali-T62x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+ <event counter="ARM_Mali-T62x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+ <event counter="ARM_Mali-T62x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+ <event counter="ARM_Mali-T62x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+ <event counter="ARM_Mali-T62x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+ </category>
+
+ <category name="Mali Tiler" per_cpu="no">
+
+ <event counter="ARM_Mali-T62x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>
+
+ <event counter="ARM_Mali-T62x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+ <event counter="ARM_Mali-T62x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+ <event counter="ARM_Mali-T62x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+ <event counter="ARM_Mali-T62x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+ <event counter="ARM_Mali-T62x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
+ <event counter="ARM_Mali-T62x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+ <event counter="ARM_Mali-T62x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+ <event counter="ARM_Mali-T62x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+ <event counter="ARM_Mali-T62x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+ <event counter="ARM_Mali-T62x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
+ <event counter="ARM_Mali-T62x_TI_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
+ <event counter="ARM_Mali-T62x_TI_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
+
+ </category>
+
+ <category name="Mali Shader Core" per_cpu="no">
+
+ <event counter="ARM_Mali-T62x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>
+ <event counter="ARM_Mali-T62x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+ <event counter="ARM_Mali-T62x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+ <event counter="ARM_Mali-T62x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+ <event counter="ARM_Mali-T62x_FRAG_CYCLES_FPKQ_ACTIVE" title="Mali Core Cycles" name="Fragment cycles pre-pipe buffer not empty" description="Number of cycles the pre-pipe queue contains quads"/>
+
+ <event counter="ARM_Mali-T62x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>
+ <event counter="ARM_Mali-T62x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+ <event counter="ARM_Mali-T62x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-T62x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
+ <event counter="ARM_Mali-T62x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>
+ <event counter="ARM_Mali-T62x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>
+
+ <event counter="ARM_Mali-T62x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-T62x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
+ <event counter="ARM_Mali-T62x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+ <event counter="ARM_Mali-T62x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+ <event counter="ARM_Mali-T62x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
+ <event counter="ARM_Mali-T62x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+ <event counter="ARM_Mali-T62x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
+ <event counter="ARM_Mali-T62x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
+
+ <event counter="ARM_Mali-T62x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+ <event counter="ARM_Mali-T62x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+
+ <event counter="ARM_Mali-T62x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+ <event counter="ARM_Mali-T62x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
+ <event counter="ARM_Mali-T62x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
+
+ <event counter="ARM_Mali-T62x_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+ <event counter="ARM_Mali-T62x_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+ </category>
+
+ <category name="Mali L2 Cache" per_cpu="no">
+
+ <event counter="ARM_Mali-T62x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
+ <event counter="ARM_Mali-T62x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
+ <event counter="ARM_Mali-T62x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T62x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
+ <event counter="ARM_Mali-T62x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
+ <event counter="ARM_Mali-T62x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
+ <event counter="ARM_Mali-T62x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+ <event counter="ARM_Mali-T62x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+ </category>
diff --git a/tools/gator/daemon/events-Mali-T6xx.xml b/tools/gator/daemon/events-Mali-T6xx.xml
deleted file mode 100644
index 5e8979704870..000000000000
--- a/tools/gator/daemon/events-Mali-T6xx.xml
+++ /dev/null
@@ -1,46 +0,0 @@
- <category name="Mali-T6xx Software Counters" per_cpu="no">
- <event counter="ARM_Mali-T6xx_TOTAL_ALLOC_PAGES" title="Mali Total Alloc Pages" name="Total number of allocated pages" description="Mali total number of allocated pages."/>
- </category>
- <category name="Mali-T6xx PM Shader" per_cpu="no">
- <event counter="ARM_Mali-T6xx_PM_SHADER_0" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 0" description="Mali PM Shader: PM Shader Core 0."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_1" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 1" description="Mali PM Shader: PM Shader Core 1."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_2" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 2" description="Mali PM Shader: PM Shader Core 2."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_3" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 3" description="Mali PM Shader: PM Shader Core 3."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_4" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 4" description="Mali PM Shader: PM Shader Core 4."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_5" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 5" description="Mali PM Shader: PM Shader Core 5."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_6" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 6" description="Mali PM Shader: PM Shader Core 6."/>
- <event counter="ARM_Mali-T6xx_PM_SHADER_7" class="absolute" display="average" average_selection="yes" percentage="yes" title="Mali PM Shader" name="PM Shader Core 7" description="Mali PM Shader: PM Shader Core 7."/>
- </category>
- <category name="Mali-T6xx PM Tiler" per_cpu="no">
- <event counter="ARM_Mali-T6xx_PM_TILER_0" display="average" average_selection="yes" percentage="yes" title="Mali PM Tiler" name="PM Tiler Core 0" description="Mali PM Tiler: PM Tiler Core 0."/>
- </category>
- <category name="Mali-T6xx PM L2" per_cpu="no">
- <event counter="ARM_Mali-T6xx_PM_L2_0" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 0" description="Mali PM L2: PM L2 Core 0."/>
- <event counter="ARM_Mali-T6xx_PM_L2_1" display="average" average_selection="yes" percentage="yes" title="Mali PM L2" name="PM L2 Core 1" description="Mali PM L2: PM L2 Core 1."/>
- </category>
- <category name="Mali-T6xx MMU Address Space" per_cpu="no">
- <event counter="ARM_Mali-T6xx_MMU_AS_0" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 0" description="Mali MMU Address Space 0 usage."/>
- <event counter="ARM_Mali-T6xx_MMU_AS_1" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 1" description="Mali MMU Address Space 1 usage."/>
- <event counter="ARM_Mali-T6xx_MMU_AS_2" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 2" description="Mali MMU Address Space 2 usage."/>
- <event counter="ARM_Mali-T6xx_MMU_AS_3" display="average" average_selection="yes" percentage="yes" title="Mali MMU Address Space" name="MMU Address Space 3" description="Mali MMU Address Space 3 usage."/>
- </category>
- <category name="Mali-T6xx MMU Page Fault" per_cpu="no">
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_0" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 0" description="Reports the number of newly allocated pages after a MMU page fault in address space 0."/>
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_1" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 1" description="Reports the number of newly allocated pages after a MMU page fault in address space 1."/>
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_2" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 2" description="Reports the number of newly allocated pages after a MMU page fault in address space 2."/>
- <event counter="ARM_Mali-T6xx_MMU_PAGE_FAULT_3" title="Mali MMU Page Fault Add. Space" name="Mali MMU Page Fault Add. Space 3" description="Reports the number of newly allocated pages after a MMU page fault in address space 3."/>
- </category>
- <counter_set name="ARM_Mali-T6xx_Filmstrip_cnt" count="1"/>
- <category name="Mali-T6xx Filmstrip" counter_set="ARM_Mali-T6xx_Filmstrip_cnt" per_cpu="no">
- <option_set name="fs">
- <option event_delta="0x3c" name="1:60" description="captures every 60th frame"/>
- <option event_delta="0x1e" name="1:30" description="captures every 30th frame"/>
- <option event_delta="0xa" name="1:10" description="captures every 10th frame"/>
- </option_set>
- <event event="0x0400" option_set="fs" title="ARM Mali-T6xx" name="Filmstrip" description="Scaled framebuffer"/>
- </category>
- <category name="Mali-T6xx Activity" per_cpu="no">
- <event counter="ARM_Mali-T6xx_fragment" title="GPU Fragment" name="Activity" class="activity" activity1="Activity" activity_color1="0x00006fcc" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 0 Activity"/>
- <event counter="ARM_Mali-T6xx_vertex" title="GPU Vertex-Tiling-Compute" name="Activity" class="activity" activity1="Activity" activity_color1="0x00eda000" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 1 Activity"/>
- <event counter="ARM_Mali-T6xx_opencl" title="GPU Vertex-Compute" name="Activity" class="activity" activity1="Activity" activity_color1="0x00ef022f" rendering_type="bar" average_selection="yes" percentage="yes" cores="1" description="GPU Job Slot 2 Activity"/>
- </category>
diff --git a/tools/gator/daemon/events-Mali-T6xx_hw.xml b/tools/gator/daemon/events-Mali-T6xx_hw.xml
deleted file mode 100644
index df2796262473..000000000000
--- a/tools/gator/daemon/events-Mali-T6xx_hw.xml
+++ /dev/null
@@ -1,91 +0,0 @@
- <category name="Mali-T6xx Job Manager" per_cpu="no">
- <event counter="ARM_Mali-T6xx_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles the GPU was active"/>
- <event counter="ARM_Mali-T6xx_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles the GPU had a pending interrupt"/>
- <event counter="ARM_Mali-T6xx_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) was active"/>
- <event counter="ARM_Mali-T6xx_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) was active"/>
- <event counter="ARM_Mali-T6xx_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) was active"/>
- <event counter="ARM_Mali-T6xx_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
- <event counter="ARM_Mali-T6xx_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
- <event counter="ARM_Mali-T6xx_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
- <event counter="ARM_Mali-T6xx_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
- <event counter="ARM_Mali-T6xx_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
- <event counter="ARM_Mali-T6xx_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
- </category>
- <category name="Mali-T6xx Tiler" per_cpu="no">
- <event counter="ARM_Mali-T6xx_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
- <event counter="ARM_Mali-T6xx_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
- <event counter="ARM_Mali-T6xx_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
- <event counter="ARM_Mali-T6xx_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
- <event counter="ARM_Mali-T6xx_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
- <event counter="ARM_Mali-T6xx_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
- <event counter="ARM_Mali-T6xx_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
- <event counter="ARM_Mali-T6xx_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
- <event counter="ARM_Mali-T6xx_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
- <event counter="ARM_Mali-T6xx_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
- <event counter="ARM_Mali-T6xx_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
- <event counter="ARM_Mali-T6xx_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
- <event counter="ARM_Mali-T6xx_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
- <event counter="ARM_Mali-T6xx_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
- <event counter="ARM_Mali-T6xx_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
- <event counter="ARM_Mali-T6xx_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
- <event counter="ARM_Mali-T6xx_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
- <event counter="ARM_Mali-T6xx_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
- <event counter="ARM_Mali-T6xx_COMMAND_1" title="Mali Tiler Commands" name="Prims in 1 command" description="Number of primitives producing 1 command"/>
- <event counter="ARM_Mali-T6xx_COMMAND_2" title="Mali Tiler Commands" name="Prims in 2 command" description="Number of primitives producing 2 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_3" title="Mali Tiler Commands" name="Prims in 3 command" description="Number of primitives producing 3 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_4" title="Mali Tiler Commands" name="Prims in 4 command" description="Number of primitives producing 4 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_4_7" title="Mali Tiler Commands" name="Prims in 4-7 commands" description="Number of primitives producing 4-7 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_5_7" title="Mali Tiler Commands" name="Prims in 5-7 commands" description="Number of primitives producing 5-7 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_8_15" title="Mali Tiler Commands" name="Prims in 8-15 commands" description="Number of primitives producing 8-15 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_16_63" title="Mali Tiler Commands" name="Prims in 16-63 commands" description="Number of primitives producing 16-63 commands"/>
- <event counter="ARM_Mali-T6xx_COMMAND_64" title="Mali Tiler Commands" name="Prims in &gt;= 64 commands" description="Number of primitives producing &gt;= 64 commands"/>
- </category>
- <category name="Mali-T6xx Shader Core" per_cpu="no">
- <event counter="ARM_Mali-T6xx_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles the Tripipe was active"/>
- <event counter="ARM_Mali-T6xx_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
- <event counter="ARM_Mali-T6xx_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
- <event counter="ARM_Mali-T6xx_FRAG_CYCLE_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
- <event counter="ARM_Mali-T6xx_FRAG_THREADS" title="Mali Core Threads" name="Fragment threads" description="Number of fragment threads started"/>
- <event counter="ARM_Mali-T6xx_FRAG_DUMMY_THREADS" title="Mali Core Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_TEST" title="Mali Core Threads" name="Frag threads doing late ZS" description="Number of threads doing late ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_THREADS_LZS_KILLED" title="Mali Core Threads" name="Frag threads killed late ZS" description="Number of threads killed by late ZS test"/>
- <event counter="ARM_Mali-T6xx_COMPUTE_TASKS" title="Mali Compute Threads" name="Compute tasks" description="Number of compute tasks"/>
- <event counter="ARM_Mali-T6xx_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads started" description="Number of compute threads started"/>
- <event counter="ARM_Mali-T6xx_COMPUTE_CYCLES_DESC" title="Mali Compute Threads" name="Compute cycles awaiting descriptors" description="Number of compute cycles spent waiting for descriptors"/>
- <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
- <event counter="ARM_Mali-T6xx_FRAG_PRIMATIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
- <event counter="ARM_Mali-T6xx_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
- <event counter="ARM_Mali-T6xx_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
- <event counter="ARM_Mali-T6xx_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
- <event counter="ARM_Mali-T6xx_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
- <event counter="ARM_Mali-T6xx_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
- <event counter="ARM_Mali-T6xx_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
- <event counter="ARM_Mali-T6xx_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
- <event counter="ARM_Mali-T6xx_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
- <event counter="ARM_Mali-T6xx_TEX_THREADS" title="Mali Texture Pipe" name="T instruction issues" description="Number of instructions issused to the T-pipe, including restarts"/>
- <event counter="ARM_Mali-T6xx_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
- <event counter="ARM_Mali-T6xx_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
- <event counter="ARM_Mali-T6xx_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
- </category>
- <category name="Mali-T6xx L2 and MMU" per_cpu="no">
- <event counter="ARM_Mali-T6xx_L2_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
- <event counter="ARM_Mali-T6xx_L2_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
- <event counter="ARM_Mali-T6xx_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
- <event counter="ARM_Mali-T6xx_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
- <event counter="ARM_Mali-T6xx_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
- <event counter="ARM_Mali-T6xx_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
- <event counter="ARM_Mali-T6xx_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
- <event counter="ARM_Mali-T6xx_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
- </category>
diff --git a/tools/gator/daemon/events-Mali-T72x_hw.xml b/tools/gator/daemon/events-Mali-T72x_hw.xml
new file mode 100644
index 000000000000..5587534770c8
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-T72x_hw.xml
@@ -0,0 +1,95 @@
+
+ <category name="Mali Job Manager" per_cpu="no">
+
+ <event counter="ARM_Mali-T72x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>
+ <event counter="ARM_Mali-T72x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>
+ <event counter="ARM_Mali-T72x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>
+ <event counter="ARM_Mali-T72x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
+ <event counter="ARM_Mali-T72x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
+
+ <event counter="ARM_Mali-T72x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+ <event counter="ARM_Mali-T72x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+ <event counter="ARM_Mali-T72x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+ <event counter="ARM_Mali-T72x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+ <event counter="ARM_Mali-T72x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+ <event counter="ARM_Mali-T72x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+ </category>
+
+ <category name="Mali Tiler" per_cpu="no">
+
+ <event counter="ARM_Mali-T72x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>
+
+ <event counter="ARM_Mali-T72x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+ <event counter="ARM_Mali-T72x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+ <event counter="ARM_Mali-T72x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+ <event counter="ARM_Mali-T72x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+ <event counter="ARM_Mali-T72x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
+ <event counter="ARM_Mali-T72x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+ <event counter="ARM_Mali-T72x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+ <event counter="ARM_Mali-T72x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+ <event counter="ARM_Mali-T72x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+ <event counter="ARM_Mali-T72x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
+ </category>
+
+ <category name="Mali Shader Core" per_cpu="no">
+
+ <event counter="ARM_Mali-T72x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>
+ <event counter="ARM_Mali-T72x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+ <event counter="ARM_Mali-T72x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+ <event counter="ARM_Mali-T72x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+
+ <event counter="ARM_Mali-T72x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>
+ <event counter="ARM_Mali-T72x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+ <event counter="ARM_Mali-T72x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-T72x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
+ <event counter="ARM_Mali-T72x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>
+ <event counter="ARM_Mali-T72x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>
+
+ <event counter="ARM_Mali-T72x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-T72x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
+ <event counter="ARM_Mali-T72x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+ <event counter="ARM_Mali-T72x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+ <event counter="ARM_Mali-T72x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
+ <event counter="ARM_Mali-T72x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+ <event counter="ARM_Mali-T72x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
+ <event counter="ARM_Mali-T72x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of batched instructions executed by the A-pipe"/>
+
+ <event counter="ARM_Mali-T72x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+ <event counter="ARM_Mali-T72x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+
+ <event counter="ARM_Mali-T72x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+ <event counter="ARM_Mali-T72x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
+
+ <event counter="ARM_Mali-T72x_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+ <event counter="ARM_Mali-T72x_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+ </category>
+
+ <category name="Mali L2 Cache" per_cpu="no">
+
+ <event counter="ARM_Mali-T72x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
+ <event counter="ARM_Mali-T72x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
+ <event counter="ARM_Mali-T72x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
+ <event counter="ARM_Mali-T72x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T72x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
+ <event counter="ARM_Mali-T72x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T72x_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T72x_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T72x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+ <event counter="ARM_Mali-T72x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+
+ </category>
diff --git a/tools/gator/daemon/events-Mali-T76x_hw.xml b/tools/gator/daemon/events-Mali-T76x_hw.xml
new file mode 100644
index 000000000000..be74c5a42624
--- /dev/null
+++ b/tools/gator/daemon/events-Mali-T76x_hw.xml
@@ -0,0 +1,108 @@
+
+ <category name="Mali Job Manager" per_cpu="no">
+
+ <event counter="ARM_Mali-T76x_GPU_ACTIVE" title="Mali Job Manager Cycles" name="GPU cycles" description="Number of cycles GPU active"/>
+ <event counter="ARM_Mali-T76x_IRQ_ACTIVE" title="Mali Job Manager Cycles" name="IRQ cycles" description="Number of cycles GPU interrupt pending"/>
+ <event counter="ARM_Mali-T76x_JS0_ACTIVE" title="Mali Job Manager Cycles" name="JS0 cycles" description="Number of cycles JS0 (fragment) active"/>
+ <event counter="ARM_Mali-T76x_JS1_ACTIVE" title="Mali Job Manager Cycles" name="JS1 cycles" description="Number of cycles JS1 (vertex/tiler/compute) active"/>
+ <event counter="ARM_Mali-T76x_JS2_ACTIVE" title="Mali Job Manager Cycles" name="JS2 cycles" description="Number of cycles JS2 (vertex/compute) active"/>
+
+ <event counter="ARM_Mali-T76x_JS0_JOBS" title="Mali Job Manager Work" name="JS0 jobs" description="Number of Jobs (fragment) completed in JS0"/>
+ <event counter="ARM_Mali-T76x_JS0_TASKS" title="Mali Job Manager Work" name="JS0 tasks" description="Number of Tasks completed in JS0"/>
+ <event counter="ARM_Mali-T76x_JS1_JOBS" title="Mali Job Manager Work" name="JS1 jobs" description="Number of Jobs (vertex/tiler/compute) completed in JS1"/>
+ <event counter="ARM_Mali-T76x_JS1_TASKS" title="Mali Job Manager Work" name="JS1 tasks" description="Number of Tasks completed in JS1"/>
+ <event counter="ARM_Mali-T76x_JS2_TASKS" title="Mali Job Manager Work" name="JS2 tasks" description="Number of Tasks completed in JS2"/>
+ <event counter="ARM_Mali-T76x_JS2_JOBS" title="Mali Job Manager Work" name="JS2 jobs" description="Number of Jobs (vertex/compute) completed in JS2"/>
+
+ </category>
+
+ <category name="Mali Tiler" per_cpu="no">
+
+ <event counter="ARM_Mali-T76x_TI_ACTIVE" title="Mali Tiler Cycles" name="Tiler cycles" description="Number of cycles Tiler active"/>
+
+ <event counter="ARM_Mali-T76x_TI_POLYGONS" title="Mali Tiler Primitives" name="Polygons" description="Number of polygons processed"/>
+ <event counter="ARM_Mali-T76x_TI_QUADS" title="Mali Tiler Primitives" name="Quads" description="Number of quads processed"/>
+ <event counter="ARM_Mali-T76x_TI_TRIANGLES" title="Mali Tiler Primitives" name="Triangles" description="Number of triangles processed"/>
+ <event counter="ARM_Mali-T76x_TI_LINES" title="Mali Tiler Primitives" name="Lines" description="Number of lines processed"/>
+ <event counter="ARM_Mali-T76x_TI_POINTS" title="Mali Tiler Primitives" name="Points" description="Number of points processed"/>
+
+ <event counter="ARM_Mali-T76x_TI_FRONT_FACING" title="Mali Tiler Culling" name="Front facing prims" description="Number of front facing primitives"/>
+ <event counter="ARM_Mali-T76x_TI_BACK_FACING" title="Mali Tiler Culling" name="Back facing prims" description="Number of back facing primitives"/>
+ <event counter="ARM_Mali-T76x_TI_PRIM_VISIBLE" title="Mali Tiler Culling" name="Visible prims" description="Number of visible primitives"/>
+ <event counter="ARM_Mali-T76x_TI_PRIM_CULLED" title="Mali Tiler Culling" name="Culled prims" description="Number of culled primitives"/>
+ <event counter="ARM_Mali-T76x_TI_PRIM_CLIPPED" title="Mali Tiler Culling" name="Clipped prims" description="Number of clipped primitives"/>
+
+ <event counter="ARM_Mali-T76x_TI_LEVEL0" title="Mali Tiler Hierarchy" name="L0 prims" description="Number of primitives in hierarchy level 0"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL1" title="Mali Tiler Hierarchy" name="L1 prims" description="Number of primitives in hierarchy level 1"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL2" title="Mali Tiler Hierarchy" name="L2 prims" description="Number of primitives in hierarchy level 2"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL3" title="Mali Tiler Hierarchy" name="L3 prims" description="Number of primitives in hierarchy level 3"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL4" title="Mali Tiler Hierarchy" name="L4 prims" description="Number of primitives in hierarchy level 4"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL5" title="Mali Tiler Hierarchy" name="L5 prims" description="Number of primitives in hierarchy level 5"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL6" title="Mali Tiler Hierarchy" name="L6 prims" description="Number of primitives in hierarchy level 6"/>
+ <event counter="ARM_Mali-T76x_TI_LEVEL7" title="Mali Tiler Hierarchy" name="L7 prims" description="Number of primitives in hierarchy level 7"/>
+
+ </category>
+
+ <category name="Mali Shader Core" per_cpu="no">
+
+ <event counter="ARM_Mali-T76x_TRIPIPE_ACTIVE" title="Mali Core Cycles" name="Tripipe cycles" description="Number of cycles tripipe was active"/>
+ <event counter="ARM_Mali-T76x_FRAG_ACTIVE" title="Mali Core Cycles" name="Fragment cycles" description="Number of cycles fragment processing was active"/>
+ <event counter="ARM_Mali-T76x_COMPUTE_ACTIVE" title="Mali Core Cycles" name="Compute cycles" description="Number of cycles vertex\compute processing was active"/>
+ <event counter="ARM_Mali-T76x_FRAG_CYCLES_NO_TILE" title="Mali Core Cycles" name="Fragment cycles waiting for tile" description="Number of cycles spent waiting for a physical tile buffer"/>
+ <event counter="ARM_Mali-T76x_FRAG_CYCLES_FPKQ_ACTIVE" title="Mali Core Cycles" name="Fragment cycles pre-pipe buffer not empty" description="Number of cycles the pre-pipe queue contains quads"/>
+
+ <event counter="ARM_Mali-T76x_FRAG_THREADS" title="Mali Fragment Threads" name="Fragment threads" description="Number of fragment threads started"/>
+ <event counter="ARM_Mali-T76x_FRAG_DUMMY_THREADS" title="Mali Fragment Threads" name="Dummy fragment threads" description="Number of dummy fragment threads started"/>
+ <event counter="ARM_Mali-T76x_FRAG_THREADS_LZS_TEST" title="Mali Fragment Threads" name="Fragment threads doing late ZS" description="Number of threads doing late ZS test"/>
+ <event counter="ARM_Mali-T76x_FRAG_THREADS_LZS_KILLED" title="Mali Fragment Threads" name="Fragment threads killed late ZS" description="Number of threads killed by late ZS test"/>
+
+ <event counter="ARM_Mali-T76x_COMPUTE_TASKS" title="Mali Compute Tasks" name="Compute tasks" description="Number of compute tasks"/>
+ <event counter="ARM_Mali-T76x_COMPUTE_THREADS" title="Mali Compute Threads" name="Compute threads" description="Number of compute threads started"/>
+
+ <event counter="ARM_Mali-T76x_FRAG_PRIMITIVES" title="Mali Fragment Primitives" name="Primitives loaded" description="Number of primitives loaded from tiler"/>
+ <event counter="ARM_Mali-T76x_FRAG_PRIMITIVES_DROPPED" title="Mali Fragment Primitives" name="Primitives dropped" description="Number of primitives dropped because out of tile"/>
+
+ <event counter="ARM_Mali-T76x_FRAG_QUADS_RAST" title="Mali Fragment Quads" name="Quads rasterized" description="Number of quads rasterized"/>
+ <event counter="ARM_Mali-T76x_FRAG_QUADS_EZS_TEST" title="Mali Fragment Quads" name="Quads doing early ZS" description="Number of quads doing early ZS test"/>
+ <event counter="ARM_Mali-T76x_FRAG_QUADS_EZS_KILLED" title="Mali Fragment Quads" name="Quads killed early Z" description="Number of quads killed by early ZS test"/>
+
+ <event counter="ARM_Mali-T76x_FRAG_NUM_TILES" title="Mali Fragment Tasks" name="Tiles rendered" description="Number of tiles rendered"/>
+ <event counter="ARM_Mali-T76x_FRAG_TRANS_ELIM" title="Mali Fragment Tasks" name="Tile writes killed by TE" description="Number of tile writes skipped by transaction elimination"/>
+
+ <event counter="ARM_Mali-T76x_ARITH_WORDS" title="Mali Arithmetic Pipe" name="A instructions" description="Number of instructions completed by the the A-pipe (normalized per pipeline)"/>
+
+ <event counter="ARM_Mali-T76x_LS_WORDS" title="Mali Load/Store Pipe" name="LS instructions" description="Number of instructions completed by the LS-pipe"/>
+ <event counter="ARM_Mali-T76x_LS_ISSUES" title="Mali Load/Store Pipe" name="LS instruction issues" description="Number of instructions issued to the LS-pipe, including restarts"/>
+
+ <event counter="ARM_Mali-T76x_TEX_WORDS" title="Mali Texture Pipe" name="T instructions" description="Number of instructions completed by the T-pipe"/>
+ <event counter="ARM_Mali-T76x_TEX_ISSUES" title="Mali Texture Pipe" name="T instruction issues" description="Number of threads through loop 2 address calculation"/>
+ <event counter="ARM_Mali-T76x_TEX_RECIRC_FMISS" title="Mali Texture Pipe" name="Cache misses" description="Number of instructions in the T-pipe, recirculated due to cache miss"/>
+
+ <event counter="ARM_Mali-T76x_LSC_READ_HITS" title="Mali Load/Store Cache" name="Read hits" description="Number of read hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T76x_LSC_READ_MISSES" title="Mali Load/Store Cache" name="Read misses" description="Number of read misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T76x_LSC_WRITE_HITS" title="Mali Load/Store Cache" name="Write hits" description="Number of write hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T76x_LSC_WRITE_MISSES" title="Mali Load/Store Cache" name="Write misses" description="Number of write misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T76x_LSC_ATOMIC_HITS" title="Mali Load/Store Cache" name="Atomic hits" description="Number of atomic hits in the Load/Store cache"/>
+ <event counter="ARM_Mali-T76x_LSC_ATOMIC_MISSES" title="Mali Load/Store Cache" name="Atomic misses" description="Number of atomic misses in the Load/Store cache"/>
+ <event counter="ARM_Mali-T76x_LSC_LINE_FETCHES" title="Mali Load/Store Cache" name="Line fetches" description="Number of line fetches in the Load/Store cache"/>
+ <event counter="ARM_Mali-T76x_LSC_DIRTY_LINE" title="Mali Load/Store Cache" name="Dirty line evictions" description="Number of dirty line evictions in the Load/Store cache"/>
+ <event counter="ARM_Mali-T76x_LSC_SNOOPS" title="Mali Load/Store Cache" name="Snoops in to LSC" description="Number of coherent memory snoops in to the Load/Store cache"/>
+
+ </category>
+
+ <category name="Mali L2 Cache" per_cpu="no">
+
+ <event counter="ARM_Mali-T76x_L2_EXT_WRITE_BEATS" title="Mali L2 Cache" name="External write beats" description="Number of external bus write beats"/>
+ <event counter="ARM_Mali-T76x_L2_EXT_READ_BEATS" title="Mali L2 Cache" name="External read beats" description="Number of external bus read beats"/>
+ <event counter="ARM_Mali-T76x_L2_READ_SNOOP" title="Mali L2 Cache" name="Read snoops" description="Number of read transaction snoops"/>
+ <event counter="ARM_Mali-T76x_L2_READ_HIT" title="Mali L2 Cache" name="L2 read hits" description="Number of reads hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T76x_L2_WRITE_SNOOP" title="Mali L2 Cache" name="Write snoops" description="Number of write transaction snoops"/>
+ <event counter="ARM_Mali-T76x_L2_WRITE_HIT" title="Mali L2 Cache" name="L2 write hits" description="Number of writes hitting in the L2 cache"/>
+ <event counter="ARM_Mali-T76x_L2_EXT_AR_STALL" title="Mali L2 Cache" name="External bus stalls (AR)" description="Number of cycles a valid read address (AR) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T76x_L2_EXT_W_STALL" title="Mali L2 Cache" name="External bus stalls (W)" description="Number of cycles a valid write data (W channel) is stalled by the external interconnect"/>
+ <event counter="ARM_Mali-T76x_L2_EXT_R_BUF_FULL" title="Mali L2 Cache" name="External bus response buffer full" description="Number of cycles a valid request is blocked by a full response buffer"/>
+ <event counter="ARM_Mali-T76x_L2_EXT_RD_BUF_FULL" title="Mali L2 Cache" name="External bus read data buffer full" description="Number of cycles a valid request is blocked by a full read data buffer"/>
+ <event counter="ARM_Mali-T76x_L2_EXT_W_BUF_FULL" title="Mali L2 Cache" name="External bus write buffer full" description="Number of cycles a valid request is blocked by a full write buffer"/>
+ <event counter="ARM_Mali-T76x_L2_READ_LOOKUP" title="Mali L2 Cache" name="L2 read lookups" description="Number of reads into the L2 cache"/>
+ <event counter="ARM_Mali-T76x_L2_WRITE_LOOKUP" title="Mali L2 Cache" name="L2 write lookups" description="Number of writes into the L2 cache"/>
+ </category>
diff --git a/tools/gator/daemon/events-Mali-V500.xml b/tools/gator/daemon/events-Mali-V500.xml
index d2751e7239b5..89bc7f4734df 100644
--- a/tools/gator/daemon/events-Mali-V500.xml
+++ b/tools/gator/daemon/events-Mali-V500.xml
@@ -1,29 +1,30 @@
<category name="Mali-V500">
- <event counter="ARM_Mali-V500_cnt0" title="Mali Video Engine" name="Samples" class="absolute" description="The number of times we have taken a sample"/>
- <event counter="ARM_Mali-V500_cnt1" title="Mali Video Engine" name="Queued input-buffers" class="absolute" description="The number of input-buffers that has been queued for consumption by the MVE"/>
- <event counter="ARM_Mali-V500_cnt2" title="Mali Video Engine" name="Consumed input-buffers" class="absolute" description="The number of input-buffers that has been consumed by the MVE and returned to the application"/>
- <event counter="ARM_Mali-V500_cnt3" title="Mali Video Engine" name="Queued output-buffers" class="absolute" description="The number of output-buffers that has been queued for usage by the MVE"/>
- <event counter="ARM_Mali-V500_cnt4" title="Mali Video Engine" name="Consumed output-buffers" class="absolute" description="The number of output-buffers that has been consumed by the MVE and returned to the application"/>
- <event counter="ARM_Mali-V500_cnt5" title="Mali Video Engine" name="Created Sessions" class="absolute" description="The number of created sessions throughout the lifetime of the process"/>
- <event counter="ARM_Mali-V500_cnt6" title="Mali Video Engine" name="Active Sessions" description="The number of currently existing sessions"/>
- <event counter="ARM_Mali-V500_cnt7" title="Mali Video Engine" name="Processed Frames" class="absolute" description="The number of processed frames. A processed frame is one where the encode or decode is complete for that particular frame. Frames can be processed out of order so this is not the same as the number of output-buffers returned"/>
- <event counter="ARM_Mali-V500_cnt8" title="Mali Video Engine" name="Input Flushes Requested" class="absolute" description="The number of requested flushes of the input queue"/>
- <event counter="ARM_Mali-V500_cnt9" title="Mali Video Engine" name="Input Flushes Complete" class="absolute" description="The number of completed flushes of the input queue"/>
- <event counter="ARM_Mali-V500_cnt10" title="Mali Video Engine" name="Output Flushes Requested" class="absolute" description="The number of requested flushes of the output queue"/>
- <event counter="ARM_Mali-V500_cnt11" title="Mali Video Engine" name="Output Flushes Complete" class="absolute" description="The number of completed flushes of the output queue"/>
- <event counter="ARM_Mali-V500_cnt12" title="Mali Video Engine" name="Queued Output Buffers (current)" description="The number of output-buffers that are currently queued for usage by the MVE"/>
- <event counter="ARM_Mali-V500_cnt13" title="Mali Video Engine" name="Queued Input Buffers (current)" description="The number of input-buffers that are currently queued for consumption by the MVE"/>
- <event counter="ARM_Mali-V500_cnt14" title="Mali Video Engine" name="Output Queue Flushes" description="The number of pending flushes for the MVE output-queue"/>
- <event counter="ARM_Mali-V500_cnt15" title="Mali Video Engine" name="Input Queue Flushes" description="The number of pending flushes for the MVE input-queue"/>
- <event counter="ARM_Mali-V500_cnt16" title="Mali Video Engine" name="Errors encountered" class="absolute" description="The number of errors encountered"/>
- <event counter="ARM_Mali-V500_cnt17" title="Mali Video Engine" name="Bits consumed" class="absolute" description="The number of bits consumed during decode"/>
- <event counter="ARM_Mali-V500_cnt18" title="Mali Video Engine" name="AFBC bandwidth" class="absolute" description="The amount of AFBC-encoded bytes read or written"/>
- <event counter="ARM_Mali-V500_cnt19" title="Mali Video Engine" name="Bandwidth (read)" class="absolute" description="The amount of bytes read over the AXI bus"/>
- <event counter="ARM_Mali-V500_cnt20" title="Mali Video Engine" name="Bandwidth (write)" class="absolute" description="The amount of bytes written over the AXI bus"/>
- <event counter="ARM_Mali-V500_evn0" title="Mali Video Engine" name="Session created" description="Generated when a session has been created"/>
- <event counter="ARM_Mali-V500_evn1" title="Mali Video Engine" name="Session destroyed" description="Generated when a session has been destroyed"/>
- <event counter="ARM_Mali-V500_evn2" title="Mali Video Engine" name="Frame Processed" description="Generated when the MVE has finished processing a frame"/>
- <event counter="ARM_Mali-V500_evn3" title="Mali Video Engine" name="Output buffer received" description="Generated when an an output buffer is returned to us from the MVE"/>
- <event counter="ARM_Mali-V500_evn4" title="Mali Video Engine" name="Input buffer received" description="Generated when we an input buffer is returned to us from the MVE"/>
- <!--event counter="ARM_Mali-V500_act" title="VPU" name="Activity" class="activity" activity1="Parsed" activity_color1="0x000000ff" activity2="Piped" activity_color2="0x0000ff00" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" cores="8" description="Mali-V500 Activity"/-->
+ <event counter="ARM_Mali-V500_cnt0" title="MVE-V500 Stats" name="Samples" class="absolute" description="The number of times we have taken a sample"/>
+ <event counter="ARM_Mali-V500_cnt1" title="MVE-V500 Input Totals" name="Queued input-buffers" class="absolute" description="The number of input-buffers that has been queued for consumption by the MVE"/>
+ <event counter="ARM_Mali-V500_cnt2" title="MVE-V500 Input Totals" name="Consumed input-buffers" class="absolute" description="The number of input-buffers that has been consumed by the MVE and returned to the application"/>
+ <event counter="ARM_Mali-V500_cnt3" title="MVE-V500 Output Totals" name="Queued output-buffers" class="absolute" description="The number of output-buffers that has been queued for usage by the MVE"/>
+ <event counter="ARM_Mali-V500_cnt4" title="MVE-V500 Output Totals" name="Consumed output-buffers" class="absolute" description="The number of output-buffers that has been consumed by the MVE and returned to the application"/>
+ <event counter="ARM_Mali-V500_cnt5" title="MVE-V500 Stats" name="Created Sessions" class="absolute" description="The number of created sessions throughout the lifetime of the process"/>
+ <event counter="ARM_Mali-V500_cnt6" title="MVE-V500 Sessions" name="Active Sessions" description="The number of currently existing sessions"/>
+ <event counter="ARM_Mali-V500_cnt7" title="MVE-V500 Stats" name="Processed Frames" class="absolute" description="The number of processed frames. A processed frame is one where the encode or decode is complete for that particular frame. Frames can be processed out of order so this is not the same as the number of output-buffers returned"/>
+ <event counter="ARM_Mali-V500_cnt8" title="MVE-V500 Input Totals" name="Input Flushes Requested" class="absolute" description="The number of requested flushes of the input queue"/>
+ <event counter="ARM_Mali-V500_cnt9" title="MVE-V500 Input Totals" name="Input Flushes Complete" class="absolute" description="The number of completed flushes of the input queue"/>
+ <event counter="ARM_Mali-V500_cnt10" title="MVE-V500 Output Totals" name="Output Flushes Requested" class="absolute" description="The number of requested flushes of the output queue"/>
+ <event counter="ARM_Mali-V500_cnt11" title="MVE-V500 Output Totals" name="Output Flushes Complete" class="absolute" description="The number of completed flushes of the output queue"/>
+ <event counter="ARM_Mali-V500_cnt12" title="MVE-V500 Output" name="Queued Output Buffers (current)" description="The number of output-buffers that are currently queued for usage by the MVE"/>
+ <event counter="ARM_Mali-V500_cnt13" title="MVE-V500 Input" name="Queued Input Buffers (current)" description="The number of input-buffers that are currently queued for consumption by the MVE"/>
+ <event counter="ARM_Mali-V500_cnt14" title="MVE-V500 Output" name="Output Queue Flushes" description="The number of pending flushes for the MVE output-queue"/>
+ <event counter="ARM_Mali-V500_cnt15" title="MVE-V500 Input" name="Input Queue Flushes" description="The number of pending flushes for the MVE input-queue"/>
+ <event counter="ARM_Mali-V500_cnt16" title="MVE-V500 Stats" name="Errors encountered" class="absolute" description="The number of errors encountered"/>
+ <event counter="ARM_Mali-V500_cnt17" title="MVE-V500 Bandwidth" name="Bits consumed" class="absolute" description="The number of bits consumed during decode"/>
+ <event counter="ARM_Mali-V500_cnt18" title="MVE-V500 Bandwidth" name="AFBC bandwidth" class="absolute" description="The amount of AFBC-encoded bytes read or written"/>
+ <event counter="ARM_Mali-V500_cnt19" title="MVE-V500 Bandwidth" name="Bandwidth (read)" class="absolute" description="The amount of bytes read over the AXI bus"/>
+ <event counter="ARM_Mali-V500_cnt20" title="MVE-V500 Bandwidth" name="Bandwidth (write)" class="absolute" description="The amount of bytes written over the AXI bus"/>
+ <event counter="ARM_Mali-V500_evn0" title="MVE-V500 Sessions" name="Session created" description="Generated when a session has been created"/>
+ <event counter="ARM_Mali-V500_evn1" title="MVE-V500 Sessions" name="Session destroyed" description="Generated when a session has been destroyed"/>
+ <event counter="ARM_Mali-V500_evn2" title="MVE-V500 Frames" name="Frame Processed" description="Generated when the MVE has finished processing a frame"/>
+ <event counter="ARM_Mali-V500_evn3" title="MVE-V500 Output" name="Output buffer received" description="Generated when an an output buffer is returned to us from the MVE"/>
+ <event counter="ARM_Mali-V500_evn4" title="MVE-V500 Input" name="Input buffer received" description="Generated when we an input buffer is returned to us from the MVE"/>
+ <event counter="ARM_Mali-V500_act0" title="MVE-V500 Parsed" name="Activity" class="activity" activity1="activity" activity_color1="0x000000ff" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" cores="8" description="Mali-V500 Activity"/>
+ <event counter="ARM_Mali-V500_act1" title="MVE-V500 Piped" name="Activity" class="activity" activity1="activity" activity_color1="0x0000ff00" rendering_type="bar" average_selection="yes" average_cores="yes" percentage="yes" cores="8" description="Mali-V500 Activity"/>
</category>
diff --git a/tools/gator/daemon/events-ftrace.xml b/tools/gator/daemon/events-ftrace.xml
new file mode 100644
index 000000000000..33ab7aab2196
--- /dev/null
+++ b/tools/gator/daemon/events-ftrace.xml
@@ -0,0 +1,7 @@
+ <category name="Ftrace">
+ <!-- counter attribute must start with ftrace_ and be unique -->
+ <!-- regex item in () is the value shown -->
+ <!--
+ <event counter="ftrace_trace_marker_numbers" title="ftrace" name="trace_marker" class="absolute" regex="([0-9]+)" description="Numbers written to /sys/kernel/debug/tracing/trace_marker, ex: echo 42 > /sys/kernel/debug/tracing/trace_marker"/>
+ -->
+ </category>
diff --git a/tools/gator/daemon/main.cpp b/tools/gator/daemon/main.cpp
index 2998c7012221..fbce1e15d0d0 100644
--- a/tools/gator/daemon/main.cpp
+++ b/tools/gator/daemon/main.cpp
@@ -19,16 +19,15 @@
#include <sys/wait.h>
#include <unistd.h>
+#include "CCNDriver.h"
#include "Child.h"
#include "EventsXML.h"
-#include "KMod.h"
#include "Logging.h"
#include "Monitor.h"
#include "OlySocket.h"
#include "OlyUtility.h"
#include "SessionData.h"
-
-#define DEBUG false
+#include "Setup.h"
extern Child* child;
static int shutdownFilesystem();
@@ -40,8 +39,9 @@ static bool driverRunningAtStart = false;
static bool driverMountedAtStart = false;
struct cmdline_t {
+ char *module;
int port;
- char* module;
+ bool update;
};
#define DEFAULT_PORT 8080
@@ -105,7 +105,6 @@ static void child_exit(int) {
}
}
-static const int UDP_ANS_PORT = 30000;
static const int UDP_REQ_PORT = 30001;
typedef struct {
@@ -125,11 +124,10 @@ static const char DST_REQ[] = { 'D', 'S', 'T', '_', 'R', 'E', 'Q', ' ', 0, 0, 0,
class UdpListener {
public:
- UdpListener() : mDstAns(), mReq(-1), mAns(-1) {}
+ UdpListener() : mDstAns(), mReq(-1) {}
void setup(int port) {
mReq = udpPort(UDP_REQ_PORT);
- mAns = udpPort(UDP_ANS_PORT);
// Format the answer buffer
memset(&mDstAns, 0, sizeof(mDstAns));
@@ -161,16 +159,13 @@ public:
logg->logError(__FILE__, __LINE__, "recvfrom failed");
handleException();
} else if ((read == 12) && (memcmp(buf, DST_REQ, sizeof(DST_REQ)) == 0)) {
- if (sendto(mAns, &mDstAns, sizeof(mDstAns), 0, (struct sockaddr *)&sockaddr, addrlen) != sizeof(mDstAns)) {
- logg->logError(__FILE__, __LINE__, "sendto failed");
- handleException();
- }
+ // Don't care if sendto fails - gatord shouldn't exit because of it and Streamline will retry
+ sendto(mReq, &mDstAns, sizeof(mDstAns), 0, (struct sockaddr *)&sockaddr, addrlen);
}
}
void close() {
::close(mReq);
- ::close(mAns);
}
private:
@@ -180,10 +175,10 @@ private:
int on;
int family = AF_INET6;
- s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ s = socket_cloexec(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
if (s == -1) {
family = AF_INET;
- s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ s = socket_cloexec(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s == -1) {
logg->logError(__FILE__, __LINE__, "socket failed");
handleException();
@@ -210,7 +205,6 @@ private:
RVIConfigureInfo mDstAns;
int mReq;
- int mAns;
};
static UdpListener udpListener;
@@ -233,7 +227,7 @@ static int mountGatorFS() {
static bool init_module (const char * const location) {
bool ret(false);
- const int fd = open(location, O_RDONLY);
+ const int fd = open(location, O_RDONLY | O_CLOEXEC);
if (fd >= 0) {
struct stat st;
if (fstat(fd, &st) == 0) {
@@ -332,10 +326,26 @@ static int shutdownFilesystem() {
return 0; // success
}
+static const char OPTSTRING[] = "hvudap:s:c:e:m:o:";
+
+static bool hasDebugFlag(int argc, char** argv) {
+ int c;
+
+ optind = 1;
+ while ((c = getopt(argc, argv, OPTSTRING)) != -1) {
+ if (c == 'd') {
+ return true;
+ }
+ }
+
+ return false;
+}
+
static struct cmdline_t parseCommandLine(int argc, char** argv) {
struct cmdline_t cmdline;
cmdline.port = DEFAULT_PORT;
cmdline.module = NULL;
+ cmdline.update = false;
char version_string[256]; // arbitrary length to hold the version information
int c;
@@ -346,11 +356,15 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
snprintf(version_string, sizeof(version_string), "Streamline gatord development version %d", PROTOCOL_VERSION);
}
- while ((c = getopt(argc, argv, "hvp:s:c:e:m:o:")) != -1) {
- switch(c) {
+ optind = 1;
+ while ((c = getopt(argc, argv, OPTSTRING)) != -1) {
+ switch (c) {
case 'c':
gSessionData->mConfigurationXMLPath = optarg;
break;
+ case 'd':
+ // Already handled
+ break;
case 'e':
gSessionData->mEventsXMLPath = optarg;
break;
@@ -366,6 +380,12 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
case 'o':
gSessionData->mTargetPath = optarg;
break;
+ case 'u':
+ cmdline.update = true;
+ break;
+ case 'a':
+ gSessionData->mAllowCommands = true;
+ break;
case 'h':
case '?':
logg->logError(__FILE__, __LINE__,
@@ -375,9 +395,11 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
"-h this help page\n"
"-m module path and filename of gator.ko\n"
"-p port_number port upon which the server listens; default is 8080\n"
- "-s session_xml path and filename of a session xml used for local capture\n"
+ "-s session_xml path and filename of a session.xml used for local capture\n"
"-o apc_dir path and name of the output for a local capture\n"
"-v version information\n"
+ "-d enable debug messages\n"
+ "-a allow the user user to provide a command to run at the start of a capture"
, version_string);
handleException();
break;
@@ -407,7 +429,7 @@ static struct cmdline_t parseCommandLine(int argc, char** argv) {
return cmdline;
}
-void handleClient() {
+static void handleClient() {
OlySocket client(sock->acceptConnection());
int pid = fork();
@@ -452,12 +474,15 @@ int main(int argc, char** argv) {
// e.g. it may not be the group leader when launched as 'sudo gatord'
setsid();
- logg = new Logging(DEBUG); // Set up global thread-safe logging
- gSessionData = new SessionData(); // Global data class
- util = new OlyUtility(); // Set up global utility class
+ // Set up global thread-safe logging
+ logg = new Logging(hasDebugFlag(argc, argv));
+ // Global data class
+ gSessionData = new SessionData();
+ // Set up global utility class
+ util = new OlyUtility();
// Initialize drivers
- new KMod();
+ new CCNDriver();
prctl(PR_SET_NAME, (unsigned long)&"gatord-main", 0, 0, 0);
pthread_mutex_init(&numSessions_mutex, NULL);
@@ -474,6 +499,10 @@ int main(int argc, char** argv) {
// Parse the command line parameters
struct cmdline_t cmdline = parseCommandLine(argc, argv);
+ if (cmdline.update) {
+ return update(argv[0]);
+ }
+
// Verify root permissions
uid_t euid = geteuid();
if (euid) {
@@ -490,17 +519,18 @@ int main(int argc, char** argv) {
" >>> gator.ko should be co-located with gatord in the same directory\n"
" >>> OR insmod gator.ko prior to launching gatord\n"
" >>> OR specify the location of gator.ko on the command line\n"
- " >>> OR run Linux 3.4 or later with perf (CONFIG_PERF_EVENTS and CONFIG_HW_PERF_EVENTS) and tracing (CONFIG_TRACING) support to collect data via userspace only");
+ " >>> OR run Linux 3.4 or later with perf (CONFIG_PERF_EVENTS and CONFIG_HW_PERF_EVENTS) and tracing (CONFIG_TRACING and CONFIG_CONTEXT_SWITCH_TRACER) support to collect data via userspace only");
handleException();
}
}
- gSessionData->hwmon.setup();
{
EventsXML eventsXML;
mxml_node_t *xml = eventsXML.getTree();
- gSessionData->fsDriver.setup(xml);
- gSessionData->maliVideo.setup(xml);
+ // Initialize all drivers
+ for (Driver *driver = Driver::getHead(); driver != NULL; driver = driver->getNext()) {
+ driver->readEvents(xml);
+ }
mxmlDelete(xml);
}
@@ -517,9 +547,14 @@ int main(int argc, char** argv) {
child->run();
delete child;
} else {
+ gSessionData->annotateListener.setup();
sock = new OlyServerSocket(cmdline.port);
udpListener.setup(cmdline.port);
- if (!monitor.init() || !monitor.add(sock->getFd()) || !monitor.add(udpListener.getReq())) {
+ if (!monitor.init() ||
+ !monitor.add(sock->getFd()) ||
+ !monitor.add(udpListener.getReq()) ||
+ !monitor.add(gSessionData->annotateListener.getFd()) ||
+ false) {
logg->logError(__FILE__, __LINE__, "Monitor setup failed");
handleException();
}
@@ -537,6 +572,8 @@ int main(int argc, char** argv) {
handleClient();
} else if (events[i].data.fd == udpListener.getReq()) {
udpListener.handle();
+ } else if (events[i].data.fd == gSessionData->annotateListener.getFd()) {
+ gSessionData->annotateListener.handle();
}
}
}
diff --git a/tools/gator/daemon/mxml/config.h b/tools/gator/daemon/mxml/config.h
index 1f59ba34a474..ad6df1d7debe 100644
--- a/tools/gator/daemon/mxml/config.h
+++ b/tools/gator/daemon/mxml/config.h
@@ -1,10 +1,10 @@
/* config.h. Generated from config.h.in by configure. */
/*
- * "$Id: config.h.in 408 2010-09-19 05:26:46Z mike $"
+ * "$Id: config.h.in 451 2014-01-04 21:50:06Z msweet $"
*
* Configuration file for Mini-XML, a small XML-like file parsing library.
*
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -12,7 +12,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -30,7 +30,7 @@
* Version number...
*/
-#define MXML_VERSION "Mini-XML v2.7"
+#define MXML_VERSION "Mini-XML v2.8"
/*
@@ -92,5 +92,5 @@ extern int _mxml_vsnprintf(char *, size_t, const char *, va_list);
# endif /* !HAVE_VSNPRINTF */
/*
- * End of "$Id: config.h.in 408 2010-09-19 05:26:46Z mike $".
+ * End of "$Id: config.h.in 451 2014-01-04 21:50:06Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml-attr.c b/tools/gator/daemon/mxml/mxml-attr.c
index c9950f5fb732..8e89cc1474f8 100644
--- a/tools/gator/daemon/mxml/mxml-attr.c
+++ b/tools/gator/daemon/mxml/mxml-attr.c
@@ -1,9 +1,9 @@
/*
- * "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $"
+ * "$Id: mxml-attr.c 451 2014-01-04 21:50:06Z msweet $"
*
* Attribute support code for Mini-XML, a small XML-like file parsing library.
*
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -11,15 +11,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlElementDeleteAttr() - Delete an attribute.
- * mxmlElementGetAttr() - Get an attribute.
- * mxmlElementSetAttr() - Set an attribute.
- * mxmlElementSetAttrf() - Set an attribute with a formatted value.
- * mxml_set_attr() - Set or add an attribute name/value pair.
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -90,6 +82,9 @@ mxmlElementDeleteAttr(mxml_node_t *node,/* I - Element */
memmove(attr, attr + 1, i * sizeof(mxml_attr_t));
node->value.element.num_attrs --;
+
+ if (node->value.element.num_attrs == 0)
+ free(node->value.element.attrs);
return;
}
}
@@ -315,5 +310,5 @@ mxml_set_attr(mxml_node_t *node, /* I - Element node */
/*
- * End of "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $".
+ * End of "$Id: mxml-attr.c 451 2014-01-04 21:50:06Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml-entity.c b/tools/gator/daemon/mxml/mxml-entity.c
index c5c9f61f73c2..0d11df6a70bc 100644
--- a/tools/gator/daemon/mxml/mxml-entity.c
+++ b/tools/gator/daemon/mxml/mxml-entity.c
@@ -1,10 +1,10 @@
/*
- * "$Id: mxml-entity.c 408 2010-09-19 05:26:46Z mike $"
+ * "$Id: mxml-entity.c 451 2014-01-04 21:50:06Z msweet $"
*
* Character entity support code for Mini-XML, a small XML-like
* file parsing library.
*
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -12,18 +12,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlEntityAddCallback() - Add a callback to convert entities to
- * Unicode.
- * mxmlEntityGetName() - Get the name that corresponds to the
- * character value.
- * mxmlEntityGetValue() - Get the character corresponding to a named
- * entity.
- * mxmlEntityRemoveCallback() - Remove a callback.
- * _mxml_entity_cb() - Lookup standard (X)HTML entities.
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -456,5 +445,5 @@ _mxml_entity_cb(const char *name) /* I - Entity name */
/*
- * End of "$Id: mxml-entity.c 408 2010-09-19 05:26:46Z mike $".
+ * End of "$Id: mxml-entity.c 451 2014-01-04 21:50:06Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml-file.c b/tools/gator/daemon/mxml/mxml-file.c
index 7860ee5f8370..3812c253fc3e 100644
--- a/tools/gator/daemon/mxml/mxml-file.c
+++ b/tools/gator/daemon/mxml/mxml-file.c
@@ -1,9 +1,9 @@
/*
- * "$Id: mxml-file.c 438 2011-03-24 05:47:51Z mike $"
+ * "$Id: mxml-file.c 455 2014-01-05 03:28:03Z msweet $"
*
* File loading code for Mini-XML, a small XML-like file parsing library.
*
- * Copyright 2003-2011 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -11,44 +11,11 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlLoadFd() - Load a file descriptor into an XML node tree.
- * mxmlLoadFile() - Load a file into an XML node tree.
- * mxmlLoadString() - Load a string into an XML node tree.
- * mxmlSaveAllocString() - Save an XML tree to an allocated string.
- * mxmlSaveFd() - Save an XML tree to a file descriptor.
- * mxmlSaveFile() - Save an XML tree to a file.
- * mxmlSaveString() - Save an XML node tree to a string.
- * mxmlSAXLoadFd() - Load a file descriptor into an XML node tree
- * using a SAX callback.
- * mxmlSAXLoadFile() - Load a file into an XML node tree
- * using a SAX callback.
- * mxmlSAXLoadString() - Load a string into an XML node tree
- * using a SAX callback.
- * mxmlSetCustomHandlers() - Set the handling functions for custom data.
- * mxmlSetErrorCallback() - Set the error message callback.
- * mxmlSetWrapMargin() - Set the wrap margin when saving XML data.
- * mxml_add_char() - Add a character to a buffer, expanding as needed.
- * mxml_fd_getc() - Read a character from a file descriptor.
- * mxml_fd_putc() - Write a character to a file descriptor.
- * mxml_fd_read() - Read a buffer of data from a file descriptor.
- * mxml_fd_write() - Write a buffer of data to a file descriptor.
- * mxml_file_getc() - Get a character from a file.
- * mxml_file_putc() - Write a character to a file.
- * mxml_get_entity() - Get the character corresponding to an entity...
- * mxml_load_data() - Load data into an XML node tree.
- * mxml_parse_element() - Parse an element for any attributes...
- * mxml_string_getc() - Get a character from a string.
- * mxml_string_putc() - Write a character to a string.
- * mxml_write_name() - Write a name string.
- * mxml_write_node() - Save an XML node to a file.
- * mxml_write_string() - Write a string, escaping & and < as needed.
- * mxml_write_ws() - Do whitespace callback...
+ * http://www.msweet.org/projects.php/Mini-XML
*/
+/*** This file modified by ARM on 25 Aug 2014 to avoid pointer overflow when checking if the write position is beyond the end of the buffer in mxmlSaveString and mxml_string_putc ***/
+
/*
* Include necessary headers...
*/
@@ -128,7 +95,7 @@ static int mxml_write_node(mxml_node_t *node, void *p,
_mxml_global_t *global);
static int mxml_write_string(const char *s, void *p,
_mxml_putc_cb_t putc_cb);
-static int mxml_write_ws(mxml_node_t *node, void *p,
+static int mxml_write_ws(mxml_node_t *node, void *p,
mxml_save_cb_t cb, int ws,
int col, _mxml_putc_cb_t putc_cb);
@@ -400,7 +367,7 @@ mxmlSaveString(mxml_node_t *node, /* I - Node to write */
mxml_save_cb_t cb) /* I - Whitespace callback or MXML_NO_CALLBACK */
{
int col; /* Final column */
- char *ptr[2]; /* Pointers for putc_cb */
+ char *ptr[3]; /* Pointers for putc_cb */
_mxml_global_t *global = _mxml_global();
/* Global data */
@@ -411,6 +378,7 @@ mxmlSaveString(mxml_node_t *node, /* I - Node to write */
ptr[0] = buffer;
ptr[1] = buffer + bufsize;
+ ptr[2] = 0;
if ((col = mxml_write_node(node, ptr, cb, 0, mxml_string_putc, global)) < 0)
return (-1);
@@ -422,7 +390,7 @@ mxmlSaveString(mxml_node_t *node, /* I - Node to write */
* Nul-terminate the buffer...
*/
- if (ptr[0] >= ptr[1])
+ if (ptr[2] != 0)
buffer[bufsize - 1] = '\0';
else
ptr[0][0] = '\0';
@@ -567,7 +535,7 @@ mxmlSAXLoadString(
*
* The save function accepts a node pointer and must return a malloc'd
* string on success and NULL on error.
- *
+ *
*/
void
@@ -756,7 +724,7 @@ mxml_fd_getc(void *p, /* I - File descriptor buffer */
return (EOF);
ch = *(buf->current)++;
-
+
if (ch != 0xff)
return (EOF);
@@ -775,7 +743,7 @@ mxml_fd_getc(void *p, /* I - File descriptor buffer */
return (EOF);
ch = *(buf->current)++;
-
+
if (ch != 0xfe)
return (EOF);
@@ -1287,8 +1255,8 @@ mxml_file_getc(void *p, /* I - Pointer to file */
* Multi-word UTF-16 char...
*/
- int lch = (getc(fp) << 8);
- lch |= getc(fp);
+ int lch = getc(fp);
+ lch = (lch << 8) | getc(fp);
if (lch < 0xdc00 || lch >= 0xdfff)
return (EOF);
@@ -1317,7 +1285,7 @@ mxml_file_getc(void *p, /* I - Pointer to file */
*/
int lch = getc(fp);
- lch |= (getc(fp) << 8);
+ lch |= (getc(fp) << 8);
if (lch < 0xdc00 || lch >= 0xdfff)
return (EOF);
@@ -1463,8 +1431,10 @@ mxml_load_data(
if (cb && parent)
type = (*cb)(parent);
- else
+ else if (parent)
type = MXML_TEXT;
+ else
+ type = MXML_IGNORE;
while ((ch = (*getc_cb)(p, &encoding)) != EOF)
{
@@ -1518,7 +1488,7 @@ mxml_load_data(
default : /* Ignore... */
node = NULL;
break;
- }
+ }
if (*bufptr)
{
@@ -1661,9 +1631,9 @@ mxml_load_data(
* There can only be one root element!
*/
- mxml_error("<%s> cannot be a second root node after <%s>",
+ mxml_error("<%s> cannot be a second root node after <%s>",
buffer, first->value.element.name);
- goto error;
+ goto error;
}
if ((node = mxmlNewElement(parent, buffer)) == NULL)
@@ -1729,9 +1699,9 @@ mxml_load_data(
* There can only be one root element!
*/
- mxml_error("<%s> cannot be a second root node after <%s>",
+ mxml_error("<%s> cannot be a second root node after <%s>",
buffer, first->value.element.name);
- goto error;
+ goto error;
}
if ((node = mxmlNewElement(parent, buffer)) == NULL)
@@ -1796,9 +1766,9 @@ mxml_load_data(
* There can only be one root element!
*/
- mxml_error("<%s> cannot be a second root node after <%s>",
+ mxml_error("<%s> cannot be a second root node after <%s>",
buffer, first->value.element.name);
- goto error;
+ goto error;
}
if ((node = mxmlNewElement(parent, buffer)) == NULL)
@@ -1882,9 +1852,9 @@ mxml_load_data(
* There can only be one root element!
*/
- mxml_error("<%s> cannot be a second root node after <%s>",
+ mxml_error("<%s> cannot be a second root node after <%s>",
buffer, first->value.element.name);
- goto error;
+ goto error;
}
if ((node = mxmlNewElement(parent, buffer)) == NULL)
@@ -1974,9 +1944,9 @@ mxml_load_data(
* There can only be one root element!
*/
- mxml_error("<%s> cannot be a second root node after <%s>",
+ mxml_error("<%s> cannot be a second root node after <%s>",
buffer, first->value.element.name);
- goto error;
+ goto error;
}
if ((node = mxmlNewElement(parent, buffer)) == NULL)
@@ -2076,7 +2046,7 @@ mxml_load_data(
{
node = parent;
- while (parent->parent != top && parent->parent)
+ while (parent != top && parent->parent)
parent = parent->parent;
if (node != parent)
@@ -2286,7 +2256,7 @@ mxml_parse_element(
if (ch == '&')
if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
goto error;
-
+
if (mxml_add_char(ch, &ptr, &value, &valsize))
goto error;
}
@@ -2310,7 +2280,7 @@ mxml_parse_element(
if (ch == '&')
if ((ch = mxml_get_entity(node, p, encoding, getc_cb)) == EOF)
goto error;
-
+
if (mxml_add_char(ch, &ptr, &value, &valsize))
goto error;
}
@@ -2643,8 +2613,12 @@ mxml_string_putc(int ch, /* I - Character to write */
pp = (char **)p;
- if (pp[0] < pp[1])
- pp[0][0] = ch;
+ if (pp[2] == 0) {
+ if (pp[0] < pp[1])
+ pp[0][0] = ch;
+ else
+ pp[2] = (char *)1;
+ }
pp[0] ++;
@@ -3078,5 +3052,5 @@ mxml_write_ws(mxml_node_t *node, /* I - Current node */
/*
- * End of "$Id: mxml-file.c 438 2011-03-24 05:47:51Z mike $".
+ * End of "$Id: mxml-file.c 455 2014-01-05 03:28:03Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml-get.c b/tools/gator/daemon/mxml/mxml-get.c
index a5356d57e186..40ed3d0839b4 100644
--- a/tools/gator/daemon/mxml/mxml-get.c
+++ b/tools/gator/daemon/mxml/mxml-get.c
@@ -1,9 +1,9 @@
/*
- * "$Id: mxml-get.c 427 2011-01-03 02:03:29Z mike $"
+ * "$Id: mxml-get.c 451 2014-01-04 21:50:06Z msweet $"
*
* Node get functions for Mini-XML, a small XML-like file parsing library.
*
- * Copyright 2011 by Michael R Sweet.
+ * Copyright 2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -11,26 +11,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlGetCDATA() - Get the value for a CDATA node.
- * mxmlGetCustom() - Get the value for a custom node.
- * mxmlGetElement() - Get the name for an element node.
- * mxmlGetFirstChild() - Get the first child of an element node.
- * mxmlGetInteger() - Get the integer value from the specified node or its
- * first child.
- * mxmlGetLastChild() - Get the last child of an element node.
- * mxmlGetNextSibling() - Get the next node for the current parent.
- * mxmlGetOpaque() - Get an opaque string value for a node or its first
- * child.
- * mxmlGetParent() - Get the parent node.
- * mxmlGetPrevSibling() - Get the previous node for the current parent.
- * mxmlGetReal() - Get the real value for a node or its first child.
- * mxmlGetText() - Get the text value for a node or its first child.
- * mxmlGetType() - Get the node type.
- * mxmlGetUserData() - Get the user data pointer for a node.
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -467,5 +448,5 @@ mxmlGetUserData(mxml_node_t *node) /* I - Node to get */
/*
- * End of "$Id: mxml-get.c 427 2011-01-03 02:03:29Z mike $".
+ * End of "$Id: mxml-get.c 451 2014-01-04 21:50:06Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml-index.c b/tools/gator/daemon/mxml/mxml-index.c
index b6efc66f055c..10814390d3a0 100644
--- a/tools/gator/daemon/mxml/mxml-index.c
+++ b/tools/gator/daemon/mxml/mxml-index.c
@@ -1,9 +1,9 @@
/*
- * "$Id: mxml-index.c 426 2011-01-01 23:42:17Z mike $"
+ * "$Id: mxml-index.c 451 2014-01-04 21:50:06Z msweet $"
*
* Index support code for Mini-XML, a small XML-like file parsing library.
*
- * Copyright 2003-2011 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -11,10 +11,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
- *
- * Contents:
- *
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -658,5 +655,5 @@ index_sort(mxml_index_t *ind, /* I - Index to sort */
/*
- * End of "$Id: mxml-index.c 426 2011-01-01 23:42:17Z mike $".
+ * End of "$Id: mxml-index.c 451 2014-01-04 21:50:06Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml-node.c b/tools/gator/daemon/mxml/mxml-node.c
index 44af759f9de3..128cda1a4cf2 100644
--- a/tools/gator/daemon/mxml/mxml-node.c
+++ b/tools/gator/daemon/mxml/mxml-node.c
@@ -1,9 +1,9 @@
/*
- * "$Id: mxml-node.c 436 2011-01-22 01:02:05Z mike $"
+ * "$Id: mxml-node.c 451 2014-01-04 21:50:06Z msweet $"
*
* Node support code for Mini-XML, a small XML-like file parsing library.
*
- * Copyright 2003-2011 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -11,26 +11,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlAdd() - Add a node to a tree.
- * mxmlDelete() - Delete a node and all of its children.
- * mxmlGetRefCount() - Get the current reference (use) count for a node.
- * mxmlNewCDATA() - Create a new CDATA node.
- * mxmlNewCustom() - Create a new custom data node.
- * mxmlNewElement() - Create a new element node.
- * mxmlNewInteger() - Create a new integer node.
- * mxmlNewOpaque() - Create a new opaque string.
- * mxmlNewReal() - Create a new real number node.
- * mxmlNewText() - Create a new text fragment node.
- * mxmlNewTextf() - Create a new formatted text fragment node.
- * mxmlRemove() - Remove a node from its parent.
- * mxmlNewXML() - Create a new XML document tree.
- * mxmlRelease() - Release a node.
- * mxmlRetain() - Retain a node.
- * mxml_new() - Create a new node.
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -529,7 +510,7 @@ mxmlNewReal(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
* list. The constant MXML_NO_PARENT can be used to specify that the new
* text node has no parent. The whitespace parameter is used to specify
* whether leading whitespace is present before the node. The text
- * string must be nul-terminated and is copied into the new node.
+ * string must be nul-terminated and is copied into the new node.
*/
mxml_node_t * /* O - New node */
@@ -573,7 +554,7 @@ mxmlNewText(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
* list. The constant MXML_NO_PARENT can be used to specify that the new
* text node has no parent. The whitespace parameter is used to specify
* whether leading whitespace is present before the node. The format
- * string must be nul-terminated and is formatted into the new node.
+ * string must be nul-terminated and is formatted into the new node.
*/
mxml_node_t * /* O - New node */
@@ -803,5 +784,5 @@ mxml_new(mxml_node_t *parent, /* I - Parent node */
/*
- * End of "$Id: mxml-node.c 436 2011-01-22 01:02:05Z mike $".
+ * End of "$Id: mxml-node.c 451 2014-01-04 21:50:06Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml-private.c b/tools/gator/daemon/mxml/mxml-private.c
index 72f3e2320c7c..bec4bbfbf378 100644
--- a/tools/gator/daemon/mxml/mxml-private.c
+++ b/tools/gator/daemon/mxml/mxml-private.c
@@ -1,9 +1,9 @@
/*
- * "$Id: mxml-private.c 422 2010-11-07 22:55:11Z mike $"
+ * "$Id: mxml-private.c 451 2014-01-04 21:50:06Z msweet $"
*
* Private functions for Mini-XML, a small XML-like file parsing library.
*
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -11,15 +11,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxml_error() - Display an error message.
- * mxml_integer_cb() - Default callback for integer values.
- * mxml_opaque_cb() - Default callback for opaque values.
- * mxml_real_cb() - Default callback for real number values.
- * _mxml_global() - Get global data.
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -238,7 +230,7 @@ static DWORD _mxml_tls_index; /* Index for global storage */
/*
* 'DllMain()' - Main entry for library.
*/
-
+
BOOL WINAPI /* O - Success/failure */
DllMain(HINSTANCE hinst, /* I - DLL module handle */
DWORD reason, /* I - Reason */
@@ -250,28 +242,28 @@ DllMain(HINSTANCE hinst, /* I - DLL module handle */
(void)hinst;
(void)reserved;
- switch (reason)
- {
+ switch (reason)
+ {
case DLL_PROCESS_ATTACH : /* Called on library initialization */
- if ((_mxml_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES)
- return (FALSE);
- break;
+ if ((_mxml_tls_index = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ return (FALSE);
+ break;
case DLL_THREAD_DETACH : /* Called when a thread terminates */
if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
free(global);
- break;
+ break;
case DLL_PROCESS_DETACH : /* Called when library is unloaded */
if ((global = (_mxml_global_t *)TlsGetValue(_mxml_tls_index)) != NULL)
free(global);
- TlsFree(_mxml_tls_index);
- break;
+ TlsFree(_mxml_tls_index);
+ break;
- default:
- break;
- }
+ default:
+ break;
+ }
return (TRUE);
}
@@ -295,7 +287,7 @@ _mxml_global(void)
global->entity_cbs[0] = _mxml_entity_cb;
global->wrap = 72;
- TlsSetValue(_mxml_tls_index, (LPVOID)global);
+ TlsSetValue(_mxml_tls_index, (LPVOID)global);
}
return (global);
@@ -327,5 +319,5 @@ _mxml_global(void)
/*
- * End of "$Id: mxml-private.c 422 2010-11-07 22:55:11Z mike $".
+ * End of "$Id: mxml-private.c 451 2014-01-04 21:50:06Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml-private.h b/tools/gator/daemon/mxml/mxml-private.h
index 8789e6c52cbd..c5e4e6b6f27a 100644
--- a/tools/gator/daemon/mxml/mxml-private.h
+++ b/tools/gator/daemon/mxml/mxml-private.h
@@ -1,9 +1,9 @@
/*
- * "$Id: mxml-private.h 408 2010-09-19 05:26:46Z mike $"
+ * "$Id: mxml-private.h 451 2014-01-04 21:50:06Z msweet $"
*
* Private definitions for Mini-XML, a small XML-like file parsing library.
*
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -11,7 +11,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -46,5 +46,5 @@ extern int _mxml_entity_cb(const char *name);
/*
- * End of "$Id: mxml-private.h 408 2010-09-19 05:26:46Z mike $".
+ * End of "$Id: mxml-private.h 451 2014-01-04 21:50:06Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml-search.c b/tools/gator/daemon/mxml/mxml-search.c
index f975af1543ca..313a52f0ce2f 100644
--- a/tools/gator/daemon/mxml/mxml-search.c
+++ b/tools/gator/daemon/mxml/mxml-search.c
@@ -1,10 +1,10 @@
/*
- * "$Id: mxml-search.c 427 2011-01-03 02:03:29Z mike $"
+ * "$Id: mxml-search.c 451 2014-01-04 21:50:06Z msweet $"
*
* Search/navigation functions for Mini-XML, a small XML-like file
* parsing library.
*
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -12,14 +12,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlFindElement() - Find the named element.
- * mxmlFindValue() - Find a value with the given path.
- * mxmlWalkNext() - Walk to the next logical node in the tree.
- * mxmlWalkPrev() - Walk to the previous logical node in the tree.
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -126,7 +119,7 @@ mxmlFindElement(mxml_node_t *node, /* I - Current node */
*
* The first child node of the found node is returned if the given node has
* children and the first child is a value node.
- *
+ *
* @since Mini-XML 2.7@
*/
@@ -283,5 +276,5 @@ mxmlWalkPrev(mxml_node_t *node, /* I - Current node */
/*
- * End of "$Id: mxml-search.c 427 2011-01-03 02:03:29Z mike $".
+ * End of "$Id: mxml-search.c 451 2014-01-04 21:50:06Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml-set.c b/tools/gator/daemon/mxml/mxml-set.c
index b0bd52790b2e..16d4bf1050dd 100644
--- a/tools/gator/daemon/mxml/mxml-set.c
+++ b/tools/gator/daemon/mxml/mxml-set.c
@@ -1,9 +1,9 @@
/*
- * "$Id: mxml-set.c 441 2011-12-09 23:49:00Z mike $"
+ * "$Id: mxml-set.c 451 2014-01-04 21:50:06Z msweet $"
*
* Node set functions for Mini-XML, a small XML-like file parsing library.
*
- * Copyright 2003-2011 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -11,19 +11,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
- *
- * Contents:
- *
- * mxmlSetCDATA() - Set the element name of a CDATA node.
- * mxmlSetCustom() - Set the data and destructor of a custom data node.
- * mxmlSetElement() - Set the name of an element node.
- * mxmlSetInteger() - Set the value of an integer node.
- * mxmlSetOpaque() - Set the value of an opaque node.
- * mxmlSetReal() - Set the value of a real number node.
- * mxmlSetText() - Set the value of a text node.
- * mxmlSetTextf() - Set the value of a text node to a formatted string.
- * mxmlSetUserData() - Set the user data pointer for a node.
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -345,5 +333,5 @@ mxmlSetUserData(mxml_node_t *node, /* I - Node to set */
/*
- * End of "$Id: mxml-set.c 441 2011-12-09 23:49:00Z mike $".
+ * End of "$Id: mxml-set.c 451 2014-01-04 21:50:06Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml-string.c b/tools/gator/daemon/mxml/mxml-string.c
index 6be42523f95c..9d5b58e6adb7 100644
--- a/tools/gator/daemon/mxml/mxml-string.c
+++ b/tools/gator/daemon/mxml/mxml-string.c
@@ -1,9 +1,9 @@
/*
- * "$Id: mxml-string.c 424 2010-12-25 16:21:50Z mike $"
+ * "$Id: mxml-string.c 454 2014-01-05 03:25:07Z msweet $"
*
* String functions for Mini-XML, a small XML-like file parsing library.
*
- * Copyright 2003-2010 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -11,15 +11,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
- *
- * Contents:
- *
- * _mxml_snprintf() - Format a string.
- * _mxml_strdup() - Duplicate a string.
- * _mxml_strdupf() - Format and duplicate a string.
- * _mxml_vsnprintf() - Format a string into a fixed size buffer.
- * _mxml_vstrdupf() - Format and duplicate a string.
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -38,7 +30,7 @@
# ifdef __va_copy
# define va_copy(dst,src) __va_copy(dst,src)
# else
-# define va_copy(dst,src) memcpy(&dst, &src, sizeof(va_list))
+# define va_copy(dst,src) memcpy(&dst, src, sizeof(va_list))
# endif /* __va_copy */
#endif /* va_copy */
@@ -157,7 +149,8 @@ _mxml_vsnprintf(char *buffer, /* O - Output buffer */
if (*format == '%')
{
- if (bufptr && bufptr < bufend) *bufptr++ = *format;
+ if (bufptr && bufptr < bufend)
+ *bufptr++ = *format;
bytes ++;
format ++;
continue;
@@ -472,5 +465,5 @@ _mxml_vstrdupf(const char *format, /* I - Printf-style format string */
/*
- * End of "$Id: mxml-string.c 424 2010-12-25 16:21:50Z mike $".
+ * End of "$Id: mxml-string.c 454 2014-01-05 03:25:07Z msweet $".
*/
diff --git a/tools/gator/daemon/mxml/mxml.h b/tools/gator/daemon/mxml/mxml.h
index 79c711f4c80f..bba5fd23a67b 100644
--- a/tools/gator/daemon/mxml/mxml.h
+++ b/tools/gator/daemon/mxml/mxml.h
@@ -1,9 +1,9 @@
/*
- * "$Id: mxml.h 427 2011-01-03 02:03:29Z mike $"
+ * "$Id: mxml.h 451 2014-01-04 21:50:06Z msweet $"
*
* Header file for Mini-XML, a small XML-like file parsing library.
*
- * Copyright 2003-2011 by Michael R Sweet.
+ * Copyright 2003-2014 by Michael R Sweet.
*
* These coded instructions, statements, and computer programs are the
* property of Michael R Sweet and are protected by Federal copyright
@@ -11,7 +11,7 @@
* which should have been included with this file. If this file is
* missing or damaged, see the license at:
*
- * http://www.minixml.org/
+ * http://www.msweet.org/projects.php/Mini-XML
*/
/*
@@ -36,6 +36,9 @@
* Constants...
*/
+# define MXML_MAJOR_VERSION 2 /* Major version number */
+# define MXML_MINOR_VERSION 8 /* Minor version number */
+
# define MXML_TAB 8 /* Tabs every N columns */
# define MXML_NO_CALLBACK 0 /* Don't use a type callback */
@@ -93,7 +96,7 @@ typedef enum mxml_type_e /**** The XML node type. ****/
typedef void (*mxml_custom_destroy_cb_t)(void *);
/**** Custom data destructor ****/
-typedef void (*mxml_error_cb_t)(const char *);
+typedef void (*mxml_error_cb_t)(const char *);
/**** Error callback function ****/
typedef struct mxml_attr_s /**** An XML element attribute value. @private@ ****/
@@ -161,7 +164,7 @@ typedef struct mxml_index_s mxml_index_t;
typedef int (*mxml_custom_load_cb_t)(mxml_node_t *, const char *);
/**** Custom data load callback function ****/
-typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *);
+typedef char *(*mxml_custom_save_cb_t)(mxml_node_t *);
/**** Custom data save callback function ****/
typedef int (*mxml_entity_cb_t)(const char *);
@@ -173,7 +176,7 @@ typedef mxml_type_t (*mxml_load_cb_t)(mxml_node_t *);
typedef const char *(*mxml_save_cb_t)(mxml_node_t *, int);
/**** Save callback function ****/
-typedef void (*mxml_sax_cb_t)(mxml_node_t *, mxml_sax_event_t, void *);
+typedef void (*mxml_sax_cb_t)(mxml_node_t *, mxml_sax_event_t, void *);
/**** SAX callback function ****/
@@ -325,5 +328,5 @@ extern mxml_type_t mxml_real_cb(mxml_node_t *node);
/*
- * End of "$Id: mxml.h 427 2011-01-03 02:03:29Z mike $".
+ * End of "$Id: mxml.h 451 2014-01-04 21:50:06Z msweet $".
*/