1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/debug/trace_event_impl.h"
9 #include "base/debug/trace_event.h"
10 #include "base/file_util.h"
11 #include "base/format_macros.h"
12 #include "base/logging.h"
13 #include "base/stringprintf.h"
18 const char* kATraceMarkerFile
= "/sys/kernel/debug/tracing/trace_marker";
26 void TraceLog::InitATrace() {
27 DCHECK(g_atrace_fd
== -1);
28 g_atrace_fd
= open(kATraceMarkerFile
, O_WRONLY
| O_APPEND
);
29 if (g_atrace_fd
== -1)
30 LOG(WARNING
) << "Couldn't open " << kATraceMarkerFile
;
33 void TraceLog::SendToATrace(char phase
,
37 const char** arg_names
,
38 const unsigned char* arg_types
,
39 const unsigned long long* arg_values
) {
40 if (g_atrace_fd
== -1)
44 case TRACE_EVENT_PHASE_BEGIN
:
45 case TRACE_EVENT_PHASE_INSTANT
: {
46 std::string out
= StringPrintf("B|%d|%s-%s", getpid(), category
, name
);
47 for (int i
= 0; i
< num_args
; ++i
) {
48 out
+= (i
== 0 ? '|' : ';');
51 TraceEvent::TraceValue value
;
52 value
.as_uint
= arg_values
[i
];
53 std::string::size_type value_start
= out
.length();
54 TraceEvent::AppendValueAsJSON(arg_types
[i
], value
, &out
);
55 // Remove the quotes which may confuse the atrace script.
56 ReplaceSubstringsAfterOffset(&out
, value_start
, "\\\"", "'");
57 ReplaceSubstringsAfterOffset(&out
, value_start
, "\"", "");
58 // Replace chars used for separators with similar chars in the value.
59 std::replace(out
.begin() + value_start
, out
.end(), ';', ',');
60 std::replace(out
.begin() + value_start
, out
.end(), '|', '!');
62 write(g_atrace_fd
, out
.c_str(), out
.size());
64 if (phase
!= TRACE_EVENT_PHASE_INSTANT
)
66 // Fall through. Simulate an instance event with a pair of begin/end.
68 case TRACE_EVENT_PHASE_END
: {
69 // Though a single 'E' is enough, here append pid and name so that
70 // unpaired events can be found easily.
71 std::string out
= StringPrintf("E|%d|%s-%s", getpid(), category
, name
);
72 write(g_atrace_fd
, out
.c_str(), out
.size());
75 case TRACE_EVENT_PHASE_COUNTER
:
76 for (int i
= 0; i
< num_args
; ++i
) {
77 DCHECK(arg_types
[i
] == TRACE_VALUE_TYPE_INT
);
78 std::string out
= StringPrintf(
80 getpid(), category
, name
,
81 arg_names
[i
], static_cast<int>(arg_values
[i
]));
82 write(g_atrace_fd
, out
.c_str(), out
.size());
92 void TraceLog::AddClockSyncMetadataEvents() {
93 // Since Android does not support sched_setaffinity, we cannot establish clock
94 // sync unless the scheduler clock is set to global. If the trace_clock file
95 // can't be read, we will assume the kernel doesn't support tracing and do
97 std::string clock_mode
;
98 if (!file_util::ReadFileToString(
99 FilePath("/sys/kernel/debug/tracing/trace_clock"), &clock_mode
))
102 if (clock_mode
!= "local [global]\n") {
104 "The kernel's tracing clock must be set to global in order for " <<
105 "trace_event to be synchronized with . Do this by\n" <<
106 " echo global > /sys/kerel/debug/tracing/trace_clock";
110 int atrace_fd
= g_atrace_fd
;
111 if (atrace_fd
== -1) {
112 // This function may be called when atrace is not enabled.
113 atrace_fd
= open(kATraceMarkerFile
, O_WRONLY
| O_APPEND
);
114 if (atrace_fd
== -1) {
115 LOG(WARNING
) << "Couldn't open " << kATraceMarkerFile
;
120 // Android's kernel trace system has a trace_marker feature: this is a file on
121 // debugfs that takes the written data and pushes it onto the trace
122 // buffer. So, to establish clock sync, we write our monotonic clock into that
124 TimeTicks now
= TimeTicks::NowFromSystemTraceTime();
125 double now_in_seconds
= now
.ToInternalValue() / 1000000.0;
126 std::string marker
= StringPrintf(
127 "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds
);
128 if (write(atrace_fd
, marker
.c_str(), marker
.size()) != 0) {
129 DLOG(WARNING
) << "Couldn't write to " << kATraceMarkerFile
<< ": "
133 if (g_atrace_fd
== -1)
137 // Must be called with lock_ locked.
138 void TraceLog::ApplyATraceEnabledFlag(unsigned char* category_enabled
) {
139 if (g_atrace_fd
!= -1)
140 *category_enabled
|= ATRACE_ENABLED
;