eCS's ACPI does not currently have any way to automatically throttle the CPU when not needed. If running ACPI you either run at full or you can manually use setgetthrtl.exe but this is mostly for testing as it isn't convenient for actual use as you would then have to set the throttle back up manually as well. Here is some code to watch the cpu usage and change the throttle respectively. This code is not real dynamic right now but appears to more or less do the job. I am hoping others will also pick this up and maybe come up with something until a better approach is found. I am running this program on a hyperthreading SMP system (one CPU but is being seen and used as 2) running eCS 2.0 rc6a. RC6a puts setgetthrtl.exe into the boot:\ecs\bin if ACPI was installed from the Betazone on another system then it is in the utils directory and setgetthrtl.exe either has to be in the path or in the same directory as the executable.
The bulk of the code I got from edm2, which in turn came from the SMP addendum.inf from the OS2 toolkit. I have left in currently the ability to set the time for the checks between 1-9 seconds, I changed from failing if no number is given to defaulting to 5 seconds.
I am open to better code suggestions

I am very interested in opinions on the best timing for how often to do the cpu checks.
I have been thinking it may be a good idea to boost the priority, should it run at normal priority but higher delta? or foreground server? time critical?
I have currently just selected throttle settings to idle settings to what seemed like they would work OK, better ideas for this?
From what I can tell, you cannot set the throttle settings independently on various processors so I only set CPU 0, however, I only have a hyperthreading machine to check on and not a true SMP system... if setgetthrtl.exe is run with no switches then it will show current throttle state (2nd CPU here show throttle disabled). The parameters for setgetthrtl.exe are cpu number (starting at 0) and throttle (mine shows min 13 and max 100).
And now for the code

#define INCL_BASE
#include <os2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DEBUG 0
APIRET APIENTRY DosPerfSysCall(ULONG ulCommand, ULONG ulParm1,
ULONG ulParm2, ULONG ulParm3);
#define ORD_DOS32PERFSYSCALL 976
#define CMD_KI_RDCNT (0x63)
typedef struct _CPUUTIL {
ULONG ulTimeLow; /* Low 32 bits of time stamp */
ULONG ulTimeHigh; /* High 32 bits of time stamp */
ULONG ulIdleLow; /* Low 32 bits of idle time */
ULONG ulIdleHigh; /* High 32 bits of idle time */
ULONG ulBusyLow; /* Low 32 bits of busy time */
ULONG ulBusyHigh; /* High 32 bits of busy time */
ULONG ulIntrLow; /* Low 32 bits of interrupt time */
ULONG ulIntrHigh; /* High 32 bits of interrupt time */
} CPUUTIL;
typedef CPUUTIL *PCPUUTIL;
/* Convert 8-byte (low, high) time value to double */
#define LL2F(high, low) (4294967296.0*(high)+(low))
/* This is a 1 processor example */
int main (int argc, char *argv[])
{
APIRET rc;
int i, iter, sleep_sec, cputhrtl50;
double ts_val, ts_val_prev;
double idle_val, idle_val_prev;
double busy_val, busy_val_prev;
double intr_val, intr_val_prev;
CPUUTIL CPUUtil;
if ((argc < 2) || (*argv[1] < '1') || (*argv[1] > '9')) {
sleep_sec = 5;
} else
sleep_sec = *argv[1] - '0';
cputhrtl50 = 100;
iter = 0;
do {
rc = DosPerfSysCall(CMD_KI_RDCNT,(ULONG) &CPUUtil,0,0);
if (rc) {
fprintf(stderr, "CMD_KI_RDCNT failed rc = %d\n",rc);
exit(1);
}
ts_val = LL2F(CPUUtil.ulTimeHigh, CPUUtil.ulTimeLow);
idle_val = LL2F(CPUUtil.ulIdleHigh, CPUUtil.ulIdleLow);
busy_val = LL2F(CPUUtil.ulBusyHigh, CPUUtil.ulBusyLow);
intr_val = LL2F(CPUUtil.ulIntrHigh, CPUUtil.ulIntrLow);
if (iter > 0) {
double ts_delta = ts_val - ts_val_prev;
#if DEBUG
printf("idle: %4.2f%% busy: %4.2f%% intr: %4.2f%%\n",
(idle_val - idle_val_prev)/ts_delta*100.0,
(busy_val - busy_val_prev)/ts_delta*100.0,
(intr_val - intr_val_prev)/ts_delta*100.0);
#endif
if (((idle_val - idle_val_prev)/ts_delta*100.0) > 75){
if (((idle_val - idle_val_prev)/ts_delta*100.0) > 85){
if (((idle_val - idle_val_prev)/ts_delta*100.0) > 90){
if (cputhrtl50 != 15){
system( "setgetthrtl 0 15");
cputhrtl50 = 15;}} else
if (cputhrtl50 != 25){
system( "setgetthrtl 0 25");
cputhrtl50 = 25;}} else
if (cputhrtl50 != 50){
system( "setgetthrtl 0 50");
cputhrtl50 = 50;}}
if (((idle_val - idle_val_prev)/ts_delta*100.0) < 35){
if (((idle_val - idle_val_prev)/ts_delta*100.0) < 25){
if (((idle_val - idle_val_prev)/ts_delta*100.0) < 10){
if (cputhrtl50 != 100){
system( "setgetthrtl 0 100");
cputhrtl50 = 100;}} else
if (cputhrtl50 != 75){
system( "setgetthrtl 0 75");
cputhrtl50 = 75;}} else
if (cputhrtl50 != 50){
system( "setgetthrtl 0 50");
cputhrtl50 = 50;}}
}
ts_val_prev = ts_val;
idle_val_prev = idle_val;
busy_val_prev = busy_val;
intr_val_prev = intr_val;
iter++;
DosSleep(1000*sleep_sec);
} while (1);
}