Windows Vista – How I cured its insomnia

October 5th, 2008 at 02:06pm Os

I have previously mentioned how Windows Vista really wasn’t that scary at all, however I was having one issue that was annoying – it just didn’t want to sleep automatically. It would sleep on demand quite happily, but there was no way I could make it sleep after any decent idle period. So I decided to attempt to figure it out, since no amount of warm milk would solve the problem.

Step 1: Isolate the problem

As there was no difficulty in getting Vista to sleep manually, I assumed there was no problem with sleep per se, rather there was something blocking the idle detection system that was keeping it awake.

The first thing to look at is one of the simplest, by default if you have Media Player sharing enabled, Vista will not go to sleep, on the assumption that other devices may be streaming from your PC. To turn this off, go into Power Options, Edit plan settings, Change advanced power settings and at the bottom make sure that Multimedia settings looks like this:

image

Most of the time that would be enough, but my PC was determined to remain awake. So I soldiered on.

The next thing I looked at was whether a process was intermittently resetting the idle timer: lacking proper tools to check this I tried the most obvious thing – setting the sleep timer in Power options to one minute. This worked – the PC went to sleep quite happily after a minute idle – but is obviously impractical for day to day use. Increasing the time to two minutes didn’t work, it doggedly stayed awake. It was time to get technical.

Step 2: Bring out the gimp toolkit

As a developer I knew there was an API that could be used to stop windows from turning off the display or even sleeping while it was, say, showing a video. You wouldn’t want your PC to shut off midway, so Media Player prevents this. A quick search on MSDN turns up this API call, SetThreadExecutionState that is used to prevent the PC from idling. I needed to track what was calling that roughly every minute that was keeping my poor PC wide eyed.

My first thought was to write something that would hook the SetThreadExecutionState function in kernel32 to allow me to see what was calling it and how often. My second thought was that although this would be interesting to write, someone must have already done this as debugging power options has to be a common enough occurrence. Some more googling turned up a reference to the Windows Device Driver Kit utility Pwrtest which is precisely for this very purpose. The one difficulty is that the WDDK isn’t easily obtainable to the average Joe end user; fortunately I have an MSDN subscription so I downloaded it and started testing.

Step 3: Nailing it down

From an elevated-privilege command prompt, I ran “pwrtest.exe /es” to show execution state changes, and just left it running. This was the result:

image

(click for larger image)

The culprit was the Bluetooth stack, roughly every two minutes it was refreshing its state and resetting Windows’ idle timeout. The simple act of unplugging the cheap Bluetooth USB dongle I use cured the problem, my PC could now go counting sheep quite happily.

All was well in the world and my power bills would be reduced. Rejoice!

Epilogue: Don’t blame the Dongle for everything

Even after supposedly curing the issue, every now and again Vista would again remain awake, even with the Bluetooth dongle unplugged, in a box and buried in the back garden. Pwrtest /es wasn’t showing anything resetting the timer, yet still Vista would stay awake. Fortunately pwrtest has another option, “/info:powerinfo” that shows a snapshot of the Windows data structure SYSTEM_POWER_INFORMATION, which is defined as:

typedef struct _SYSTEM_POWER_INFORMATION {
ULONG MaxIdlenessAllowed;
ULONG Idleness;
ULONG TimeRemaining;
UCHAR CoolingMode; } SYSTEM_POWER_INFORMATION;

The pertinent information fields are Idleness and TimeRemaining, I wrote a little batch file to call “pwrtest /info:powerinfo”, sleep 20 seconds (using the sleep.exe command from the Server 2003 power tools), and loop.

This showed that the time remaining would start dropping for a while (indicating that the system was detecting the idle state) then after a while reset back. It also showed that when it did this the Idleness value was under 80, which is what the field MaxIdlenessAllowed was set to.

Investigating more showed that every time the system went above 20% CPU usage (ie, less than 80% idle), the timeout was reset, preventing the PC from sleeping. This is a lot easier to debug, just bring up Windows Task Manager and see which process is eating all the pies. As it turned out it was Firefox; my habit of having 40+ tabs open, many of which had Flash rubbish running kept pushing things over 20%, even on a quad-core processor.

Changing the MaxIdlenessAllowed value turned out to be a bit of a problem, but thanks to this post on the Microsoft Technet forums the following in an elevated command prompt did the trick:

powercfg -setacvalueindex scheme_current sub_sleep 81cd32e0-7833-44f3-8737-7081f38d1f70 70

powercfg -setactive scheme_current

The long GUID is the id of the ‘balanced’ power plan. This changed the MaxIdlenessAllowed value to 70, down from 80, which doesn’t reset the counter until Windows reaches 30% processor usage, which even with a multitude of flash-laden Firefox tabs didn’t keep the PC awake.

Finally, unless I’m actually doing something intensive enough to keep it awake – when I don’t want it to switch off – Vista is now happily sliding into the land of Nod. With this fixed, the idea of going back to Windows XP holds no appeal in the slightest.

Entry Filed under: Technical


Calendar

October 2008
M T W T F S S
 12345
6789101112
13141516171819
20212223242526
2728293031  

Most Recent Posts