Multi-Queue or FindRequest - Which is better

I?m improving an HID filter driver that supports up to 15 Force Feedback (FFB) HID devices.
Each HID device is represented by a raw PDO (There is a single parent FDO device).
Its current architecture allows multiple DirectInput feeding applications, each sending its FFB data to one or more of the (raw PDO) HID devices.
There is also a ?Client? application that is receiving the FFB data and activates corresponding actuators.
The client gets a file handle to one of the raw devices like this:

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
h = CreateFile ( deviceInterfaceDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL, // no SECURITY_ATTRIBUTES structure
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Then, the client constantly reads the FFB data from the device using overlapped I/O operation:

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
do
{
// This is an async (overlapped) transaction
memset(&FfbOverlapped,0, sizeof(OVERLAPPED));
FfbOverlapped.hEvent = hIoctlEvent;
DeviceIoControl(h, GET_FFB_DATA, NULL, 0, &FfbData, IoSize, &bytes, &FfbOverlapped);
gotdata = GetOverlappedResult(h, &FfbOverlapped, &nBytesTranss, TRUE);
if (gotdata && nBytesTranss && nBytesTranss<=BUFFERSIZE && nBytesTranss>0)
FfbSendData(FfbData, nBytesTranss);
} while (nBytesTranss);
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

Data Flow inside the driver:
Every Request received at the filter device as IOCTL_HID_WRITE_REPORT IOCTL is requeued into a manual queue ?FfbWriteQueue?.
Whenever the overlapped operation has posted a Request on the manual queue ?FfbReadQueue?, the FFB data waiting on the ?FfbWriteQueue? is copied to the ?FfbReadQueue? and both requests are completed.

This works fine but the FFB data destined to different devices are mixed on the same queue.
As long as there is only one client application, this is not a problem since the destination of the FFB reports is marked on the reports. However, if there are several clients, I get a race.

Here?s my question:
Do you recommend creating 15 FfbReadQueue/FfbWriteQueus pairs - each one associated with the corresponding PDO - so that with every arriving request, it will be directed to the corresponding pair of queues.
OR
Use WdfIoQueueFindRequest on a single FfbReadQueue - exstracting the FFB request corresponding to the open file (=raw PDO).

I would suggest keeping it simple and creating 15 Read/Write pair of queues.

I vote with Mr. Gupta. 15 pairs of Queues. Easy to understand, test, document, and maintain. Marginally faster, even.

Peter
OSR
@OSRDrivers

I was hesitating to add 30 additional queues. Since you don’t seem to worry I’ll go for it. Thank you guys.

On Nov 21, 2014, at 10:56 PM, xxxxx@gmail.com wrote:

I was hesitating to add 30 additional queues. Since you don’t seem to worry I’ll go for it. Thank you guys.

Queues are lightweight and low on resources. If it makes for a better design to add 30 of them, then don’t hesitate. Do it.

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Why is this bad? A queue costs like 32-48 bytes and nothing else.

wrote in message news:xxxxx@ntdev…
>I was hesitating to add 30 additional queues. Since you don’t seem to worry I’ll go for it. Thank you guys.
>

A wdf queue is a bit bigger than that :slight_smile:

d

Bent from my phone


From: Maxim S. Shatskihmailto:xxxxx
Sent: ?11/?24/?2014 3:35 AM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: Re:[ntdev] Multi-Queue or FindRequest - Which is better

Why is this bad? A queue costs like 32-48 bytes and nothing else.

wrote in message news:xxxxx@ntdev…
>I was hesitating to add 30 additional queues. Since you don’t seem to worry I’ll go for it. Thank you guys.
>


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer</mailto:xxxxx></mailto:xxxxx>

I was not worried about bytes. My computer is not an Intel 8088 anymore and we are all out of the 64K boundaries. I was not sure there weren’t limitation on the queue COUNT and that the penalty on creating and initializing 30 queues was not tangible. I now understand it is not.

Here is a follow up question.
Now that I have 30 queues, do I need to register 30 notification callback functions? It sounds a bad idea to have so many functions that defer only in the queue object index. However, I cannot find a way to pass the index to the function when it is being called.
I can of course loop through the queues to see which one is ready, but this will be inefficient. Raising a per-queue flag is also possible but adds additional complexity as I have to create a synchronization mechanism.
Any addional ideas?
Thank you all.

On Nov 27, 2014, at 11:33 AM, xxxxx@gmail.com wrote:

Here is a follow up question.
Now that I have 30 queues, do I need to register 30 notification callback functions? It sounds a bad idea to have so many functions that defer only in the queue object index. However, I cannot find a way to pass the index to the function when it is being called.
I can of course loop through the queues to see which one is ready, but this will be inefficient. Raising a per-queue flag is also possible but adds additional complexity as I have to create a synchronization mechanism.

Why do you need an index? The queue itself gets passed to the callback function. You can add a context to each queue to contain whatever queue-specific information you need, exactly like you add a context to your WDFDEVICE.

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I totally forgot that a WDF queue is a framework object, which means it may have a context space.
I’m going to allocate a context space when creating each queue (It is going to hold the queue index and whether it is a Read or Write queue). It will then be initialized.
Assigning a single notification callback function to all queues will be sufficient as I can access context space of the passed queue and extract its index.
Sounds quite straightforward.
Thank you very much Tim!