jitter.sh 2.4 KB

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