summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/mmap.cc84
1 files changed, 74 insertions, 10 deletions
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index 662489c8c..feb9e5d0e 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -188,13 +188,12 @@ CreateMapping (HANDLE fhdl, size_t len, off_t off, DWORD openflags,
static void *
MapView (HANDLE h, void *addr, size_t len, DWORD openflags,
- int prot, int flags, off_t off)
+ int prot, int flags, off_t off, bool from_fixup_after_fork)
{
NTSTATUS status;
LARGE_INTEGER offset = { QuadPart:off };
DWORD protect = gen_create_protect (openflags, flags);
void *base = addr;
- SIZE_T commitsize = attached (prot) ? 0 : len;
SIZE_T viewsize = len;
#ifdef __x86_64__ /* AT_ROUND_TO_PAGE isn't supported on 64 bit systems. */
ULONG alloc_type = MEM_TOP_DOWN;
@@ -203,12 +202,51 @@ MapView (HANDLE h, void *addr, size_t len, DWORD openflags,
| MEM_TOP_DOWN;
#endif
+#ifdef __x86_64__
+ /* Don't call NtMapViewOfSectionEx during fork. It requires autoloading
+ a function under loader lock (STATUS_DLL_INIT_FAILED). */
+ if (!from_fixup_after_fork && wincap.has_extended_mem_api ())
+ {
+ MEM_ADDRESS_REQUIREMENTS mmap_req = {
+ (PVOID) MMAP_STORAGE_LOW,
+ (PVOID) (MMAP_STORAGE_HIGH - 1),
+ 0
+ };
+ MEM_EXTENDED_PARAMETER mmap_ext = {
+ .Type = MemExtendedParameterAddressRequirements,
+ .Pointer = (PVOID) &mmap_req
+ };
+
+ alloc_type |= attached (prot) ? MEM_RESERVE : 0;
+ status = NtMapViewOfSectionEx (h, NtCurrentProcess (), &base, &offset,
+ &viewsize, alloc_type, protect,
+ addr ? NULL : &mmap_ext, addr ? 0 : 1);
+ if (!NT_SUCCESS (status) && addr && !fixed (flags))
+ {
+ base = NULL;
+ status = NtMapViewOfSectionEx (h, NtCurrentProcess (), &base,
+ &offset, &viewsize, alloc_type,
+ protect, &mmap_ext, 1);
+ }
+ if (!NT_SUCCESS (status))
+ {
+ base = NULL;
+ SetLastError (RtlNtStatusToDosError (status));
+ }
+ debug_printf ("%p (status %p) = NtMapViewOfSectionEx (h:%p, addr:%p, "
+ "off:%Y, viewsize:%U, alloc_type:%y, protect:%y",
+ base, status, h, addr, off, viewsize, alloc_type, protect);
+ return base;
+ }
+#endif
+
/* Try mapping using the given address first, even if it's NULL.
If it failed, and addr was not NULL and flags is not MAP_FIXED,
try again with NULL address.
Note: Retrying the mapping might be unnecessary, now that mmap64 checks
for a valid memory area first. */
+ SIZE_T commitsize = attached (prot) ? 0 : len;
status = NtMapViewOfSection (h, NtCurrentProcess (), &base, 0, commitsize,
&offset, &viewsize, ViewShare, alloc_type,
protect);
@@ -1051,7 +1089,8 @@ go_ahead:
}
#ifdef __x86_64__
- addr = mmap_alloc.alloc (addr, orig_len ?: len, fixed (flags));
+ if (!wincap.has_extended_mem_api ())
+ addr = mmap_alloc.alloc (addr, orig_len ?: len, fixed (flags));
#else
if (orig_len)
{
@@ -1637,9 +1676,33 @@ fhandler_dev_zero::mmap (caddr_t *addr, size_t len, int prot,
DWORD protect = gen_protect (prot, flags);
DWORD alloc_type = MEM_TOP_DOWN | MEM_RESERVE
| (noreserve (flags) ? 0 : MEM_COMMIT);
- base = VirtualAlloc (*addr, len, alloc_type, protect);
- if (!base && addr && !fixed (flags))
- base = VirtualAlloc (NULL, len, alloc_type, protect);
+#ifdef __x86_64__
+ if (wincap.has_extended_mem_api ())
+ {
+ MEM_ADDRESS_REQUIREMENTS mmap_req = {
+ (PVOID) MMAP_STORAGE_LOW,
+ (PVOID) (MMAP_STORAGE_HIGH - 1),
+ 0
+ };
+ MEM_EXTENDED_PARAMETER mmap_ext = {
+ .Type = MemExtendedParameterAddressRequirements,
+ .Pointer = (PVOID) &mmap_req
+ };
+
+ base = VirtualAlloc2 (GetCurrentProcess(), *addr, len, alloc_type,
+ protect, *addr ? NULL : &mmap_ext,
+ *addr ? 0 : 1);
+ if (!base && addr && !fixed (flags))
+ base = VirtualAlloc2 (GetCurrentProcess(), NULL, len, alloc_type,
+ protect, &mmap_ext, 1);
+ }
+ else
+#endif
+ {
+ base = VirtualAlloc (*addr, len, alloc_type, protect);
+ if (!base && addr && !fixed (flags))
+ base = VirtualAlloc (NULL, len, alloc_type, protect);
+ }
if (!base || (fixed (flags) && base != *addr))
{
if (!base)
@@ -1664,7 +1727,7 @@ fhandler_dev_zero::mmap (caddr_t *addr, size_t len, int prot,
return INVALID_HANDLE_VALUE;
}
- base = MapView (h, *addr, len, get_access(), prot, flags, off);
+ base = MapView (h, *addr, len, get_access(), prot, flags, off, false);
if (!base || (fixed (flags) && base != *addr))
{
if (!base)
@@ -1718,7 +1781,7 @@ fhandler_dev_zero::fixup_mmap_after_fork (HANDLE h, int prot, int flags,
base = VirtualAlloc (address, size, alloc_type, PAGE_READWRITE);
}
else
- base = MapView (h, address, size, get_access (), prot, flags, offset);
+ base = MapView (h, address, size, get_access (), prot, flags, offset, true);
if (base != address)
{
MEMORY_BASIC_INFORMATION m;
@@ -1744,7 +1807,7 @@ fhandler_disk_file::mmap (caddr_t *addr, size_t len, int prot,
return INVALID_HANDLE_VALUE;
}
- void *base = MapView (h, *addr, len, get_access (), prot, flags, off);
+ void *base = MapView (h, *addr, len, get_access (), prot, flags, off, false);
if (!base || (fixed (flags) && base != *addr))
{
if (!base)
@@ -1804,7 +1867,8 @@ fhandler_disk_file::fixup_mmap_after_fork (HANDLE h, int prot, int flags,
void *address)
{
/* Re-create the map */
- void *base = MapView (h, address, size, get_access (), prot, flags, offset);
+ void *base = MapView (h, address, size, get_access (), prot, flags,
+ offset, true);
if (base != address)
{
MEMORY_BASIC_INFORMATION m;