simplified changespeed function, modified README and removed DOS format from README
This commit is contained in:
parent
fab416fbb4
commit
3328ec3204
176
README.md
176
README.md
|
@ -1,84 +1,92 @@
|
||||||
# Homemade Speedstep
|
# Homemade Speedstep
|
||||||
homemade_speedstep is a program I made while learning the C programming language to replace an old python script I've been using to keep my old laptop from shutting down due to thermal overload.
|
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.
|
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.
|
It is meant for GNU/Linux systems where thermal throttling is not working for whatever reason, leading to shutdowns from reaching critical temperatures.
|
||||||
## License
|
## License
|
||||||
This Free Software is licensed under the **GNU Public License version 3**.
|
This Free Software is licensed under the **GNU Public License version 3**.
|
||||||
|
|
||||||
Read the **LICENSE** file distributed alongside this source code for more information.
|
Read the **LICENSE** file distributed alongside this source code for more information.
|
||||||
## Requirements
|
## Requirements
|
||||||
The program requires running as root, as it needs permission to read and write from the `/sys` directory.
|
The program requires running as root, as it needs permission to read and write from the `/sys` directory.
|
||||||
|
|
||||||
It also requires support for the cpufreq 'userspace' governor built into the kernel.
|
It also requires cpufreq support to be built into the kernel.
|
||||||
|
## Building
|
||||||
The 'userspace' governor must be the currently running one.
|
Run `make` to compile the program, the binary will be placed in the `bin` directory.
|
||||||
## 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.
|
||||||
|
|
||||||
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 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 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`).
|
||||||
|
|
||||||
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.
|
||||||
## How it works
|
|
||||||
The program checks the available frequencies that the CPU can run at and it will try to keep it at the maximum that your system can run at before reaching your upper temperature threshold.
|
Every second, 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.
|
||||||
|
|
||||||
If the temperature stays within the upper and lower bound, it will keep the current 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.
|
||||||
|
|
||||||
Upon reaching the upper threshold, it will step down the frequency by one step as defined by the available frequencies, down to the minimum frequency it can run at.
|
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.
|
||||||
|
|
||||||
Once the temperature goes back down and it reaches the minimum threshold, the program will step up the frequency until it reaches the maximum again.
|
If the temperature remains between the thresholds, the maximum frequency will remain unchanged.
|
||||||
## 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:
|
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.
|
||||||
|
|
||||||
`homemade_speedstep <max temp> <min temp>`
|
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.
|
||||||
|
|
||||||
**Important**: max temp and min temp must be passed as 5 digit integers, like so: 82ºC = 82000
|
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
|
||||||
**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.
|
## 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:
|
||||||
Using OpenRC this would be done by adding the following in a `/etc/init.d/homemade_speedstep` file:
|
|
||||||
```
|
`homemade_speedstep <max temp> <min temp>`
|
||||||
#!/sbin/openrc-run
|
|
||||||
name="homemade_speedstep"
|
**Important**: max temp and min temp must be passed as 5 digit integers, like so: 82ºC = 82000
|
||||||
description="crude imitation of intel's speedstep"
|
|
||||||
command=/usr/bin/homemade_speedstep
|
---
|
||||||
command_args="${HSMAXTEMP} ${HSMINTEMP}"
|
**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.
|
||||||
command_background=true
|
|
||||||
pidfile="/run/${RC_SVCNAME}.pid"
|
Using OpenRC this would be done by adding the following in a `/etc/init.d/homemade_speedstep` file:
|
||||||
|
```
|
||||||
checkconfig() {
|
#!/sbin/openrc-run
|
||||||
if [ ${HSMAXTEMP} -lt 100000 ] && [ ${HSMINTEMP} -lt ${HSMAXTEMP} ] ; then
|
name="homemade_speedstep"
|
||||||
return 0
|
description="crude imitation of intel's speedstep"
|
||||||
fi
|
command=/usr/bin/homemade_speedstep
|
||||||
}
|
command_args="${HSMAXTEMP} ${HSMINTEMP}"
|
||||||
|
command_background=true
|
||||||
start_pre() {
|
pidfile="/run/${RC_SVCNAME}.pid"
|
||||||
# Prevent of double check
|
|
||||||
if [ "${RC_CMD}" != "restart" ] ; then
|
checkconfig() {
|
||||||
checkconfig || return $?
|
if [ ${HSMAXTEMP} -lt 100000 ] && [ ${HSMINTEMP} -lt ${HSMAXTEMP} ] ; then
|
||||||
fi
|
return 0
|
||||||
}
|
fi
|
||||||
|
}
|
||||||
stop_pre() {
|
|
||||||
if [ "${RC_CMD}" = "restart" ] ; then
|
start_pre() {
|
||||||
checkconfig || return $?
|
# Prevent of double check
|
||||||
fi
|
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
|
stop_pre() {
|
||||||
# Change these to your liking
|
if [ "${RC_CMD}" = "restart" ] ; then
|
||||||
# Upper temperature threshold
|
checkconfig || return $?
|
||||||
HSMAXTEMP=82000
|
fi
|
||||||
# Lower temperature threshold
|
}
|
||||||
HSMINTEMP=70000
|
```
|
||||||
```
|
and the following in a `/etc/conf.d/homemade_speedstep` file:
|
||||||
and finally running `rc-update add homemade_speedstep default`
|
```
|
||||||
|
# /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`
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#define MAXSPDSUFFIX "/cpufreq/scaling_max_freq"
|
#define MAXSPDSUFFIX "/cpufreq/scaling_max_freq"
|
||||||
#define CURTEMPPATH "/sys/devices/virtual/thermal/thermal_zone0/temp"
|
#define CURTEMPPATH "/sys/devices/virtual/thermal/thermal_zone0/temp"
|
||||||
|
|
||||||
void changespeed(int threads, char** steps, int curstep){
|
void changespeed(int threads, char* step){
|
||||||
int i;
|
int i;
|
||||||
char filename[100];
|
char filename[100];
|
||||||
FILE* file;
|
FILE* file;
|
||||||
|
@ -18,7 +18,7 @@ void changespeed(int threads, char** steps, int curstep){
|
||||||
sprintf(filename, MAXSPDPREFIX"%d"MAXSPDSUFFIX, i);
|
sprintf(filename, MAXSPDPREFIX"%d"MAXSPDSUFFIX, i);
|
||||||
file = fopen(filename, "w");
|
file = fopen(filename, "w");
|
||||||
if (file != NULL){
|
if (file != NULL){
|
||||||
fprintf(file, "%s\n", steps[curstep]);
|
fprintf(file, "%s\n", step);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,6 +204,7 @@ int main(int argc, char** argv){
|
||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
int timepassed = 0;
|
int timepassed = 0;
|
||||||
|
int temperature;
|
||||||
FILE* curtempfile;
|
FILE* curtempfile;
|
||||||
/* from here onwards an infinite while loop should start */
|
/* from here onwards an infinite while loop should start */
|
||||||
while((curtempfile = fopen(CURTEMPPATH, "r")) != NULL){
|
while((curtempfile = fopen(CURTEMPPATH, "r")) != NULL){
|
||||||
|
@ -213,26 +214,26 @@ int main(int argc, char** argv){
|
||||||
char* char_temperature = malloc(sizeof(char) * 8);
|
char* char_temperature = malloc(sizeof(char) * 8);
|
||||||
getfilec(curtempfile, char_temperature);
|
getfilec(curtempfile, char_temperature);
|
||||||
newlinetonullbyte(char_temperature);
|
newlinetonullbyte(char_temperature);
|
||||||
int temperature = stringtoint(char_temperature, stringlength(char_temperature));
|
temperature = stringtoint(char_temperature, stringlength(char_temperature));
|
||||||
|
free(char_temperature);
|
||||||
/* check if current temp is higher than max and step down */
|
/* check if current temp is higher than max and step down */
|
||||||
if (temperature >= maxtemp && curstep < stepc - 1){
|
if (temperature >= maxtemp && curstep < stepc - 1){
|
||||||
curstep++;
|
curstep++;
|
||||||
changespeed(THREADS, steps, curstep);
|
changespeed(THREADS, steps[curstep]);
|
||||||
timepassed = 0;
|
timepassed = 0;
|
||||||
}
|
}
|
||||||
/* check if current temp is lower than min and step down */
|
/* check if current temp is lower than min and step down */
|
||||||
if (temperature <= mintemp && curstep > 0){
|
if (temperature <= mintemp && curstep > 0){
|
||||||
curstep--;
|
curstep--;
|
||||||
changespeed(THREADS, steps, curstep);
|
changespeed(THREADS, steps[curstep]);
|
||||||
timepassed = 0;
|
timepassed = 0;
|
||||||
}
|
}
|
||||||
/* check if a minute passed without step changes and temp is below minmax average */
|
/* check if a minute passed without step changes and temp is below minmax average */
|
||||||
if (timepassed > 60 && temperature <= (mintemp+maxtemp)/2 && curstep > 0){
|
if (timepassed > 60 && temperature <= (mintemp+maxtemp)/2 && curstep > 0){
|
||||||
curstep--;
|
curstep--;
|
||||||
changespeed(THREADS, steps, curstep);
|
changespeed(THREADS, steps[curstep]);
|
||||||
timepassed = 0;
|
timepassed = 0;
|
||||||
}
|
}
|
||||||
free(char_temperature);
|
|
||||||
fclose(curtempfile);
|
fclose(curtempfile);
|
||||||
sleep(POLLING_TIME);
|
sleep(POLLING_TIME);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue