summaryrefslogtreecommitdiff
path: root/tools/perf/tests/shell/record_offcpu.sh
blob: 21a22efe08f5acfbd657063cc77c4200995f1799 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/bin/sh
# perf record offcpu profiling tests (exclusive)
# SPDX-License-Identifier: GPL-2.0

set -e

err=0
perfdata=$(mktemp /tmp/__perf_test.perf.data.XXXXX)

ts=$(printf "%u" $((~0 << 32))) # OFF_CPU_TIMESTAMP
dummy_timestamp=${ts%???} # remove the last 3 digits to match perf script

cleanup() {
  rm -f ${perfdata}
  rm -f ${perfdata}.old
  trap - EXIT TERM INT
}

trap_cleanup() {
  cleanup
  exit 1
}
trap trap_cleanup EXIT TERM INT

test_above_thresh="Threshold test (above threshold)"
test_below_thresh="Threshold test (below threshold)"

test_offcpu_priv() {
  echo "Checking off-cpu privilege"

  if [ "$(id -u)" != 0 ]
  then
    echo "off-cpu test [Skipped permission]"
    err=2
    return
  fi
  if perf version --build-options 2>&1 | grep HAVE_BPF_SKEL | grep -q OFF
  then
    echo "off-cpu test [Skipped missing BPF support]"
    err=2
    return
  fi
}

test_offcpu_basic() {
  echo "Basic off-cpu test"

  if ! perf record --off-cpu -e dummy -o ${perfdata} sleep 1 2> /dev/null
  then
    echo "Basic off-cpu test [Failed record]"
    err=1
    return
  fi
  if ! perf evlist -i ${perfdata} | grep -q "offcpu-time"
  then
    echo "Basic off-cpu test [Failed no event]"
    err=1
    return
  fi
  if ! perf report -i ${perfdata} -q --percent-limit=90 | grep -E -q sleep
  then
    echo "Basic off-cpu test [Failed missing output]"
    err=1
    return
  fi
  echo "Basic off-cpu test [Success]"
}

test_offcpu_child() {
  echo "Child task off-cpu test"

  # perf bench sched messaging creates 400 processes
  if ! perf record --off-cpu -e dummy -o ${perfdata} -- \
    perf bench sched messaging -g 10 > /dev/null 2>&1
  then
    echo "Child task off-cpu test [Failed record]"
    err=1
    return
  fi
  if ! perf evlist -i ${perfdata} | grep -q "offcpu-time"
  then
    echo "Child task off-cpu test [Failed no event]"
    err=1
    return
  fi
  # each process waits at least for poll, so it should be more than 400 events
  if ! perf report -i ${perfdata} -s comm -q -n -t ';' --percent-limit=90 | \
    awk -F ";" '{ if (NF > 3 && int($3) < 400) exit 1; }'
  then
    echo "Child task off-cpu test [Failed invalid output]"
    err=1
    return
  fi
  echo "Child task off-cpu test [Success]"
}

# task blocks longer than the --off-cpu-thresh, perf should collect a direct sample
test_offcpu_above_thresh() {
  echo "${test_above_thresh}"

  # collect direct off-cpu samples for tasks blocked for more than 999ms
  if ! perf record -e dummy --off-cpu --off-cpu-thresh 999 -o ${perfdata} -- sleep 1 2> /dev/null
  then
    echo "${test_above_thresh} [Failed record]"
    err=1
    return
  fi
  # direct sample's timestamp should be lower than the dummy_timestamp of the at-the-end sample
  # check if a direct sample exists
  if ! perf script --time "0, ${dummy_timestamp}" -i ${perfdata} -F event | grep -q "offcpu-time"
  then
    echo "${test_above_thresh} [Failed missing direct samples]"
    err=1
    return
  fi
  # there should only be one direct sample, and its period should be higher than off-cpu-thresh
  if ! perf script --time "0, ${dummy_timestamp}" -i ${perfdata} -F period | \
       awk '{ if (int($1) > 999000000) exit 0; else exit 1; }'
  then
    echo "${test_above_thresh} [Failed off-cpu time too short]"
    err=1
    return
  fi
  echo "${test_above_thresh} [Success]"
}

# task blocks shorter than the --off-cpu-thresh, perf should collect an at-the-end sample
test_offcpu_below_thresh() {
  echo "${test_below_thresh}"

  # collect direct off-cpu samples for tasks blocked for more than 1.2s
  if ! perf record -e dummy --off-cpu --off-cpu-thresh 1200 -o ${perfdata} -- sleep 1 2> /dev/null
  then
    echo "${test_below_thresh} [Failed record]"
    err=1
    return
  fi
  # see if there's an at-the-end sample
  if ! perf script --time "${dummy_timestamp}," -i ${perfdata} -F event | grep -q 'offcpu-time'
  then
    echo "${test_below_thresh} [Failed at-the-end samples cannot be found]"
    err=1
    return
  fi
  # plus there shouldn't be any direct samples
  if perf script --time "0, ${dummy_timestamp}" -i ${perfdata} -F event | grep -q 'offcpu-time'
  then
    echo "${test_below_thresh} [Failed direct samples are found when they shouldn't be]"
    err=1
    return
  fi
  echo "${test_below_thresh} [Success]"
}

test_offcpu_priv

if [ $err = 0 ]; then
  test_offcpu_basic
fi

if [ $err = 0 ]; then
  test_offcpu_child
fi

if [ $err = 0 ]; then
  test_offcpu_above_thresh
fi

if [ $err = 0 ]; then
  test_offcpu_below_thresh
fi

cleanup
exit $err