I need to prevent the processor from entering an idle state (non C0 C state). Admittedly I do not know much about processor C and P states so bear with me. We use a camera from a third party vendor which occasionally delivers corrupted frames. The vendor has determined that when the CPU enters an idle state it interferes with the transmission of the frame over the firewire. To confirm this I used the following code on a Windows 7 PC and indeed, disabling the idle states resolved the issue.
//WIN7
const DWORD DISABLED = 1;
const DWORD ENABLED = 0;
GUID *scheme;
PowerGetActiveScheme(NULL, &scheme);
PowerWriteACValueIndex(NULL, scheme, &GUID_PROCESSOR_SETTINGS_SUBGROUP, &GUID_PROCESSOR_IDLE_DISABLE, DISABLED);
PowerSetActiveScheme(NULL, scheme);
If I run my application and open Windows permon and add the %C1 Time, %C2 Time and %C3 time I see that they are all zero when I disable these states, when I enable them I see quite a bit of time spent in the C3 state (this is on a Dell Precision T3500 quad core PC).
I also need to do this on XP however these calls are not available on XP. So I attempted to do the following to disable the idle states
unsigned int ActPwrSch;
DWORD currPolicy,newPolicy, curr1Policy,curr2Policy, new1Policy, new2Policy;
MACHINE_PROCESSOR_POWER_POLICY Policy;
if(GetActivePwrScheme(&ActPwrSch))
{
if(ReadProcessorPwrScheme(ActPwrSch,&Policy))
{
printf("Read Power Scheme:\n");
//if(Policy.ProcessorPolicyAc.DisableCStates!=0)
currPolicy = Policy.ProcessorPolicyAc.Policy[0].AllowPromotion;
curr1Policy = Policy.ProcessorPolicyAc.Policy[1].AllowPromotion;
curr2Policy = Policy.ProcessorPolicyAc.Policy[2].AllowPromotion;
Policy.ProcessorPolicyAc.Policy[0].AllowPromotion = 0;
Policy.ProcessorPolicyAc.Policy[1].AllowPromotion = 0;
Policy.ProcessorPolicyAc.Policy[2].AllowPromotion = 0;
newPolicy = Policy.ProcessorPolicyAc.Policy[0].AllowPromotion;
if(WriteProcessorPwrScheme(ActPwrSch,&Policy))
{
printf("WriteProcessorPwrScheme succeed\n");
if(SetActivePwrScheme(ActPwrSch,0,0))
{
printf("SetActivePwrScheme succeed!!\n");
}
}
}
However when I run my application I still see that the processor is spending time in the C1 state (by looking at the same counters in perfmon). And I still get my corrupted image problem. The XP PC is an single core Dell optiplex PC.
Does anybody know how I can prevent entry into any of the C1-C3 states on XP? As I said it seems that I have done it on Windows 7.
You can use SetThreadExecutionState function which enables the application to inform the system that it is in use.
EDIT: After a little research and testing I came to a solution or I think I did. You're on the right track for Windows XP. If you read the documentation for the PROCESSOR_POWER_POLICY structure , you'll notice you can disable each C-states that offends you:
Policy[0].AllowPromotion = 0; // Disable's C1 (usually C1 won't cause problems, so you should leave it alone.)
Policy[1].AllowPromotion = 0; // Disable's C2
Policy[2].AllowPromotion = 0; // Disable's C3
In Vista and Windows7 you can't use this interface instead you have to do this:
GUID *scheme;
PowerGetActiveScheme(NULL, &scheme);
PowerWriteACValueIndex(NULL, scheme, &GUID_PROCESSOR_SETTINGS_SUBGROUP, &GUID_PROCESSOR_IDLE_DISABLE, 1);
PowerSetActiveScheme(NULL, scheme);
I haven't found a way to disable individual C states on Vista and Windows 7. If you need some sample codes please email me I can help you out.
This seems to be working for me:
void PowerState(bool bEnable)
{
// CPU idle state
unsigned int ActPwrSch;
MACHINE_PROCESSOR_POWER_POLICY Policy;
if (GetActivePwrScheme(&ActPwrSch))
{
if (ReadProcessorPwrScheme(ActPwrSch, &Policy))
{
Policy.ProcessorPolicyAc.Policy[0].AllowPromotion = bEnable ? 1: 0; // C1
Policy.ProcessorPolicyAc.Policy[1].AllowPromotion = bEnable ? 1: 0; // C2
Policy.ProcessorPolicyAc.Policy[2].AllowPromotion = bEnable ? 1: 0; // C3
if (WriteProcessorPwrScheme(ActPwrSch, &Policy))
SetActivePwrScheme(ActPwrSch, 0, 0);
}
}
OSVERSIONINFO osvi;
memset(&osvi, 0, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
// For Vista and above
if (osvi.dwMajorVersion >= 6)
{
static const GUID processor_idle_disable_guid = {0x5d76a2ca, 0xe8c0, 0x402f, 0xa1, 0x33, 0x21, 0x58, 0x49, 0x2d, 0x58, 0xad};
GUID *scheme;
PowerGetActiveScheme(NULL, &scheme);
PowerWriteACValueIndex(NULL, scheme, &GUID_PROCESSOR_SETTINGS_SUBGROUP, &processor_idle_disable_guid, bEnable ? 0 : 1);
PowerSetActiveScheme(NULL, scheme);
}
}
Surely a TSR running a mathematical calculation every 5 minutes will prevent an idle state? Alternatively you can purchase a cheap hardware or software mouse emulator that sends a mouse move signal at defined intervals.
来源:https://stackoverflow.com/questions/9721218/trying-to-disable-processor-idle-states-c-states-on-windows-pc