Windows 10 version 1803 added the ability to request specific alignment and address region requirements when creating address space mappings either for virtual memory (VirtualÂAlloc2
) or file mappings (MapÂViewÂOfÂFile3
). These new functions let you pass a MEM_
structure which can specify additional constraints:
LowestÂStartingÂAddress
: The lowest address in the region.HighestÂEndingÂAddress
: The highest address in the region.Alignment
: The desired alignment.
If any field is zero, then the system uses whatever value it normally would have. For example, if you say that the alignment is zero, then the memory will be aligned on the allocation granularity (for normal-sized pages) or the large page granularity (for large pages).
Here are some sample usages:
Scenario | LowestÂStartingÂAddress | HighestÂEndingÂAddress | Alignment |
---|---|---|---|
Align to multiple of N | 0 | 0 | N |
Below 4GB | 0 | 0x00000000`FFFFFFFF |
0 |
Above 4GB | 0x00000001`00000000 |
0 | 0 |
At 1MB boundary between 2GB and 4GB |
0x00000000`80000000 |
0x00000000`FFFFFFFF |
0x00000000`00100000 |
Note that the HighestÂEndingÂAddress
is endpoint-inclusive. In other words, it is the highest address in the region, not the highest address plus one.
Here’s how you pass the MEM_
:
MEM_ADDRESS_REQUIREMENTS requirements = {0}; requirements.LowestStartingAddress = ⟦ value ⟧; requirements.HighestStartingAddress = ⟦ value ⟧; requirements.Alignment = ⟦ value ⟧; MEM_EXTENDED_PARAMETER param = {0}; param.Type = MemExtendedParameterAddressRequirements; param.Pointer = &requirements; auto result = VirtualAlloc2(nullptr, nullptr, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE, ¶m, 1);
The VirtualÂAlloc2
function takes a pointer to an array of MEM_
structures, but since we have only one, we just pass the address of a single object and tell the system that we have an array of only one element.
Note that you cannot combine non-default MEM_
with an explicit BaseÂAddress
. If you pass an explicit base address, then you are saying, “I want the memory to be exactly here; I don’t want the system to choose for me.” Under those conditions, it’s meaningless to tell the system “And here is how I’d like you to choose the address for me.”
I requested a function like this 2 decades ago. It's nice to see that Microsoft finally implemented it.
They half-baked what I requested though:
1. There should be a way to specify a "preceding allocation", i.e. lets say you want something aligned on 1 MiB boundary but want a 4 KiB block preceding it it.
2. There should be a way to specify that the end address of the block be aligned as opposed to the begin address...
Hi Raymond, I had a question and I wasn't sure if there might be a better place to ask it.
I know that you've commented before on some of the internal aspects of the global memory manager and how it validates pointers to functions like GlobalLock. I noticed though, that when you GlobalLock a pointer, it only increments the lock count until it reaches 255, but subsequent calls to GlobalLock still return a pointer to...