| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- #!/bin/bash
- # SPDX-License-Identifier: GPL-2.0+
- #
- # Alternate sleeping and spinning on randomly selected CPUs. The purpose
- # of this script is to inflict random OS jitter on a concurrently running
- # test.
- #
- # Usage: jitter.sh me jittering-path duration [ sleepmax [ spinmax ] ]
- #
- # me: Random-number-generator seed salt.
- # duration: Time to run in seconds.
- # jittering-path: Path to file whose removal will stop this script.
- # sleepmax: Maximum microseconds to sleep, defaults to one second.
- # spinmax: Maximum microseconds to spin, defaults to one millisecond.
- #
- # Copyright (C) IBM Corporation, 2016
- #
- # Authors: Paul E. McKenney <paulmck@linux.ibm.com>
- me=$(($1 * 1000))
- jittering=$2
- duration=$3
- sleepmax=${4-1000000}
- spinmax=${5-1000}
- n=1
- starttime=`gawk 'BEGIN { print systime(); }' < /dev/null`
- nohotplugcpus=
- for i in /sys/devices/system/cpu/cpu[0-9]*
- do
- if test -f $i/online
- then
- :
- else
- curcpu=`echo $i | sed -e 's/^[^0-9]*//'`
- nohotplugcpus="$nohotplugcpus $curcpu"
- fi
- done
- # Uses global variables startsecs, startns, endsecs, endns, and limit.
- # Exit code is success for time not yet elapsed and failure otherwise.
- function timecheck {
- local done=`awk -v limit=$limit \
- -v startsecs=$startsecs \
- -v startns=$startns \
- -v endsecs=$endsecs \
- -v endns=$endns < /dev/null '
- BEGIN {
- delta = (endsecs - startsecs) * 1000 * 1000;
- delta += int((endns - startns) / 1000);
- print delta >= limit;
- }'`
- return $done
- }
- while :
- do
- # Check for done.
- t=`gawk -v s=$starttime 'BEGIN { print systime() - s; }' < /dev/null`
- if test "$t" -gt "$duration"
- then
- exit 0;
- fi
- # Check for stop request.
- if ! test -f "$jittering"
- then
- exit 1;
- fi
- # Set affinity to randomly selected online CPU
- if cpus=`grep 1 /sys/devices/system/cpu/*/online 2>&1 |
- sed -e 's,/[^/]*$,,' -e 's/^[^0-9]*//'`
- then
- :
- else
- cpus=
- fi
- # Do not leave out non-hot-pluggable CPUs
- cpus="$cpus $nohotplugcpus"
- cpumask=`awk -v cpus="$cpus" -v me=$me -v n=$n 'BEGIN {
- srand(n + me + systime());
- ncpus = split(cpus, ca);
- print ca[int(rand() * ncpus + 1)];
- }' < /dev/null`
- n=$(($n+1))
- if ! taskset -c -p $cpumask $$ > /dev/null 2>&1
- then
- echo taskset failure: '"taskset -c -p ' $cpumask $$ '"'
- exit 1
- fi
- # Sleep a random duration
- sleeptime=`awk -v me=$me -v n=$n -v sleepmax=$sleepmax 'BEGIN {
- srand(n + me + systime());
- printf("%06d", int(rand() * sleepmax));
- }' < /dev/null`
- n=$(($n+1))
- sleep .$sleeptime
- # Spin a random duration, but with rather coarse granularity.
- limit=`awk -v me=$me -v n=$n -v spinmax=$spinmax 'BEGIN {
- srand(n + me + systime());
- printf("%06d", int(rand() * spinmax));
- }' < /dev/null`
- n=$(($n+1))
- startsecs=`date +%s`
- startns=`date +%N`
- endsecs=$startns
- endns=$endns
- while timecheck
- do
- endsecs=`date +%s`
- endns=`date +%N`
- done
- done
- exit 1
|