blob: 0e65d7842647d95c48cc1f5950ed550a4a368062 [file] [log] [blame]
Jon Medhurstaaf37a32013-06-11 12:10:56 +01001/**
Jon Medhurst15ce78d2014-04-10 09:02:02 +01002 * Copyright (C) ARM Limited 2010-2014. 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 "CPUFreqDriver.h"
17#include "DiskIODriver.h"
18#include "FSDriver.h"
19#include "HwmonDriver.h"
Jon Medhurstaaf37a32013-06-11 12:10:56 +010020#include "Logging.h"
Jon Medhurst96b56152014-10-30 18:01:15 +000021#include "MemInfoDriver.h"
22#include "NetDriver.h"
23#include "SessionXML.h"
24
25#define CORE_NAME_UNKNOWN "unknown"
Jon Medhurstaaf37a32013-06-11 12:10:56 +010026
27SessionData* gSessionData = NULL;
28
29SessionData::SessionData() {
Jon Medhurst96b56152014-10-30 18:01:15 +000030 usDrivers[0] = new HwmonDriver();
31 usDrivers[1] = new FSDriver();
32 usDrivers[2] = new MemInfoDriver();
33 usDrivers[3] = new NetDriver();
34 usDrivers[4] = new CPUFreqDriver();
35 usDrivers[5] = new DiskIODriver();
Jon Medhurstaaf37a32013-06-11 12:10:56 +010036 initialize();
37}
38
39SessionData::~SessionData() {
40}
41
42void SessionData::initialize() {
43 mWaitingOnCommand = false;
44 mSessionIsActive = false;
45 mLocalCapture = false;
46 mOneShot = false;
Jon Medhurste31266f2014-08-04 15:47:44 +010047 mSentSummary = false;
Jon Medhurst96b56152014-10-30 18:01:15 +000048 mAllowCommands = false;
Jon Medhurste31266f2014-08-04 15:47:44 +010049 const size_t cpuIdSize = sizeof(int)*NR_CPUS;
50 // Share mCpuIds across all instances of gatord
51 mCpuIds = (int *)mmap(NULL, cpuIdSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
52 if (mCpuIds == MAP_FAILED) {
53 logg->logError(__FILE__, __LINE__, "Unable to mmap shared memory for cpuids");
54 handleException();
55 }
56 memset(mCpuIds, -1, cpuIdSize);
Jon Medhurst96b56152014-10-30 18:01:15 +000057 strcpy(mCoreName, CORE_NAME_UNKNOWN);
58 readModel();
Jon Medhurstaaf37a32013-06-11 12:10:56 +010059 readCpuInfo();
Jon Medhurst96b56152014-10-30 18:01:15 +000060 mImages = NULL;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010061 mConfigurationXMLPath = NULL;
62 mSessionXMLPath = NULL;
63 mEventsXMLPath = NULL;
64 mTargetPath = NULL;
65 mAPCDir = NULL;
Jon Medhurst96b56152014-10-30 18:01:15 +000066 mCaptureWorkingDir = NULL;
67 mCaptureCommand = NULL;
68 mCaptureUser = NULL;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010069 mSampleRate = 0;
70 mLiveRate = 0;
71 mDuration = 0;
Jon Medhurst96b56152014-10-30 18:01:15 +000072 mMonotonicStarted = -1;
Jon Medhurstaaf37a32013-06-11 12:10:56 +010073 mBacktraceDepth = 0;
74 mTotalBufferSize = 0;
75 // sysconf(_SC_NPROCESSORS_CONF) is unreliable on 2.6 Android, get the value from the kernel module
76 mCores = 1;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010077 mPageSize = 0;
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 {
94 logg->logError(__FILE__, __LINE__, "Invalid sample rate (%s) in session xml.", session.parameters.sample_rate);
95 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 {
111 logg->logError(__FILE__, __LINE__, "Invalid value for buffer mode in session xml.");
112 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)) {
123 logg->logError(__FILE__, __LINE__, "Running a command during a capture is not currently allowed. Please restart gatord with the -a flag.");
124 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
142void SessionData::readCpuInfo() {
143 char temp[256]; // arbitrarily large amount
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100144 mMaxCpuId = -1;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100145
Jon Medhurst96b56152014-10-30 18:01:15 +0000146 FILE *f = fopen("/proc/cpuinfo", "r");
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100147 if (f == NULL) {
148 logg->logMessage("Error opening /proc/cpuinfo\n"
149 "The core name in the captured xml file will be 'unknown'.");
150 return;
151 }
152
153 bool foundCoreName = false;
Jon Medhurste31266f2014-08-04 15:47:44 +0100154 int processor = -1;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100155 while (fgets(temp, sizeof(temp), f)) {
Jon Medhurste31266f2014-08-04 15:47:44 +0100156 const size_t len = strlen(temp);
157
158 if (len == 1) {
159 // 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.
160 processor = -1;
161 continue;
162 }
163
164 if (len > 0) {
Jon Medhurst96b56152014-10-30 18:01:15 +0000165 // Replace the line feed with a null
166 temp[len - 1] = '\0';
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100167 }
168
169 const bool foundHardware = strstr(temp, "Hardware") != 0;
170 const bool foundCPUPart = strstr(temp, "CPU part") != 0;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100171 const bool foundProcessor = strstr(temp, "processor") != 0;
172 if (foundHardware || foundCPUPart || foundProcessor) {
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100173 char* position = strchr(temp, ':');
174 if (position == NULL || (unsigned int)(position - temp) + 2 >= strlen(temp)) {
175 logg->logMessage("Unknown format of /proc/cpuinfo\n"
176 "The core name in the captured xml file will be 'unknown'.");
177 return;
178 }
179 position += 2;
180
Jon Medhurst96b56152014-10-30 18:01:15 +0000181 if (foundHardware && (strcmp(mCoreName, CORE_NAME_UNKNOWN) == 0)) {
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100182 strncpy(mCoreName, position, sizeof(mCoreName));
183 mCoreName[sizeof(mCoreName) - 1] = 0; // strncpy does not guarantee a null-terminated string
184 foundCoreName = true;
185 }
186
187 if (foundCPUPart) {
Jon Medhurste31266f2014-08-04 15:47:44 +0100188 const int cpuId = strtol(position, NULL, 0);
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100189 // 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
Jon Medhurste31266f2014-08-04 15:47:44 +0100190 if (cpuId > mMaxCpuId) {
191 mMaxCpuId = cpuId;
192 }
193 if (processor >= NR_CPUS) {
194 logg->logMessage("Too many processors, please increase NR_CPUS");
195 } else if (processor >= 0) {
196 mCpuIds[processor] = cpuId;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100197 }
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100198 }
199
200 if (foundProcessor) {
201 processor = strtol(position, NULL, 0);
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100202 }
203 }
204 }
205
206 if (!foundCoreName) {
207 logg->logMessage("Could not determine core name from /proc/cpuinfo\n"
Jon Medhurste31266f2014-08-04 15:47:44 +0100208 "The core name in the captured xml file will be 'unknown'.");
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100209 }
210 fclose(f);
Jon Medhurste31266f2014-08-04 15:47:44 +0100211}
212
213uint64_t getTime() {
214 struct timespec ts;
Jon Medhurste31266f2014-08-04 15:47:44 +0100215 if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) != 0) {
216 logg->logError(__FILE__, __LINE__, "Failed to get uptime");
217 handleException();
218 }
219 return (NS_PER_S*ts.tv_sec + ts.tv_nsec);
220}
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100221
222int getEventKey() {
Jon Medhurst34d97692013-12-19 09:23:06 +0000223 // key 0 is reserved as a timestamp
224 // key 1 is reserved as the marker for thread specific counters
Jon Medhurst96b56152014-10-30 18:01:15 +0000225 // key 2 is reserved as the marker for core
Jon Medhurst34d97692013-12-19 09:23:06 +0000226 // Odd keys are assigned by the driver, even keys by the daemon
Jon Medhurst96b56152014-10-30 18:01:15 +0000227 static int key = 4;
Jon Medhurstaaf37a32013-06-11 12:10:56 +0100228
229 const int ret = key;
230 key += 2;
231 return ret;
232}
Jon Medhurst96b56152014-10-30 18:01:15 +0000233
234int pipe_cloexec(int pipefd[2]) {
235 if (pipe(pipefd) != 0) {
236 return -1;
237 }
238
239 int fdf;
240 if (((fdf = fcntl(pipefd[0], F_GETFD)) == -1) || (fcntl(pipefd[0], F_SETFD, fdf | FD_CLOEXEC) != 0) ||
241 ((fdf = fcntl(pipefd[1], F_GETFD)) == -1) || (fcntl(pipefd[1], F_SETFD, fdf | FD_CLOEXEC) != 0)) {
242 close(pipefd[0]);
243 close(pipefd[1]);
244 return -1;
245 }
246 return 0;
247}
248
249FILE *fopen_cloexec(const char *path, const char *mode) {
250 FILE *fh = fopen(path, mode);
251 if (fh == NULL) {
252 return NULL;
253 }
254 int fd = fileno(fh);
255 int fdf = fcntl(fd, F_GETFD);
256 if ((fdf == -1) || (fcntl(fd, F_SETFD, fdf | FD_CLOEXEC) != 0)) {
257 fclose(fh);
258 return NULL;
259 }
260 return fh;
261}