Canceled and Suspended Requests


Windows I/O is inherently asynchronous and reentrant. The system can request that a driver stop processing an I/O request at any time for many reasons, most commonly:

  • The thread or process that issued the request cancels it or exits.

  • A system Plug and Play or power event such as hibernation occurs.

  • The device is being, or has been, removed.

The actions that a driver takes to stop processing an I/O request depend on the reason for suspension or cancellation. Usually, the driver can either cancel the request or complete it with an error. In some situations, the system might request that a driver suspend (that is, temporarily pause) processing; the system notifies the driver later when to resume processing.

To provide a good user experience, drivers should provide callbacks to handle cancellation and suspension of any I/O request that might take a long time to complete or that might not complete within a fixed period of time, such as a request for asynchronous input.

Request Cancellation

The actions that WDF takes to cancel an I/O request depend on whether the request has already been delivered to the target driver:

  • If the request has never been delivered-either because the framework has not yet queued it or because it is still in a queue, the framework cancels or suspends it automatically without notifying the driver.

    If the original I/O request has been canceled, the framework completes the request with a cancellation status.

  • If the request has been delivered but the driver forwards it to a different queue, the framework automatically cancels the request without notifying the driver.

    KMDF drivers can receive notification by registering an EvtIoCanceledOnQueue callback for the queue.

    UMDF drivers cannot receive this type of notification.

  • If the request has been delivered and is owned by the driver, the framework does not cancel it.

    However, if the driver explicitly marks the request cancelable and registers a cancellation callback, the framework notifies the driver that the request was canceled. In its callback, the driver should complete the request or should arrange for it to complete quickly.

To mark a request cancelable or uncancelable:

  • A UMDF driver calls the request object's IWDFIoRequest::MarkCancelable or IWDFIoRequest::UnmarkCancelable method.

  • A KMDF driver calls WdfRequestMarkCancelable or WdfRequestUnmarkCancelable.

When a driver marks a request cancelable, it passes an I/O cancel callback that the framework calls if the request is canceled.

Drivers must not leave requests in the noncancelable state for long periods of time. A driver should mark a request cancelable and register an I/O cancellation callback if either of the following conditions is true:

  • The request involves a long-term operation.

  • The request might never succeed, for example, if the request is waiting for synchronous input.

The I/O cancel callback must perform any tasks that are required to cancel the request, such as stopping any device I/O operations that are in progress and canceling any related requests that it has already forwarded to an I/O target. Eventually, the driver must complete the request with one of the following status values:

  • UMDF drivers complete the request with ERROR_OPERATION_ABORTED if the request was canceled before it completed successfully or S_OK if it completed successfully despite the cancellation.

  • KMDF drivers complete the request with STATUS_CANCELLED if the request was canceled before it completed successfully or STATUS_SUCCESS if it completed succssfully despite the cancellation.

Requests that a driver has marked cancelable cannot be forwarded to another queue. Before requeuing a request, the driver must first make it noncancelable. After the request has been added to the new queue, the framework again considers it cancelable until that queue dispatches it to the driver.

To properly implement request cancellation, you must pay careful attention to race conditions between the code in the normal request completion path and the code in the request cancellation path. The framework's synchronization techniques can help to simplify cancellation.

Chapter 10, "Synchronization," includes more information on synchronization techniques for request cancellation.

image from book
Another Way to Look at Mark and Unmark

When a driver marks a request as cancelable, it gives up ownership of the request to the cancel routine, which could run at any time and complete the request. The driver routine that completes the request must regain ownership before it can complete the request or forward it to another queue. The unmark-cancelable methods regain ownership of the request for the driver from the cancel routine. The driver must call an unmark-cancelable method and check for success before the driver performs any operations on the request such as completing it or forwarding it to another queue.

image from book

 KMDF   KMDF provides a way for a driver to determine whether a request has been canceled even if the driver has not marked it cancelable. If the driver does not mark a request cancelable, it can call WdfRequestIsCanceled to determine whether the I/O manager or original requester has attempted to cancel the request. A driver that processes data on a periodic basis might use this method. For example, a driver involved in image processing might complete a transfer request in small chunks and poll for cancellation after processing each chunk. In this case, the driver supports cancellation of the I/O request, but only after each discrete chunk of processing is complete. If the driver determines that the request has been canceled, it performs any required cleanup and completes the request with the status STATUS_CANCELLED.

Chapter 9, "I/O Targets," includes information about canceling I/O requests that your driver sent to an I/O target.

Table 8-15 summarizes the framework actions when a request is canceled.

Table 8-15: Framework Handling of Request Cancellation
Open table as spreadsheet

When cancellation occurs

The framework

Before the request has ever been delivered to the driver

Cancels the request. No driver code is required, and no notification is sent to the driver.

While the request is in a queue but after it has been delivered to the driver, which could occur if the driver receives an I/O request and then requeues it

Cancels the request. No driver code is required, and no notification is sent to the driver.

If a KMDF driver has registered an EvtIoCanceledOnQueue callback for the queue, invokes this callback, and then cancels the request; otherwise, cancels the request as described above. (KMDF only)

While the driver owns the request

If the driver has marked the request cancelable, calls the cancel callback that the driver registered for the request.

If the driver has not marked the request cancelable, does nothing.

The driver can call WdfRequestIsCanceled to find out whether the request has been canceled. (KMDF only)

Tip 

Chapter 24, "Static Driver Verifier," describes how to annotate your driver's callback functions so that SDV can analyze compliance with KMDF rules for request completion and request cancellation.

Request Suspension

When the device transitions to a low-power state-often because the user has requested hibernation or closed the lid on a laptop-a driver can complete, requeue, or continue to hold any requests that it is currently processing.

A driver can implement an I/O stop callback to be notified in case of such power changes:

  • UMDF notifies the driver of the impending power change by calling the queue callback object's IQueueCallbackIoStop::OnIoStop method for each such request.

  • KMDF notifies the driver of the impending power change by calling the EvtIoStop callback for each such request.

Each call includes flags that indicate the reason for stopping the queue and whether the I/O request is currently cancelable. Depending on the value of the flags, the driver can:

  • Complete the request.

  • Requeue the request.

  • Ignore the notification if the current request will complete in a timely manner.

  • Acknowledge the notification but continue to hold the request. (KMDF only)

If the queue is stopping because the device is being removed, the driver should complete the request as soon as possible. After the framework calls the I/O stop callbacks, device removal processing blocks until all driver-owned requests are complete.

Drivers should implement the I/O stop callback for any request that might take a long time to complete or that might not complete. For example, if your driver forwards requests to an I/O target, those requests could remain pending at the target for some time. You should implement an I/O stop callback for the queue that dispatched the request to the driver. Managing I/O requests in preparation for power-down provides a good user experience for laptops and other power-managed systems.




Developing Drivers with the Microsoft Windows Driver Foundation
Developing Drivers with the Windows Driver Foundation (Pro Developer)
ISBN: 0735623740
EAN: 2147483647
Year: 2007
Pages: 224

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