Alexandre Julliard : ntdll: Handle pages faults without fetching the view pointer when possible.

Alexandre Julliard julliard at winehq.org
Fri Sep 22 15:49:05 CDT 2017


Module: wine
Branch: master
Commit: 8bc95aa74be74d7ba9ce558d42902e55ece2a197
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=8bc95aa74be74d7ba9ce558d42902e55ece2a197

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Fri Sep 22 12:15:27 2017 +0200

ntdll: Handle pages faults without fetching the view pointer when possible.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/virtual.c | 49 +++++++++++++++++++++++++++++--------------------
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 7d6b36d..1e6b8a7 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -416,6 +416,16 @@ static inline UINT_PTR get_mask( ULONG zero_bits )
 
 
 /***********************************************************************
+ *           is_write_watch_range
+ */
+static inline BOOL is_write_watch_range( const void *addr, size_t size )
+{
+    struct file_view *view = VIRTUAL_FindView( addr, size );
+    return view && (view->protect & VPROT_WRITEWATCH);
+}
+
+
+/***********************************************************************
  *           find_view_range
  *
  * Find the first view overlapping at least part of the specified range.
@@ -1758,30 +1768,31 @@ void virtual_clear_thread_stack(void)
  */
 NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack )
 {
-    struct file_view *view;
     NTSTATUS ret = STATUS_ACCESS_VIOLATION;
+    void *page = ROUND_ADDR( addr, page_mask );
     sigset_t sigset;
+    BYTE vprot;
 
     server_enter_uninterrupted_section( &csVirtual, &sigset );
-    if ((view = VIRTUAL_FindView( addr, 0 )))
+    vprot = get_page_vprot( page );
+    if (!on_signal_stack && (vprot & VPROT_GUARD))
+    {
+        set_page_vprot_bits( page, page_size, 0, VPROT_GUARD );
+        mprotect_range( page, page_size, 0, 0 );
+        ret = STATUS_GUARD_PAGE_VIOLATION;
+    }
+    else if (err & EXCEPTION_WRITE_FAULT)
     {
-        void *page = ROUND_ADDR( addr, page_mask );
-        BYTE vprot = get_page_vprot( page );
-        if ((err & EXCEPTION_WRITE_FAULT) && (view->protect & VPROT_WRITEWATCH))
+        if (vprot & VPROT_WRITEWATCH)
         {
-            if (vprot & VPROT_WRITEWATCH)
-            {
-                set_page_vprot_bits( page, page_size, 0, VPROT_WRITEWATCH );
-                mprotect_range( page, page_size, 0, 0 );
-            }
-            /* ignore fault if page is writable now */
-            if (VIRTUAL_GetUnixProt( get_page_vprot( page )) & PROT_WRITE) ret = STATUS_SUCCESS;
+            set_page_vprot_bits( page, page_size, 0, VPROT_WRITEWATCH );
+            mprotect_range( page, page_size, 0, 0 );
         }
-        if (!on_signal_stack && (vprot & VPROT_GUARD))
+        /* ignore fault if page is writable now */
+        if (VIRTUAL_GetUnixProt( get_page_vprot( page )) & PROT_WRITE)
         {
-            set_page_vprot_bits( page, page_size, 0, VPROT_GUARD );
-            mprotect_range( page, page_size, 0, 0 );
-            ret = STATUS_GUARD_PAGE_VIOLATION;
+            if ((vprot & VPROT_WRITEWATCH) || is_write_watch_range( page, page_size ))
+                ret = STATUS_SUCCESS;
         }
     }
     server_leave_uninterrupted_section( &csVirtual, &sigset );
@@ -3061,7 +3072,6 @@ NTSTATUS WINAPI NtFlushVirtualMemory( HANDLE process, LPCVOID *addr_ptr,
 NTSTATUS WINAPI NtGetWriteWatch( HANDLE process, ULONG flags, PVOID base, SIZE_T size, PVOID *addresses,
                                  ULONG_PTR *count, ULONG *granularity )
 {
-    struct file_view *view;
     NTSTATUS status = STATUS_SUCCESS;
     sigset_t sigset;
 
@@ -3079,7 +3089,7 @@ NTSTATUS WINAPI NtGetWriteWatch( HANDLE process, ULONG flags, PVOID base, SIZE_T
 
     server_enter_uninterrupted_section( &csVirtual, &sigset );
 
-    if ((view = VIRTUAL_FindView( base, size )) && (view->protect & VPROT_WRITEWATCH))
+    if (is_write_watch_range( base, size ))
     {
         ULONG_PTR pos = 0;
         char *addr = base;
@@ -3107,7 +3117,6 @@ NTSTATUS WINAPI NtGetWriteWatch( HANDLE process, ULONG flags, PVOID base, SIZE_T
  */
 NTSTATUS WINAPI NtResetWriteWatch( HANDLE process, PVOID base, SIZE_T size )
 {
-    struct file_view *view;
     NTSTATUS status = STATUS_SUCCESS;
     sigset_t sigset;
 
@@ -3120,7 +3129,7 @@ NTSTATUS WINAPI NtResetWriteWatch( HANDLE process, PVOID base, SIZE_T size )
 
     server_enter_uninterrupted_section( &csVirtual, &sigset );
 
-    if ((view = VIRTUAL_FindView( base, size )) && (view->protect & VPROT_WRITEWATCH))
+    if (is_write_watch_range( base, size ))
         reset_write_watches( base, size );
     else
         status = STATUS_INVALID_PARAMETER;




More information about the wine-cvs mailing list