1#!/bin/bash 2# SPDX-License-Identifier: GPL-2.0+ 3# 4# Alternate sleeping and spinning on randomly selected CPUs. The purpose 5# of this script is to inflict random OS jitter on a concurrently running 6# test. 7# 8# Usage: jitter.sh me duration [ sleepmax [ spinmax ] ] 9# 10# me: Random-number-generator seed salt. 11# duration: Time to run in seconds. 12# sleepmax: Maximum microseconds to sleep, defaults to one second. 13# spinmax: Maximum microseconds to spin, defaults to one millisecond. 14# 15# Copyright (C) IBM Corporation, 2016 16# 17# Authors: Paul E. McKenney <paulmck@linux.ibm.com> 18 19me=$(($1 * 1000)) 20duration=$2 21sleepmax=${3-1000000} 22spinmax=${4-1000} 23 24n=1 25 26starttime=`awk 'BEGIN { print systime(); }' < /dev/null` 27 28while : 29do 30 # Check for done. 31 t=`awk -v s=$starttime 'BEGIN { print systime() - s; }' < /dev/null` 32 if test "$t" -gt "$duration" 33 then 34 exit 0; 35 fi 36 37 # Set affinity to randomly selected online CPU 38 cpus=`grep 1 /sys/devices/system/cpu/*/online | 39 sed -e 's,/[^/]*$,,' -e 's/^[^0-9]*//'` 40 41 # Do not leave out poor old cpu0 which may not be hot-pluggable 42 if [ ! -f "/sys/devices/system/cpu/cpu0/online" ]; then 43 cpus="0 $cpus" 44 fi 45 46 cpumask=`awk -v cpus="$cpus" -v me=$me -v n=$n 'BEGIN { 47 srand(n + me + systime()); 48 ncpus = split(cpus, ca); 49 curcpu = ca[int(rand() * ncpus + 1)]; 50 mask = lshift(1, curcpu); 51 if (mask + 0 <= 0) 52 mask = 1; 53 printf("%#x\n", mask); 54 }' < /dev/null` 55 n=$(($n+1)) 56 if ! taskset -p $cpumask $$ > /dev/null 2>&1 57 then 58 echo taskset failure: '"taskset -p ' $cpumask $$ '"' 59 exit 1 60 fi 61 62 # Sleep a random duration 63 sleeptime=`awk -v me=$me -v n=$n -v sleepmax=$sleepmax 'BEGIN { 64 srand(n + me + systime()); 65 printf("%06d", int(rand() * sleepmax)); 66 }' < /dev/null` 67 n=$(($n+1)) 68 sleep .$sleeptime 69 70 # Spin a random duration 71 limit=`awk -v me=$me -v n=$n -v spinmax=$spinmax 'BEGIN { 72 srand(n + me + systime()); 73 printf("%06d", int(rand() * spinmax)); 74 }' < /dev/null` 75 n=$(($n+1)) 76 for i in {1..$limit} 77 do 78 echo > /dev/null 79 done 80done 81 82exit 1 83