2 * Copyright (C) ARM Limited 2010-2015. 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.
9 #include "FtraceSource.h"
13 #include <sys/prctl.h>
14 #include <sys/syscall.h>
18 #include "DriverSource.h"
20 #include "SessionData.h"
24 static void handler(int signum)
29 FtraceSource::FtraceSource(sem_t *senderSem) : mFtraceFh(NULL), mBuffer(0, FRAME_BLOCK_COUNTER, 128*1024, senderSem), mTid(-1), mTracingOn(0) {
32 FtraceSource::~FtraceSource() {
35 bool FtraceSource::prepare() {
38 act.sa_handler = handler;
39 act.sa_flags = (int)SA_RESETHAND;
40 if (sigaction(SIGUSR1, &act, NULL) != 0) {
41 logg->logError("sigaction failed: %s\n", strerror(errno));
46 gSessionData->ftraceDriver.prepare();
48 if (DriverSource::readIntDriver("/sys/kernel/debug/tracing/tracing_on", &mTracingOn)) {
49 logg->logError("Unable to read if ftrace is enabled");
53 if (DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", "0") != 0) {
54 logg->logError("Unable to turn ftrace off before truncating the buffer");
60 fd = open("/sys/kernel/debug/tracing/trace", O_WRONLY | O_TRUNC | O_CLOEXEC, 0666);
62 logg->logError("Unable truncate ftrace buffer: %s", strerror(errno));
68 if (DriverSource::writeDriver("/sys/kernel/debug/tracing/trace_clock", "perf") != 0) {
69 logg->logError("Unable to switch ftrace to the perf clock, please ensure you are running Linux 3.10 or later");
73 mFtraceFh = fopen_cloexec("/sys/kernel/debug/tracing/trace_pipe", "rb");
74 if (mFtraceFh == NULL) {
75 logg->logError("Unable to open trace_pipe");
82 void FtraceSource::run() {
83 prctl(PR_SET_NAME, (unsigned long)&"gatord-ftrace", 0, 0, 0);
84 mTid = syscall(__NR_gettid);
86 if (DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", "1") != 0) {
87 logg->logError("Unable to turn ftrace on");
91 // Wait until monotonicStarted is set before sending data
92 int64_t monotonicStarted = 0;
93 while (monotonicStarted <= 0 && gSessionData->mSessionIsActive) {
96 if (gSessionData->perf.isSetup()) {
97 monotonicStarted = gSessionData->mMonotonicStarted;
99 if (DriverSource::readInt64Driver("/dev/gator/started", &monotonicStarted) == -1) {
100 logg->logError("Error reading gator driver start time");
106 while (gSessionData->mSessionIsActive) {
109 if (fgets(buf, sizeof(buf), mFtraceFh) == NULL) {
110 if (errno == EINTR) {
111 // Interrupted by interrupt - likely user request to terminate
114 logg->logError("Unable read trace data: %s", strerror(errno));
118 const uint64_t currTime = getTime() - gSessionData->mMonotonicStarted;
120 char *const colon = strstr(buf, ": ");
122 if (strstr(buf, " [LOST ") != NULL) {
123 logg->logError("Ftrace events lost, aborting the capture. It is recommended to discard this report and collect a new capture. If this error occurs often, please reduce the number of ftrace counters selected or the amount of ftrace events generated.");
125 logg->logError("Unable to find colon: %s", buf);
131 char *const space = strrchr(buf, ' ');
133 logg->logError("Unable to find space: %s", buf);
138 int64_t *data = NULL;
139 int count = gSessionData->ftraceDriver.read(colon + 2, &data);
142 const long long time = strtod(space, NULL) * 1000000000;
144 logg->logError("Unable to parse time: %s", strerror(errno));
147 mBuffer.event64(-1, time);
149 for (int i = 0; i < count; ++i) {
150 mBuffer.event64(data[2*i + 0], data[2*i + 1]);
153 mBuffer.check(currTime);
155 if (gSessionData->mOneShot && gSessionData->mSessionIsActive && (mBuffer.bytesAvailable() <= 0)) {
156 logg->logMessage("One shot (ftrace)");
165 DriverSource::writeDriver("/sys/kernel/debug/tracing/tracing_on", mTracingOn);
167 DriverSource::writeDriver("/sys/kernel/debug/tracing/trace_clock", "local");
168 gSessionData->ftraceDriver.stop();
171 void FtraceSource::interrupt() {
172 // Closing the underlying file handle does not result in the read on the ftrace file handle to return, so send a signal to the thread
173 syscall(__NR_tgkill, getpid(), mTid, SIGUSR1);
176 bool FtraceSource::isDone() {
177 return mBuffer.isDone();
180 void FtraceSource::write(Sender *sender) {
181 // Don't send ftrace data until the summary packet is sent so that monotonic delta is available
182 if (!gSessionData->mSentSummary) {
185 if (!mBuffer.isDone()) {
186 mBuffer.write(sender);