Realtime CPU Throttling

  • Thread starter skip0110
  • 5 comments
  • 674 views
5,178
United States
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 :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 :D

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:
Shannon
Does it only work for Intel processors?
Only works for processors/motherborads that talk to the FreeBSD ACPI interface. I think other Unixes have the same interface, but I can't be sure.

Writing something to do the same thing on Windows would be way out of my leauge. Someone else had already written the drivers, my code just polls the CPU usage (in fuction readtimes) and adjusts the volatge (cpu.throttle_state) appropraitely.
 
Wow, I need a program like that. My case gets warm quickly doing intensive things and even when idling. But, I'm on Windows XP Home....
 
standard235
Wow, I need a program like that. My case gets warm quickly doing intensive things and even when idling. But, I'm on Windows XP Home....
Maybe this is what you need?

http://www.diefer.de/speedswitchxp/

(Thinks to self...I will have acess to a Windows machine by the end of the week and the source is availible....maybe I can hack the code to throttle the way I like :dopey: )
 
Back