none
Synchronizing timers cancellation in NDIS driver RRS feed

  • Question

  • Hi,

    I've encountered the following problem:

    During handling of MiniportHaltEx I need to cancel multiple non-periodic timers that are being used be various driver components. The standard handling goes like this:

    • Call NdisCancelTimerObject for the specific timer
    • Call NdisFreeTimerObject
    • Free other context-related stuff
    • Continue to halting the next module (which might contain timers as well).

    Obviously, there is an inherent race in such flow - there is a possiblity that timer handler was already added to the DPCs queue before timer cancellation. So once the handler starts executing, I encounter a context that is already freed. MSDN suggests using a separate synchronization mechanism, so that the caller will wait for signalling from timer handler on execution completion. However, there will be a signal only in the marginal case of execution on another processor and in the vast majority of cases the caller will need to hold the execution till the pre-defined timeout (I'm also not sure what it shall be). So in case of having numerous timers I'll waist a significant amount of time during MiniportHaltEx handling. Is there any other way to resolve this issue?

    Thanks

    P.S. I'm referring to the pre-WDI model here but the issue is similar for WDI-compliant driver as well (except for somewhat different API).

    Sunday, January 24, 2016 8:39 AM

Answers

  • Yes, it is possible that a timer callback is scheduled and runs while other thread attempts to cancel it. Then NdisCancelTimerObject fails and returns false. This is similar to common timer DPCs in WDM. If you tear context data from a running callback asynchronously, it won't end well. So come on, design the sync and data structures properly...

    -- pa

    • Marked as answer by -IgorC- Sunday, January 24, 2016 1:35 PM
    Sunday, January 24, 2016 11:41 AM

All replies

  • Yes, it is possible that a timer callback is scheduled and runs while other thread attempts to cancel it. Then NdisCancelTimerObject fails and returns false. This is similar to common timer DPCs in WDM. If you tear context data from a running callback asynchronously, it won't end well. So come on, design the sync and data structures properly...

    -- pa

    • Marked as answer by -IgorC- Sunday, January 24, 2016 1:35 PM
    Sunday, January 24, 2016 11:41 AM
  • Yes, it is possible that a timer callback is scheduled and runs while other thread attempts to cancel it. Then NdisCancelTimerObject fails and returns false. This is similar to common timer DPCs in WDM. If you tear context data from a running callback asynchronously, it won't end well. So come on, design the sync and data structures properly...

    -- pa

    I somehow missed there is a return status for NdisCancelTimerObject! :)

    So is it enough to wait for signal from the callback only in case NdisCancelTimerObject returns false and no need if it returns true?

    Sunday, January 24, 2016 11:48 AM
  • All you know when NdisCancelTimerObject returned false is that the timer was not queued. Either it is already canceled, or not scheduled at all, or running. You can make the context stuff referenced by the callback reference-counted: increase reference when scheduling the timer, decrease in the callback OR when successfully canceled the callback. 

    Whether it's worth to add some signal (event) when the count drops to 0 (like, a "condition variable" in usermode): IMHO this is matter of individual taste, I won't do this if the timer duration is limited and quite short. 

    -- pa


    • Edited by Pavel A Sunday, January 24, 2016 12:59 PM
    Sunday, January 24, 2016 12:53 PM