1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this 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 */ 15 16import {BaseStruct} from "./BaseStruct.js"; 17import {Rect} from "../component/trace/timer-shaft/Rect.js"; 18 19const padding = 1; 20 21export class ThreadStruct extends BaseStruct { 22 static runningColor: string = "#467b3b"; 23 static rColor = "#a0b84d"; 24 static uninterruptibleSleepColor = "#f19d38"; 25 static sColor = "#FBFBFB"; 26 static hoverThreadStruct: ThreadStruct | undefined; 27 static selectThreadStruct: ThreadStruct | undefined; 28 static statusMap: any = { 29 "D": "Uninterruptible Sleep", 30 "S": "Sleeping", 31 "R": "Runnable", 32 "Running": "Running", 33 "R+": "Runnable (Preempted)", 34 "DK": "Uninterruptible Sleep + Wake Kill", 35 "I": "Task Dead", 36 "T": "Stopped", 37 "t": "Traced", 38 "X": "Exit (Dead)", 39 "Z": "Exit (Zombie)", 40 "K": "Wake Kill", 41 "W": "Waking", 42 "P": "Parked", 43 "N": "No Load" 44 } 45 hasSched: number | undefined; 46 pid: number | undefined; 47 processName: string | undefined; 48 threadName: string | undefined; 49 tid: number | undefined; 50 upid: number | undefined; 51 utid: number | undefined; 52 cpu: number | undefined; 53 dur: number | undefined; 54 end_ts: number | undefined; 55 id: number | undefined; 56 is_main_thread: number | undefined; 57 name: string | undefined; 58 startTime: number | undefined; 59 start_ts: number | undefined; 60 state: string | undefined; 61 type: string | undefined; 62 63 static draw(ctx: CanvasRenderingContext2D, data: ThreadStruct) { 64 if (data.frame) { 65 ctx.globalAlpha = 1 66 let stateText = data.state || ''; 67 if ("S" == data.state) { 68 ctx.fillStyle = ThreadStruct.sColor; 69 ctx.globalAlpha = 0.2; // transparency 70 ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) 71 ctx.globalAlpha = 1; // transparency 72 } else if ("R" == data.state) { 73 ctx.fillStyle = ThreadStruct.rColor; 74 ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) 75 ctx.fillStyle = "#fff"; 76 ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); 77 } else if ("D" == data.state) { 78 ctx.fillStyle = ThreadStruct.uninterruptibleSleepColor; 79 ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) 80 ctx.fillStyle = "#fff"; 81 ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); 82 } else if ("Running" == data.state) { 83 ctx.fillStyle = ThreadStruct.runningColor; 84 ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) 85 ctx.fillStyle = "#fff"; 86 ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); 87 } else { 88 ctx.fillStyle = ThreadStruct.rColor; 89 ctx.fillRect(data.frame.x, data.frame.y + padding, data.frame.width, data.frame.height - padding * 2) 90 ctx.fillStyle = "#fff"; 91 ThreadStruct.drawString(ctx, ThreadStruct.getEndState(data.state || ''), 2, data.frame); 92 } 93 if (ThreadStruct.selectThreadStruct && ThreadStruct.equals(ThreadStruct.selectThreadStruct, data) && ThreadStruct.selectThreadStruct.state != "S") { 94 ctx.strokeStyle = '#232c5d' 95 ctx.lineWidth = 2 96 ctx.strokeRect(data.frame.x, data.frame.y + padding, data.frame.width - 2, data.frame.height - padding * 2) 97 } 98 } 99 } 100 101 static drawString(ctx: CanvasRenderingContext2D, str: string, textPadding: number, frame: Rect) { 102 let textMetrics = ctx.measureText(str); 103 let charWidth = Math.round(textMetrics.width / str.length) 104 if (textMetrics.width < frame.width - textPadding * 2) { 105 let x2 = Math.floor(frame.width / 2 - textMetrics.width / 2 + frame.x + textPadding) 106 ctx.textBaseline = "middle" 107 ctx.fillText(str, x2, Math.floor(frame.y + frame.height / 2), frame.width - textPadding * 2) 108 return; 109 } 110 if (frame.width - textPadding * 2 > charWidth * 4) { 111 let chatNum = (frame.width - textPadding * 2) / charWidth; 112 let x1 = frame.x + textPadding 113 ctx.textBaseline = "middle" 114 ctx.fillText(str.substring(0, chatNum - 4) + '...', x1, Math.floor(frame.y + frame.height / 2), frame.width - textPadding * 2) 115 return; 116 } 117 } 118 119 static getEndState(state: string): string { 120 let statusMapElement = ThreadStruct.statusMap[state]; 121 if (statusMapElement) { 122 return statusMapElement 123 } else { 124 if ("" == statusMapElement || statusMapElement == null) { 125 return ""; 126 } 127 return "Unknown State"; 128 } 129 } 130 131 static equals(d1: ThreadStruct, d2: ThreadStruct): boolean { 132 if (d1 && d2 && d1.cpu == d2.cpu && 133 d1.tid == d2.tid && 134 d1.state == d2.state && 135 d1.startTime == d2.startTime && 136 d1.dur == d2.dur) { 137 return true; 138 } else { 139 return false; 140 } 141 } 142} 143