- 5,178
- Worcester, MA
- skip0110
I just wrote a little C app that runs in the background monitoring my CPU load and adjusting CPU speed to maintain the lowest possible temp, using the ACPI interface.
CPU is slowed to about 1.3 Ghz when I'm typing or mostly idle but when I fire up an application all my 2.66 Ghz report...it's so cool
I can slow it all the way down to 333 Mhz but it usually idles around 667 Mhz.
I'm posting the code here because I used some obscure functions; probably none of the regulars to these forums would be interested but I'm sure someone would be; it took quite a bit of research to get it all working smoothly.
Anyways, here is the code, look at it, learn, or criticize, but please don't copy it all without giving credit
And a question as well, if anyone knows how to write a multithreaded Unix app in C please let me know how or link me to a tutorial. Thanks.
CPU is slowed to about 1.3 Ghz when I'm typing or mostly idle but when I fire up an application all my 2.66 Ghz report...it's so cool
I'm posting the code here because I used some obscure functions; probably none of the regulars to these forums would be interested but I'm sure someone would be; it took quite a bit of research to get it all working smoothly.
Anyways, here is the code, look at it, learn, or criticize, but please don't copy it all without giving credit
Code:
#include <sys/param.h>
#include <sys/sysctl.h>
/* These includes for CPUSTATES and CP_IDLE */
#if __FreeBSD_version < 500101
#include <sys/dkstat.h>
#else
#include <sys/resource.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MINSPEED 1
#define MAXSPEED 8
static int setcurfreq(int freq);
static int readtimes(long * idle, long * total);
static int readtimes(long * idle, long * total)
{
static long idle_old, total_old;
long cp_time[CPUSTATES];
size_t cp_time_len = sizeof(cp_time);
long total_new, i;
int error;
if ((error = sysctlbyname("kern.cp_time", (void *)cp_time,
&cp_time_len, NULL, 0)) != 0)
return error;
for (total_new = 0, i = 0; i < CPUSTATES; i++)
total_new += cp_time[i];
if (idle)
*idle = cp_time[CP_IDLE] - idle_old;
if (total)
*total = total_new - total_old;
idle_old = cp_time[CP_IDLE];
total_old = total_new;
return 0;
}
static int setcurfreq(int freq)
{
if (sysctlbyname("hw.acpi.cpu.throttle_state", NULL, NULL, &freq, sizeof(freq)))
return -1;
return 0;
}
int main(int argc, char * argv[])
{
int curspeed;
long idle, total;
size_t len;
len = sizeof(curspeed);
if (sysctlbyname("hw.acpi.cpu.throttle_state", &curspeed, &len, NULL, 0))
err(1, "Error reading current CPU frequency");
do {
usleep(1000000); /* Check status every 0.5 seconds */
if (readtimes(&idle, &total))
err(1, "readtimes");
printf("Speed = %i, Idle = %f\n", curspeed, ((float)idle)/((float)total));
if ((idle < (total/4)) && (curspeed<(MAXSPEED-1))) curspeed+=2;
else if ((idle < (total/3)) && (curspeed<MAXSPEED)) curspeed++;
if ((idle > (3*total/4)) && (curspeed>MINSPEED)) curspeed--;
if (setcurfreq(curspeed))
err(1, "Error setting CPU frequency");
} while(1);
/* NOT REACHED */
return 0;
}
And a question as well, if anyone knows how to write a multithreaded Unix app in C please let me know how or link me to a tutorial. Thanks.
Last edited: