mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-01-28 22:04:43 -08:00
Updated ntdll-ForceBottomUpAlloc patchset
Includes various performance optimizations and fixes stuttering in Darksiders III reported by some users.
This commit is contained in:
parent
dd581d0b2f
commit
9c3a91903e
@ -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) ||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user