From 09712593c8496be5e952b7316099f9eed5043203 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Thu, 25 Jun 2009 14:18:53 +0200 Subject: [PATCH] ntdll: Release some address space after the process initialization is done. --- dlls/ntdll/loader.c | 2 +- dlls/ntdll/ntdll_misc.h | 2 +- dlls/ntdll/virtual.c | 79 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 76 insertions(+), 7 deletions(-) diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 2f9b41ec593..aa9395e4b79 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2477,11 +2477,11 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3, if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS) goto error; if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error; if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error; - if (nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) VIRTUAL_UseLargeAddressSpace(); status = wine_call_on_stack( attach_process_dlls, wm, NtCurrentTeb()->Tib.StackBase ); if (status != STATUS_SUCCESS) goto error; + virtual_release_address_space( nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE ); virtual_clear_thread_stack(); return; diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 34ae2d62d55..b6a3d88241c 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -150,7 +150,7 @@ extern NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err ); extern BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size ); extern BOOL virtual_check_buffer_for_write( void *ptr, SIZE_T size ); extern void VIRTUAL_SetForceExec( BOOL enable ); -extern void VIRTUAL_UseLargeAddressSpace(void); +extern void virtual_release_address_space( BOOL free_high_mem ); extern struct _KUSER_SHARED_DATA *user_shared_data; /* completion */ diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 33918ca5d4b..bacfa32e475 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -369,6 +369,36 @@ static void add_reserved_area( void *addr, size_t size ) } +/*********************************************************************** + * remove_reserved_area + * + * Remove a reserved area from the list maintained by libwine. + * The csVirtual section must be held by caller. + */ +static void remove_reserved_area( void *addr, size_t size ) +{ + struct file_view *view; + + TRACE( "removing %p-%p\n", addr, (char *)addr + size ); + wine_mmap_remove_reserved_area( addr, size, 0 ); + + /* unmap areas not covered by an existing view */ + LIST_FOR_EACH_ENTRY( view, &views_list, struct file_view, entry ) + { + if ((char *)view->base >= (char *)addr + size) + { + munmap( addr, size ); + break; + } + if ((char *)view->base + view->size <= (char *)addr) continue; + if (view->base > addr) munmap( addr, (char *)view->base - (char *)addr ); + if ((char *)view->base + view->size > (char *)addr + size) break; + size = (char *)addr + size - ((char *)view->base + view->size); + addr = (char *)view->base + view->size; + } +} + + /*********************************************************************** * is_beyond_limit * @@ -1615,17 +1645,56 @@ void VIRTUAL_SetForceExec( BOOL enable ) server_leave_uninterrupted_section( &csVirtual, &sigset ); } +struct free_range +{ + char *base; + char *limit; +}; + +/* free reserved areas above the limit; callback for wine_mmap_enum_reserved_areas */ +static int free_reserved_memory( void *base, size_t size, void *arg ) +{ + struct free_range *range = arg; + + if ((char *)base >= range->limit) return 0; + if ((char *)base + size <= range->base) return 0; + if ((char *)base < range->base) + { + size -= range->base - (char *)base; + base = range->base; + } + if ((char *)base + size > range->limit) size = range->limit - (char *)base; + remove_reserved_area( base, size ); + return 1; /* stop enumeration since the list has changed */ +} /*********************************************************************** - * VIRTUAL_UseLargeAddressSpace + * virtual_release_address_space * - * Increase the address space size for apps that support it. + * Release some address space once we have loaded and initialized the app. */ -void VIRTUAL_UseLargeAddressSpace(void) +void virtual_release_address_space( BOOL free_high_mem ) { +#ifdef __i386__ + struct free_range range; + sigset_t sigset; + + server_enter_uninterrupted_section( &csVirtual, &sigset ); + + range.base = (char *)0x20000000; + range.limit = (char *)0x7f000000; + while (wine_mmap_enum_reserved_areas( free_reserved_memory, &range, 0 )) /* nothing */; + /* no large address space on win9x */ - if (NtCurrentTeb()->Peb->OSPlatformId != VER_PLATFORM_WIN32_NT) return; - user_space_limit = working_set_limit = address_space_limit; + if (free_high_mem && NtCurrentTeb()->Peb->OSPlatformId == VER_PLATFORM_WIN32_NT) + { + range.base = (char *)0x80000000; + range.limit = address_space_limit; + while (wine_mmap_enum_reserved_areas( free_reserved_memory, &range, 1 )) /* nothing */; + user_space_limit = working_set_limit = address_space_limit; + } + server_leave_uninterrupted_section( &csVirtual, &sigset ); +#endif }