|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <err.h> |
|
#include <unistd.h> |
|
#include <stdbool.h> |
|
|
|
long const temp_high_mark = 80000; |
|
long const temp_low_mark = 76000; |
|
char const *const speed_throttle = "700000\n"; |
|
char const *const speed_max = "1500000\n"; |
|
|
|
long measure(FILE *f); |
|
void set_speed(FILE *f, char const *const speed, size_t n); |
|
|
|
long measure(FILE *f) |
|
{ |
|
static char *line = NULL; |
|
ssize_t n = 0; |
|
|
|
// Read a line |
|
n = getline(&line, (size_t *)&n, f); |
|
if (n == -1) return -1; |
|
if (*line == '\0') return -2; |
|
|
|
// Rewind the stream and ignore input buffer (kernel gives |
|
// different response every read) |
|
rewind(f); |
|
if (fflush(f) == EOF) { |
|
err(3,"Unable to read temperature (seek)\n"); |
|
} |
|
|
|
// Convert to number |
|
char *endptr; |
|
long x = strtol(line, &endptr, 10); |
|
if (*endptr != '\n') return -2; |
|
return x; |
|
} |
|
|
|
void set_speed(FILE *f, char const *const speed, size_t n) |
|
{ |
|
size_t wrote = fwrite(speed, n, 1, f); |
|
if (wrote != 1) { |
|
err(3,"Unable to set speed\n"); |
|
} |
|
if (fflush(f) == EOF) { |
|
err(3,"Unable to set speed (seek)\n"); |
|
} |
|
} |
|
|
|
int main(int argc, char **argv) |
|
{ |
|
FILE *temp_f = fopen("/sys/class/thermal/thermal_zone0/temp", "r"); |
|
if (temp_f == NULL) { |
|
err(1, "Unable to open temperature file"); |
|
} |
|
FILE *speed_f = fopen("/sys/devices/system/cpu/cpufreq/policy0/scaling_max_freq", "w"); |
|
if (speed_f == NULL) { |
|
err(1, "Unable to open CPU speed file. Are your root?"); |
|
} |
|
|
|
bool throttling = true; |
|
set_speed(speed_f, speed_throttle, sizeof(speed_throttle)); |
|
|
|
while (true) { |
|
long temp = measure(temp_f); |
|
|
|
if (temp == -1) { |
|
err(1, "Unable to read temperature"); |
|
} else if (temp == -2) { |
|
errx(2, "Unable to convert temperature"); |
|
} |
|
|
|
if (throttling && temp < temp_low_mark) { |
|
throttling = false; |
|
set_speed(speed_f, speed_max, sizeof(speed_max)); |
|
printf("Max speed\n"); |
|
fflush(stdout); |
|
} else if (!throttling && temp > temp_high_mark) { |
|
throttling = true; |
|
set_speed(speed_f, speed_throttle, sizeof(speed_throttle)); |
|
printf("Throttling\n"); |
|
fflush(stdout); |
|
} |
|
sleep(2); |
|
} |
|
} |