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>
This commit is contained in:
parent
16baeb7fb7
commit
7218c5466f
|
@ -172,8 +172,7 @@ CreateMapping (HANDLE fhdl, size_t len, off_t off, DWORD openflags,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Zero len creates mapping for whole file and allows
|
/* Zero len creates mapping for whole file */
|
||||||
AT_EXTENDABLE_FILE mapping, if we ever use it... */
|
|
||||||
sectionsize.QuadPart = 0;
|
sectionsize.QuadPart = 0;
|
||||||
status = NtCreateSection (&h, SECTION_ALL_ACCESS, &oa, §ionsize,
|
status = NtCreateSection (&h, SECTION_ALL_ACCESS, &oa, §ionsize,
|
||||||
protect, attributes, fhdl);
|
protect, attributes, fhdl);
|
||||||
|
@ -195,12 +194,7 @@ MapView (HANDLE h, void *addr, size_t len, DWORD openflags,
|
||||||
DWORD protect = gen_create_protect (openflags, flags);
|
DWORD protect = gen_create_protect (openflags, flags);
|
||||||
void *base = addr;
|
void *base = addr;
|
||||||
SIZE_T viewsize = 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;
|
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__
|
#ifdef __x86_64__
|
||||||
/* Don't call NtMapViewOfSectionEx during fork. It requires autoloading
|
/* 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)
|
if (!anonymous (flags) && fd != -1)
|
||||||
{
|
{
|
||||||
|
UNICODE_STRING fname;
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
FILE_STANDARD_INFORMATION fsi;
|
||||||
|
|
||||||
/* Ensure that fd is open */
|
/* Ensure that fd is open */
|
||||||
cygheap_fdget cfd (fd);
|
cygheap_fdget cfd (fd);
|
||||||
if (cfd < 0)
|
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
|
/* 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
|
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
|
what POSIX requires. The problem is, we can't create that mapping.
|
||||||
64 bit systems. The file mapping will be only a single page, 4K, and
|
The file mapping will be only a single page, 4K, and the remainder
|
||||||
since 64 bit systems don't support the AT_ROUND_TO_PAGE flag, the
|
of the 64K slot will result in a SEGV when accessed.
|
||||||
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
|
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
|
The justification is that there's very likely no application actually
|
||||||
no application actually utilizing the map beyond EOF, and we know that
|
utilizing the map beyond EOF, and we know that all bytes beyond EOF
|
||||||
all bytes beyond EOF are set to 0 anyway. If this test doesn't work
|
are set to 0 anyway. If this test doesn't work, it will result in
|
||||||
on 64 bit systems, it will result in not using mmap at all in a
|
not using mmap at all in a package. But we want mmap being treated
|
||||||
package. But we want that mmap is treated as usable by autoconf,
|
as usable by autoconf.
|
||||||
regardless whether the autoconf test runs on a 32 bit or a 64 bit
|
|
||||||
system.
|
|
||||||
|
|
||||||
Ok, so we know exactly what autoconf is doing. The file is called
|
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
|
"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.
|
mapping is MAP_SHARED, the offset is 0.
|
||||||
|
|
||||||
If all these requirements are given, we just return an anonymous map.
|
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. */
|
The tests are ordered for speed. */
|
||||||
#ifdef __x86_64__
|
if (len == pagesize
|
||||||
if (1)
|
&& prot == (PROT_READ | PROT_WRITE)
|
||||||
#else
|
&& flags == MAP_SHARED
|
||||||
if (wincap.is_wow64 ())
|
&& off == 0
|
||||||
#endif
|
&& (RtlSplitUnicodePath (fh->pc.get_nt_native_path (), NULL,
|
||||||
{
|
&fname),
|
||||||
UNICODE_STRING fname;
|
wcscmp (fname.Buffer, L"conftest.txt") == 0)
|
||||||
IO_STATUS_BLOCK io;
|
&& NT_SUCCESS (NtQueryInformationFile (fh->get_handle (), &io,
|
||||||
FILE_STANDARD_INFORMATION fsi;
|
&fsi, sizeof fsi,
|
||||||
|
FileStandardInformation))
|
||||||
if (len == pagesize
|
&& fsi.EndOfFile.QuadPart == 1LL)
|
||||||
&& prot == (PROT_READ | PROT_WRITE)
|
flags |= MAP_ANONYMOUS;
|
||||||
&& 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)
|
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;
|
goto go_ahead;
|
||||||
}
|
}
|
||||||
fsiz -= off;
|
fsiz -= off;
|
||||||
/* We're creating the pages beyond EOF as reserved, anonymous pages.
|
/* We're creating the pages beyond EOF as reserved, anonymous
|
||||||
Note that 64 bit environments don't support the AT_ROUND_TO_PAGE
|
pages if MAP_AUTOGROW is not set. */
|
||||||
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
|
|
||||||
if ((off_t) len > fsiz)
|
if ((off_t) len > fsiz)
|
||||||
{
|
{
|
||||||
if (autogrow (flags))
|
if (autogrow (flags))
|
||||||
|
@ -1053,9 +1024,12 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, off_t off)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Otherwise, don't map beyond EOF, since Windows would change
|
{
|
||||||
the file to the new length, in contrast to POSIX. */
|
/* Otherwise, don't map beyond EOF, since Windows would change
|
||||||
len = fsiz;
|
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.
|
/* 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__
|
#ifdef __x86_64__
|
||||||
if (!wincap.has_extended_mem_api ())
|
if (!wincap.has_extended_mem_api ())
|
||||||
addr = mmap_alloc.alloc (addr, orig_len ?: len, fixed (flags));
|
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
|
deallocated and the address we got is used as base address for the
|
||||||
subsequent real mappings. This ensures that we have enough space
|
subsequent real mappings. This ensures that we have enough space
|
||||||
for the whole thing. */
|
for the whole thing. */
|
||||||
orig_len = roundup2 (orig_len, pagesize);
|
|
||||||
PVOID newaddr = VirtualAlloc (addr, orig_len, MEM_TOP_DOWN | MEM_RESERVE,
|
PVOID newaddr = VirtualAlloc (addr, orig_len, MEM_TOP_DOWN | MEM_RESERVE,
|
||||||
PAGE_READWRITE);
|
PAGE_READWRITE);
|
||||||
if (!newaddr)
|
if (!newaddr)
|
||||||
|
@ -1132,51 +1106,18 @@ go_ahead:
|
||||||
if (orig_len)
|
if (orig_len)
|
||||||
{
|
{
|
||||||
/* If the requested length is bigger than the file size, the
|
/* If the requested length is bigger than the file size, the
|
||||||
remainder is created as anonymous mapping. Actually two
|
remainder is created as anonymous mapping, as reserved pages which
|
||||||
mappings are created, first the remainder from the file end to
|
raise a SIGBUS when trying to access them. This results in an
|
||||||
the next 64K boundary as accessible pages with the same
|
allocation gap in the first 64K block the file ends in, but there's
|
||||||
protection as the file's pages, then as much pages as necessary
|
nothing at all we can do about that. */
|
||||||
to accomodate the requested length, but as reserved pages which
|
len = roundup2 (len, pagesize);
|
||||||
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
|
|
||||||
if (orig_len - len)
|
if (orig_len - len)
|
||||||
{
|
{
|
||||||
orig_len -= len;
|
size_t sigbus_page_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;
|
|
||||||
|
|
||||||
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)
|
if (sigbus_page_len)
|
||||||
{
|
{
|
||||||
|
caddr_t at_base = base + len;
|
||||||
prot = PROT_READ | PROT_WRITE | __PROT_ATTACH;
|
prot = PROT_READ | PROT_WRITE | __PROT_ATTACH;
|
||||||
flags = MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED;
|
flags = MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED;
|
||||||
at_base = mmap_worker (NULL, &fh_anonymous, at_base,
|
at_base = mmap_worker (NULL, &fh_anonymous, at_base,
|
||||||
|
|
|
@ -51,10 +51,6 @@ extern GUID __cygwin_socket_guid;
|
||||||
#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
|
#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
|
||||||
#define FILE_DEVICE_SECURE_OPEN 0x00000100
|
#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. */
|
/* Lock type in NtLockVirtualMemory/NtUnlockVirtualMemory call. */
|
||||||
#define MAP_PROCESS 1
|
#define MAP_PROCESS 1
|
||||||
#define MAP_SYSTEM 2
|
#define MAP_SYSTEM 2
|
||||||
|
|
Loading…
Reference in New Issue