Snow White’s Poison Apple (or “Verifying PocketPC’s Suspend/Resume Path”)

PocketPC devices save a significant amount of power by dropping into a suspend state, which is almost the same as being completely off.  Unfortunately, it’s possible for a driver to crash or hang in the suspend/resume path, which causes the device to become a Sleeping Beauty: she goes to sleep but all the kings horses and all the kings men can’t wake wake Sleeping Beauty again.


A hang in the suspend or resume path of a Pocket PC device is difficult to debug because most of the OS and hardware are inaccessible or even powered.  An overwhelming majority of these hangs are caused a device driver that hits a page fault in its XXX_PowerDown() or XXX_PowerUp() routine.  These functions are called by the Device Manager at the very end of suspend and the very beginning of resume when the scheduler isn’t running and the storage device is usually powered off.  In this state, a page fault will never be serviced and the system will just hang.  This problem won’t be hit all the time because the memory pages will be loaded at boot and won’t be paged-out right away; however, after a period of time the memory manager may page-out the memory and the device will just appear to hang at random.


To verify a driver’s power routines don’t touch memory that can be paged out, set the following key in the registry:




This key instructs the kernel to page out all memory used by drivers, which will force a page-fault if one exists.  If this key is set and the device never successfully suspends and resumes, then the DevHealth tool can be used to identify which drivers are pageable.  Any pageable driver that has an XXX_PowerDown or XXX_PowerUp routine must be sure all of the code run and memory touched by those routines are marked as non-pageable.  To mark code as non-pageable,  enclose it in the following pragmas:

#pragma comment(linker, “/section:.no_page,ER!P”)

#pragma code_seg(push, “.no_page”)

// NON-PAGEABLE CODE, i.e. code needed during

// suspend/resume or shutdown,  ISTs, code used during

// paging, any code called by non pageable code

#pragma code_seg(pop)


For more information on optimizing memory usage by making driver pageable and marking sections of code as non-pageable, consult the article Tuning the Platform for Optimum Performance article in the Windows Mobile 6.0 documentation.

Comments (3)

  1. B says:

    Would this scenario occur for SmartPhones as well??

  2. JeCahill says:

    SmartPhones don’t suspend, so this particular bug and test aren’t applicable. SmartPhones drop to a low power state when there’s no work, but this isn’t the same as suspending.

    The difference between "low power state" and "suspend" is thread activity.  When a SmartPhone is in a "low power state", threads can wake-up and run normally.  However, in a suspend state, the Real Time Clock (RTC) is the only clock that’s running, so no timers will expire and no threads will be scheduled to run.  After a resume happens (either by the RTC or some other hardware interrupt), threads are able to run again and the scheduler evaluates which timers have expired and schedules all of the threads at that point.  

    MikeCal wrote two blogs that provide more insight into the difference between the SmartPhone and PocketPC power models. Check out the following blogs on the Windows Mobile Team Blog for more info on this:

    Power To the Smartphone:

    Power to the PocketPC:

  3. JeCahill says:

    The astute reader will notice that I changed the title of this blog.  The original title was "Sleeping Beauty’s Poison Apple", however, after posting the blog I realized that Sleeping Beauty never ate a poison apple.  Obviously, I don’t read fairytales enough because I had confused the stories of Sleeping Beauty and Snow White.  I apologize for the mistake and hope this didn’t cause too much confusion.