337 lines · bash
1#!/bin/sh2# kernel lock contention analysis test3# SPDX-License-Identifier: GPL-2.04 5set -e6 7err=08perfdata=$(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 INT15}16 17trap_cleanup() {18 cleanup19 exit ${err}20}21trap trap_cleanup EXIT TERM INT22 23check() {24 if [ "$(id -u)" != 0 ]; then25 echo "[Skip] No root permission"26 err=227 exit28 fi29 30 if ! perf list | grep -q lock:contention_begin; then31 echo "[Skip] No lock contention tracepoints"32 err=233 exit34 fi35 36 # shellcheck disable=SC204637 if [ `nproc` -lt 4 ]; then38 echo "[Skip] Low number of CPUs (`nproc`), lock event cannot be triggered certainly"39 err=240 exit41 fi42}43 44test_record()45{46 echo "Testing perf lock record and perf lock contention"47 perf lock record -o ${perfdata} -- perf bench sched messaging > /dev/null 2>&148 # the output goes to the stderr and we expect only 1 output (-E 1)49 perf lock contention -i ${perfdata} -E 1 -q 2> ${result}50 if [ "$(cat "${result}" | wc -l)" != "1" ]; then51 echo "[Fail] Recorded result count is not 1:" "$(cat "${result}" | wc -l)"52 err=153 exit54 fi55}56 57test_bpf()58{59 echo "Testing perf lock contention --use-bpf"60 61 if ! perf lock con -b true > /dev/null 2>&1 ; then62 echo "[Skip] No BPF support"63 return64 fi65 66 # the perf lock contention output goes to the stderr67 perf lock con -a -b -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result}68 if [ "$(cat "${result}" | wc -l)" != "1" ]; then69 echo "[Fail] BPF result count is not 1:" "$(cat "${result}" | wc -l)"70 err=171 exit72 fi73}74 75test_record_concurrent()76{77 echo "Testing perf lock record and perf lock contention at the same time"78 perf lock record -o- -- perf bench sched messaging 2> /dev/null | \79 perf lock contention -i- -E 1 -q 2> ${result}80 if [ "$(cat "${result}" | wc -l)" != "1" ]; then81 echo "[Fail] Recorded result count is not 1:" "$(cat "${result}" | wc -l)"82 err=183 exit84 fi85}86 87test_aggr_task()88{89 echo "Testing perf lock contention --threads"90 perf lock contention -i ${perfdata} -t -E 1 -q 2> ${result}91 if [ "$(cat "${result}" | wc -l)" != "1" ]; then92 echo "[Fail] Recorded result count is not 1:" "$(cat "${result}" | wc -l)"93 err=194 exit95 fi96 97 if ! perf lock con -b true > /dev/null 2>&1 ; then98 return99 fi100 101 # the perf lock contention output goes to the stderr102 perf lock con -a -b -t -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result}103 if [ "$(cat "${result}" | wc -l)" != "1" ]; then104 echo "[Fail] BPF result count is not 1:" "$(cat "${result}" | wc -l)"105 err=1106 exit107 fi108}109 110test_aggr_addr()111{112 echo "Testing perf lock contention --lock-addr"113 perf lock contention -i ${perfdata} -l -E 1 -q 2> ${result}114 if [ "$(cat "${result}" | wc -l)" != "1" ]; then115 echo "[Fail] Recorded result count is not 1:" "$(cat "${result}" | wc -l)"116 err=1117 exit118 fi119 120 if ! perf lock con -b true > /dev/null 2>&1 ; then121 return122 fi123 124 # the perf lock contention output goes to the stderr125 perf lock con -a -b -l -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result}126 if [ "$(cat "${result}" | wc -l)" != "1" ]; then127 echo "[Fail] BPF result count is not 1:" "$(cat "${result}" | wc -l)"128 err=1129 exit130 fi131}132 133test_aggr_cgroup()134{135 echo "Testing perf lock contention --lock-cgroup"136 137 if ! perf lock con -b true > /dev/null 2>&1 ; then138 echo "[Skip] No BPF support"139 return140 fi141 142 # the perf lock contention output goes to the stderr143 perf lock con -a -b -g -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result}144 if [ "$(cat "${result}" | wc -l)" != "1" ]; then145 echo "[Fail] BPF result count is not 1:" "$(cat "${result}" | wc -l)"146 err=1147 exit148 fi149}150 151test_type_filter()152{153 echo "Testing perf lock contention --type-filter (w/ spinlock)"154 perf lock contention -i ${perfdata} -Y spinlock -q 2> ${result}155 if [ "$(grep -c -v spinlock "${result}")" != "0" ]; then156 echo "[Fail] Recorded result should not have non-spinlocks:" "$(cat "${result}")"157 err=1158 exit159 fi160 161 if ! perf lock con -b true > /dev/null 2>&1 ; then162 return163 fi164 165 perf lock con -a -b -Y spinlock -q -- perf bench sched messaging > /dev/null 2> ${result}166 if [ "$(grep -c -v spinlock "${result}")" != "0" ]; then167 echo "[Fail] BPF result should not have non-spinlocks:" "$(cat "${result}")"168 err=1169 exit170 fi171}172 173test_lock_filter()174{175 echo "Testing perf lock contention --lock-filter (w/ tasklist_lock)"176 perf lock contention -i ${perfdata} -l -q 2> ${result}177 if [ "$(grep -c tasklist_lock "${result}")" != "1" ]; then178 echo "[Skip] Could not find 'tasklist_lock'"179 return180 fi181 182 perf lock contention -i ${perfdata} -L tasklist_lock -q 2> ${result}183 184 # find out the type of tasklist_lock185 test_lock_filter_type=$(head -1 "${result}" | awk '{ print $8 }' | sed -e 's/:.*//')186 187 if [ "$(grep -c -v "${test_lock_filter_type}" "${result}")" != "0" ]; then188 echo "[Fail] Recorded result should not have non-${test_lock_filter_type} locks:" "$(cat "${result}")"189 err=1190 exit191 fi192 193 if ! perf lock con -b true > /dev/null 2>&1 ; then194 return195 fi196 197 perf lock con -a -b -L tasklist_lock -q -- perf bench sched messaging > /dev/null 2> ${result}198 if [ "$(grep -c -v "${test_lock_filter_type}" "${result}")" != "0" ]; then199 echo "[Fail] BPF result should not have non-${test_lock_filter_type} locks:" "$(cat "${result}")"200 err=1201 exit202 fi203}204 205test_stack_filter()206{207 echo "Testing perf lock contention --callstack-filter (w/ unix_stream)"208 perf lock contention -i ${perfdata} -v -q 2> ${result}209 if [ "$(grep -c unix_stream "${result}")" = "0" ]; then210 echo "[Skip] Could not find 'unix_stream'"211 return212 fi213 214 perf lock contention -i ${perfdata} -E 1 -S unix_stream -q 2> ${result}215 if [ "$(cat "${result}" | wc -l)" != "1" ]; then216 echo "[Fail] Recorded result should have a lock from unix_stream:" "$(cat "${result}")"217 err=1218 exit219 fi220 221 if ! perf lock con -b true > /dev/null 2>&1 ; then222 return223 fi224 225 perf lock con -a -b -S unix_stream -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result}226 if [ "$(cat "${result}" | wc -l)" != "1" ]; then227 echo "[Fail] BPF result should have a lock from unix_stream:" "$(cat "${result}")"228 err=1229 exit230 fi231}232 233test_aggr_task_stack_filter()234{235 echo "Testing perf lock contention --callstack-filter with task aggregation"236 perf lock contention -i ${perfdata} -v -q 2> ${result}237 if [ "$(grep -c unix_stream "${result}")" = "0" ]; then238 echo "[Skip] Could not find 'unix_stream'"239 return240 fi241 242 perf lock contention -i ${perfdata} -t -E 1 -S unix_stream -q 2> ${result}243 if [ "$(cat "${result}" | wc -l)" != "1" ]; then244 echo "[Fail] Recorded result should have a task from unix_stream:" "$(cat "${result}")"245 err=1246 exit247 fi248 249 if ! perf lock con -b true > /dev/null 2>&1 ; then250 return251 fi252 253 perf lock con -a -b -t -S unix_stream -E 1 -q -- perf bench sched messaging > /dev/null 2> ${result}254 if [ "$(cat "${result}" | wc -l)" != "1" ]; then255 echo "[Fail] BPF result should have a task from unix_stream:" "$(cat "${result}")"256 err=1257 exit258 fi259}260test_cgroup_filter()261{262 echo "Testing perf lock contention --cgroup-filter"263 264 if ! perf lock con -b true > /dev/null 2>&1 ; then265 echo "[Skip] No BPF support"266 return267 fi268 269 perf lock con -a -b -g -E 1 -F wait_total -q -- perf bench sched messaging > /dev/null 2> ${result}270 if [ "$(cat "${result}" | wc -l)" != "1" ]; then271 echo "[Fail] BPF result should have a cgroup result:" "$(cat "${result}")"272 err=1273 exit274 fi275 276 cgroup=$(cat "${result}" | awk '{ print $3 }')277 perf lock con -a -b -g -E 1 -G "${cgroup}" -q -- perf bench sched messaging > /dev/null 2> ${result}278 if [ "$(cat "${result}" | wc -l)" != "1" ]; then279 echo "[Fail] BPF result should have a result with cgroup filter:" "$(cat "${cgroup}")"280 err=1281 exit282 fi283}284 285 286test_csv_output()287{288 echo "Testing perf lock contention CSV output"289 perf lock contention -i ${perfdata} -E 1 -x , --output ${result}290 # count the number of commas in the header291 # it should have 5: contended, total-wait, max-wait, avg-wait, type, caller292 header=$(grep "# output:" ${result} | tr -d -c , | wc -c)293 if [ "${header}" != "5" ]; then294 echo "[Fail] Recorded result does not have enough output columns: ${header} != 5"295 err=1296 exit297 fi298 # count the number of commas in the output299 output=$(grep -v "^#" ${result} | tr -d -c , | wc -c)300 if [ "${header}" != "${output}" ]; then301 echo "[Fail] Recorded result does not match the number of commas: ${header} != ${output}"302 err=1303 exit304 fi305 306 if ! perf lock con -b true > /dev/null 2>&1 ; then307 echo "[Skip] No BPF support"308 return309 fi310 311 # the perf lock contention output goes to the stderr312 perf lock con -a -b -E 1 -x , --output ${result} -- perf bench sched messaging > /dev/null 2>&1313 output=$(grep -v "^#" ${result} | tr -d -c , | wc -c)314 if [ "${header}" != "${output}" ]; then315 echo "[Fail] BPF result does not match the number of commas: ${header} != ${output}"316 err=1317 exit318 fi319}320 321check322 323test_record324test_bpf325test_record_concurrent326test_aggr_task327test_aggr_addr328test_aggr_cgroup329test_type_filter330test_lock_filter331test_stack_filter332test_aggr_task_stack_filter333test_cgroup_filter334test_csv_output335 336exit ${err}337