Description of the problem:
1. Allocate contiguous buffer and get its physical address. We can use several ways to allocate this memory ( inTaskWithPhysicalMask(), inTaskWithOptions(), IOMallocContiguous()
). Usually this step is performed by our drivers at startup of OS or at connection of any supported Thunderbolt/USB/FireWire device(s).
2. Free this allocated memory. This is performed than we remove Thunderbolt/USB/FireWire device or just unload our driver.
3. Perform step #1 one more time. Now memory buffer has another physical address. In most cases this new address equals to:
previous_physical_address+previous_buffer_size.
If we perform these 3 steps several times - at some moment it will be impossible to allocate any more memory. This is not a memory leak - system correctly reports decrease of free memory at it allocation
and increase to the previous amount at deallocation. The problem is very wide. I observed it on different setups under OS X 10.6.8 and 10.7.4. Another developer observed it on his setup, too.
Some source code:
const mach_vm_size_t allocationSize = 9 * 1024 * 1024;
IOBufferMemoryDescriptor * mBMD = IOBufferMemoryDescriptor::inTaskWithPhysicalMask(kernel_task, kIOMemoryPhysicallyContiguous|kIOMemoryKernelUserShared,
allocationSize, 0x0FFFFFFFF);
if (mBMD != NULL)
{
IOPhysicalAddress address = mBMD->getPhysicalSegment(0, NULL);
IOLog("Physical Address %X, virtual address %X\n",
address, mBMD->getBytesNoCopy());
mBMD->release();
}
else
{
IOLog("IOBufferMemoryDescriptor NULL\n");
}
If you execute this code several times during one session you'll receive something like:
Physical Address 23227000...
Physical Address 23b27000...
Physical Address 24427000...
....
IOBufferMemoryDescriptor NULL