OLD | NEW |
---|---|
(Empty) | |
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. | |
4 | |
5 #include "base/debug/trace_event_impl.h" | |
6 | |
7 #include <fcntl.h> | |
8 | |
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" | |
14 | |
15 namespace { | |
16 | |
17 int g_atrace_fd = -1; | |
18 const char* kATraceMarkerFile = "/sys/kernel/debug/tracing/trace_marker"; | |
19 | |
20 } // namespace | |
21 | |
22 namespace base { | |
23 namespace debug { | |
24 | |
25 // static | |
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; | |
31 } | |
32 | |
33 // static | |
34 bool TraceLog::IsATraceEnabled() { | |
35 return g_atrace_fd != -1; | |
36 } | |
37 | |
38 void TraceLog::SendToATrace(char phase, | |
39 const char* category, | |
40 const char* name, | |
41 int num_args, | |
42 const char** arg_names, | |
43 const unsigned char* arg_types, | |
44 const unsigned long long* arg_values) { | |
45 if (!IsATraceEnabled()) | |
46 return; | |
47 | |
48 switch (phase) { | |
49 case TRACE_EVENT_PHASE_BEGIN: | |
50 case TRACE_EVENT_PHASE_INSTANT: { | |
51 std::string out = StringPrintf("B|%d|%s-%s", getpid(), category, name); | |
52 // Append the value of the arguments to the name. | |
53 // TODO(wangxianzhu): Send arguments to atrace when it supports arguments. | |
54 for (int i = 0; i < num_args; ++i) { | |
epenner
2012/10/29 23:58:55
I just tried this patch and I think this causes so
Xianzhu
2012/10/30 02:21:31
In the last patch set instead of appending the arg
| |
55 out += ';'; | |
56 out += arg_names[i]; | |
57 out += '='; | |
58 TraceEvent::TraceValue value; | |
59 value.as_uint = arg_values[i]; | |
60 std::string::size_type value_start = out.length(); | |
61 TraceEvent::AppendValueAsJSON(arg_types[i], value, &out); | |
62 // Remove the quotes which may confuse the atrace script. | |
63 ReplaceSubstringsAfterOffset(&out, value_start, "\\\"", "'"); | |
64 ReplaceSubstringsAfterOffset(&out, value_start, "\"", ""); | |
65 } | |
66 write(g_atrace_fd, out.c_str(), out.size()); | |
67 | |
68 if (phase != TRACE_EVENT_PHASE_INSTANT) | |
69 break; | |
70 // Fall through. Simulate an instance event with a pair of begin/end. | |
71 } | |
72 case TRACE_EVENT_PHASE_END: { | |
73 // Though a single 'E' is enough, here append pid and name so that | |
74 // unpaired events can be found easily. | |
75 std::string out = StringPrintf("E|%d|%s-%s", getpid(), category, name); | |
76 write(g_atrace_fd, out.c_str(), out.size()); | |
77 break; | |
78 } | |
79 case TRACE_EVENT_PHASE_COUNTER: | |
80 for (int i = 0; i < num_args; ++i) { | |
81 DCHECK(arg_types[i] == TRACE_VALUE_TYPE_INT); | |
82 std::string out = StringPrintf( | |
83 "C|%d|%s-%s-%s|%d", | |
84 getpid(), category, name, | |
85 arg_names[i], static_cast<int>(arg_values[i])); | |
86 write(g_atrace_fd, out.c_str(), out.size()); | |
87 } | |
88 break; | |
89 | |
90 default: | |
91 // Do nothing. | |
92 break; | |
93 } | |
94 } | |
95 | |
96 void TraceLog::AddClockSyncMetadataEvents() { | |
97 // Since Android does not support sched_setaffinity, we cannot establish clock | |
98 // sync unless the scheduler clock is set to global. If the trace_clock file | |
99 // can't be read, we will assume the kernel doesn't support tracing and do | |
100 // nothing. | |
101 std::string clock_mode; | |
102 if (!file_util::ReadFileToString( | |
103 FilePath("/sys/kernel/debug/tracing/trace_clock"), &clock_mode)) | |
104 return; | |
105 | |
106 if (clock_mode != "local [global]\n") { | |
107 DLOG(WARNING) << | |
108 "The kernel's tracing clock must be set to global in order for " << | |
109 "trace_event to be synchronized with . Do this by\n" << | |
110 " echo global > /sys/kerel/debug/tracing/trace_clock"; | |
111 return; | |
112 } | |
113 | |
114 int atrace_fd = g_atrace_fd; | |
115 if (atrace_fd == -1) { | |
116 // This function may be called when atrace is not enabled. | |
117 atrace_fd = open(kATraceMarkerFile, O_WRONLY | O_APPEND); | |
118 if (atrace_fd == -1) { | |
119 LOG(WARNING) << "Couldn't open " << kATraceMarkerFile; | |
120 return; | |
121 } | |
122 } | |
123 | |
124 // Android's kernel trace system has a trace_marker feature: this is a file on | |
125 // debugfs that takes the written data and pushes it onto the trace | |
126 // buffer. So, to establish clock sync, we write our monotonic clock into that | |
127 // trace buffer. | |
128 TimeTicks now = TimeTicks::NowFromSystemTraceTime(); | |
129 double now_in_seconds = now.ToInternalValue() / 1000000.0; | |
130 std::string marker = StringPrintf( | |
131 "trace_event_clock_sync: parent_ts=%f\n", now_in_seconds); | |
132 if (write(atrace_fd, marker.c_str(), marker.size()) != 0) { | |
133 DLOG(WARNING) << "Couldn't write to " << kATraceMarkerFile << ": " | |
134 << strerror(errno); | |
135 } | |
136 | |
137 if (g_atrace_fd == -1) | |
138 close(atrace_fd); | |
139 } | |
140 | |
141 } // namespace debug | |
142 } // namespace base | |
OLD | NEW |