On Nov 9, 2009, at 10:50 AM, Duane Murphy wrote:
I'm wondering if there is a way to "recover" an equivalent memory
descriptor from a memory descriptors virtual address.
You're stuck in "I have no handle" hell.
Here's more detail.
We use a user client interface to pass a large buffer to the kernel to
read some data. This buffer is allocated in user space and passed into
the user client to become the structureOutputDescriptor of the
IOExternalMethodArguments.
Due to our cross platform interface, this buffer is converted to a
memory address and length using. The memory address is determined
using IOMemoryDescriotor::map() and getVirtualAddress() on the
resulting IOMemoryMap.
Long term, you need to fix your "cross platform interface" so that it takes a handle, not a pointer/length tuple.
The mapping operation you are performing here is *expensive* on every platform that splits the user/kernel virtual space, and it's never going to be cheap.
Later this self same address must be used to read data from the disk.
This is accomplished using IOMemoryDescriptor::withAddress() using the
virtual address determined previously.
Would this second memory descriptor be fundamentally equivalent to the
first?
Inasmuch as it describes the same range of client memory, yes.
Using the same addresses etc? Is there a way of making that
happen? My fear is that this process is contributing to virtual memory
fragmentation or at least not making the best use of available virtual
memory.
You're definitely contributing to fragementation of the kernel's virtual address space when you map the original descriptor, and doing a lot of redundant work to construct the second descriptor.
The proper solution would, of course, be to be able to get the
original memory descriptor to the IO routine. Unfortunately that may
prove to be rather difficult given our cross platform engine.
Does your "cross platform" code depend on dereferencing the pointer it's passed to manipulate data inside the buffer?
If not, then consider passing a pointer to the IOMemoryDescriptor rather than the buffer.
If it does, a common workaround is to maintain a list of currently-active IOMemoryDescriptors on the client side, and to look back into the list from your I/O shim to recover the IOMD. This doesn't save you the cost of mapping the descriptor, but it does save you constructing a second one. This lookup isn't necessarily as hard as it seems; your client can find the I/O shim fairly easy when it's instantiated, so it's just a matter of registering/deregistering its list as it comes and goes...