One request at a time, please

While we have lots of documentation on MSDN, occasionally the high-level concepts get drowned out by all the details. Today I want to draw attention to an important point regarding OID requests.

Recall that protocols use OID requests to Query information from or to Set information on a miniport. (There’s slightly more to it than that, but that's not important right now). For example, a protocol might query the current interrupt moderation parameters by querying the miniport for OID_GEN_INTERRUPT_MODERATION.

Here’s the key point for today: a miniport will only ever have one outstanding OID request at a time. Even if the protocol issues a dozen OID requests, NDIS will step in and queue all but the first. The next request only goes down to the miniport once the previous request is completed.

A consequence of this design is that it’s perfectly legitimate for your miniport to stash a pointer to "the" pending OID request in its adapter context block. The stashed pointer comes in handy when debugging, since you can see whether or not your miniport thought it had a pending OID request.

Furthermore, you don’t need to worry about protecting your OID request path from two simultaneous requests. For example, you don’t have to worry about one request to Query the interrupt moderation parameters interfering with a hypothetical simultaneous Set request. (Of course, you still need to think about synchronizing your OID request path with other parts of your driver, like the datapath).

However, automatic serialization isn't "free". The downside is that you must not dawdle when completing OIDs. If you pend an OID request, all other OID requests will just pile up until that first request is completed. Since the user interface might be waiting for one of those queued OIDs, the user will notice if an OID is queued for too long. Additionally, NDIS reserves the right to reset your miniport if it detects that an OID appears to be stuck for too long. What’s a good rule of thumb? Think of 1 second as an upper bound on how long you can pend an OID request.

By the way, the above discussion also applies to filter instances: there is at most one pending OID request on a filter instance. Just as with miniports, filters should be quick to complete a pending OID.

Finally, note that today's discussion does not apply to Direct OID requests. This is intentional—in fact, one big motivation for Direct OIDs is to circumvent the one-OID-at-a-time limit. While "regular" OIDs are meant to be easy to use, Direct OIDs are meant to be fast and lightweight.