You've already forked wine-staging
mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2025-09-12 18:50:20 -07:00
Rebase against 314368e6c442f043ebfc22b70c1113e4e6232c04.
This commit is contained in:
@@ -1,18 +1,19 @@
|
||||
From 0e03dab87634938bf9b6462a3e7dce1def1289c9 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <gofmanp@gmail.com>
|
||||
From ff02cbe4aea411563e0a9d22ed832acc2747d5b7 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <pgofman@codeweavers.com>
|
||||
Date: Tue, 14 Jan 2020 21:39:23 +0300
|
||||
Subject: [PATCH] ntdll: Increase step after failed map attempt in
|
||||
Subject: [PATCH 1/4] ntdll: Increase step after failed map attempt in
|
||||
try_map_free_area().
|
||||
|
||||
Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
|
||||
---
|
||||
dlls/ntdll/unix/virtual.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index 4b8942b1b53b..f4dba39cb160 100644
|
||||
index b469e9df4a1..52915e07323 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -1083,6 +1083,7 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
|
||||
@@ -1080,6 +1080,7 @@ static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
|
||||
step == 0)
|
||||
break;
|
||||
start = (char *)start + step;
|
@@ -0,0 +1,29 @@
|
||||
From 01730a2261a59a2826a652360b69dd3c74917fa6 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <pgofman@codeweavers.com>
|
||||
Date: Thu, 23 Jul 2020 18:40:39 +0300
|
||||
Subject: [PATCH] ntdll: Increase free ranges view block size on 64 bit.
|
||||
|
||||
Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
|
||||
---
|
||||
dlls/ntdll/unix/virtual.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index f7eab895f58..54ad53ea088 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -183,7 +183,11 @@ static BYTE *pages_vprot;
|
||||
#endif
|
||||
|
||||
static struct file_view *view_block_start, *view_block_end, *next_free_view;
|
||||
+#ifdef _WIN64
|
||||
+static const size_t view_block_size = 0x200000;
|
||||
+#else
|
||||
static const size_t view_block_size = 0x100000;
|
||||
+#endif
|
||||
static void *preload_reserve_start;
|
||||
static void *preload_reserve_end;
|
||||
static BOOL force_exec_prot; /* whether to force PROT_EXEC on all PROT_READ mmaps */
|
||||
--
|
||||
2.28.0
|
||||
|
@@ -1,58 +0,0 @@
|
||||
From c9f4923096e5c6dcb1591355e3cdab63167448d4 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
|
||||
unless top down is requested.
|
||||
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48175
|
||||
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46568
|
||||
---
|
||||
dlls/ntdll/unix/virtual.c | 12 ++++++++++--
|
||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index 3907b0db70a9..4b8942b1b53b 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -1775,13 +1775,19 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
|
||||
}
|
||||
else
|
||||
{
|
||||
- size_t view_size = size + granularity_mask + 1;
|
||||
struct alloc_area alloc;
|
||||
+ size_t view_size;
|
||||
|
||||
alloc.size = size;
|
||||
alloc.top_down = top_down;
|
||||
alloc.limit = (void*)(get_zero_bits_64_mask( zero_bits_64 ) & (UINT_PTR)user_space_limit);
|
||||
|
||||
+ if (is_win64 && !top_down)
|
||||
+ {
|
||||
+ /* Ditch 0x7ffffe000000 - 0x7fffffff0000 reserved area. */
|
||||
+ alloc.limit = min(alloc.limit, (void *)0x7ffffe000000);
|
||||
+ }
|
||||
+
|
||||
if (mmap_enum_reserved_areas( alloc_reserved_area_callback, &alloc, top_down ))
|
||||
{
|
||||
ptr = alloc.result;
|
||||
@@ -1791,7 +1797,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
|
||||
goto done;
|
||||
}
|
||||
|
||||
- if (zero_bits_64)
|
||||
+ if (is_win64 || zero_bits_64)
|
||||
{
|
||||
if (!(ptr = map_free_area( address_space_start, alloc.limit, size,
|
||||
top_down, get_unix_prot(vprot) )))
|
||||
@@ -1800,6 +1806,8 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
|
||||
goto done;
|
||||
}
|
||||
|
||||
+ view_size = size + granularity_mask + 1;
|
||||
+
|
||||
for (;;)
|
||||
{
|
||||
if ((ptr = wine_anon_mmap( NULL, view_size, get_unix_prot(vprot), 0 )) == (void *)-1)
|
||||
--
|
||||
2.26.2
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,256 @@
|
||||
From 479dfa05cc83b7ae8ab0f40862e74efedd98df48 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <pgofman@codeweavers.com>
|
||||
Date: Tue, 2 Jun 2020 21:06:33 +0300
|
||||
Subject: [PATCH 4/4] ntdll: Exclude natively mapped areas from free areas
|
||||
list.
|
||||
|
||||
Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
|
||||
---
|
||||
dlls/ntdll/unix/virtual.c | 130 ++++++++++++++++++++++++++++++--------
|
||||
1 file changed, 103 insertions(+), 27 deletions(-)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index e7dfc516538..dad12b5a9f2 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -103,6 +103,7 @@ struct file_view
|
||||
#define VPROT_WRITEWATCH 0x40
|
||||
/* per-mapping protection flags */
|
||||
#define VPROT_SYSTEM 0x0200 /* system view (underlying mmap not under our control) */
|
||||
+#define VPROT_NATIVE 0x0400
|
||||
|
||||
/* Conversion from VPROT_* to Win32 flags */
|
||||
static const BYTE VIRTUAL_Win32Flags[16] =
|
||||
@@ -877,7 +878,9 @@ static void dump_view( struct file_view *view )
|
||||
BYTE prot = get_page_vprot( addr );
|
||||
|
||||
TRACE( "View: %p - %p", addr, addr + view->size - 1 );
|
||||
- if (view->protect & VPROT_SYSTEM)
|
||||
+ if (view->protect & VPROT_NATIVE)
|
||||
+ TRACE(" (native)\n");
|
||||
+ else if (view->protect & VPROT_SYSTEM)
|
||||
TRACE( " (builtin image)\n" );
|
||||
else if (view->protect & SEC_IMAGE)
|
||||
TRACE( " (image)\n" );
|
||||
@@ -1019,6 +1022,16 @@ static struct file_view *find_view_range( const void *addr, size_t size )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+struct alloc_area
|
||||
+{
|
||||
+ char *map_area_start, *map_area_end, *result;
|
||||
+ size_t size;
|
||||
+ ptrdiff_t step;
|
||||
+ int unix_prot;
|
||||
+ BOOL top_down;
|
||||
+ char *native_mapped;
|
||||
+ size_t native_mapped_size;
|
||||
+};
|
||||
|
||||
/***********************************************************************
|
||||
* try_map_free_area
|
||||
@@ -1026,21 +1039,27 @@ static struct file_view *find_view_range( const void *addr, size_t size )
|
||||
* Try mmaping some expected free memory region, eventually stepping and
|
||||
* retrying inside it, and return where it actually succeeded, or NULL.
|
||||
*/
|
||||
-static void* try_map_free_area( void *base, void *end, ptrdiff_t step,
|
||||
- void *start, size_t size, int unix_prot )
|
||||
+static void* try_map_free_area( struct alloc_area *area, void *base, void *end, void *start )
|
||||
{
|
||||
+ ptrdiff_t step = area->step;
|
||||
void *ptr;
|
||||
|
||||
- while (start && base <= start && (char*)start + size <= (char*)end)
|
||||
+ while (start && base <= start && (char*)start + area->size <= (char*)end)
|
||||
{
|
||||
- if ((ptr = anon_mmap_tryfixed( start, size, unix_prot, 0 )) != MAP_FAILED) return start;
|
||||
+ if ((ptr = anon_mmap_tryfixed( start, area->size, area->unix_prot, 0 )) != MAP_FAILED) return start;
|
||||
TRACE( "Found free area is already mapped, start %p.\n", start );
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
ERR( "mmap() error %s, range %p-%p, unix_prot %#x.\n",
|
||||
- strerror(errno), start, (char *)start + size, unix_prot );
|
||||
+ strerror(errno), start, (char *)start + area->size, area->unix_prot );
|
||||
return NULL;
|
||||
}
|
||||
+ if (!area->native_mapped && step)
|
||||
+ {
|
||||
+ area->native_mapped = start;
|
||||
+ area->native_mapped_size = step > 0 ? step : -step;
|
||||
+ area->native_mapped_size = min(area->native_mapped_size, (char *)end - (char *)start);
|
||||
+ }
|
||||
if ((step > 0 && (char *)end - (char *)start < step) ||
|
||||
(step < 0 && (char *)start - (char *)base < -step) ||
|
||||
step == 0)
|
||||
@@ -1502,15 +1521,6 @@ static inline void *unmap_extra_space( void *ptr, size_t total_size, size_t want
|
||||
return ptr;
|
||||
}
|
||||
|
||||
-struct alloc_area
|
||||
-{
|
||||
- char *map_area_start, *map_area_end, *result;
|
||||
- size_t size;
|
||||
- ptrdiff_t step;
|
||||
- int unix_prot;
|
||||
- BOOL top_down;
|
||||
-};
|
||||
-
|
||||
static int CDECL alloc_area_in_reserved_or_between_callback( void *start, SIZE_T size, void *arg )
|
||||
{
|
||||
char *intersect_start, *intersect_end;
|
||||
@@ -1536,8 +1546,8 @@ static int CDECL alloc_area_in_reserved_or_between_callback( void *start, SIZE_T
|
||||
|
||||
if (alloc_start >= intersect_end)
|
||||
{
|
||||
- if ((area->result = try_map_free_area( area->map_area_start, alloc_start + size, area->step,
|
||||
- alloc_start, area->size, area->unix_prot )))
|
||||
+ if ((area->result = try_map_free_area( area, area->map_area_start,
|
||||
+ alloc_start + size, alloc_start )))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1571,8 +1581,8 @@ static int CDECL alloc_area_in_reserved_or_between_callback( void *start, SIZE_T
|
||||
|
||||
if (intersect_start - area->map_area_start >= area->size)
|
||||
{
|
||||
- if ((area->result = try_map_free_area( area->map_area_start, intersect_start, area->step,
|
||||
- area->map_area_start, area->size, area->unix_prot )))
|
||||
+ if ((area->result = try_map_free_area( area, area->map_area_start,
|
||||
+ intersect_start, area->map_area_start )))
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1627,8 +1637,7 @@ static void *alloc_free_area_in_range( struct alloc_area *area, char *base, char
|
||||
if (start >= area->map_area_end || start < area->map_area_start)
|
||||
return NULL;
|
||||
|
||||
- return try_map_free_area( area->map_area_start, start + area->size, area->step,
|
||||
- start, area->size, area->unix_prot );
|
||||
+ return try_map_free_area( area, area->map_area_start, start + area->size, start );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1637,8 +1646,7 @@ static void *alloc_free_area_in_range( struct alloc_area *area, char *base, char
|
||||
|| area->map_area_end - start < area->size)
|
||||
return NULL;
|
||||
|
||||
- return try_map_free_area( start, area->map_area_end, area->step,
|
||||
- start, area->size, area->unix_prot );
|
||||
+ return try_map_free_area( area, start, area->map_area_end, start );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1648,6 +1656,7 @@ static void *alloc_free_area( void *limit, size_t size, BOOL top_down, int unix_
|
||||
char *reserve_start, *reserve_end;
|
||||
struct alloc_area area;
|
||||
char *base, *end;
|
||||
+ NTSTATUS status;
|
||||
int ranges_inc;
|
||||
|
||||
TRACE("limit %p, size %p, top_down %#x.\n", limit, (void *)size, top_down);
|
||||
@@ -1703,16 +1712,67 @@ static void *alloc_free_area( void *limit, size_t size, BOOL top_down, int unix_
|
||||
{
|
||||
/* range is split in two by the preloader reservation, try first part. */
|
||||
if ((area.result = alloc_free_area_in_range( &area, base, reserve_start )))
|
||||
- return area.result;
|
||||
+ break;
|
||||
/* then fall through to try second part. */
|
||||
base = reserve_end;
|
||||
}
|
||||
}
|
||||
|
||||
if ((area.result = alloc_free_area_in_range( &area, base, end )))
|
||||
- return area.result;
|
||||
+ break;
|
||||
}
|
||||
- return NULL;
|
||||
+
|
||||
+ if (area.native_mapped)
|
||||
+ {
|
||||
+ char *native_mapped_start, *native_mapped_end;
|
||||
+
|
||||
+ TRACE("Excluding %p - %p from free list.\n",
|
||||
+ area.native_mapped, (char *)area.native_mapped + area.native_mapped_size );
|
||||
+
|
||||
+ native_mapped_start = ROUND_ADDR(area.native_mapped, granularity_mask);
|
||||
+ native_mapped_end = ROUND_ADDR((char *)area.native_mapped + area.native_mapped_size + granularity_mask,
|
||||
+ granularity_mask);
|
||||
+
|
||||
+ if (area.result >= native_mapped_end || area.result + size < native_mapped_start)
|
||||
+ /* In case of top down allocation try_map_free_area() result area can overlap the
|
||||
+ * area previously marked as native if the latter was unmapped behind our back. */
|
||||
+ {
|
||||
+ struct file_view *prev, *next;
|
||||
+
|
||||
+ prev = find_view_range( native_mapped_start - 1, native_mapped_end - native_mapped_start + 2 );
|
||||
+ if (prev && (char *)prev->base >= native_mapped_end)
|
||||
+ {
|
||||
+ next = prev;
|
||||
+ prev = WINE_RB_ENTRY_VALUE( wine_rb_prev( &next->entry ), struct file_view, entry );
|
||||
+ }
|
||||
+ else if (prev)
|
||||
+ {
|
||||
+ next = WINE_RB_ENTRY_VALUE( wine_rb_next( &prev->entry ), struct file_view, entry );
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ next = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (prev && prev->protect & VPROT_NATIVE && (char *)prev->base + prev->size >= native_mapped_start)
|
||||
+ {
|
||||
+ assert( (char *)prev->base + prev->size == native_mapped_start );
|
||||
+ native_mapped_start = prev->base;
|
||||
+ delete_view( prev );
|
||||
+ }
|
||||
+ if (next && next->protect & VPROT_NATIVE && native_mapped_end >= (char *)next->base)
|
||||
+ {
|
||||
+ assert( native_mapped_end == (char *)next->base );
|
||||
+ native_mapped_end = (char *)next->base + next->size;
|
||||
+ delete_view( next );
|
||||
+ }
|
||||
+ if ((status = create_view( &next, native_mapped_start, native_mapped_end - native_mapped_start,
|
||||
+ VPROT_SYSTEM | VPROT_NATIVE )))
|
||||
+ ERR("Could not cretae view for natively mapped area, status %#x.\n", status);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return area.result;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@@ -1766,6 +1826,17 @@ static NTSTATUS map_fixed_area( void *base, size_t size, unsigned int vprot )
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
+static void clear_native_views(void)
|
||||
+{
|
||||
+ struct file_view *view, *next_view;
|
||||
+
|
||||
+ WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR( view, next_view, &views_tree, struct file_view, entry )
|
||||
+ {
|
||||
+ if (view->protect & VPROT_NATIVE)
|
||||
+ delete_view( view );
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/***********************************************************************
|
||||
* map_view
|
||||
*
|
||||
@@ -1789,7 +1860,12 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
|
||||
else if (!(ptr = alloc_free_area( (void*)(get_zero_bits_64_mask( zero_bits_64 )
|
||||
& (UINT_PTR)user_space_limit), size, top_down, get_unix_prot( vprot ) )))
|
||||
{
|
||||
- return STATUS_NO_MEMORY;
|
||||
+ WARN("Allocation failed, clearing native views.\n");
|
||||
+
|
||||
+ clear_native_views();
|
||||
+ if (!(ptr = alloc_free_area( (void*)(get_zero_bits_64_mask( zero_bits_64 )
|
||||
+ & (UINT_PTR)user_space_limit), size, top_down, get_unix_prot( vprot ) )))
|
||||
+ return STATUS_NO_MEMORY;
|
||||
}
|
||||
status = create_view( view_ret, ptr, size, vprot );
|
||||
if (status != STATUS_SUCCESS) unmap_area( ptr, size );
|
||||
--
|
||||
2.26.2
|
||||
|
@@ -1,66 +0,0 @@
|
||||
From eda2aae6a4845e3b0f5e4edb805fb4add4316f17 Mon Sep 17 00:00:00 2001
|
||||
From: Paul Gofman <pgofman@codeweavers.com>
|
||||
Date: Tue, 2 Jun 2020 21:06:33 +0300
|
||||
Subject: [PATCH] ntdll: Permanently exclude natively mapped areas from free
|
||||
areas list.
|
||||
|
||||
---
|
||||
dlls/ntdll/unix/virtual.c | 25 +++++++++++++++++++++++++
|
||||
1 file changed, 25 insertions(+)
|
||||
|
||||
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
|
||||
index 667401aaa93..c49c60166c2 100644
|
||||
--- a/dlls/ntdll/unix/virtual.c
|
||||
+++ b/dlls/ntdll/unix/virtual.c
|
||||
@@ -124,6 +124,9 @@ static const BYTE VIRTUAL_Win32Flags[16] =
|
||||
static struct wine_rb_tree views_tree;
|
||||
static pthread_mutex_t virtual_mutex;
|
||||
|
||||
+static void *last_already_mapped;
|
||||
+static size_t last_already_mapped_size;
|
||||
+
|
||||
static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
|
||||
static const UINT page_shift = 12;
|
||||
static const UINT_PTR page_mask = 0xfff;
|
||||
@@ -997,6 +1000,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)
|
||||
@@ -1841,9 +1851,24 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
|
||||
|
||||
if (is_win64 || zero_bits_64)
|
||||
{
|
||||
+ last_already_mapped = NULL;
|
||||
+
|
||||
if (!(ptr = alloc_free_area( alloc.limit, alloc.size, top_down, alloc.unix_prot)))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
+ if (last_already_mapped)
|
||||
+ {
|
||||
+ void *last_mapped_start, *last_mapped_end;
|
||||
+
|
||||
+ TRACE("Permanently excluding %p - %p from free list.\n",
|
||||
+ last_already_mapped, (char *)last_already_mapped + last_already_mapped_size - 1);
|
||||
+ last_mapped_start = ROUND_ADDR(last_already_mapped, granularity_mask);
|
||||
+ last_mapped_end = ROUND_ADDR((char *)last_already_mapped + last_already_mapped_size + granularity_mask,
|
||||
+ granularity_mask);
|
||||
+ if (ptr > last_mapped_end || (char *)ptr + size < (char *)last_mapped_start)
|
||||
+ free_ranges_remove_range(last_mapped_start, last_mapped_end, last_already_mapped);
|
||||
+ }
|
||||
+
|
||||
TRACE( "got mem in free area %p-%p\n", ptr, (char *)ptr + size );
|
||||
goto done;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
Reference in New Issue
Block a user