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