homemade_speedstep/README.md

4.6 KiB

Homemade Speedstep

homemade_speedstep is a program I made while learning the C programming language to replace a python script I've been using to keep my old laptop from shutting down due to thermal overload.

If you're familiar with Intel's speedstep technology, this program attempts to imitate its behaviour, although in a much more crude way.

It is meant for GNU/Linux systems where thermal throttling is not working for whatever reason, leading to shutdowns from reaching critical temperatures.

License

This Free Software is licensed under the GNU Public License version 3.

Read the LICENSE file distributed alongside this source code for more information.

Requirements

The program requires running as root, as it needs permission to read and write from the /sys directory.

It also requires cpufreq support to be built into the kernel.

Building

Run make to compile the program, the binary will be placed in the bin directory.

You can run it from there or you can run make install to place it in the /usr/bin folder.

Run make install-openrc to install the program as an openrc service.

Run make debug to compile the program with debug symbols (only useful if you wish to debug it).

Run make clean to remove the compiled binary (note: only from bin, to remove from /usr/bin run rm /usr/bin/homemade_speedstep).

How it works

The program checks the available frequency steps supported by your CPU and uses them to set the maximum frequency your cpufreq governor may choose for it to run at.

Every n ammount of seconds, set by the user at build time, the program reads the temperature of the CPU and two thresholds, a minimum and maximum temperature you provide it with, to set this maximum frequency.

Any time the temperature hits the upper threshold, the maximum frequency will be lowered by one step, until the temperature is below the threshold or the minimum step is reached.

Likewise, any time the temperature reaches the minimum threshold, the maximum frequency will be raised a step, until the temperature is no longer below the threshold or the maximum step is reached.

If the temperature remains between the thresholds, the maximum frequency will remain unchanged.

This behaviour could lead to the CPU running at a lower frequency than necessary at times, like in a situation where the upper threshold was momentarily hit, but the temperature then reameindd between both thresholds from then onwwards.

Another unfortunate situation where the maximum frequency could unnecesarily remain below necessary would be when the lower thershold is reached and the temperature goes back up, but remains within both thresholds from then onwards.

This is overcome with a third check that keeps track of the last time the maximum frequency was changed, and if the temperature is below the average of both minimum and maximum threshold; if so, the maximum frequency will be raised by a step.

Important: this is not a complex algorithm to choose the frequency your CPU is running at at any given moment, that is the job of the CPU governor and out of scope of this program

Usage

You must provide the temperature at which you wish to step down the maximum frequency as first argument, and the temperature at which you wish to step up the maximum frequency as second argument; like so:

homemade_speedstep <max temp> <min temp>

Important: max temp and min temp must be passed as 5 digit integers, like so: 82ºC = 82000


Recomendation: add a service to your init script that runs this program at startup in the background so you don't need to keep a terminal emulator open running it.

Using OpenRC this would be done by adding the following in a /etc/init.d/homemade_speedstep file:

#!/sbin/openrc-run
name="homemade_speedstep"
description="crude imitation of intel's speedstep"
command=/usr/bin/homemade_speedstep
command_args="${HSMAXTEMP} ${HSMINTEMP}"
command_background=true
pidfile="/run/${RC_SVCNAME}.pid"
error_log=/var/log/homemade_speedstep.err

checkconfig() {
  if [ ${HSMAXTEMP} -lt 100000 ] && [ ${HSMINTEMP} -lt ${HSMAXTEMP} ] ; then
    return 0
  fi
}

start_pre() {
  # Prevent of double check
  if [ "${RC_CMD}" != "restart" ] ; then
    checkconfig || return $?
  fi
}

stop_pre() {
  if [ "${RC_CMD}" = "restart" ] ; then
    checkconfig || return $?
  fi
}

and the following in a /etc/conf.d/homemade_speedstep file:

# /etc/conf.d/homemade_speedstep: config gile for /etc/init.d/homemade_speedstep
# Change these to your liking
# Upper temperature threshold
HSMAXTEMP=82000
# Lower temperature threshold
HSMINTEMP=70000

and finally running rc-update add homemade_speedstep default