• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python
2#
3# Copyright (c) 2015 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7import os
8
9from autotest_lib.client.bin import test, utils
10from autotest_lib.client.common_lib import error
11
12
13class platform_TraceClockMonotonic(test.test):
14    """
15    This verifies that the kernel supports monotonic clock timestamps for
16    ftrace events.  This is the same clock that Chrome will use for
17    timestamping its trace events.
18    """
19    version = 1
20
21    executable = 'ftrace-clock-monotonic'
22
23    TRACE_PATH = '/sys/kernel/debug/tracing/'
24    TRACE_CLOCK = TRACE_PATH + 'trace_clock'
25    TRACE_FILE = TRACE_PATH + 'trace'
26    TRACE_ENABLE = TRACE_PATH + 'tracing_on'
27
28    def _setup_trace(self):
29        """
30        Verify that the system supports the monotonic trace clock and set up
31        the trace system to use it, and clean up any old stuff in the trace
32        and enable it.
33        """
34        with open(self.TRACE_CLOCK, 'r+') as clock:
35            content = clock.read()
36            if not 'mono' in content:
37                raise error.TestFail('Kernel does not support monotonic clock')
38
39            # Set up to use the monotonic clock
40            clock.write('mono')
41
42        # clear out the trace
43        with open(self.TRACE_FILE, 'w') as trace:
44            trace.write('')
45
46        # enable tracing
47        with open(self.TRACE_ENABLE, 'w') as enable:
48            enable.write('1')
49
50    def setup(self):
51        """Cleans and makes ftrace-clock-monotonic.c.
52
53        Prepares environment for tests by removing directory we will extract
54        to (if it exists), extracting tarball of tests, and making them.
55        """
56        os.chdir(self.srcdir)
57        utils.make('clean')
58        utils.make()
59
60    def process_trace(self):
61        """Opens the trace file and processes it.
62
63        Looks for the 3 markers that are written out by the binary.  The binary
64        gets a clock timestamp and then writes it out into the trace three times.
65        This looks at each entry and the content of the entry, and verifies that
66        they are all in chronological order.
67        Example trace file without the header:
68           <...>-16484 [003] ...1 509651.512676: tracing_mark_write: start: 509651.512651785
69           <...>-16484 [003] ...1 509651.512680: tracing_mark_write: middle: 509651.512678312
70           <...>-16484 [003] ...1 509651.512682: tracing_mark_write: end: 509651.512680934
71        """
72        with open(self.TRACE_FILE, 'r') as trace:
73            prev_timestamp = 0
74            for line in trace:
75                if 'tracing_mark_write' not in line:
76                    continue
77
78                columns = line.split()
79                entry_timestamp = float(columns[3].replace(':',''))
80                sample_timestamp = float(columns[6])
81                if sample_timestamp > entry_timestamp:
82                    raise error.TestFail('sample timestamp after trace marker entry')
83
84                if sample_timestamp < prev_timestamp:
85                    raise error.TestFail('sample timestamp before previous timestamp')
86                prev_timestamp = entry_timestamp
87
88            if prev_timestamp == 0:
89                raise error.TestFail('no valid timestamps seen in trace file')
90
91    def run_once(self):
92        self._setup_trace()
93        binpath = os.path.join(self.srcdir, self.executable)
94        utils.system_output(binpath, retain_output = True)
95        self.process_trace()
96