ntdll: Add a magic parameter to NtFreeVirtualMemory() for releasing address space.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-08-03 12:02:51 +02:00
parent c44218ba50
commit 669d1cce03
5 changed files with 46 additions and 41 deletions

View File

@ -3775,6 +3775,17 @@ static void init_wow64( CONTEXT *context )
#endif
/* release some address space once dlls are loaded*/
static void release_address_space(void)
{
#ifndef _WIN64
void *addr = (void *)1;
SIZE_T size = 0;
NtFreeVirtualMemory( GetCurrentProcess(), &addr, &size, MEM_RELEASE );
#endif
}
/******************************************************************
* LdrInitializeThunk (NTDLL.@)
*
@ -3901,7 +3912,7 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR
NtTerminateProcess( GetCurrentProcess(), status );
}
}
unix_funcs->virtual_release_address_space();
release_address_space();
if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.DllBase, DLL_PROCESS_ATTACH );
if (wm->ldr.Flags & LDR_WINE_INTERNAL) unix_funcs->init_builtin_dll( wm->ldr.DllBase );
if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie );

View File

@ -1895,7 +1895,6 @@ static struct unix_funcs unix_funcs =
ntdll_sin,
ntdll_sqrt,
ntdll_tan,
virtual_release_address_space,
load_so_dll,
init_builtin_dll,
init_unix_lib,

View File

@ -109,8 +109,6 @@ extern LONGLONG CDECL fast_RtlGetSystemTimePrecise(void) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL fast_wait_cv( RTL_CONDITION_VARIABLE *variable, const void *value,
const LARGE_INTEGER *timeout ) DECLSPEC_HIDDEN;
extern void CDECL virtual_release_address_space(void) DECLSPEC_HIDDEN;
extern NTSTATUS CDECL unwind_builtin_dll( ULONG type, struct _DISPATCHER_CONTEXT *dispatch,
CONTEXT *context ) DECLSPEC_HIDDEN;

View File

@ -580,6 +580,20 @@ static void mmap_init( const struct preload_info *preload_info )
#endif
}
/***********************************************************************
* get_wow_user_space_limit
*/
static void *get_wow_user_space_limit(void)
{
#ifdef _WIN64
if (main_image_info.ImageCharacteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) return (void *)0xc0000000;
return (void *)0x7fff0000;
#endif
return user_space_limit;
}
/***********************************************************************
* add_builtin_module
*/
@ -2703,17 +2717,8 @@ void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info, BOOL wow64 )
info->LowestUserAddress = (void *)0x10000;
info->ActiveProcessorsAffinityMask = get_system_affinity_mask();
info->NumberOfProcessors = peb->NumberOfProcessors;
#ifdef _WIN64
if (wow64)
{
if (main_image_info.ImageCharacteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)
info->HighestUserAddress = (char *)0xc0000000 - 1;
else
info->HighestUserAddress = (char *)0x7fff0000 - 1;
return;
}
#endif
info->HighestUserAddress = (char *)user_space_limit - 1;
if (wow64) info->HighestUserAddress = (char *)get_wow_user_space_limit() - 1;
else info->HighestUserAddress = (char *)user_space_limit - 1;
}
@ -3639,38 +3644,29 @@ static int CDECL free_reserved_memory( void *base, SIZE_T size, void *arg )
*
* Release some address space once we have loaded and initialized the app.
*/
void CDECL virtual_release_address_space(void)
static void virtual_release_address_space(void)
{
struct free_range range;
sigset_t sigset;
if (is_win64) return;
server_enter_uninterrupted_section( &virtual_mutex, &sigset );
range.base = (char *)0x82000000;
range.limit = user_space_limit;
range.limit = get_wow_user_space_limit();
if (range.limit > (char *)0xfffff000) return; /* 64-bit limit, nothing to do */
if (range.limit > range.base)
{
while (mmap_enum_reserved_areas( free_reserved_memory, &range, 1 )) /* nothing */;
#ifdef __APPLE__
/* On macOS, we still want to free some of low memory, for OpenGL resources */
range.base = (char *)0x40000000;
range.base = (char *)0x40000000;
#else
range.base = NULL;
return;
#endif
}
else
range.base = (char *)0x20000000;
else range.base = (char *)0x20000000;
if (range.base)
{
range.limit = (char *)0x7f000000;
while (mmap_enum_reserved_areas( free_reserved_memory, &range, 0 )) /* nothing */;
}
server_leave_uninterrupted_section( &virtual_mutex, &sigset );
range.limit = (char *)0x7f000000;
while (mmap_enum_reserved_areas( free_reserved_memory, &range, 0 )) /* nothing */;
}
@ -3884,12 +3880,16 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
size = ROUND_SIZE( addr, size );
base = ROUND_ADDR( addr, page_mask );
/* avoid freeing the DOS area when a broken app passes a NULL pointer */
if (!base) return STATUS_INVALID_PARAMETER;
server_enter_uninterrupted_section( &virtual_mutex, &sigset );
if (!(view = find_view( base, size )) || !is_view_valloc( view ))
/* avoid freeing the DOS area when a broken app passes a NULL pointer */
if (!base)
{
/* address 1 is magic to mean release reserved space */
if (addr == (void *)1 && !*size_ptr && type == MEM_RELEASE) virtual_release_address_space();
else status = STATUS_INVALID_PARAMETER;
}
else if (!(view = find_view( base, size )) || !is_view_valloc( view ))
{
status = STATUS_INVALID_PARAMETER;
}

View File

@ -26,7 +26,7 @@
struct _DISPATCHER_CONTEXT;
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 123
#define NTDLL_UNIXLIB_VERSION 124
struct unix_funcs
{
@ -69,9 +69,6 @@ struct unix_funcs
double (CDECL *sqrt)( double d );
double (CDECL *tan)( double d );
/* virtual memory functions */
void (CDECL *virtual_release_address_space)(void);
/* loader functions */
NTSTATUS (CDECL *load_so_dll)( UNICODE_STRING *nt_name, void **module );
void (CDECL *init_builtin_dll)( void *module );