162306a36Sopenharmony_ci#!/bin/bash
262306a36Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0+
362306a36Sopenharmony_ci#
462306a36Sopenharmony_ci# Alternate sleeping and spinning on randomly selected CPUs.  The purpose
562306a36Sopenharmony_ci# of this script is to inflict random OS jitter on a concurrently running
662306a36Sopenharmony_ci# test.
762306a36Sopenharmony_ci#
862306a36Sopenharmony_ci# Usage: jitter.sh me jittering-path duration [ sleepmax [ spinmax ] ]
962306a36Sopenharmony_ci#
1062306a36Sopenharmony_ci# me: Random-number-generator seed salt.
1162306a36Sopenharmony_ci# duration: Time to run in seconds.
1262306a36Sopenharmony_ci# jittering-path: Path to file whose removal will stop this script.
1362306a36Sopenharmony_ci# sleepmax: Maximum microseconds to sleep, defaults to one second.
1462306a36Sopenharmony_ci# spinmax: Maximum microseconds to spin, defaults to one millisecond.
1562306a36Sopenharmony_ci#
1662306a36Sopenharmony_ci# Copyright (C) IBM Corporation, 2016
1762306a36Sopenharmony_ci#
1862306a36Sopenharmony_ci# Authors: Paul E. McKenney <paulmck@linux.ibm.com>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cime=$(($1 * 1000))
2162306a36Sopenharmony_cijittering=$2
2262306a36Sopenharmony_ciduration=$3
2362306a36Sopenharmony_cisleepmax=${4-1000000}
2462306a36Sopenharmony_cispinmax=${5-1000}
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_cin=1
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistarttime=`gawk 'BEGIN { print systime(); }' < /dev/null`
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cinohotplugcpus=
3162306a36Sopenharmony_cifor i in /sys/devices/system/cpu/cpu[0-9]*
3262306a36Sopenharmony_cido
3362306a36Sopenharmony_ci	if test -f $i/online
3462306a36Sopenharmony_ci	then
3562306a36Sopenharmony_ci		:
3662306a36Sopenharmony_ci	else
3762306a36Sopenharmony_ci		curcpu=`echo $i | sed -e 's/^[^0-9]*//'`
3862306a36Sopenharmony_ci		nohotplugcpus="$nohotplugcpus $curcpu"
3962306a36Sopenharmony_ci	fi
4062306a36Sopenharmony_cidone
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ciwhile :
4362306a36Sopenharmony_cido
4462306a36Sopenharmony_ci	# Check for done.
4562306a36Sopenharmony_ci	t=`gawk -v s=$starttime 'BEGIN { print systime() - s; }' < /dev/null`
4662306a36Sopenharmony_ci	if test "$t" -gt "$duration"
4762306a36Sopenharmony_ci	then
4862306a36Sopenharmony_ci		exit 0;
4962306a36Sopenharmony_ci	fi
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	# Check for stop request.
5262306a36Sopenharmony_ci	if ! test -f "$jittering"
5362306a36Sopenharmony_ci	then
5462306a36Sopenharmony_ci		exit 1;
5562306a36Sopenharmony_ci	fi
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	# Set affinity to randomly selected online CPU
5862306a36Sopenharmony_ci	if cpus=`grep 1 /sys/devices/system/cpu/*/online 2>&1 |
5962306a36Sopenharmony_ci		 sed -e 's,/[^/]*$,,' -e 's/^[^0-9]*//'`
6062306a36Sopenharmony_ci	then
6162306a36Sopenharmony_ci		:
6262306a36Sopenharmony_ci	else
6362306a36Sopenharmony_ci		cpus=
6462306a36Sopenharmony_ci	fi
6562306a36Sopenharmony_ci	# Do not leave out non-hot-pluggable CPUs
6662306a36Sopenharmony_ci	cpus="$cpus $nohotplugcpus"
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	cpumask=`awk -v cpus="$cpus" -v me=$me -v n=$n 'BEGIN {
6962306a36Sopenharmony_ci		srand(n + me + systime());
7062306a36Sopenharmony_ci		ncpus = split(cpus, ca);
7162306a36Sopenharmony_ci		print ca[int(rand() * ncpus + 1)];
7262306a36Sopenharmony_ci	}' < /dev/null`
7362306a36Sopenharmony_ci	n=$(($n+1))
7462306a36Sopenharmony_ci	if ! taskset -c -p $cpumask $$ > /dev/null 2>&1
7562306a36Sopenharmony_ci	then
7662306a36Sopenharmony_ci		echo taskset failure: '"taskset -c -p ' $cpumask $$ '"'
7762306a36Sopenharmony_ci		exit 1
7862306a36Sopenharmony_ci	fi
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	# Sleep a random duration
8162306a36Sopenharmony_ci	sleeptime=`awk -v me=$me -v n=$n -v sleepmax=$sleepmax 'BEGIN {
8262306a36Sopenharmony_ci		srand(n + me + systime());
8362306a36Sopenharmony_ci		printf("%06d", int(rand() * sleepmax));
8462306a36Sopenharmony_ci	}' < /dev/null`
8562306a36Sopenharmony_ci	n=$(($n+1))
8662306a36Sopenharmony_ci	sleep .$sleeptime
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	# Spin a random duration
8962306a36Sopenharmony_ci	limit=`awk -v me=$me -v n=$n -v spinmax=$spinmax 'BEGIN {
9062306a36Sopenharmony_ci		srand(n + me + systime());
9162306a36Sopenharmony_ci		printf("%06d", int(rand() * spinmax));
9262306a36Sopenharmony_ci	}' < /dev/null`
9362306a36Sopenharmony_ci	n=$(($n+1))
9462306a36Sopenharmony_ci	for i in {1..$limit}
9562306a36Sopenharmony_ci	do
9662306a36Sopenharmony_ci		echo > /dev/null
9762306a36Sopenharmony_ci	done
9862306a36Sopenharmony_cidone
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ciexit 1
101