blob: 2b661bdf294c59ead6585fd892971d6d5d5b8669 [file] [log] [blame]
Jon Medhurstaaf37a32013-06-11 12:10:56 +01001/**
Jon Medhurstb1d07442015-05-08 12:04:18 +01002 * Copyright (C) ARM Limited 2010-2015. All rights reserved.
Jon Medhurstaaf37a32013-06-11 12:10:56 +01003 *
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
Jon Medhurstaaf37a32013-06-11 12:10:56 +01009#include "SessionData.h"
Jon Medhurst15ce78d2014-04-10 09:02:02 +010010
Jon Medhurst96b56152014-10-30 18:01:15 +000011#include <fcntl.h>
Jon Medhurst15ce78d2014-04-10 09:02:02 +010012#include <string.h>
Jon Medhurste31266f2014-08-04 15:47:44 +010013#include <sys/mman.h>
Jon Medhurst96b56152014-10-30 18:01:15 +000014#include <unistd.h>
Jon Medhurst15ce78d2014-04-10 09:02:02 +010015
Jon Medhurst96b56152014-10-30 18:01:15 +000016#include "DiskIODriver.h"
17#include "FSDriver.h"
18#include "HwmonDriver.h"
Jon Medhurstaaf37a32013-06-11 12:10:56 +010019#include "Logging.h"
Jon Medhurst96b56152014-10-30 18:01:15 +000020#include "MemInfoDriver.h"
21#include "NetDriver.h"
22#include "SessionXML.h"
23
24#define CORE_NAME_UNKNOWN "unknown"
Jon Medhurstaaf37a32013-06-11 12:10:56 +010025
26SessionData* gSessionData = NULL;
27
28SessionData::SessionData() {
Jon Medhurst96b56152014-10-30 18:01:15 +000029 usDrivers[0] = new HwmonDriver();
30 usDrivers[1] = new FSDriver();
31 usDrivers[2] = new MemInfoDriver();
32 usDrivers[3] = new NetDriver();
Jon Medhurstb1d07442015-05-08 12:04:18 +010033 usDrivers[4] = new DiskIODriver();
Jon Medhurstaaf37a32013-06-11 12:10:56 +010034 initialize();
35}
36
37SessionData::~SessionData() {
38}
39
40void SessionData::initialize() {
41 mWaitingOnCommand = false;
42 mSessionIsActive = false;
43 mLocalCapture = false;
44 mOneShot = false;
Jon Medhurste31266f2014-08-04 15:47:44 +010045 mSentSummary = false;
Jon Medhurst96b56152014-10-30 18:01:15 +000046 mAllowCommands = false;
Jon Medhurste31266f2014-08-04 15:47:44 +010047 const size_t cpuIdSize = sizeof(int)*NR_CPUS;
48 // Share mCpuIds across all instances of gatord
49 mCpuIds = (int *)mmap(NULL, cpuIdSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
50 if (mCpuIds == MAP_FAILED) {
Jon Medhurstb1d07442015-05-08 12:04:18 +010051 logg->logError("Unable to mmap shared memory for cpuids");
Jon Medhurste31266f2014-08-04 15:47:44 +010052 handleException();
53 }
54 memset(mCpuIds, -1, cpuIdSize);
Jon Medhurst96b56152014-10-30 18:01:15 +000055 strcpy(mCoreName, CORE_NAME_UNKNOWN);
56 readModel();
Jon Medhurstaaf37a32013-06-11 12:10:56 +010057 readCpuInfo();
Jon Medhurst96b56152014-10-30 18:01:15 +000058 mImages = NULL;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010059 mConfigurationXMLPath = NULL;
60 mSessionXMLPath = NULL;
61 mEventsXMLPath = NULL;
Jon Medhurstb1d07442015-05-08 12:04:18 +010062 mEventsXMLAppend = NULL;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010063 mTargetPath = NULL;
64 mAPCDir = NULL;
Jon Medhurst96b56152014-10-30 18:01:15 +000065 mCaptureWorkingDir = NULL;
66 mCaptureCommand = NULL;
67 mCaptureUser = NULL;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010068 mSampleRate = 0;
69 mLiveRate = 0;
70 mDuration = 0;
Jon Medhurst96b56152014-10-30 18:01:15 +000071 mMonotonicStarted = -1;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010072 mBacktraceDepth = 0;
73 mTotalBufferSize = 0;
74 // sysconf(_SC_NPROCESSORS_CONF) is unreliable on 2.6 Android, get the value from the kernel module
75 mCores = 1;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010076 mPageSize = 0;
Jon Medhurstb1d07442015-05-08 12:04:18 +010077 mAnnotateStart = -1;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010078}
79
80void SessionData::parseSessionXML(char* xmlString) {
81 SessionXML session(xmlString);
82 session.parse();
83
Jon Medhurst34d97692013-12-19 09:23:06 +000084 // Set session data values - use prime numbers just below the desired value to reduce the chance of events firing at the same time
Jon Medhurstaaf37a32013-06-11 12:10:56 +010085 if (strcmp(session.parameters.sample_rate, "high") == 0) {
Jon Medhurst34d97692013-12-19 09:23:06 +000086 mSampleRate = 9973; // 10000
Jon Medhurstaaf37a32013-06-11 12:10:56 +010087 } else if (strcmp(session.parameters.sample_rate, "normal") == 0) {
Jon Medhurst34d97692013-12-19 09:23:06 +000088 mSampleRate = 997; // 1000
Jon Medhurstaaf37a32013-06-11 12:10:56 +010089 } else if (strcmp(session.parameters.sample_rate, "low") == 0) {
Jon Medhurst34d97692013-12-19 09:23:06 +000090 mSampleRate = 97; // 100
Jon Medhurstaaf37a32013-06-11 12:10:56 +010091 } else if (strcmp(session.parameters.sample_rate, "none") == 0) {
92 mSampleRate = 0;
93 } else {
Jon Medhurstb1d07442015-05-08 12:04:18 +010094 logg->logError("Invalid sample rate (%s) in session xml.", session.parameters.sample_rate);
Jon Medhurstaaf37a32013-06-11 12:10:56 +010095 handleException();
96 }
97 mBacktraceDepth = session.parameters.call_stack_unwinding == true ? 128 : 0;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010098
99 // Determine buffer size (in MB) based on buffer mode
100 mOneShot = true;
101 if (strcmp(session.parameters.buffer_mode, "streaming") == 0) {
102 mOneShot = false;
103 mTotalBufferSize = 1;
104 } else if (strcmp(session.parameters.buffer_mode, "small") == 0) {
105 mTotalBufferSize = 1;
106 } else if (strcmp(session.parameters.buffer_mode, "normal") == 0) {
107 mTotalBufferSize = 4;
108 } else if (strcmp(session.parameters.buffer_mode, "large") == 0) {
109 mTotalBufferSize = 16;
110 } else {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100111 logg->logError("Invalid value for buffer mode in session xml.");
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100112 handleException();
113 }
114
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100115 // Convert milli- to nanoseconds
116 mLiveRate = session.parameters.live_rate * (int64_t)1000000;
117 if (mLiveRate > 0 && mLocalCapture) {
118 logg->logMessage("Local capture is not compatable with live, disabling live");
119 mLiveRate = 0;
120 }
Jon Medhurst96b56152014-10-30 18:01:15 +0000121
122 if (!mAllowCommands && (mCaptureCommand != NULL)) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100123 logg->logError("Running a command during a capture is not currently allowed. Please restart gatord with the -a flag.");
Jon Medhurst96b56152014-10-30 18:01:15 +0000124 handleException();
125 }
126}
127
128void SessionData::readModel() {
129 FILE *fh = fopen("/proc/device-tree/model", "rb");
130 if (fh == NULL) {
131 return;
132 }
133
134 char buf[256];
135 if (fgets(buf, sizeof(buf), fh) != NULL) {
136 strcpy(mCoreName, buf);
137 }
138
139 fclose(fh);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100140}
141
Jon Medhurstb1d07442015-05-08 12:04:18 +0100142static void setImplementer(int &cpuId, const int implementer) {
143 if (cpuId == -1) {
144 cpuId = 0;
145 }
146 cpuId |= implementer << 12;
147}
148
149static void setPart(int &cpuId, const int part) {
150 if (cpuId == -1) {
151 cpuId = 0;
152 }
153 cpuId |= part;
154}
155
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100156void SessionData::readCpuInfo() {
157 char temp[256]; // arbitrarily large amount
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100158 mMaxCpuId = -1;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100159
Jon Medhurst96b56152014-10-30 18:01:15 +0000160 FILE *f = fopen("/proc/cpuinfo", "r");
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100161 if (f == NULL) {
162 logg->logMessage("Error opening /proc/cpuinfo\n"
163 "The core name in the captured xml file will be 'unknown'.");
164 return;
165 }
166
Jon Medhurstb1d07442015-05-08 12:04:18 +0100167 bool foundCoreName = (strcmp(mCoreName, CORE_NAME_UNKNOWN) != 0);
Jon Medhurste31266f2014-08-04 15:47:44 +0100168 int processor = -1;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100169 while (fgets(temp, sizeof(temp), f)) {
Jon Medhurste31266f2014-08-04 15:47:44 +0100170 const size_t len = strlen(temp);
171
172 if (len == 1) {
173 // New section, clear the processor. Streamline will not know the cpus if the pre Linux 3.8 format of cpuinfo is encountered but also that no incorrect information will be transmitted.
174 processor = -1;
175 continue;
176 }
177
178 if (len > 0) {
Jon Medhurst96b56152014-10-30 18:01:15 +0000179 // Replace the line feed with a null
180 temp[len - 1] = '\0';
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100181 }
182
Jon Medhurstb1d07442015-05-08 12:04:18 +0100183 const bool foundHardware = !foundCoreName && strstr(temp, "Hardware") != 0;
184 const bool foundCPUImplementer = strstr(temp, "CPU implementer") != 0;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100185 const bool foundCPUPart = strstr(temp, "CPU part") != 0;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100186 const bool foundProcessor = strstr(temp, "processor") != 0;
Jon Medhurstb1d07442015-05-08 12:04:18 +0100187 if (foundHardware || foundCPUImplementer || foundCPUPart || foundProcessor) {
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100188 char* position = strchr(temp, ':');
189 if (position == NULL || (unsigned int)(position - temp) + 2 >= strlen(temp)) {
190 logg->logMessage("Unknown format of /proc/cpuinfo\n"
191 "The core name in the captured xml file will be 'unknown'.");
192 return;
193 }
194 position += 2;
195
Jon Medhurstb1d07442015-05-08 12:04:18 +0100196 if (foundHardware) {
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100197 strncpy(mCoreName, position, sizeof(mCoreName));
198 mCoreName[sizeof(mCoreName) - 1] = 0; // strncpy does not guarantee a null-terminated string
199 foundCoreName = true;
200 }
201
Jon Medhurstb1d07442015-05-08 12:04:18 +0100202 if (foundCPUImplementer) {
203 const int implementer = strtol(position, NULL, 0);
Jon Medhurste31266f2014-08-04 15:47:44 +0100204 if (processor >= NR_CPUS) {
205 logg->logMessage("Too many processors, please increase NR_CPUS");
206 } else if (processor >= 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100207 setImplementer(mCpuIds[processor], implementer);
208 } else {
209 setImplementer(mMaxCpuId, implementer);
210 }
211 }
212
213 if (foundCPUPart) {
214 const int cpuId = strtol(position, NULL, 0);
215 if (processor >= NR_CPUS) {
216 logg->logMessage("Too many processors, please increase NR_CPUS");
217 } else if (processor >= 0) {
218 setPart(mCpuIds[processor], cpuId);
219 } else {
220 setPart(mMaxCpuId, cpuId);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100221 }
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100222 }
223
224 if (foundProcessor) {
225 processor = strtol(position, NULL, 0);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100226 }
227 }
228 }
229
Jon Medhurstb1d07442015-05-08 12:04:18 +0100230 // If this does not have the full topology in /proc/cpuinfo, mCpuIds[0] may not have the 1 CPU part emitted - this guarantees it's in mMaxCpuId
231 for (int i = 0; i < NR_CPUS; ++i) {
232 if (mCpuIds[i] > mMaxCpuId) {
233 mMaxCpuId = mCpuIds[i];
234 }
235 }
236
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100237 if (!foundCoreName) {
238 logg->logMessage("Could not determine core name from /proc/cpuinfo\n"
Jon Medhurste31266f2014-08-04 15:47:44 +0100239 "The core name in the captured xml file will be 'unknown'.");
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100240 }
241 fclose(f);
Jon Medhurste31266f2014-08-04 15:47:44 +0100242}
243
244uint64_t getTime() {
245 struct timespec ts;
Jon Medhurste31266f2014-08-04 15:47:44 +0100246 if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
Jon Medhurstb1d07442015-05-08 12:04:18 +0100247 logg->logError("Failed to get uptime");
Jon Medhurste31266f2014-08-04 15:47:44 +0100248 handleException();
249 }
250 return (NS_PER_S*ts.tv_sec + ts.tv_nsec);
251}
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100252
253int getEventKey() {
Jon Medhurst34d97692013-12-19 09:23:06 +0000254 // key 0 is reserved as a timestamp
255 // key 1 is reserved as the marker for thread specific counters
Jon Medhurst96b56152014-10-30 18:01:15 +0000256 // key 2 is reserved as the marker for core
Jon Medhurst34d97692013-12-19 09:23:06 +0000257 // Odd keys are assigned by the driver, even keys by the daemon
Jon Medhurst96b56152014-10-30 18:01:15 +0000258 static int key = 4;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100259
260 const int ret = key;
261 key += 2;
262 return ret;
263}
Jon Medhurst96b56152014-10-30 18:01:15 +0000264
265int pipe_cloexec(int pipefd[2]) {
266 if (pipe(pipefd) != 0) {
267 return -1;
268 }
269
270 int fdf;
271 if (((fdf = fcntl(pipefd[0], F_GETFD)) == -1) || (fcntl(pipefd[0], F_SETFD, fdf | FD_CLOEXEC) != 0) ||
272 ((fdf = fcntl(pipefd[1], F_GETFD)) == -1) || (fcntl(pipefd[1], F_SETFD, fdf | FD_CLOEXEC) != 0)) {
273 close(pipefd[0]);
274 close(pipefd[1]);
275 return -1;
276 }
277 return 0;
278}
279
280FILE *fopen_cloexec(const char *path, const char *mode) {
281 FILE *fh = fopen(path, mode);
282 if (fh == NULL) {
283 return NULL;
284 }
285 int fd = fileno(fh);
286 int fdf = fcntl(fd, F_GETFD);
287 if ((fdf == -1) || (fcntl(fd, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
288 fclose(fh);
289 return NULL;
290 }
291 return fh;
292}