title: Windows: Disabling CPU idle C-states from kernel-mode driver
body: <p>I'm writing an audio device driver which needs to process device interrupts in real-time. When the CPU enters C3 state, interrupts are delayed, causing problems to the driver. Is there a way for the driver to tell the OS not to enter idle C-states?</p>
  
  <p>What I've found is that idle C-states can be disabled from user-space:</p>
  
  <pre><code>const DWORD DISABLED = 1;
  const DWORD ENABLED = 0;
  GUID *scheme;
  PowerGetActiveScheme(NULL, &amp;scheme);
  PowerWriteACValueIndex(NULL, scheme, &amp;GUID_PROCESSOR_SETTINGS_SUBGROUP, &amp;GUID_PROCESSOR_IDLE_DISABLE, DISABLED);
  PowerSetActiveScheme(NULL, scheme);
  </code></pre>
  
  <p>However, it is a global setting, which can be overwritten by the user or another application (e.g. when the user changes the Power Plan).</p>
  
  <p>What I need is something like PoRegisterSystemState, but not for S- and P-states, but for C-states. (ref: <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/preventing-system-power-state-changes" rel="noreferrer">https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/preventing-system-power-state-changes</a>)</p>
  
  <p>Is there any way to achieve this?</p>
  
  <p>=====</p>
  
  <p>It turns out there isn't a supported way to disable idle C-states from kernel space, and there isn't a service in user space to provide common API to do this. 
  The way to control C-states is from "Processor Power Management" in "Change advanced power settings" dialog, through registry, or via C API PowerWriteACValueIndex / PowerWriteDCValueIndex. </p>
  
  <p>The original problem was delayed interrupts in all but C1 idle state, so I needed to disable both C2, C3 and deeper idle states. The problem with disabling all idle C-states, including C1 (as shown in the example code PowerWriteACValueIndex(NULL, scheme, &amp;GUID_PROCESSOR_SETTINGS_SUBGROUP, &amp;GUID_PROCESSOR_IDLE_DISABLE, DISABLED)) is that the CPU usage is reported as 100%, and some applications (DAWs) get confused. </p>
  
  <p>The solution for my problem is to disable all but C1 idle state, which can be done by setting the following values in the Processor Power Management:
   - Processor idle threshold scaling -> Disable scaling;
   - Processor idle promote threshold -> 100%;
   - Processor idle demote threshold -> 100%. </p>
  
  <p>Perhaps I'll create a service that does just that, that will use the PowerWriteACValueIndex / PowerWriteDCValueIndex API. </p>