mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-05-06 23:39:31 +03:00
Merge branch 'dev' into dev2
This commit is contained in:
commit
e82e03c3e2
7 changed files with 80 additions and 25 deletions
|
@ -208,19 +208,20 @@ static inline void mi_prim_tls_slot_set(size_t slot, void* value) mi_attr_noexce
|
||||||
#elif _WIN32 && MI_WIN_USE_FIXED_TLS && !defined(MI_WIN_USE_FLS)
|
#elif _WIN32 && MI_WIN_USE_FIXED_TLS && !defined(MI_WIN_USE_FLS)
|
||||||
|
|
||||||
// On windows we can store the thread-local heap at a fixed TLS slot to avoid
|
// On windows we can store the thread-local heap at a fixed TLS slot to avoid
|
||||||
// thread-local initialization checks in the fast path. This uses a fixed location
|
// thread-local initialization checks in the fast path.
|
||||||
// in the TCB though (last user-reserved slot by default) which may clash with other applications.
|
// We always use the second user TLS slot (the first one is always allocated already),
|
||||||
|
// and at initialization (`windows/prim.c`) we call TlsAlloc and verify
|
||||||
|
// we indeed get the second slot (and fail otherwise).
|
||||||
|
// Todo: we could make the Tls slot completely dynamic but that would require
|
||||||
|
// an extra read of the static Tls slot instead of using a constant offset.
|
||||||
#define MI_HAS_TLS_SLOT 2 // 2 = we can reliably initialize the slot (saving a test on each malloc)
|
#define MI_HAS_TLS_SLOT 2 // 2 = we can reliably initialize the slot (saving a test on each malloc)
|
||||||
|
|
||||||
#if MI_WIN_USE_FIXED_TLS > 1
|
#if MI_WIN_USE_FIXED_TLS > 1
|
||||||
#define MI_TLS_SLOT (MI_WIN_USE_FIXED_TLS)
|
#define MI_TLS_SLOT (MI_WIN_USE_FIXED_TLS)
|
||||||
#elif MI_SIZE_SIZE == 4
|
#elif MI_SIZE_SIZE == 4
|
||||||
#define MI_TLS_SLOT (0x710) // Last user-reserved slot <https://en.wikipedia.org/wiki/Win32_Thread_Information_Block>
|
#define MI_TLS_SLOT (0x0E18) // Second User TLS slot <https://en.wikipedia.org/wiki/Win32_Thread_Information_Block>
|
||||||
// #define MI_TLS_SLOT (0xF0C) // Last TlsSlot (might clash with other app reserved slot)
|
|
||||||
#else
|
#else
|
||||||
#define MI_TLS_SLOT (0x888) // Last user-reserved slot <https://en.wikipedia.org/wiki/Win32_Thread_Information_Block>
|
#define MI_TLS_SLOT (0x1488) // Second User TLS slot <https://en.wikipedia.org/wiki/Win32_Thread_Information_Block>
|
||||||
// #define MI_TLS_SLOT (0x1678) // Last TlsSlot (might clash with other app reserved slot)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline void* mi_prim_tls_slot(size_t slot) mi_attr_noexcept {
|
static inline void* mi_prim_tls_slot(size_t slot) mi_attr_noexcept {
|
||||||
|
|
6
src/os.c
6
src/os.c
|
@ -1,5 +1,5 @@
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
Copyright (c) 2018-2023, Microsoft Research, Daan Leijen
|
Copyright (c) 2018-2025, Microsoft Research, Daan Leijen
|
||||||
This is free software; you can redistribute it and/or modify it under the
|
This is free software; you can redistribute it and/or modify it under the
|
||||||
terms of the MIT license. A copy of the license can be found in the file
|
terms of the MIT license. A copy of the license can be found in the file
|
||||||
"LICENSE" at the root of this distribution.
|
"LICENSE" at the root of this distribution.
|
||||||
|
@ -152,8 +152,8 @@ static void mi_os_free_huge_os_pages(void* p, size_t size);
|
||||||
|
|
||||||
static void mi_os_prim_free(void* addr, size_t size, size_t commit_size) {
|
static void mi_os_prim_free(void* addr, size_t size, size_t commit_size) {
|
||||||
mi_assert_internal((size % _mi_os_page_size()) == 0);
|
mi_assert_internal((size % _mi_os_page_size()) == 0);
|
||||||
if (addr == NULL || size == 0) return; // || _mi_os_is_huge_reserved(addr)
|
if (addr == NULL) return; // || _mi_os_is_huge_reserved(addr)
|
||||||
int err = _mi_prim_free(addr, size);
|
int err = _mi_prim_free(addr, size); // allow size==0 (issue #1041)
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
_mi_warning_message("unable to free OS memory (error: %d (0x%x), size: 0x%zx bytes, address: %p)\n", err, err, size, addr);
|
_mi_warning_message("unable to free OS memory (error: %d (0x%x), size: 0x%zx bytes, address: %p)\n", err, err, size, addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
Copyright (c) 2018-2023, Microsoft Research, Daan Leijen, Alon Zakai
|
Copyright (c) 2018-2025, Microsoft Research, Daan Leijen, Alon Zakai
|
||||||
This is free software; you can redistribute it and/or modify it under the
|
This is free software; you can redistribute it and/or modify it under the
|
||||||
terms of the MIT license. A copy of the license can be found in the file
|
terms of the MIT license. A copy of the license can be found in the file
|
||||||
"LICENSE" at the root of this distribution.
|
"LICENSE" at the root of this distribution.
|
||||||
|
@ -58,7 +58,7 @@ void _mi_prim_mem_init( mi_os_mem_config_t* config) {
|
||||||
extern void emmalloc_free(void*);
|
extern void emmalloc_free(void*);
|
||||||
|
|
||||||
int _mi_prim_free(void* addr, size_t size) {
|
int _mi_prim_free(void* addr, size_t size) {
|
||||||
MI_UNUSED(size);
|
if (size==0) return 0;
|
||||||
emmalloc_free(addr);
|
emmalloc_free(addr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
Copyright (c) 2018-2023, Microsoft Research, Daan Leijen
|
Copyright (c) 2018-2025, Microsoft Research, Daan Leijen
|
||||||
This is free software; you can redistribute it and/or modify it under the
|
This is free software; you can redistribute it and/or modify it under the
|
||||||
terms of the MIT license. A copy of the license can be found in the file
|
terms of the MIT license. A copy of the license can be found in the file
|
||||||
"LICENSE" at the root of this distribution.
|
"LICENSE" at the root of this distribution.
|
||||||
|
@ -70,6 +70,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
#define MADV_FREE POSIX_MADV_FREE
|
#define MADV_FREE POSIX_MADV_FREE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MI_UNIX_LARGE_PAGE_SIZE (2*MI_MiB) // TODO: can we query the OS for this?
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
// Use syscalls for some primitives to allow for libraries that override open/read/close etc.
|
// Use syscalls for some primitives to allow for libraries that override open/read/close etc.
|
||||||
|
@ -156,7 +157,7 @@ void _mi_prim_mem_init( mi_os_mem_config_t* config )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
config->large_page_size = 2*MI_MiB; // TODO: can we query the OS for this?
|
config->large_page_size = MI_UNIX_LARGE_PAGE_SIZE;
|
||||||
config->has_overcommit = unix_detect_overcommit();
|
config->has_overcommit = unix_detect_overcommit();
|
||||||
config->has_partial_free = true; // mmap can free in parts
|
config->has_partial_free = true; // mmap can free in parts
|
||||||
config->has_virtual_reserve = true; // todo: check if this true for NetBSD? (for anonymous mmap with PROT_NONE)
|
config->has_virtual_reserve = true; // todo: check if this true for NetBSD? (for anonymous mmap with PROT_NONE)
|
||||||
|
@ -186,6 +187,7 @@ void _mi_prim_mem_init( mi_os_mem_config_t* config )
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
|
|
||||||
int _mi_prim_free(void* addr, size_t size ) {
|
int _mi_prim_free(void* addr, size_t size ) {
|
||||||
|
if (size==0) return 0;
|
||||||
bool err = (munmap(addr, size) == -1);
|
bool err = (munmap(addr, size) == -1);
|
||||||
return (err ? errno : 0);
|
return (err ? errno : 0);
|
||||||
}
|
}
|
||||||
|
@ -385,6 +387,9 @@ int _mi_prim_alloc(void* hint_addr, size_t size, size_t try_alignment, bool comm
|
||||||
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);
|
||||||
|
if (hint_addr == NULL && size >= 8*MI_UNIX_LARGE_PAGE_SIZE && try_alignment > 1 && _mi_is_power_of_two(try_alignment) && try_alignment < MI_UNIX_LARGE_PAGE_SIZE) {
|
||||||
|
try_alignment = MI_UNIX_LARGE_PAGE_SIZE; // try to align along large page size for larger allocations
|
||||||
|
}
|
||||||
|
|
||||||
*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);
|
||||||
|
@ -428,7 +433,7 @@ int _mi_prim_decommit(void* start, size_t size, bool* needs_recommit) {
|
||||||
int err = 0;
|
int err = 0;
|
||||||
// decommit: use MADV_DONTNEED as it decreases rss immediately (unlike MADV_FREE)
|
// decommit: use MADV_DONTNEED as it decreases rss immediately (unlike MADV_FREE)
|
||||||
err = unix_madvise(start, size, MADV_DONTNEED);
|
err = unix_madvise(start, size, MADV_DONTNEED);
|
||||||
#if !MI_DEBUG && !MI_SECURE
|
#if !MI_DEBUG && MI_SECURE<=2
|
||||||
*needs_recommit = false;
|
*needs_recommit = false;
|
||||||
#else
|
#else
|
||||||
*needs_recommit = true;
|
*needs_recommit = true;
|
||||||
|
|
|
@ -631,9 +631,21 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) {
|
||||||
MI_UNUSED(reserved);
|
MI_UNUSED(reserved);
|
||||||
MI_UNUSED(module);
|
MI_UNUSED(module);
|
||||||
#if MI_TLS_SLOT >= 2
|
#if MI_TLS_SLOT >= 2
|
||||||
if ((reason==DLL_PROCESS_ATTACH || reason==DLL_THREAD_ATTACH) && mi_prim_get_default_heap() == NULL) {
|
if (reason==DLL_PROCESS_ATTACH) {
|
||||||
|
const DWORD tls_slot = TlsAlloc();
|
||||||
|
if (tls_slot != 1) {
|
||||||
|
_mi_error_message(EFAULT, "unable to allocate the second TLS slot (rebuild without MI_WIN_USE_FIXED_TLS?)\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (reason==DLL_PROCESS_ATTACH || reason==DLL_THREAD_ATTACH) {
|
||||||
|
if (mi_prim_get_default_heap() == NULL) {
|
||||||
_mi_heap_set_default_direct((mi_heap_t*)&_mi_heap_empty);
|
_mi_heap_set_default_direct((mi_heap_t*)&_mi_heap_empty);
|
||||||
}
|
}
|
||||||
|
#if MI_DEBUG
|
||||||
|
void* const p = TlsGetValue(1);
|
||||||
|
mi_assert_internal(p == (void*)&_mi_heap_empty);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (reason==DLL_PROCESS_ATTACH) {
|
if (reason==DLL_PROCESS_ATTACH) {
|
||||||
_mi_process_load();
|
_mi_process_load();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Issue #981: test overriding allocation in a DLL that is compiled independent of mimalloc.
|
// Issue #981: test overriding allocation in a DLL that is compiled independent of mimalloc.
|
||||||
// This is imported by the `mimalloc-test-override` project.
|
// This is imported by the `mimalloc-test-override` project.
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
#include "main-override-dep.h"
|
#include "main-override-dep.h"
|
||||||
|
|
||||||
std::string TestAllocInDll::GetString()
|
std::string TestAllocInDll::GetString()
|
||||||
|
@ -10,6 +11,41 @@ std::string TestAllocInDll::GetString()
|
||||||
const char* t = "test";
|
const char* t = "test";
|
||||||
memcpy(test, t, 4);
|
memcpy(test, t, 4);
|
||||||
std::string r = test;
|
std::string r = test;
|
||||||
|
std::cout << "override-dep: GetString: " << r << "\n";
|
||||||
delete[] test;
|
delete[] test;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Static {
|
||||||
|
private:
|
||||||
|
void* p;
|
||||||
|
public:
|
||||||
|
Static() {
|
||||||
|
printf("override-dep: static constructor\n");
|
||||||
|
p = malloc(64);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
~Static() {
|
||||||
|
free(p);
|
||||||
|
printf("override-dep: static destructor\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static Static s = Static();
|
||||||
|
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE module, DWORD reason, LPVOID reserved) {
|
||||||
|
(void)(reserved);
|
||||||
|
(void)(module);
|
||||||
|
if (reason==DLL_PROCESS_ATTACH) {
|
||||||
|
printf("override-dep: dll attach\n");
|
||||||
|
}
|
||||||
|
else if (reason==DLL_PROCESS_DETACH) {
|
||||||
|
printf("override-dep: dll detach\n");
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ static void test_thread_local(); // issue #944
|
||||||
static void test_mixed1(); // issue #942
|
static void test_mixed1(); // issue #942
|
||||||
static void test_stl_allocators();
|
static void test_stl_allocators();
|
||||||
|
|
||||||
#if x_WIN32
|
#if _WIN32
|
||||||
#include "main-override-dep.h"
|
#include "main-override-dep.h"
|
||||||
static void test_dep(); // issue #981: test overriding in another DLL
|
static void test_dep(); // issue #981: test overriding in another DLL
|
||||||
#else
|
#else
|
||||||
|
@ -150,11 +150,12 @@ static bool test_stl_allocator1() {
|
||||||
struct some_struct { int i; int j; double z; };
|
struct some_struct { int i; int j; double z; };
|
||||||
|
|
||||||
|
|
||||||
#if x_WIN32
|
#if _WIN32
|
||||||
static void test_dep()
|
static void test_dep()
|
||||||
{
|
{
|
||||||
TestAllocInDll t;
|
TestAllocInDll t;
|
||||||
std::string s = t.GetString();
|
std::string s = t.GetString();
|
||||||
|
std::cout << "test_dep GetString: " << s << "\n";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue