2 * Copyright (C) ARM Limited 2014. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
14 #include <sys/types.h>
19 #include "DriverSource.h"
21 #include "SessionData.h"
25 FSCounter(FSCounter *next, char *name, const char *regex);
28 FSCounter *getNext() const { return next; }
29 int getKey() const { return key; }
30 bool isEnabled() const { return enabled; }
31 void setEnabled(const bool enabled) { this->enabled = enabled; }
32 const char *getName() const { return name; }
36 FSCounter *const next;
43 // Intentionally unimplemented
44 FSCounter(const FSCounter &);
45 FSCounter &operator=(const FSCounter &);
48 FSCounter::FSCounter(FSCounter *next, char *name, const char *regex) : next(next), name(name), key(getEventKey()), enabled(false), useRegex(regex != NULL) {
50 int result = regcomp(®, regex, REG_EXTENDED);
53 regerror(result, ®, buf, sizeof(buf));
54 logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf);
60 FSCounter::~FSCounter() {
67 int64_t FSCounter::read() {
72 const int fd = open(name, O_RDONLY);
76 while (pos < sizeof(buf) - 1) {
77 const ssize_t bytes = ::read(fd, buf + pos, sizeof(buf) - pos - 1);
80 } else if (bytes == 0) {
89 int result = regexec(®, buf, 2, match, 0);
91 regerror(result, ®, buf, sizeof(buf));
92 logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, buf);
96 if (match[1].rm_so < 0) {
97 logg->logError(__FILE__, __LINE__, "Parsing %s failed", name);
102 value = strtoll(buf + match[1].rm_so, &endptr, 0);
104 logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", name, strerror(errno));
108 if (DriverSource::readInt64Driver(name, &value) != 0) {
115 logg->logError(__FILE__, __LINE__, "Unable to read %s", name);
119 FSDriver::FSDriver() : counters(NULL) {
122 FSDriver::~FSDriver() {
123 while (counters != NULL) {
124 FSCounter * counter = counters;
125 counters = counter->getNext();
130 void FSDriver::setup(mxml_node_t *const xml) {
131 // fs driver does not currently work with perf
132 if (gSessionData->perf.isSetup()) {
136 mxml_node_t *node = xml;
138 node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
142 const char *counter = mxmlElementGetAttr(node, "counter");
143 if ((counter != NULL) && (counter[0] == '/')) {
144 const char *regex = mxmlElementGetAttr(node, "regex");
145 counters = new FSCounter(counters, strdup(counter), regex);
150 FSCounter *FSDriver::findCounter(const Counter &counter) const {
151 for (FSCounter * fsCounter = counters; fsCounter != NULL; fsCounter = fsCounter->getNext()) {
152 if (strcmp(fsCounter->getName(), counter.getType()) == 0) {
160 bool FSDriver::claimCounter(const Counter &counter) const {
161 return findCounter(counter) != NULL;
164 bool FSDriver::countersEnabled() const {
165 for (FSCounter *counter = counters; counter != NULL; counter = counter->getNext()) {
166 if (counter->isEnabled()) {
173 void FSDriver::resetCounters() {
174 for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
175 counter->setEnabled(false);
179 void FSDriver::setupCounter(Counter &counter) {
180 FSCounter *const fsCounter = findCounter(counter);
181 if (fsCounter == NULL) {
182 counter.setEnabled(false);
185 fsCounter->setEnabled(true);
186 counter.setKey(fsCounter->getKey());
189 int FSDriver::writeCounters(mxml_node_t *root) const {
191 for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
192 if (access(counter->getName(), R_OK) == 0) {
193 mxml_node_t *node = mxmlNewElement(root, "counter");
194 mxmlElementSetAttr(node, "name", counter->getName());
202 void FSDriver::start() {
205 void FSDriver::read(Buffer * const buffer) {
206 for (FSCounter * counter = counters; counter != NULL; counter = counter->getNext()) {
207 if (!counter->isEnabled()) {
210 buffer->event(counter->getKey(), counter->read());