#!/usr/bin/env bash # Cap the CPU clock, to see how the program copes with a CPU slowed to stay cool. # # sudo tools/thermal-sim/cap-cpu.sh 800 # every core at most 800 MHz # sudo tools/thermal-sim/cap-cpu.sh restore # back to what it was # # Writes scaling_max_freq on every core. The values found the first time are # kept in /run/fgc-cap-cpu.saved, so `restore` puts back the real ones however # many caps were set in between. A reboot also clears the cap. set -euo pipefail saved=/run/fgc-cap-cpu.saved cpus=(/sys/devices/system/cpu/cpu[0-9]*/cpufreq) usage() { echo "usage: $0 | restore" >&2; exit 2; } [[ $# -eq 1 ]] || usage [[ $EUID -eq 0 ]] || { echo "$0: needs root (sudo)" >&2; exit 1; } [[ -e ${cpus[0]}/scaling_max_freq ]] || { echo "$0: no cpufreq on this machine" >&2; exit 1; } if [[ $1 == restore ]]; then [[ -f $saved ]] || { echo "nothing to restore (no cap set since boot)"; exit 0; } while read -r dir khz; do echo "$khz" > "$dir/scaling_max_freq"; done < "$saved" rm -f "$saved" echo "CPU clock limits restored" exit 0 fi [[ $1 =~ ^[0-9]+$ ]] || usage khz=$(( $1 * 1000 )) if [[ ! -f $saved ]]; then for d in "${cpus[@]}"; do echo "$d $(cat "$d/scaling_max_freq")"; done > "$saved" fi for d in "${cpus[@]}"; do min=$(cat "$d/cpuinfo_min_freq") (( khz < min )) && { echo "$0: $1 MHz is under this CPU's minimum ($((min / 1000)) MHz)" >&2; exit 1; } echo "$khz" > "$d/scaling_max_freq" done echo "every core capped at $1 MHz ('$0 restore' to undo)"