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 CPU 38 cpus=`ls /sys/devices/system/cpu/*/online | 39 sed -e 's,/[^/]*$,,' -e 's/^[^0-9]*//' | 40 grep -v '^0*$'` 41 cpumask=`awk -v cpus="$cpus" -v me=$me -v n=$n 'BEGIN { 42 srand(n + me + systime()); 43 ncpus = split(cpus, ca); 44 curcpu = ca[int(rand() * ncpus + 1)]; 45 mask = lshift(1, curcpu); 46 if (mask + 0 <= 0) 47 mask = 1; 48 printf("%#x\n", mask); 49 }' < /dev/null` 50 n=$(($n+1)) 51 if ! taskset -p $cpumask $$ > /dev/null 2>&1 52 then 53 echo taskset failure: '"taskset -p ' $cpumask $$ '"' 54 exit 1 55 fi 56 57 # Sleep a random duration 58 sleeptime=`awk -v me=$me -v n=$n -v sleepmax=$sleepmax 'BEGIN { 59 srand(n + me + systime()); 60 printf("%06d", int(rand() * sleepmax)); 61 }' < /dev/null` 62 n=$(($n+1)) 63 sleep .$sleeptime 64 65 # Spin a random duration 66 limit=`awk -v me=$me -v n=$n -v spinmax=$spinmax 'BEGIN { 67 srand(n + me + systime()); 68 printf("%06d", int(rand() * spinmax)); 69 }' < /dev/null` 70 n=$(($n+1)) 71 for i in {1..$limit} 72 do 73 echo > /dev/null 74 done 75done 76 77exit 1 78