1# -*- tab-width: 4 -*- ;; Emacs 2# vi: set filetype=sh tabstop=8 shiftwidth=8 noexpandtab :: Vi/ViM 3############################################################ IDENT(1) 4# 5# $Title: dwatch(8) module for dtrace_lockstat(4) contention $ 6# $Copyright: 2026 Devin Teske. All rights reserved. $ 7# 8############################################################ DESCRIPTION 9# 10# Print kernel lock contention events reported by dtrace_lockstat(4), 11# naming the lock, the thread held-off by it, and for how long. Answers 12# "the system is slow -- where is it fighting over locks?" The default 13# profile watches block events (thread went off-CPU waiting); lock-spin 14# watches spin events instead. Contention shorter than a threshold is 15# suppressed (default 1 ms; tunable via DWATCH_LOCK_MS in the environment, 16# 0 to show everything). 17# 18############################################################ PROBE 19 20case "$PROFILE" in 21lock|lock-block) 22 : ${PROBE:=$( echo \ 23 lockstat:::adaptive-block, \ 24 lockstat:::lockmgr-block, \ 25 lockstat:::rw-block, \ 26 lockstat:::sx-block )} ;; 27lock-spin) 28 : ${PROBE:=$( echo \ 29 lockstat:::adaptive-spin, \ 30 lockstat:::rw-spin, \ 31 lockstat:::spin-spin, \ 32 lockstat:::sx-spin, \ 33 lockstat:::thread-spin )} ;; 34lock-adaptive) 35 : ${PROBE:=lockstat:::adaptive-block, lockstat:::adaptive-spin} ;; 36lock-lockmgr) 37 : ${PROBE:=lockstat:::lockmgr-block} ;; 38lock-rw) 39 : ${PROBE:=lockstat:::rw-block, lockstat:::rw-spin} ;; 40lock-sx) 41 : ${PROBE:=lockstat:::sx-block, lockstat:::sx-spin} ;; 42lock-thread) 43 : ${PROBE:=lockstat:::thread-spin} ;; 44*) 45 : ${PROBE:=lockstat:::${PROFILE#lock-}} 46esac 47 48############################################################ EVENT ACTION 49 50: ${DWATCH_LOCK_MS:=1} 51 52case "$DWATCH_LOCK_MS" in 53""|*[!0-9]*) die "DWATCH_LOCK_MS must be a number" ;; # NOTREACHED 54esac 55 56[ "$CUSTOM_TEST" ] || 57 EVENT_TEST="(int64_t)arg1 >= (int64_t)$DWATCH_LOCK_MS * 1000000" 58 59############################################################ ACTIONS 60 61exec 9<<EOF 62this string lock_class; 63this string lock_how; 64this string lock_name; 65this string lock_verb; 66 67/* 68 * Lock classes from sys/lock.h as-witnessed by dtrace_lockstat(4) 69 */ 70inline string lockstat_class[string name] = 71 name == "adaptive-block" ? "mtx" : 72 name == "adaptive-spin" ? "mtx" : 73 name == "lockmgr-block" ? "lockmgr" : 74 name == "rw-block" ? "rw" : 75 name == "rw-spin" ? "rw" : 76 name == "spin-spin" ? "spin mtx" : 77 name == "sx-block" ? "sx" : 78 name == "sx-spin" ? "sx" : 79 name == "thread-spin" ? "thread" : 80 name; 81 82inline string lockstat_verb[string name] = 83 name == "adaptive-block" ? "blocked" : 84 name == "lockmgr-block" ? "blocked" : 85 name == "rw-block" ? "blocked" : 86 name == "sx-block" ? "blocked" : 87 "spun"; 88 89$PROBE /* probe ID $ID */ 90{${TRACE:+ 91 printf("<$ID>"); 92} 93 /* 94 * struct lock_object * (first member of every kernel lock) 95 */ 96 this->lock_name = 97 stringof(((struct lock_object *)arg0)->lo_name); 98 this->lock_class = lockstat_class[probename]; 99 this->lock_verb = lockstat_verb[probename]; 100 this->lock_how = ""; 101} 102 103lockstat:::lockmgr-block, 104lockstat:::rw-block, 105lockstat:::sx-block /* probe ID $(( $ID + 1 )) */ 106{${TRACE:+ 107 printf("<$(( $ID + 1 ))>"); 108} 109 /* arg2 is 0 when acquiring as writer, 1 as reader */ 110 this->lock_how = arg2 == 0 ? " as writer" : " as reader"; 111} 112EOF 113ACTIONS=$( cat <&9 ) 114ID=$(( $ID + 2 )) 115 116############################################################ EVENT DETAILS 117 118if [ ! "$CUSTOM_DETAILS" ]; then 119exec 9<<EOF 120 /* 121 * Print lock contention details 122 */ 123 printf("%s %d.%03d ms on %s \"%s\"%s", 124 this->lock_verb, 125 (int64_t)arg1 / 1000000, 126 ((int64_t)arg1 % 1000000) / 1000, 127 this->lock_class, 128 this->lock_name, 129 this->lock_how); 130EOF 131EVENT_DETAILS=$( cat <&9 ) 132fi 133 134################################################################################ 135# END 136################################################################################ 137