none
Checking DIRQL value before acquiring the interrupt spin lock RRS feed

  • Question

  • Hi All, 

    My driver is exporting function to other driver and it access some register in interrupt context. This register is also accessed by my driver routines. So i have to create interrupt spinlock to protect the registers. 

    My question is i want to check the DIRQL value before acquiring the interrupt spinlock in the exported IO functions. Because i don't know the DIRQL value of the other driver. If the IRQL is already higher, then acquiring the spinlock will cause the bugcheck.. 

    Please clarify this.

    Wednesday, August 13, 2014 7:31 AM

Answers

  • do not raise to Dirql on your own. The act of acquiring the interrupt lock is sufficient to raise to dirql. I'd the exported function doesn't know if it shoulda acquire the lock, change the function parameters to give it enough context so it can do the right thing instead of dancing around the issue

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Wednesday, August 13, 2014 2:27 PM
  • If B is not calling at HIGH_LEVEL, then A can just acquire the interrupt lock.

    Yes

    In WDM during IoConnectInterrupt() we can specify the SyncIRQL. In WDF how do specify the SyncIRQL level?

    If driver A could create interrupt object with SyncIrql  = HIGH_IRQL, all you need is acquire the interrupt lock.

    But acquiring the lock will be done in the driver A - either in WDM or KMDF way - because KMDF objects cannot be shared across drivers.

    Please, press harder on your "driver guys" to provide solution for you.

    -- pa


    • Edited by Pavel A Tuesday, August 19, 2014 1:44 PM
    • Marked as answer by Selva.S Tuesday, August 19, 2014 1:51 PM
    Tuesday, August 19, 2014 1:44 PM

All replies

  • Thanks Pavel.

    My question is the register was shared with other IO functions. They might also try to access the register. So before read/write to those register i have to acquire the spinlock (not interrupt spinlock). 

    So when the other driver invokes the exported function, i can't acquire the spinlock becaue the IRQL is already high.  

    So my idea is to raise the IRQL value (of the other driver (Performance Monitor)) in my driver IO function before read/write to the registers.

    Then my IO function and exported function will run in the same IRQL value when read/write the registers.

    Wednesday, August 13, 2014 11:42 AM
  • do not raise to Dirql on your own. The act of acquiring the interrupt lock is sufficient to raise to dirql. I'd the exported function doesn't know if it shoulda acquire the lock, change the function parameters to give it enough context so it can do the right thing instead of dancing around the issue

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Wednesday, August 13, 2014 2:27 PM
  • Let me make the question simple:

    B Driver's ISR (HIGH_LEVEL) -> A Driver's Exported Fun -> Access A's Registers

    A Driver's Io Function -> Access A's Registers

    How the synchronization can be done:

    For IRQL, A Driver's Io function can raise the IRQL to HIGH_LEVEL before read/write the registers. Am i correct?

    Now i can't use spinlock to synchronize access from multiple processors. What is the correct way? Can i use Interlocked operation to check variable 0 or 1 in a while loop after raising the IRQL?



    • Edited by Selva.S Thursday, August 14, 2014 2:24 AM
    Thursday, August 14, 2014 2:20 AM
  • raising IRQL != acquiring a lock. IRQL is CPU specific. in your proposal on processor 1 the ISR could be running at HIGH_LEVEL and then processor 0 raises IRQL to HIGH_LEVEL, but does not synchronize with the ISR. Interlocked games will not suffice. If you want A to synchronize with B, B must export a way for A to acquire the interrupt spin lock.

    Why is B touching A's registers? typically a driver only touches registers that it owns


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, August 14, 2014 3:08 AM
  • Actually B is a performance monitor legacy driver. If A has to acquire B interrupt spinlock, then A has to check B interrupt lock is valid, because B can be unloaded at any time.

    And B is not WDF based.

    • Edited by Selva.S Thursday, August 14, 2014 4:18 AM
    Thursday, August 14, 2014 3:55 AM
  • you then have block in B's unload routine to make sure all outstanding references to B's interrupt object in A are rundown before unloading. IOW, you have to provide synchronization on unload

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, August 14, 2014 4:31 AM
  • There is legacy WDM driver and its ISR runs at HIGH_LEVEL. I dont have the source code. Just for information i am asking this question. 

    How can we mention that an ISR should be run at HIGH_LEVEL. In IoConnectInterrupt() both the IRQL and SYNCIRQL specify the value between DIRQL value only.

    Monday, August 18, 2014 1:07 PM
  • Thanks Pavel.

    So we can specify the SynchronizeIrql even as HIGH_LEVEL also in the interrupt obj, am i understood correctly? Please confirm.

    I have one question. This is regarding synchronization between two driver access to registers.

    "A" driver access some registers at HIGH_LEVEL via Read/Write function exported in my driver"B". The same registers are also accessed by the "B" driver in its IO function.

    The "A"  driver doesn't have any interrupt object they are simply using KeRaiseIRQL function before invoking the read/write function. But "B" driver has interrupt object.

    How can i synchronize the between "A"  and "B" access to the device registers. 

    One idea is - I have to modify the SyncIrql level of "B" driver interrupt object to HIGH_LEVEL. I can use this interrupt object spinlock to synchronize the access to the registers. 

    Any other better approach?

    Please clarify.



    • Edited by Selva.S Tuesday, August 19, 2014 2:58 AM
    Tuesday, August 19, 2014 2:57 AM
  • I told you in a previous response, IRQL is per CPU, not global. Raising to the IRQL the ISR runs at is NOT the same acquiring that interrupt spin lock which runs at that IRQL. You also previously said you couldn't modify B, but now you are talking about changing B. In short, you have to

    1) share the interrupt object between the two drivers, that is the only way to synchronize

    2) have rundown protection in the use of the interrupt object when B unloads


    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, August 19, 2014 3:16 AM
  • Sorry for the confusion. 

    Actually i my last post i have interchanged A and B. It is like this:

    A (my driver) has interrupt object (currently i don't know its DIRQL and SynchronizeIrql). This exports function to B (legacy driver) and B doesn't have any interrupt object. 

    B invokes A's exported function in HIGH_LEVEL to access device registers. A's internal functions also access the registers. 

    In this case i am thinking to modify the SyncIrql level of my driver A's interrupt object to HIGH_LEVEL. I can use this interrupt object spinlock to synchronize the access to the registers between my driver IO function and B driver calls.

    (Once again i am really sorry for the wrong information in my previous post). 

    Please clarify.

    Tuesday, August 19, 2014 5:25 AM
  • This current design still doesn't help you. AGAIN, IRQL is per CPU, not global.  for instance, B invokes A's exports at HIGH_IRQL on CPU0. While this is happening on CPU0, CPU1 processes A's interrupt, calls the ISR (let's say at HIGH_IRQL). CPU1 can run concurrently with CPU0 even though both are running at HIGH_IRQL. The interrupt spinlock AND the associated IRQL are the key to sync here, not just the IRQL

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, August 19, 2014 5:52 AM
  • Yes. I understood that IRQL are processor specific. We need SPINLOCK to synchronize the access from multiple processor.

    My intention is, when B invokes the A's exports at HIGH_LEVEL, in the exported function acquire A's interrupt spinlock. This will protect the registers even when CPU1 processes A's interrupt, calls the ISR (let's say at HIGH_IRQL). 

    For the above the important thing is : A's interrupt object SyncIrql should be HIGH_IRQL. 

    When B calls at HIGH_LEVEL and in the exported function acquiring A's interrupt spinlock will again try to raise the IRQL to SyncIrql (HIGH_LEVEL). This won't cause any bugcheck.

    Please confirm.

    Tuesday, August 19, 2014 6:10 AM
  • why is B calling at high_irql? Just call at normal irql and then A can just acquire the interrupt lock without any raising to irql first hoops

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Tuesday, August 19, 2014 6:23 AM
  • B is a performance monitor driver.  Even i am trying to get the things from the driver guys.

    If B is calling at HIGH_LEVEL, then the following will work as expected?

    ---------------- Snip --------------

    A's interrupt object SyncIrql should be HIGH_IRQL. 

    When B calls the exported function at HIGH_LEVEL  and in the exported function acquire A's interrupt spinlock. 

    This way we can synchronize B access and A internal access to the device registers.

    ------------------ End -----------------------

    If B is not calling at HIGH_LEVEL, then A can just acquire the interrupt lock.

    In WDM during IoConnectInterrupt() we can specify the SyncIRQL. In WDF how do specify the SyncIRQL level?

    • Edited by Selva.S Tuesday, August 19, 2014 10:16 AM
    Tuesday, August 19, 2014 6:48 AM
  • Hi All,

    In WDM during IoConnectInterrupt() we can specify the SyncIRQL. In WDF how do specify the SyncIRQL level?

    Could any one please clarify.

    I got some idea, i have to do the below modification:

    interruptConfig.InterruptTranslated->u.Interrupt.Level = HIGH_LEVEL;

    Am i correct?

    • Edited by Selva.S Wednesday, August 20, 2014 6:36 AM
    Wednesday, August 20, 2014 5:41 AM