public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: mmap: Remove AT_ROUND_TO_PAGE workaround
@ 2020-07-22  8:51 Corinna Vinschen
  0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2020-07-22  8:51 UTC (permalink / raw)
  To: cygwin-cvs

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=1c803a6d8864d6f7b2696099f44734914657aa7c

commit 1c803a6d8864d6f7b2696099f44734914657aa7c
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Mon Jul 20 20:55:43 2020 +0200

    Cygwin: mmap: Remove AT_ROUND_TO_PAGE workaround
    
    It's working on 32 bit OSes only anyway. It even fails on WOW64.
    
    Drop unsupported NtMapViewOfSection flags.
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 winsup/cygwin/mmap.cc | 145 +++++++++++++++-----------------------------------
 winsup/cygwin/ntdll.h |   4 --
 2 files changed, 43 insertions(+), 106 deletions(-)

diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index 1fccc6c58..6b2e1c655 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -172,8 +172,7 @@ CreateMapping (HANDLE fhdl, size_t len, off_t off, DWORD openflags,
     }
   else
     {
-      /* Zero len creates mapping for whole file and allows
-	 AT_EXTENDABLE_FILE mapping, if we ever use it... */
+      /* Zero len creates mapping for whole file */
       sectionsize.QuadPart = 0;
       status = NtCreateSection (&h, SECTION_ALL_ACCESS, &oa, &sectionsize,
 				protect, attributes, fhdl);
@@ -195,12 +194,7 @@ MapView (HANDLE h, void *addr, size_t len, DWORD openflags,
   DWORD protect = gen_create_protect (openflags, flags);
   void *base = addr;
   SIZE_T viewsize = len;
-#ifdef __x86_64__ /* AT_ROUND_TO_PAGE isn't supported on 64 bit systems. */
   ULONG alloc_type = MEM_TOP_DOWN;
-#else
-  ULONG alloc_type = (base && !wincap.is_wow64 () ? AT_ROUND_TO_PAGE : 0)
-		     | MEM_TOP_DOWN;
-#endif
 
 #ifdef __x86_64__
   /* Don't call NtMapViewOfSectionEx during fork.  It requires autoloading
@@ -878,6 +872,10 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, off_t off)
 
   if (!anonymous (flags) && fd != -1)
     {
+      UNICODE_STRING fname;
+      IO_STATUS_BLOCK io;
+      FILE_STANDARD_INFORMATION fsi;
+
       /* Ensure that fd is open */
       cygheap_fdget cfd (fd);
       if (cfd < 0)
@@ -896,19 +894,16 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, off_t off)
 
       /* The autoconf mmap test maps a file of size 1 byte.  It then tests
 	 every byte of the entire mapped page of 64K for 0-bytes since that's
-	 what POSIX requires.  The problem is, we can't create that mapping on
-	 64 bit systems.  The file mapping will be only a single page, 4K, and
-	 since 64 bit systems don't support the AT_ROUND_TO_PAGE flag, the
-	 remainder of the 64K slot will result in a SEGV when accessed.
-
-	 So, what we do here is cheating for the sake of the autoconf test
-	 on 64 bit systems.  The justification is that there's very likely
-	 no application actually utilizing the map beyond EOF, and we know that
-	 all bytes beyond EOF are set to 0 anyway.  If this test doesn't work
-	 on 64 bit systems, it will result in not using mmap at all in a
-	 package.  But we want that mmap is treated as usable by autoconf,
-	 regardless whether the autoconf test runs on a 32 bit or a 64 bit
-	 system.
+	 what POSIX requires.  The problem is, we can't create that mapping.
+	 The file mapping will be only a single page, 4K, and the remainder
+	 of the 64K slot will result in a SEGV when accessed.
+
+	 So, what we do here is cheating for the sake of the autoconf test.
+	 The justification is that there's very likely no application actually
+	 utilizing the map beyond EOF, and we know that all bytes beyond EOF
+	 are set to 0 anyway.  If this test doesn't work, it will result in
+	 not using mmap at all in a package.  But we want mmap being treated
+	 as usable by autoconf.
 
 	 Ok, so we know exactly what autoconf is doing.  The file is called
 	 "conftest.txt", it has a size of 1 byte, the mapping size is the
@@ -916,31 +911,19 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, off_t off)
 	 mapping is MAP_SHARED, the offset is 0.
 
 	 If all these requirements are given, we just return an anonymous map.
-	 This will help to get over the autoconf test even on 64 bit systems.
 	 The tests are ordered for speed. */
-#ifdef __x86_64__
-      if (1)
-#else
-      if (wincap.is_wow64 ())
-#endif
-	{
-	  UNICODE_STRING fname;
-	  IO_STATUS_BLOCK io;
-	  FILE_STANDARD_INFORMATION fsi;
-
-	  if (len == pagesize
-	      && prot == (PROT_READ | PROT_WRITE)
-	      && flags == MAP_SHARED
-	      && off == 0
-	      && (RtlSplitUnicodePath (fh->pc.get_nt_native_path (), NULL,
-				       &fname),
-		  wcscmp (fname.Buffer, L"conftest.txt") == 0)
-	      && NT_SUCCESS (NtQueryInformationFile (fh->get_handle (), &io,
-						     &fsi, sizeof fsi,
-						     FileStandardInformation))
-	      && fsi.EndOfFile.QuadPart == 1LL)
-	    flags |= MAP_ANONYMOUS;
-	}
+      if (len == pagesize
+	  && prot == (PROT_READ | PROT_WRITE)
+	  && flags == MAP_SHARED
+	  && off == 0
+	  && (RtlSplitUnicodePath (fh->pc.get_nt_native_path (), NULL,
+				   &fname),
+	      wcscmp (fname.Buffer, L"conftest.txt") == 0)
+	  && NT_SUCCESS (NtQueryInformationFile (fh->get_handle (), &io,
+						 &fsi, sizeof fsi,
+						 FileStandardInformation))
+	  && fsi.EndOfFile.QuadPart == 1LL)
+	flags |= MAP_ANONYMOUS;
     }
 
   if (anonymous (flags) || fd == -1)
@@ -1025,20 +1008,8 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, off_t off)
 	  goto go_ahead;
 	}
       fsiz -= off;
-      /* We're creating the pages beyond EOF as reserved, anonymous pages.
-	 Note that 64 bit environments don't support the AT_ROUND_TO_PAGE
-	 flag, which is required to get this right for the remainder of
-	 the first 64K block the file ends in.  We perform the workaround
-	 nevertheless to support expectations that the range mapped beyond
-	 EOF can be safely munmap'ed instead of being taken by another,
-	 totally unrelated mapping. */
-      if ((off_t) len > fsiz && !autogrow (flags))
-	orig_len = len;
-#ifdef __i386__
-      else if (!wincap.is_wow64 () && roundup2 (len, wincap.page_size ())
-				      < roundup2 (len, pagesize))
-	orig_len = len;
-#endif
+      /* We're creating the pages beyond EOF as reserved, anonymous
+	 pages if MAP_AUTOGROW is not set. */
       if ((off_t) len > fsiz)
 	{
 	  if (autogrow (flags))
@@ -1053,9 +1024,12 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, off_t off)
 		}
 	    }
 	  else
-	    /* Otherwise, don't map beyond EOF, since Windows would change
-	       the file to the new length, in contrast to POSIX. */
-	    len = fsiz;
+	    {
+	      /* Otherwise, don't map beyond EOF, since Windows would change
+		 the file to the new length, in contrast to POSIX. */
+	      orig_len = len;
+	      len = fsiz;
+	    }
 	}
 
       /* If the requested offset + len is <= file size, drop MAP_AUTOGROW.
@@ -1088,6 +1062,7 @@ go_ahead:
 	}
     }
 
+  orig_len = roundup2 (orig_len, pagesize);
 #ifdef __x86_64__
   if (!wincap.has_extended_mem_api ())
     addr = mmap_alloc.alloc (addr, orig_len ?: len, fixed (flags));
@@ -1099,7 +1074,6 @@ go_ahead:
 	 deallocated and the address we got is used as base address for the
 	 subsequent real mappings.  This ensures that we have enough space
 	 for the whole thing. */
-      orig_len = roundup2 (orig_len, pagesize);
       PVOID newaddr = VirtualAlloc (addr, orig_len, MEM_TOP_DOWN | MEM_RESERVE,
 				    PAGE_READWRITE);
       if (!newaddr)
@@ -1132,51 +1106,18 @@ go_ahead:
   if (orig_len)
     {
       /* If the requested length is bigger than the file size, the
-	 remainder is created as anonymous mapping.  Actually two
-	 mappings are created, first the remainder from the file end to
-	 the next 64K boundary as accessible pages with the same
-	 protection as the file's pages, then as much pages as necessary
-	 to accomodate the requested length, but as reserved pages which
-	 raise a SIGBUS when trying to access them.  AT_ROUND_TO_PAGE
-	 and page protection on shared pages is only supported by the
-	 32 bit environment, so don't even try on 64 bit or even WOW64.
-	 This results in an allocation gap in the first 64K block the file
-	 ends in, but there's nothing at all we can do about that. */
-#ifdef __x86_64__
-      len = roundup2 (len, wincap.allocation_granularity ());
-      orig_len = roundup2 (orig_len, wincap.allocation_granularity ());
-#else
-      len = roundup2 (len, wincap.is_wow64 () ? wincap.allocation_granularity ()
-					      : wincap.page_size ());
-#endif
+	 remainder is created as anonymous mapping, as reserved pages which
+	 raise a SIGBUS when trying to access them.  This results in an
+	 allocation gap in the first 64K block the file ends in, but there's
+	 nothing at all we can do about that. */
+      len = roundup2 (len, pagesize);
       if (orig_len - len)
 	{
-	  orig_len -= len;
-	  size_t valid_page_len = 0;
-#ifndef __x86_64__
-	  if (!wincap.is_wow64 ())
-	    valid_page_len = orig_len % pagesize;
-#endif
-	  size_t sigbus_page_len = orig_len - valid_page_len;
+	  size_t sigbus_page_len = orig_len - len;
 
-	  caddr_t at_base = base + len;
-	  if (valid_page_len)
-	    {
-	      prot |= __PROT_FILLER;
-	      flags &= MAP_SHARED | MAP_PRIVATE;
-	      flags |= MAP_ANONYMOUS | MAP_FIXED;
-	      at_base = mmap_worker (NULL, &fh_anonymous, at_base,
-				     valid_page_len, prot, flags, -1, 0, NULL);
-	      if (!at_base)
-		{
-		  fh->munmap (fh->get_handle (), base, len);
-		  set_errno (ENOMEM);
-		  goto out_with_unlock;
-		}
-	      at_base += valid_page_len;
-	    }
 	  if (sigbus_page_len)
 	    {
+	      caddr_t at_base = base + len;
 	      prot = PROT_READ | PROT_WRITE | __PROT_ATTACH;
 	      flags = MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED;
 	      at_base = mmap_worker (NULL, &fh_anonymous, at_base,
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 5c6552751..0c6ad13dc 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -51,10 +51,6 @@ extern GUID __cygwin_socket_guid;
 #define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
 #define FILE_DEVICE_SECURE_OPEN        0x00000100
 
-/* Allocation type values in NtMapViewOfSection call. */
-#define AT_EXTENDABLE_FILE 0x00002000
-#define AT_ROUND_TO_PAGE 0x40000000
-
 /* Lock type in NtLockVirtualMemory/NtUnlockVirtualMemory call. */
 #define MAP_PROCESS 1
 #define MAP_SYSTEM  2


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-07-22  8:51 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-22  8:51 [newlib-cygwin] Cygwin: mmap: Remove AT_ROUND_TO_PAGE workaround Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).