mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-07-12 06:08:42 +03:00
Fix wasm backend compilation
This commit is contained in:
parent
1338edf2cf
commit
c019eee52a
3 changed files with 45 additions and 50 deletions
|
@ -307,6 +307,14 @@ static inline uintptr_t _mi_align_down(uintptr_t sz, size_t alignment) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__attribute__((__unused__)) static void* mi_align_up_ptr(void* p, size_t alignment) {
|
||||||
|
return (void*)_mi_align_up((uintptr_t)p, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((__unused__)) static void* mi_align_down_ptr(void* p, size_t alignment) {
|
||||||
|
return (void*)_mi_align_down((uintptr_t)p, alignment);
|
||||||
|
}
|
||||||
|
|
||||||
// Divide upwards: `s <= _mi_divide_up(s,d)*d < s+d`.
|
// Divide upwards: `s <= _mi_divide_up(s,d)*d < s+d`.
|
||||||
static inline uintptr_t _mi_divide_up(uintptr_t size, size_t divider) {
|
static inline uintptr_t _mi_divide_up(uintptr_t size, size_t divider) {
|
||||||
mi_assert_internal(divider != 0);
|
mi_assert_internal(divider != 0);
|
||||||
|
|
52
src/os.c
52
src/os.c
|
@ -29,7 +29,7 @@ bool _mi_os_has_overcommit(void) {
|
||||||
return mi_os_mem_config.has_overcommit;
|
return mi_os_mem_config.has_overcommit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _mi_os_has_virtual_reserve(void) {
|
bool _mi_os_has_virtual_reserve(void) {
|
||||||
return mi_os_mem_config.has_virtual_reserve;
|
return mi_os_mem_config.has_virtual_reserve;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,14 +73,6 @@ void _mi_os_init(void) {
|
||||||
bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats);
|
bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* stats);
|
||||||
bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats);
|
bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats);
|
||||||
|
|
||||||
static void* mi_align_up_ptr(void* p, size_t alignment) {
|
|
||||||
return (void*)_mi_align_up((uintptr_t)p, alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void* mi_align_down_ptr(void* p, size_t alignment) {
|
|
||||||
return (void*)_mi_align_down((uintptr_t)p, alignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* -----------------------------------------------------------
|
/* -----------------------------------------------------------
|
||||||
aligned hinting
|
aligned hinting
|
||||||
|
@ -173,7 +165,7 @@ void _mi_os_free_ex(void* addr, size_t size, bool still_committed, mi_memid_t me
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
mi_assert(memid.memkind < MI_MEM_OS);
|
mi_assert(memid.memkind < MI_MEM_OS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,7 +189,7 @@ 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(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), size: 0x%zx bytes, align: 0x%zx, commit: %d, allow large: %d)\n", err, err, size, try_alignment, commit, allow_large);
|
||||||
|
@ -205,14 +197,14 @@ static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bo
|
||||||
mi_stat_counter_increase(stats->mmap_calls, 1);
|
mi_stat_counter_increase(stats->mmap_calls, 1);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
_mi_stat_increase(&stats->reserved, size);
|
_mi_stat_increase(&stats->reserved, size);
|
||||||
if (commit) {
|
if (commit) {
|
||||||
_mi_stat_increase(&stats->committed, size);
|
_mi_stat_increase(&stats->committed, size);
|
||||||
// seems needed for asan (or `mimalloc-test-api` fails)
|
// seems needed for asan (or `mimalloc-test-api` fails)
|
||||||
#ifdef MI_TRACK_ASAN
|
#ifdef MI_TRACK_ASAN
|
||||||
if (*is_zero) { mi_track_mem_defined(p,size); }
|
if (*is_zero) { mi_track_mem_defined(p,size); }
|
||||||
else { mi_track_mem_undefined(p,size); }
|
else { mi_track_mem_undefined(p,size); }
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
@ -249,7 +241,7 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit
|
||||||
// over-allocate uncommitted (virtual) memory
|
// over-allocate uncommitted (virtual) memory
|
||||||
p = mi_os_prim_alloc(over_size, 1 /*alignment*/, false /* commit? */, false /* allow_large */, is_large, is_zero, stats);
|
p = mi_os_prim_alloc(over_size, 1 /*alignment*/, false /* commit? */, false /* allow_large */, is_large, is_zero, stats);
|
||||||
if (p == NULL) return NULL;
|
if (p == NULL) return NULL;
|
||||||
|
|
||||||
// set p to the aligned part in the full region
|
// set p to the aligned part in the full region
|
||||||
// note: this is dangerous on Windows as VirtualFree needs the actual base pointer
|
// note: this is dangerous on Windows as VirtualFree needs the actual base pointer
|
||||||
// this is handled though by having the `base` field in the memid's
|
// this is handled though by having the `base` field in the memid's
|
||||||
|
@ -265,7 +257,7 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit
|
||||||
// overallocate...
|
// overallocate...
|
||||||
p = mi_os_prim_alloc(over_size, 1, commit, false, is_large, is_zero, stats);
|
p = mi_os_prim_alloc(over_size, 1, commit, false, is_large, is_zero, stats);
|
||||||
if (p == NULL) return NULL;
|
if (p == NULL) return NULL;
|
||||||
|
|
||||||
// and selectively unmap parts around the over-allocated area. (noop on sbrk)
|
// and selectively unmap parts around the over-allocated area. (noop on sbrk)
|
||||||
void* aligned_p = mi_align_up_ptr(p, alignment);
|
void* aligned_p = mi_align_up_ptr(p, alignment);
|
||||||
size_t pre_size = (uint8_t*)aligned_p - (uint8_t*)p;
|
size_t pre_size = (uint8_t*)aligned_p - (uint8_t*)p;
|
||||||
|
@ -276,7 +268,7 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit
|
||||||
if (post_size > 0) { mi_os_prim_free((uint8_t*)aligned_p + mid_size, post_size, commit, stats); }
|
if (post_size > 0) { mi_os_prim_free((uint8_t*)aligned_p + mid_size, post_size, commit, stats); }
|
||||||
// we can return the aligned pointer on `mmap` (and sbrk) systems
|
// we can return the aligned pointer on `mmap` (and sbrk) systems
|
||||||
p = aligned_p;
|
p = aligned_p;
|
||||||
*base = aligned_p; // since we freed the pre part, `*base == p`.
|
*base = aligned_p; // since we freed the pre part, `*base == p`.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +292,7 @@ void* _mi_os_alloc(size_t size, mi_memid_t* memid, mi_stats_t* tld_stats) {
|
||||||
void* p = mi_os_prim_alloc(size, 0, true, false, &os_is_large, &os_is_zero, stats);
|
void* p = mi_os_prim_alloc(size, 0, true, false, &os_is_large, &os_is_zero, stats);
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
*memid = _mi_memid_create_os(true, os_is_zero, os_is_large);
|
*memid = _mi_memid_create_os(true, os_is_zero, os_is_large);
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +304,7 @@ void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allo
|
||||||
if (size == 0) return NULL;
|
if (size == 0) return NULL;
|
||||||
size = _mi_os_good_alloc_size(size);
|
size = _mi_os_good_alloc_size(size);
|
||||||
alignment = _mi_align_up(alignment, _mi_os_page_size());
|
alignment = _mi_align_up(alignment, _mi_os_page_size());
|
||||||
|
|
||||||
bool os_is_large = false;
|
bool os_is_large = false;
|
||||||
bool os_is_zero = false;
|
bool os_is_zero = false;
|
||||||
void* os_base = NULL;
|
void* os_base = NULL;
|
||||||
|
@ -390,7 +382,7 @@ static void* mi_os_page_align_area_conservative(void* addr, size_t size, size_t*
|
||||||
|
|
||||||
bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) {
|
bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats) {
|
||||||
MI_UNUSED(tld_stats);
|
MI_UNUSED(tld_stats);
|
||||||
mi_stats_t* stats = &_mi_stats_main;
|
mi_stats_t* stats = &_mi_stats_main;
|
||||||
if (is_zero != NULL) { *is_zero = false; }
|
if (is_zero != NULL) { *is_zero = false; }
|
||||||
_mi_stat_increase(&stats->committed, size); // use size for precise commit vs. decommit
|
_mi_stat_increase(&stats->committed, size); // use size for precise commit vs. decommit
|
||||||
_mi_stat_counter_increase(&stats->commit_calls, 1);
|
_mi_stat_counter_increase(&stats->commit_calls, 1);
|
||||||
|
@ -400,21 +392,21 @@ bool _mi_os_commit(void* addr, size_t size, bool* is_zero, mi_stats_t* tld_stats
|
||||||
void* start = mi_os_page_align_areax(false /* conservative? */, addr, size, &csize);
|
void* start = mi_os_page_align_areax(false /* conservative? */, addr, size, &csize);
|
||||||
if (csize == 0) return true;
|
if (csize == 0) return true;
|
||||||
|
|
||||||
// commit
|
// commit
|
||||||
bool os_is_zero = false;
|
bool os_is_zero = false;
|
||||||
int err = _mi_prim_commit(start, csize, &os_is_zero);
|
int err = _mi_prim_commit(start, csize, &os_is_zero);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
_mi_warning_message("cannot commit OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize);
|
_mi_warning_message("cannot commit OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (os_is_zero && is_zero != NULL) {
|
if (os_is_zero && is_zero != NULL) {
|
||||||
*is_zero = true;
|
*is_zero = true;
|
||||||
mi_assert_expensive(mi_mem_is_zero(start, csize));
|
mi_assert_expensive(mi_mem_is_zero(start, csize));
|
||||||
}
|
}
|
||||||
// note: the following seems required for asan (otherwise `mimalloc-test-stress` fails)
|
// note: the following seems required for asan (otherwise `mimalloc-test-stress` fails)
|
||||||
#ifdef MI_TRACK_ASAN
|
#ifdef MI_TRACK_ASAN
|
||||||
if (os_is_zero) { mi_track_mem_defined(start,csize); }
|
if (os_is_zero) { mi_track_mem_defined(start,csize); }
|
||||||
else { mi_track_mem_undefined(start,csize); }
|
else { mi_track_mem_undefined(start,csize); }
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -428,11 +420,11 @@ static bool mi_os_decommit_ex(void* addr, size_t size, bool* needs_recommit, mi_
|
||||||
// page align
|
// page align
|
||||||
size_t csize;
|
size_t csize;
|
||||||
void* start = mi_os_page_align_area_conservative(addr, size, &csize);
|
void* start = mi_os_page_align_area_conservative(addr, size, &csize);
|
||||||
if (csize == 0) return true;
|
if (csize == 0) return true;
|
||||||
|
|
||||||
// decommit
|
// decommit
|
||||||
*needs_recommit = true;
|
*needs_recommit = true;
|
||||||
int err = _mi_prim_decommit(start,csize,needs_recommit);
|
int err = _mi_prim_decommit(start,csize,needs_recommit);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
_mi_warning_message("cannot decommit OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize);
|
_mi_warning_message("cannot decommit OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize);
|
||||||
}
|
}
|
||||||
|
@ -450,7 +442,7 @@ bool _mi_os_decommit(void* addr, size_t size, mi_stats_t* tld_stats) {
|
||||||
// but may be used later again. This will release physical memory
|
// but may be used later again. This will release physical memory
|
||||||
// pages and reduce swapping while keeping the memory committed.
|
// pages and reduce swapping while keeping the memory committed.
|
||||||
// We page align to a conservative area inside the range to reset.
|
// We page align to a conservative area inside the range to reset.
|
||||||
bool _mi_os_reset(void* addr, size_t size, mi_stats_t* stats) {
|
bool _mi_os_reset(void* addr, size_t size, mi_stats_t* stats) {
|
||||||
// page align conservatively within the range
|
// page align conservatively within the range
|
||||||
size_t csize;
|
size_t csize;
|
||||||
void* start = mi_os_page_align_area_conservative(addr, size, &csize);
|
void* start = mi_os_page_align_area_conservative(addr, size, &csize);
|
||||||
|
@ -470,7 +462,7 @@ bool _mi_os_reset(void* addr, size_t size, mi_stats_t* stats) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// either resets or decommits memory, returns true if the memory needs
|
// either resets or decommits memory, returns true if the memory needs
|
||||||
// to be recommitted if it is to be re-used later on.
|
// to be recommitted if it is to be re-used later on.
|
||||||
bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, mi_stats_t* stats)
|
bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, mi_stats_t* stats)
|
||||||
{
|
{
|
||||||
|
@ -483,7 +475,7 @@ bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, mi_stats_t* stats)
|
||||||
{
|
{
|
||||||
bool needs_recommit = true;
|
bool needs_recommit = true;
|
||||||
mi_os_decommit_ex(p, size, &needs_recommit, stats);
|
mi_os_decommit_ex(p, size, &needs_recommit, stats);
|
||||||
return needs_recommit;
|
return needs_recommit;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (allow_reset) { // this can sometimes be not allowed if the range is not fully committed
|
if (allow_reset) { // this can sometimes be not allowed if the range is not fully committed
|
||||||
|
@ -493,7 +485,7 @@ bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, mi_stats_t* stats)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// either resets or decommits memory, returns true if the memory needs
|
// either resets or decommits memory, returns true if the memory needs
|
||||||
// to be recommitted if it is to be re-used later on.
|
// to be recommitted if it is to be re-used later on.
|
||||||
bool _mi_os_purge(void* p, size_t size, mi_stats_t * stats) {
|
bool _mi_os_purge(void* p, size_t size, mi_stats_t * stats) {
|
||||||
return _mi_os_purge_ex(p, size, true, stats);
|
return _mi_os_purge_ex(p, size, true, stats);
|
||||||
|
|
|
@ -7,6 +7,10 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
|
|
||||||
// This file is included in `src/prim/prim.c`
|
// This file is included in `src/prim/prim.c`
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "mimalloc.h"
|
#include "mimalloc.h"
|
||||||
#include "mimalloc/internal.h"
|
#include "mimalloc/internal.h"
|
||||||
#include "mimalloc/atomic.h"
|
#include "mimalloc/atomic.h"
|
||||||
|
@ -36,26 +40,17 @@ int _mi_prim_free(void* addr, size_t size ) {
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
// Allocation: sbrk or memory_grow
|
// Allocation: sbrk
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
|
|
||||||
#if defined(MI_USE_SBRK)
|
static void* mi_memory_grow( size_t size ) {
|
||||||
static void* mi_memory_grow( size_t size ) {
|
void* p = sbrk(size);
|
||||||
void* p = sbrk(size);
|
if (p == (void*)(-1)) return NULL;
|
||||||
if (p == (void*)(-1)) return NULL;
|
#if !defined(__wasm__) // on wasm this is always zero initialized already.
|
||||||
#if !defined(__wasm__) // on wasm this is always zero initialized already.
|
memset(p,0,size);
|
||||||
memset(p,0,size);
|
|
||||||
#endif
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
#elif defined(__wasm__)
|
|
||||||
static void* mi_memory_grow( size_t size ) {
|
|
||||||
size_t base = (size > 0 ? __builtin_wasm_memory_grow(0,_mi_divide_up(size, _mi_os_page_size()))
|
|
||||||
: __builtin_wasm_memory_size(0));
|
|
||||||
if (base == SIZE_MAX) return NULL;
|
|
||||||
return (void*)(base * _mi_os_page_size());
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(MI_USE_PTHREADS)
|
#if defined(MI_USE_PTHREADS)
|
||||||
static pthread_mutex_t mi_heap_grow_mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t mi_heap_grow_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
@ -96,7 +91,7 @@ static void* mi_prim_mem_grow(size_t size, size_t try_alignment) {
|
||||||
if (base != NULL) {
|
if (base != NULL) {
|
||||||
p = mi_align_up_ptr(base, try_alignment);
|
p = mi_align_up_ptr(base, try_alignment);
|
||||||
if ((uint8_t*)p + size > (uint8_t*)base + alloc_size) {
|
if ((uint8_t*)p + size > (uint8_t*)base + alloc_size) {
|
||||||
// another thread used wasm_memory_grow/sbrk in-between and we do not have enough
|
// another thread used sbrk in-between and we do not have enough
|
||||||
// space after alignment. Give up (and waste the space as we cannot shrink :-( )
|
// space after alignment. Give up (and waste the space as we cannot shrink :-( )
|
||||||
// (in `mi_os_mem_alloc_aligned` this will fall back to overallocation to align)
|
// (in `mi_os_mem_alloc_aligned` this will fall back to overallocation to align)
|
||||||
p = NULL;
|
p = NULL;
|
||||||
|
@ -105,7 +100,7 @@ static void* mi_prim_mem_grow(size_t size, size_t try_alignment) {
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
_mi_warning_message("unable to allocate sbrk/wasm_memory_grow OS memory (%zu bytes, %zu alignment)\n", size, try_alignment);
|
_mi_warning_message("unable to allocate sbrk OS memory (%zu bytes, %zu alignment)\n", size, try_alignment);
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +109,7 @@ static void* mi_prim_mem_grow(size_t size, size_t try_alignment) {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
|
// Note: the `try_alignment` argument is respected by over-allocating.
|
||||||
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(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);
|
||||||
*is_large = false;
|
*is_large = false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue