Implement POSIX_MADV_WILLNEED/POSIX_MADV_DONTNEED for newer OSes

* autoload.cc (DiscardVirtualMemory): Import.
        (PrefetchVirtualMemory): Import.
        * mmap.cc (posix_madvise): Actually implement POSIX_MADV_WILLNEED
        utilizing PrefetchVirtualMemory and POSIX_MADV_DONTNEED utilizing
        DiscardVirtualMemory on systems supporting them.
        * wincap.h (wincaps::has_broken_prefetchvm): New element.
        * wincap.cc: Implement above element throughout.
        (wincapc::init): Make sure has_broken_prefetchvm is only true on
        W10 under WOW64.
        * include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2003.
        (CYGWIN_VERSION_API_MINOR): Reset to 0.

        * new-features.xml (ov-new2.3): New section, document posix_madvise
        POSIX_MADV_WILLNEED/POSIX_MADV_DONTNEED change.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2015-08-27 13:34:10 +02:00
parent e6d9af11f1
commit 35d5d87540
9 changed files with 149 additions and 21 deletions

View File

@ -1,3 +1,17 @@
2015-08-27 Corinna Vinschen <corinna@vinschen.de>
* autoload.cc (DiscardVirtualMemory): Import.
(PrefetchVirtualMemory): Import.
* mmap.cc (posix_madvise): Actually implement POSIX_MADV_WILLNEED
utilizing PrefetchVirtualMemory and POSIX_MADV_DONTNEED utilizing
DiscardVirtualMemory on systems supporting them.
* wincap.h (wincaps::has_broken_prefetchvm): New element.
* wincap.cc: Implement above element throughout.
(wincapc::init): Make sure has_broken_prefetchvm is only true on
W10 under WOW64.
* include/cygwin/version.h (CYGWIN_VERSION_DLL_MAJOR): Bump to 2003.
(CYGWIN_VERSION_API_MINOR): Reset to 0.
2015-08-26 Corinna Vinschen <corinna@vinschen.de>
* fhandler_proc.cc (format_proc_cpuinfo): Only fetch group relations,

View File

@ -570,12 +570,14 @@ LoadDLLfunc (GetUdpTable, 12, iphlpapi)
LoadDLLfuncEx (CancelSynchronousIo, 4, kernel32, 1)
LoadDLLfunc (CreateSymbolicLinkW, 12, kernel32)
LoadDLLfuncEx2 (DiscardVirtualMemory, 8, kernel32, 1, 127)
LoadDLLfuncEx (GetLogicalProcessorInformationEx, 12, kernel32, 1)
LoadDLLfuncEx (GetNamedPipeClientProcessId, 8, kernel32, 1)
LoadDLLfunc (GetSystemTimePreciseAsFileTime, 4, kernel32)
LoadDLLfuncEx (IdnToAscii, 20, kernel32, 1)
LoadDLLfuncEx (IdnToUnicode, 20, kernel32, 1)
LoadDLLfunc (LocaleNameToLCID, 8, kernel32)
LoadDLLfuncEx (PrefetchVirtualMemory, 16, kernel32, 1)
LoadDLLfunc (SetThreadGroupAffinity, 12, kernel32)
LoadDLLfunc (SetThreadStackGuarantee, 4, kernel32)

View File

@ -42,8 +42,8 @@ details. */
the Cygwin shared library". This version is used to track important
changes to the DLL and is mainly informative in nature. */
#define CYGWIN_VERSION_DLL_MAJOR 2002
#define CYGWIN_VERSION_DLL_MINOR 2
#define CYGWIN_VERSION_DLL_MAJOR 2003
#define CYGWIN_VERSION_DLL_MINOR 0
/* Major numbers before CYGWIN_VERSION_DLL_EPOCH are
incompatible. */

View File

@ -1531,35 +1531,111 @@ munlock (const void *addr, size_t len)
return ret;
}
/* This is required until Mingw-w64 catches up with newer functions. */
extern "C" WINAPI DWORD DiscardVirtualMemory (PVOID, SIZE_T);
extern "C" int
posix_madvise (void *addr, size_t len, int advice)
{
int ret;
int ret = 0;
/* Check parameters. */
if (advice < POSIX_MADV_NORMAL || advice > POSIX_MADV_DONTNEED
|| !len)
ret = EINVAL;
else
{
/* Check requested memory area. */
MEMORY_BASIC_INFORMATION m;
char *p = (char *) addr;
char *endp = p + len;
while (p < endp)
{
if (!VirtualQuery (p, &m, sizeof m) || m.State == MEM_FREE)
{
ret = ENOMEM;
break;
}
p = (char *) m.BaseAddress + m.RegionSize;
}
ret = 0;
ret = EINVAL;
goto out;
}
/* Check requested memory area. */
MEMORY_BASIC_INFORMATION m;
char *p, *endp;
for (p = (char *) addr, endp = p + len;
p < endp;
p = (char *) m.BaseAddress + m.RegionSize)
{
if (!VirtualQuery (p, &m, sizeof m) || m.State == MEM_FREE)
{
ret = ENOMEM;
break;
}
}
if (ret)
goto out;
switch (advice)
{
case POSIX_MADV_WILLNEED:
{
/* Align address and length values to page size. */
size_t pagesize = wincap.allocation_granularity ();
PVOID base = (PVOID) rounddown ((uintptr_t) addr, pagesize);
SIZE_T size = roundup2 (((uintptr_t) addr - (uintptr_t) base)
+ len, pagesize);
WIN32_MEMORY_RANGE_ENTRY me = { base, size };
if (!PrefetchVirtualMemory (GetCurrentProcess (), 1, &me, 0)
&& GetLastError () != ERROR_PROC_NOT_FOUND)
{
/* FIXME 2015-08-27: On W10 build 10240 under WOW64,
PrefetchVirtualMemory always returns ERROR_INVALID_PARAMETER
for some reason. If we're running on W10 WOW64, ignore this
error for now. There's an open case at Microsoft for this. */
if (!wincap.has_broken_prefetchvm ()
|| GetLastError () != ERROR_INVALID_PARAMETER)
ret = EINVAL;
}
}
break;
case POSIX_MADV_DONTNEED:
{
/* Align address and length values to page size. */
size_t pagesize = wincap.allocation_granularity ();
PVOID base = (PVOID) rounddown ((uintptr_t) addr, pagesize);
SIZE_T size = roundup2 (((uintptr_t) addr - (uintptr_t) base)
+ len, pagesize);
DWORD err = DiscardVirtualMemory (base, size);
/* DiscardVirtualMemory is unfortunately pretty crippled:
On copy-on-write pages it returns ERROR_INVALID_PARAMETER, on
any file-backed memory map it returns ERROR_USER_MAPPED_FILE.
Since POSIX_MADV_DONTNEED is advisory only anyway, let them
slip through. */
switch (err)
{
case ERROR_PROC_NOT_FOUND:
case ERROR_USER_MAPPED_FILE:
case 0:
break;
case ERROR_INVALID_PARAMETER:
{
ret = EINVAL;
/* Check if the region contains copy-on-write pages.*/
for (p = (char *) addr, endp = p + len;
p < endp;
p = (char *) m.BaseAddress + m.RegionSize)
{
if (VirtualQuery (p, &m, sizeof m)
&& m.State == MEM_COMMIT
&& m.Protect
& (PAGE_EXECUTE_WRITECOPY | PAGE_WRITECOPY))
{
/* Yes, let this slip. */
ret = 0;
break;
}
}
}
break;
default:
ret = geterrno_from_win_error (err);
break;
}
}
break;
default:
break;
}
out:
syscall_printf ("%d = posix_madvise(%p, %lu, %d)", ret, addr, len, advice);
/* Eventually do nothing. */
return 0;
return ret;
}
/*

View File

@ -1,6 +1,12 @@
What's new:
-----------
- posix_madvise(POSIX_MADV_WILLNEED) now utilizes OS functionality available
starting with Windows 8/Server 2012. Still a no-op on older systems.
- posix_madvise(POSIX_MADV_DONTNEED) now utilizes OS functionality available
starting with Windows 8.1/Server 2012R2. Still a no-op on older systems.
What changed:
-------------

View File

@ -50,6 +50,7 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_set_thread_stack_guarantee:false,
has_broken_rtl_query_process_debug_information:false,
has_processor_groups:false,
has_broken_prefetchvm:false,
};
wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -82,6 +83,7 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_set_thread_stack_guarantee:true,
has_broken_rtl_query_process_debug_information:true,
has_processor_groups:false,
has_broken_prefetchvm:false,
};
wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -114,6 +116,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
has_set_thread_stack_guarantee:true,
has_broken_rtl_query_process_debug_information:false,
has_processor_groups:false,
has_broken_prefetchvm:false,
};
wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -146,6 +149,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_set_thread_stack_guarantee:true,
has_broken_rtl_query_process_debug_information:false,
has_processor_groups:true,
has_broken_prefetchvm:false,
};
wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -178,6 +182,7 @@ wincaps wincap_8 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_set_thread_stack_guarantee:true,
has_broken_rtl_query_process_debug_information:false,
has_processor_groups:true,
has_broken_prefetchvm:false,
};
wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -210,6 +215,7 @@ wincaps wincap_10 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_set_thread_stack_guarantee:true,
has_broken_rtl_query_process_debug_information:false,
has_processor_groups:true,
has_broken_prefetchvm:true,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
@ -281,6 +287,7 @@ wincapc::init ()
((wincaps *)caps)->has_restricted_stack_args = false;
((wincaps *)caps)->wow64_has_secondary_stack = false;
((wincaps *)caps)->has_gaa_largeaddress_bug = false;
((wincaps *)caps)->has_broken_prefetchvm = false;
}
__small_sprintf (osnam, "NT-%d.%d", version.dwMajorVersion,

View File

@ -43,6 +43,7 @@ struct wincaps
unsigned has_set_thread_stack_guarantee : 1;
unsigned has_broken_rtl_query_process_debug_information : 1;
unsigned has_processor_groups : 1;
unsigned has_broken_prefetchvm : 1;
};
class wincapc
@ -100,6 +101,7 @@ public:
bool IMPLEMENT (has_set_thread_stack_guarantee)
bool IMPLEMENT (has_broken_rtl_query_process_debug_information)
bool IMPLEMENT (has_processor_groups)
bool IMPLEMENT (has_broken_prefetchvm)
#undef IMPLEMENT
};

View File

@ -1,3 +1,8 @@
2015-08-27 Corinna Vinschen <corinna@vinschen.de>
* new-features.xml (ov-new2.3): New section, document posix_madvise
POSIX_MADV_WILLNEED/POSIX_MADV_DONTNEED change.
2015-08-18 Jon Turney <jon.turney@dronecode.org.uk>
* faq-using.xml (faq.using.bloda): Add Lavasoft Web Companion to

View File

@ -4,6 +4,22 @@
<sect1 id="ov-new"><title>What's new and what changed in Cygwin</title>
<sect2 id="ov-new2.3"><title>What's new and what changed in 2.3</title>
<itemizedlist mark="bullet">
<listitem><para>
posix_madvise(POSIX_MADV_WILLNEED) now utilizes OS functionality available
starting with Windows 8/Server 2012.
</para><para>
posix_madvise(POSIX_MADV_DONTNEED) now utilizes OS functionality available
starting with Windows 8.1/Server 2012R2.
</para></listitem>
</itemizedlist>
</sect2>
<sect2 id="ov-new2.2"><title>What's new and what changed in 2.2</title>
<itemizedlist mark="bullet">