1-- 2-- Copyright 2023 The Android Open Source Project 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-- Extracts the blocking thread from a slice name 18-- 19-- @arg slice_name STRING Name of slice 20-- @ret STRING Blocking thread 21SELECT 22 CREATE_FUNCTION( 23 'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_THREAD(slice_name STRING)', 24 'STRING', 25 ' 26 SELECT STR_SPLIT(STR_SPLIT($slice_name, "with owner ", 1), " (", 0) 27 ' 28); 29 30-- Extracts the blocking thread tid from a slice name 31-- 32-- @arg slice_name STRING Name of slice 33-- @ret INT Blocking thread tid 34SELECT 35 CREATE_FUNCTION( 36 'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_TID(slice_name STRING)', 37 'INT', 38 ' 39 SELECT CAST(STR_SPLIT(STR_SPLIT($slice_name, " (", 1), ")", 0) AS INT) 40 ' 41); 42 43-- Extracts the blocking method from a slice name 44-- 45-- @arg slice_name STRING Name of slice 46-- @ret STRING Blocking thread 47SELECT 48 CREATE_FUNCTION( 49 'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_METHOD(slice_name STRING)', 50 'STRING', 51 ' 52 SELECT STR_SPLIT(STR_SPLIT($slice_name, ") at ", 1), "(", 0) 53 || "(" 54 || STR_SPLIT(STR_SPLIT($slice_name, ") at ", 1), "(", 1) 55 ' 56); 57 58-- Extracts a shortened form of the blocking method name from a slice name. 59-- The shortened form discards the parameter and return 60-- types. 61-- 62-- @arg slice_name STRING Name of slice 63-- @ret STRING Blocking thread 64SELECT 65 CREATE_FUNCTION( 66 'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_SHORT_BLOCKING_METHOD(slice_name STRING)', 67 'STRING', 68 ' 69 SELECT 70 STR_SPLIT(STR_SPLIT(ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_METHOD($slice_name), " ", 1), "(", 0) 71 ' 72); 73 74-- Extracts the monitor contention blocked method from a slice name 75-- 76-- @arg slice_name STRING Name of slice 77-- @ret STRING Blocking thread 78SELECT 79 CREATE_FUNCTION( 80 'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKED_METHOD(slice_name STRING)', 81 'STRING', 82 ' 83 SELECT STR_SPLIT(STR_SPLIT($slice_name, "blocking from ", 1), "(", 0) 84 || "(" 85 || STR_SPLIT(STR_SPLIT($slice_name, "blocking from ", 1), "(", 1) 86 ' 87); 88 89-- Extracts a shortened form of the monitor contention blocked method name 90-- from a slice name. The shortened form discards the parameter and return 91-- types. 92-- 93-- @arg slice_name STRING Name of slice 94-- @ret STRING Blocking thread 95SELECT 96 CREATE_FUNCTION( 97 'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_SHORT_BLOCKED_METHOD(slice_name STRING)', 98 'STRING', 99 ' 100 SELECT 101 STR_SPLIT(STR_SPLIT(ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKED_METHOD($slice_name), " ", 1), "(", 0) 102 ' 103); 104 105-- Extracts the number of waiters on the monitor from a slice name 106-- 107-- @arg slice_name STRING Name of slice 108-- @ret INT Count of waiters on the lock 109SELECT 110 CREATE_FUNCTION( 111 'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_WAITER_COUNT(slice_name STRING)', 112 'INT', 113 ' 114 SELECT CAST(STR_SPLIT(STR_SPLIT($slice_name, "waiters=", 1), " ", 0) AS INT) 115 ' 116); 117 118-- Extracts the monitor contention blocking source location from a slice name 119-- 120-- @arg slice_name STRING Name of slice 121-- @ret STRING Blocking thread 122SELECT 123 CREATE_FUNCTION( 124 'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_SRC(slice_name STRING)', 125 'STRING', 126 ' 127 SELECT STR_SPLIT(STR_SPLIT($slice_name, ")(", 1), ")", 0) 128 ' 129); 130 131-- Extracts the monitor contention blocked source location from a slice name 132-- 133-- @arg slice_name STRING Name of slice 134-- @ret STRING Blocking thread 135SELECT 136 CREATE_FUNCTION( 137 'ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKED_SRC(slice_name STRING)', 138 'STRING', 139 ' 140 SELECT STR_SPLIT(STR_SPLIT($slice_name, ")(", 2), ")", 0) 141 ' 142); 143 144CREATE TABLE internal_broken_android_monitor_contention 145AS 146SELECT ancestor.parent_id AS id FROM slice 147 JOIN slice ancestor ON ancestor.id = slice.parent_id 148 WHERE ancestor.name LIKE 'Lock contention on a monitor lock%' 149 GROUP BY ancestor.id; 150 151-- Contains parsed monitor contention slices. 152-- 153-- @column blocking_method Name of the method holding the lock. 154-- @column blocked_methhod Name of the method trying to acquire the lock. 155-- @column short_blocking_method Blocking_method without arguments and return types. 156-- @column short_blocked_method Blocked_method without arguments and return types. 157-- @column blocking_src File location of blocking_method in form <filename:linenumber>. 158-- @column blocked_src File location of blocked_method in form <filename:linenumber>. 159-- @column waiter_count Zero indexed number of threads trying to acquire the lock. 160-- @column blocking_utid Utid of thread holding the lock. 161-- @column blocking_thread_name Thread name of thread holding the lock. 162-- @column upid Upid of process experiencing lock contention. 163-- @column process_name Process name of process experiencing lock contention. 164-- @column id Slice id of lock contention. 165-- @column ts Timestamp of lock contention start. 166-- @column dur Duration of lock contention. 167-- @column track_id Thread track id of blocked thread. 168-- @column is_blocked_main_thread Whether the blocked thread is the main thread. 169-- @column is_blocking_main_thread Whether the blocking thread is the main thread. 170-- @column binder_reply_id Slice id of binder reply slice if lock contention was part of a binder txn. 171-- @column binder_reply_ts Timestamp of binder reply slice if lock contention was part of a binder txn. 172-- @column binder_reply_tid Tid of binder reply slice if lock contention was part of a binder txn. 173CREATE TABLE android_monitor_contention 174AS 175SELECT 176 ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_METHOD(slice.name) AS blocking_method, 177 ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKED_METHOD(slice.name) AS blocked_method, 178 ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_SHORT_BLOCKING_METHOD(slice.name) AS short_blocking_method, 179 ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_SHORT_BLOCKED_METHOD(slice.name) AS short_blocked_method, 180 ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_SRC(slice.name) AS blocking_src, 181 ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKED_SRC(slice.name) AS blocked_src, 182 ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_WAITER_COUNT(slice.name) AS waiter_count, 183 thread.utid AS blocked_utid, 184 thread.name AS blocked_thread_name, 185 blocking_thread.utid AS blocking_utid, 186 ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_THREAD(slice.name) AS blocking_thread_name, 187 ANDROID_EXTRACT_ANDROID_MONITOR_CONTENTION_BLOCKING_TID(slice.name) AS blocking_tid, 188 thread.upid AS upid, 189 process.name AS process_name, 190 slice.id, 191 slice.ts, 192 slice.dur, 193 slice.track_id, 194 thread.is_main_thread AS is_blocked_thread_main, 195 thread.tid AS blocked_thread_tid, 196 blocking_thread.is_main_thread AS is_blocking_thread_main, 197 blocking_thread.tid AS blocking_thread_tid, 198 binder_reply.id AS binder_reply_id, 199 binder_reply.ts AS binder_reply_ts, 200 binder_reply_thread.tid AS binder_reply_tid, 201 process.pid 202FROM slice 203JOIN thread_track 204 ON thread_track.id = slice.track_id 205LEFT JOIN thread 206 USING (utid) 207LEFT JOIN process 208 USING (upid) 209LEFT JOIN internal_broken_android_monitor_contention ON internal_broken_android_monitor_contention.id = slice.id 210LEFT JOIN ANCESTOR_SLICE(slice.id) binder_reply ON binder_reply.name = 'binder reply' 211LEFT JOIN thread_track binder_reply_thread_track ON binder_reply.track_id = binder_reply_thread_track.id 212LEFT JOIN thread binder_reply_thread ON binder_reply_thread_track.utid = binder_reply_thread.utid 213JOIN thread blocking_thread ON blocking_thread.tid = blocking_tid AND blocking_thread.upid = thread.upid 214WHERE slice.name LIKE 'monitor contention%' 215 AND slice.dur != -1 216 AND internal_broken_android_monitor_contention.id IS NULL 217 AND short_blocking_method IS NOT NULL 218 AND short_blocked_method IS NOT NULL 219GROUP BY slice.id; 220 221-- Contains parsed monitor contention slices with the parent-child relationships. 222-- 223-- @column parent_id Id of slice blocking the blocking_thread. 224-- @column blocking_method Name of the method holding the lock. 225-- @column blocked_methhod Name of the method trying to acquire the lock. 226-- @column short_blocking_method Blocking_method without arguments and return types. 227-- @column short_blocked_method Blocked_method without arguments and return types. 228-- @column blocking_src File location of blocking_method in form <filename:linenumber>. 229-- @column blocked_src File location of blocked_method in form <filename:linenumber>. 230-- @column waiter_count Zero indexed number of threads trying to acquire the lock. 231-- @column blocking_utid Utid of thread holding the lock. 232-- @column blocking_thread_name Thread name of thread holding the lock. 233-- @column upid Upid of process experiencing lock contention. 234-- @column process_name Process name of process experiencing lock contention. 235-- @column id Slice id of lock contention. 236-- @column ts Timestamp of lock contention start. 237-- @column dur Duration of lock contention. 238-- @column track_id Thread track id of blocked thread. 239-- @column is_blocked_main_thread Whether the blocked thread is the main thread. 240-- @column is_blocking_main_thread Whether the blocking thread is the main thread. 241-- @column binder_reply_id Slice id of binder reply slice if lock contention was part of a binder txn. 242-- @column binder_reply_ts Timestamp of binder reply slice if lock contention was part of a binder txn. 243-- @column binder_reply_tid Tid of binder reply slice if lock contention was part of a binder txn. 244CREATE TABLE android_monitor_contention_chain 245AS 246SELECT parent.id AS parent_id, child.* FROM android_monitor_contention child 247LEFT JOIN android_monitor_contention parent ON child.blocked_utid = parent.blocking_utid 248 AND parent.ts BETWEEN child.ts AND child.ts + child.dur; 249 250CREATE VIEW internal_blocking_thread_state 251AS 252SELECT utid AS blocking_utid, ts, dur, state, blocked_function 253FROM thread_state; 254 255-- Contains the span join of the |android_monitor_contention_chain| with their 256-- blocking thread thread state. 257-- 258-- @column parent_id Id of slice blocking the blocking_thread. 259-- @column blocking_method Name of the method holding the lock. 260-- @column blocked_methhod Name of the method trying to acquire the lock. 261-- @column short_blocking_method Blocking_method without arguments and return types. 262-- @column short_blocked_method Blocked_method without arguments and return types. 263-- @column blocking_src File location of blocking_method in form <filename:linenumber>. 264-- @column blocked_src File location of blocked_method in form <filename:linenumber>. 265-- @column waiter_count Zero indexed number of threads trying to acquire the lock. 266-- @column blocking_utid Utid of thread holding the lock. 267-- @column blocking_thread_name Thread name of thread holding the lock. 268-- @column upid Upid of process experiencing lock contention. 269-- @column process_name Process name of process experiencing lock contention. 270-- @column id Slice id of lock contention. 271-- @column ts Timestamp of lock contention start. 272-- @column dur Duration of lock contention. 273-- @column track_id Thread track id of blocked thread. 274-- @column is_blocked_main_thread Whether the blocked thread is the main thread. 275-- @column is_blocking_main_thread Whether the blocking thread is the main thread. 276-- @column binder_reply_id Slice id of binder reply slice if lock contention was part of a binder txn. 277-- @column binder_reply_ts Timestamp of binder reply slice if lock contention was part of a binder txn. 278-- @column binder_reply_tid Tid of binder reply slice if lock contention was part of a binder txn. 279-- @column blocking_utid Utid of the blocking |thread_state|. 280-- @column ts Timestamp of the blocking |thread_state|. 281-- @column state Thread state of the blocking thread. 282-- @column blocked_function Blocked kernel function of the blocking thread. 283CREATE VIRTUAL TABLE android_monitor_contention_chain_thread_state 284USING 285 SPAN_JOIN(android_monitor_contention_chain PARTITIONED blocking_utid, 286 internal_blocking_thread_state PARTITIONED blocking_utid); 287 288-- Aggregated blocked_functions on the 'blocking thread', the thread holding the lock. 289-- This builds on the data from |android_monitor_contention_chain| and 290-- for each contention slice, it returns the aggregated sum of all the thread states on the 291-- blocking thread. 292-- 293-- @column id Slice id of the monitor contention. 294-- @column thread_state A |thread_state| that occurred in the blocking thread during the contention. 295-- @column thread_state_dur Total time the blocking thread spent in the |thread_state| during 296-- contention. 297-- @column thread_state_count Count of all times the blocking thread entered |thread_state| during 298-- the contention. 299CREATE VIEW android_monitor_contention_chain_thread_state_by_txn 300AS 301SELECT 302 id, 303 state AS thread_state, 304 SUM(dur) AS thread_state_dur, 305 COUNT(dur) AS thread_state_count 306FROM android_monitor_contention_chain_thread_state 307GROUP BY id, thread_state; 308 309-- Aggregated blocked_functions on the 'blocking thread', the thread holding the lock. 310-- This builds on the data from |android_monitor_contention_chain| and 311-- for each contention, it returns the aggregated sum of all the kernel 312-- blocked function durations on the blocking thread. 313-- 314-- @column id Slice id of the monitor contention. 315-- @column blocked_function Blocked kernel function in a thread state in the blocking thread during 316-- the contention. 317-- @column blocked_function_dur Total time the blocking thread spent in the |blocked_function| 318-- during the contention. 319-- @column blocked_function_count Count of all times the blocking thread executed the 320-- |blocked_function| during the contention. 321CREATE VIEW android_monitor_contention_chain_blocked_functions_by_txn 322AS 323SELECT 324 id, 325 blocked_function, 326 SUM(dur) AS blocked_function_dur, 327 COUNT(dur) AS blocked_function_count 328FROM android_monitor_contention_chain_thread_state 329WHERE blocked_function IS NOT NULL 330GROUP BY id, blocked_function; 331