aboutsummaryrefslogtreecommitdiff
path: root/daemon/PerfDriver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'daemon/PerfDriver.cpp')
-rw-r--r--daemon/PerfDriver.cpp92
1 files changed, 73 insertions, 19 deletions
diff --git a/daemon/PerfDriver.cpp b/daemon/PerfDriver.cpp
index 8e25c22..ac97a07 100644
--- a/daemon/PerfDriver.cpp
+++ b/daemon/PerfDriver.cpp
@@ -11,6 +11,7 @@
#include <dirent.h>
#include <sys/utsname.h>
#include <time.h>
+#include <unistd.h>
#include "Buffer.h"
#include "Config.h"
@@ -30,7 +31,7 @@
struct gator_cpu {
const int cpuid;
// Human readable name
- const char core_name[32];
+ const char *const core_name;
// gatorfs event and Perf PMU name
const char *const pmnc_name;
const int pmnc_counters;
@@ -62,9 +63,20 @@ static const struct gator_cpu gator_cpus[] = {
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;
+ const int count;
+};
+
+static const struct uncore_counter uncore_counters[] = {
+ { "CCI_400", 4 },
+ { "CCI_400-r1", 4 },
+};
+
class PerfCounter {
public:
- PerfCounter(PerfCounter *next, const char *name, uint32_t type, uint64_t config) : mNext(next), mName(name), mType(type), mCount(0), mKey(getEventKey()), mConfig(config), mEnabled(false) {}
+ 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() {
delete [] mName;
}
@@ -79,6 +91,7 @@ public:
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;
@@ -87,10 +100,11 @@ private:
int mCount;
const int mKey;
uint64_t mConfig;
- bool mEnabled;
+ int mEnabled : 1,
+ mPerCpu : 1;
};
-PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false) {
+PerfDriver::PerfDriver() : mCounters(NULL), mIsSetup(false), mLegacySupport(false) {
}
PerfDriver::~PerfDriver() {
@@ -105,13 +119,27 @@ void PerfDriver::addCpuCounters(const char *const counterName, const int type, c
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);
+ mCounters = new PerfCounter(mCounters, 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);
+ mCounters = new PerfCounter(mCounters, name, type, -1, true);
+ }
+}
+
+void PerfDriver::addUncoreCounters(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, 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);
}
}
@@ -139,10 +167,16 @@ bool PerfDriver::setup() {
}
}
- if (KERNEL_VERSION(release[0], release[1], release[2]) < KERNEL_VERSION(3, 12, 0)) {
+ 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;
}
+ 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__);
+ return false;
+ }
// Add supported PMUs
bool foundCpu = false;
@@ -174,6 +208,21 @@ bool PerfDriver::setup() {
foundCpu = true;
addCpuCounters(gator_cpus[i].pmnc_name, type, gator_cpus[i].pmnc_counters);
}
+
+ for (int i = 0; i < ARRAY_LENGTH(uncore_counters); ++i) {
+ if (strcmp(dirent->d_name, uncore_counters[i].name) != 0) {
+ continue;
+ }
+
+ int type;
+ char buf[256];
+ snprintf(buf, sizeof(buf), PERF_DEVICES "/%s/type", dirent->d_name);
+ if (DriverSource::readIntDriver(buf, &type) != 0) {
+ continue;
+ }
+
+ addUncoreCounters(uncore_counters[i].name, type, uncore_counters[i].count);
+ }
}
closedir(dir);
@@ -203,12 +252,12 @@ bool PerfDriver::setup() {
id = getTracepointId("irq/softirq_exit", &printb);
if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_irq_softirq", PERF_TYPE_TRACEPOINT, id);
+ mCounters = new PerfCounter(mCounters, "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);
+ mCounters = new PerfCounter(mCounters, "Linux_irq_irq", PERF_TYPE_TRACEPOINT, id, true);
}
//Linux_block_rq_wr
@@ -218,7 +267,7 @@ bool PerfDriver::setup() {
id = getTracepointId(SCHED_SWITCH, &printb);
if (id >= 0) {
- mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id);
+ mCounters = new PerfCounter(mCounters, "Linux_sched_switch", PERF_TYPE_TRACEPOINT, id, true);
}
//Linux_meminfo_memused
@@ -227,7 +276,7 @@ bool PerfDriver::setup() {
//Linux_power_cpu_freq
//Linux_power_cpu_idle
- mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1);
+ mCounters = new PerfCounter(mCounters, "Linux_cpu_wait_contention", TYPE_DERIVED, -1, false);
//Linux_cpu_wait_io
@@ -252,15 +301,16 @@ bool PerfDriver::summary(Buffer *const buffer) {
}
const int64_t timestamp = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec;
- if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
- logg->logMessage("%s(%s:%i): clock_gettime failed", __FUNCTION__, __FILE__, __LINE__);
- return false;
- }
- const int64_t uptime = (int64_t)ts.tv_sec * 1000000000L + ts.tv_nsec;
+ const int64_t uptime = getTime();
buffer->summary(timestamp, uptime, 0, 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]) {
@@ -270,7 +320,11 @@ bool PerfDriver::summary(Buffer *const buffer) {
if (gator_cpus[j].cpuid == gSessionData->mCpuIds[i]) {
buffer->coreName(i, gSessionData->mCpuIds[i], gator_cpus[j].core_name);
} else {
- snprintf(buf, sizeof(buf), "Unknown (0x%.3x)", gSessionData->mCpuIds[i]);
+ 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);
}
}
@@ -326,10 +380,10 @@ int PerfDriver::writeCounters(mxml_node_t *root) const {
return count;
}
-bool PerfDriver::enable(PerfGroup *group, Buffer *const buffer) const {
+bool PerfDriver::enable(PerfGroup *const group, Buffer *const buffer) const {
for (PerfCounter * counter = mCounters; counter != NULL; counter = counter->getNext()) {
if (counter->isEnabled() && (counter->getType() != TYPE_DERIVED)) {
- if (!group->add(buffer, counter->getKey(), counter->getType(), counter->getConfig(), counter->getCount(), 0, 0)) {
+ 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)) {
logg->logMessage("%s(%s:%i): PerfGroup::add failed", __FUNCTION__, __FILE__, __LINE__);
return false;
}