mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-08 00:09:31 +03:00
add address hint to primitive allocation API
This commit is contained in:
parent
b27d154ffd
commit
0e76fe3798
8 changed files with 29 additions and 23 deletions
|
@ -116,7 +116,7 @@
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<ConformanceMode>Default</ConformanceMode>
|
<ConformanceMode>Default</ConformanceMode>
|
||||||
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>
|
||||||
<PreprocessorDefinitions>MI_DEBUG=4;%(PreprocessorDefinitions);</PreprocessorDefinitions>
|
<PreprocessorDefinitions>MI_DEBUG=1;%(PreprocessorDefinitions);</PreprocessorDefinitions>
|
||||||
<CompileAs>CompileAsCpp</CompileAs>
|
<CompileAs>CompileAsCpp</CompileAs>
|
||||||
<SupportJustMyCode>false</SupportJustMyCode>
|
<SupportJustMyCode>false</SupportJustMyCode>
|
||||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||||
|
|
|
@ -43,9 +43,10 @@ int _mi_prim_free(void* addr, size_t size );
|
||||||
// If `commit` is false, the virtual memory range only needs to be reserved (with no access)
|
// If `commit` is false, the virtual memory range only needs to be reserved (with no access)
|
||||||
// which will later be committed explicitly using `_mi_prim_commit`.
|
// which will later be committed explicitly using `_mi_prim_commit`.
|
||||||
// `is_zero` is set to true if the memory was zero initialized (as on most OS's)
|
// `is_zero` is set to true if the memory was zero initialized (as on most OS's)
|
||||||
|
// The `hint_addr` address is either `NULL` or a preferred allocation address but can be ignored.
|
||||||
// pre: !commit => !allow_large
|
// pre: !commit => !allow_large
|
||||||
// try_alignment >= _mi_os_page_size() and a power of 2
|
// try_alignment >= _mi_os_page_size() and a power of 2
|
||||||
int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr);
|
int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr);
|
||||||
|
|
||||||
// Commit memory. Returns error code or 0 on success.
|
// Commit memory. Returns error code or 0 on success.
|
||||||
// For example, on Linux this would make the memory PROT_READ|PROT_WRITE.
|
// For example, on Linux this would make the memory PROT_READ|PROT_WRITE.
|
||||||
|
|
|
@ -289,7 +289,7 @@ static void* mi_arena_try_alloc_at_id(mi_arena_id_t arena_id, bool match_numa_no
|
||||||
bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld )
|
bool commit, bool allow_large, mi_arena_id_t req_arena_id, mi_memid_t* memid, mi_os_tld_t* tld )
|
||||||
{
|
{
|
||||||
MI_UNUSED_RELEASE(alignment);
|
MI_UNUSED_RELEASE(alignment);
|
||||||
mi_assert_internal(alignment <= MI_SEGMENT_ALIGN);
|
mi_assert(alignment <= MI_SEGMENT_ALIGN);
|
||||||
const size_t bcount = mi_block_count_of_size(size);
|
const size_t bcount = mi_block_count_of_size(size);
|
||||||
const size_t arena_index = mi_arena_id_index(arena_id);
|
const size_t arena_index = mi_arena_id_index(arena_id);
|
||||||
mi_assert_internal(arena_index < mi_atomic_load_relaxed(&mi_arena_count));
|
mi_assert_internal(arena_index < mi_atomic_load_relaxed(&mi_arena_count));
|
||||||
|
|
11
src/os.c
11
src/os.c
|
@ -214,7 +214,8 @@ void _mi_os_free(void* p, size_t size, mi_memid_t memid, mi_stats_t* stats) {
|
||||||
-------------------------------------------------------------- */
|
-------------------------------------------------------------- */
|
||||||
|
|
||||||
// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
|
// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
|
||||||
static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, mi_stats_t* tld_stats) {
|
// Also `hint_addr` is a hint and may be ignored.
|
||||||
|
static void* mi_os_prim_alloc_at(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, mi_stats_t* tld_stats) {
|
||||||
mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
|
mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
|
||||||
mi_assert_internal(is_zero != NULL);
|
mi_assert_internal(is_zero != NULL);
|
||||||
mi_assert_internal(is_large != NULL);
|
mi_assert_internal(is_large != NULL);
|
||||||
|
@ -223,9 +224,9 @@ static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bo
|
||||||
if (try_alignment == 0) { try_alignment = 1; } // avoid 0 to ensure there will be no divide by zero when aligning
|
if (try_alignment == 0) { try_alignment = 1; } // avoid 0 to ensure there will be no divide by zero when aligning
|
||||||
*is_zero = false;
|
*is_zero = false;
|
||||||
void* p = NULL;
|
void* p = NULL;
|
||||||
int err = _mi_prim_alloc(size, try_alignment, commit, allow_large, is_large, is_zero, &p);
|
int err = _mi_prim_alloc(hint_addr, size, try_alignment, commit, allow_large, is_large, is_zero, &p);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
_mi_warning_message("unable to allocate OS memory (error: %d (0x%x), size: 0x%zx bytes, align: 0x%zx, commit: %d, allow large: %d)\n", err, err, size, try_alignment, commit, allow_large);
|
_mi_warning_message("unable to allocate OS memory (error: %d (0x%x), addr: %p, size: 0x%zx bytes, align: 0x%zx, commit: %d, allow large: %d)\n", err, err, hint_addr, size, try_alignment, commit, allow_large);
|
||||||
}
|
}
|
||||||
|
|
||||||
MI_UNUSED(tld_stats);
|
MI_UNUSED(tld_stats);
|
||||||
|
@ -245,6 +246,10 @@ static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bo
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, mi_stats_t* tld_stats) {
|
||||||
|
return mi_os_prim_alloc_at(NULL, size, try_alignment, commit, allow_large, is_large, is_zero, tld_stats);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Primitive aligned allocation from the OS.
|
// Primitive aligned allocation from the OS.
|
||||||
// This function guarantees the allocated memory is aligned.
|
// This function guarantees the allocated memory is aligned.
|
||||||
|
|
|
@ -71,8 +71,8 @@ int _mi_prim_free(void* addr, size_t size) {
|
||||||
extern void* emmalloc_memalign(size_t alignment, size_t size);
|
extern void* emmalloc_memalign(size_t alignment, size_t size);
|
||||||
|
|
||||||
// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
|
// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
|
||||||
int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) {
|
int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) {
|
||||||
MI_UNUSED(try_alignment); MI_UNUSED(allow_large); MI_UNUSED(commit);
|
MI_UNUSED(try_alignment); MI_UNUSED(allow_large); MI_UNUSED(commit); MI_UNUSED(hint_addr);
|
||||||
*is_large = false;
|
*is_large = false;
|
||||||
// TODO: Track the highest address ever seen; first uses of it are zeroes.
|
// TODO: Track the highest address ever seen; first uses of it are zeroes.
|
||||||
// That assumes no one else uses sbrk but us (they could go up,
|
// That assumes no one else uses sbrk but us (they could go up,
|
||||||
|
|
|
@ -357,14 +357,14 @@ static void* unix_mmap(void* addr, size_t size, size_t try_alignment, int protec
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
|
// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
|
||||||
int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) {
|
int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) {
|
||||||
mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
|
mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
|
||||||
mi_assert_internal(commit || !allow_large);
|
mi_assert_internal(commit || !allow_large);
|
||||||
mi_assert_internal(try_alignment > 0);
|
mi_assert_internal(try_alignment > 0);
|
||||||
|
|
||||||
*is_zero = true;
|
*is_zero = true;
|
||||||
int protect_flags = (commit ? (PROT_WRITE | PROT_READ) : PROT_NONE);
|
int protect_flags = (commit ? (PROT_WRITE | PROT_READ) : PROT_NONE);
|
||||||
*addr = unix_mmap(NULL, size, try_alignment, protect_flags, false, allow_large, is_large);
|
*addr = unix_mmap(hint_addr, size, try_alignment, protect_flags, false, allow_large, is_large);
|
||||||
return (*addr != NULL ? 0 : errno);
|
return (*addr != NULL ? 0 : errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -119,8 +119,8 @@ static void* mi_prim_mem_grow(size_t size, size_t try_alignment) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
|
// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
|
||||||
int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) {
|
int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) {
|
||||||
MI_UNUSED(allow_large); MI_UNUSED(commit);
|
MI_UNUSED(allow_large); MI_UNUSED(commit); MI_UNUSED(hint_addr);
|
||||||
*is_large = false;
|
*is_large = false;
|
||||||
*is_zero = false;
|
*is_zero = false;
|
||||||
*addr = mi_prim_mem_grow(size, try_alignment);
|
*addr = mi_prim_mem_grow(size, try_alignment);
|
||||||
|
|
|
@ -203,7 +203,7 @@ static void* win_virtual_alloc_prim_once(void* addr, size_t size, size_t try_ali
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// on modern Windows try use VirtualAlloc2 for aligned allocation
|
// on modern Windows try use VirtualAlloc2 for aligned allocation
|
||||||
if (try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0 && pVirtualAlloc2 != NULL) {
|
if (addr == NULL && try_alignment > 1 && (try_alignment % _mi_os_page_size()) == 0 && pVirtualAlloc2 != NULL) {
|
||||||
MI_MEM_ADDRESS_REQUIREMENTS reqs = { 0, 0, 0 };
|
MI_MEM_ADDRESS_REQUIREMENTS reqs = { 0, 0, 0 };
|
||||||
reqs.Alignment = try_alignment;
|
reqs.Alignment = try_alignment;
|
||||||
MI_MEM_EXTENDED_PARAMETER param = { {0, 0}, {0} };
|
MI_MEM_EXTENDED_PARAMETER param = { {0, 0}, {0} };
|
||||||
|
@ -291,14 +291,14 @@ static void* win_virtual_alloc(void* addr, size_t size, size_t try_alignment, DW
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _mi_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) {
|
int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** addr) {
|
||||||
mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
|
mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
|
||||||
mi_assert_internal(commit || !allow_large);
|
mi_assert_internal(commit || !allow_large);
|
||||||
mi_assert_internal(try_alignment > 0);
|
mi_assert_internal(try_alignment > 0);
|
||||||
*is_zero = true;
|
*is_zero = true;
|
||||||
int flags = MEM_RESERVE;
|
int flags = MEM_RESERVE;
|
||||||
if (commit) { flags |= MEM_COMMIT; }
|
if (commit) { flags |= MEM_COMMIT; }
|
||||||
*addr = win_virtual_alloc(NULL, size, try_alignment, flags, false, allow_large, is_large);
|
*addr = win_virtual_alloc(hint_addr, size, try_alignment, flags, false, allow_large, is_large);
|
||||||
return (*addr != NULL ? 0 : (int)GetLastError());
|
return (*addr != NULL ? 0 : (int)GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue