Chromium Code Reviews| Index: systrace/systrace/tracing_agents/ftrace_agent.py |
| diff --git a/systrace/systrace/agents/ftrace_agent.py b/systrace/systrace/tracing_agents/ftrace_agent.py |
| similarity index 54% |
| rename from systrace/systrace/agents/ftrace_agent.py |
| rename to systrace/systrace/tracing_agents/ftrace_agent.py |
| index 758fc617e5e10dea6140501b7a7d678e6dbf49ce..1ffb93d80ab5da42141c924c3d7dce13918232ad 100644 |
| --- a/systrace/systrace/agents/ftrace_agent.py |
| +++ b/systrace/systrace/tracing_agents/ftrace_agent.py |
| @@ -4,10 +4,15 @@ |
| import os |
| import sys |
| -import time |
| -from systrace import systrace_agent |
| +from collections import namedtuple |
| +from devil.utils import timeout_retry |
| +from systrace.tracing_agents import TracingAgent |
| +from systrace.tracing_agents import TraceResults |
| +ftrace_postproc = namedtuple('ftrace_postproc', ['fix_threads', |
| + 'fix_tgids', |
| + 'fix_circular']) |
| class FtraceAgentIo(object): |
| @@ -25,6 +30,13 @@ class FtraceAgentIo(object): |
| def haveWritePermissions(path): |
| return os.access(path, os.W_OK) |
| + @staticmethod |
| + def checkedWriteFile(path, data): |
|
Zhen Wang
2016/03/30 16:14:08
nit: s/checkedWriteFile/checkAndWriteFile
alexandermont
2016/03/30 19:33:25
Done
|
| + if FtraceAgentIo.haveWritePermissions(path): |
| + FtraceAgentIo.writeFile(path, data) |
| + else: |
| + raise IOError('Cannot write to %s; did you forget sudo/root?' % path) |
| + |
| FT_DIR = "/sys/kernel/debug/tracing/" |
| FT_CLOCK = FT_DIR + "trace_clock" |
| FT_BUFFER_SIZE = FT_DIR + "buffer_size_kb" |
| @@ -84,116 +96,120 @@ all_categories = { |
| } |
| -def try_create_agent(options, categories): |
| +def list_categories(_): |
| + agent = FtraceAgent(FtraceAgentIo) |
| + agent._print_avail_categories() |
| + |
| + |
| +def try_create_agent(options, _): |
| if options.target != 'linux': |
| return False |
| - return FtraceAgent(options, categories, FtraceAgentIo) |
| + return FtraceAgent(FtraceAgentIo) |
| -class FtraceAgent(systrace_agent.SystraceAgent): |
| +def _get_trace_buffer_size(options): |
| + buffer_size = 4096 |
| + if ((options.trace_buf_size is not None) |
| + and (options.trace_buf_size > 0)): |
| + buffer_size = options.trace_buf_size |
| + return buffer_size |
| - def __init__(self, options, categories, fio=FtraceAgentIo): |
| + |
| +class FtraceAgent(TracingAgent): |
| + |
| + def __init__(self, fio=FtraceAgentIo): |
| """Initialize a systrace agent. |
| Args: |
| options: The command-line options. |
| categories: The trace categories to capture. |
| """ |
| - super(FtraceAgent, self).__init__(options, categories) |
| - if not self._categories: |
| - self._categories = ["sched"] |
| + super(FtraceAgent, self).__init__() |
| self._fio = fio |
| - self._categories = [x for x in self._categories |
| - if self._is_category_available(x)] |
| - self._expect_trace = False |
| - |
| - def _get_trace_buffer_size(self): |
| - buffer_size = 4096 |
| - if ((self._options.trace_buf_size is not None) |
| - and (self._options.trace_buf_size > 0)): |
| - buffer_size = self._options.trace_buf_size |
| - return buffer_size |
| - |
| - def _get_trace_time(self): |
| - wait_time = 5 |
| - if ((self._options.trace_time is not None) |
| - and (self._options.trace_time > 0)): |
| - wait_time = self._options.trace_time |
| - return wait_time |
| - |
| - def start(self): |
| + self._postproc = None |
| + self._categories = None |
| + |
| + def _fix_categories(self, categories): |
| + if not categories: |
| + categories = ["sched"] |
| + return [x for x in categories |
| + if self._is_category_available(x)] |
| + |
| + def _StartAgentTracing_func(self, options, categories): |
| """Start tracing. |
| """ |
| - if self._options.list_categories or len(self._categories) == 0: |
| - self._expect_trace = False |
| - else: |
| - self._expect_trace = True |
| + categories = self._fix_categories(categories) |
| + self._fio.checkedWriteFile(FT_BUFFER_SIZE, |
| + str(_get_trace_buffer_size(options))) |
| - self._fio.writeFile(FT_BUFFER_SIZE, str(self._get_trace_buffer_size())) |
| + self._fio.checkedWriteFile(FT_CLOCK, 'global') |
| + self._fio.checkedWriteFile(FT_TRACER, 'nop') |
| + self._fio.checkedWriteFile(FT_OVERWRITE, "0") |
| - self._fio.writeFile(FT_CLOCK, 'global') |
| - self._fio.writeFile(FT_TRACER, 'nop') |
| - self._fio.writeFile(FT_OVERWRITE, "0") |
| + # TODO: riandrews to push necessary patches for TGID option to upstream |
| + # linux kernel |
| + # self._fio.checkedWriteFile(FT_PRINT_TGID, '1') |
| - # TODO: riandrews to push necessary patches for TGID option to upstream |
| - # linux kernel |
| - # self._fio.writeFile(FT_PRINT_TGID, '1') |
| + for category in categories: |
| + self._category_enable(category) |
| - for category in self._categories: |
| - self._category_enable(category) |
| + self._categories = categories # need to store list of categories to disable |
| + self._postproc = ftrace_postproc(options.fix_threads, |
| + options.fix_tgids, |
| + options.fix_circular) |
| - self._fio.writeFile(FT_TRACE, '') |
| + self._fio.checkedWriteFile(FT_TRACE, '') |
| - print "starting tracing." |
| - sys.stdout.flush() |
| + print "starting tracing." |
| + sys.stdout.flush() |
| - self._fio.writeFile(FT_TRACE_ON, '1') |
| + self._fio.checkedWriteFile(FT_TRACE_ON, '1') |
| + return True |
| + |
| + def StartAgentTracing(self, options, categories, timeout=10): |
| + return timeout_retry.Run(self._StartAgentTracing_func, |
| + timeout, 1, |
| + args=[options, categories]) |
| - def collect_result(self): |
| + def _StopAgentTracing_func(self): |
| """Collect the result of tracing. |
| - This function will block while collecting the result. For sync mode, it |
| - reads the data, e.g., from stdout, until it finishes. For async mode, it |
| - blocks until the agent is stopped and the data is ready. |
| - """ |
| - if self._options.list_categories or len(self._categories) == 0: |
| - self._print_avail_categories() |
| - else: |
| - try: |
| - time.sleep(self._get_trace_time()) |
| - except KeyboardInterrupt: |
| - pass |
| - self._fio.writeFile(FT_TRACE_ON, '0') |
| - for category in self._categories: |
| - self._category_disable(category) |
| - if self._options.fix_threads: |
| - print "WARN: thread name fixing is not yet supported." |
| - if self._options.fix_tgids: |
| - print "WARN: tgid fixing is not yet supported." |
| - if self._options.fix_circular: |
| - print "WARN: circular buffer fixups are not yet supported." |
| - |
| - def expect_trace(self): |
| - """Check if the agent is returning a trace or not. |
| - |
| - This will be determined in collect_result(). |
| - Returns: |
| - Whether the agent is expecting a trace or not. |
| + This function will block while collecting the result. |
| """ |
| - return self._expect_trace |
| + self._fio.checkedWriteFile(FT_TRACE_ON, '0') |
| + for category in self._categories: |
| + self._category_disable(category) |
| + if self._postproc.fix_threads: |
| + print "WARN: thread name fixing is not yet supported." |
| + if self._postproc.fix_tgids: |
| + print "WARN: tgid fixing is not yet supported." |
| + if self._postproc.fix_circular: |
| + print "WARN: circular buffer fixups are not yet supported." |
| + return True |
| + |
| + def StopAgentTracing(self, timeout=10): |
| + return timeout_retry.Run(self._StopAgentTracing_func, |
| + timeout, 1) |
| - def get_trace_data(self): |
| + def _GetResults_func(self): |
| """Get the trace data. |
| Returns: |
| The trace data. |
| """ |
| d = self._fio.readFile(FT_TRACE) |
| - self._fio.writeFile(FT_BUFFER_SIZE, "1") |
| - return d |
| + self._fio.checkedWriteFile(FT_BUFFER_SIZE, "1") |
| + return TraceResults('systemTraceEvents', d) |
| + |
| + def GetResults(self, timeout=30): |
| + return timeout_retry.Run(self._GetResults_func, |
| + timeout, 1) |
| + |
| + def SupportsExplicitClockSync(self): |
| + return False |
| - def get_class_name(self): |
| - return 'trace-data' |
| + def RecordClockSyncMarker(self, sync_id, callback): |
| + raise NotImplementedError |
| def _is_category_available(self, category): |
| if category not in all_categories: |
| @@ -238,8 +254,8 @@ class FtraceAgent(systrace_agent.SystraceAgent): |
| def _category_enable(self, category): |
| for path in self._category_enable_paths(category): |
| - self._fio.writeFile(path, "1") |
| + self._fio.checkedWriteFile(path, "1") |
| def _category_disable(self, category): |
| for path in self._category_enable_paths(category): |
| - self._fio.writeFile(path, "0") |
| + self._fio.checkedWriteFile(path, "0") |