[newlib-cygwin] Implement POSIX_MADV_WILLNEED/POSIX_MADV_DONTNEED for newer OSes

Corinna Vinschen corinna@sourceware.org
Thu Aug 27 11:34:00 GMT 2015


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

commit 35d5d87540c3262c341c35e974d0d3a53ce30684
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Thu Aug 27 13:34:10 2015 +0200

    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>

Diff:
---
 winsup/cygwin/ChangeLog                |  14 +++++
 winsup/cygwin/autoload.cc              |   2 +
 winsup/cygwin/include/cygwin/version.h |   4 +-
 winsup/cygwin/mmap.cc                  | 110 ++++++++++++++++++++++++++++-----
 winsup/cygwin/release/{2.2.2 => 2.3.0} |   6 ++
 winsup/cygwin/wincap.cc                |   7 +++
 winsup/cygwin/wincap.h                 |   2 +
 winsup/doc/ChangeLog                   |   5 ++
 winsup/doc/new-features.xml            |  16 +++++
 9 files changed, 147 insertions(+), 19 deletions(-)

diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index ba25c1e..c76eb7a 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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,
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index f9c0f00..0192c6d 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -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)
 
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index 82a0f96..53842ef 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -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. */
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index cb8b828..984504e 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -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)
+      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)
 	{
-	  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 = ENOMEM;
-	      break;
+	      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;
+		    }
+		}
 	    }
-	  p = (char *) m.BaseAddress + m.RegionSize;
-	}
-      ret = 0;
+	    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;
 }
 
 /*
diff --git a/winsup/cygwin/release/2.2.2 b/winsup/cygwin/release/2.3.0
similarity index 58%
rename from winsup/cygwin/release/2.2.2
rename to winsup/cygwin/release/2.3.0
index baa2d0d..88b6748 100644
--- a/winsup/cygwin/release/2.2.2
+++ b/winsup/cygwin/release/2.3.0
@@ -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:
 -------------
diff --git a/winsup/cygwin/wincap.cc b/winsup/cygwin/wincap.cc
index 92d47d3..6e98df6 100644
--- a/winsup/cygwin/wincap.cc
+++ b/winsup/cygwin/wincap.cc
@@ -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,
diff --git a/winsup/cygwin/wincap.h b/winsup/cygwin/wincap.h
index e4f67bc..26751b1 100644
--- a/winsup/cygwin/wincap.h
+++ b/winsup/cygwin/wincap.h
@@ -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
 };
diff --git a/winsup/doc/ChangeLog b/winsup/doc/ChangeLog
index 02061ff..c645c67 100644
--- a/winsup/doc/ChangeLog
+++ b/winsup/doc/ChangeLog
@@ -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
diff --git a/winsup/doc/new-features.xml b/winsup/doc/new-features.xml
index ed8d61d..edd1963 100644
--- a/winsup/doc/new-features.xml
+++ b/winsup/doc/new-features.xml
@@ -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">



More information about the Cygwin-cvs mailing list