Implement PAL backoff (#227)
The POSIX PAL and in some configurations the Windows PAL overallocate address space. If address space has become exhausted then this can lead to issues, where the PAL fails, even though there is enough aligned address space to satisfy the underlying request. This commit tries increasingly smaller overallocation sizes in an attempt to succeed in more cases.
This commit is contained in:
committed by
GitHub
parent
c6197cb5f2
commit
591b049585
@@ -209,23 +209,30 @@ namespace snmalloc
|
||||
*/
|
||||
std::pair<void*, size_t> reserve_at_least(size_t size) noexcept
|
||||
{
|
||||
SNMALLOC_ASSERT(size == bits::next_pow2(size));
|
||||
|
||||
// Magic number for over-allocating chosen by the Pal
|
||||
// These should be further refined based on experiments.
|
||||
constexpr size_t min_size =
|
||||
bits::is64() ? bits::one_at_bit(32) : bits::one_at_bit(28);
|
||||
auto size_request = bits::max(size, min_size);
|
||||
void* p = mmap(
|
||||
nullptr,
|
||||
size_request,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | DefaultMMAPFlags<OS>::flags,
|
||||
AnonFD<OS>::fd,
|
||||
0);
|
||||
|
||||
if (p == MAP_FAILED)
|
||||
OS::error("Out of memory");
|
||||
for (size_t size_request = bits::max(size, min_size);
|
||||
size_request >= size;
|
||||
size_request = size_request / 2)
|
||||
{
|
||||
void* p = mmap(
|
||||
nullptr,
|
||||
size_request,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | DefaultMMAPFlags<OS>::flags,
|
||||
AnonFD<OS>::fd,
|
||||
0);
|
||||
|
||||
return {p, size_request};
|
||||
if (p != MAP_FAILED)
|
||||
return {p, size_request};
|
||||
}
|
||||
|
||||
OS::error("Out of memory");
|
||||
}
|
||||
};
|
||||
} // namespace snmalloc
|
||||
|
||||
@@ -218,19 +218,24 @@ namespace snmalloc
|
||||
# else
|
||||
std::pair<void*, size_t> reserve_at_least(size_t size) noexcept
|
||||
{
|
||||
SNMALLOC_ASSERT(size == bits::next_pow2(size));
|
||||
|
||||
// Magic number for over-allocating chosen by the Pal
|
||||
// These should be further refined based on experiments.
|
||||
constexpr size_t min_size =
|
||||
bits::is64() ? bits::one_at_bit(32) : bits::one_at_bit(28);
|
||||
auto size_request = bits::max(size, min_size);
|
||||
|
||||
DWORD flags = MEM_RESERVE;
|
||||
void* ret = VirtualAlloc(nullptr, size_request, flags, PAGE_READWRITE);
|
||||
if (ret == nullptr)
|
||||
for (size_t size_request = bits::max(size, min_size);
|
||||
size_request >= size;
|
||||
size_request = size_request / 2)
|
||||
{
|
||||
error("Failed to allocate memory\n");
|
||||
void* ret =
|
||||
VirtualAlloc(nullptr, size_request, MEM_RESERVE, PAGE_READWRITE);
|
||||
if (ret != nullptr)
|
||||
{
|
||||
return std::pair(ret, size_request);
|
||||
}
|
||||
}
|
||||
return std::pair(ret, size_request);
|
||||
error("Failed to allocate memory\n");
|
||||
}
|
||||
# endif
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user