Power Resource Manager (PRM)

Describes the Power Resource Manager.

Introduction

The Power Resource Manager (PRM) integrates the Symbian device driver with existing power control and functions used for resource state changing and querying. It defines an exported API that device drivers and other users of power resources (represented by kernel-side components) can use to control the state of power resources. The PRM assists the development of device drivers by removing the need to understand the complexities of platform specific power resource management by providing a simple to use generic framework.

The PRM also allows user-side clients to gain access to the services. Clients of the PRM can:

  • request information on the clients and resources registered with PRM

  • get the current state of the resources

  • request changes to the state of power resources

  • request notification of changes (i.e. power-down or change clock frequency) to the power resources that they depend on.

The following diagram shows the generic and customisable parts of the framework:

  • exported kernel level API (PowerResourceManager)

  • base virtual class for Power Resource Controller (DPowerResourceController)

  • PDD required for user-side proxy client

  • platform specific implementation of resource control at the level of register interface to hardware resource controller (DXXXPowerResourceController)

Concepts

Power resources

A power resource is anything that has an effect on power consumption. These are typically platform specific and either physical or logical. Physical power resources are provided by hardware: for example, clocks, outputs from voltage regulators, switched power domains and performance levels. Logical power resources do not directly map to hardware components, but their state has an effect on overall power consumption. In this category we include, for example, shared buses and devices that provide services to other components.

Power resources can be further categorised based on:

  • Number of clients

    A power resource can have a single user or it can be shared. There is no limit to the number of clients sharing a resource. If the resource is shared, then a request system is used. This comprises a list of client level objects, one for each client requesting a level on the resource. The resource level is determined by a set of rules which govern whether a request is accepted or declined.

  • States

    The resource state may be binary, multi-level or multi-property. A binary state is either On or Off and a multi-level state can change either discretely or continuously between a minimum (which could be Off) and a maximum value (which could be fully On).

    A multi-property resource has different properties across different portions of the operating curve. For example, the level may be controllable within the ‘operational’ part of that curve but have different discrete fixed states for the ‘idle’ or ‘sleep’ modes of operation.

  • Execution time

    The execution time of a resource can be either instantaneous or long latency. An instantaneous resource can be operated almost immediately (no longer than a few system clock cycles, comparable to a CPU instruction execution time). Operations on long latency resources take a significant time to complete (a non-negligible amount of CPU clock cycles).

    Power resources may be long latency for state change operations and instantaneous for obtaining the current state. This is typically the case of a PLL (Phase Locked Loop) device (definition from Wikipedia), which requires time to stabilise after a frequency change is initiated but whose current output frequency can be read from a register. Note: instantaneous operations may pre-empt operations on long latency resources, and requests to get the state of a shared resource may be issued while a state change is underway. If the read operation is instantaneous and the change is long latency, care must be taken (at the PSL level) to not return inconsistent values.

    Other power resources may be long latency on both state change and state read operations. This is typically the case for any resources accessed through an inter-IC bus (even if their operation is instantaneous).

  • Resource sense

    Each client sharing a resource may have a different requirement on its state. The resource sense is used to determine whose requirement prevails.

    Positive sense

    Can have their value increased without affecting their sharers.

    The level is set to the highest level that is requested. The highest requirement for binary resources is the On state.

    Negative sense

    Can have their value decreased without affecting their sharers.

    The level is set to the lowest level that is requested. The lowest requirement for binary resources is the Off state.

    Custom sense

    May be increased or decreased freely by some privileged sharers but not by others, which are bound by the requirement of the privileged sharers.

    The decision to change the prevailing level (or binary state) depends on the privileges of the client and past usage of the resource. This decision is made by the PSL custom function implementation.

  • Static or Dynamic

    Most power resources are known at device creation time, so their control should be addressed by such components as the Variant or ASSP. These resources are registered during the creation of the Resource Controller; these are static resources. Resources controlled by device drivers (internal or external) are only registered at driver-creation time using the registration and deregistration API provided by the PRM; these are known as dynamic resources.

    Note: Dynamic resources are only available when you use the extended library. See setup and configuration.

Physical resources may belong to one or more of these categories, for example, a multilevel resource may be shared between different clients and take a significant time to change state (long latency).

External devices may include and control their own power resources. In some cases, an external device can function as a bus expander, allowing other devices to be connected, and eventually share the power resources it controls.

Caching the prevailing level

The PRM caches the prevailing level of each resource as well as the client that requested it. The cached state is guaranteed to be the state that the resource was in when the last request to change or read the state from its hardware was issued.

On resource state read operations, the PRM allows clients to select the cached state instead of the current state of the hardware resource. A cached state read is always an instantaneous operation executed in the context of the calling client thread (even for long latency resources).

However, care must be taken as the cached state may not be the state the resource is at that moment. For example, a resource can be non-sticky: when it is turned on it stays on during an operation but then automatically switches itself off.

The consistency of the cached state relies on all resource state operations being requested through the Power Resource Controller.

Dynamic resources

A generic layer provides basic functionality for static resources an extended version of the PRM provides APIs for dynamic resources and resource dependencies. These dynamic resource and resource dependent APIs are only available through the extended library resmanextended.lib.

A dynamic resource is registered with the PRM using PowerResourceManager::RegisterDynamicResource(). This function is also used to register a dynamic resource that supports dependencies between resources.

TInt RegisterDynamicResource(TUint aClientId, DDynamicPowerResource* aResource, TUint& aResourceId)

Pass the ID of the client that requests the dynamic resource and the dynamic resource (DDynamicPowerResource) to register. The PRM sets aResourceId to the resource ID of this resource. Dynamic resources that support dependencies are derived from the class DDynamicPowerResourceD.

Deregistering a dynamic resource

Use PowerResourceManager::DeRegisterDynamicResource() to deregister a dynamic resource from the PRM. You can also use the function to deregister a dynamic resource that supports a dependency.

TInt DeRegisterDynamicResource(TUint aClientId, TUint aResourceId, TInt* aState)

aState is a pointer to the final state that the resource is set to before deregistration if this value is NULL the state of the resource is changed to its default.

Changing resource state on a dynamic resource

Because a dynamic resource can deregister from the PRM it is necessary to indicate to clients that this has happened. Any remaining notification requests are completed with a -2 in the client field of the callback function. This indicates that this notification is because the resource has been deregistered and not because the notification conditions have been met. When a client recieves a notification of this type the request notification should be cancelled using CancelNotification().

Resource dependencies

A resource may register a dependency on another resource. At least one of the resources must be a dynamic resource. Request a dependency between resources with PowerResourceManager::RegisterResourceDependency().

TInt RegisterResourceDependency(TUint aClientId, SResourceDependencyInfo* aResDependecyInfo1, SResourceDependencyInfo* aResDependencyInfo2)

This function is passed the ID of the client that sets the resource dependency and the dependency information of the resource (SResourceDependencyInfo). SResourceDependencyInfo contains the resource ID and the priority of the dependency.

The kernel will panic if a closed loop dependency is found for the specified dependency or if a resource with same dependency priority is already registered.

Use GetNumDependentsForResource() to retrieve the number of resources that depend on the specified resource directly and GetDependentsIdForResource() to return the IDs of all the dependent resources.

Deregistering resource dependencies

Use PowerResourceManager::DeRegisterResourceDependency() to remove a dependency. This function takes the ID of the client that requests the deregistration of the resource dependency and the IDs of the linked resources.

TInt DeRegisterResourceDependency(TUint aClientId, TUint aResourceId1, TUint aResourceId2)

Note: These functions are only available when you use the extended library.

Changing resource state on a dependent resource

A resource state can change when the state of any of its dependent resources changes. A state change causes a notification if the requested conditions are met. The client ID in the callback function is updated with the ID of the resource that triggered this resource change (bit 16 of the ID is set for dependency resource; this is used to distinguish between a resource ID and a client ID).

Clients

The PRM has both user and kernel-side clients. Kernel-side clients are:

  • device drivers

  • performance scaling and/or performance monitoring and prediction components

User-side clients are:

  • user-side system-wide power management framework

  • other power-aware servers and power-aware applications

Clients register with the PRM by name. Clients can request to allocate and reserve client level objects and request message objects after registering with PRM.

Client level objects

Client level objects represent a client requesting a level on a resource. They are used by resources to set the current level of the resource and the current owner of the resource level.

Each resource has a doubly linked list on which client level objects are held. When a client requests a level for the first time, a new client level object is added to the list; however, if the client already has an object on the list, this object is adjusted to reflect the change in the required level.

The following rules determine whether the change is allowed on positive and negative sense resources:

  • If the requested change is in the direction permitted by the resource sense and would result in exceeding the prevailing level, the change is allowed.

    The new prevailing level is recorded, and the previous prevailing level and the requirements other clients have on the resource remain on record.

  • If the requested change is not in the direction permitted by the resource sense, but the client requesting the change is the owner of the prevailing level, the resource state changes up to next highest for a positive sense resource, or lowest for a negative sense resource.

    This value is now the prevailing level and the client that requested it remains the owner of the prevailing level.

  • If the requested change is not in the direction permitted by the resource sense, and the client requesting the change is not the owner of the prevailing level, the change is not allowed.

    Even though the request was rejected, the client's existing requirement is adjusted to reflect the request.

Prevailing levels are recorded by either adjusting the previous requirement for the client that requested it or, if it is the first time this client requests a level, a new requirement is created.

Notifications

A client may request a state change notification from a resource. Notifications can be conditional or unconditional; conditional notifications specify a threshold on the resources state, which when crossed in the direction specified, triggers the notification.

Notifications are always issued post resource change and invoke callback functions executed in the context of the requesting client thread. The process of notifying a client involves queuing a DFC in that clients' thread. The notification object encapsulating the DFC must be created in kernel heap and passed to the notification API by the client that requested the notification. The client may share the same callback function between several notifications, but a unique DFC must be created and queued per notification.

Because notifications result in DFCs being queued, it is not possible to guarantee that all changes of resource state are notified. If the resource state changes again before the first DFC runs, a separate notification cannot be generated. It is also not possible to guarantee that by the time the notification callback runs, the resource state is still the same as the state that caused the notification to be issued: it is the responsibility of the driver to read the resource state after receiving a notification.

User-side

Introduction

The RBusDevResManUs user-side API makes relevant PRM functionality available to user-side applications that have power-aware features.

RBusDevResManUs is derived from RBusLogicalChannel, the user-side handle to a logical channel base class, and presents the user-side interface to a kernel-side LDD. The LDD is built as resman.ldd.

The API enables concurrent access by multiple clients, with one channel supported for each. Sharing of channels between threads is not supported.

Note: To open a channel on the user-side API a client must exhibit the PlatSec capability PowerMgt.

If a client wishes to access information on kernel-side clients of the Resource Controller, it must also exhibit the ReadDeviceData capability.

Initialisation

Clients do not need to explicitly load the kernel-side LDD, as this is a kernel extension and so is loaded and initialised during kernel initialisation (attempts to re-load it returns the error code KErrAlreadyExists but initialistation otherwise appears successful).

Clients open a channel on the LDD by calling the RBusDevResManUs::Open() method. The client passes a name to the method - ideally, this is the client’s component name. It is the client’s responsibility to ensure the name is unique even if multiple channels are opened.

The client then needs to call the Initialise() method specifying the number of request objects required. The numbers passed to Initialise() determine the extent of memory allocation required (in part by the LDD and in addition by request to the Resource Controller) and also the maximum number of concurrent client requests supported.

The number of request objects created at initialisation should be the maximum number of concurrent (asynchronous) requests that the client expects to have outstanding at any time.

Getting power resource information

RBusDevResManUs::GetResourceInfo() is a method to retrieve the information for a specified resource, which it returns in a TResourceInfo object. There is also a method to get all the information for all the resources (GetAllResourcesInfo()). This function requires the allocation of buffer memory in which the information for all the resources is returned. GetNoOfResources() returns the total number of resources available for access.

The example below shows these functions in use. The amount of resources available are returned by GetNoOfResources. This figure is used to calculate the size of the buffer that is populated with the resource information by the GetAllResourcesInfo method.

 TInt r = KErrNone;
 TUint numResources=0;
    if((r=gChannel.GetNoOfResources(numResources))!=KErrNone)
        {
        // Failed
        return r;
        }

    RBuf buffer;
    if((buffer.Create(numResources*sizeof(TResourceInfo)))!=KErrNone)
        {
        // Failed
        return KErrGeneral;
        }

    buffer.SetLength(numResources*sizeof(TResourceInfo));

    if((r=gChannel.GetAllResourcesInfo(buffer,numResources))!=KErrNone)
        {
        // Failed
        return r;
        }

Get the current resource state with GetResourceState(). Passing ETrue results in the cached state being read rather than the current hardware state. The cached state is guaranteed to be the state that the resource was in when it was last changed or read from hardware. This is why it is important that all change requests are carried out through the Resource Controller. readValue returns the current prevailing level and levelOwnerId the ID of the client that owns the prevailing level. GetResourceState() can be cancelled using CancelGetResourceState() passing the resource ID of the resource that the original request was on. Use the method GetResourceIdByName() to get the ID of a resource from the resource's name.

// Get initial state
TRequestStatus status;
TBool cached = EFalse;
TInt readValue;
TInt levelOwnerId = 0;

gChannel.GetResourceState(status, gSharedResource, cached, &readValue, &levelOwnerId);
User::WaitForRequest(status);

GetNumClientsUsingResource() and GetNumResourcesInUseByClient() are used to retrieve the numbers of clients using a resource and the number of resources in use by a client, respectively. GetInfoOnClientsUsingResource() and GetInfoOnResourcesInUseByClient() complement the last two methods by retrieving the resource information for each resource that is in use by a specified client or retrieving the client information for each client using the specified resource.

The API supports receiving a number of concurrent (asynchronous) requests from a client; the maximum number is determined by the number of resources that were specified at initialisation. If a client issues a request that exceeds its allocation, the error code KErrUnderflow is returned.

Some synchronous methods take a binary value, aIncludeKern, which defaults to EFalse. If this parameter is set to ETrue, the API attempts to return information that includes kernel-side clients.

Requesting notifications

Clients can request to be notified when a resource changes its state using the RBusDevResManUs::RequestNotification() method. Clients can also request to be notified when a resource reaches a specified threshold in a specified direction (positive or negative resource sense) using the same method but also passing it threshold and direction values.

To cancel a notification, use CancelNotification() passing the resource ID from which the notification was requested. Note: Any notifications issued by a client must be cancelled before the client deregisters.

It is not guaranteed that all changes of resource state result in a notification – a resource may change state more than once before a notification request is completed. In addition, it is not guaranteed that a resource is in the same state as it was when the notification was generated. For these reasons, it is the responsibility of the user-side client to read the state of a resource after receiving a notification.

Changing the state of power resources

To change a resource state call the asynchronous ChangeResourceState() method passing the ID of the resource on which the change is being requested and the requested state.

CancelChangeResourceState() cancels all the ChangeResourceState() outstanding requests from the client on the specified power resource. For each outstanding request, the request object is removed from the doubly linked list within the Resource Controller and returned to the request object pool.

Kernel-side

The Power Resource Manager component is implemented as a kernel extension. It has an exported public interface accessible to kernel-side components. Kernel components link to the resource manager kernel extension DLL (resman.lib). Extended features are compiled and exported in an additional library (resmanextended.lib). The export library is built from the generic layer.

To ease the development of the PRM including the functionality provided by the generic layer and the mandatory PSL implementation, the generic layer is compiled into a kernel library (klib) (resmanpsl.lib for the basic version and resmanextendedpsl.lib for the extended version) which is included by the PSL to produce the kernel extension.

Concepts

Request messages

Request message objects represent a request for an operation on a resource by a client. For example a request to change a resource's level or notification if a resource's level changes.

The client may attempt to increase its quota by requesting the allocation of request messages, but this may fail with KErrNoMemory. A long latency resource request on may fail with KErrUnderflow if the number of request messages pre-allocated by the client has been exceeded and no more messages are left in the free pool to satisfy the request.

The pre-allocation and reservation of client levels and request messages is synchronously serviced in the context of the calling client, although this may result in memory allocation that is not time bound.

See Pre-allocating client level and request message objects for implementation guidelines.

Callbacks

A callback object is a customised DFC that is used to signal the completion of notifications and the PRM's asynchronous APIs. Use the class TPowerResourceCb to create a resource callback object that encapsulates callback functions.

The resource callback object is initialised with a callback function TPowerResourceCbFn, a pointer to data passed to the callback function, the priority of the DFC within the queue (0 to 7, where 7 is highest) and optionally, a pointer to the DFC queue that this DFC should use.

inline TPowerResourceCb(TPowerResourceCbFn aFn, TAny* aPtr, TInt aPriority)

This one specifies the DFC queue:

inline TPowerResourceCb(TPowerResourceCbFn aFn, TAny* aPtr, TDfcQue* aQue, TInt aPriority)

The user specified callback function is invoked with five arguments:

  • the ID of the client is:

    • the client that issued an asynchronous operation - if the callback function is called as a result of an asynchronous resource state read operation

    • the client that is currently holding the resource - if the callback function is called as a result of an asynchronous resource state change operation or resource state change notification.

    • Note:

      • If -1 is passed as the client ID this specifies that no client is currently holding the resource.

      • In the extended version of PRM (see Dynamic and Dependant resources) if -2 is passed as the client ID in the callback function it signifies that the dynamic resource is deregistering. With dependency resources, the ID of the dependent resource is passed as the client ID if the state of the resource (specified in aResourceId) changes as a result of the dependant resources stage changing (whose ID is specified in aClientId).

    • issued an asynchronous API (state read or change) which leads to the callback function being called

    • requested the resource state change that leads to queuing a notification, which then leads to the callback function being called.

  • the resource ID - a client may have multiple notifications pending on different resources and a single callback function. The resource ID can be used to specify which resource change is being notified

  • the level of the resource when either:

  • the ID of the resource level owner

  • the error code returned when the callback is called as a result of an asynchronous request to change the state of the resource. This is not relevant when the callback is called as a result of a notification of state change

  • a user defined argument that is passed to the constructor.

Cancel an asynchronous request, or its callback, by calling CancelAsyncRequestCallback().

Registration and initialisation

Clients need to register with the PRM using PowerResourceManager::RegisterClient() before they can request operations on resources.

Registration happens at different times for different clients:

  • kernel extensions register from their entry point during kernel boot

  • device drivers for internal or external devices register on opening a channel.

When a client registers with the PRM, a client link object is removed from the free pool, populated with the relevant information, and a pointer to it is added to a container of clients within the PRM. If no free link exists within the pool, a number of client links are created in kernel heap. As a result, client registration may fail in out of memory situations. Client links are never destroyed after the client deregisters, but are released back into the free pool.

Clients are registered by name; the PRM does not check that a name is unique unless the DEBUG_VERSION macro is enabled. The component registering the client should check that the name is unique. The ID returned is a handle to the client link object that represents the client in the PRM.

On registration, a client also specifies the type of ownership (TOwnerType) that applies. This is either:

  • EOwnerThread - the client ID is only used by the thread that registered the client to call the PRM APIs

  • EOwnerProcess - the client ID is used by all threads in the process to call the PRM APIs.

The default is EOwnerProcess.

Pre-allocating client level and request message objects

The controller has an initial pool of free client levels and request messages whose size can be configured at build time by the PSL. After registering with the PRM, a client can request the pre-allocation of a number of client levels and request messages to guarantee deterministic behaviour (to avoid out of memory failure) of the resource state change operation using PowerResourceManager::AllocReserve(). This allocation remains reserved to the specified client until the client is deregistered from the PRM. The number of client level objects reserved by a client depends on the number of resources on which a resource state change will be requested.

A client may issue more than one request, possibly to the same resource, before the previous one completes, it is therefore more difficult to determine how many objects to pre-allocate.

It is recommended that as many request messages as asynchronous long latency resources the client expects to use are pre-allocated. The free pool should be relied on for the situations when a resource is requested more than once before the first request completes.

Deregistration

All notifications and asynchronous requests must be cancelled before the client is deregistered, otherwise the kernel will panic. Use the PowerResourceManager::CancelNotification() and CancelAsyncRequestCallback() methods to cancel all pending notifications and asynchronous requests. Notifications that have been registered with the Controller should be deregistered before they are deleted as the Controller may attempt to issue them. Deleting a notification that is still registered with the Controller results in the kernel panicking.

Client level objects and request objects reserved by the client remain reserved for that client until it deregisters. When the client is deregistering these objects are moved to free pool by the PRM.

Client deregistration can result in a resource state change:

  • If the resource is shared and the deregistering client owned the prevailing level, the resource state is moved to the next level according to its sense. If it is a custom sense resource, the resource state is changed as a result of calling a custom function.

  • If the resource is not shared or if it is shared but the client is the only one using it at the time of deregistration, the resource is moved to the default state. The default state is only known by the PSL.

A deregistering client can have a number of active requirements on a number of resources and more than one of these resources may need to change state as a result of the client deregistering. The combined operation of deregistering the client and adjusting the state of all resources it shares executes synchronously. That is, the client thread is blocked throughout whether the resources whose state needs to change is instantaneous or long latency.

Getting power resource information

The resource information can be retrieved using the method PowerResourceManager::GetResourceInfo(), information can also be retrieved for all of the resources used by the specified client using GetInfoOnResourcesInUseByClient(). This function takes a buffer that must be the size of the information structure multipled by the number of resources in use by the client, this figure can be retrieved using the method GetNumResourcesInUseByClient(). Specify the resource ID as zero to retrieve all information from all the clients registered with PRM.

To get information about clients using a resource, use the method GetInfoOnClientsUsingResource(). Use the number of clients using a resource using GetNumClientsUsingResource(). Specify the client ID as zero to retrieve all information from all the resources registered with PRM.

Use PowerResourceManager::GetResourceState() to retrieve resource state information. This function can be called synchronously or asynchronously. Asynchronous calls require the client to create a callback object in the kernel heap or data section. The synchronous GetResourceState() call.

TInt GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TInt& aState, TInt& aLevelOwnerId);

The asynchronous GetResourceState() call.

TInt GetResourceState(TUint aClientId, TUint aResourceId, TBool aCached, TPowerResourceCb& aCb);

If executing asynchronously, the callback function encapsulated in the callback object (called in the client’s context) is invoked when the state of the resource is available. The third argument of the callback function carries the resource state. If this function is called with aCached set as ETrue, then the callback function is called in the context of the calling thread both for instantaneous and long latency resources, thus blocking the calling thread throughout.

For instantaneous resources, GetResourceState() executes in the context of the calling thread and, if specified, the callback function is called after getting the state of the requested resource. The calling thread is blocked throughout.

GetResourceState() takes a boolean value that determines from where the requested resource state information is retrieved:

  • ETrue - the resource state is the cached value, this value is returned faster but is not guaranteed to be correct

  • EFalse - the resource state is read from the resource, this value takes longer to return, but is much more likely to be correct.

Changing the state of power resources

The PowerResourceManager::ChangeResourceState() method is used to request a change on a resource. When a state change is requested on a shared resource, only the minimum state change that satisfies the request is guaranteed.

TInt ChangeResourceState(TUint aClientId, TUint aResourceId, TInt aNewState, TPowerResourceCb* aCb=NULL);

The values passed to the method are:

  • the ID of the client requesting the change

  • the ID of the resource that the change is to take place

  • the new state of the resource

  • a pointer to the resource callback object.

The requested state is either a binary value for a binary resource, an integer level for a multilevel resource or some platform specific token for a multi-property resource. The pointer to the callback object is defined by the class TPowerResourceCb; its use is optional and is treated by synchronous and asynchronous resources as described below.

Changing resource state on a long latency resource

If the callback object is specified, then ChangeResourceState() is executed asynchronously and returns immediately. The actual resource change happens in the resource controller thread and the callback function encapsulated in the callback object is called after the resource is changed.

If the callback object is NULL, then ChangeResourceState() executes synchronously, meaning the client thread is blocked until the resource state has changed. The PRM panics if the synchronous version of this API for long latency resources is called from DFC thread 0.

Changing resource state on an instantaneous resource

On an instantaneous resource ChangeResourceState() always executes synchronously.

If a callback object is specified, then the callback function encapsulated in the callback object is called from the client thread after the resource change and before returning from the function.

Use CancelAsyncRequestCallBack() to cancel change requests on a resource. When the client no longer requires a level on a resource use the method DeRegisterClientLevelFromResource() to remove a client level object from a resource.

Requesting notifications

Clients can request notification of a state change on a resource. Notifications are issued post resource change and invoke the callback function encapsulated in a notification object. The callback is executed in the context of the requesting client thread.

The parameters passed to PowerResourceManager::RequestNotification() are:

  • the ID of the client requesting the notification

  • the ID of the resource for which notification of state changes is being requested

  • a reference to a notification object encapsulating a callback function called whenever a resource state change takes place.

A notification may be unconditional or conditional. An unconditional notification request notifies the client each time the state changes. A conditional notification request notifies the client when a threshold has been met in the direction specified. A conditional notification has these additional parameters:

  • aThreshold - the level of the resource state that triggers the notification

  • aDirection - the direction the resource state change that triggers a notification:

    • EFalse - the resource state is equal to or below the threshold

    • ETrue - the resource state is equal to or above the threshold.

The client must create the notification object (DPowerResourceNotification) in the kernel heap or data section. Note: The client may share the same callback function between several notifications but a unique DFC must be created and queued for each notification.

Because notifications result in DFCs being queued, it is not possible to guarantee that all resource state changes are notified. If the resource state changes again, before the first DFC runs, it does not generate a separate notification. It is also not possible to guarantee that by the time the notification callback runs the resource state is still the same state that caused the notification to be issued. The client should read the resource state after receiving a notification.

Use CancelRequestNotification() to cancel a notification request. It takes a reference to the notification object associated with the original notification request that is being cancelled.