From: Corinna Vinschen <cori...@vinschen.de> It's working on 32 bit OSes only anyway. It even fails on WOW64.
Signed-off-by: Corinna Vinschen <cori...@vinschen.de> --- Notes: Hi Ken, can you please review this patch and check if it doesn't break your testcase again? Thanks, Corinna winsup/cygwin/mmap.cc | 117 ++++++++++++------------------------------ 1 file changed, 34 insertions(+), 83 deletions(-) diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc index 1fccc6c58ee9..8ac96606c2e6 100644 --- a/winsup/cygwin/mmap.cc +++ b/winsup/cygwin/mmap.cc @@ -195,12 +195,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 +873,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 +895,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 +912,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) @@ -1089,6 +1073,7 @@ go_ahead: } #ifdef __x86_64__ + orig_len = roundup2 (orig_len, pagesize); if (!wincap.has_extended_mem_api ()) addr = mmap_alloc.alloc (addr, orig_len ?: len, fixed (flags)); #else @@ -1099,7 +1084,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 +1116,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, -- 2.26.2