1 /*
<lambda>null2 * Copyright 2018 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package trebuchet.importers.ftrace.events
18
19 import trebuchet.importers.ftrace.FtraceImporterState
20 import trebuchet.model.SchedulingState
21 import trebuchet.util.MatchResult
22 import trebuchet.util.PreviewReader
23
24 private fun PreviewReader.readSchedulingState(): SchedulingState {
25 val byte = readByte()
26 return when (byte) {
27 'S'.toByte() -> SchedulingState.SLEEPING
28 'R'.toByte() -> SchedulingState.RUNNABLE
29 'D'.toByte() -> {
30 if (peek() == '|'.toByte()) {
31 skip()
32 return when (readByte()) {
33 'K'.toByte() -> SchedulingState.UNINTR_SLEEP_WAKE_KILL
34 'W'.toByte() -> SchedulingState.UNINTR_SLEEP_WAKING
35 else -> SchedulingState.UNINTR_SLEEP
36 }
37 }
38 SchedulingState.UNINTR_SLEEP
39 }
40 'T'.toByte() -> SchedulingState.STOPPED
41 't'.toByte() -> SchedulingState.DEBUG
42 'Z'.toByte() -> SchedulingState.ZOMBIE
43 'X'.toByte() -> SchedulingState.EXIT_DEAD
44 'x'.toByte() -> SchedulingState.TASK_DEAD
45 'K'.toByte() -> SchedulingState.WAKE_KILL
46 'W'.toByte() -> SchedulingState.WAKING
47 else -> SchedulingState.UNKNOWN
48 }
49 }
50
<lambda>null51 private fun MatchResult.schedState(group: Int) = read(group) { readSchedulingState() }
52
53 class SchedSwitchEvent(val prevComm: String, val prevPid: Int, val prevPrio: Int,
54 val prevState: SchedulingState, val nextComm: String, val nextPid: Int,
55 val nextPrio: Int) : FtraceEventDetails {
importnull56 override fun import(event: FtraceEvent, state: FtraceImporterState) {
57 val prevThread = state.threadFor(prevPid, task = prevComm)
58 val nextThread = state.threadFor(nextPid, task = nextComm)
59 val cpu = state.cpuFor(event.cpu)
60
61 prevThread.schedulingStateBuilder.switchState(prevState, event.timestamp)
62 nextThread.schedulingStateBuilder.switchState(SchedulingState.RUNNING, event.timestamp)
63 cpu.schedulingProcessBuilder.switchProcess(nextThread.process, nextThread, event.timestamp)
64 }
65 }
66
67 class SchedWakeupEvent(val comm: String, val pid: Int, val prio: Int, val targetCpu: Int)
68 : FtraceEventDetails {
importnull69 override fun import(event: FtraceEvent, state: FtraceImporterState) {
70 val thread = state.threadFor(pid, task = comm)
71 thread.schedulingStateBuilder.switchState(SchedulingState.WAKING, event.timestamp)
72 }
73 }
74
75 object SchedEvent {
76 private const val SchedSwitchRE = "prev_comm=(.*) prev_pid=(\\d+) prev_prio=(\\d+) prev_state=([^\\s]+) ==> next_comm=(.*) next_pid=(\\d+) next_prio=(\\d+)"
77 private const val SchedWakeupRE = """comm=(.+) pid=(\d+) prio=(\d+)(?: success=\d+)? target_cpu=(\d+)"""
78
sharedStatenull79 val register: EventRegistryEntry = { sharedState ->
80 sharedState.onParseDetailsWithMatch("sched_switch", SchedSwitchRE) {
81 SchedSwitchEvent(string(1), int(2), int(3), schedState(4),
82 string(5), int(6), int(7))
83 }
84 sharedState.onParseDetailsWithMatch(arrayOf("sched_waking", "sched_wake"), SchedWakeupRE) {
85 SchedWakeupEvent(string(1), int(2), int(3), int(4))
86 }
87 }
88 }
89