Merge branch 'dev' into dev-exp

This commit is contained in:
daan 2019-08-12 01:59:31 -07:00
commit 63d4d2ad9c

View file

@ -279,31 +279,56 @@ static void* mi_unix_mmap(size_t size, size_t try_alignment, int protect_flags)
fd = VM_MAKE_TAG(100); fd = VM_MAKE_TAG(100);
#endif #endif
if (use_large_os_page(size, try_alignment)) { if (use_large_os_page(size, try_alignment)) {
int lflags = flags; static volatile uintptr_t large_page_try_ok = 0;
int lfd = fd; uintptr_t try_ok = mi_atomic_read(&large_page_try_ok);
#ifdef MAP_ALIGNED_SUPER if (try_ok > 0) {
lflags |= MAP_ALIGNED_SUPER; // If the OS is not configured for large OS pages, or the user does not have
#endif // enough permission, the `mmap` will always fail (but it might also fail for other reasons).
#ifdef MAP_HUGETLB // Therefore, once a large page allocation failed, we don't try again for `large_page_try_ok` times
lflags |= MAP_HUGETLB; // to avoid too many failing calls to mmap.
#endif mi_atomic_compare_exchange(&large_page_try_ok, try_ok - 1, try_ok);
#ifdef MAP_HUGE_2MB }
lflags |= MAP_HUGE_2MB; else {
#endif int lflags = flags;
#ifdef VM_FLAGS_SUPERPAGE_SIZE_2MB int lfd = fd;
lfd |= VM_FLAGS_SUPERPAGE_SIZE_2MB; #ifdef MAP_ALIGNED_SUPER
#endif lflags |= MAP_ALIGNED_SUPER;
if (lflags != flags) { #endif
// try large page allocation #ifdef MAP_HUGETLB
// TODO: if always failing due to permissions or no huge pages, try to avoid repeatedly trying? lflags |= MAP_HUGETLB;
// Should we check this in _mi_os_init? (as on Windows) #endif
p = mi_unix_mmapx(size, try_alignment, protect_flags, lflags, lfd); #ifdef MAP_HUGE_2MB
if (p == MAP_FAILED) p = NULL; // fall back to regular mmap if large is exhausted or no permission lflags |= MAP_HUGE_2MB;
#endif
#ifdef VM_FLAGS_SUPERPAGE_SIZE_2MB
lfd |= VM_FLAGS_SUPERPAGE_SIZE_2MB;
#endif
if (lflags != flags) {
// try large OS page allocation
p = mi_unix_mmapx(size, try_alignment, protect_flags, lflags, lfd);
if (p == MAP_FAILED) {
mi_atomic_write(&large_page_try_ok, 10); // on error, don't try again for the next N allocations
p = NULL; // and fall back to regular mmap
}
}
} }
} }
if (p == NULL) { if (p == NULL) {
p = mi_unix_mmapx(size, try_alignment, protect_flags, flags, fd); p = mi_unix_mmapx(size, try_alignment, protect_flags, flags, fd);
if (p == MAP_FAILED) p = NULL; if (p == MAP_FAILED) {
p = NULL;
}
#if defined(MADV_HUGEPAGE)
// Many Linux systems don't allow MAP_HUGETLB but they support instead
// transparent huge pages (TPH). It is not required to call `madvise` with MADV_HUGE
// though since properly aligned allocations will already use large pages if available
// in that case -- in particular for our large regions (in `memory.c`).
// However, some systems only allow TPH if called with explicit `madvise`, so
// when large OS pages are enabled for mimalloc, we call `madvice` anyways.
else if (use_large_os_page(size, try_alignment)) {
madvise(p, size, MADV_HUGEPAGE);
}
#endif
} }
return p; return p;
} }