Use VirtualAlloc2 on Windows.

The newer API (Windows 10 and newer) allows the allocator to ask for
strongly aligned memory.

This is enabled only if the `WINVER` macro is set to target Windows 10
or newer.  There is now a CMake option to target older versions of
Windows, so we can test both code paths.

The Azure Pipelines config now includes a test of the compatibility
version.  This runs only the release build, because it's mainly there as
a sanity check - 99% of the code is the same as the default Windows
config.
This commit is contained in:
David Chisnall
2019-02-19 12:34:53 +00:00
committed by David Chisnall
parent 6ec84856df
commit 2ee3ba59ee
3 changed files with 56 additions and 8 deletions

View File

@@ -68,19 +68,31 @@ namespace snmalloc
template<bool committed>
void* reserve(size_t* size, size_t align) noexcept
{
DWORD flags = MEM_RESERVE;
if (committed)
flags |= MEM_COMMIT;
# if (WINVER >= _WIN32_WINNT_WIN10) && !defined(USE_SYSTEMATIC_TESTING)
// If we're on Windows 10 or newer, we can use the VirtualAlloc2
// function. The FromApp variant is useable by UWP applications and
// cannot allocate executable memory.
MEM_ADDRESS_REQUIREMENTS addressReqs = {0};
MEM_EXTENDED_PARAMETER param = {0};
addressReqs.Alignment = align;
param.Type = MemExtendedParameterAddressRequirements;
param.Pointer = &addressReqs;
return VirtualAlloc2FromApp(
nullptr, nullptr, *size, flags, PAGE_READWRITE, &param, 1);
# else
// Add align, so we can guarantee to provide at least size.
size_t request = *size + align;
// Alignment must be a power of 2.
assert(align == bits::next_pow2(align));
DWORD flags = MEM_RESERVE;
if (committed)
flags |= MEM_COMMIT;
void* p;
# ifdef USE_SYSTEMATIC_TESTING
# ifdef USE_SYSTEMATIC_TESTING
size_t retries = 1000;
do
{
@@ -90,9 +102,9 @@ namespace snmalloc
systematic_bump_ptr() += request;
retries--;
} while (p == nullptr && retries > 0);
# else
# else
p = VirtualAlloc(nullptr, request, flags, PAGE_READWRITE);
# endif
# endif
uintptr_t aligned_p = bits::align_up((size_t)p, align);
@@ -105,6 +117,7 @@ namespace snmalloc
}
*size = request;
return p;
# endif
}
};
}