[PATCH 2/3] libwine: On Mac, use Mach APIs to enumerate address space holes instead of using trial and error.

Ken Thomases ken at codeweavers.com
Wed Mar 6 18:59:38 CST 2019


Signed-off-by: Ken Thomases <ken at codeweavers.com>
---
 libs/wine/mmap.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/libs/wine/mmap.c b/libs/wine/mmap.c
index affdc0a..473b22c 100644
--- a/libs/wine/mmap.c
+++ b/libs/wine/mmap.c
@@ -228,6 +228,70 @@ void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
 }
 
 
+#ifdef __APPLE__
+
+/***********************************************************************
+ *           reserve_area
+ *
+ * Reserve as much memory as possible in the given area.
+ */
+static inline void reserve_area( void *addr, void *end )
+{
+#ifdef __i386__
+    static const mach_vm_address_t max_address = VM_MAX_ADDRESS;
+#else
+    static const mach_vm_address_t max_address = MACH_VM_MAX_ADDRESS;
+#endif
+    mach_vm_address_t address = (mach_vm_address_t)addr;
+    mach_vm_address_t end_address = (mach_vm_address_t)end;
+
+    if (!end_address || max_address < end_address)
+        end_address = max_address;
+
+    while (address < end_address)
+    {
+        mach_vm_address_t hole_address = address;
+        kern_return_t ret;
+        mach_vm_size_t size;
+        vm_region_basic_info_data_64_t info;
+        mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64;
+        mach_port_t dummy_object_name = MACH_PORT_NULL;
+
+        /* find the mapped region at or above the current address. */
+        ret = mach_vm_region(mach_task_self(), &address, &size, VM_REGION_BASIC_INFO_64,
+                             (vm_region_info_t)&info, &count, &dummy_object_name);
+        if (ret != KERN_SUCCESS)
+        {
+            address = max_address;
+            size = 0;
+        }
+
+        if (end_address < address)
+            address = end_address;
+        if (hole_address < address)
+        {
+            /* found a hole, attempt to reserve it. */
+            size_t hole_size = address - hole_address;
+            mach_vm_address_t alloc_address = hole_address;
+
+            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 );
+            else if (ret == KERN_NO_SPACE)
+            {
+                /* something filled (part of) the hole before we could.
+                   go back and look again. */
+                address = hole_address;
+                continue;
+            }
+        }
+        address += size;
+    }
+}
+
+#else
+
 /***********************************************************************
  *		mmap_reserve
  *
@@ -297,6 +361,7 @@ static inline void reserve_area( void *addr, void *end )
 #endif
 }
 
+#endif /* __APPLE__ */
 
 #ifdef __i386__
 /***********************************************************************
-- 
2.10.2




More information about the wine-devel mailing list