1#!/bin/sh 2# kernel lock contention analysis test 3# SPDX-License-Identifier: GPL-2.0 4 5set -e 6 7err=0 8perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) 9result=$(mktemp /tmp/__perf_test.result.XXXXX) 10 11cleanup() { 12 rm -f ${perfdata} 13 rm -f ${result} 14 trap - exit term int 15} 16 17trap_cleanup() { 18 cleanup 19 exit ${err} 20} 21trap trap_cleanup exit term int 22 23check() { 24 if [ `id -u` != 0 ]; then 25 echo "[Skip] No root permission" 26 err=2 27 exit 28 fi 29 30 if ! perf list | grep -q lock:contention_begin; then 31 echo "[Skip] No lock contention tracepoints" 32 err=2 33 exit 34 fi 35} 36 37test_record() 38{ 39 echo "Testing perf lock record and perf lock contention" 40 perf lock record -o ${perfdata} -- perf bench sched messaging > /dev/null 2>&1 41 # the output goes to the stderr and we expect only 1 output (-E 1) 42 perf lock contention -i ${perfdata} -E 1 -q 2> ${result} 43 if [ $(cat "${result}" | wc -l) != "1" ]; then 44 echo "[Fail] Recorded result count is not 1:" $(cat "${result}" | wc -l) 45 err=1 46 exit 47 fi 48} 49 50test_bpf() 51{ 52 echo "Testing perf lock contention --use-bpf" 53 54 if ! perf lock con -b true > /dev/null 2>&1 ; then 55 echo "[Skip] No BPF support" 56 return 57 fi 58 59 # the perf lock contention output goes to the stderr 60 perf lock con -a -b -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result} 61 if [ $(cat "${result}" | wc -l) != "1" ]; then 62 echo "[Fail] BPF result count is not 1:" $(cat "${result}" | wc -l) 63 err=1 64 exit 65 fi 66} 67 68test_record_concurrent() 69{ 70 echo "Testing perf lock record and perf lock contention at the same time" 71 perf lock record -o- -- perf bench sched messaging 2> /dev/null | \ 72 perf lock contention -i- -E 1 -q 2> ${result} 73 if [ $(cat "${result}" | wc -l) != "1" ]; then 74 echo "[Fail] Recorded result count is not 1:" $(cat "${result}" | wc -l) 75 err=1 76 exit 77 fi 78} 79 80test_aggr_task() 81{ 82 echo "Testing perf lock contention --threads" 83 perf lock contention -i ${perfdata} -t -E 1 -q 2> ${result} 84 if [ $(cat "${result}" | wc -l) != "1" ]; then 85 echo "[Fail] Recorded result count is not 1:" $(cat "${result}" | wc -l) 86 err=1 87 exit 88 fi 89 90 if ! perf lock con -b true > /dev/null 2>&1 ; then 91 return 92 fi 93 94 # the perf lock contention output goes to the stderr 95 perf lock con -a -b -t -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result} 96 if [ $(cat "${result}" | wc -l) != "1" ]; then 97 echo "[Fail] BPF result count is not 1:" $(cat "${result}" | wc -l) 98 err=1 99 exit 100 fi 101} 102 103test_aggr_addr() 104{ 105 echo "Testing perf lock contention --lock-addr" 106 perf lock contention -i ${perfdata} -l -E 1 -q 2> ${result} 107 if [ $(cat "${result}" | wc -l) != "1" ]; then 108 echo "[Fail] Recorded result count is not 1:" $(cat "${result}" | wc -l) 109 err=1 110 exit 111 fi 112 113 if ! perf lock con -b true > /dev/null 2>&1 ; then 114 return 115 fi 116 117 # the perf lock contention output goes to the stderr 118 perf lock con -a -b -l -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result} 119 if [ $(cat "${result}" | wc -l) != "1" ]; then 120 echo "[Fail] BPF result count is not 1:" $(cat "${result}" | wc -l) 121 err=1 122 exit 123 fi 124} 125 126test_type_filter() 127{ 128 echo "Testing perf lock contention --type-filter (w/ spinlock)" 129 perf lock contention -i ${perfdata} -Y spinlock -q 2> ${result} 130 if [ $(grep -c -v spinlock "${result}") != "0" ]; then 131 echo "[Fail] Recorded result should not have non-spinlocks:" $(cat "${result}") 132 err=1 133 exit 134 fi 135 136 if ! perf lock con -b true > /dev/null 2>&1 ; then 137 return 138 fi 139 140 perf lock con -a -b -Y spinlock -q -- perf bench sched messaging > /dev/null 2> ${result} 141 if [ $(grep -c -v spinlock "${result}") != "0" ]; then 142 echo "[Fail] BPF result should not have non-spinlocks:" $(cat "${result}") 143 err=1 144 exit 145 fi 146} 147 148test_lock_filter() 149{ 150 echo "Testing perf lock contention --lock-filter (w/ tasklist_lock)" 151 perf lock contention -i ${perfdata} -l -q 2> ${result} 152 if [ $(grep -c tasklist_lock "${result}") != "1" ]; then 153 echo "[Skip] Could not find 'tasklist_lock'" 154 return 155 fi 156 157 perf lock contention -i ${perfdata} -L tasklist_lock -q 2> ${result} 158 159 # find out the type of tasklist_lock 160 local type=$(head -1 "${result}" | awk '{ print $8 }' | sed -e 's/:.*//') 161 162 if [ $(grep -c -v "${type}" "${result}") != "0" ]; then 163 echo "[Fail] Recorded result should not have non-${type} locks:" $(cat "${result}") 164 err=1 165 exit 166 fi 167 168 if ! perf lock con -b true > /dev/null 2>&1 ; then 169 return 170 fi 171 172 perf lock con -a -b -L tasklist_lock -q -- perf bench sched messaging > /dev/null 2> ${result} 173 if [ $(grep -c -v "${type}" "${result}") != "0" ]; then 174 echo "[Fail] BPF result should not have non-${type} locks:" $(cat "${result}") 175 err=1 176 exit 177 fi 178} 179 180test_stack_filter() 181{ 182 echo "Testing perf lock contention --callstack-filter (w/ unix_stream)" 183 perf lock contention -i ${perfdata} -v -q 2> ${result} 184 if [ $(grep -c unix_stream "${result}") == "0" ]; then 185 echo "[Skip] Could not find 'unix_stream'" 186 return 187 fi 188 189 perf lock contention -i ${perfdata} -E 1 -S unix_stream -q 2> ${result} 190 if [ $(cat "${result}" | wc -l) != "1" ]; then 191 echo "[Fail] Recorded result should have a lock from unix_stream:" $(cat "${result}") 192 err=1 193 exit 194 fi 195 196 if ! perf lock con -b true > /dev/null 2>&1 ; then 197 return 198 fi 199 200 perf lock con -a -b -S unix_stream -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result} 201 if [ $(cat "${result}" | wc -l) != "1" ]; then 202 echo "[Fail] BPF result should have a lock from unix_stream:" $(cat "${result}") 203 err=1 204 exit 205 fi 206} 207 208test_aggr_task_stack_filter() 209{ 210 echo "Testing perf lock contention --callstack-filter with task aggregation" 211 perf lock contention -i ${perfdata} -v -q 2> ${result} 212 if [ $(grep -c unix_stream "${result}") == "0" ]; then 213 echo "[Skip] Could not find 'unix_stream'" 214 return 215 fi 216 217 perf lock contention -i ${perfdata} -t -E 1 -S unix_stream -q 2> ${result} 218 if [ $(cat "${result}" | wc -l) != "1" ]; then 219 echo "[Fail] Recorded result should have a task from unix_stream:" $(cat "${result}") 220 err=1 221 exit 222 fi 223 224 if ! perf lock con -b true > /dev/null 2>&1 ; then 225 return 226 fi 227 228 perf lock con -a -b -t -S unix_stream -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result} 229 if [ $(cat "${result}" | wc -l) != "1" ]; then 230 echo "[Fail] BPF result should have a task from unix_stream:" $(cat "${result}") 231 err=1 232 exit 233 fi 234} 235 236check 237 238test_record 239test_bpf 240test_record_concurrent 241test_aggr_task 242test_aggr_addr 243test_type_filter 244test_lock_filter 245test_stack_filter 246test_aggr_task_stack_filter 247 248exit ${err} 249