diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2013-11-27 12:32:18 +0530 |
---|---|---|
committer | Viresh Kumar <viresh.kumar@linaro.org> | 2013-11-27 14:06:24 +0530 |
commit | 96107aec3553c7445e9130a977c5f6a90900cafb (patch) | |
tree | 1b6610b52204781f1f7d2a836c558b76b4fd3556 | |
parent | 5765e2f0c2c8f7aa0d1568b87a6ea258d606f5d8 (diff) |
NOHZ: Add is-cpu-isolated script
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rwxr-xr-x | is-cpu-isolated.sh | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/is-cpu-isolated.sh b/is-cpu-isolated.sh new file mode 100755 index 0000000..8a5772d --- /dev/null +++ b/is-cpu-isolated.sh @@ -0,0 +1,202 @@ +#!/bin/bash + +# Variable decided outcome of test, this is the minimum isolation we need. +MIN_ISOLATION=10 +RESULT="PASS" + +if [ $2 ]; then + MIN_ISOLATION=$2 +fi + +# $1 is the number of samples required of isolation time, by default 1 +if [ "$1" = "-h" -o "$1" = "--help" ]; then + echo "Usage: $0 <number of samples to take> <Min Isolation Time Expected>" + exit +elif [ $1 ]; then + sample_count=$1 +else + sample_count=1 +fi + + +# ROUTINES +debug_script=1 +isdebug() { + if [ $debug_script -eq 1 ]; then + $* + fi +} + +# routine to get tick count +get_tick_count() { cat /proc/interrupts | grep arch_timer | grep 30 | sed 's/\s\+/ /g' | cut -d' ' -f4 ; } +#For testing script on: x86 +#get_tick_count() { cat /proc/interrupts | grep NMI | sed 's/\s\+/ /g' | cut -d' ' -f4 ; } + +# routine to get CPU isolation time +get_isolation_duration() { + isdebug echo "" + isdebug echo "" + isdebug echo "Capture Isolation time" + isdebug echo "----------------------" + + isdebug echo "No. of samples requested:" $sample_count", min isolation required:" $MIN_ISOLATION + isdebug echo "" + + new_count=$(get_tick_count) + old_count=$new_count + + isdebug echo "initial count: " $old_count + + while [ $new_count -eq $old_count ] + do + new_count=$(get_tick_count) + done + + x=0 + while [ $x -lt $sample_count ] + do + let x=x+1 + + isdebug echo "count locked: " $new_count + + old_count=$new_count; + + # Get time as a UNIX timestamp (seconds elapsed since Jan 1, 1970 0:00 UTC) + T1="$(date +%s)" + + isdebug echo "Start Time in seconds: ${T1}" + + # sometimes there are continuous ticks, skip them. + sleep 1 + + while [ $new_count -eq $old_count ] + do + new_count=$(get_tick_count) + done + + isdebug echo "sampling over: " $new_count + + T2="$(date +%s)" + isdebug echo "End Time in seconds: ${T2}" + + T=$(($T2-$T1)) + isdebug echo "Time in seconds: " + echo $T + isdebug echo "" + + if [ $T -lt $MIN_ISOLATION -a $RESULT="PASS" ]; then + RESULT="FAIL" + fi + done + + isdebug echo "Result:" + echo $RESULT": "$MIN_ISOLATION + isdebug echo "" +} + +isolate_cpu1() { + isdebug echo "" + isdebug echo "Started Isolating CPUs - via CPUSETS" + isdebug echo "------------------------------------" + isdebug echo "" + + # Check that we have cpusets enabled in the kernel + if ! grep -q -s cpuset /proc/filesystems ; then + echo "Error: Kernel is lacking support for cpuset!" + exit 1 + fi + + # Try to disable sched_tick_max_deferment + if [ -d /sys/kernel/debug -a -f /sys/kernel/debug/sched_tick_max_deferment ]; then + echo -1 > /sys/kernel/debug/sched_tick_max_deferment + else + sysctl -e kernel.sched_tick_max_deferment=-1 + + fi + + # Below doesn't work + # sysctl -e kernel.sched_tick_max_deferment=-1 + + # make sure that the /dev/cpuset dir exits + # and mount the cpuset filesystem if needed + [ -d /dev/cpuset ] || mkdir /dev/cpuset + mount | grep /dev/cpuset > /dev/null || mount -t cpuset none /dev/cpuset + + # Create 2 cpusets. One GP and one NOHZ domain. + [ -d /dev/cpuset/gp ] || mkdir /dev/cpuset/gp + [ -d /dev/cpuset/rt ] || mkdir /dev/cpuset/rt + + # Setup the GP domain: CPU0 + echo 0 > /dev/cpuset/gp/mems + echo 0 > /dev/cpuset/gp/cpus + + # Setup the NOHZ domain: CPU1 + echo 0 > /dev/cpuset/rt/mems + echo 1 > /dev/cpuset/rt/cpus + + # Try to move all processes in top set to the GP set. + for pid in `cat /dev/cpuset/tasks`; do + if [ -d /proc/$pid ]; then + echo $pid > /dev/cpuset/gp/tasks 2>/dev/null + if [ $? != 0 ]; then + isdebug echo -n "Cannot move PID $pid: " + isdebug echo "$(cat /proc/$pid/status | grep ^Name | cut -f2)" + fi + fi + done + + # Disable load balancing on top level (otherwise the child-sets' setting + # won't take effect.) + echo 0 > /dev/cpuset/sched_load_balance + + # Enable load balancing withing the GP domain + echo 1 > /dev/cpuset/gp/sched_load_balance + + # But disallow load balancing within the NOHZ domain + echo 0 > /dev/cpuset/rt/sched_load_balance + + # Allow maximum tick deferment + #echo -1 > /sys/kernel/debug/sched_tick_max_deferment + + # Start a single threaded task on CPU1 or RT group + echo $$ > /dev/cpuset/rt/tasks + stress -q --cpu 1 --timeout 2000 & + echo $$ > /dev/cpuset/gp/tasks +} + +clear_cpusets() { + isdebug echo "" + isdebug echo "Started cleaning CPUSETS" + isdebug echo "------------------------" + isdebug echo "" + + # + # Cleanup + # + + # kill all instances of stress + for i in `ps | grep stress | sed 's/^\ *//g' | cut -d' ' -f1`; + do + kill -9 $i; + done + + # Try to move all from GP back to root + for pid in `cat /dev/cpuset/gp/tasks`; do + if [ -d /proc/$pid ]; then + echo $pid > /dev/cpuset/tasks 2>/dev/null + if [ $? != 0 ]; then + isdebug echo -n "Cannot move PID $pid: " + isdebug echo "$(cat /proc/$pid/status | grep ^Name | cut -f2)" + fi + fi + done + + # Remove the CPUsets + rmdir /dev/cpuset/gp + rmdir /dev/cpuset/rt +} + +# tests to run +isolate_cpu1 +get_isolation_duration +clear_cpusets |