Cancel Safe IRP Queuing

Hi All,

The IRP returned by IoCsqRemoveNextIrp is in non-cancelable state, is
this correct?

In my driver, I serialize IRPs by implementing a cancel-safe IRP queue.
Later I call IoCsqRemoveNextIrp to process the IRPs one at a time.

An individual IRP processing itself takes a while, so I want the IRP to
be in cancelable state while under processing (after I retrieve the IRP
form the serializing queue using IoCsqRemoveNextIrp). Does that mean I
have to put the IRP on a separate queue while under processing?

I guess that also means considering the case where the IRP is cancelled
after I take it out from the serialization queue and before I put it on
the second queue. Is this analysis correct?

Thanks,
Bandeep

> The IRP returned by IoCsqRemoveNextIrp is in non-cancelable state, is

this correct?

I have never used the CSQ seriously so I can’t comment on this. (I used my
own bullet-proof queue since NT 3.xx). I am not surprised at all the IRP
becomes non-cancelable after being removed from the queue.

An individual IRP processing itself takes a while, so I want the IRP to
be in cancelable state while under processing (after I retrieve the IRP
form the serializing queue using IoCsqRemoveNextIrp). Does that mean I
have to put the IRP on a separate queue while under processing?

Since you already had a queue for IRP serialization, there is always at most
one IRP active at any given moment. Having another queue makes no sense.

I guess that also means considering the case where the IRP is cancelled
after I take it out from the serialization queue and before I put it on
the second queue. Is this analysis correct?

Since you want the IRP *ALWAYS* cancelable, there are more challenges I can
remember off head:

  1. As you mentioned
  2. Cancelled right after you setup a cancel routine but before you
    processing it.
  3. Cancelled when you are processing it.
  4. Cancelled when you are about to complete it.
  5. Your hardware may not able to cancel the request correctly and gives you
    normal completion signals. (This is GROSS)

Is your driver controlling a piece of hardware? I guess you want to do
IN-PROGRESS IRP cancellation. I had worked on a WDM driver that supports
aborting packet-base DMA transactions. It is quite tricky. You will have to
synchronize the code actually initiates the hardware I/O and the IN-PROGRESS
IRP cancel routine. You need to CAREFULLY test the cancel state when
installing an IN-PROGRESS cancel routine before you initiate the HW I/O. You
might have to execute some strange code in your cancel routine like this:

KeAcquireSpinLockXxx();
// No statement between Lock/Unlock; make sure the code following
// the Unlock() is not executed at a certain time frame.
KeReleaseSpinLockXxx();

Dealing with the race condition between IN-PROGRESS cancel routine and
normal completion (DpcForIsr) requires your H/W does exactly right on
canceling an I/O.

The code I’ve written works precisely at it’s supposed to be but I couldn’t
post it here since it’s owned by who paid for it-:slight_smile:

The bottom line is: canceling IN-PROGRESS I/O is the last thing you want
unless absolutely necessary.

If I’m not helpful enough here, please provide more details.

Good luck,
Calvin

Calvin Guan Software Engineer
ATI Technologies Inc. www.ati.com

xxxxx@wipro.com wrote:

The IRP returned by IoCsqRemoveNextIrp is in non-cancelable state, is
this correct?

Uh, yes. You are guaranteed that (a) the IRP was not cancelled prior to
its removal from the CSQ, and (b) there’s currently no active cancel
routine in the IRP.

An individual IRP processing itself takes a while, so I want the IRP to
be in cancelable state while under processing (after I retrieve the IRP
form the serializing queue using IoCsqRemoveNextIrp).

Bravo. Good for you. This is precisely the right thing to do (too many
folks ignore this).

Does that mean I
have to put the IRP on a separate queue while under processing?

Yes. Or somewhere.

One way to handle this: You can take the IRP off the CSQ you use for
pending IRPs, and put the IRP in a separate CSQ for “in progress” IRPs.
In this case, your “remove the IRP” or “complete the canceled IRP”
handler for your in progress IRPs will also have to deal with actually
cancelling the request on your hardware.

I guess that also means considering the case where the IRP is cancelled
after I take it out from the serialization queue and before I put it on
the second queue. Is this analysis correct?

YES! Exactly. But, note that the CSQ checks to see if the IRP you
insert into it has already been cancelled (for example, your IRP could
be cancelled between the time you remove it from the “pending” CSQ and
before you put in on your “in progress” CSQ.

Peter
OSR

Peter Viscarola (OSR) wrote:

YES! Exactly. But, note that the CSQ checks to see if the IRP you
insert into it has already been cancelled (for example, your IRP could
be cancelled between the time you remove it from the “pending” CSQ and
before you put in on your “in progress” CSQ.

…and if it HAS been cancelled, then what? IoCsqInsertIrp returns
“void”, so there’s no way for us to be notified. Does it complete the
IRP, so that it evaporates?

It is clearly a fabulous tool, but there are still some semantics of the
CSQ routines that elude me.

The CSQ will call your cancel routine inline in the call to
IoCsqInsertIrp. This means that if you grab a lock before calling
IoCsqInsertIrp, you cannot grap the same lock in your cancellation
routine. The lock / unlock functions that the IOCSQ call will work
properly, this only applies to locks acquire outside of those iocsq
function pointers.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, February 07, 2005 10:07 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Cancel Safe IRP Queuing

Peter Viscarola (OSR) wrote:

YES! Exactly. But, note that the CSQ checks to see if the IRP you
insert into it has already been cancelled (for example, your IRP could

be cancelled between the time you remove it from the “pending” CSQ and

before you put in on your “in progress” CSQ.

…and if it HAS been cancelled, then what? IoCsqInsertIrp returns
“void”, so there’s no way for us to be notified. Does it complete the
IRP, so that it evaporates?

It is clearly a fabulous tool, but there are still some semantics of the

CSQ routines that elude me.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@windows.microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

Thanks to Peter, Doron, Calvin and Tim.

Tim: I had the same question as yours after reading Peter’s mail. Doron
has answered that. Thanks again, Doron.

Calvin: I think at this point, if CSQ works as I understand, it should
suffice. I intentionally wanted to move away from using ‘Cancel’
routines. Thank you for offering to help.

Bandeep

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Doron Holan
Sent: Tuesday, February 08, 2005 3:24 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Cancel Safe IRP Queuing

The CSQ will call your cancel routine inline in the call to
IoCsqInsertIrp. This means that if you grab a lock before calling
IoCsqInsertIrp, you cannot grap the same lock in your cancellation
routine. The lock / unlock functions that the IOCSQ call will work
properly, this only applies to locks acquire outside of those iocsq
function pointers.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, February 07, 2005 10:07 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Cancel Safe IRP Queuing

Peter Viscarola (OSR) wrote:

YES! Exactly. But, note that the CSQ checks to see if the IRP you
insert into it has already been cancelled (for example, your IRP could

be cancelled between the time you remove it from the “pending” CSQ and

before you put in on your “in progress” CSQ.

…and if it HAS been cancelled, then what? IoCsqInsertIrp returns
“void”, so there’s no way for us to be notified. Does it complete the
IRP, so that it evaporates?

It is clearly a fabulous tool, but there are still some semantics of the

CSQ routines that elude me.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@windows.microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: unknown lmsubst tag argument:
‘’
To unsubscribe send a blank email to xxxxx@lists.osr.com

>An individual IRP processing itself takes a while, so I want the IRP to

be in cancelable state while under processing (after I retrieve the IRP
form the serializing queue using IoCsqRemoveNextIrp). Does that mean I
have to put the IRP on a separate queue while under processing?

Yes, and this will also need a proper cancel routine to properly undo the state
you put the IRP in.

Generally, it is a bad idea to have the cancellable IRP which already submitted
to the hardware, but I think USB stack provides this.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

> 5) Your hardware may not able to cancel the request correctly and gives you

normal completion signals. (This is GROSS)

BTW - I think that SERIAL sample code can be a sample of cancelling the IRP
which is already “on the hardware”.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Maxim S. Shatskih wrote:

>An individual IRP processing itself takes a while, so I want the IRP to
>be in cancelable state while under processing (after I retrieve the IRP
>form the serializing queue using IoCsqRemoveNextIrp). Does that mean I
>have to put the IRP on a separate queue while under processing?
>
>

Yes, and this will also need a proper cancel routine to properly undo the state
you put the IRP in.

Generally, it is a bad idea to have the cancellable IRP which already submitted
to the hardware, but I think USB stack provides this.

You know, this is a very good point. As a conscientious driver writer,
I think there is a tendencey to want to have IRPs cancellable at all
times, but that is not the right thing to do. If an IRP is waiting on
an operation that cannot sensibly be cancelled, or if an IRP is going to
be completed before control is transferred out of the driver, there is
no point in allowing for cancellation. It’s easy to waste a lot of time
and effort allowing for cancellation where it is not needed.

This is a corollary to the old saw, “never catch an exception you aren’t
prepared to handle”.

Tim Roberts wrote:

You know, this is a very good point. As a conscientious driver writer,
I think there is a tendencey to want to have IRPs cancellable at all
times, but that is not the right thing to do. If an IRP is waiting on
an operation that cannot sensibly be cancelled, or if an IRP is going to
be completed before control is transferred out of the driver, there is
no point in allowing for cancellation. It’s easy to waste a lot of time
and effort allowing for cancellation where it is not needed.

This is a corollary to the old saw, “never catch an exception you aren’t
prepared to handle”.

I pontificated on this once, I think.

The other case where it’s not necessary to cancel in-progress IRPs is
when you can GUARANTEE that the request you pass to your device will
complete “very quickly” (let’s say, oh, 3 seconds). You have to be able
to GUARANTEE this, not just THINK this is the case.

I actually talk about this at great length in our seminars. I suspect
there are at least as many errors (or more) caused by attempting to
handle cancel when it’s not necessary, as there are caused by legitimate
cancel cases.

Peter
OSR

In this particular case though, my driver initiates a request on the
driver stack below (USB stack). As the original request to my driver has
a rather large timeout associated with it, I need to be able to keep it
cancelable while I am waiting for the USB stack/device to finish
processing the request.

As Max pointed out, USB stack does provide for canceling previously
issued IRPs.

Thanks,
Bandeep

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Peter Viscarola
(OSR)
Sent: Thursday, February 10, 2005 4:29 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Cancel Safe IRP Queuing

Tim Roberts wrote:

You know, this is a very good point. As a conscientious driver
writer,
I think there is a tendencey to want to have IRPs cancellable at all
times, but that is not the right thing to do. If an IRP is waiting on

an operation that cannot sensibly be cancelled, or if an IRP is going
to
be completed before control is transferred out of the driver, there is

no point in allowing for cancellation. It’s easy to waste a lot of
time
and effort allowing for cancellation where it is not needed.

This is a corollary to the old saw, “never catch an exception you
aren’t
prepared to handle”.

I pontificated on this once, I think.

The other case where it’s not necessary to cancel in-progress IRPs is
when you can GUARANTEE that the request you pass to your device will
complete “very quickly” (let’s say, oh, 3 seconds). You have to be able

to GUARANTEE this, not just THINK this is the case.

I actually talk about this at great length in our seminars. I suspect
there are at least as many errors (or more) caused by attempting to
handle cancel when it’s not necessary, as there are caused by legitimate

cancel cases.

Peter
OSR


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@wipro.com
To unsubscribe send a blank email to xxxxx@lists.osr.com