1 #!/bin/bash 2 # 3 # Alternate sleeping and spinning on randomly selected CPUs. The purpose 4 # of this script is to inflict random OS jitter on a concurrently running 5 # test. 6 # 7 # Usage: jitter.sh me duration [ sleepmax [ spinmax ] ] 8 # 9 # me: Random-number-generator seed salt. 10 # duration: Time to run in seconds. 11 # sleepmax: Maximum microseconds to sleep, defaults to one second. 12 # spinmax: Maximum microseconds to spin, defaults to one millisecond. 13 # 14 # This program is free software; you can redistribute it and/or modify 15 # it under the terms of the GNU General Public License as published by 16 # the Free Software Foundation; either version 2 of the License, or 17 # (at your option) any later version. 18 # 19 # This program is distributed in the hope that it will be useful, 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 # GNU General Public License for more details. 23 # 24 # You should have received a copy of the GNU General Public License 25 # along with this program; if not, you can access it online at 26 # http://www.gnu.org/licenses/gpl-2.0.html. 27 # 28 # Copyright (C) IBM Corporation, 2016 29 # 30 # Authors: Paul E. McKenney <paulmck (at] linux.vnet.ibm.com> 31 32 me=$(($1 * 1000)) 33 duration=$2 34 sleepmax=${3-1000000} 35 spinmax=${4-1000} 36 37 n=1 38 39 starttime=`awk 'BEGIN { print systime(); }' < /dev/null` 40 41 while : 42 do 43 # Check for done. 44 t=`awk -v s=$starttime 'BEGIN { print systime() - s; }' < /dev/null` 45 if test "$t" -gt "$duration" 46 then 47 exit 0; 48 fi 49 50 # Set affinity to randomly selected CPU 51 cpus=`ls /sys/devices/system/cpu/*/online | 52 sed -e 's,/[^/]*$,,' -e 's/^[^0-9]*//' | 53 grep -v '^0*$'` 54 cpumask=`awk -v cpus="$cpus" -v me=$me -v n=$n 'BEGIN { 55 srand(n + me + systime()); 56 ncpus = split(cpus, ca); 57 curcpu = ca[int(rand() * ncpus + 1)]; 58 mask = lshift(1, curcpu); 59 if (mask + 0 <= 0) 60 mask = 1; 61 printf("%#x\n", mask); 62 }' < /dev/null` 63 n=$(($n+1)) 64 if ! taskset -p $cpumask $$ > /dev/null 2>&1 65 then 66 echo taskset failure: '"taskset -p ' $cpumask $$ '"' 67 exit 1 68 fi 69 70 # Sleep a random duration 71 sleeptime=`awk -v me=$me -v n=$n -v sleepmax=$sleepmax 'BEGIN { 72 srand(n + me + systime()); 73 printf("%06d", int(rand() * sleepmax)); 74 }' < /dev/null` 75 n=$(($n+1)) 76 sleep .$sleeptime 77 78 # Spin a random duration 79 limit=`awk -v me=$me -v n=$n -v spinmax=$spinmax 'BEGIN { 80 srand(n + me + systime()); 81 printf("%06d", int(rand() * spinmax)); 82 }' < /dev/null` 83 n=$(($n+1)) 84 for i in {1..$limit} 85 do 86 echo > /dev/null 87 done 88 done 89 90 exit 1 91