File Index
Files and directories
Sign in
FILE

lock_contention.sh

File preview with syntax highlighting.

linux-6.19.14/tools/perf/tests/shell/lock_contention.sh BASH
  1#!/bin/bash
  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)
 10errout=$(mktemp /tmp/__perf_test.errout.XXXXX)
 11
 12cleanup() {
 13	rm -f ${perfdata}
 14	rm -f ${result}
 15	rm -f ${errout}
 16	trap - EXIT TERM INT ERR
 17}
 18
 19trap_cleanup() {
 20	if (( $? == 139 )); then #SIGSEGV
 21		err=1
 22	fi
 23	echo "Unexpected signal in ${FUNCNAME[1]}"
 24	cleanup
 25	exit ${err}
 26}
 27trap trap_cleanup EXIT TERM INT ERR
 28
 29check() {
 30	if [ "$(id -u)" != 0 ]; then
 31		echo "[Skip] No root permission"
 32		err=2
 33		exit
 34	fi
 35
 36	if ! perf list tracepoint | grep -q lock:contention_begin; then
 37		echo "[Skip] No lock contention tracepoints"
 38		err=2
 39		exit
 40	fi
 41
 42	# shellcheck disable=SC2046
 43	if [ `nproc` -lt 4 ]; then
 44		echo "[Skip] Low number of CPUs (`nproc`), lock event cannot be triggered certainly"
 45		err=2
 46		exit
 47	fi
 48}
 49
 50test_record()
 51{
 52	echo "Testing perf lock record and perf lock contention"
 53	perf lock record -o ${perfdata} -- perf bench sched messaging -p > /dev/null 2>&1
 54	# the output goes to the stderr and we expect only 1 output (-E 1)
 55	perf lock contention -i ${perfdata} -E 1 -q 2> ${result}
 56	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
 57		echo "[Fail] Recorded result count is not 1:" "$(cat "${result}" | wc -l)"
 58		err=1
 59		exit
 60	fi
 61}
 62
 63test_bpf()
 64{
 65	echo "Testing perf lock contention --use-bpf"
 66
 67	if ! perf lock con -b true > /dev/null 2>&1 ; then
 68		echo "[Skip] No BPF support"
 69		return
 70	fi
 71
 72	# the perf lock contention output goes to the stderr
 73	perf lock con -a -b -E 1 -q -- perf bench sched messaging -p > /dev/null 2> ${result}
 74	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
 75		echo "[Fail] BPF result count is not 1:" "$(cat "${result}" | wc -l)"
 76		err=1
 77		exit
 78	fi
 79}
 80
 81test_record_concurrent()
 82{
 83	echo "Testing perf lock record and perf lock contention at the same time"
 84	perf lock record -o- -- perf bench sched messaging -p 2> ${errout} | \
 85	perf lock contention -i- -E 1 -q 2> ${result}
 86	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
 87		echo "[Fail] Recorded result count is not 1:" "$(cat "${result}" | wc -l)"
 88		cat ${errout}
 89		cat ${result}
 90		err=1
 91		exit
 92	fi
 93}
 94
 95test_aggr_task()
 96{
 97	echo "Testing perf lock contention --threads"
 98	perf lock contention -i ${perfdata} -t -E 1 -q 2> ${result}
 99	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
100		echo "[Fail] Recorded result count is not 1:" "$(cat "${result}" | wc -l)"
101		err=1
102		exit
103	fi
104
105	if ! perf lock con -b true > /dev/null 2>&1 ; then
106		return
107	fi
108
109	# the perf lock contention output goes to the stderr
110	perf lock con -a -b -t -E 1 -q -- perf bench sched messaging -p > /dev/null 2> ${result}
111	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
112		echo "[Fail] BPF result count is not 1:" "$(cat "${result}" | wc -l)"
113		err=1
114		exit
115	fi
116}
117
118test_aggr_addr()
119{
120	echo "Testing perf lock contention --lock-addr"
121	perf lock contention -i ${perfdata} -l -E 1 -q 2> ${result}
122	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
123		echo "[Fail] Recorded result count is not 1:" "$(cat "${result}" | wc -l)"
124		err=1
125		exit
126	fi
127
128	if ! perf lock con -b true > /dev/null 2>&1 ; then
129		return
130	fi
131
132	# the perf lock contention output goes to the stderr
133	perf lock con -a -b -l -E 1 -q -- perf bench sched messaging -p > /dev/null 2> ${result}
134	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
135		echo "[Fail] BPF result count is not 1:" "$(cat "${result}" | wc -l)"
136		err=1
137		exit
138	fi
139}
140
141test_aggr_cgroup()
142{
143	echo "Testing perf lock contention --lock-cgroup"
144
145	if ! perf lock con -b true > /dev/null 2>&1 ; then
146		echo "[Skip] No BPF support"
147		return
148	fi
149
150	# the perf lock contention output goes to the stderr
151	perf lock con -a -b --lock-cgroup -E 1 -q -- perf bench sched messaging -p > /dev/null 2> ${result}
152	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
153		echo "[Fail] BPF result count is not 1:" "$(cat "${result}" | wc -l)"
154		err=1
155		exit
156	fi
157}
158
159test_type_filter()
160{
161	echo "Testing perf lock contention --type-filter (w/ spinlock)"
162	perf lock contention -i ${perfdata} -Y spinlock -q 2> ${result}
163	if [ "$(grep -c -v spinlock "${result}")" != "0" ]; then
164		echo "[Fail] Recorded result should not have non-spinlocks:" "$(cat "${result}")"
165		err=1
166		exit
167	fi
168
169	if ! perf lock con -b true > /dev/null 2>&1 ; then
170		return
171	fi
172
173	perf lock con -a -b -Y spinlock -q -- perf bench sched messaging -p > /dev/null 2> ${result}
174	if [ "$(grep -c -v spinlock "${result}")" != "0" ]; then
175		echo "[Fail] BPF result should not have non-spinlocks:" "$(cat "${result}")"
176		err=1
177		exit
178	fi
179}
180
181test_lock_filter()
182{
183	echo "Testing perf lock contention --lock-filter (w/ tasklist_lock)"
184	perf lock contention -i ${perfdata} -l -q 2> ${result}
185	if [ "$(grep -c tasklist_lock "${result}")" != "1" ]; then
186		echo "[Skip] Could not find 'tasklist_lock'"
187		return
188	fi
189
190	perf lock contention -i ${perfdata} -L tasklist_lock -q 2> ${result}
191
192	# find out the type of tasklist_lock
193	test_lock_filter_type=$(head -1 "${result}" | awk '{ print $8 }' | sed -e 's/:.*//')
194
195	if [ "$(grep -c -v "${test_lock_filter_type}" "${result}")" != "0" ]; then
196		echo "[Fail] Recorded result should not have non-${test_lock_filter_type} locks:" "$(cat "${result}")"
197		err=1
198		exit
199	fi
200
201	if ! perf lock con -b true > /dev/null 2>&1 ; then
202		return
203	fi
204
205	perf lock con -a -b -L tasklist_lock -q -- perf bench sched messaging -p > /dev/null 2> ${result}
206	if [ "$(grep -c -v "${test_lock_filter_type}" "${result}")" != "0" ]; then
207		echo "[Fail] BPF result should not have non-${test_lock_filter_type} locks:" "$(cat "${result}")"
208		err=1
209		exit
210	fi
211}
212
213test_stack_filter()
214{
215	echo "Testing perf lock contention --callstack-filter (w/ unix_stream)"
216	perf lock contention -i ${perfdata} -v -q 2> ${result}
217	if [ "$(grep -c unix_stream "${result}")" = "0" ]; then
218		echo "[Skip] Could not find 'unix_stream'"
219		return
220	fi
221
222	perf lock contention -i ${perfdata} -E 1 -S unix_stream -q 2> ${result}
223	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
224		echo "[Fail] Recorded result should have a lock from unix_stream:" "$(cat "${result}")"
225		err=1
226		exit
227	fi
228
229	if ! perf lock con -b true > /dev/null 2>&1 ; then
230		return
231	fi
232
233	perf lock con -a -b -S unix_stream -E 1 -q -- perf bench sched messaging -p > /dev/null 2> ${result}
234	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
235		echo "[Fail] BPF result should have a lock from unix_stream:" "$(cat "${result}")"
236		err=1
237		exit
238	fi
239}
240
241test_aggr_task_stack_filter()
242{
243	echo "Testing perf lock contention --callstack-filter with task aggregation"
244	perf lock contention -i ${perfdata} -v -q 2> ${result}
245	if [ "$(grep -c unix_stream "${result}")" = "0" ]; then
246		echo "[Skip] Could not find 'unix_stream'"
247		return
248	fi
249
250	perf lock contention -i ${perfdata} -t -E 1 -S unix_stream -q 2> ${result}
251	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
252		echo "[Fail] Recorded result should have a task from unix_stream:" "$(cat "${result}")"
253		err=1
254		exit
255	fi
256
257	if ! perf lock con -b true > /dev/null 2>&1 ; then
258		return
259	fi
260
261	perf lock con -a -b -t -S unix_stream -E 1 -q -- perf bench sched messaging -p > /dev/null 2> ${result}
262	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
263		echo "[Fail] BPF result should have a task from unix_stream:" "$(cat "${result}")"
264		err=1
265		exit
266	fi
267}
268test_cgroup_filter()
269{
270	echo "Testing perf lock contention --cgroup-filter"
271
272	if ! perf lock con -b true > /dev/null 2>&1 ; then
273		echo "[Skip] No BPF support"
274		return
275	fi
276
277	perf lock con -a -b --lock-cgroup -E 1 -F wait_total -q -- perf bench sched messaging -p > /dev/null 2> ${result}
278	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
279		echo "[Fail] BPF result should have a cgroup result:" "$(cat "${result}")"
280		err=1
281		exit
282	fi
283
284	cgroup=$(cat "${result}" | awk '{ print $3 }')
285	perf lock con -a -b --lock-cgroup -E 1 -G "${cgroup}" -q -- perf bench sched messaging -p > /dev/null 2> ${result}
286	if [ "$(cat "${result}" | wc -l)" != "1" ]; then
287		echo "[Fail] BPF result should have a result with cgroup filter:" "$(cat "${cgroup}")"
288		err=1
289		exit
290	fi
291}
292
293
294test_csv_output()
295{
296	echo "Testing perf lock contention CSV output"
297	perf lock contention -i ${perfdata} -E 1 -x , --output ${result}
298	# count the number of commas in the header
299	# it should have 5: contended, total-wait, max-wait, avg-wait, type, caller
300	header=$(grep "# output:" ${result} | tr -d -c , | wc -c)
301	if [ "${header}" != "5" ]; then
302		echo "[Fail] Recorded result does not have enough output columns: ${header} != 5"
303		err=1
304		exit
305	fi
306	# count the number of commas in the output
307	output=$(grep -v "^#" ${result} | tr -d -c , | wc -c)
308	if [ "${header}" != "${output}" ]; then
309		echo "[Fail] Recorded result does not match the number of commas: ${header} != ${output}"
310		err=1
311		exit
312	fi
313
314	if ! perf lock con -b true > /dev/null 2>&1 ; then
315		echo "[Skip] No BPF support"
316		return
317	fi
318
319	# the perf lock contention output goes to the stderr
320	perf lock con -a -b -E 1 -x , --output ${result} -- perf bench sched messaging -p > /dev/null 2>&1
321	output=$(grep -v "^#" ${result} | tr -d -c , | wc -c)
322	if [ "${header}" != "${output}" ]; then
323		echo "[Fail] BPF result does not match the number of commas: ${header} != ${output}"
324		err=1
325		exit
326	fi
327}
328
329check
330
331test_record
332test_bpf
333test_record_concurrent
334test_aggr_task
335test_aggr_addr
336test_aggr_cgroup
337test_type_filter
338test_lock_filter
339test_stack_filter
340test_aggr_task_stack_filter
341test_cgroup_filter
342test_csv_output
343
344cleanup
345exit ${err}
~/ Read-only file preview.