1#!/bin/bash 2# perf record offcpu profiling tests (exclusive) 3# SPDX-License-Identifier: GPL-2.0 4 5set -e 6 7err=0 8perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX) 9 10ts=$(printf "%u" $((~0 << 32))) # OFF_CPU_TIMESTAMP 11dummy_timestamp=${ts%???} # remove the last 3 digits to match perf script 12 13cleanup() { 14 rm -f ${perfdata} 15 rm -f ${perfdata}.old 16 trap - EXIT TERM INT 17} 18 19trap_cleanup() { 20 cleanup 21 exit 1 22} 23trap trap_cleanup EXIT TERM INT 24 25test_above_thresh="Threshold test (above threshold)" 26test_below_thresh="Threshold test (below threshold)" 27 28test_offcpu_priv() { 29 echo "Checking off-cpu privilege" 30 31 if [ "$(id -u)" != 0 ] 32 then 33 echo "off-cpu test [Skipped permission]" 34 err=2 35 return 36 fi 37 if perf version --build-options 2>&1 | grep HAVE_BPF_SKEL | grep -q OFF 38 then 39 echo "off-cpu test [Skipped missing BPF support]" 40 err=2 41 return 42 fi 43} 44 45test_offcpu_basic() { 46 echo "Basic off-cpu test" 47 48 if ! perf record --off-cpu -e dummy -o ${perfdata} sleep 1 2> /dev/null 49 then 50 echo "Basic off-cpu test [Failed record]" 51 err=1 52 return 53 fi 54 if ! perf evlist -i ${perfdata} | grep -q "offcpu-time" 55 then 56 echo "Basic off-cpu test [Failed no event]" 57 err=1 58 return 59 fi 60 if ! perf report -i ${perfdata} -q --percent-limit=90 | grep -E -q sleep 61 then 62 echo "Basic off-cpu test [Failed missing output]" 63 err=1 64 return 65 fi 66 echo "Basic off-cpu test [Success]" 67} 68 69test_offcpu_child() { 70 echo "Child task off-cpu test" 71 72 # perf bench sched messaging creates 400 processes 73 if ! perf record --off-cpu -e dummy -o ${perfdata} -- \ 74 perf bench sched messaging -g 10 > /dev/null 2>&1 75 then 76 echo "Child task off-cpu test [Failed record]" 77 err=1 78 return 79 fi 80 if ! perf evlist -i ${perfdata} | grep -q "offcpu-time" 81 then 82 echo "Child task off-cpu test [Failed no event]" 83 err=1 84 return 85 fi 86 # each process waits at least for poll, so it should be more than 400 events 87 if ! perf report -i ${perfdata} -s comm -q -n -t ';' --percent-limit=90 | \ 88 awk -F ";" '{ if (NF > 3 && int($3) < 400) exit 1; }' 89 then 90 echo "Child task off-cpu test [Failed invalid output]" 91 err=1 92 return 93 fi 94 echo "Child task off-cpu test [Success]" 95} 96 97# task blocks longer than the --off-cpu-thresh, perf should collect a direct sample 98test_offcpu_above_thresh() { 99 echo "${test_above_thresh}" 100 101 # collect direct off-cpu samples for tasks blocked for more than 999ms 102 if ! perf record -e dummy --off-cpu --off-cpu-thresh 999 -o ${perfdata} -- sleep 1 2> /dev/null 103 then 104 echo "${test_above_thresh} [Failed record]" 105 err=1 106 return 107 fi 108 # direct sample's timestamp should be lower than the dummy_timestamp of the at-the-end sample 109 # check if a direct sample exists 110 if ! perf script --time "0, ${dummy_timestamp}" -i ${perfdata} -F event | grep -q "offcpu-time" 111 then 112 echo "${test_above_thresh} [Failed missing direct samples]" 113 err=1 114 return 115 fi 116 # there should only be one direct sample, and its period should be higher than off-cpu-thresh 117 if ! perf script --time "0, ${dummy_timestamp}" -i ${perfdata} -F period | \ 118 awk '{ if (int($1) > 999000000) exit 0; else exit 1; }' 119 then 120 echo "${test_above_thresh} [Failed off-cpu time too short]" 121 err=1 122 return 123 fi 124 echo "${test_above_thresh} [Success]" 125} 126 127# task blocks shorter than the --off-cpu-thresh, perf should collect an at-the-end sample 128test_offcpu_below_thresh() { 129 echo "${test_below_thresh}" 130 131 # collect direct off-cpu samples for tasks blocked for more than 1.2s 132 if ! perf record -e dummy --off-cpu --off-cpu-thresh 1200 -o ${perfdata} -- sleep 1 2> /dev/null 133 then 134 echo "${test_below_thresh} [Failed record]" 135 err=1 136 return 137 fi 138 # see if there's an at-the-end sample 139 if ! perf script --time "${dummy_timestamp}," -i ${perfdata} -F event | grep -q 'offcpu-time' 140 then 141 echo "${test_below_thresh} [Failed at-the-end samples cannot be found]" 142 err=1 143 return 144 fi 145 # plus there shouldn't be any direct samples 146 if perf script --time "0, ${dummy_timestamp}" -i ${perfdata} -F event | grep -q 'offcpu-time' 147 then 148 echo "${test_below_thresh} [Failed direct samples are found when they shouldn't be]" 149 err=1 150 return 151 fi 152 echo "${test_below_thresh} [Success]" 153} 154 155test_offcpu_priv 156 157if [ $err = 0 ]; then 158 test_offcpu_basic 159fi 160 161if [ $err = 0 ]; then 162 test_offcpu_child 163fi 164 165if [ $err = 0 ]; then 166 test_offcpu_above_thresh 167fi 168 169if [ $err = 0 ]; then 170 test_offcpu_below_thresh 171fi 172 173cleanup 174exit $err 175