When does Windows clean up WdfDmaTransaction objects which have been released? RRS feed

  • Question

  • Hi,

    I have developed a driver (kmdf, win7/x64) for a custom test board which pumps large amounts of test data at a PCI Express board. The Queue is configured as sequential so my expectation was all requests are strictly serialised. In the original design I had a single WdfDmaTransaction which was declared during EvtDeviceAdd and reused. However, my customer was having occasional blue screens where the minidump claimed that an "Operation was performed on a transaction which is in the wrong state". I was never able to reproduce this on my test machines and on an on-site session with the customer the error occurred just once but before I had the firewire test-card etc. set up for debugging on a second PC.

    So, now I have done what I always do in these cases, throw it in the bin and do it again differently. In this re-design, the write requests to the hardware have an extension area defined. The WdfDmaTransaction object is now created every time I get a new request. The variable referring to the the WdfDmaTransaction object is in the extension space defined for the Write Requests. The assumption being windows will eventually clean everything up when the WdfDmaTransaction has been released and the request completes. This doesn't seem to be the case. I have just done a break in the debugger to take a look at what my driver is doing and see there are a whole lot of WdfDmaTransaction objects still stuck in my driver. All but the last are marked as "Released". Do I have to explicitly WdfObjectDelete() the WdfDmaTransaction object after calling WdfDmaTransactionRelease() ? Surely, once the request completes and gets cleaned up there is no reference to it any more. Am I eventually going to get millions of defunct WdfDmaTransaction objects which will eventually choke the system? At the moment the resource monitor looks ok (after 24 Hrs. running).

    Thanks in advance for any opinions.

            !WDFDMAENABLER 0x0000057fe2ef6838  dt FxDmaEnabler 0xfffffa801d1097c0 Context fffffa801d109ab0
                !WDFDMATRANSACTION 0x0000057fe5b78d88  dt FxDmaTransactionBase 0xfffffa801a487270
                !WDFDMATRANSACTION 0x0000057fe1bfe8f8  dt FxDmaTransactionBase 0xfffffa801e401700
                !WDFDMATRANSACTION 0x0000057fe13a9518  dt FxDmaTransactionBase 0xfffffa801ec56ae0
                !WDFDMATRANSACTION 0x0000057fe0ed6ef8  dt FxDmaTransactionBase 0xfffffa801f129100
                !WDFDMATRANSACTION 0x0000057fe5c26878  dt FxDmaTransactionBase 0xfffffa801a3d9780
                !WDFDMATRANSACTION 0x0000057fe1b9df08  dt FxDmaTransactionBase 0xfffffa801e4620f0
                !WDFDMATRANSACTION 0x0000057fe0bbea98  dt FxDmaTransactionBase 0xfffffa801f441560
                !WDFDMATRANSACTION 0x0000057fe166c288  dt FxDmaTransactionBase 0xfffffa801e993d70
                !WDFDMATRANSACTION 0x0000057fe5ca7288  dt FxDmaTransactionBase 0xfffffa801a358d70
                !WDFDMATRANSACTION 0x0000057fe1b0d988  dt FxDmaTransactionBase 0xfffffa801e4f2670
                !WDFDMATRANSACTION 0x0000057fe5d5f818  dt FxDmaTransactionBase 0xfffffa801a2a07e0
                !WDFDMATRANSACTION 0x0000057fe1c5f408  dt FxDmaTransactionBase 0xfffffa801e3a0bf0
                !WDFDMATRANSACTION 0x0000057fe56f6fd8  dt FxDmaTransactionBase 0xfffffa801a909020
                !WDFDMATRANSACTION 0x0000057fe5c74668  dt FxDmaTransactionBase 0xfffffa801a38b990
                !WDFDMATRANSACTION 0x0000057fe0cb0d18  dt FxDmaTransactionBase 0xfffffa801f34f2e0
            !WDFSPINLOCK 0x0000057fe2e843c8  dt FxSpinLock 0xfffffa801d17bc30

    WDF Verifier settings for mdrpciems.sys is OFF
    0: kd> !wdfkd.wdfdmatransaction 0x0000057fe5b78d88 0xff

    Dumping WDFDMATRANSACTION 0x0000057fe5b78d88
      State: FxDmaTransactionStateReleased
      Direction: Write
      Length of fragment being transfered: 0x0
      Max length of fragment: 0x0
      Bytes transfered : 0x0
      Bytes remaining to be transfered: 0x0

    0: kd> !wdfkd.wdfdmatransaction 0x0000057fe0cb0d18 0xff

    Dumping WDFDMATRANSACTION 0x0000057fe0cb0d18
      State: FxDmaTransactionStateTransfer
      Direction: Write
      Input Mdl: 0xfffffa801f600000
      Mdl of current fragment being transfered: 0xfffffa801f600000
      Length of fragment being transfered: 0x10000
      Max length of fragment: 0x10000
      Bytes transfered : 0x3b780000
      Bytes remaining to be transfered: 0x44870000

    0: kd> !wdfkd.wdfdmatransaction 0x0000057fe5c74668 0xff

    Dumping WDFDMATRANSACTION 0x0000057fe5c74668
      State: FxDmaTransactionStateReleased
      Direction: Write
      Mapregister Base address: 0xfffffa801e300d90
      Mapregisters needed: 0
      Length of fragment being transfered: 0x0
      Max length of fragment: 0x0
      Bytes transfered : 0x0
      Bytes remaining to be transfered: 0x0

    • Edited by cfgardiner Sunday, November 22, 2015 2:16 PM
    Sunday, November 22, 2015 1:42 PM


  • WDF wil only automatically delete objects if the parent is deleted, otherwise the default parent is the WDFDEVICE which has a very long lifetime and won't delete the children until the device is removed. in this case, calling Release on the transition allows you to reuse it, it does not delete it. You either need to call WdfObjectDelete when done with the object OR parent it to an object that represents completion at a higher level, like a WDFREQUEST (which when completed is deleted, thus the transaction would be to).

    please read (Reusing DMA Transaction Objects)

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

    Monday, November 23, 2015 5:31 AM