Updated ntdll-ForceBottomUpAlloc patchset

Includes various performance optimizations and fixes
stuttering in Darksiders III reported by some users.
This commit is contained in:
Paul Gofman 2020-01-20 13:27:46 +03:00
parent dd581d0b2f
commit 9c3a91903e
8 changed files with 631 additions and 17 deletions

View File

@ -1,4 +1,4 @@
From d326b5e1f14765fed43f674f3693bb881c9e2c55 Mon Sep 17 00:00:00 2001
From b42d3dd8af6e0910bb204d64ac885d2cdc09e4df Mon Sep 17 00:00:00 2001
From: Paul Gofman <gofmanp@gmail.com>
Date: Thu, 9 Jan 2020 15:05:09 +0300
Subject: [PATCH] ntdll: Stop search on mmap() error in try_map_free_area().
@ -6,28 +6,27 @@ Subject: [PATCH] ntdll: Stop search on mmap() error in try_map_free_area().
The anon mmap errors do not depend on start address hint. Ignoring them
makes the search take incredible time until it fails.
---
dlls/ntdll/virtual.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
dlls/ntdll/virtual.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 8b515fcbce..e74179b711 100644
index 8b515fcbce..1d6239f765 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -570,8 +570,16 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
@@ -570,8 +570,14 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
return start;
TRACE( "Found free area is already mapped, start %p.\n", start );
- if (ptr != (void *)-1)
- munmap( ptr, size );
+ if (ptr == (void *)-1)
+ {
+ ERR("wine_anon_mmap() error %s, start %p, size %p, unix_prot %#x.\n",
+ strerror(errno), start, (void *)size, unix_prot);
+ return NULL;
+ }
+ else
+ {
munmap( ptr, size );
+ }
+
+ munmap( ptr, size );
if ((step > 0 && (char *)end - (char *)start < step) ||
(step < 0 && (char *)start - (char *)base < -step) ||

View File

@ -0,0 +1,51 @@
From 61e5e74a97121f630fc7f5c5144fd0172d547b60 Mon Sep 17 00:00:00 2001
From: Paul Gofman <gofmanp@gmail.com>
Date: Thu, 16 Jan 2020 16:09:24 +0300
Subject: [PATCH] ntdll: Use MAP_FIXED_NOREPLACE flag in try_map_free_area() if
available.
Avoids actual mapping followed by unmapping back if the memory range is
already mapped.
---
dlls/ntdll/virtual.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 1d6239f765..486693f312 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -562,22 +562,28 @@ static struct wine_rb_entry *find_view_inside_range( void **base_ptr, void **end
static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
void *start, size_t size, int unix_prot )
{
+#ifdef MAP_FIXED_NOREPLACE
+ static int flags = MAP_FIXED_NOREPLACE;
+#else
+ statinc int flags = 0;
+#endif
void *ptr;
while (start && base <= start && (char*)start + size <= (char*)end)
{
- if ((ptr = wine_anon_mmap( start, size, unix_prot, 0 )) == start)
+ if ((ptr = wine_anon_mmap( start, size, unix_prot, flags )) == start)
return start;
TRACE( "Found free area is already mapped, start %p.\n", start );
- if (ptr == (void *)-1)
+ if (ptr == (void *)-1 && errno != EEXIST)
{
ERR("wine_anon_mmap() error %s, start %p, size %p, unix_prot %#x.\n",
strerror(errno), start, (void *)size, unix_prot);
return NULL;
}
- munmap( ptr, size );
+ if (ptr != (void *)-1)
+ munmap( ptr, size );
if ((step > 0 && (char *)end - (char *)start < step) ||
(step < 0 && (char *)start - (char *)base < -step) ||
--
2.24.1

View File

@ -1,4 +1,4 @@
From 83230b22cd21e6d055401fa0da1e543cbe80bbef Mon Sep 17 00:00:00 2001
From 0aee0556e8c5eaff0ac15cd2f2a8ba7c234dfe57 Mon Sep 17 00:00:00 2001
From: Paul Gofman <gofmanp@gmail.com>
Date: Mon, 25 Nov 2019 12:19:20 +0300
Subject: [PATCH] ntdll: Force bottom up allocation order for 64 bit arch
@ -11,10 +11,10 @@ Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46568
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 8b515fcbce3..2d0cbf652a9 100644
index 486693f312..81d844ab17 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -1266,14 +1266,20 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
@@ -1278,14 +1278,20 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
}
else
{
@ -36,7 +36,7 @@ index 8b515fcbce3..2d0cbf652a9 100644
if (wine_mmap_enum_reserved_areas( alloc_reserved_area_callback, &alloc, top_down ))
{
ptr = alloc.result;
@@ -1283,7 +1289,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
@@ -1295,7 +1301,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
goto done;
}
@ -45,7 +45,7 @@ index 8b515fcbce3..2d0cbf652a9 100644
{
if (!(ptr = map_free_area( address_space_start, alloc.limit, size, mask, top_down, VIRTUAL_GetUnixProt(vprot) )))
return STATUS_NO_MEMORY;
@@ -1291,6 +1297,8 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
@@ -1303,6 +1309,8 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
goto done;
}
@ -55,5 +55,5 @@ index 8b515fcbce3..2d0cbf652a9 100644
{
if ((ptr = wine_anon_mmap( NULL, view_size, VIRTUAL_GetUnixProt(vprot), 0 )) == (void *)-1)
--
2.24.0
2.24.1

View File

@ -0,0 +1,25 @@
From 0c2da5027e397cd2a3677cad6e505482e7c8b063 Mon Sep 17 00:00:00 2001
From: Paul Gofman <gofmanp@gmail.com>
Date: Tue, 14 Jan 2020 21:39:23 +0300
Subject: [PATCH] ntdll: Increase step after failed map attempt in
try_map_free_area().
---
dlls/ntdll/virtual.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 81d844ab17..a262401f58 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -590,6 +590,7 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
step == 0)
break;
start = (char *)start + step;
+ step *= 2;
}
return NULL;
--
2.24.1

View File

@ -0,0 +1,259 @@
From dcbf5bcf5fc813040532be9a4adc1999b74c189d Mon Sep 17 00:00:00 2001
From: Paul Gofman <gofmanp@gmail.com>
Date: Tue, 14 Jan 2020 21:28:57 +0300
Subject: [PATCH] libs/wine: Add functions for managing free area list.
---
include/wine/library.h | 5 +++
libs/wine/mmap.c | 75 ++++++++++++++++++++++++++++++++----------
libs/wine/wine.map | 4 +++
3 files changed, 67 insertions(+), 17 deletions(-)
diff --git a/include/wine/library.h b/include/wine/library.h
index c141d96392..3e10bb4dee 100644
--- a/include/wine/library.h
+++ b/include/wine/library.h
@@ -89,6 +89,11 @@ extern int wine_mmap_is_in_reserved_area( void *addr, size_t size );
extern int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, void *arg),
void *arg, int top_down );
+extern void wine_mmap_add_free_area( void *addr, size_t size );
+extern void wine_mmap_remove_free_area( void *addr, size_t size, int unmap );
+extern int wine_mmap_is_in_free_area( void *addr, size_t size );
+extern int wine_mmap_enum_free_areas( int (*enum_func)(void *base, size_t size, void *arg),
+ void *arg, int top_down );
#ifdef __i386__
/* LDT management */
diff --git a/libs/wine/mmap.c b/libs/wine/mmap.c
index f2b5adc1d2..baa466c776 100644
--- a/libs/wine/mmap.c
+++ b/libs/wine/mmap.c
@@ -52,7 +52,9 @@ struct reserved_area
size_t size;
};
-static struct list reserved_areas = LIST_INIT(reserved_areas);
+static struct list reserved_areas_list = LIST_INIT(reserved_areas_list);
+static struct list free_areas_list = LIST_INIT(free_areas_list);
+
#ifndef __APPLE__
static const unsigned int granularity_mask = 0xffff; /* reserved areas have 64k granularity */
#endif
@@ -427,7 +429,7 @@ void mmap_init(void)
reserve_malloc_space( 8 * 1024 * 1024 );
- if (!list_head( &reserved_areas ))
+ if (!list_head( &reserved_areas_list ))
{
/* if we don't have a preloader, try to reserve some space below 2Gb */
reserve_area( (void *)0x00110000, (void *)0x40000000 );
@@ -435,7 +437,7 @@ void mmap_init(void)
/* check for a reserved area starting at the user space limit */
/* to avoid wasting time trying to allocate it again */
- LIST_FOR_EACH( ptr, &reserved_areas )
+ LIST_FOR_EACH( ptr, &reserved_areas_list )
{
area = LIST_ENTRY( ptr, struct reserved_area, entry );
if ((char *)area->base > user_space_limit) break;
@@ -466,7 +468,7 @@ void mmap_init(void)
/* reserve the DOS area if not already done */
- ptr = list_head( &reserved_areas );
+ ptr = list_head( &reserved_areas_list );
if (ptr)
{
area = LIST_ENTRY( ptr, struct reserved_area, entry );
@@ -476,7 +478,7 @@ void mmap_init(void)
#elif defined(__x86_64__) || defined(__aarch64__)
- if (!list_head( &reserved_areas ))
+ if (!list_head( &reserved_areas_list ))
{
/* if we don't have a preloader, try to reserve the space now */
reserve_area( (void *)0x000000010000, (void *)0x000068000000 );
@@ -497,14 +499,14 @@ void mmap_init(void)
* Note: the reserved areas functions are not reentrant, caller is
* responsible for proper locking.
*/
-void wine_mmap_add_reserved_area( void *addr, size_t size )
+static void wine_mmap_add_area( struct list *areas, void *addr, size_t size )
{
struct reserved_area *area;
struct list *ptr;
if (!((char *)addr + size)) size--; /* avoid wrap-around */
- LIST_FOR_EACH( ptr, &reserved_areas )
+ LIST_FOR_EACH( ptr, areas )
{
area = LIST_ENTRY( ptr, struct reserved_area, entry );
if (area->base > addr)
@@ -524,7 +526,7 @@ void wine_mmap_add_reserved_area( void *addr, size_t size )
area->size += size;
/* try to merge with the next one too */
- if ((ptr = list_next( &reserved_areas, ptr )))
+ if ((ptr = list_next( areas, ptr )))
{
struct reserved_area *next = LIST_ENTRY( ptr, struct reserved_area, entry );
if ((char *)addr + size == (char *)next->base)
@@ -546,6 +548,15 @@ void wine_mmap_add_reserved_area( void *addr, size_t size )
}
}
+void wine_mmap_add_reserved_area( void *addr, size_t size )
+{
+ wine_mmap_add_area(&reserved_areas_list, addr, size);
+}
+
+void wine_mmap_add_free_area( void *addr, size_t size )
+{
+ wine_mmap_add_area(&free_areas_list, addr, size);
+}
/***********************************************************************
* wine_mmap_remove_reserved_area
@@ -556,14 +567,14 @@ void wine_mmap_add_reserved_area( void *addr, size_t size )
* Note: the reserved areas functions are not reentrant, caller is
* responsible for proper locking.
*/
-void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap )
+static void wine_mmap_remove_area( struct list *areas, void *addr, size_t size, int unmap )
{
struct reserved_area *area;
struct list *ptr;
if (!((char *)addr + size)) size--; /* avoid wrap-around */
- ptr = list_head( &reserved_areas );
+ ptr = list_head( areas );
/* find the first area covering address */
while (ptr)
{
@@ -584,7 +595,7 @@ void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap )
else
{
/* range contains the whole area -> remove area completely */
- ptr = list_next( &reserved_areas, ptr );
+ ptr = list_next( areas, ptr );
if (unmap) munmap( area->base, area->size );
list_remove( &area->entry );
free( area );
@@ -616,10 +627,19 @@ void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap )
}
}
}
- ptr = list_next( &reserved_areas, ptr );
+ ptr = list_next( areas, ptr );
}
}
+void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap )
+{
+ wine_mmap_remove_area(&reserved_areas_list, addr, size, unmap);
+}
+
+void wine_mmap_remove_free_area( void *addr, size_t size, int unmap )
+{
+ wine_mmap_remove_area(&free_areas_list, addr, size, unmap);
+}
/***********************************************************************
* wine_mmap_is_in_reserved_area
@@ -631,12 +651,12 @@ void wine_mmap_remove_reserved_area( void *addr, size_t size, int unmap )
* Note: the reserved areas functions are not reentrant, caller is
* responsible for proper locking.
*/
-int wine_mmap_is_in_reserved_area( void *addr, size_t size )
+static int wine_mmap_is_in_area( struct list *areas, void *addr, size_t size )
{
struct reserved_area *area;
struct list *ptr;
- LIST_FOR_EACH( ptr, &reserved_areas )
+ LIST_FOR_EACH( ptr, areas )
{
area = LIST_ENTRY( ptr, struct reserved_area, entry );
if (area->base > addr) break;
@@ -648,6 +668,15 @@ int wine_mmap_is_in_reserved_area( void *addr, size_t size )
return 0;
}
+int wine_mmap_is_in_reserved_area( void *addr, size_t size )
+{
+ return wine_mmap_is_in_area( &reserved_areas_list, addr, size );
+}
+
+int wine_mmap_is_in_free_area( void *addr, size_t size )
+{
+ return wine_mmap_is_in_area( &free_areas_list, addr, size );
+}
/***********************************************************************
* wine_mmap_enum_reserved_areas
@@ -658,7 +687,7 @@ int wine_mmap_is_in_reserved_area( void *addr, size_t size )
* Note: the reserved areas functions are not reentrant, caller is
* responsible for proper locking.
*/
-int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, void *arg), void *arg,
+int wine_mmap_enum_areas( struct list *areas, int (*enum_func)(void *base, size_t size, void *arg), void *arg,
int top_down )
{
int ret = 0;
@@ -666,7 +695,7 @@ int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, voi
if (top_down)
{
- for (ptr = reserved_areas.prev; ptr != &reserved_areas; ptr = ptr->prev)
+ for (ptr = areas->prev; ptr != areas; ptr = ptr->prev)
{
struct reserved_area *area = LIST_ENTRY( ptr, struct reserved_area, entry );
if ((ret = enum_func( area->base, area->size, arg ))) break;
@@ -674,7 +703,7 @@ int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, voi
}
else
{
- for (ptr = reserved_areas.next; ptr != &reserved_areas; ptr = ptr->next)
+ for (ptr = areas->next; ptr != areas; ptr = ptr->next)
{
struct reserved_area *area = LIST_ENTRY( ptr, struct reserved_area, entry );
if ((ret = enum_func( area->base, area->size, arg ))) break;
@@ -682,3 +711,15 @@ int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, voi
}
return ret;
}
+
+int wine_mmap_enum_reserved_areas( int (*enum_func)(void *base, size_t size, void *arg), void *arg,
+ int top_down )
+{
+ return wine_mmap_enum_areas(&reserved_areas_list, enum_func, arg, top_down);
+}
+
+int wine_mmap_enum_free_areas( int (*enum_func)(void *base, size_t size, void *arg), void *arg,
+ int top_down )
+{
+ return wine_mmap_enum_areas(&free_areas_list, enum_func, arg, top_down);
+}
diff --git a/libs/wine/wine.map b/libs/wine/wine.map
index 72ffed80c0..448ab98572 100644
--- a/libs/wine/wine.map
+++ b/libs/wine/wine.map
@@ -112,6 +112,10 @@ WINE_1.0
wine_mmap_enum_reserved_areas;
wine_mmap_is_in_reserved_area;
wine_mmap_remove_reserved_area;
+ wine_mmap_add_free_area;
+ wine_mmap_enum_free_areas;
+ wine_mmap_is_in_free_area;
+ wine_mmap_remove_free_area;
wine_pthread_get_functions;
wine_pthread_set_functions;
wine_set_fs;
--
2.24.1

View File

@ -0,0 +1,198 @@
From c8c6a1025ead2e1befbdccf9a53f8fd4141f8d53 Mon Sep 17 00:00:00 2001
From: Paul Gofman <gofmanp@gmail.com>
Date: Tue, 14 Jan 2020 21:42:21 +0300
Subject: [PATCH] ntdll: Use free area list for virtual memory allocation.
---
dlls/ntdll/virtual.c | 111 +++++++++++++++++++++----------------------
1 file changed, 55 insertions(+), 56 deletions(-)
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index a262401f58..2951b5b15b 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -596,60 +596,6 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
return NULL;
}
-
-/***********************************************************************
- * map_free_area
- *
- * Find a free area between views inside the specified range and map it.
- * The csVirtual section must be held by caller.
- */
-static void *map_free_area( void *base, void *end, size_t size, size_t mask, int top_down,
- int unix_prot )
-{
- struct wine_rb_entry *first = find_view_inside_range( &base, &end, top_down );
- ptrdiff_t step = top_down ? -(mask + 1) : (mask + 1);
- void *start;
-
- if (top_down)
- {
- start = ROUND_ADDR( (char *)end - size, mask );
- if (start >= end || start < base) return NULL;
-
- while (first)
- {
- struct file_view *view = WINE_RB_ENTRY_VALUE( first, struct file_view, entry );
- if ((start = try_map_free_area( (char *)view->base + view->size, (char *)start + size, step,
- start, size, unix_prot ))) break;
- start = ROUND_ADDR( (char *)view->base - size, mask );
- /* stop if remaining space is not large enough */
- if (!start || start >= end || start < base) return NULL;
- first = wine_rb_prev( first );
- }
- }
- else
- {
- start = ROUND_ADDR( (char *)base + mask, mask );
- if (!start || start >= end || (char *)end - (char *)start < size) return NULL;
-
- while (first)
- {
- struct file_view *view = WINE_RB_ENTRY_VALUE( first, struct file_view, entry );
- if ((start = try_map_free_area( start, view->base, step,
- start, size, unix_prot ))) break;
- start = ROUND_ADDR( (char *)view->base + view->size + mask, mask );
- /* stop if remaining space is not large enough */
- if (!start || start >= end || (char *)end - (char *)start < size) return NULL;
- first = wine_rb_next( first );
- }
- }
-
- if (!first)
- return try_map_free_area( base, end, step, start, size, unix_prot );
-
- return start;
-}
-
-
/***********************************************************************
* find_reserved_free_area
*
@@ -864,6 +810,7 @@ static struct file_view *alloc_view(void)
*/
static void delete_view( struct file_view *view ) /* [in] View */
{
+ wine_mmap_add_free_area(view->base, view->size);
if (!(view->protect & VPROT_SYSTEM)) unmap_area( view->base, view->size );
set_page_vprot( view->base, view->size, 0 );
wine_rb_remove( &views_tree, &view->entry );
@@ -921,6 +868,7 @@ static NTSTATUS create_view( struct file_view **view_ret, void *base, size_t siz
TRACE( "forcing exec permission on %p-%p\n", base, (char *)base + size - 1 );
mprotect( base, size, unix_prot | PROT_EXEC );
}
+ wine_mmap_remove_free_area(view->base, view->size, 0);
return STATUS_SUCCESS;
}
@@ -1158,6 +1106,7 @@ struct alloc_area
int top_down;
void *limit;
void *result;
+ int unix_prot;
};
/***********************************************************************
@@ -1199,6 +1148,41 @@ static int alloc_reserved_area_callback( void *start, size_t size, void *arg )
return 0;
}
+static int alloc_free_area_callback( void *base, size_t area_size, void *arg )
+{
+ struct alloc_area *alloc = arg;
+ void *end = (char *)base + area_size;
+ size_t size = alloc->size;
+ ptrdiff_t step = alloc->top_down ? -(alloc->mask + 1) : (alloc->mask + 1);
+ void *start;
+
+ if (base < address_space_start) base = address_space_start;
+ if (is_beyond_limit( base, size, alloc->limit )) end = alloc->limit;
+ if (base >= end) return 0;
+
+ if (alloc->top_down)
+ {
+ start = ROUND_ADDR( (char *)end - size, alloc->mask );
+ if (start >= end || start < base)
+ return 0;
+
+ if ((alloc->result = try_map_free_area( base, (char *)start + size, step,
+ start, size, alloc->unix_prot )))
+ return 1;
+ }
+ else
+ {
+ start = ROUND_ADDR( (char *)base + alloc->mask, alloc->mask );
+ if (!start || start >= end || (char *)end - (char *)start < size)
+ return 0;
+
+ if ((alloc->result = try_map_free_area( start, end, step,
+ start, size, alloc->unix_prot )))
+ return 1;
+ }
+ return 0;
+}
+
/***********************************************************************
* map_fixed_area
*
@@ -1286,6 +1270,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
alloc.mask = mask;
alloc.top_down = top_down;
alloc.limit = (void*)(get_zero_bits_64_mask( zero_bits_64 ) & (UINT_PTR)user_space_limit);
+ alloc.unix_prot = VIRTUAL_GetUnixProt(vprot);
if (is_win64 && !top_down)
{
@@ -1304,9 +1289,11 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
if (is_win64 || zero_bits_64)
{
- if (!(ptr = map_free_area( address_space_start, alloc.limit, size, mask, top_down, VIRTUAL_GetUnixProt(vprot) )))
+ if (!wine_mmap_enum_free_areas( alloc_free_area_callback, &alloc, top_down ))
return STATUS_NO_MEMORY;
- TRACE( "got mem with map_free_area %p-%p\n", ptr, (char *)ptr + size );
+
+ ptr = alloc.result;
+ TRACE( "got mem in free area %p-%p\n", ptr, (char *)ptr + size );
goto done;
}
@@ -1981,6 +1968,12 @@ static int alloc_virtual_heap( void *base, size_t size, void *arg )
return (alloc->base != (void *)-1);
}
+static int remove_reserved_area_from_free( void *base, size_t size, void *arg )
+{
+ wine_mmap_remove_free_area(base, size, 0);
+ return 0;
+}
+
/***********************************************************************
* virtual_init
*/
@@ -2039,6 +2032,9 @@ void virtual_init(void)
size = (char *)address_space_start - (char *)0x10000;
if (size && wine_mmap_is_in_reserved_area( (void*)0x10000, size ) == 1)
wine_anon_mmap( (void *)0x10000, size, PROT_READ | PROT_WRITE, MAP_FIXED );
+
+ wine_mmap_add_free_area(address_space_start, (char *)user_space_limit - (char *)address_space_start);
+ wine_mmap_enum_reserved_areas( remove_reserved_area_from_free, NULL, 0);
}
@@ -2734,6 +2730,9 @@ void virtual_set_large_address_space(void)
/* no large address space on win9x */
if (NtCurrentTeb()->Peb->OSPlatformId != VER_PLATFORM_WIN32_NT) return;
+ if (address_space_limit > user_space_limit)
+ wine_mmap_add_free_area(user_space_limit, (char *)address_space_limit - (char *)user_space_limit);
+
user_space_limit = working_set_limit = address_space_limit;
}
--
2.24.1

View File

@ -0,0 +1,72 @@
From e015956f133594c51f5f1e7baccf3fe56ef7d83f Mon Sep 17 00:00:00 2001
From: Paul Gofman <gofmanp@gmail.com>
Date: Wed, 15 Jan 2020 17:05:09 +0300
Subject: [PATCH] ntdll: Permanently exclude natively mapped areas from free
areas list.
---
dlls/ntdll/virtual.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 2951b5b15b..3617dcf348 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -110,6 +110,9 @@ static const BYTE VIRTUAL_Win32Flags[16] =
static struct wine_rb_tree views_tree;
+static void *last_already_mapped;
+static size_t last_already_mapped_size;
+
static RTL_CRITICAL_SECTION csVirtual;
static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
{
@@ -585,6 +588,13 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
if (ptr != (void *)-1)
munmap( ptr, size );
+ if (!last_already_mapped && step)
+ {
+ last_already_mapped = start;
+ last_already_mapped_size = step > 0 ? step : -step;
+ last_already_mapped_size = min(last_already_mapped_size, (char *)end - (char *)start);
+ }
+
if ((step > 0 && (char *)end - (char *)start < step) ||
(step < 0 && (char *)start - (char *)base < -step) ||
step == 0)
@@ -1156,6 +1166,8 @@ static int alloc_free_area_callback( void *base, size_t area_size, void *arg )
ptrdiff_t step = alloc->top_down ? -(alloc->mask + 1) : (alloc->mask + 1);
void *start;
+ TRACE("base %p, area_size %p, size %p.\n", base, (void *)area_size, (void *)size);
+
if (base < address_space_start) base = address_space_start;
if (is_beyond_limit( base, size, alloc->limit )) end = alloc->limit;
if (base >= end) return 0;
@@ -1287,11 +1299,21 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
goto done;
}
+
if (is_win64 || zero_bits_64)
{
+ last_already_mapped = NULL;
+
if (!wine_mmap_enum_free_areas( alloc_free_area_callback, &alloc, top_down ))
return STATUS_NO_MEMORY;
+ if (last_already_mapped)
+ {
+ TRACE("Permanently excluding %p - %p from free list.\n",
+ last_already_mapped, (char *)last_already_mapped + last_already_mapped_size - 1);
+ wine_mmap_remove_free_area(last_already_mapped, last_already_mapped_size, 0);
+ }
+
ptr = alloc.result;
TRACE( "got mem in free area %p-%p\n", ptr, (char *)ptr + size );
goto done;
--
2.24.1

View File

@ -4864,14 +4864,24 @@ fi
# | 44-bit user-mode VA limitation from Windows < 8.1)
# |
# | Modified files:
# | * dlls/ntdll/virtual.c
# | * dlls/ntdll/virtual.c, include/wine/library.h, libs/wine/mmap.c, libs/wine/wine.map
# |
if test "$enable_ntdll_ForceBottomUpAlloc" -eq 1; then
patch_apply ntdll-ForceBottomUpAlloc/0001-ntdll-Stop-search-on-mmap-error-in-try_map_free_area.patch
patch_apply ntdll-ForceBottomUpAlloc/0002-ntdll-Force-bottom-up-allocation-order-for-64-bit-ar.patch
patch_apply ntdll-ForceBottomUpAlloc/0002-ntdll-Use-MAP_FIXED_NOREPLACE-flag-in-try_map_free_a.patch
patch_apply ntdll-ForceBottomUpAlloc/0003-ntdll-Force-bottom-up-allocation-order-for-64-bit-ar.patch
patch_apply ntdll-ForceBottomUpAlloc/0004-ntdll-Increase-step-after-failed-map-attempt-in-try_.patch
patch_apply ntdll-ForceBottomUpAlloc/0005-libs-wine-Add-functions-for-managing-free-area-list.patch
patch_apply ntdll-ForceBottomUpAlloc/0006-ntdll-Use-free-area-list-for-virtual-memory-allocati.patch
patch_apply ntdll-ForceBottomUpAlloc/0007-ntdll-Permanently-exclude-natively-mapped-areas-from.patch
(
printf '%s\n' '+ { "Paul Gofman", "ntdll: Stop search on mmap() error in try_map_free_area().", 1 },';
printf '%s\n' '+ { "Paul Gofman", "ntdll: Use MAP_FIXED_NOREPLACE flag in try_map_free_area() if available.", 1 },';
printf '%s\n' '+ { "Paul Gofman", "ntdll: Force bottom up allocation order for 64 bit arch unless top down is requested.", 1 },';
printf '%s\n' '+ { "Paul Gofman", "ntdll: Increase step after failed map attempt in try_map_free_area().", 1 },';
printf '%s\n' '+ { "Paul Gofman", "libs/wine: Add functions for managing free area list.", 1 },';
printf '%s\n' '+ { "Paul Gofman", "ntdll: Use free area list for virtual memory allocation.", 1 },';
printf '%s\n' '+ { "Paul Gofman", "ntdll: Permanently exclude natively mapped areas from free areas list.", 1 },';
) >> "$patchlist"
fi