While KMDF is a great approach to writing drivers, not much new and exciting has happened to it since V1.0 was introduced in December of 2005. A few small bugs fixed, it's faster, and a few minor additional functions have been added.
KMDF V1.9, which shipped with the Windows 7 WDK, introduced more new features than any other update to KMDF. While none of the new functionality is exactly revolutionary, all of it is most welcome, and a few, new features in particular, promise to make life easier for us developers. One such feature is the addition of "Counted Queues." And it's that feature that we'll be exploring in this article.
Remember, all the features of KMDF V1.9 are available on all platforms onto which you install your KMDF driver. The KMDF wrapper library is redistributed automatically as part of the WDF co-installer. So, even though features might be restricted to KMDF V1.9, the version of KMDF available is dictated by your driver and its installation process and not by the underlying OS version.
If you're familiar with KMDF, you know that WDF Requests arrive at your driver via one or more upper edge WDF Queues that you define. These queues are used to organize and control the delivery of requests to your driver. Prior to KMDF V1.9, the number of requests that are presented simultaneously from a queue to your driver was defined solely by the Queue's dispatch type. You had two choices:
- WdfIoQueueDispatchSequential -- One request is presented from the queue to your driver. When your driver completes the handling of that one request, a new request is presented.
- WdfIoQueueDispatchParallel -- An unlimited number of requests are presented from the queue to your driver.
This design provides you with all the flexibility that you really need: If your driver can only handle a single request at a time from a particular queue, you make the queue Sequential. On the other hand, if your driver can handle multiple requests simultaneously from a particular queue, you set the dispatch type to Parallel.
The only difficulty with this approach is for those drivers that want something more than one and but less than an unlimited number of requests. For example, suppose (due to space, throughput, device architecture, or other constraints) you want keep as many as five requests in progress simultaneously from a given queue, but never more than five. While prior to V1.9 you could write your own code to handle this situation using a queue that's been configured for Parallel dispatching, the overhead involved was not be optimal. The good news is that KMDF V1.9 eliminates the requirement for you to roll your own, and adds support for Counted Queues.
A Parallel Queue with a Maximum
Counted queues introduce the concept of a maximum number of requests that can be in progress simultaneously from a parallel queue. Thus, you configure the dispatch type for the queue to be parallel (WdfIoQueueDispatchParallel), and before creating the queue, you fill-in the WDF_IO_QUEUE_CONFIG structure's Settings.Parallel.NumberOfPresentedRequests field with the maximum number of WDF Requests you allow to be presented by the queue simultaneously. The code that does this is shown below.
// Configure our queue of incoming requests
// We'll take 2 requests at a time, thank you.
// Declare our I/O Event Processing callbacks
// We handle, read, write, and device control requests.
queueConfig.EvtIoRead = NothingEvtRead;
queueConfig.EvtIoWrite = NothingEvtWrite;
queueConfig.EvtIoDeviceControl = NothingEvtDeviceControl;
// Because this is a queue for a software-only device, indicate
// that the queue doesn't need to be power managed
queueConfig.PowerManaged = WdfFalse;
status = WdfIoQueueCreate(device,
NULL); // optional pointer to receive queue handle
In Figure 1, you can see the driver initializes its default queue to use dispatch type Parallel in the usual way, using the WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE macro. It then sets the maximum number of requests that will be presented by the queue at one time to NOTHING_REQUESTS_IN_PROGRESS (which happens to be defined as 2 in this example). After configuring Event Processing Callbacks and indicating that the queue state is not to be altered by changes in device power state, the driver creates the queue by calling WdfIoQueueCreate.
Once the queue is created, you're all set! KMDF will present request from the queue to your driver until the maximum number of in-progress requests has been reached.
The only caveat to note is that the maximum number of in-progress requests is configured via the WDF_IO_QUEUE_ CONFIG structure. This means that the maximum number of in-progress requests can be varied dynamically by your driver. It's a configuration parameter that's set when the WDF Queue is created, not a dynamically changeable attribute.
Defining In Progress Requests
In order to fully understand Counted Queues, it's important to understand what comprises a presented "in progress request" in terms of KMDF. The rules for in-progress requests for a Counted Queue are the same as those for a queue configured for Sequential dispatching. Sequential Dispatching is, after all, entirely equivalent to Counted Queues with a Settings.Parallel.NumberOfPresentedRequests set to 1.
When a request is presented by a KMDF Queue, that request is considered to be "in-progress" until one of the following three things occurs:
- The Request is completed by the driver, by calling WdfRequestComplete (or one of the similar functions).
- The Request is forwarded to another Queue within the driver using WdfRequestForwardToIoQueue (or similar).
- The Request is sent to another device/driver in the system using WdfRequestSend, specifying the WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET flag in the WDF_REQUEST_SEND_ OPTIONS structure Flags field.
So, a request remains "in progress" until it's been completed, it's been put on another queue, or it's been sent away by the driver using "send and forget." Simple, right?
Yup, It Really IS That Easy
As with most things in KMDF, this really is as simple as it seems. Now that's something that you don't normally hear when talking about Windows drivers! If you haven't tried KMDF yet, you really must give it a try. If you're already an experienced KMDF driver writer, keep the idea of Counted Queues in the back of your mind. It's not the sort of feature you'll use in every driver, but when you do have a need for it, you'll be glad it's there.