Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Side by Side Diff: systrace/systrace/agents/ftrace_agent.py

Issue 1776013005: [DO NOT COMMIT] Refactor systrace to support new clock sync design (Closed) Base URL: git@github.com:catapult-project/catapult@master
Patch Set: more changes from code reviews Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright (c) 2015 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 import os
6 import sys
7 import time
8
9 from systrace import systrace_agent
10
11
12 class FtraceAgentIo(object):
13
14 @staticmethod
15 def writeFile(path, data):
16 with open(path, 'w') as f:
17 f.write(data)
18
19 @staticmethod
20 def readFile(path):
21 with open(path, 'r') as f:
22 return f.read()
23
24 @staticmethod
25 def haveWritePermissions(path):
26 return os.access(path, os.W_OK)
27
28 FT_DIR = "/sys/kernel/debug/tracing/"
29 FT_CLOCK = FT_DIR + "trace_clock"
30 FT_BUFFER_SIZE = FT_DIR + "buffer_size_kb"
31 FT_TRACER = FT_DIR + "current_tracer"
32 FT_PRINT_TGID = FT_DIR + "options/print-tgid"
33 FT_TRACE_ON = FT_DIR + "tracing_on"
34 FT_TRACE = FT_DIR + "trace"
35 FT_TRACE_MARKER = FT_DIR + "trace_marker"
36 FT_OVERWRITE = FT_DIR + "options/overwrite"
37
38 all_categories = {
39 "sched": {
40 "desc": "CPU Scheduling",
41 "req": ["sched/sched_switch/", "sched/sched_wakeup/"]
42 },
43 "freq": {
44 "desc": "CPU Frequency",
45 "req": ["power/cpu_frequency/", "power/clock_set_rate/"]
46 },
47 "irq": {
48 "desc": "CPU IRQS and IPIS",
49 "req": ["irq/"],
50 "opt": ["ipi/"]
51 },
52 "workq": {
53 "desc": "Kernel workqueues",
54 "req": ["workqueue/"]
55 },
56 "memreclaim": {
57 "desc": "Kernel Memory Reclaim",
58 "req": ["vmscan/mm_vmscan_direct_reclaim_begin/",
59 "vmscan/mm_vmscan_direct_reclaim_end/",
60 "vmscan/mm_vmscan_kswapd_wake/",
61 "vmscan/mm_vmscan_kswapd_sleep/"]
62 },
63 "idle": {
64 "desc": "CPU Idle",
65 "req": ["power/cpu_idle/"]
66 },
67 "regulators": {
68 "desc": "Voltage and Current Regulators",
69 "req": ["regulator/"]
70 },
71 "disk": {
72 "desc": "Disk I/O",
73 "req": ["block/block_rq_issue/",
74 "block/block_rq_complete/"],
75 "opt": ["f2fs/f2fs_sync_file_enter/",
76 "f2fs/f2fs_sync_file_exit/",
77 "f2fs/f2fs_write_begin/",
78 "f2fs/f2fs_write_end/",
79 "ext4/ext4_da_write_begin/",
80 "ext4/ext4_da_write_end/",
81 "ext4/ext4_sync_file_enter/",
82 "ext4/ext4_sync_file_exit/"]
83 }
84 }
85
86
87 def try_create_agent(options, categories):
88 if options.target != 'linux':
89 return False
90 return FtraceAgent(options, categories, FtraceAgentIo)
91
92
93 class FtraceAgent(systrace_agent.SystraceAgent):
94
95 def __init__(self, options, categories, fio=FtraceAgentIo):
96 """Initialize a systrace agent.
97
98 Args:
99 options: The command-line options.
100 categories: The trace categories to capture.
101 """
102 super(FtraceAgent, self).__init__(options, categories)
103 if not self._categories:
104 self._categories = ["sched"]
105 self._fio = fio
106 self._categories = [x for x in self._categories
107 if self._is_category_available(x)]
108 self._expect_trace = False
109
110 def _get_trace_buffer_size(self):
111 buffer_size = 4096
112 if ((self._options.trace_buf_size is not None)
113 and (self._options.trace_buf_size > 0)):
114 buffer_size = self._options.trace_buf_size
115 return buffer_size
116
117 def _get_trace_time(self):
118 wait_time = 5
119 if ((self._options.trace_time is not None)
120 and (self._options.trace_time > 0)):
121 wait_time = self._options.trace_time
122 return wait_time
123
124 def start(self):
125 """Start tracing.
126 """
127 if self._options.list_categories or len(self._categories) == 0:
128 self._expect_trace = False
129 else:
130 self._expect_trace = True
131
132 self._fio.writeFile(FT_BUFFER_SIZE, str(self._get_trace_buffer_size()))
133
134 self._fio.writeFile(FT_CLOCK, 'global')
135 self._fio.writeFile(FT_TRACER, 'nop')
136 self._fio.writeFile(FT_OVERWRITE, "0")
137
138 # TODO: riandrews to push necessary patches for TGID option to upstream
139 # linux kernel
140 # self._fio.writeFile(FT_PRINT_TGID, '1')
141
142 for category in self._categories:
143 self._category_enable(category)
144
145 self._fio.writeFile(FT_TRACE, '')
146
147 print "starting tracing."
148 sys.stdout.flush()
149
150 self._fio.writeFile(FT_TRACE_ON, '1')
151
152 def collect_result(self):
153 """Collect the result of tracing.
154
155 This function will block while collecting the result. For sync mode, it
156 reads the data, e.g., from stdout, until it finishes. For async mode, it
157 blocks until the agent is stopped and the data is ready.
158 """
159 if self._options.list_categories or len(self._categories) == 0:
160 self._print_avail_categories()
161 else:
162 try:
163 time.sleep(self._get_trace_time())
164 except KeyboardInterrupt:
165 pass
166 self._fio.writeFile(FT_TRACE_ON, '0')
167 for category in self._categories:
168 self._category_disable(category)
169 if self._options.fix_threads:
170 print "WARN: thread name fixing is not yet supported."
171 if self._options.fix_tgids:
172 print "WARN: tgid fixing is not yet supported."
173 if self._options.fix_circular:
174 print "WARN: circular buffer fixups are not yet supported."
175
176 def expect_trace(self):
177 """Check if the agent is returning a trace or not.
178
179 This will be determined in collect_result().
180 Returns:
181 Whether the agent is expecting a trace or not.
182 """
183 return self._expect_trace
184
185 def get_trace_data(self):
186 """Get the trace data.
187
188 Returns:
189 The trace data.
190 """
191 d = self._fio.readFile(FT_TRACE)
192 self._fio.writeFile(FT_BUFFER_SIZE, "1")
193 return d
194
195 def get_class_name(self):
196 return 'trace-data'
197
198 def _is_category_available(self, category):
199 if category not in all_categories:
200 return False
201 events_dir = FT_DIR + "events/"
202 req_events = all_categories[category]["req"]
203 for event in req_events:
204 event_full_path = events_dir + event + "enable"
205 if not self._fio.haveWritePermissions(event_full_path):
206 return False
207 return True
208
209 def _avail_categories(self):
210 ret = []
211 for event in all_categories:
212 if self._is_category_available(event):
213 ret.append(event)
214 return ret
215
216 def _print_avail_categories(self):
217 avail = self._avail_categories()
218 if len(avail):
219 print "tracing options:"
220 for category in self._avail_categories():
221 desc = all_categories[category]["desc"]
222 print "{0: <16}".format(category), ": ", desc
223 else:
224 print "No tracing categories available - perhaps you need root?"
225
226 def _category_enable_paths(self, category):
227 events_dir = FT_DIR + "events/"
228 req_events = all_categories[category]["req"]
229 for event in req_events:
230 event_full_path = events_dir + event + "enable"
231 yield event_full_path
232 if "opt" in all_categories[category]:
233 opt_events = all_categories[category]["opt"]
234 for event in opt_events:
235 event_full_path = events_dir + event + "enable"
236 if self._fio.haveWritePermissions(event_full_path):
237 yield event_full_path
238
239 def _category_enable(self, category):
240 for path in self._category_enable_paths(category):
241 self._fio.writeFile(path, "1")
242
243 def _category_disable(self, category):
244 for path in self._category_enable_paths(category):
245 self._fio.writeFile(path, "0")
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698