1// Copyright (C) 2019 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use size file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import * as m from 'mithril'; 16 17import {Actions} from '../common/actions'; 18import {timeToCode, toNs} from '../common/time'; 19 20import {globals} from './globals'; 21import {Panel, PanelSize} from './panel'; 22import {scrollToTrackAndTs} from './scroll_helper'; 23 24 25export class ThreadStatePanel extends Panel { 26 view() { 27 const threadState = globals.threadStateDetails; 28 if (threadState === undefined || threadState.utid === undefined || 29 threadState.ts === undefined || threadState.dur === undefined || 30 threadState.state === undefined) { 31 return m('.details-panel'); 32 } 33 const threadInfo = globals.threads.get(threadState.utid); 34 if (threadInfo) { 35 return m( 36 '.details-panel', 37 m('.details-panel-heading', m('h2', 'Thread State')), 38 m('.details-table', [m('table.half-width', [ 39 m('tr', 40 m('th', `Start time`), 41 m('td', `${timeToCode(threadState.ts)}`)), 42 m('tr', 43 m('th', `Duration`), 44 m( 45 'td', 46 `${timeToCode(threadState.dur)} `, 47 )), 48 m('tr', 49 m('th', `State`), 50 m('td', 51 this.getStateContent( 52 threadState.state, 53 threadState.cpu, 54 threadState.sliceId, 55 threadState.ts))), 56 m('tr', 57 m('th', `Process`), 58 m('td', `${threadInfo.procName} [${threadInfo.pid}]`)), 59 this.getBlockedFunctionContent(threadState.blockedFunction), 60 ])])); 61 } 62 return m('.details-panel'); 63 } 64 65 renderCanvas(_ctx: CanvasRenderingContext2D, _size: PanelSize) {} 66 67 // If it is the running state, we want to show which CPU and a button to 68 // go to the sched slice. Otherwise, just show the state. 69 getStateContent( 70 state: string, cpu: number|undefined, sliceId: number|undefined, 71 ts: number) { 72 if (sliceId === undefined || cpu === undefined) { 73 return [state]; 74 } 75 76 return [ 77 `${state} on CPU ${cpu}`, 78 m( 79 'i.material-icons.grey', 80 { 81 onclick: () => { 82 // TODO(hjd): Use trackId from TP. 83 let trackId; 84 for (const track of Object.values(globals.state.tracks)) { 85 if (track.kind === 'CpuSliceTrack' && 86 (track.config as {cpu: number}).cpu === cpu) { 87 trackId = track.id; 88 } 89 } 90 if (trackId) { 91 globals.makeSelection( 92 Actions.selectSlice({id: sliceId, trackId})); 93 scrollToTrackAndTs( 94 trackId, toNs(ts + globals.state.traceTime.startSec)); 95 } 96 }, 97 title: 'Go to CPU slice' 98 }, 99 'call_made') 100 ]; 101 } 102 103 getBlockedFunctionContent(blockedFunction: string|undefined) { 104 if (blockedFunction === undefined) { 105 return null; 106 } 107 return m('tr', m('th', `Blocked Function`), m('td', blockedFunction)); 108 } 109} 110