How is synchronization b/w completion/cancel routine taken care of in kmdf?

Hi,

On WDM, driver when it is about to complete an IRP, it can clear the cancel routine using:

IoAcquireCancelSpinLock(&CancelIrql);
IoSetCancelRoutine(pIrp, NULL);
IoReleaseCancelSpinLock(CancelIrql);

before calling CompleteRequest and take care of synchronizing cancel/complete operation.

How should this be acheived in KMDF code?

I see the following in WDK:

QUOTE
Windows Driver Kit: Kernel-Mode Driver Framework

Synchronizing Cancel and Completion Code
[This is preliminary documentation and subject to change.]

If your driver and device perform device I/O operations asynchronously by means of EvtInterruptIsr and EvtInterruptDpc callback functions, and if the driver calls WdfRequestMarkCancelable to make an I/O request cancelable, there is potential for a synchronization problem if both the EvtInterruptDpc and EvtRequestCancel callback functions contain calls to WdfRequestComplete.

The driver must call WdfRequestComplete only once, to either complete or cancel the request. But if the EvtInterruptDpc and EvtRequestCancel callback functions are not synchronized with each other, the framework can call one while the other is executing. Avoiding this problem is easy if your driver uses the framework’s automatic synchronization, which ensures that the callback functions will be called one at a time.

If the driver uses framework’s automatic synchronization, its EvtRequestCancel callback function can call WdfRequestComplete to cancel a request. The driver’s EvtInterruptDpc callback function should use the following code:

Status = WdfRequestUnmarkCancelable(Request);
if( Status != STATUS_CANCELLED ) {
WdfRequestComplete(Request, RequestStatus);

This code ensures that the driver does not call WdfRequestComplete to complete the request if the driver has already called it to cancel the request.

If your driver calls WdfRequestMarkCancelable to register an EvtRequestCancel callback function, and if your driver uses the framework’s automatic synchronization,

? 2005 Microsoft Corporation
Send feedback on this topic
Built on September 23, 2005

UNQUOTE

To make use of this automatic synchronization from framework, should I be specifying:

WdfSynchronizationScopeDevice?
Will that take care of resolving possible race condition b/w completion routine and cancel routine both being asynchronous?

At present I am using WdfSynchronizationScopeNone (not using any synchronization scope).

Regds,
-Praveen

Regds,
-Praveen

Incase I do not want to use “automatic synchronization” and provide code like the following would it work:

EvtRequestCancel()
{

pReqCtxt = GetReqContext(Request);
ACQUIRE_LOCK (driver lock);
if (pReqCtxt->CompleteFlag)
{
// EvtRequestcompletion() routine is executing and will take care of this IRP completion. Just return;
RELEASE_LOCK();
return;
}
else
{
pReqCtxt->CompleteFlag = 1;
RELEASE_LOCK();
WdfRequestComplete (…, STATUS_CANCELLED);
}
return;
}

EvtRequestCompletion()
{
pReqCtxt = GetReqContext(Request);

if (pReqCtxt == NULL)
return; // Cancel routine got exeucted before us and has returned.

ACQUIRE_LOCK (driver lock);
if (pReqCtxt->CompleteFlag)
{
// EvtRequestcompletion() routine is executing and will take care of this IRP completion. Just return;
RELEASE_LOCK();
return;
}
else
{
pReqCtxt->CompleteFlag = 1;
RELEASE_LOCK();
status = WdfRequestUnmarkCancelable (Request);
if (SUCCESS)
WdfRequestComplete (…, STATUS_XYZ);
}
return;
}

Will this work?
What if EvtRequestCancel gets called and executes and returns.
After sometime my driver EvtRequestCompletion tries to execute… In this case when EvtRequestCompletion() executes,
would pReqCtxt() contain any valid data if EvtRequestcancel had already completed exeuction and the Request?

Regds,

“Praveen Kumar Amritaluru” wrote in message news:xxxxx@ntdev…
Hi,

On WDM, driver when it is about to complete an IRP, it can clear the cancel routine using:

IoAcquireCancelSpinLock(&CancelIrql);
IoSetCancelRoutine(pIrp, NULL);
IoReleaseCancelSpinLock(CancelIrql);

before calling CompleteRequest and take care of synchronizing cancel/complete operation.

How should this be acheived in KMDF code?

I see the following in WDK:

QUOTE
Windows Driver Kit: Kernel-Mode Driver Framework

Synchronizing Cancel and Completion Code
[This is preliminary documentation and subject to change.]

If your driver and device perform device I/O operations asynchronously by means of EvtInterruptIsr and EvtInterruptDpc callback functions, and if the driver calls WdfRequestMarkCancelable to make an I/O request cancelable, there is potential for a synchronization problem if both the EvtInterruptDpc and EvtRequestCancel callback functions contain calls to WdfRequestComplete.

The driver must call WdfRequestComplete only once, to either complete or cancel the request. But if the EvtInterruptDpc and EvtRequestCancel callback functions are not synchronized with each other, the framework can call one while the other is executing. Avoiding this problem is easy if your driver uses the framework’s automatic synchronization, which ensures that the callback functions will be called one at a time.

If the driver uses framework’s automatic synchronization, its EvtRequestCancel callback function can call WdfRequestComplete to cancel a request. The driver’s EvtInterruptDpc callback function should use the following code:

Status = WdfRequestUnmarkCancelable(Request);
if( Status != STATUS_CANCELLED ) {
WdfRequestComplete(Request, RequestStatus);

This code ensures that the driver does not call WdfRequestComplete to complete the request if the driver has already called it to cancel the request.

If your driver calls WdfRequestMarkCancelable to register an EvtRequestCancel callback function, and if your driver uses the framework’s automatic synchronization,

? 2005 Microsoft Corporation
Send feedback on this topic
Built on September 23, 2005

UNQUOTE

To make use of this automatic synchronization from framework, should I be specifying:

WdfSynchronizationScopeDevice?
Will that take care of resolving possible race condition b/w completion routine and cancel routine both being asynchronous?

At present I am using WdfSynchronizationScopeNone (not using any synchronization scope).

Regds,
-Praveen

Regds,
-Praveen

The WDF/KMDF contract on cancellation goes like this:

  1. All requests are cancelable before they are presented to the driver. So
    if a request is in the default queue or a queue you have forwarded it to, it
    is cancelable. (Because of this, I prefer not to store partially processed
    requests in WDFQUEUEs. I prefer to put them on lists that I manually
    manage.)

  2. When a request is presented to the driver, it is not cancelable.

  3. If a driver wishes to make a presented request cancelable, it can call
    WdfRequestMarkCancelable. After this point, your cancel routine may be
    invoked. This should be done for any request that has a long or
    indeterminate completion time, like the event-signalling requests that you
    described.

  4. If you want to make a cancelable presented request uncancelable again,
    you call WdfRequestUnmarkCancelable. This can fail. If it does, your
    cancel routine either will be run, is running currently, or has already run.
    (In this case, the request has been cancelled by the sender.) If
    WdfRequestUnmarkCancelable succeeds, your cancel routine will not be run.
    You may not call WdfRequestUnmarkCancelable after the request has been
    completed by the cancel routine, which unfortunately pushes some state
    management onto you.

  5. You may not complete a cancelable request. If your operation finishes,
    you must call WdfRequestUnmarkCancelable before you complete the request.
    This eliminates the race between your normal completion path and your
    cancellation path.

It is possible to set callbacks on WDFQUEUEs that are invoked when a request
in the queue is cancelled. I prefer not to use these, as they complicate
the contract described above.

  • Jake Oshins
    Windows Kernel Team

“Praveen Kumar Amritaluru” wrote in message
news:xxxxx@ntdev…
Hi,

On WDM, driver when it is about to complete an IRP, it can clear the cancel
routine using:

IoAcquireCancelSpinLock(&CancelIrql);
IoSetCancelRoutine(pIrp, NULL);
IoReleaseCancelSpinLock(CancelIrql);

before calling CompleteRequest and take care of synchronizing
cancel/complete operation.

How should this be acheived in KMDF code?

I see the following in WDK:

QUOTE
Windows Driver Kit: Kernel-Mode Driver Framework

Synchronizing Cancel and Completion Code
[This is preliminary documentation and subject to change.]

If your driver and device perform device I/O operations asynchronously by
means of EvtInterruptIsr and EvtInterruptDpc callback functions, and if the
driver calls WdfRequestMarkCancelable to make an I/O request cancelable,
there is potential for a synchronization problem if both the EvtInterruptDpc
and EvtRequestCancel callback functions contain calls to WdfRequestComplete.
The driver must call WdfRequestComplete only once, to either complete or
cancel the request. But if the EvtInterruptDpc and EvtRequestCancel callback
functions are not synchronized with each other, the framework can call one
while the other is executing. Avoiding this problem is easy if your driver
uses the framework’s automatic synchronization, which ensures that the
callback functions will be called one at a time.
If the driver uses framework’s automatic synchronization, its
EvtRequestCancel callback function can call WdfRequestComplete to cancel a
request. The driver’s EvtInterruptDpc callback function should use the
following code:
Status = WdfRequestUnmarkCancelable(Request);
if( Status != STATUS_CANCELLED ) {
WdfRequestComplete(Request, RequestStatus);

This code ensures that the driver does not call WdfRequestComplete to
complete the request if the driver has already called it to cancel the
request.
If your driver calls WdfRequestMarkCancelable to register an
EvtRequestCancel callback function, and if your driver uses the framework’s
automatic synchronization,

© 2005 Microsoft Corporation
Send feedback on this topic
Built on September 23, 2005

UNQUOTE

To make use of this automatic synchronization from framework, should I be
specifying:

WdfSynchronizationScopeDevice?
Will that take care of resolving possible race condition b/w completion
routine and cancel routine both being asynchronous?

At present I am using WdfSynchronizationScopeNone (not using any
synchronization scope).

Regds,
-Praveen

Regds,
-Praveen

Thanks Jake.

Steps #3 and #5 are currently being done.

Incase of step #4, I am calling WdfRequestUnmarkCancelable but not checking
the return status
though intended to do so.That I need to do now. Add 2 lines of code.

Can you pls elaborate on what you mean by:

You may not call WdfRequestUnmarkCancelable after the request has been
completed by the cancel routine, which unfortunately pushes some state
management onto you.

Assuming that cancel routine completed the request, will the contents of
request context and request become unusable by my driver?

Thanks,
-Praveen

“Jake Oshins” wrote in message
news:xxxxx@ntdev…
> The WDF/KMDF contract on cancellation goes like this:
>
> 1) All requests are cancelable before they are presented to the driver.
> So if a request is in the default queue or a queue you have forwarded it
> to, it is cancelable. (Because of this, I prefer not to store partially
> processed requests in WDFQUEUEs. I prefer to put them on lists that I
> manually manage.)
>
> 2) When a request is presented to the driver, it is not cancelable.
>
> 3) If a driver wishes to make a presented request cancelable, it can call
> WdfRequestMarkCancelable. After this point, your cancel routine may be
> invoked. This should be done for any request that has a long or
> indeterminate completion time, like the event-signalling requests that you
> described.
>
> 4) If you want to make a cancelable presented request uncancelable again,
> you call WdfRequestUnmarkCancelable. This can fail. If it does, your
> cancel routine either will be run, is running currently, or has already
> run. (In this case, the request has been cancelled by the sender.) If
> WdfRequestUnmarkCancelable succeeds, your cancel routine will not be run.
> You may not call WdfRequestUnmarkCancelable after the request has been
> completed by the cancel routine, which unfortunately pushes some state
> management onto you.
>
> 5) You may not complete a cancelable request. If your operation
> finishes, you must call WdfRequestUnmarkCancelable before you complete the
> request. This eliminates the race between your normal completion path and
> your cancellation path.
>
> It is possible to set callbacks on WDFQUEUEs that are invoked when a
> request in the queue is cancelled. I prefer not to use these, as they
> complicate the contract described above.
>
> - Jake Oshins
> Windows Kernel Team
>
>
> “Praveen Kumar Amritaluru” wrote in message
> news:xxxxx@ntdev…
> Hi,
>
> On WDM, driver when it is about to complete an IRP, it can clear the
> cancel routine using:
>
> IoAcquireCancelSpinLock(&CancelIrql);
> IoSetCancelRoutine(pIrp, NULL);
> IoReleaseCancelSpinLock(CancelIrql);
>
> before calling CompleteRequest and take care of synchronizing
> cancel/complete operation.
>
>
> How should this be acheived in KMDF code?
>
> I see the following in WDK:
>
> QUOTE
> Windows Driver Kit: Kernel-Mode Driver Framework
>
> Synchronizing Cancel and Completion Code
> [This is preliminary documentation and subject to change.]
>
>
> If your driver and device perform device I/O operations asynchronously by
> means of EvtInterruptIsr and EvtInterruptDpc callback functions, and if
> the driver calls WdfRequestMarkCancelable to make an I/O request
> cancelable, there is potential for a synchronization problem if both the
> EvtInterruptDpc and EvtRequestCancel callback functions contain calls to
> WdfRequestComplete.
> The driver must call WdfRequestComplete only once, to either complete or
> cancel the request. But if the EvtInterruptDpc and EvtRequestCancel
> callback functions are not synchronized with each other, the framework can
> call one while the other is executing. Avoiding this problem is easy if
> your driver uses the framework’s automatic synchronization, which ensures
> that the callback functions will be called one at a time.
> If the driver uses framework’s automatic synchronization, its
> EvtRequestCancel callback function can call WdfRequestComplete to cancel a
> request. The driver’s EvtInterruptDpc callback function should use the
> following code:
> Status = WdfRequestUnmarkCancelable(Request);
> if( Status != STATUS_CANCELLED ) {
> WdfRequestComplete(Request, RequestStatus);
>
>
> This code ensures that the driver does not call WdfRequestComplete to
> complete the request if the driver has already called it to cancel the
> request.
> If your driver calls WdfRequestMarkCancelable to register an
> EvtRequestCancel callback function, and if your driver uses the
> framework’s automatic synchronization,
>
> © 2005 Microsoft Corporation
> Send feedback on this topic
> Built on September 23, 2005
>
> UNQUOTE
>
>
> To make use of this automatic synchronization from framework, should I be
> specifying:
>
> WdfSynchronizationScopeDevice?
> Will that take care of resolving possible race condition b/w completion
> routine and cancel routine both being asynchronous?
>
> At present I am using WdfSynchronizationScopeNone (not using any
> synchronization scope).
>
> Regds,
> -Praveen
>
>
>
>
>
>
>
> Regds,
> -Praveen
>
>

Remember that if UnmarkCancelable has return failure, it means that
someone else might be completing the request out from underneath you.
You need to provide sufficient locking so that you know when you call
UnmarkCancelable that the request will not be completed while making the
call.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Praveen Kumar
Amritaluru
Sent: Tuesday, November 28, 2006 12:37 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] How is synchronization b/w completion/cancel routine
taken care of in kmdf?

Thanks Jake.

Steps #3 and #5 are currently being done.

Incase of step #4, I am calling WdfRequestUnmarkCancelable but not
checking
the return status
though intended to do so.That I need to do now. Add 2 lines of code.

Can you pls elaborate on what you mean by:

You may not call WdfRequestUnmarkCancelable after the request has been

completed by the cancel routine, which unfortunately pushes some state

management onto you.

Assuming that cancel routine completed the request, will the contents of

request context and request become unusable by my driver?

Thanks,
-Praveen

“Jake Oshins” wrote in message
news:xxxxx@ntdev…
> The WDF/KMDF contract on cancellation goes like this:
>
> 1) All requests are cancelable before they are presented to the
driver.
> So if a request is in the default queue or a queue you have forwarded
it
> to, it is cancelable. (Because of this, I prefer not to store
partially
> processed requests in WDFQUEUEs. I prefer to put them on lists that I

> manually manage.)
>
> 2) When a request is presented to the driver, it is not cancelable.
>
> 3) If a driver wishes to make a presented request cancelable, it can
call
> WdfRequestMarkCancelable. After this point, your cancel routine may
be
> invoked. This should be done for any request that has a long or
> indeterminate completion time, like the event-signalling requests that
you
> described.
>
> 4) If you want to make a cancelable presented request uncancelable
again,
> you call WdfRequestUnmarkCancelable. This can fail. If it does, your

> cancel routine either will be run, is running currently, or has
already
> run. (In this case, the request has been cancelled by the sender.) If

> WdfRequestUnmarkCancelable succeeds, your cancel routine will not be
run.
> You may not call WdfRequestUnmarkCancelable after the request has been

> completed by the cancel routine, which unfortunately pushes some state

> management onto you.
>
> 5) You may not complete a cancelable request. If your operation
> finishes, you must call WdfRequestUnmarkCancelable before you complete
the
> request. This eliminates the race between your normal completion path
and
> your cancellation path.
>
> It is possible to set callbacks on WDFQUEUEs that are invoked when a
> request in the queue is cancelled. I prefer not to use these, as they

> complicate the contract described above.
>
> - Jake Oshins
> Windows Kernel Team
>
>
> “Praveen Kumar Amritaluru” wrote in message

> news:xxxxx@ntdev…
> Hi,
>
> On WDM, driver when it is about to complete an IRP, it can clear the
> cancel routine using:
>
> IoAcquireCancelSpinLock(&CancelIrql);
> IoSetCancelRoutine(pIrp, NULL);
> IoReleaseCancelSpinLock(CancelIrql);
>
> before calling CompleteRequest and take care of synchronizing
> cancel/complete operation.
>
>
> How should this be acheived in KMDF code?
>
> I see the following in WDK:
>
> QUOTE
> Windows Driver Kit: Kernel-Mode Driver Framework
>
> Synchronizing Cancel and Completion Code
> [This is preliminary documentation and subject to change.]
>
>
> If your driver and device perform device I/O operations asynchronously
by
> means of EvtInterruptIsr and EvtInterruptDpc callback functions, and
if
> the driver calls WdfRequestMarkCancelable to make an I/O request
> cancelable, there is potential for a synchronization problem if both
the
> EvtInterruptDpc and EvtRequestCancel callback functions contain calls
to
> WdfRequestComplete.
> The driver must call WdfRequestComplete only once, to either complete
or
> cancel the request. But if the EvtInterruptDpc and EvtRequestCancel
> callback functions are not synchronized with each other, the framework
can
> call one while the other is executing. Avoiding this problem is easy
if
> your driver uses the framework’s automatic synchronization, which
ensures
> that the callback functions will be called one at a time.
> If the driver uses framework’s automatic synchronization, its
> EvtRequestCancel callback function can call WdfRequestComplete to
cancel a
> request. The driver’s EvtInterruptDpc callback function should use the

> following code:
> Status = WdfRequestUnmarkCancelable(Request);
> if( Status != STATUS_CANCELLED ) {
> WdfRequestComplete(Request, RequestStatus);
>
>
> This code ensures that the driver does not call WdfRequestComplete to
> complete the request if the driver has already called it to cancel the

> request.
> If your driver calls WdfRequestMarkCancelable to register an
> EvtRequestCancel callback function, and if your driver uses the
> framework’s automatic synchronization,
>
> (c) 2005 Microsoft Corporation
> Send feedback on this topic
> Built on September 23, 2005
>
> UNQUOTE
>
>
> To make use of this automatic synchronization from framework, should I
be
> specifying:
>
> WdfSynchronizationScopeDevice?
> Will that take care of resolving possible race condition b/w
completion
> routine and cancel routine both being asynchronous?
>
> At present I am using WdfSynchronizationScopeNone (not using any
> synchronization scope).
>
> Regds,
> -Praveen
>
>
>
>
>
>
>
> Regds,
> -Praveen
>
>


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

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