Home | History | Annotate | Download | only in bin
      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