blob: 37dc1475b9c225e564ee4ab1d29b16c999ef8dc4 [file] [log] [blame]
Brian Silverman79ec7fc2020-06-08 20:11:22 -05001#include "aos/ftrace.h"
2
Tyler Chatowbf0609c2021-07-31 16:13:27 -07003#include <cstdarg>
4#include <cstdio>
Brian Silverman79ec7fc2020-06-08 20:11:22 -05005
Austin Schuhc9de0132022-12-26 18:04:53 -08006#include "absl/strings/str_cat.h"
7
8DEFINE_bool(enable_ftrace, false,
9 "If false, disable logging to /sys/kernel/tracing/trace_marker");
Austin Schuh27237362021-11-06 16:29:02 -070010
Brian Silverman79ec7fc2020-06-08 20:11:22 -050011namespace aos {
12
Austin Schuhc9de0132022-12-26 18:04:53 -080013namespace {
Austin Schuh3458e492022-12-26 13:41:54 -080014int MaybeCheckOpen(const char *file) {
15 if (!FLAGS_enable_ftrace) return -1;
Austin Schuhc9de0132022-12-26 18:04:53 -080016 int result =
17 open(absl::StrCat("/sys/kernel/tracing/", file).c_str(), O_WRONLY);
18 if (result == -1) {
19 result = open(absl::StrCat("/sys/kernel/debug/tracing/", file).c_str(),
20 O_WRONLY);
21 }
22
23 // New kernels prefer /sys/kernel/tracing, and old kernels prefer
24 // /sys/kernel/debug/tracing... When Ubuntu 18.04 and the 4.9 kernel
25 // disappear finally, we can switch fully to /sys/kernel/tracing.
26 PCHECK(result >= 0) << ": Failed to open /sys/kernel/tracing/" << file
27 << " or legacy /sys/kernel/debug/tracing/" << file;
Austin Schuh3458e492022-12-26 13:41:54 -080028 return result;
29}
Austin Schuhc9de0132022-12-26 18:04:53 -080030} // namespace
Austin Schuh3458e492022-12-26 13:41:54 -080031
Austin Schuh27237362021-11-06 16:29:02 -070032Ftrace::Ftrace()
Austin Schuhc9de0132022-12-26 18:04:53 -080033 : message_fd_(MaybeCheckOpen("trace_marker")),
34 on_fd_(MaybeCheckOpen("tracing_on")) {}
Austin Schuh27237362021-11-06 16:29:02 -070035
Brian Silverman79ec7fc2020-06-08 20:11:22 -050036Ftrace::~Ftrace() {
37 if (message_fd_ != -1) {
38 PCHECK(close(message_fd_) == 0);
39 }
40 if (message_fd_ != -1) {
41 PCHECK(close(on_fd_) == 0);
42 }
43}
44
45void Ftrace::FormatMessage(const char *format, ...) {
46 if (message_fd_ == -1) {
47 return;
48 }
49 char buffer[512];
50 va_list ap;
51 va_start(ap, format);
52 const int result = vsnprintf(buffer, sizeof(buffer), format, ap);
53 va_end(ap);
54 CHECK_LE(static_cast<size_t>(result), sizeof(buffer))
55 << ": Format string ended up too long: " << format;
56 WriteMessage(std::string_view(buffer, result));
57}
58
59void Ftrace::WriteMessage(std::string_view content) {
60 if (message_fd_ == -1) {
61 return;
62 }
63 const int result = write(message_fd_, content.data(), content.size());
64 if (result == -1 && errno == EBADF) {
65 // This just means tracing is turned off. Ignore it.
66 return;
67 }
68 PCHECK(result >= 0) << ": Failed to write ftrace message: " << content;
69 CHECK_EQ(static_cast<size_t>(result), content.size())
70 << ": Failed to write complete ftrace message: " << content;
71}
72
73} // namespace aos