Greeting all,
this is probably not a big deal…
But the help of DDK 3790.1830 does not state any limitations on the reentrancy of this function. This is the DDK, with which the driver was built.
In my case, I had an MDL like this:
struct _MDL * 0xa179edb8
+0x000 Next : (null)
+0x004 Size : 84
+0x006 MdlFlags : 57
+0x008 Process : (null)
+0x00c MappedSystemVa : 0xa8b25000
+0x010 StartVa : 0x00002000
+0x014 ByteCount : 0xe000
+0x018 ByteOffset : 0
I called MmGetSystemAddressForMdlSafe from two threads for this MDL, without synchronization.
The first thread received back the address 0xa8b25000, accessed this address for read and went on. Note, that this address is equal to the MappedSystemVa field.
The second thread received back the address 0xa8aa7000, tried to read from it and crashed.
The MdlFlags=0x57 means:
MDL_MAPPED_TO_SYSTEM_VA
MDL_PAGES_LOCKED
MDL_SOURCE_IS_NONPAGED_POOL
MDL_PARTIAL
MDL_IO_PAGE_READ
In the help of WDK 6001.17051 I read:
Only one thread can call MmGetSystemAddressForMdlSafe for the same MDL because this routine assumes that the caller owns the MDL. However, MmGetSystemAddressForMdlSafe can be called twice in serial for the same MDL either by using the same thread or by locking, if multiple threads are used. If a driver must split a request, the driver can allocate additional MDLs, or the driver can use IoBuildPartialMdl.
So…just another lesson learned.
Hello,
MmGetSystemAddressForMdlSafe() is actually a macro, not a function.
When you take a closer look at it in wdm.h, it becomes apparent why it is
not thread-safe.
On Wed, 05 Nov 2008 16:11:45 +0100, wrote:
> Greeting all,
> this is probably not a big deal…
>
> But the help of DDK 3790.1830 does not state any limitations on the
> reentrancy of this function. This is the DDK, with which the driver was
> built.
>
> In my case, I had an MDL like this:
> struct _MDL * 0xa179edb8
> +0x000 Next : (null)
> +0x004 Size : 84
> +0x006 MdlFlags : 57
> +0x008 Process : (null)
> +0x00c MappedSystemVa : 0xa8b25000
> +0x010 StartVa : 0x00002000
> +0x014 ByteCount : 0xe000
> +0x018 ByteOffset : 0
>
> I called MmGetSystemAddressForMdlSafe from two threads for this MDL,
> without synchronization.
> The first thread received back the address 0xa8b25000, accessed this
> address for read and went on. Note, that this address is equal to the
> MappedSystemVa field.
> The second thread received back the address 0xa8aa7000, tried to read
> from it and crashed.
>
> The MdlFlags=0x57 means:
> MDL_MAPPED_TO_SYSTEM_VA
> MDL_PAGES_LOCKED
> MDL_SOURCE_IS_NONPAGED_POOL
> MDL_PARTIAL
> MDL_IO_PAGE_READ
>
> In the help of WDK 6001.17051 I read:
> Only one thread can call MmGetSystemAddressForMdlSafe for the same MDL
> because this routine assumes that the caller owns the MDL. However,
> MmGetSystemAddressForMdlSafe can be called twice in serial for the same
> MDL either by using the same thread or by locking, if multiple threads
> are used. If a driver must split a request, the driver can allocate
> additional MDLs, or the driver can use IoBuildPartialMdl.
>
> So…just another lesson learned.
Yeah, I saw the macro.
It checks some flags and then calls MmMapLockedPagesSpecifyCache.
And for this function, neither the DDK nor the WDK say anything about reentrancy.
In principle, MmMapLockedPagesSpecifyCache could be reentrant, i.e., it could do the mapping only once and set the relevant flags only once…