fix build on non desktop windows app partitions

This commit is contained in:
Max Bachmann 2025-05-06 23:49:23 +02:00 committed by GitHub
parent e2d7c24c73
commit 0a8cffcbba
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG key ID: B5690EEEBB952194

View file

@ -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
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
#define MI_HAS_HUGE_PAGE_API
#define MI_HAS_CONSOLE_IO
#endif
//--------------------------------------------- //---------------------------------------------
// Dynamically bind Windows API points for portability // Dynamically bind Windows API points for portability
@ -46,9 +50,11 @@ 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);
static PVirtualAlloc2 pVirtualAlloc2 = NULL; static PVirtualAlloc2 pVirtualAlloc2 = NULL;
#ifdef MI_HAS_HUGE_PAGE_API
typedef NTSTATUS (__stdcall *PNtAllocateVirtualMemoryEx)(HANDLE, PVOID*, SIZE_T*, ULONG, ULONG, MI_MEM_EXTENDED_PARAMETER*, ULONG);
static PNtAllocateVirtualMemoryEx pNtAllocateVirtualMemoryEx = NULL; static PNtAllocateVirtualMemoryEx pNtAllocateVirtualMemoryEx = NULL;
#endif
// Similarly, GetNumaProcessorNodeEx is only supported since Windows 7 // Similarly, GetNumaProcessorNodeEx is only supported since Windows 7
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;
@ -75,6 +81,7 @@ static bool win_enable_large_os_pages(size_t* large_page_size)
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;
#ifdef MI_HAS_HUGE_PAGE_API
// 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
// Set "Lock pages in memory" permission in the group policy editor // Set "Lock pages in memory" permission in the group policy editor
@ -104,6 +111,10 @@ static bool win_enable_large_os_pages(size_t* large_page_size)
_mi_warning_message("cannot enable large OS page support, error %lu\n", err); _mi_warning_message("cannot enable large OS page support, error %lu\n", err);
} }
return (ok!=0); return (ok!=0);
#else
_mi_warning_message("large OS pages unsupported in this winapi partition\n");
return false;
#endif
} }
@ -136,12 +147,14 @@ void _mi_prim_mem_init( mi_os_mem_config_t* config )
if (pVirtualAlloc2==NULL) pVirtualAlloc2 = (PVirtualAlloc2)(void (*)(void))GetProcAddress(hDll, "VirtualAlloc2"); if (pVirtualAlloc2==NULL) pVirtualAlloc2 = (PVirtualAlloc2)(void (*)(void))GetProcAddress(hDll, "VirtualAlloc2");
FreeLibrary(hDll); FreeLibrary(hDll);
} }
#ifdef MI_HAS_HUGE_PAGE_API
// NtAllocateVirtualMemoryEx is used for huge page allocation // NtAllocateVirtualMemoryEx is used for huge page allocation
hDll = LoadLibrary(TEXT("ntdll.dll")); hDll = LoadLibrary(TEXT("ntdll.dll"));
if (hDll != NULL) { if (hDll != NULL) {
pNtAllocateVirtualMemoryEx = (PNtAllocateVirtualMemoryEx)(void (*)(void))GetProcAddress(hDll, "NtAllocateVirtualMemoryEx"); pNtAllocateVirtualMemoryEx = (PNtAllocateVirtualMemoryEx)(void (*)(void))GetProcAddress(hDll, "NtAllocateVirtualMemoryEx");
FreeLibrary(hDll); FreeLibrary(hDll);
} }
#endif
// Try to use Win7+ numa API // Try to use Win7+ numa API
hDll = LoadLibrary(TEXT("kernel32.dll")); hDll = LoadLibrary(TEXT("kernel32.dll"));
if (hDll != NULL) { if (hDll != NULL) {
@ -370,6 +383,7 @@ static void* _mi_prim_alloc_huge_os_pagesx(void* hint_addr, size_t size, int num
win_enable_large_os_pages(NULL); win_enable_large_os_pages(NULL);
MI_MEM_EXTENDED_PARAMETER params[3] = { {{0,0},{0}},{{0,0},{0}},{{0,0},{0}} }; MI_MEM_EXTENDED_PARAMETER params[3] = { {{0,0},{0}},{{0,0},{0}},{{0,0},{0}} };
#ifdef MI_HAS_HUGE_PAGE_API
// on modern Windows try use NtAllocateVirtualMemoryEx for 1GiB huge pages // on modern Windows try use NtAllocateVirtualMemoryEx for 1GiB huge pages
static bool mi_huge_pages_available = true; static bool mi_huge_pages_available = true;
if (pNtAllocateVirtualMemoryEx != NULL && mi_huge_pages_available) { if (pNtAllocateVirtualMemoryEx != NULL && mi_huge_pages_available) {
@ -393,6 +407,7 @@ static void* _mi_prim_alloc_huge_os_pagesx(void* hint_addr, size_t size, int num
_mi_warning_message("unable to allocate using huge (1GiB) pages, trying large (2MiB) pages instead (status 0x%lx)\n", err); _mi_warning_message("unable to allocate using huge (1GiB) pages, trying large (2MiB) pages instead (status 0x%lx)\n", err);
} }
} }
#endif
// on modern Windows try use VirtualAlloc2 for numa aware large OS page allocation // on modern Windows try use VirtualAlloc2 for numa aware large OS page allocation
if (pVirtualAlloc2 != NULL && numa_node >= 0) { if (pVirtualAlloc2 != NULL && numa_node >= 0) {
params[0].Type.Type = MiMemExtendedParameterNumaNode; params[0].Type.Type = MiMemExtendedParameterNumaNode;
@ -447,6 +462,7 @@ size_t _mi_prim_numa_node_count(void) {
if (affinity.Mask != 0) break; // found the maximum non-empty node if (affinity.Mask != 0) break; // found the maximum non-empty node
} }
} }
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
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;
@ -454,6 +470,7 @@ size_t _mi_prim_numa_node_count(void) {
if (mask != 0) break; // found the maximum non-empty node if (mask != 0) break; // found the maximum non-empty node
}; };
} }
#endif
// max node was invalid or had no processor assigned, try again // max node was invalid or had no processor assigned, try again
numa_max--; numa_max--;
} }
@ -541,19 +558,26 @@ 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;
#ifdef MI_HAS_CONSOLE_IO
static bool hconIsConsole; static bool hconIsConsole;
#endif
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;
#ifdef MI_HAS_CONSOLE_IO
if (hconIsConsole) { if (hconIsConsole) {
WriteConsoleA(hcon, msg, (DWORD)len, &written, NULL); WriteConsoleA(hcon, msg, (DWORD)len, &written, NULL);
} }
else if (hcon != INVALID_HANDLE_VALUE) { else
#endif
if (hcon != INVALID_HANDLE_VALUE) {
// use direct write if stderr was redirected // use direct write if stderr was redirected
WriteFile(hcon, msg, (DWORD)len, &written, NULL); WriteFile(hcon, msg, (DWORD)len, &written, NULL);
} }