Power Management


The mobility trends described earlier will gradually cause two fundamental shifts in the way most people use their computers. First, people take their PCs with them when they leave their offices to work offsite, to travel, or to attend meetings. Second, people now expect to be able to use their PCs much more like they do PDAs and cell phones, without having to go through long startup and shutdown procedures between sessions.

To meet these expectations, the hardware, operating system, and applications must each do their part to help realize extended battery life and fast, reliable system standby and resume transitions. Through the OnNow power management initiatives, Microsoft has been working since the release of Windows 98 to drive battery life and availability improvements in PC hardware, the core Windows components , and applications.

Longhorn continues this investment with several key new features for improved power management, including a redesigned and enhanced kernel power policy manager. Extensions to the power manager will provide a common framework for applications and devices to register for and receive notifications of important system power events, including the user s current power preferences (for example, the user currently wants maximum battery life or maximum performance), and notifications of when the remaining battery capacity crosses specific thresholds (for example, remaining battery capacity is 30 percent).

An application can also use the power policy manager to handle the storage and retrieval of its application-specific power settings with the current user system power policy. When a power transition occurs that affects a power setting that the application has registered for, the power manager will notify the application with an updated value for the power setting. The power manager can handle all overhead of storing, managing, and retrieving power settings for an application. This can significantly reduce the work required by the application to support intelligent and efficient power-aware behavior.

Coinciding with the release of Windows 98, Microsoft published a white paper on designing power-aware applications: OnNow Power Management Architecture for Applications. Many of the fundamental design and implementation guidelines in this paper are unchanged under the new Longhorn power manager framework. Before we examine what has changed for Longhorn applications, it s worth reviewing what has not.

First and foremost, applications should respond to and make proper use of the system power broadcast (WM_POWERBROADCAST) messages. When the system is about to go to sleep, Windows will broadcast a sleep query message, along with a flag indicating whether applications are allowed to display the user interface (UI). Regardless of the state of the UI allowed flag, applications should make every effort to prepare for sleep without querying or notifying the user. When the flag is set to disallow UI, it usually indicates that the user is unable to see and respond to the UI ”for example, when the lid on a laptop is closed. Unless an application is in the middle of an uninterruptible operation, it should use the sleep query message to quickly and silently save its state so that it can seamlessly resume when the system wakes up again. In particular, because network connections and file handles are likely to be invalid after a standby/resume transition, applications should autosave any open files and silently close open file handles as part of their sleep preparation sequence.

Windows monitors system utilization and user input to detect when the system is being actively used, and depending on current power policy settings, it might turn off specific devices or transition the entire system to the standby state (ACPI-defined S3, or suspend to RAM state) to save power after the idle time-out has expired . Longhorn will be more aggressive about reducing system power consumption. The S3 system standby sleep state will be used much more frequently than in earlier versions of Windows.

Users often perform tasks with their PCs that might not be detected by the system as actual activity. One common example is when a user is presenting a document to others. Applications designed to understand such a presentation mode can call Windows application programming interfaces (APIs) to tell the power manager that the system or display is currently required, thus preventing the idle timers from expiring.

However, the user might be running an application such as a spreadsheet that has no concept of this presentation scenario and does not use these API calls to prevent system power management events. Windows users frequently complain about the display turning off in this case. To address this problem, Longhorn will include a keep the system and display on setting, which will temporarily override current power policy values; this setting will be easily accessible from the system battery meter. When the user chooses this setting, all idle timers will be disabled until the temporary override expires or is explicitly canceled .

Applications can also use timer objects to schedule the system to wake or to ensure that the system will be available at a predetermined time. This enables applications to schedule tasks such as backup, media recording, and the like.

Applications should be aware that the level of activity generated by a task might fall below the system idle detection threshold, and thus the system might transition to a low-power standby state at any time. To prevent this, applications should call the SetThreadExecutionState API when performing critical work. This ensures that the system will remain in the working state for the duration of the task. Applications must also take care to call the SetThreadExecutionState API again when the work is complete, thus allowing the system to continue to monitor system utilization and transition to a low-power state as indicated by the current power policy.

Application developers should also be aware of how their designs affect processor power management features. Recent mobile CPU designs have achieved impressive power efficiency through the use of processor idle sleep states (ACPI-defined C states) and dynamic voltage and frequency scaling technologies, otherwise known as performance states . These technologies dynamically reduce processor power consumption while providing performance on demand. However, periodic activity will cause the processor to exit the low- power idle sleep state (C state), and increases in CPU utilization might cause the operating system to increase the current CPU performance state, resulting in greatly increased CPU power consumption. You should test and profile applications on mobile or desktop systems employing these power-saving technologies to evaluate and minimize the effect the application has on processor power consumption.

Software developers should consider how application features can be scaled back based on the system power state (for example, is the system running on utility or battery power?) and the current power policy (for example, the user has indicated, via selecting a power policy, that she wants maximum battery life). In such cases, the user is agreeing to a reduced experience in exchange for the longest possible battery life. Software features that are good candidates for scaling or temporary suspension when operating the system in low-power modes include the following:

  • Nonessential background content processing such as spelling checking, grammar checking, pagination, and indexing for future searches. Some tasks, such as indexing, can be turned off entirely while the system is running on a battery, others can reduce their processing, and therefore power, requirements by reducing the update frequency.

  • Visual elements and effects such as thumbnail and preview panes, animations, and media playback. Thumbnail and preview pane update frequency should be reduced to less than once per second. Animations and playback can be scaled by reducing size and frame rate. Some effects should be turned off entirely if they are nonessential and cannot scale gracefully.

  • Polling for status changes and new data. Polling is almost always an inferior design, and should be avoided whenever possible. Any polling activity necessary should be scaled down in frequency to less than one activity per second. When possible, polling should be replaced by notifications or synchronous designs.

     // This program demonstrates how a managed program can notice the 
    // power state of the machine changing, and respond appropriately:
    // changing intervals of regularly performed actions, and suspending
    // or resuming actions.

    using System;
    using System.Threading;
    using System.Runtime.InteropServices;
    using Microsoft.Win32;

    namespace PowerSample {
    class PowerSample {
    private PowerThread[] _threads;

    // this struct and system API call are described in MSDN. It
    // does not take much interop to get a lot of information
    // about the machine.

    enum _ACLineStatus : byte {
    Offline = 0, Online = 1, Unknown = 255
    }
    enum _BatteryFlag : byte {
    High = 1, Low = 2, Critical = 4, Charging = 8,
    NoSystemBattery = 128, Unknown = 255
    }

    internal struct SystemPowerStatus {
    public _ACLineStatus ACLineStatus;
    public _BatteryFlag BatteryFlag;
    public byte BatteryLifePercent;
    public byte Reserved1;
    public uint BatteryLifeTime;
    public uint BatteryFullLifeTime;
    }

    [DllImport("kernel32")]
    internal static extern
    bool GetSystemPowerStatus (out SystemPowerStatus sps);

    // these flags and system API call are also described in MSDN.

    [Flags]
    enum ExecutionState : uint {
    SystemRequired = 0x01,
    SystemDisplayRequired = 0x02,
    UserPresent = 0x04,
    Continuous = 0x80000000,
    }

    [DllImport("kernel32")] internal static extern
    uint SetThreadExecutionState (ExecutionState esFlags);

    // This nested class represents application code with periodic
    // processing to do. It encapsulates a Thread object. This
    // object is responsive to a method to let it know the power
    // state of the machine; when the machine goes from AC to DC
    // power, we suspend all low priority processing, and increase
    // the interval at which we perform other periodic processing.
    //
    // In the best of all possible worlds, the application
    // programmer would not be required to poll in worker threads
    // like this; being sensitive to the systems power state
    // minimizes the negative consequences of this kind of code.
    // This example assumes that there is some periodic activity
    // that needs to occur.

    class PowerThread {
    private bool _lowPriority;
    private Thread _thread;
    private string _name;

    // storage used primarily in the context of the worker thread
    private int _sleepDelay;
    private bool _onBattery;

    public PowerThread(string name, bool lowPriority) {
    this._name = name;
    this._lowPriority = lowPriority;

    this._thread = null;
    this._sleepDelay = lowPriority ? 5000 : 1000;
    this._onBattery = false;
    }

    public void Start() {
    if (null == this._thread) {
    this._thread = new Thread(new ThreadStart(ThreadProc));

    this._thread.IsBackground = true;

    if (this._lowPriority) {
    this._thread.Priority = ThreadPriority.Lowest;
    }

    this._thread.Start();

    // When the thread is initialized, we examine the
    // power state of the machine and notify the
    // thread. This way the initial state of the
    // thread (once its initialized) will be
    // consistent with the power state of the machine.
    SystemPowerStatus status = new SystemPowerStatus();
    if (GetSystemPowerStatus (out status)) {
    this.PowerChange(status);
    }
    }
    }

    private void ThreadProc() {
    while (true) {
    int milliseconds = _sleepDelay;
    if (this._onBattery) {
    // This is where we artificially slow things
    // down on DC power. Your application might
    // adopt a different strategy for minimizing
    // power use while on DC.
    milliseconds *= 2;
    }
    else {
    // when on AC, we keep the computer awake
    // every time we do some processing. Once
    // were done with our processing, the
    // computer will go back to the normal timeout
    // as dictated by the kernel power policy.
    SetThreadExecutionState(ES_SYSTEM_REQUIRED);
    }

    Console.WriteLine(_name + " working every "
    + milliseconds.ToString()
    + " milliseconds "
    + (this._onBattery ? "and letting system time out"
    : "and reserving system")
    );

    Thread.Sleep(milliseconds);
    }
    }

    public void PowerChange (SystemPowerStatus status) {
    // the significance of the numbers in the
    // SYSTEM_POWER_STATUS fields is described in MSDN
    if (ACLineStatus.Online == status.ACLineStatus &&
    true == _onBattery) {
    // system is now on AC power
    Console.WriteLine(_name + " transitioning to AC power");
    _onBattery = false;

    if (true == this._lowPriority) {
    Console.WriteLine("Resuming " + this._name);
    this._thread.Resume();
    }
    }
    else if (0 == status.ACLineStatus && false == _onBattery) {
    // AC is offline (weve gone on DC - battery or UPS)
    Console.WriteLine(_name + " transitioning to DC power");
    _onBattery = true;

    if (true == this._lowPriority) {
    Console.WriteLine ("Suspending " + this._name);
    this._thread.Suspend();
    }
    }
    }
    }

    // This is our event handler for the system event. The event
    // indicates whether the power state of the machine has
    // changed, or if we've come back from a standby, etc. Our
    // behavior is the same in any case - we're just going to turn
    // around and get more detailed information about the power
    // state of the machine, and feed that information to our
    // worker threads.
    void OnPowerModeChange(object obj, PowerModeChangedEventArgs e) {
    if (e.Mode == PowerModes.StatusChange) {
    Console.WriteLine("Power status or capacity change detected");
    if (null != this._threads) {
    SystemPowerStatus status = new SystemPowerStatus();

    if (GetSystemPowerStatus (out status)) {
    foreach (PowerThread victim in this._threads) {
    victim.PowerChange(status);
    }
    }
    }
    }
    }

    // This routine sets up an event hook, creates a few worker
    // threads, lets the threads run for a while (being responsive
    // to power changes), and then terminates.
    void Go () {
    SystemEvents.PowerModeChanged +=
    new PowerModeChangedEventHandler(OnPowerModeChange);

    Console.WriteLine("Creating worker threads");

    this._threads = new PowerThread[3];
    this._threads[0] = new PowerThread("Worker thread 1", false);
    this._threads[1] = new PowerThread("Worker thread 2", false);
    this._threads[2] = new PowerThread("Low-priority thread", true);

    foreach (PowerThread victim in this._threads) {
    victim.Start();
    }

    Console.WriteLine ("Working for five minutes");
    Console.WriteLine ("(Please trip over the power cord now!)");
    Thread.Sleep(5 * 60 * 1000);

    Console.WriteLine("Ending worker threads - bye");
    }

    static void Main (string[] args) {
    PowerSample ps = new PowerSample();

    if (null != ps) ps.Go ();
    }
    }
    }



Introducing Microsoft WinFX
Introducing WinFX(TM) The Application Programming Interface for the Next Generation of Microsoft Windows Code Name Longhorn (Pro Developer)
ISBN: 0735620857
EAN: 2147483647
Year: 2004
Pages: 83
Authors: Brent Rector

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net