1<!DOCTYPE html>
2<!--
3Copyright (c) 2012 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel="import" href="/tracing/extras/importer/linux_perf/parser.html">
9<link rel="import" href="/tracing/model/counter.html">
10
11<script>
12'use strict';
13
14/**
15 * @fileoverview Parses scheduler events in the Linux event trace format.
16 */
17tr.exportTo('tr.e.importer.linux_perf', function() {
18
19  var Parser = tr.e.importer.linux_perf.Parser;
20
21  /**
22   * Parses linux sched trace events.
23   * @constructor
24   */
25  function SchedParser(importer) {
26    Parser.call(this, importer);
27
28    importer.registerEventHandler('sched_switch',
29        SchedParser.prototype.schedSwitchEvent.bind(this));
30    importer.registerEventHandler('sched_wakeup',
31        SchedParser.prototype.schedWakeupEvent.bind(this));
32    importer.registerEventHandler('sched_blocked_reason',
33        SchedParser.prototype.schedBlockedEvent.bind(this));
34    importer.registerEventHandler('sched_cpu_hotplug',
35        SchedParser.prototype.schedCpuHotplugEvent.bind(this));
36  }
37
38  var TestExports = {};
39
40  // Matches the sched_switch record
41  var schedSwitchRE = new RegExp(
42      'prev_comm=(.+) prev_pid=(\\d+) prev_prio=(\\d+) ' +
43      'prev_state=(\\S\\+?|\\S\\|\\S) ==> ' +
44      'next_comm=(.+) next_pid=(\\d+) next_prio=(\\d+)');
45
46  // Matches sched_blocked_reason record
47  var schedBlockedRE = new RegExp('pid=(\\d+) iowait=(\\d) caller=(.+)');
48  TestExports.schedSwitchRE = schedSwitchRE;
49
50  // Matches the sched_wakeup record
51  var schedWakeupRE =
52      /comm=(.+) pid=(\d+) prio=(\d+) success=(\d+) target_cpu=(\d+)/;
53  TestExports.schedWakeupRE = schedWakeupRE;
54
55  SchedParser.prototype = {
56    __proto__: Parser.prototype,
57
58    /**
59     * Parses scheduler events and sets up state in the CPUs of the importer.
60     */
61    schedSwitchEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
62      var event = schedSwitchRE.exec(eventBase.details);
63      if (!event)
64        return false;
65
66      var prevState = event[4];
67      var nextComm = event[5];
68      var nextPid = parseInt(event[6]);
69      var nextPrio = parseInt(event[7]);
70
71      var nextThread = this.importer.threadsByLinuxPid[nextPid];
72      var nextName;
73      if (nextThread)
74        nextName = nextThread.userFriendlyName;
75      else
76        nextName = nextComm;
77
78      var cpu = this.importer.getOrCreateCpu(cpuNumber);
79      cpu.switchActiveThread(
80          ts,
81          {stateWhenDescheduled: prevState},
82          nextPid,
83          nextName,
84          {
85            comm: nextComm,
86            tid: nextPid,
87            prio: nextPrio
88          });
89
90      return true;
91    },
92
93    schedWakeupEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
94      var event = schedWakeupRE.exec(eventBase.details);
95      if (!event)
96        return false;
97
98      var fromPid = pid;
99      var comm = event[1];
100      var pid = parseInt(event[2]);
101      var prio = parseInt(event[3]);
102      this.importer.markPidRunnable(ts, pid, comm, prio, fromPid);
103      return true;
104    },
105
106    schedCpuHotplugEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
107      var event = /cpu (\d+) (.+) error=(\d+)/.exec(eventBase.details);
108      if (!event)
109        return false;
110
111      var cpuNumber = event[1];
112      var state = event[2];
113      var targetCpu = this.importer.getOrCreateCpu(cpuNumber);
114
115      var powerCounter = targetCpu.getOrCreateCounter('', 'Cpu Hotplug');
116      if (powerCounter.numSeries === 0) {
117        powerCounter.addSeries(new tr.model.CounterSeries('State',
118            tr.b.ColorScheme.getColorIdForGeneralPurposeString(
119                powerCounter.name + '.' + 'State')));
120      }
121      powerCounter.series.forEach(function(series) {
122        if (series.name == 'State')
123          series.addCounterSample(ts, state.localeCompare('offline') ? 0 : 1);
124      });
125      return true;
126    },
127
128    schedBlockedEvent: function(eventName, cpuNumber, pid, ts, eventBase) {
129      var event = schedBlockedRE.exec(eventBase.details);
130      if (!event)
131        return false;
132
133      var pid = parseInt(event[1]);
134      var iowait = parseInt(event[2]);
135      var caller = event[3];
136
137      this.importer.addPidBlockedReason(ts, pid, iowait, caller);
138      return true;
139    }
140  };
141
142  Parser.register(SchedParser);
143
144  return {
145    SchedParser: SchedParser,
146    _SchedParserTestExports: TestExports
147  };
148});
149</script>
150
151