1*6dbdd20aSAndroid Build Coastguard Worker// Copyright (C) 2021 The Android Open Source Project 2*6dbdd20aSAndroid Build Coastguard Worker// 3*6dbdd20aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*6dbdd20aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*6dbdd20aSAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*6dbdd20aSAndroid Build Coastguard Worker// 7*6dbdd20aSAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*6dbdd20aSAndroid Build Coastguard Worker// 9*6dbdd20aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*6dbdd20aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*6dbdd20aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*6dbdd20aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*6dbdd20aSAndroid Build Coastguard Worker// limitations under the License. 14*6dbdd20aSAndroid Build Coastguard Worker 15*6dbdd20aSAndroid Build Coastguard Workerimport {THREAD_STATE_TRACK_KIND} from '../../public/track_kinds'; 16*6dbdd20aSAndroid Build Coastguard Workerimport {Trace} from '../../public/trace'; 17*6dbdd20aSAndroid Build Coastguard Workerimport {PerfettoPlugin} from '../../public/plugin'; 18*6dbdd20aSAndroid Build Coastguard Workerimport {getThreadUriPrefix, getTrackName} from '../../public/utils'; 19*6dbdd20aSAndroid Build Coastguard Workerimport {NUM, NUM_NULL, STR_NULL} from '../../trace_processor/query_result'; 20*6dbdd20aSAndroid Build Coastguard Workerimport {ThreadStateTrack} from './thread_state_track'; 21*6dbdd20aSAndroid Build Coastguard Workerimport {removeFalsyValues} from '../../base/array_utils'; 22*6dbdd20aSAndroid Build Coastguard Workerimport {TrackNode} from '../../public/workspace'; 23*6dbdd20aSAndroid Build Coastguard Workerimport {ThreadStateSelectionAggregator} from './thread_state_selection_aggregator'; 24*6dbdd20aSAndroid Build Coastguard Workerimport ProcessThreadGroupsPlugin from '../dev.perfetto.ProcessThreadGroups'; 25*6dbdd20aSAndroid Build Coastguard Worker 26*6dbdd20aSAndroid Build Coastguard Workerfunction uriForThreadStateTrack(upid: number | null, utid: number): string { 27*6dbdd20aSAndroid Build Coastguard Worker return `${getThreadUriPrefix(upid, utid)}_state`; 28*6dbdd20aSAndroid Build Coastguard Worker} 29*6dbdd20aSAndroid Build Coastguard Worker 30*6dbdd20aSAndroid Build Coastguard Workerexport default class implements PerfettoPlugin { 31*6dbdd20aSAndroid Build Coastguard Worker static readonly id = 'dev.perfetto.ThreadState'; 32*6dbdd20aSAndroid Build Coastguard Worker static readonly dependencies = [ProcessThreadGroupsPlugin]; 33*6dbdd20aSAndroid Build Coastguard Worker 34*6dbdd20aSAndroid Build Coastguard Worker async onTraceLoad(ctx: Trace): Promise<void> { 35*6dbdd20aSAndroid Build Coastguard Worker const {engine} = ctx; 36*6dbdd20aSAndroid Build Coastguard Worker 37*6dbdd20aSAndroid Build Coastguard Worker ctx.selection.registerAreaSelectionAggregator( 38*6dbdd20aSAndroid Build Coastguard Worker new ThreadStateSelectionAggregator(), 39*6dbdd20aSAndroid Build Coastguard Worker ); 40*6dbdd20aSAndroid Build Coastguard Worker 41*6dbdd20aSAndroid Build Coastguard Worker const result = await engine.query(` 42*6dbdd20aSAndroid Build Coastguard Worker include perfetto module viz.threads; 43*6dbdd20aSAndroid Build Coastguard Worker include perfetto module viz.summary.threads; 44*6dbdd20aSAndroid Build Coastguard Worker 45*6dbdd20aSAndroid Build Coastguard Worker select 46*6dbdd20aSAndroid Build Coastguard Worker utid, 47*6dbdd20aSAndroid Build Coastguard Worker t.upid, 48*6dbdd20aSAndroid Build Coastguard Worker tid, 49*6dbdd20aSAndroid Build Coastguard Worker t.name as threadName, 50*6dbdd20aSAndroid Build Coastguard Worker is_main_thread as isMainThread, 51*6dbdd20aSAndroid Build Coastguard Worker is_kernel_thread as isKernelThread 52*6dbdd20aSAndroid Build Coastguard Worker from _threads_with_kernel_flag t 53*6dbdd20aSAndroid Build Coastguard Worker join _sched_summary using (utid) 54*6dbdd20aSAndroid Build Coastguard Worker `); 55*6dbdd20aSAndroid Build Coastguard Worker 56*6dbdd20aSAndroid Build Coastguard Worker const it = result.iter({ 57*6dbdd20aSAndroid Build Coastguard Worker utid: NUM, 58*6dbdd20aSAndroid Build Coastguard Worker upid: NUM_NULL, 59*6dbdd20aSAndroid Build Coastguard Worker tid: NUM_NULL, 60*6dbdd20aSAndroid Build Coastguard Worker threadName: STR_NULL, 61*6dbdd20aSAndroid Build Coastguard Worker isMainThread: NUM_NULL, 62*6dbdd20aSAndroid Build Coastguard Worker isKernelThread: NUM, 63*6dbdd20aSAndroid Build Coastguard Worker }); 64*6dbdd20aSAndroid Build Coastguard Worker for (; it.valid(); it.next()) { 65*6dbdd20aSAndroid Build Coastguard Worker const {utid, upid, tid, threadName, isMainThread, isKernelThread} = it; 66*6dbdd20aSAndroid Build Coastguard Worker const title = getTrackName({ 67*6dbdd20aSAndroid Build Coastguard Worker utid, 68*6dbdd20aSAndroid Build Coastguard Worker tid, 69*6dbdd20aSAndroid Build Coastguard Worker threadName, 70*6dbdd20aSAndroid Build Coastguard Worker kind: THREAD_STATE_TRACK_KIND, 71*6dbdd20aSAndroid Build Coastguard Worker }); 72*6dbdd20aSAndroid Build Coastguard Worker 73*6dbdd20aSAndroid Build Coastguard Worker const uri = uriForThreadStateTrack(upid, utid); 74*6dbdd20aSAndroid Build Coastguard Worker ctx.tracks.registerTrack({ 75*6dbdd20aSAndroid Build Coastguard Worker uri, 76*6dbdd20aSAndroid Build Coastguard Worker title, 77*6dbdd20aSAndroid Build Coastguard Worker tags: { 78*6dbdd20aSAndroid Build Coastguard Worker kind: THREAD_STATE_TRACK_KIND, 79*6dbdd20aSAndroid Build Coastguard Worker utid, 80*6dbdd20aSAndroid Build Coastguard Worker upid: upid ?? undefined, 81*6dbdd20aSAndroid Build Coastguard Worker ...(isKernelThread === 1 && {kernelThread: true}), 82*6dbdd20aSAndroid Build Coastguard Worker }, 83*6dbdd20aSAndroid Build Coastguard Worker chips: removeFalsyValues([ 84*6dbdd20aSAndroid Build Coastguard Worker isKernelThread === 0 && isMainThread === 1 && 'main thread', 85*6dbdd20aSAndroid Build Coastguard Worker ]), 86*6dbdd20aSAndroid Build Coastguard Worker track: new ThreadStateTrack(ctx, uri, utid), 87*6dbdd20aSAndroid Build Coastguard Worker }); 88*6dbdd20aSAndroid Build Coastguard Worker 89*6dbdd20aSAndroid Build Coastguard Worker const group = ctx.plugins 90*6dbdd20aSAndroid Build Coastguard Worker .getPlugin(ProcessThreadGroupsPlugin) 91*6dbdd20aSAndroid Build Coastguard Worker .getGroupForThread(utid); 92*6dbdd20aSAndroid Build Coastguard Worker const track = new TrackNode({uri, title, sortOrder: 10}); 93*6dbdd20aSAndroid Build Coastguard Worker group?.addChildInOrder(track); 94*6dbdd20aSAndroid Build Coastguard Worker } 95*6dbdd20aSAndroid Build Coastguard Worker 96*6dbdd20aSAndroid Build Coastguard Worker ctx.selection.registerSqlSelectionResolver({ 97*6dbdd20aSAndroid Build Coastguard Worker sqlTableName: 'thread_state', 98*6dbdd20aSAndroid Build Coastguard Worker callback: async (id: number) => { 99*6dbdd20aSAndroid Build Coastguard Worker const result = await ctx.engine.query(` 100*6dbdd20aSAndroid Build Coastguard Worker select 101*6dbdd20aSAndroid Build Coastguard Worker thread_state.utid, 102*6dbdd20aSAndroid Build Coastguard Worker thread.upid 103*6dbdd20aSAndroid Build Coastguard Worker from 104*6dbdd20aSAndroid Build Coastguard Worker thread_state 105*6dbdd20aSAndroid Build Coastguard Worker join thread on thread_state.utid = thread.id 106*6dbdd20aSAndroid Build Coastguard Worker where thread_state.id = ${id} 107*6dbdd20aSAndroid Build Coastguard Worker `); 108*6dbdd20aSAndroid Build Coastguard Worker 109*6dbdd20aSAndroid Build Coastguard Worker const {upid, utid} = result.firstRow({ 110*6dbdd20aSAndroid Build Coastguard Worker upid: NUM_NULL, 111*6dbdd20aSAndroid Build Coastguard Worker utid: NUM, 112*6dbdd20aSAndroid Build Coastguard Worker }); 113*6dbdd20aSAndroid Build Coastguard Worker 114*6dbdd20aSAndroid Build Coastguard Worker return { 115*6dbdd20aSAndroid Build Coastguard Worker eventId: id, 116*6dbdd20aSAndroid Build Coastguard Worker trackUri: uriForThreadStateTrack(upid, utid), 117*6dbdd20aSAndroid Build Coastguard Worker }; 118*6dbdd20aSAndroid Build Coastguard Worker }, 119*6dbdd20aSAndroid Build Coastguard Worker }); 120*6dbdd20aSAndroid Build Coastguard Worker } 121*6dbdd20aSAndroid Build Coastguard Worker} 122