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/**
6 * @fileoverview Parses Mali DDK/kernel events in the Linux event trace format.
7 */
8base.require('linux_perf_parser');
9base.exportTo('tracing', function() {
10
11  var LinuxPerfParser = tracing.LinuxPerfParser;
12
13  /**
14   * Parses Mali DDK/kernel trace events.
15   * @constructor
16   */
17  function LinuxPerfMaliParser(importer) {
18    LinuxPerfParser.call(this, importer);
19
20    // kernel events
21    importer.registerEventHandler('mali_dvfs_event',
22        LinuxPerfMaliParser.prototype.dvfsEventEvent.bind(this));
23    importer.registerEventHandler('mali_dvfs_set_clock',
24        LinuxPerfMaliParser.prototype.dvfsSetClockEvent.bind(this));
25    importer.registerEventHandler('mali_dvfs_set_voltage',
26        LinuxPerfMaliParser.prototype.dvfsSetVoltageEvent.bind(this));
27
28    // DDK events (from X server)
29    importer.registerEventHandler('tracing_mark_write:mali_driver',
30        LinuxPerfMaliParser.prototype.maliDDKEvent.bind(this));
31  }
32
33  LinuxPerfMaliParser.prototype = {
34    __proto__: LinuxPerfParser.prototype,
35
36    maliDDKOpenSlice: function(pid, ts, func, blockinfo) {
37      var kthread = this.importer.getOrCreateKernelThread('mali_ddk', pid,
38                                                          'mali_ddk');
39      kthread.thread.beginSlice('gpu-driver', func, ts,
40                                { 'blockinfo': blockinfo });
41    },
42
43    maliDDKCloseSlice: function(pid, ts, args, blockinfo) {
44      var kthread = this.importer.getOrCreateKernelThread('mali_ddk', pid,
45                                                          'mali_ddk');
46      var thread = kthread.thread;
47      if (!thread.openSliceCount) {
48        this.importer.importError('maliDDKCloseSlice w/o matching OpenSlice');
49        return;
50      }
51      thread.endSlice(ts);
52    },
53
54    /**
55     * Parses maliDDK events and sets up state in the importer.
56     * events will come in pairs with a cros_trace_print_enter
57     * like this:
58     *
59     * tracing_mark_write: mali_driver: cros_trace_print_enter:
60     * gles/src/texture/mali_gles_texture_slave.c1505:
61     * gles2_texturep_upload_2d
62     *
63     * and a cros_trace_print_exit like this:
64     *
65     * tracing_mark_write: mali_driver: cros_trace_print_exit:
66     * gles/src/texture/mali_gles_texture_slave.c1505:
67     */
68    maliDDKEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
69      var maliEvent =
70          /^s*(\w+):\s*([\w\\\/.\-]*):?\s*(.*)$/.exec(eventBase[2]);
71      switch (maliEvent[1]) {
72        case 'cros_trace_print_enter':
73          this.maliDDKOpenSlice(pid, ts, maliEvent[3], maliEvent[2]);
74          break;
75        case 'cros_trace_print_exit':
76          this.maliDDKCloseSlice(pid, ts, [], maliEvent[2]);
77      }
78      return true;
79    },
80
81    /*
82     * Kernel event support.
83     */
84
85    dvfsSample: function(counterName, seriesName, ts, value) {
86      // NB: record all data on cpu 0; cpuNumber is not meaningful
87      var targetCpu = this.importer.getOrCreateCpuState(0);
88      var counter = targetCpu.cpu.getOrCreateCounter('', counterName);
89      if (counter.numSeries == 0) {
90        counter.seriesNames.push(seriesName);
91        counter.seriesColors.push(tracing.getStringColorId(counter.name));
92      }
93      counter.timestamps.push(ts);
94      counter.samples.push(value);
95    },
96
97    dvfsEventEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
98      var event = /utilization=(\d+)/.exec(eventBase[5]);
99      if (!event)
100        return false;
101
102      this.dvfsSample('DVFS Utilization', 'utilization', ts, event[1]);
103      return true;
104    },
105
106    dvfsSetClockEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
107      var event = /frequency=(\d+)/.exec(eventBase[5]);
108      if (!event)
109        return false;
110
111      this.dvfsSample('DVFS Frequency', 'frequency', ts, event[1]);
112      return true;
113    },
114
115    dvfsSetVoltageEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
116      var event = /voltage=(\d+)/.exec(eventBase[5]);
117      if (!event)
118        return false;
119
120      this.dvfsSample('DVFS Voltage', 'voltage', ts, event[1]);
121      return true;
122    }
123  };
124
125  LinuxPerfParser.registerSubtype(LinuxPerfMaliParser);
126
127  return {
128    LinuxPerfMaliParser: LinuxPerfMaliParser
129  };
130});
131