mirror of
https://github.com/microsoft/mimalloc.git
synced 2025-07-01 17:24:38 +03:00
Merge branch 'dev' into dev3
This commit is contained in:
commit
8253ac1bd9
4 changed files with 51 additions and 23 deletions
|
@ -734,10 +734,12 @@ if (MI_BUILD_TESTS)
|
||||||
target_compile_definitions(mimalloc-test-${TEST_NAME} PRIVATE ${mi_defines})
|
target_compile_definitions(mimalloc-test-${TEST_NAME} PRIVATE ${mi_defines})
|
||||||
target_compile_options(mimalloc-test-${TEST_NAME} PRIVATE ${mi_cflags})
|
target_compile_options(mimalloc-test-${TEST_NAME} PRIVATE ${mi_cflags})
|
||||||
target_include_directories(mimalloc-test-${TEST_NAME} PRIVATE include)
|
target_include_directories(mimalloc-test-${TEST_NAME} PRIVATE include)
|
||||||
if(MI_BUILD_SHARED AND (MI_TRACK_ASAN OR MI_DEBUG_TSAN OR MI_DEBUG_UBSAN))
|
if(MI_BUILD_STATIC AND NOT MI_DEBUG_TSAN)
|
||||||
|
target_link_libraries(mimalloc-test-${TEST_NAME} PRIVATE mimalloc-static ${mi_libraries})
|
||||||
|
elseif(MI_BUILD_SHARED)
|
||||||
target_link_libraries(mimalloc-test-${TEST_NAME} PRIVATE mimalloc ${mi_libraries})
|
target_link_libraries(mimalloc-test-${TEST_NAME} PRIVATE mimalloc ${mi_libraries})
|
||||||
else()
|
else()
|
||||||
target_link_libraries(mimalloc-test-${TEST_NAME} PRIVATE mimalloc-static ${mi_libraries})
|
message(STATUS "cannot build TSAN tests without MI_BUILD_SHARED being enabled")
|
||||||
endif()
|
endif()
|
||||||
add_test(NAME test-${TEST_NAME} COMMAND mimalloc-test-${TEST_NAME})
|
add_test(NAME test-${TEST_NAME} COMMAND mimalloc-test-${TEST_NAME})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
|
@ -71,24 +71,20 @@ typedef void* mi_nothrow_t;
|
||||||
#define MI_INTERPOSE_FUN(oldfun,newfun) { (const void*)&newfun, (const void*)&oldfun }
|
#define MI_INTERPOSE_FUN(oldfun,newfun) { (const void*)&newfun, (const void*)&oldfun }
|
||||||
#define MI_INTERPOSE_MI(fun) MI_INTERPOSE_FUN(fun,mi_##fun)
|
#define MI_INTERPOSE_MI(fun) MI_INTERPOSE_FUN(fun,mi_##fun)
|
||||||
|
|
||||||
__attribute__((used)) static struct mi_interpose_s _mi_interposes[] __attribute__((section("__DATA, __interpose"))) =
|
#define MI_INTERPOSE_DECLS(name) __attribute__((used)) static struct mi_interpose_s name[] __attribute__((section("__DATA, __interpose")))
|
||||||
|
|
||||||
|
MI_INTERPOSE_DECLS(_mi_interposes) =
|
||||||
{
|
{
|
||||||
MI_INTERPOSE_MI(malloc),
|
MI_INTERPOSE_MI(malloc),
|
||||||
MI_INTERPOSE_MI(calloc),
|
MI_INTERPOSE_MI(calloc),
|
||||||
MI_INTERPOSE_MI(realloc),
|
MI_INTERPOSE_MI(realloc),
|
||||||
MI_INTERPOSE_MI(strdup),
|
MI_INTERPOSE_MI(strdup),
|
||||||
#if defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
|
||||||
MI_INTERPOSE_MI(strndup),
|
|
||||||
#endif
|
|
||||||
MI_INTERPOSE_MI(realpath),
|
MI_INTERPOSE_MI(realpath),
|
||||||
MI_INTERPOSE_MI(posix_memalign),
|
MI_INTERPOSE_MI(posix_memalign),
|
||||||
MI_INTERPOSE_MI(reallocf),
|
MI_INTERPOSE_MI(reallocf),
|
||||||
MI_INTERPOSE_MI(valloc),
|
MI_INTERPOSE_MI(valloc),
|
||||||
MI_INTERPOSE_FUN(malloc_size,mi_malloc_size_checked),
|
MI_INTERPOSE_FUN(malloc_size,mi_malloc_size_checked),
|
||||||
MI_INTERPOSE_MI(malloc_good_size),
|
MI_INTERPOSE_MI(malloc_good_size),
|
||||||
#if defined(MAC_OS_X_VERSION_10_15) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15
|
|
||||||
MI_INTERPOSE_MI(aligned_alloc),
|
|
||||||
#endif
|
|
||||||
#ifdef MI_OSX_ZONE
|
#ifdef MI_OSX_ZONE
|
||||||
// we interpose malloc_default_zone in alloc-override-osx.c so we can use mi_free safely
|
// we interpose malloc_default_zone in alloc-override-osx.c so we can use mi_free safely
|
||||||
MI_INTERPOSE_MI(free),
|
MI_INTERPOSE_MI(free),
|
||||||
|
@ -99,6 +95,12 @@ typedef void* mi_nothrow_t;
|
||||||
MI_INTERPOSE_FUN(vfree,mi_cfree),
|
MI_INTERPOSE_FUN(vfree,mi_cfree),
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
MI_INTERPOSE_DECLS(_mi_interposes_10_7) __OSX_AVAILABLE(10.7) = {
|
||||||
|
MI_INTERPOSE_MI(strndup),
|
||||||
|
};
|
||||||
|
MI_INTERPOSE_DECLS(_mi_interposes_10_15) __OSX_AVAILABLE(10.15) = {
|
||||||
|
MI_INTERPOSE_MI(aligned_alloc),
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -439,14 +439,14 @@ static mi_decl_noinline void mi_recurse_exit_prim(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mi_recurse_enter(void) {
|
static bool mi_recurse_enter(void) {
|
||||||
#if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD)
|
#if defined(__APPLE__) || defined(__ANDROID__) || defined(MI_TLS_RECURSE_GUARD)
|
||||||
if (_mi_preloading()) return false;
|
if (_mi_preloading()) return false;
|
||||||
#endif
|
#endif
|
||||||
return mi_recurse_enter_prim();
|
return mi_recurse_enter_prim();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mi_recurse_exit(void) {
|
static void mi_recurse_exit(void) {
|
||||||
#if defined(__APPLE__) || defined(MI_TLS_RECURSE_GUARD)
|
#if defined(__APPLE__) || defined(__ANDROID__) || defined(MI_TLS_RECURSE_GUARD)
|
||||||
if (_mi_preloading()) return;
|
if (_mi_preloading()) return;
|
||||||
#endif
|
#endif
|
||||||
mi_recurse_exit_prim();
|
mi_recurse_exit_prim();
|
||||||
|
|
|
@ -12,6 +12,10 @@ terms of the MIT license. A copy of the license can be found in the file
|
||||||
#include "mimalloc/prim.h"
|
#include "mimalloc/prim.h"
|
||||||
#include <stdio.h> // fputs, stderr
|
#include <stdio.h> // fputs, stderr
|
||||||
|
|
||||||
|
// xbox has no console IO
|
||||||
|
#if !defined(WINAPI_FAMILY_PARTITION) || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
|
||||||
|
#define MI_HAS_CONSOLE_IO
|
||||||
|
#endif
|
||||||
|
|
||||||
//---------------------------------------------
|
//---------------------------------------------
|
||||||
// Dynamically bind Windows API points for portability
|
// Dynamically bind Windows API points for portability
|
||||||
|
@ -53,21 +57,29 @@ typedef struct MI_MEM_ADDRESS_REQUIREMENTS_S {
|
||||||
|
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
typedef PVOID (__stdcall *PVirtualAlloc2)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, MI_MEM_EXTENDED_PARAMETER*, ULONG);
|
typedef PVOID (__stdcall *PVirtualAlloc2)(HANDLE, PVOID, SIZE_T, ULONG, ULONG, MI_MEM_EXTENDED_PARAMETER*, ULONG);
|
||||||
typedef NTSTATUS (__stdcall *PNtAllocateVirtualMemoryEx)(HANDLE, PVOID*, SIZE_T*, ULONG, ULONG, MI_MEM_EXTENDED_PARAMETER*, ULONG);
|
typedef LONG (__stdcall *PNtAllocateVirtualMemoryEx)(HANDLE, PVOID*, SIZE_T*, ULONG, ULONG, MI_MEM_EXTENDED_PARAMETER*, ULONG); // avoid NTSTATUS as it is not defined on xbox (pr #1084)
|
||||||
static PVirtualAlloc2 pVirtualAlloc2 = NULL;
|
static PVirtualAlloc2 pVirtualAlloc2 = NULL;
|
||||||
static PNtAllocateVirtualMemoryEx pNtAllocateVirtualMemoryEx = NULL;
|
static PNtAllocateVirtualMemoryEx pNtAllocateVirtualMemoryEx = NULL;
|
||||||
|
|
||||||
// Similarly, GetNumaProcessorNodeEx is only supported since Windows 7
|
// Similarly, GetNumaProcessorNodeEx is only supported since Windows 7 (and GetNumaNodeProcessorMask is not supported on xbox)
|
||||||
typedef struct MI_PROCESSOR_NUMBER_S { WORD Group; BYTE Number; BYTE Reserved; } MI_PROCESSOR_NUMBER;
|
typedef struct MI_PROCESSOR_NUMBER_S { WORD Group; BYTE Number; BYTE Reserved; } MI_PROCESSOR_NUMBER;
|
||||||
|
|
||||||
typedef VOID (__stdcall *PGetCurrentProcessorNumberEx)(MI_PROCESSOR_NUMBER* ProcNumber);
|
typedef VOID (__stdcall *PGetCurrentProcessorNumberEx)(MI_PROCESSOR_NUMBER* ProcNumber);
|
||||||
typedef BOOL (__stdcall *PGetNumaProcessorNodeEx)(MI_PROCESSOR_NUMBER* Processor, PUSHORT NodeNumber);
|
typedef BOOL (__stdcall *PGetNumaProcessorNodeEx)(MI_PROCESSOR_NUMBER* Processor, PUSHORT NodeNumber);
|
||||||
typedef BOOL (__stdcall* PGetNumaNodeProcessorMaskEx)(USHORT Node, PGROUP_AFFINITY ProcessorMask);
|
typedef BOOL (__stdcall* PGetNumaNodeProcessorMaskEx)(USHORT Node, PGROUP_AFFINITY ProcessorMask);
|
||||||
typedef BOOL (__stdcall *PGetNumaProcessorNode)(UCHAR Processor, PUCHAR NodeNumber);
|
typedef BOOL (__stdcall *PGetNumaProcessorNode)(UCHAR Processor, PUCHAR NodeNumber);
|
||||||
|
typedef BOOL (__stdcall* PGetNumaNodeProcessorMask)(UCHAR Node, PULONGLONG ProcessorMask);
|
||||||
|
typedef BOOL (__stdcall* PGetNumaHighestNodeNumber)(PULONG Node);
|
||||||
static PGetCurrentProcessorNumberEx pGetCurrentProcessorNumberEx = NULL;
|
static PGetCurrentProcessorNumberEx pGetCurrentProcessorNumberEx = NULL;
|
||||||
static PGetNumaProcessorNodeEx pGetNumaProcessorNodeEx = NULL;
|
static PGetNumaProcessorNodeEx pGetNumaProcessorNodeEx = NULL;
|
||||||
static PGetNumaNodeProcessorMaskEx pGetNumaNodeProcessorMaskEx = NULL;
|
static PGetNumaNodeProcessorMaskEx pGetNumaNodeProcessorMaskEx = NULL;
|
||||||
static PGetNumaProcessorNode pGetNumaProcessorNode = NULL;
|
static PGetNumaProcessorNode pGetNumaProcessorNode = NULL;
|
||||||
|
static PGetNumaNodeProcessorMask pGetNumaNodeProcessorMask = NULL;
|
||||||
|
static PGetNumaHighestNodeNumber pGetNumaHighestNodeNumber = NULL;
|
||||||
|
|
||||||
|
// Not available on xbox
|
||||||
|
typedef SIZE_T(__stdcall* PGetLargePageMinimum)(VOID);
|
||||||
|
static PGetLargePageMinimum pGetLargePageMinimum = NULL;
|
||||||
|
|
||||||
// Available after Windows XP
|
// Available after Windows XP
|
||||||
typedef BOOL (__stdcall *PGetPhysicallyInstalledSystemMemory)( PULONGLONG TotalMemoryInKilobytes );
|
typedef BOOL (__stdcall *PGetPhysicallyInstalledSystemMemory)( PULONGLONG TotalMemoryInKilobytes );
|
||||||
|
@ -83,6 +95,7 @@ static bool win_enable_large_os_pages(size_t* large_page_size)
|
||||||
static bool large_initialized = false;
|
static bool large_initialized = false;
|
||||||
if (large_initialized) return (_mi_os_large_page_size() > 0);
|
if (large_initialized) return (_mi_os_large_page_size() > 0);
|
||||||
large_initialized = true;
|
large_initialized = true;
|
||||||
|
if (pGetLargePageMinimum==NULL) return false; // no large page support (xbox etc.)
|
||||||
|
|
||||||
// Try to see if large OS pages are supported
|
// Try to see if large OS pages are supported
|
||||||
// To use large pages on Windows, we first need access permission
|
// To use large pages on Windows, we first need access permission
|
||||||
|
@ -101,8 +114,8 @@ static bool win_enable_large_os_pages(size_t* large_page_size)
|
||||||
if (ok) {
|
if (ok) {
|
||||||
err = GetLastError();
|
err = GetLastError();
|
||||||
ok = (err == ERROR_SUCCESS);
|
ok = (err == ERROR_SUCCESS);
|
||||||
if (ok && large_page_size != NULL) {
|
if (ok && large_page_size != NULL && pGetLargePageMinimum != NULL) {
|
||||||
*large_page_size = GetLargePageMinimum();
|
*large_page_size = (*pGetLargePageMinimum)();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,6 +176,9 @@ void _mi_prim_mem_init( mi_os_mem_config_t* config )
|
||||||
pGetNumaProcessorNodeEx = (PGetNumaProcessorNodeEx)(void (*)(void))GetProcAddress(hDll, "GetNumaProcessorNodeEx");
|
pGetNumaProcessorNodeEx = (PGetNumaProcessorNodeEx)(void (*)(void))GetProcAddress(hDll, "GetNumaProcessorNodeEx");
|
||||||
pGetNumaNodeProcessorMaskEx = (PGetNumaNodeProcessorMaskEx)(void (*)(void))GetProcAddress(hDll, "GetNumaNodeProcessorMaskEx");
|
pGetNumaNodeProcessorMaskEx = (PGetNumaNodeProcessorMaskEx)(void (*)(void))GetProcAddress(hDll, "GetNumaNodeProcessorMaskEx");
|
||||||
pGetNumaProcessorNode = (PGetNumaProcessorNode)(void (*)(void))GetProcAddress(hDll, "GetNumaProcessorNode");
|
pGetNumaProcessorNode = (PGetNumaProcessorNode)(void (*)(void))GetProcAddress(hDll, "GetNumaProcessorNode");
|
||||||
|
pGetNumaNodeProcessorMask = (PGetNumaNodeProcessorMask)(void (*)(void))GetProcAddress(hDll, "GetNumaNodeProcessorMask");
|
||||||
|
pGetNumaHighestNodeNumber = (PGetNumaHighestNodeNumber)(void (*)(void))GetProcAddress(hDll, "GetNumaHighestNodeNumber");
|
||||||
|
pGetLargePageMinimum = (PGetLargePageMinimum)(void (*)(void))GetProcAddress(hDll, "GetLargePageMinimum");
|
||||||
// Get physical memory (not available on XP, so check dynamically)
|
// Get physical memory (not available on XP, so check dynamically)
|
||||||
PGetPhysicallyInstalledSystemMemory pGetPhysicallyInstalledSystemMemory = (PGetPhysicallyInstalledSystemMemory)(void (*)(void))GetProcAddress(hDll,"GetPhysicallyInstalledSystemMemory");
|
PGetPhysicallyInstalledSystemMemory pGetPhysicallyInstalledSystemMemory = (PGetPhysicallyInstalledSystemMemory)(void (*)(void))GetProcAddress(hDll,"GetPhysicallyInstalledSystemMemory");
|
||||||
if (pGetPhysicallyInstalledSystemMemory != NULL) {
|
if (pGetPhysicallyInstalledSystemMemory != NULL) {
|
||||||
|
@ -412,7 +428,7 @@ static void* _mi_prim_alloc_huge_os_pagesx(void* hint_addr, size_t size, int num
|
||||||
}
|
}
|
||||||
SIZE_T psize = size;
|
SIZE_T psize = size;
|
||||||
void* base = hint_addr;
|
void* base = hint_addr;
|
||||||
NTSTATUS err = (*pNtAllocateVirtualMemoryEx)(GetCurrentProcess(), &base, &psize, flags, PAGE_READWRITE, params, param_count);
|
LONG err = (*pNtAllocateVirtualMemoryEx)(GetCurrentProcess(), &base, &psize, flags, PAGE_READWRITE, params, param_count);
|
||||||
if (err == 0 && base != NULL) {
|
if (err == 0 && base != NULL) {
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
@ -466,9 +482,11 @@ size_t _mi_prim_numa_node(void) {
|
||||||
|
|
||||||
size_t _mi_prim_numa_node_count(void) {
|
size_t _mi_prim_numa_node_count(void) {
|
||||||
ULONG numa_max = 0;
|
ULONG numa_max = 0;
|
||||||
GetNumaHighestNodeNumber(&numa_max);
|
if (pGetNumaHighestNodeNumber!=NULL) {
|
||||||
|
(*pGetNumaHighestNodeNumber)(&numa_max);
|
||||||
|
}
|
||||||
// find the highest node number that has actual processors assigned to it. Issue #282
|
// find the highest node number that has actual processors assigned to it. Issue #282
|
||||||
while(numa_max > 0) {
|
while (numa_max > 0) {
|
||||||
if (pGetNumaNodeProcessorMaskEx != NULL) {
|
if (pGetNumaNodeProcessorMaskEx != NULL) {
|
||||||
// Extended API is supported
|
// Extended API is supported
|
||||||
GROUP_AFFINITY affinity;
|
GROUP_AFFINITY affinity;
|
||||||
|
@ -479,8 +497,10 @@ size_t _mi_prim_numa_node_count(void) {
|
||||||
else {
|
else {
|
||||||
// Vista or earlier, use older API that is limited to 64 processors.
|
// Vista or earlier, use older API that is limited to 64 processors.
|
||||||
ULONGLONG mask;
|
ULONGLONG mask;
|
||||||
if (GetNumaNodeProcessorMask((UCHAR)numa_max, &mask)) {
|
if (pGetNumaNodeProcessorMask != NULL) {
|
||||||
|
if ((*pGetNumaNodeProcessorMask)((UCHAR)numa_max, &mask)) {
|
||||||
if (mask != 0) break; // found the maximum non-empty node
|
if (mask != 0) break; // found the maximum non-empty node
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// max node was invalid or had no processor assigned, try again
|
// max node was invalid or had no processor assigned, try again
|
||||||
|
@ -570,17 +590,21 @@ void _mi_prim_out_stderr( const char* msg )
|
||||||
if (!_mi_preloading()) {
|
if (!_mi_preloading()) {
|
||||||
// _cputs(msg); // _cputs cannot be used as it aborts when failing to lock the console
|
// _cputs(msg); // _cputs cannot be used as it aborts when failing to lock the console
|
||||||
static HANDLE hcon = INVALID_HANDLE_VALUE;
|
static HANDLE hcon = INVALID_HANDLE_VALUE;
|
||||||
static bool hconIsConsole;
|
static bool hconIsConsole = false;
|
||||||
if (hcon == INVALID_HANDLE_VALUE) {
|
if (hcon == INVALID_HANDLE_VALUE) {
|
||||||
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
|
||||||
hcon = GetStdHandle(STD_ERROR_HANDLE);
|
hcon = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
#ifdef MI_HAS_CONSOLE_IO
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO sbi;
|
||||||
hconIsConsole = ((hcon != INVALID_HANDLE_VALUE) && GetConsoleScreenBufferInfo(hcon, &sbi));
|
hconIsConsole = ((hcon != INVALID_HANDLE_VALUE) && GetConsoleScreenBufferInfo(hcon, &sbi));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
const size_t len = _mi_strlen(msg);
|
const size_t len = _mi_strlen(msg);
|
||||||
if (len > 0 && len < UINT32_MAX) {
|
if (len > 0 && len < UINT32_MAX) {
|
||||||
DWORD written = 0;
|
DWORD written = 0;
|
||||||
if (hconIsConsole) {
|
if (hconIsConsole) {
|
||||||
|
#ifdef MI_HAS_CONSOLE_IO
|
||||||
WriteConsoleA(hcon, msg, (DWORD)len, &written, NULL);
|
WriteConsoleA(hcon, msg, (DWORD)len, &written, NULL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else if (hcon != INVALID_HANDLE_VALUE) {
|
else if (hcon != INVALID_HANDLE_VALUE) {
|
||||||
// use direct write if stderr was redirected
|
// use direct write if stderr was redirected
|
||||||
|
|
Loading…
Add table
Reference in a new issue