ntdll: Move the mmap reserved area functions to the Unix library.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2020-05-17 11:04:47 +02:00
parent 9e26bc8116
commit 625209433f
5 changed files with 84 additions and 34 deletions

View File

@ -377,6 +377,10 @@ static HMODULE load_ntdll(void)
static struct unix_funcs unix_funcs = static struct unix_funcs unix_funcs =
{ {
map_so_dll, map_so_dll,
mmap_add_reserved_area,
mmap_remove_reserved_area,
mmap_is_in_reserved_area,
mmap_enum_reserved_areas,
}; };
@ -396,11 +400,11 @@ static void *apple_wine_thread( void *arg )
/*********************************************************************** /***********************************************************************
* apple_alloc_thread_stack * apple_alloc_thread_stack
* *
* Callback for wine_mmap_enum_reserved_areas to allocate space for * Callback for mmap_enum_reserved_areas to allocate space for
* the secondary thread's stack. * the secondary thread's stack.
*/ */
#ifndef _WIN64 #ifndef _WIN64
static int apple_alloc_thread_stack( void *base, size_t size, void *arg ) static int CDECL apple_alloc_thread_stack( void *base, size_t size, void *arg )
{ {
struct apple_stack_info *info = arg; struct apple_stack_info *info = arg;
@ -441,9 +445,9 @@ static void apple_create_wine_thread( void *arg )
* fails, just let it go wherever. It'll be a waste of space, but we * fails, just let it go wherever. It'll be a waste of space, but we
* can go on. */ * can go on. */
if (!pthread_attr_getstacksize( &attr, &info.desired_size ) && if (!pthread_attr_getstacksize( &attr, &info.desired_size ) &&
wine_mmap_enum_reserved_areas( apple_alloc_thread_stack, &info, 1 )) mmap_enum_reserved_areas( apple_alloc_thread_stack, &info, 1 ))
{ {
wine_mmap_remove_reserved_area( info.stack, info.desired_size, 0 ); mmap_remove_reserved_area( info.stack, info.desired_size, 0 );
pthread_attr_setstackaddr( &attr, (char*)info.stack + info.desired_size ); pthread_attr_setstackaddr( &attr, (char*)info.stack + info.desired_size );
} }
#endif #endif

View File

@ -23,6 +23,12 @@
#include "unixlib.h" #include "unixlib.h"
void CDECL mmap_add_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN;
void CDECL mmap_remove_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN;
int CDECL mmap_is_in_reserved_area( void *addr, SIZE_T size ) DECLSPEC_HIDDEN;
int CDECL mmap_enum_reserved_areas( int (CDECL *enum_func)(void *base, SIZE_T size, void *arg), void *arg,
int top_down ) DECLSPEC_HIDDEN;
extern void virtual_init(void) DECLSPEC_HIDDEN; extern void virtual_init(void) DECLSPEC_HIDDEN;
#endif /* __NTDLL_UNIX_PRIVATE_H */ #endif /* __NTDLL_UNIX_PRIVATE_H */

View File

@ -44,7 +44,7 @@
#include "windef.h" #include "windef.h"
#include "winnt.h" #include "winnt.h"
#include "winternl.h" #include "winternl.h"
#include "unixlib.h" #include "unix_private.h"
#include "wine/library.h" #include "wine/library.h"
struct preload_info struct preload_info
@ -108,7 +108,7 @@ static void reserve_area( void *addr, void *end )
ret = mach_vm_map( mach_task_self(), &alloc_address, hole_size, 0, VM_FLAGS_FIXED, ret = mach_vm_map( mach_task_self(), &alloc_address, hole_size, 0, VM_FLAGS_FIXED,
MEMORY_OBJECT_NULL, 0, 0, PROT_NONE, VM_PROT_ALL, VM_INHERIT_COPY ); MEMORY_OBJECT_NULL, 0, 0, PROT_NONE, VM_PROT_ALL, VM_INHERIT_COPY );
if (!ret) wine_mmap_add_reserved_area( (void*)hole_address, hole_size ); if (!ret) mmap_add_reserved_area( (void*)hole_address, hole_size );
else if (ret == KERN_NO_SPACE) else if (ret == KERN_NO_SPACE)
{ {
/* something filled (part of) the hole before we could. /* something filled (part of) the hole before we could.
@ -129,7 +129,7 @@ static void reserve_area( void *addr, void *end )
ptr = mmap( addr, size, PROT_NONE, flags, -1, 0 ); ptr = mmap( addr, size, PROT_NONE, flags, -1, 0 );
if (ptr == addr) if (ptr == addr)
{ {
wine_mmap_add_reserved_area( addr, size ); mmap_add_reserved_area( addr, size );
return; return;
} }
if (ptr != (void *)-1) munmap( ptr, size ); if (ptr != (void *)-1) munmap( ptr, size );
@ -200,6 +200,40 @@ static void mmap_init( const struct preload_info *preload_info )
#endif #endif
} }
void CDECL mmap_add_reserved_area( void *addr, SIZE_T size )
{
wine_mmap_add_reserved_area( addr, size );
}
void CDECL mmap_remove_reserved_area( void *addr, SIZE_T size )
{
wine_mmap_remove_reserved_area( addr, size, 0 );
}
int CDECL mmap_is_in_reserved_area( void *addr, SIZE_T size )
{
return wine_mmap_is_in_reserved_area( addr, size );
}
struct enum_data
{
int (CDECL *enum_func)( void *base, SIZE_T size, void *arg );
void *arg;
};
static int enum_wrapper( void *base, size_t size, void *arg )
{
struct enum_data *data = arg;
return data->enum_func( base, size, data->arg );
}
int CDECL mmap_enum_reserved_areas( int (CDECL *enum_func)(void *base, SIZE_T size, void *arg),
void *arg, int top_down )
{
struct enum_data data = { enum_func, arg };
return wine_mmap_enum_reserved_areas( enum_wrapper, &data, top_down );
}
void virtual_init(void) void virtual_init(void)
{ {
const struct preload_info **preload_info = dlsym( RTLD_DEFAULT, "wine_main_preload_info" ); const struct preload_info **preload_info = dlsym( RTLD_DEFAULT, "wine_main_preload_info" );
@ -207,7 +241,7 @@ void virtual_init(void)
if (preload_info && *preload_info) if (preload_info && *preload_info)
for (i = 0; (*preload_info)[i].size; i++) for (i = 0; (*preload_info)[i].size; i++)
wine_mmap_add_reserved_area( (*preload_info)[i].addr, (*preload_info)[i].size ); mmap_add_reserved_area( (*preload_info)[i].addr, (*preload_info)[i].size );
mmap_init( preload_info ? *preload_info : NULL ); mmap_init( preload_info ? *preload_info : NULL );
} }

View File

@ -22,11 +22,17 @@
#define __NTDLL_UNIXLIB_H #define __NTDLL_UNIXLIB_H
/* increment this when you change the function table */ /* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 1 #define NTDLL_UNIXLIB_VERSION 2
struct unix_funcs struct unix_funcs
{ {
NTSTATUS (CDECL *map_so_dll)( const IMAGE_NT_HEADERS *nt_descr, HMODULE module ); /* virtual memory functions */
NTSTATUS (CDECL *map_so_dll)( const IMAGE_NT_HEADERS *nt_descr, HMODULE module );
void (CDECL *mmap_add_reserved_area)( void *addr, SIZE_T size );
void (CDECL *mmap_remove_reserved_area)( void *addr, SIZE_T size );
int (CDECL *mmap_is_in_reserved_area)( void *addr, SIZE_T size );
int (CDECL *mmap_enum_reserved_areas)( int (CDECL *enum_func)(void *base, SIZE_T size, void *arg),
void *arg, int top_down );
}; };
#endif /* __NTDLL_UNIXLIB_H */ #endif /* __NTDLL_UNIXLIB_H */

View File

@ -685,7 +685,7 @@ static void add_reserved_area( void *addr, size_t size )
} }
/* blow away existing mappings */ /* blow away existing mappings */
wine_anon_mmap( addr, size, PROT_NONE, MAP_NORESERVE | MAP_FIXED ); wine_anon_mmap( addr, size, PROT_NONE, MAP_NORESERVE | MAP_FIXED );
wine_mmap_add_reserved_area( addr, size ); unix_funcs->mmap_add_reserved_area( addr, size );
} }
@ -700,7 +700,7 @@ static void remove_reserved_area( void *addr, size_t size )
struct file_view *view; struct file_view *view;
TRACE( "removing %p-%p\n", addr, (char *)addr + size ); TRACE( "removing %p-%p\n", addr, (char *)addr + size );
wine_mmap_remove_reserved_area( addr, size, 0 ); unix_funcs->mmap_remove_reserved_area( addr, size );
/* unmap areas not covered by an existing view */ /* unmap areas not covered by an existing view */
WINE_RB_FOR_EACH_ENTRY( view, &views_tree, struct file_view, entry ) WINE_RB_FOR_EACH_ENTRY( view, &views_tree, struct file_view, entry )
@ -730,7 +730,7 @@ struct area_boundary
* in the specified region. If no boundaries are found, result is NULL. * in the specified region. If no boundaries are found, result is NULL.
* The csVirtual section must be held by caller. * The csVirtual section must be held by caller.
*/ */
static int get_area_boundary_callback( void *start, size_t size, void *arg ) static int CDECL get_area_boundary_callback( void *start, SIZE_T size, void *arg )
{ {
struct area_boundary *area = arg; struct area_boundary *area = arg;
void *end = (char *)start + size; void *end = (char *)start + size;
@ -771,7 +771,7 @@ static inline BOOL is_beyond_limit( const void *addr, size_t size, const void *l
*/ */
static inline void unmap_area( void *addr, size_t size ) static inline void unmap_area( void *addr, size_t size )
{ {
switch (wine_mmap_is_in_reserved_area( addr, size )) switch (unix_funcs->mmap_is_in_reserved_area( addr, size ))
{ {
case -1: /* partially in a reserved area */ case -1: /* partially in a reserved area */
{ {
@ -779,7 +779,7 @@ static inline void unmap_area( void *addr, size_t size )
size_t lower_size; size_t lower_size;
area.base = addr; area.base = addr;
area.size = size; area.size = size;
wine_mmap_enum_reserved_areas( get_area_boundary_callback, &area, 0 ); unix_funcs->mmap_enum_reserved_areas( get_area_boundary_callback, &area, 0 );
assert( area.boundary ); assert( area.boundary );
lower_size = (char *)area.boundary - (char *)addr; lower_size = (char *)area.boundary - (char *)addr;
unmap_area( addr, lower_size ); unmap_area( addr, lower_size );
@ -1129,9 +1129,9 @@ struct alloc_area
/*********************************************************************** /***********************************************************************
* alloc_reserved_area_callback * alloc_reserved_area_callback
* *
* Try to map some space inside a reserved area. Callback for wine_mmap_enum_reserved_areas. * Try to map some space inside a reserved area. Callback for mmap_enum_reserved_areas.
*/ */
static int alloc_reserved_area_callback( void *start, size_t size, void *arg ) static int CDECL alloc_reserved_area_callback( void *start, SIZE_T size, void *arg )
{ {
struct alloc_area *alloc = arg; struct alloc_area *alloc = arg;
void *end = (char *)start + size; void *end = (char *)start + size;
@ -1175,7 +1175,7 @@ static NTSTATUS map_fixed_area( void *base, size_t size, unsigned int vprot )
{ {
void *ptr; void *ptr;
switch (wine_mmap_is_in_reserved_area( base, size )) switch (unix_funcs->mmap_is_in_reserved_area( base, size ))
{ {
case -1: /* partially in a reserved area */ case -1: /* partially in a reserved area */
{ {
@ -1184,7 +1184,7 @@ static NTSTATUS map_fixed_area( void *base, size_t size, unsigned int vprot )
size_t lower_size; size_t lower_size;
area.base = base; area.base = base;
area.size = size; area.size = size;
wine_mmap_enum_reserved_areas( get_area_boundary_callback, &area, 0 ); unix_funcs->mmap_enum_reserved_areas( get_area_boundary_callback, &area, 0 );
assert( area.boundary ); assert( area.boundary );
lower_size = (char *)area.boundary - (char *)base; lower_size = (char *)area.boundary - (char *)base;
status = map_fixed_area( base, lower_size, vprot ); status = map_fixed_area( base, lower_size, vprot );
@ -1251,7 +1251,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
alloc.top_down = top_down; alloc.top_down = top_down;
alloc.limit = (void*)(get_zero_bits_64_mask( zero_bits_64 ) & (UINT_PTR)user_space_limit); alloc.limit = (void*)(get_zero_bits_64_mask( zero_bits_64 ) & (UINT_PTR)user_space_limit);
if (wine_mmap_enum_reserved_areas( alloc_reserved_area_callback, &alloc, top_down )) if (unix_funcs->mmap_enum_reserved_areas( alloc_reserved_area_callback, &alloc, top_down ))
{ {
ptr = alloc.result; ptr = alloc.result;
TRACE( "got mem in reserved area %p-%p\n", ptr, (char *)ptr + size ); TRACE( "got mem in reserved area %p-%p\n", ptr, (char *)ptr + size );
@ -1433,7 +1433,7 @@ static NTSTATUS allocate_dos_memory( struct file_view **view, unsigned int vprot
/* check without the first 64K */ /* check without the first 64K */
if (wine_mmap_is_in_reserved_area( low_64k, dosmem_size - 0x10000 ) != 1) if (unix_funcs->mmap_is_in_reserved_area( low_64k, dosmem_size - 0x10000 ) != 1)
{ {
addr = wine_anon_mmap( low_64k, dosmem_size - 0x10000, unix_prot, 0 ); addr = wine_anon_mmap( low_64k, dosmem_size - 0x10000, unix_prot, 0 );
if (addr != low_64k) if (addr != low_64k)
@ -1445,7 +1445,7 @@ static NTSTATUS allocate_dos_memory( struct file_view **view, unsigned int vprot
/* now try to allocate the low 64K too */ /* now try to allocate the low 64K too */
if (wine_mmap_is_in_reserved_area( NULL, 0x10000 ) != 1) if (unix_funcs->mmap_is_in_reserved_area( NULL, 0x10000 ) != 1)
{ {
addr = wine_anon_mmap( (void *)page_size, 0x10000 - page_size, unix_prot, 0 ); addr = wine_anon_mmap( (void *)page_size, 0x10000 - page_size, unix_prot, 0 );
if (addr == (void *)page_size) if (addr == (void *)page_size)
@ -1922,8 +1922,8 @@ struct alloc_virtual_heap
size_t size; size_t size;
}; };
/* callback for wine_mmap_enum_reserved_areas to allocate space for the virtual heap */ /* callback for mmap_enum_reserved_areas to allocate space for the virtual heap */
static int alloc_virtual_heap( void *base, size_t size, void *arg ) static int CDECL alloc_virtual_heap( void *base, SIZE_T size, void *arg )
{ {
struct alloc_virtual_heap *alloc = arg; struct alloc_virtual_heap *alloc = arg;
@ -1985,8 +1985,8 @@ void virtual_init(void)
#else #else
alloc_views.size = view_block_size + (1U << (32 - page_shift)); alloc_views.size = view_block_size + (1U << (32 - page_shift));
#endif #endif
if (wine_mmap_enum_reserved_areas( alloc_virtual_heap, &alloc_views, 1 )) if (unix_funcs->mmap_enum_reserved_areas( alloc_virtual_heap, &alloc_views, 1 ))
wine_mmap_remove_reserved_area( alloc_views.base, alloc_views.size, 0 ); unix_funcs->mmap_remove_reserved_area( alloc_views.base, alloc_views.size );
else else
alloc_views.base = wine_anon_mmap( NULL, alloc_views.size, PROT_READ | PROT_WRITE, 0 ); alloc_views.base = wine_anon_mmap( NULL, alloc_views.size, PROT_READ | PROT_WRITE, 0 );
@ -1998,7 +1998,7 @@ void virtual_init(void)
/* make the DOS area accessible (except the low 64K) to hide bugs in broken apps like Excel 2003 */ /* make the DOS area accessible (except the low 64K) to hide bugs in broken apps like Excel 2003 */
size = (char *)address_space_start - (char *)0x10000; size = (char *)address_space_start - (char *)0x10000;
if (size && wine_mmap_is_in_reserved_area( (void*)0x10000, size ) == 1) if (size && unix_funcs->mmap_is_in_reserved_area( (void*)0x10000, size ) == 1)
wine_anon_mmap( (void *)0x10000, size, PROT_READ | PROT_WRITE, MAP_FIXED ); wine_anon_mmap( (void *)0x10000, size, PROT_READ | PROT_WRITE, MAP_FIXED );
} }
@ -2701,8 +2701,8 @@ struct free_range
char *limit; char *limit;
}; };
/* free reserved areas above the limit; callback for wine_mmap_enum_reserved_areas */ /* free reserved areas above the limit; callback for mmap_enum_reserved_areas */
static int free_reserved_memory( void *base, size_t size, void *arg ) static int CDECL free_reserved_memory( void *base, SIZE_T size, void *arg )
{ {
struct free_range *range = arg; struct free_range *range = arg;
@ -2737,7 +2737,7 @@ void virtual_release_address_space(void)
if (range.limit > range.base) if (range.limit > range.base)
{ {
while (wine_mmap_enum_reserved_areas( free_reserved_memory, &range, 1 )) /* nothing */; while (unix_funcs->mmap_enum_reserved_areas( free_reserved_memory, &range, 1 )) /* nothing */;
#ifdef __APPLE__ #ifdef __APPLE__
/* On macOS, we still want to free some of low memory, for OpenGL resources */ /* On macOS, we still want to free some of low memory, for OpenGL resources */
range.base = (char *)0x40000000; range.base = (char *)0x40000000;
@ -2751,7 +2751,7 @@ void virtual_release_address_space(void)
if (range.base) if (range.base)
{ {
range.limit = (char *)0x7f000000; range.limit = (char *)0x7f000000;
while (wine_mmap_enum_reserved_areas( free_reserved_memory, &range, 0 )) /* nothing */; while (unix_funcs->mmap_enum_reserved_areas( free_reserved_memory, &range, 0 )) /* nothing */;
} }
server_leave_uninterrupted_section( &csVirtual, &sigset ); server_leave_uninterrupted_section( &csVirtual, &sigset );
@ -3087,8 +3087,8 @@ NTSTATUS WINAPI DECLSPEC_HOTPATCH NtProtectVirtualMemory( HANDLE process, PVOID
} }
/* retrieve state for a free memory area; callback for wine_mmap_enum_reserved_areas */ /* retrieve state for a free memory area; callback for mmap_enum_reserved_areas */
static int get_free_mem_state_callback( void *start, size_t size, void *arg ) static int CDECL get_free_mem_state_callback( void *start, SIZE_T size, void *arg )
{ {
MEMORY_BASIC_INFORMATION *info = arg; MEMORY_BASIC_INFORMATION *info = arg;
void *end = (char *)start + size; void *end = (char *)start + size;
@ -3202,7 +3202,7 @@ static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
if (!ptr) if (!ptr)
{ {
if (!wine_mmap_enum_reserved_areas( get_free_mem_state_callback, info, 0 )) if (!unix_funcs->mmap_enum_reserved_areas( get_free_mem_state_callback, info, 0 ))
{ {
/* not in a reserved area at all, pretend it's allocated */ /* not in a reserved area at all, pretend it's allocated */
#ifdef __i386__ #ifdef __i386__