1 /* <lambda>null2 * Copyright 2017 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 18 19 import trebuchet.collections.SparseArray 20 import trebuchet.importers.ftrace.events.FtraceEvent 21 import trebuchet.model.InvalidId 22 import trebuchet.model.fragments.CpuModelFragment 23 import trebuchet.model.fragments.ModelFragment 24 import trebuchet.model.fragments.ProcessModelFragment 25 import trebuchet.model.fragments.ThreadModelFragment 26 27 class FtraceImporterState { 28 private val pidMap = SparseArray<ThreadModelFragment>(50) 29 private val cpuMap = SparseArray<CpuModelFragment>(6) 30 val modelFragment = ModelFragment() 31 32 fun finish(): ModelFragment { 33 return modelFragment 34 } 35 36 fun importEvent(event: FtraceEvent) { 37 if (modelFragment.globalStartTime == 0.0) { 38 modelFragment.globalStartTime = event.timestamp 39 } 40 modelFragment.globalEndTime = event.timestamp 41 event.import(this) 42 } 43 44 private fun createProcess(tgid: Int, name: String? = null): ThreadModelFragment { 45 val proc = ProcessModelFragment(tgid, name) 46 modelFragment.processes.add(proc) 47 val thread = proc.threadFor(tgid, name) 48 if (pidMap[tgid] != null) { 49 IllegalStateException("Unable to create process $tgid - already exists!") 50 } 51 pidMap.put(tgid, thread) 52 return thread 53 } 54 55 fun processFor(tgid: Int, name: String? = null): ProcessModelFragment { 56 val thread = pidMap[tgid] ?: createProcess(tgid, name) 57 thread.process.hint(tgid, name) 58 return thread.process 59 } 60 61 private fun createUnknownProcess(): ProcessModelFragment { 62 return ProcessModelFragment(InvalidId, hasIdCb = { process -> 63 val tgid = process.id 64 val existing = pidMap[tgid] 65 if (existing != null) { 66 existing.process.merge(process) 67 } else { 68 pidMap.put(tgid, process.threadFor(tgid, process.name)) 69 } 70 if (modelFragment.processes.none { it.id == process.id }) { 71 modelFragment.processes.add(process) 72 } 73 }) 74 } 75 76 fun threadFor(pid: Int, tgid: Int = InvalidId, task: String? = null): ThreadModelFragment { 77 var thread = pidMap[pid] 78 val processName = if (tgid == pid) task else null 79 if (thread != null) { 80 thread.hint(name = task, tgid = tgid, processName = processName) 81 return thread 82 } 83 val process = 84 if (tgid != InvalidId) processFor(tgid) 85 else createUnknownProcess() 86 thread = process.threadFor(pid, task) 87 thread.hint(processName = processName) 88 pidMap.put(pid, thread) 89 return thread 90 } 91 92 fun threadFor(line: FtraceLine) = threadFor(line.pid, line.tgid, line.task) 93 fun threadFor(event: FtraceEvent) = threadFor(event.pid, event.tgid, event.task) 94 95 fun cpuFor(cid: Int): CpuModelFragment { 96 var cpu = cpuMap[cid] 97 if (cpu == null) { 98 cpu = CpuModelFragment(cid) 99 modelFragment.cpus.add(cpu) 100 } 101 cpuMap.put(cid, cpu) 102 return cpuMap[cid]!! 103 } 104 }