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 =
{
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
*
* 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.
*/
#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;
@ -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
* can go on. */
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 );
}
#endif

View File

@ -23,6 +23,12 @@
#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;
#endif /* __NTDLL_UNIX_PRIVATE_H */

View File

@ -44,7 +44,7 @@
#include "windef.h"
#include "winnt.h"
#include "winternl.h"
#include "unixlib.h"
#include "unix_private.h"
#include "wine/library.h"
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,
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)
{
/* 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 );
if (ptr == addr)
{
wine_mmap_add_reserved_area( addr, size );
mmap_add_reserved_area( addr, size );
return;
}
if (ptr != (void *)-1) munmap( ptr, size );
@ -200,6 +200,40 @@ static void mmap_init( const struct preload_info *preload_info )
#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)
{
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)
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 );
}

View File

@ -22,11 +22,17 @@
#define __NTDLL_UNIXLIB_H
/* increment this when you change the function table */
#define NTDLL_UNIXLIB_VERSION 1
#define NTDLL_UNIXLIB_VERSION 2
struct unix_funcs
{
/* 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 */

View File

@ -685,7 +685,7 @@ static void add_reserved_area( void *addr, size_t size )
}
/* blow away existing mappings */
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;
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 */
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.
* 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;
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 )
{
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 */
{
@ -779,7 +779,7 @@ static inline void unmap_area( void *addr, size_t size )
size_t lower_size;
area.base = addr;
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 );
lower_size = (char *)area.boundary - (char *)addr;
unmap_area( addr, lower_size );
@ -1129,9 +1129,9 @@ struct alloc_area
/***********************************************************************
* 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;
void *end = (char *)start + size;
@ -1175,7 +1175,7 @@ static NTSTATUS map_fixed_area( void *base, size_t size, unsigned int vprot )
{
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 */
{
@ -1184,7 +1184,7 @@ static NTSTATUS map_fixed_area( void *base, size_t size, unsigned int vprot )
size_t lower_size;
area.base = base;
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 );
lower_size = (char *)area.boundary - (char *)base;
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.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;
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 */
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 );
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 */
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 );
if (addr == (void *)page_size)
@ -1922,8 +1922,8 @@ struct alloc_virtual_heap
size_t size;
};
/* callback for wine_mmap_enum_reserved_areas to allocate space for the virtual heap */
static int alloc_virtual_heap( void *base, size_t size, void *arg )
/* callback for mmap_enum_reserved_areas to allocate space for the virtual heap */
static int CDECL alloc_virtual_heap( void *base, SIZE_T size, void *arg )
{
struct alloc_virtual_heap *alloc = arg;
@ -1985,8 +1985,8 @@ void virtual_init(void)
#else
alloc_views.size = view_block_size + (1U << (32 - page_shift));
#endif
if (wine_mmap_enum_reserved_areas( alloc_virtual_heap, &alloc_views, 1 ))
wine_mmap_remove_reserved_area( alloc_views.base, alloc_views.size, 0 );
if (unix_funcs->mmap_enum_reserved_areas( alloc_virtual_heap, &alloc_views, 1 ))
unix_funcs->mmap_remove_reserved_area( alloc_views.base, alloc_views.size );
else
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 */
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 );
}
@ -2701,8 +2701,8 @@ struct free_range
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 )
/* free reserved areas above the limit; callback for mmap_enum_reserved_areas */
static int CDECL free_reserved_memory( void *base, SIZE_T size, void *arg )
{
struct free_range *range = arg;
@ -2737,7 +2737,7 @@ void virtual_release_address_space(void)
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__
/* On macOS, we still want to free some of low memory, for OpenGL resources */
range.base = (char *)0x40000000;
@ -2751,7 +2751,7 @@ void virtual_release_address_space(void)
if (range.base)
{
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 );
@ -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 */
static int get_free_mem_state_callback( void *start, size_t size, void *arg )
/* retrieve state for a free memory area; callback for mmap_enum_reserved_areas */
static int CDECL get_free_mem_state_callback( void *start, SIZE_T size, void *arg )
{
MEMORY_BASIC_INFORMATION *info = arg;
void *end = (char *)start + size;
@ -3202,7 +3202,7 @@ static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
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 */
#ifdef __i386__