Module: wine Branch: master Commit: 8bc95aa74be74d7ba9ce558d42902e55ece2a197 URL: http://source.winehq.org/git/wine.git/?a=commit;h=8bc95aa74be74d7ba9ce558d42...
Author: Alexandre Julliard julliard@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@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;