aboutsummaryrefslogtreecommitdiff
path: root/tools/gator/daemon/DiskIODriver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gator/daemon/DiskIODriver.cpp')
-rw-r--r--tools/gator/daemon/DiskIODriver.cpp125
1 files changed, 125 insertions, 0 deletions
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);
+}