Merge branch develop-3.10
[firefly-linux-kernel-4.4.55.git] / tools / gator / daemon / FtraceDriver.cpp
1 /**
2  * Copyright (C) ARM Limited 2014. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8
9 #include "FtraceDriver.h"
10
11 #include <regex.h>
12
13 #include "Logging.h"
14
15 class FtraceCounter : public DriverCounter {
16 public:
17         FtraceCounter(DriverCounter *next, char *name, const char *regex);
18         ~FtraceCounter();
19
20         int read(const char *const line, int64_t *values);
21
22 private:
23         regex_t reg;
24
25         // Intentionally unimplemented
26         FtraceCounter(const FtraceCounter &);
27         FtraceCounter &operator=(const FtraceCounter &);
28 };
29
30 FtraceCounter::FtraceCounter(DriverCounter *next, char *name, const char *regex) : DriverCounter(next, name) {
31         int result = regcomp(&reg, regex, REG_EXTENDED);
32         if (result != 0) {
33                 char buf[128];
34                 regerror(result, &reg, buf, sizeof(buf));
35                 logg->logError(__FILE__, __LINE__, "Invalid regex '%s': %s", regex, buf);
36                 handleException();
37         }
38 }
39
40 FtraceCounter::~FtraceCounter() {
41         regfree(&reg);
42 }
43
44 int FtraceCounter::read(const char *const line, int64_t *values) {
45         regmatch_t match[2];
46         int result = regexec(&reg, line, 2, match, 0);
47         if (result != 0) {
48                 // No match
49                 return 0;
50         }
51
52         if (match[1].rm_so < 0) {
53                 logg->logError(__FILE__, __LINE__, "Parsing %s failed", getName());
54                 handleException();
55         }
56
57         errno = 0;
58         int64_t value = strtoll(line + match[1].rm_so, NULL, 0);
59         if (errno != 0) {
60                 logg->logError(__FILE__, __LINE__, "Parsing %s failed: %s", getName(), strerror(errno));
61                 handleException();
62         }
63
64         values[0] = getKey();
65         values[1] = value;
66
67         return 1;
68 }
69
70 FtraceDriver::FtraceDriver() : mValues(NULL) {
71 }
72
73 FtraceDriver::~FtraceDriver() {
74         delete [] mValues;
75 }
76
77 void FtraceDriver::readEvents(mxml_node_t *const xml) {
78         mxml_node_t *node = xml;
79         int count = 0;
80         while (true) {
81                 node = mxmlFindElement(node, xml, "event", NULL, NULL, MXML_DESCEND);
82                 if (node == NULL) {
83                         break;
84                 }
85                 const char *counter = mxmlElementGetAttr(node, "counter");
86                 if (counter == NULL) {
87                         continue;
88                 }
89
90                 if (strncmp(counter, "ftrace_", 7) != 0) {
91                         continue;
92                 }
93
94                 const char *regex = mxmlElementGetAttr(node, "regex");
95                 if (regex == NULL) {
96                         logg->logError(__FILE__, __LINE__, "The regex counter %s is missing the required regex attribute", counter);
97                         handleException();
98                 }
99                 setCounters(new FtraceCounter(getCounters(), strdup(counter), regex));
100                 ++count;
101         }
102
103         mValues = new int64_t[2*count];
104 }
105
106 int FtraceDriver::read(const char *line, int64_t **buf) {
107         int count = 0;
108
109         for (FtraceCounter *counter = static_cast<FtraceCounter *>(getCounters()); counter != NULL; counter = static_cast<FtraceCounter *>(counter->getNext())) {
110                 if (!counter->isEnabled()) {
111                         continue;
112                 }
113                 count += counter->read(line, mValues + 2*count);
114         }
115
116         *buf = mValues;
117         return count;
118 }