mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-07-06 11:34:38 +03:00
update for new dynamic direction on windows 64-bit
This commit is contained in:
parent
f646cc925d
commit
c228ecefd8
19 changed files with 218 additions and 88 deletions
|
@ -150,3 +150,14 @@ void* mi_realloc_aligned_at(void* p, size_t newsize, size_t alignment, size_t of
|
|||
void* mi_realloc_aligned(void* p, size_t newsize, size_t alignment) mi_attr_noexcept {
|
||||
return mi_heap_realloc_aligned(mi_get_default_heap(), p, newsize, alignment);
|
||||
}
|
||||
|
||||
void* mi_aligned_offset_recalloc(void* p, size_t size, size_t newcount, size_t alignment, size_t offset) mi_attr_noexcept {
|
||||
size_t newsize;
|
||||
if (mi_mul_overflow(size,newcount,&newsize)) return NULL;
|
||||
return mi_heap_realloc_zero_aligned_at(mi_get_default_heap(), p, newsize, alignment, offset, true );
|
||||
}
|
||||
void* mi_aligned_recalloc(void* p, size_t size, size_t newcount, size_t alignment) mi_attr_noexcept {
|
||||
size_t newsize;
|
||||
if (mi_mul_overflow(size, newcount, &newsize)) return NULL;
|
||||
return mi_heap_realloc_zero_aligned(mi_get_default_heap(), p, newsize, alignment, true );
|
||||
}
|
||||
|
|
|
@ -98,11 +98,6 @@ static int __cdecl mi_setmaxstdio(int newmax);
|
|||
// Microsoft allocation extensions
|
||||
// ------------------------------------------------------
|
||||
|
||||
static void* mi__expand(void* p, size_t newsize) {
|
||||
void* res = mi_expand(p, newsize);
|
||||
if (res == NULL) errno = ENOMEM;
|
||||
return res;
|
||||
}
|
||||
|
||||
typedef size_t mi_nothrow_t;
|
||||
|
||||
|
|
|
@ -194,4 +194,5 @@ int posix_memalign(void** p, size_t alignment, size_t size) { return mi_posix_me
|
|||
#pragma GCC visibility pop
|
||||
#endif
|
||||
|
||||
#endif // MI_MALLOC_OVERRIDE & !_WIN32
|
||||
#endif // MI_MALLOC_OVERRIDE && !_WIN32
|
||||
|
||||
|
|
|
@ -80,3 +80,14 @@ void* mi_reallocarray( void* p, size_t count, size_t size ) mi_attr_noexcept {
|
|||
return newp;
|
||||
}
|
||||
|
||||
void* mi__expand(void* p, size_t newsize) mi_attr_noexcept { // Microsoft
|
||||
void* res = mi_expand(p, newsize);
|
||||
if (res == NULL) errno = ENOMEM;
|
||||
return res;
|
||||
}
|
||||
|
||||
void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_noexcept { // Microsoft
|
||||
size_t total;
|
||||
if (mi_mul_overflow(count, size, &total)) return NULL;
|
||||
return _mi_heap_realloc_zero(mi_get_default_heap(), p, total, true);
|
||||
}
|
||||
|
|
|
@ -393,12 +393,6 @@ void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept {
|
|||
return mi_heap_realloc(mi_get_default_heap(),p,newsize);
|
||||
}
|
||||
|
||||
void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_noexcept {
|
||||
size_t total;
|
||||
if (mi_mul_overflow(count, size, &total)) return NULL;
|
||||
return _mi_heap_realloc_zero(mi_get_default_heap(),p,total,true);
|
||||
}
|
||||
|
||||
void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept {
|
||||
return mi_heap_reallocn(mi_get_default_heap(),p,count,size);
|
||||
}
|
||||
|
@ -537,6 +531,7 @@ std_new_handler_t mi_get_new_handler() {
|
|||
return _ZSt15get_new_handlerv();
|
||||
}
|
||||
#else
|
||||
// note: on windows we could dynamically link to `?get_new_handler@std@@YAP6AXXZXZ`.
|
||||
std_new_handler_t mi_get_new_handler() {
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -172,7 +172,7 @@ void mi_collect(bool force) mi_attr_noexcept {
|
|||
----------------------------------------------------------- */
|
||||
|
||||
mi_heap_t* mi_heap_get_default(void) {
|
||||
mi_thread_init();
|
||||
// mi_thread_init();
|
||||
return mi_get_default_heap();
|
||||
}
|
||||
|
||||
|
|
66
src/init.c
66
src/init.c
|
@ -373,6 +373,47 @@ void mi_thread_done(void) mi_attr_noexcept {
|
|||
// --------------------------------------------------------
|
||||
static void mi_process_done(void);
|
||||
|
||||
static bool os_preloading = true; // true until this module is initialized
|
||||
static bool mi_redirected = false; // true if malloc redirects to mi_malloc
|
||||
|
||||
// Returns true if this module has not been initialized; Don't use C runtime routines until it returns false.
|
||||
bool _mi_preloading() {
|
||||
return os_preloading;
|
||||
}
|
||||
|
||||
// Communicate with the redirection module on Windows
|
||||
#if defined(_WIN32) && defined(MI_SHARED_LIB)
|
||||
mi_decl_export void _mi_redirect_init() {
|
||||
// called on redirection
|
||||
mi_redirected = true;
|
||||
}
|
||||
__declspec(dllimport) bool mi_allocator_init(const char** message);
|
||||
__declspec(dllimport) void mi_allocator_done();
|
||||
#else
|
||||
static bool mi_allocator_init(const char** message) {
|
||||
if (message != NULL) *message = NULL;
|
||||
return true;
|
||||
}
|
||||
static void mi_allocator_done() {
|
||||
// nothing to do
|
||||
}
|
||||
#endif
|
||||
|
||||
// Called once by the process loader
|
||||
static void mi_process_load(void) {
|
||||
os_preloading = false;
|
||||
atexit(&mi_process_done);
|
||||
mi_process_init();
|
||||
//mi_stats_reset();
|
||||
if (mi_redirected) _mi_verbose_message("malloc is redirected.\n");
|
||||
|
||||
// show message from the redirector (if present)
|
||||
const char* msg = NULL;
|
||||
mi_allocator_init(&msg);
|
||||
if (msg != NULL) _mi_verbose_message(msg);
|
||||
}
|
||||
|
||||
// Initialize the process; called by thread_init or the process loader
|
||||
void mi_process_init(void) mi_attr_noexcept {
|
||||
// ensure we are called once
|
||||
if (_mi_process_is_initialized) return;
|
||||
|
@ -381,7 +422,7 @@ void mi_process_init(void) mi_attr_noexcept {
|
|||
// when using dynamic linking with interpose.
|
||||
mi_heap_t* h = _mi_heap_default;
|
||||
_mi_process_is_initialized = true;
|
||||
|
||||
|
||||
_mi_heap_main.thread_id = _mi_thread_id();
|
||||
_mi_verbose_message("process init: 0x%zx\n", _mi_heap_main.thread_id);
|
||||
uintptr_t random = _mi_random_init(_mi_heap_main.thread_id) ^ (uintptr_t)h;
|
||||
|
@ -389,15 +430,16 @@ void mi_process_init(void) mi_attr_noexcept {
|
|||
_mi_heap_main.cookie = (uintptr_t)&_mi_heap_main ^ random;
|
||||
#endif
|
||||
_mi_heap_main.random = _mi_random_shuffle(random);
|
||||
mi_process_setup_auto_thread_done();
|
||||
_mi_os_init();
|
||||
#if (MI_DEBUG)
|
||||
_mi_verbose_message("debug level : %d\n", MI_DEBUG);
|
||||
#endif
|
||||
atexit(&mi_process_done);
|
||||
mi_process_setup_auto_thread_done();
|
||||
mi_stats_reset();
|
||||
_mi_os_init();
|
||||
mi_thread_init();
|
||||
mi_stats_reset(); // only call stat reset *after* thread init (or the heap tld == NULL)
|
||||
}
|
||||
|
||||
// Called when the process is done (through `at_exit`)
|
||||
static void mi_process_done(void) {
|
||||
// only shutdown if we were initialized
|
||||
if (!_mi_process_is_initialized) return;
|
||||
|
@ -413,7 +455,9 @@ static void mi_process_done(void) {
|
|||
mi_option_is_enabled(mi_option_verbose)) {
|
||||
mi_stats_print(NULL);
|
||||
}
|
||||
mi_allocator_done();
|
||||
_mi_verbose_message("process done: 0x%zx\n", _mi_heap_main.thread_id);
|
||||
os_preloading = true; // don't call the C runtime anymore
|
||||
}
|
||||
|
||||
|
||||
|
@ -425,8 +469,8 @@ static void mi_process_done(void) {
|
|||
__declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved) {
|
||||
UNUSED(reserved);
|
||||
UNUSED(inst);
|
||||
if (reason==DLL_PROCESS_ATTACH) {
|
||||
mi_process_init();
|
||||
if (reason==DLL_PROCESS_ATTACH) {
|
||||
mi_process_load();
|
||||
}
|
||||
else if (reason==DLL_THREAD_DETACH) {
|
||||
mi_thread_done();
|
||||
|
@ -437,7 +481,7 @@ static void mi_process_done(void) {
|
|||
#elif defined(__cplusplus)
|
||||
// C++: use static initialization to detect process start
|
||||
static bool _mi_process_init(void) {
|
||||
mi_process_init();
|
||||
mi_process_load();
|
||||
return (_mi_heap_main.thread_id != 0);
|
||||
}
|
||||
static bool mi_initialized = _mi_process_init();
|
||||
|
@ -445,14 +489,14 @@ static void mi_process_done(void) {
|
|||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
// GCC,Clang: use the constructor attribute
|
||||
static void __attribute__((constructor)) _mi_process_init(void) {
|
||||
mi_process_init();
|
||||
mi_process_load();
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
// MSVC: use data section magic for static libraries
|
||||
// See <https://www.codeguru.com/cpp/misc/misc/applicationcontrol/article.php/c6945/Running-Code-Before-and-After-Main.htm>
|
||||
static int _mi_process_init(void) {
|
||||
mi_process_init();
|
||||
mi_process_load();
|
||||
return 0;
|
||||
}
|
||||
typedef int(*_crt_cb)(void);
|
||||
|
@ -467,5 +511,5 @@ static void mi_process_done(void) {
|
|||
#pragma data_seg()
|
||||
|
||||
#else
|
||||
#pragma message("define a way to call mi_process_init/done on your platform")
|
||||
#pragma message("define a way to call mi_process_load on your platform")
|
||||
#endif
|
||||
|
|
|
@ -114,6 +114,7 @@ bool mi_is_in_heap_region(const void* p) {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
Commit from a region
|
||||
-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -16,6 +16,10 @@ int mi_version(void) mi_attr_noexcept {
|
|||
return MI_MALLOC_VERSION;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------
|
||||
// Options
|
||||
// --------------------------------------------------------
|
||||
|
@ -31,7 +35,7 @@ typedef struct mi_option_desc_s {
|
|||
const char* name; // option name without `mimalloc_` prefix
|
||||
} mi_option_desc_t;
|
||||
|
||||
static mi_option_desc_t options[_mi_option_last] =
|
||||
static mi_option_desc_t options[_mi_option_last] =
|
||||
{
|
||||
// stable options
|
||||
{ 0, UNINIT, "show_stats" },
|
||||
|
@ -41,15 +45,15 @@ static mi_option_desc_t options[_mi_option_last] =
|
|||
// the following options are experimental and not all combinations make sense.
|
||||
{ 0, UNINIT, "page_reset" },
|
||||
{ 0, UNINIT, "cache_reset" },
|
||||
{ 1, UNINIT, "eager_commit" },
|
||||
{ 1, UNINIT, "eager_region_commit" }, // eager_commit should be on when eager_region_commit is on
|
||||
{ 1, UNINIT, "eager_commit" },
|
||||
{ 1, UNINIT, "eager_region_commit" }, // eager_commit should be on when eager_region_commit is on
|
||||
{ 0, UNINIT, "large_os_pages" }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's
|
||||
{ 0, UNINIT, "reset_decommits" },
|
||||
{ 0, UNINIT, "reset_discards" },
|
||||
{ 0, UNINIT, "reset_decommits" },
|
||||
{ 0, UNINIT, "reset_discards" },
|
||||
#if MI_SECURE
|
||||
{ MI_SECURE, INITIALIZED, "secure" } // in a secure build the environment setting is ignored
|
||||
#else
|
||||
{ 0, UNINIT, "secure" }
|
||||
{ 0, UNINIT, "secure" }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -104,7 +108,17 @@ static void mi_vfprintf( FILE* out, const char* prefix, const char* fmt, va_list
|
|||
char buf[256];
|
||||
if (fmt==NULL) return;
|
||||
if (out==NULL) out = stdout;
|
||||
if (_mi_preloading()) return;
|
||||
vsnprintf(buf,sizeof(buf)-1,fmt,args);
|
||||
#ifdef _WIN32
|
||||
// on windows with redirection, the C runtime uses us and we cannot call `fputs`
|
||||
// while called from the C runtime itself, so use a non-locking option
|
||||
if (out==stderr) {
|
||||
if (prefix != NULL) _cputs(prefix);
|
||||
_cputs(buf);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (prefix != NULL) fputs(prefix,out);
|
||||
fputs(buf,out);
|
||||
}
|
||||
|
@ -174,21 +188,29 @@ static void mi_strlcat(char* dest, const char* src, size_t dest_size) {
|
|||
dest[dest_size - 1] = 0;
|
||||
}
|
||||
|
||||
static void mi_option_init(mi_option_desc_t* desc) {
|
||||
desc->init = DEFAULTED;
|
||||
// Read option value from the environment
|
||||
char buf[32];
|
||||
mi_strlcpy(buf, "mimalloc_", sizeof(buf));
|
||||
mi_strlcat(buf, desc->name, sizeof(buf));
|
||||
static const char* mi_getenv(const char* name) {
|
||||
if (_mi_preloading()) return NULL; // don't call getenv too early
|
||||
#pragma warning(suppress:4996)
|
||||
char* s = getenv(buf);
|
||||
const char* s = getenv(name);
|
||||
if (s == NULL) {
|
||||
char buf[64+1];
|
||||
strncpy_s(buf,64,name,64); buf[64] = 0;
|
||||
for (size_t i = 0; i < strlen(buf); i++) {
|
||||
buf[i] = toupper(buf[i]);
|
||||
buf[i] = toupper(name[i]);
|
||||
}
|
||||
#pragma warning(suppress:4996)
|
||||
s = getenv(buf);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
static void mi_option_init(mi_option_desc_t* desc) {
|
||||
if (!_mi_preloading()) desc->init = DEFAULTED;
|
||||
// Read option value from the environment
|
||||
char buf[64];
|
||||
mi_strlcpy(buf, "mimalloc_", sizeof(buf));
|
||||
mi_strlcat(buf, desc->name, sizeof(buf));
|
||||
const char* s = mi_getenv(buf);
|
||||
if (s != NULL) {
|
||||
mi_strlcpy(buf, s, sizeof(buf));
|
||||
for (size_t i = 0; i < strlen(buf); i++) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue