mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-05 23:19:31 +03:00
remove ifdefs around mi_os_aligned_hint
This commit is contained in:
parent
f4b7ea9e9e
commit
2ab70f3c84
1 changed files with 53 additions and 51 deletions
104
src/os.c
104
src/os.c
|
@ -308,7 +308,57 @@ static int mi_madvise(void* addr, size_t length, int advice) {
|
||||||
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------
|
/* -----------------------------------------------------------
|
||||||
free memory
|
aligned hinting
|
||||||
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
|
// On 64-bit systems, we can do efficient aligned allocation by using
|
||||||
|
// the 2TiB to 30TiB area to allocate those.
|
||||||
|
#if (MI_INTPTR_SIZE >= 8)
|
||||||
|
static mi_decl_cache_align _Atomic(uintptr_t)aligned_base;
|
||||||
|
|
||||||
|
// Return a MI_SEGMENT_SIZE aligned address that is probably available.
|
||||||
|
// If this returns NULL, the OS will determine the address but on some OS's that may not be
|
||||||
|
// properly aligned which can be more costly as it needs to be adjusted afterwards.
|
||||||
|
// For a size > 1GiB this always returns NULL in order to guarantee good ASLR randomization;
|
||||||
|
// (otherwise an initial large allocation of say 2TiB has a 50% chance to include (known) addresses
|
||||||
|
// in the middle of the 2TiB - 6TiB address range (see issue #372))
|
||||||
|
|
||||||
|
#define MI_HINT_BASE ((uintptr_t)2 << 40) // 2TiB start
|
||||||
|
#define MI_HINT_AREA ((uintptr_t)4 << 40) // upto 6TiB (since before win8 there is "only" 8TiB available to processes)
|
||||||
|
#define MI_HINT_MAX ((uintptr_t)30 << 40) // wrap after 30TiB (area after 32TiB is used for huge OS pages)
|
||||||
|
|
||||||
|
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size)
|
||||||
|
{
|
||||||
|
if (try_alignment <= 1 || try_alignment > MI_SEGMENT_SIZE) return NULL;
|
||||||
|
size = _mi_align_up(size, MI_SEGMENT_SIZE);
|
||||||
|
if (size > 1*MI_GiB) return NULL; // guarantee the chance of fixed valid address is at most 1/(MI_HINT_AREA / 1<<30) = 1/4096.
|
||||||
|
#if (MI_SECURE>0)
|
||||||
|
size += MI_SEGMENT_SIZE; // put in `MI_SEGMENT_SIZE` virtual gaps between hinted blocks; this splits VLA's but increases guarded areas.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uintptr_t hint = mi_atomic_add_acq_rel(&aligned_base, size);
|
||||||
|
if (hint == 0 || hint > MI_HINT_MAX) { // wrap or initialize
|
||||||
|
uintptr_t init = MI_HINT_BASE;
|
||||||
|
#if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of aligned allocations unless in debug mode
|
||||||
|
uintptr_t r = _mi_heap_random_next(mi_get_default_heap());
|
||||||
|
init = init + ((MI_SEGMENT_SIZE * ((r>>17) & 0xFFFFF)) % MI_HINT_AREA); // (randomly 20 bits)*4MiB == 0 to 4TiB
|
||||||
|
#endif
|
||||||
|
uintptr_t expected = hint + size;
|
||||||
|
mi_atomic_cas_strong_acq_rel(&aligned_base, &expected, init);
|
||||||
|
hint = mi_atomic_add_acq_rel(&aligned_base, size); // this may still give 0 or > MI_HINT_MAX but that is ok, it is a hint after all
|
||||||
|
}
|
||||||
|
if (hint%try_alignment != 0) return NULL;
|
||||||
|
return (void*)hint;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
|
||||||
|
MI_UNUSED(try_alignment); MI_UNUSED(size);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* -----------------------------------------------------------
|
||||||
|
Free memory
|
||||||
-------------------------------------------------------------- */
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats_t* stats)
|
static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats_t* stats)
|
||||||
|
@ -347,9 +397,6 @@ static bool mi_os_mem_free(void* addr, size_t size, bool was_committed, mi_stats
|
||||||
return !err;
|
return !err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(defined(__wasi__) || defined(MI_USE_SBRK) || defined(MAP_ALIGNED) || MI_INTPTR_SIZE < 8)
|
|
||||||
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------
|
/* -----------------------------------------------------------
|
||||||
Raw allocation on Windows (VirtualAlloc)
|
Raw allocation on Windows (VirtualAlloc)
|
||||||
|
@ -652,53 +699,6 @@ static void* mi_unix_mmap(void* addr, size_t size, size_t try_alignment, int pro
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// On 64-bit systems, we can do efficient aligned allocation by using
|
|
||||||
// the 2TiB to 30TiB area to allocate them.
|
|
||||||
#if (MI_INTPTR_SIZE >= 8) && (defined(_WIN32) || defined(MI_OS_USE_MMAP))
|
|
||||||
static mi_decl_cache_align _Atomic(uintptr_t) aligned_base;
|
|
||||||
|
|
||||||
// Return a 4MiB aligned address that is probably available.
|
|
||||||
// If this returns NULL, the OS will determine the address but on some OS's that may not be
|
|
||||||
// properly aligned which can be more costly as it needs to be adjusted afterwards.
|
|
||||||
// For a size > 1GiB this always returns NULL in order to guarantee good ASLR randomization;
|
|
||||||
// (otherwise an initial large allocation of say 2TiB has a 50% chance to include (known) addresses
|
|
||||||
// in the middle of the 2TiB - 6TiB address range (see issue #372))
|
|
||||||
|
|
||||||
#define MI_HINT_BASE ((uintptr_t)2 << 40) // 2TiB start
|
|
||||||
#define MI_HINT_AREA ((uintptr_t)4 << 40) // upto 6TiB (since before win8 there is "only" 8TiB available to processes)
|
|
||||||
#define MI_HINT_MAX ((uintptr_t)30 << 40) // wrap after 30TiB (area after 32TiB is used for huge OS pages)
|
|
||||||
|
|
||||||
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size)
|
|
||||||
{
|
|
||||||
if (try_alignment <= 1 || try_alignment > MI_SEGMENT_SIZE) return NULL;
|
|
||||||
size = _mi_align_up(size, MI_SEGMENT_SIZE);
|
|
||||||
if (size > 1*MI_GiB) return NULL; // guarantee the chance of fixed valid address is at most 1/(MI_HINT_AREA / 1<<30) = 1/4096.
|
|
||||||
#if (MI_SECURE>0)
|
|
||||||
size += MI_SEGMENT_SIZE; // put in `MI_SEGMENT_SIZE` virtual gaps between hinted blocks; this splits VLA's but increases guarded areas.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uintptr_t hint = mi_atomic_add_acq_rel(&aligned_base, size);
|
|
||||||
if (hint == 0 || hint > MI_HINT_MAX) { // wrap or initialize
|
|
||||||
uintptr_t init = MI_HINT_BASE;
|
|
||||||
#if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of aligned allocations unless in debug mode
|
|
||||||
uintptr_t r = _mi_heap_random_next(mi_get_default_heap());
|
|
||||||
init = init + ((MI_SEGMENT_SIZE * ((r>>17) & 0xFFFFF)) % MI_HINT_AREA); // (randomly 20 bits)*4MiB == 0 to 4TiB
|
|
||||||
#endif
|
|
||||||
uintptr_t expected = hint + size;
|
|
||||||
mi_atomic_cas_strong_acq_rel(&aligned_base, &expected, init);
|
|
||||||
hint = mi_atomic_add_acq_rel(&aligned_base, size); // this may still give 0 or > MI_HINT_MAX but that is ok, it is a hint after all
|
|
||||||
}
|
|
||||||
if (hint%try_alignment != 0) return NULL;
|
|
||||||
return (void*)hint;
|
|
||||||
}
|
|
||||||
#elif defined(__wasi__) || defined(MI_USE_SBRK) || defined(MAP_ALIGNED) || (MI_INTPTR_SIZE < 8)
|
|
||||||
// no need for mi_os_get_aligned_hint
|
|
||||||
#else
|
|
||||||
static void* mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
|
|
||||||
MI_UNUSED(try_alignment); MI_UNUSED(size);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------
|
/* -----------------------------------------------------------
|
||||||
Primitive allocation from the OS.
|
Primitive allocation from the OS.
|
||||||
|
@ -799,6 +799,7 @@ static void* mi_os_mem_alloc_aligned(size_t size, size_t alignment, bool commit,
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------
|
/* -----------------------------------------------------------
|
||||||
OS API: alloc, free, alloc_aligned
|
OS API: alloc, free, alloc_aligned
|
||||||
----------------------------------------------------------- */
|
----------------------------------------------------------- */
|
||||||
|
@ -826,6 +827,7 @@ void _mi_os_free(void* p, size_t size, mi_stats_t* stats) {
|
||||||
|
|
||||||
void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_stats_t* tld_stats)
|
void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool* large, mi_stats_t* tld_stats)
|
||||||
{
|
{
|
||||||
|
MI_UNUSED(&mi_os_get_aligned_hint); // suppress unused warnings
|
||||||
MI_UNUSED(tld_stats);
|
MI_UNUSED(tld_stats);
|
||||||
if (size == 0) return NULL;
|
if (size == 0) return NULL;
|
||||||
size = _mi_os_good_alloc_size(size);
|
size = _mi_os_good_alloc_size(size);
|
||||||
|
|
Loading…
Add table
Reference in a new issue