From 8f9cc5e01c2977ceacfe32aa51906bfcd3a9c64f Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sun, 6 Aug 2017 06:14:42 +0200 Subject: [PATCH] Added patch to use an inline version of Rtl{Enter,Leave}CriticalSection in some ntdll functions. --- ...e-Move-interlocked_inc-dec-to-port.h.patch | 90 ++++ ...-versions-of-RtlEnterCriticalSection.patch | 69 +++ ...e-fast-CS-functions-for-heap-locking.patch | 228 ++++++++++ ...-CS-functions-for-threadpool-locking.patch | 417 ++++++++++++++++++ patches/patchinstall.sh | 22 + 5 files changed, 826 insertions(+) create mode 100644 patches/ntdll-CriticalSection/0001-include-Move-interlocked_inc-dec-to-port.h.patch create mode 100644 patches/ntdll-CriticalSection/0002-ntdll-Add-inline-versions-of-RtlEnterCriticalSection.patch create mode 100644 patches/ntdll-CriticalSection/0003-ntdll-Use-fast-CS-functions-for-heap-locking.patch create mode 100644 patches/ntdll-CriticalSection/0004-ntdll-Use-fast-CS-functions-for-threadpool-locking.patch diff --git a/patches/ntdll-CriticalSection/0001-include-Move-interlocked_inc-dec-to-port.h.patch b/patches/ntdll-CriticalSection/0001-include-Move-interlocked_inc-dec-to-port.h.patch new file mode 100644 index 00000000..e46bb501 --- /dev/null +++ b/patches/ntdll-CriticalSection/0001-include-Move-interlocked_inc-dec-to-port.h.patch @@ -0,0 +1,90 @@ +From 1ac9a6a07169a6d9dc3583c332513586fa2e8a54 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sat, 5 Aug 2017 03:37:47 +0200 +Subject: include: Move interlocked_inc/dec to port.h. + +--- + dlls/ntdll/critsection.c | 10 ---------- + dlls/ntdll/threadpool.c | 10 ---------- + include/wine/port.h | 14 +++++++++++++- + 3 files changed, 13 insertions(+), 21 deletions(-) + +diff --git a/dlls/ntdll/critsection.c b/dlls/ntdll/critsection.c +index e405b08a5a7..a4bd463bd25 100644 +--- a/dlls/ntdll/critsection.c ++++ b/dlls/ntdll/critsection.c +@@ -40,16 +40,6 @@ + WINE_DEFAULT_DEBUG_CHANNEL(ntdll); + WINE_DECLARE_DEBUG_CHANNEL(relay); + +-static inline LONG interlocked_inc( PLONG dest ) +-{ +- return interlocked_xchg_add( dest, 1 ) + 1; +-} +- +-static inline LONG interlocked_dec( PLONG dest ) +-{ +- return interlocked_xchg_add( dest, -1 ) - 1; +-} +- + static inline void small_pause(void) + { + #ifdef __i386__ +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index 6063d51d9f9..b723e6f66f8 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -331,16 +331,6 @@ static void tp_object_prepare_shutdown( struct threadpool_object *object ); + static BOOL tp_object_release( struct threadpool_object *object ); + static struct threadpool *default_threadpool = NULL; + +-static inline LONG interlocked_inc( PLONG dest ) +-{ +- return interlocked_xchg_add( dest, 1 ) + 1; +-} +- +-static inline LONG interlocked_dec( PLONG dest ) +-{ +- return interlocked_xchg_add( dest, -1 ) - 1; +-} +- + static void CALLBACK process_rtl_work_item( TP_CALLBACK_INSTANCE *instance, void *userdata ) + { + struct rtl_work_item *item = userdata; +diff --git a/include/wine/port.h b/include/wine/port.h +index eb346e00fd3..e782ee00626 100644 +--- a/include/wine/port.h ++++ b/include/wine/port.h +@@ -506,6 +506,16 @@ static inline __int64 interlocked_cmpxchg64( __int64 *dest, __int64 xchg, __int6 + extern __int64 interlocked_cmpxchg64( __int64 *dest, __int64 xchg, __int64 compare ); + #endif + ++static inline int interlocked_inc( int *dest ) ++{ ++ return interlocked_xchg_add( dest, 1 ) + 1; ++} ++ ++static inline int interlocked_dec( int *dest ) ++{ ++ return interlocked_xchg_add( dest, -1 ) - 1; ++} ++ + #else /* NO_LIBWINE_PORT */ + + #define __WINE_NOT_PORTABLE(func) func##_is_not_portable func##_is_not_portable +@@ -516,9 +526,11 @@ extern __int64 interlocked_cmpxchg64( __int64 *dest, __int64 xchg, __int64 compa + #define getopt_long_only __WINE_NOT_PORTABLE(getopt_long_only) + #define interlocked_cmpxchg __WINE_NOT_PORTABLE(interlocked_cmpxchg) + #define interlocked_cmpxchg_ptr __WINE_NOT_PORTABLE(interlocked_cmpxchg_ptr) ++#define interlocked_dec __WINE_NOT_PORTABLE(interlocked_dec) ++#define interlocked_inc __WINE_NOT_PORTABLE(interlocked_inc) + #define interlocked_xchg __WINE_NOT_PORTABLE(interlocked_xchg) +-#define interlocked_xchg_ptr __WINE_NOT_PORTABLE(interlocked_xchg_ptr) + #define interlocked_xchg_add __WINE_NOT_PORTABLE(interlocked_xchg_add) ++#define interlocked_xchg_ptr __WINE_NOT_PORTABLE(interlocked_xchg_ptr) + #define lstat __WINE_NOT_PORTABLE(lstat) + #define memcpy_unaligned __WINE_NOT_PORTABLE(memcpy_unaligned) + #undef memmove +-- +2.13.1 + diff --git a/patches/ntdll-CriticalSection/0002-ntdll-Add-inline-versions-of-RtlEnterCriticalSection.patch b/patches/ntdll-CriticalSection/0002-ntdll-Add-inline-versions-of-RtlEnterCriticalSection.patch new file mode 100644 index 00000000..bb25bc85 --- /dev/null +++ b/patches/ntdll-CriticalSection/0002-ntdll-Add-inline-versions-of-RtlEnterCriticalSection.patch @@ -0,0 +1,69 @@ +From 52a0506018b5f61484935142b79e73dbbe0ae9d7 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sat, 5 Aug 2017 03:38:38 +0200 +Subject: ntdll: Add inline versions of RtlEnterCriticalSection / + RtlLeaveCriticalSections. + +--- + dlls/ntdll/ntdll_misc.h | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h +index 19d1e532759..c6c60090d10 100644 +--- a/dlls/ntdll/ntdll_misc.h ++++ b/dlls/ntdll/ntdll_misc.h +@@ -27,6 +27,7 @@ + #include "windef.h" + #include "winnt.h" + #include "winternl.h" ++#include "wine/debug.h" + #include "wine/server.h" + + #define MAX_NT_PATH_LENGTH 277 +@@ -198,6 +199,43 @@ extern int ntdll_wcstoumbs(DWORD flags, const WCHAR* src, int srclen, char* dst, + extern int CDECL NTDLL__vsnprintf( char *str, SIZE_T len, const char *format, __ms_va_list args ) DECLSPEC_HIDDEN; + extern int CDECL NTDLL__vsnwprintf( WCHAR *str, SIZE_T len, const WCHAR *format, __ms_va_list args ) DECLSPEC_HIDDEN; + ++#ifdef __WINE_WINE_PORT_H ++ ++/* inline version of RtlEnterCriticalSection */ ++static inline void enter_critical_section( RTL_CRITICAL_SECTION *crit ) ++{ ++ if (interlocked_inc( &crit->LockCount )) ++ { ++ if (crit->OwningThread == ULongToHandle(GetCurrentThreadId())) ++ { ++ crit->RecursionCount++; ++ return; ++ } ++ RtlpWaitForCriticalSection( crit ); ++ } ++ crit->OwningThread = ULongToHandle(GetCurrentThreadId()); ++ crit->RecursionCount = 1; ++} ++ ++/* inline version of RtlLeaveCriticalSection */ ++static inline void leave_critical_section( RTL_CRITICAL_SECTION *crit ) ++{ ++ WINE_DECLARE_DEBUG_CHANNEL(ntdll); ++ if (--crit->RecursionCount) ++ { ++ if (crit->RecursionCount > 0) interlocked_dec( &crit->LockCount ); ++ else ERR_(ntdll)( "section %p is not acquired\n", crit ); ++ } ++ else ++ { ++ crit->OwningThread = 0; ++ if (interlocked_dec( &crit->LockCount ) >= 0) ++ RtlpUnWaitCriticalSection( crit ); ++ } ++} ++ ++#endif /* __WINE_WINE_PORT_H */ ++ + /* load order */ + + enum loadorder +-- +2.13.1 + diff --git a/patches/ntdll-CriticalSection/0003-ntdll-Use-fast-CS-functions-for-heap-locking.patch b/patches/ntdll-CriticalSection/0003-ntdll-Use-fast-CS-functions-for-heap-locking.patch new file mode 100644 index 00000000..c0df3173 --- /dev/null +++ b/patches/ntdll-CriticalSection/0003-ntdll-Use-fast-CS-functions-for-heap-locking.patch @@ -0,0 +1,228 @@ +From 357104aee69fd26cf997692ba26a5e8bda1111de Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sat, 5 Aug 2017 03:39:23 +0200 +Subject: ntdll: Use fast CS functions for heap locking. + +--- + dlls/ntdll/heap.c | 52 ++++++++++++++++++++++++++-------------------------- + 1 file changed, 26 insertions(+), 26 deletions(-) + +diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c +index f4ddd7bd68a..f17356c740e 100644 +--- a/dlls/ntdll/heap.c ++++ b/dlls/ntdll/heap.c +@@ -1527,7 +1527,7 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr, /* [in] ptr to the heap */ + flags |= heapPtr->flags; + /* calling HeapLock may result in infinite recursion, so do the critsect directly */ + if (!(flags & HEAP_NO_SERIALIZE)) +- RtlEnterCriticalSection( &heapPtr->critSection ); ++ enter_critical_section( &heapPtr->critSection ); + + if (block) /* only check this single memory block */ + { +@@ -1550,7 +1550,7 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr, /* [in] ptr to the heap */ + ret = HEAP_ValidateInUseArena( subheap, arena, quiet ); + + if (!(flags & HEAP_NO_SERIALIZE)) +- RtlLeaveCriticalSection( &heapPtr->critSection ); ++ leave_critical_section( &heapPtr->critSection ); + return ret; + } + +@@ -1582,7 +1582,7 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr, /* [in] ptr to the heap */ + LIST_FOR_EACH_ENTRY( large_arena, &heapPtr->large_list, ARENA_LARGE, entry ) + if (!(ret = validate_large_arena( heapPtr, large_arena, quiet ))) break; + +- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) leave_critical_section( &heapPtr->critSection ); + return ret; + } + +@@ -1756,9 +1756,9 @@ HANDLE WINAPI RtlCreateHeap( ULONG flags, PVOID addr, SIZE_T totalSize, SIZE_T c + if (processHeap) + { + HEAP *heapPtr = subheap->heap; +- RtlEnterCriticalSection( &processHeap->critSection ); ++ enter_critical_section( &processHeap->critSection ); + list_add_head( &processHeap->entry, &heapPtr->entry ); +- RtlLeaveCriticalSection( &processHeap->critSection ); ++ leave_critical_section( &processHeap->critSection ); + } + else if (!addr) + { +@@ -1796,9 +1796,9 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap ) + if (heap == processHeap) return heap; /* cannot delete the main process heap */ + + /* remove it from the per-process list */ +- RtlEnterCriticalSection( &processHeap->critSection ); ++ enter_critical_section( &processHeap->critSection ); + list_remove( &heapPtr->entry ); +- RtlLeaveCriticalSection( &processHeap->critSection ); ++ leave_critical_section( &processHeap->critSection ); + + heapPtr->critSection.DebugInfo->Spare[0] = 0; + RtlDeleteCriticalSection( &heapPtr->critSection ); +@@ -1871,12 +1871,12 @@ PVOID WINAPI RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_T size ) + } + if (rounded_size < HEAP_MIN_DATA_SIZE) rounded_size = HEAP_MIN_DATA_SIZE; + +- if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) enter_critical_section( &heapPtr->critSection ); + + if (rounded_size >= HEAP_MIN_LARGE_BLOCK_SIZE && (flags & HEAP_GROWABLE)) + { + void *ret = allocate_large_block( heap, flags, size ); +- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) leave_critical_section( &heapPtr->critSection ); + if (!ret && (flags & HEAP_GENERATE_EXCEPTIONS)) RtlRaiseStatus( STATUS_NO_MEMORY ); + TRACE("(%p,%08x,%08lx): returning %p\n", heap, flags, size, ret ); + return ret; +@@ -1888,7 +1888,7 @@ PVOID WINAPI RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_T size ) + { + TRACE("(%p,%08x,%08lx): returning NULL\n", + heap, flags, size ); +- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) leave_critical_section( &heapPtr->critSection ); + if (flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY ); + return NULL; + } +@@ -1914,7 +1914,7 @@ PVOID WINAPI RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_T size ) + notify_alloc( pInUse + 1, size, flags & HEAP_ZERO_MEMORY ); + initialize_block( pInUse + 1, size, pInUse->unused_bytes, flags ); + +- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) leave_critical_section( &heapPtr->critSection ); + + TRACE("(%p,%08x,%08lx): returning %p\n", heap, flags, size, pInUse + 1 ); + return pInUse + 1; +@@ -1954,7 +1954,7 @@ BOOLEAN WINAPI RtlFreeHeap( HANDLE heap, ULONG flags, PVOID ptr ) + + flags &= HEAP_NO_SERIALIZE; + flags |= heapPtr->flags; +- if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) enter_critical_section( &heapPtr->critSection ); + + /* Inform valgrind we are trying to free memory, so it can throw up an error message */ + notify_free( ptr ); +@@ -1968,12 +1968,12 @@ BOOLEAN WINAPI RtlFreeHeap( HANDLE heap, ULONG flags, PVOID ptr ) + else + HEAP_MakeInUseBlockFree( subheap, pInUse ); + +- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) leave_critical_section( &heapPtr->critSection ); + TRACE("(%p,%08x,%p): returning TRUE\n", heap, flags, ptr ); + return TRUE; + + error: +- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) leave_critical_section( &heapPtr->critSection ); + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER ); + TRACE("(%p,%08x,%p): returning FALSE\n", heap, flags, ptr ); + return FALSE; +@@ -2015,7 +2015,7 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, SIZE_T size + flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY | + HEAP_REALLOC_IN_PLACE_ONLY; + flags |= heapPtr->flags; +- if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) enter_critical_section( &heapPtr->critSection ); + + rounded_size = ROUND_SIZE(size) + HEAP_TAIL_EXTRA_SIZE(flags); + if (rounded_size < size) goto oom; /* overflow */ +@@ -2109,19 +2109,19 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, SIZE_T size + + ret = pArena + 1; + done: +- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) leave_critical_section( &heapPtr->critSection ); + TRACE("(%p,%08x,%p,%08lx): returning %p\n", heap, flags, ptr, size, ret ); + return ret; + + oom: +- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) leave_critical_section( &heapPtr->critSection ); + if (flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY ); + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_NO_MEMORY ); + TRACE("(%p,%08x,%p,%08lx): returning NULL\n", heap, flags, ptr, size ); + return NULL; + + error: +- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) leave_critical_section( &heapPtr->critSection ); + RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER ); + TRACE("(%p,%08x,%p,%08lx): returning NULL\n", heap, flags, ptr, size ); + return NULL; +@@ -2167,7 +2167,7 @@ BOOLEAN WINAPI RtlLockHeap( HANDLE heap ) + { + HEAP *heapPtr = HEAP_GetPtr( heap ); + if (!heapPtr) return FALSE; +- RtlEnterCriticalSection( &heapPtr->critSection ); ++ enter_critical_section( &heapPtr->critSection ); + return TRUE; + } + +@@ -2188,7 +2188,7 @@ BOOLEAN WINAPI RtlUnlockHeap( HANDLE heap ) + { + HEAP *heapPtr = HEAP_GetPtr( heap ); + if (!heapPtr) return FALSE; +- RtlLeaveCriticalSection( &heapPtr->critSection ); ++ leave_critical_section( &heapPtr->critSection ); + return TRUE; + } + +@@ -2224,7 +2224,7 @@ SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr ) + } + flags &= HEAP_NO_SERIALIZE; + flags |= heapPtr->flags; +- if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) enter_critical_section( &heapPtr->critSection ); + + pArena = (const ARENA_INUSE *)ptr - 1; + if (!validate_block_pointer( heapPtr, &subheap, pArena )) +@@ -2241,7 +2241,7 @@ SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr ) + { + ret = (pArena->size & ARENA_SIZE_MASK) - pArena->unused_bytes; + } +- if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); ++ if (!(flags & HEAP_NO_SERIALIZE)) leave_critical_section( &heapPtr->critSection ); + + TRACE("(%p,%08x,%p): returning %08lx\n", heap, flags, ptr, ret ); + return ret; +@@ -2288,7 +2288,7 @@ NTSTATUS WINAPI RtlWalkHeap( HANDLE heap, PVOID entry_ptr ) + + if (!heapPtr || !entry) return STATUS_INVALID_PARAMETER; + +- if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection ); ++ if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) enter_critical_section( &heapPtr->critSection ); + + /* FIXME: enumerate large blocks too */ + +@@ -2393,7 +2393,7 @@ NTSTATUS WINAPI RtlWalkHeap( HANDLE heap, PVOID entry_ptr ) + if (TRACE_ON(heap)) HEAP_DumpEntry(entry); + + HW_end: +- if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); ++ if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) leave_critical_section( &heapPtr->critSection ); + return ret; + } + +@@ -2416,7 +2416,7 @@ ULONG WINAPI RtlGetProcessHeaps( ULONG count, HANDLE *heaps ) + ULONG total = 1; /* main heap */ + struct list *ptr; + +- RtlEnterCriticalSection( &processHeap->critSection ); ++ enter_critical_section( &processHeap->critSection ); + LIST_FOR_EACH( ptr, &processHeap->entry ) total++; + if (total <= count) + { +@@ -2424,7 +2424,7 @@ ULONG WINAPI RtlGetProcessHeaps( ULONG count, HANDLE *heaps ) + LIST_FOR_EACH( ptr, &processHeap->entry ) + *heaps++ = LIST_ENTRY( ptr, HEAP, entry ); + } +- RtlLeaveCriticalSection( &processHeap->critSection ); ++ leave_critical_section( &processHeap->critSection ); + return total; + } + +-- +2.13.1 + diff --git a/patches/ntdll-CriticalSection/0004-ntdll-Use-fast-CS-functions-for-threadpool-locking.patch b/patches/ntdll-CriticalSection/0004-ntdll-Use-fast-CS-functions-for-threadpool-locking.patch new file mode 100644 index 00000000..388231c3 --- /dev/null +++ b/patches/ntdll-CriticalSection/0004-ntdll-Use-fast-CS-functions-for-threadpool-locking.patch @@ -0,0 +1,417 @@ +From fac19f4dd587a1b8b23c87fe5ad11339d3cd3851 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sat, 5 Aug 2017 03:39:37 +0200 +Subject: ntdll: Use fast CS functions for threadpool locking. + +--- + dlls/ntdll/threadpool.c | 96 ++++++++++++++++++++++++------------------------- + 1 file changed, 48 insertions(+), 48 deletions(-) + +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index b723e6f66f8..f9dc6a5a441 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -1191,7 +1191,7 @@ static void CALLBACK timerqueue_thread_proc( void *param ) + + TRACE( "starting timer queue thread\n" ); + +- RtlEnterCriticalSection( &timerqueue.cs ); ++ enter_critical_section( &timerqueue.cs ); + for (;;) + { + NtQuerySystemTime( &now ); +@@ -1265,7 +1265,7 @@ static void CALLBACK timerqueue_thread_proc( void *param ) + } + + timerqueue.thread_running = FALSE; +- RtlLeaveCriticalSection( &timerqueue.cs ); ++ leave_critical_section( &timerqueue.cs ); + + TRACE( "terminating timer queue thread\n" ); + RtlExitUserThread( 0 ); +@@ -1311,7 +1311,7 @@ static NTSTATUS tp_timerqueue_lock( struct threadpool_object *timer ) + timer->u.timer.period = 0; + timer->u.timer.window_length = 0; + +- RtlEnterCriticalSection( &timerqueue.cs ); ++ enter_critical_section( &timerqueue.cs ); + + /* Make sure that the timerqueue thread is running. */ + if (!timerqueue.thread_running) +@@ -1332,7 +1332,7 @@ static NTSTATUS tp_timerqueue_lock( struct threadpool_object *timer ) + timerqueue.objcount++; + } + +- RtlLeaveCriticalSection( &timerqueue.cs ); ++ leave_critical_section( &timerqueue.cs ); + return status; + } + +@@ -1345,7 +1345,7 @@ static void tp_timerqueue_unlock( struct threadpool_object *timer ) + { + assert( timer->type == TP_OBJECT_TYPE_TIMER ); + +- RtlEnterCriticalSection( &timerqueue.cs ); ++ enter_critical_section( &timerqueue.cs ); + if (timer->u.timer.timer_initialized) + { + /* If timer was pending, remove it. */ +@@ -1364,7 +1364,7 @@ static void tp_timerqueue_unlock( struct threadpool_object *timer ) + + timer->u.timer.timer_initialized = FALSE; + } +- RtlLeaveCriticalSection( &timerqueue.cs ); ++ leave_critical_section( &timerqueue.cs ); + } + + /*********************************************************************** +@@ -1382,7 +1382,7 @@ static void CALLBACK waitqueue_thread_proc( void *param ) + + TRACE( "starting wait queue thread\n" ); + +- RtlEnterCriticalSection( &waitqueue.cs ); ++ enter_critical_section( &waitqueue.cs ); + + for (;;) + { +@@ -1419,10 +1419,10 @@ static void CALLBACK waitqueue_thread_proc( void *param ) + /* All wait objects have been destroyed, if no new wait objects are created + * within some amount of time, then we can shutdown this thread. */ + assert( num_handles == 0 ); +- RtlLeaveCriticalSection( &waitqueue.cs ); ++ leave_critical_section( &waitqueue.cs ); + timeout.QuadPart = (ULONGLONG)THREADPOOL_WORKER_TIMEOUT * -10000; + status = NtWaitForMultipleObjects( 1, &bucket->update_event, TRUE, FALSE, &timeout ); +- RtlEnterCriticalSection( &waitqueue.cs ); ++ enter_critical_section( &waitqueue.cs ); + + if (status == STATUS_TIMEOUT && !bucket->objcount) + break; +@@ -1430,9 +1430,9 @@ static void CALLBACK waitqueue_thread_proc( void *param ) + else + { + handles[num_handles] = bucket->update_event; +- RtlLeaveCriticalSection( &waitqueue.cs ); ++ leave_critical_section( &waitqueue.cs ); + status = NtWaitForMultipleObjects( num_handles + 1, handles, TRUE, FALSE, &timeout ); +- RtlEnterCriticalSection( &waitqueue.cs ); ++ enter_critical_section( &waitqueue.cs ); + + if (status >= STATUS_WAIT_0 && status < STATUS_WAIT_0 + num_handles) + { +@@ -1505,7 +1505,7 @@ static void CALLBACK waitqueue_thread_proc( void *param ) + if (!--waitqueue.num_buckets) + assert( list_empty( &waitqueue.buckets ) ); + +- RtlLeaveCriticalSection( &waitqueue.cs ); ++ leave_critical_section( &waitqueue.cs ); + + TRACE( "terminating wait queue thread\n" ); + +@@ -1534,7 +1534,7 @@ static NTSTATUS tp_waitqueue_lock( struct threadpool_object *wait ) + wait->u.wait.timeout = 0; + wait->u.wait.handle = INVALID_HANDLE_VALUE; + +- RtlEnterCriticalSection( &waitqueue.cs ); ++ enter_critical_section( &waitqueue.cs ); + + /* Try to assign to existing bucket if possible. */ + LIST_FOR_EACH_ENTRY( bucket, &waitqueue.buckets, struct waitqueue_bucket, bucket_entry ) +@@ -1590,7 +1590,7 @@ static NTSTATUS tp_waitqueue_lock( struct threadpool_object *wait ) + } + + out: +- RtlLeaveCriticalSection( &waitqueue.cs ); ++ leave_critical_section( &waitqueue.cs ); + return status; + } + +@@ -1601,7 +1601,7 @@ static void tp_waitqueue_unlock( struct threadpool_object *wait ) + { + assert( wait->type == TP_OBJECT_TYPE_WAIT ); + +- RtlEnterCriticalSection( &waitqueue.cs ); ++ enter_critical_section( &waitqueue.cs ); + if (wait->u.wait.bucket) + { + struct waitqueue_bucket *bucket = wait->u.wait.bucket; +@@ -1613,7 +1613,7 @@ static void tp_waitqueue_unlock( struct threadpool_object *wait ) + + NtSetEvent( bucket->update_event, NULL ); + } +- RtlLeaveCriticalSection( &waitqueue.cs ); ++ leave_critical_section( &waitqueue.cs ); + } + + /*********************************************************************** +@@ -1721,7 +1721,7 @@ static NTSTATUS tp_threadpool_lock( struct threadpool **out, TP_CALLBACK_ENVIRON + pool = default_threadpool; + } + +- RtlEnterCriticalSection( &pool->cs ); ++ enter_critical_section( &pool->cs ); + + /* Make sure that the threadpool has at least one thread. */ + if (!pool->num_workers) +@@ -1735,7 +1735,7 @@ static NTSTATUS tp_threadpool_lock( struct threadpool **out, TP_CALLBACK_ENVIRON + pool->objcount++; + } + +- RtlLeaveCriticalSection( &pool->cs ); ++ leave_critical_section( &pool->cs ); + + if (status != STATUS_SUCCESS) + return status; +@@ -1751,9 +1751,9 @@ static NTSTATUS tp_threadpool_lock( struct threadpool **out, TP_CALLBACK_ENVIRON + */ + static void tp_threadpool_unlock( struct threadpool *pool ) + { +- RtlEnterCriticalSection( &pool->cs ); ++ enter_critical_section( &pool->cs ); + pool->objcount--; +- RtlLeaveCriticalSection( &pool->cs ); ++ leave_critical_section( &pool->cs ); + tp_threadpool_release( pool ); + } + +@@ -1882,10 +1882,10 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa + struct threadpool_group *group = object->group; + interlocked_inc( &group->refcount ); + +- RtlEnterCriticalSection( &group->cs ); ++ enter_critical_section( &group->cs ); + list_add_tail( &group->members, &object->group_entry ); + object->is_group_member = TRUE; +- RtlLeaveCriticalSection( &group->cs ); ++ leave_critical_section( &group->cs ); + } + + if (is_simple_callback) +@@ -1906,7 +1906,7 @@ static void tp_object_submit( struct threadpool_object *object, BOOL signaled ) + assert( !object->shutdown ); + assert( !pool->shutdown ); + +- RtlEnterCriticalSection( &pool->cs ); ++ enter_critical_section( &pool->cs ); + + /* Start new worker threads if required. */ + if (pool->num_busy_workers >= pool->num_workers && +@@ -1929,7 +1929,7 @@ static void tp_object_submit( struct threadpool_object *object, BOOL signaled ) + RtlWakeConditionVariable( &pool->update_event ); + } + +- RtlLeaveCriticalSection( &pool->cs ); ++ leave_critical_section( &pool->cs ); + } + + /*********************************************************************** +@@ -1942,7 +1942,7 @@ static void tp_object_cancel( struct threadpool_object *object ) + struct threadpool *pool = object->pool; + LONG pending_callbacks = 0; + +- RtlEnterCriticalSection( &pool->cs ); ++ enter_critical_section( &pool->cs ); + if (object->num_pending_callbacks) + { + pending_callbacks = object->num_pending_callbacks; +@@ -1952,7 +1952,7 @@ static void tp_object_cancel( struct threadpool_object *object ) + if (object->type == TP_OBJECT_TYPE_WAIT) + object->u.wait.signaled = 0; + } +- RtlLeaveCriticalSection( &pool->cs ); ++ leave_critical_section( &pool->cs ); + + while (pending_callbacks--) + tp_object_release( object ); +@@ -1968,7 +1968,7 @@ static void tp_object_wait( struct threadpool_object *object, BOOL group_wait ) + { + struct threadpool *pool = object->pool; + +- RtlEnterCriticalSection( &pool->cs ); ++ enter_critical_section( &pool->cs ); + if (group_wait) + { + while (object->num_pending_callbacks || object->num_running_callbacks) +@@ -1979,7 +1979,7 @@ static void tp_object_wait( struct threadpool_object *object, BOOL group_wait ) + while (object->num_pending_callbacks || object->num_associated_callbacks) + RtlSleepConditionVariableCS( &object->finished_event, &pool->cs, NULL ); + } +- RtlLeaveCriticalSection( &pool->cs ); ++ leave_critical_section( &pool->cs ); + } + + /*********************************************************************** +@@ -2017,13 +2017,13 @@ static BOOL tp_object_release( struct threadpool_object *object ) + { + struct threadpool_group *group = object->group; + +- RtlEnterCriticalSection( &group->cs ); ++ enter_critical_section( &group->cs ); + if (object->is_group_member) + { + list_remove( &object->group_entry ); + object->is_group_member = FALSE; + } +- RtlLeaveCriticalSection( &group->cs ); ++ leave_critical_section( &group->cs ); + + tp_group_release( group ); + } +@@ -2052,7 +2052,7 @@ static void CALLBACK threadpool_worker_proc( void *param ) + + TRACE( "starting worker thread for pool %p\n", pool ); + +- RtlEnterCriticalSection( &pool->cs ); ++ enter_critical_section( &pool->cs ); + pool->num_busy_workers--; + for (;;) + { +@@ -2078,7 +2078,7 @@ static void CALLBACK threadpool_worker_proc( void *param ) + object->num_associated_callbacks++; + object->num_running_callbacks++; + pool->num_busy_workers++; +- RtlLeaveCriticalSection( &pool->cs ); ++ leave_critical_section( &pool->cs ); + + /* Initialize threadpool instance struct. */ + callback_instance = (TP_CALLBACK_INSTANCE *)&instance; +@@ -2171,7 +2171,7 @@ static void CALLBACK threadpool_worker_proc( void *param ) + } + + skip_cleanup: +- RtlEnterCriticalSection( &pool->cs ); ++ enter_critical_section( &pool->cs ); + pool->num_busy_workers--; + + /* Simple callbacks are automatically shutdown after execution. */ +@@ -2213,7 +2213,7 @@ static void CALLBACK threadpool_worker_proc( void *param ) + } + } + pool->num_workers--; +- RtlLeaveCriticalSection( &pool->cs ); ++ leave_critical_section( &pool->cs ); + + TRACE( "terminating worker thread for pool %p\n", pool ); + tp_threadpool_release( pool ); +@@ -2389,7 +2389,7 @@ NTSTATUS WINAPI TpCallbackMayRunLong( TP_CALLBACK_INSTANCE *instance ) + return STATUS_SUCCESS; + + pool = object->pool; +- RtlEnterCriticalSection( &pool->cs ); ++ enter_critical_section( &pool->cs ); + + /* Start new worker threads if required. */ + if (pool->num_busy_workers >= pool->num_workers) +@@ -2404,7 +2404,7 @@ NTSTATUS WINAPI TpCallbackMayRunLong( TP_CALLBACK_INSTANCE *instance ) + } + } + +- RtlLeaveCriticalSection( &pool->cs ); ++ leave_critical_section( &pool->cs ); + this->may_run_long = TRUE; + return status; + } +@@ -2485,13 +2485,13 @@ VOID WINAPI TpDisassociateCallback( TP_CALLBACK_INSTANCE *instance ) + return; + + pool = object->pool; +- RtlEnterCriticalSection( &pool->cs ); ++ enter_critical_section( &pool->cs ); + + object->num_associated_callbacks--; + if (!object->num_pending_callbacks && !object->num_associated_callbacks) + RtlWakeAllConditionVariable( &object->finished_event ); + +- RtlLeaveCriticalSection( &pool->cs ); ++ leave_critical_section( &pool->cs ); + this->associated = FALSE; + } + +@@ -2543,7 +2543,7 @@ VOID WINAPI TpReleaseCleanupGroupMembers( TP_CLEANUP_GROUP *group, BOOL cancel_p + + TRACE( "%p %u %p\n", group, cancel_pending, userdata ); + +- RtlEnterCriticalSection( &this->cs ); ++ enter_critical_section( &this->cs ); + + /* Unset group, increase references, and mark objects for shutdown */ + LIST_FOR_EACH_ENTRY_SAFE( object, next, &this->members, struct threadpool_object, group_entry ) +@@ -2569,7 +2569,7 @@ VOID WINAPI TpReleaseCleanupGroupMembers( TP_CLEANUP_GROUP *group, BOOL cancel_p + list_init( &members ); + list_move_tail( &members, &this->members ); + +- RtlLeaveCriticalSection( &this->cs ); ++ leave_critical_section( &this->cs ); + + /* Cancel pending callbacks if requested */ + if (cancel_pending) +@@ -2669,10 +2669,10 @@ VOID WINAPI TpSetPoolMaxThreads( TP_POOL *pool, DWORD maximum ) + + TRACE( "%p %u\n", pool, maximum ); + +- RtlEnterCriticalSection( &this->cs ); ++ enter_critical_section( &this->cs ); + this->max_workers = max( maximum, 1 ); + this->min_workers = min( this->min_workers, this->max_workers ); +- RtlLeaveCriticalSection( &this->cs ); ++ leave_critical_section( &this->cs ); + } + + /*********************************************************************** +@@ -2685,7 +2685,7 @@ BOOL WINAPI TpSetPoolMinThreads( TP_POOL *pool, DWORD minimum ) + + TRACE( "%p %u\n", pool, minimum ); + +- RtlEnterCriticalSection( &this->cs ); ++ enter_critical_section( &this->cs ); + + while (this->num_workers < minimum) + { +@@ -2700,7 +2700,7 @@ BOOL WINAPI TpSetPoolMinThreads( TP_POOL *pool, DWORD minimum ) + this->max_workers = max( this->min_workers, this->max_workers ); + } + +- RtlLeaveCriticalSection( &this->cs ); ++ leave_critical_section( &this->cs ); + return !status; + } + +@@ -2716,7 +2716,7 @@ VOID WINAPI TpSetTimer( TP_TIMER *timer, LARGE_INTEGER *timeout, LONG period, LO + + TRACE( "%p %p %u %u\n", timer, timeout, period, window_length ); + +- RtlEnterCriticalSection( &timerqueue.cs ); ++ enter_critical_section( &timerqueue.cs ); + + assert( this->u.timer.timer_initialized ); + this->u.timer.timer_set = timeout != NULL; +@@ -2776,7 +2776,7 @@ VOID WINAPI TpSetTimer( TP_TIMER *timer, LARGE_INTEGER *timeout, LONG period, LO + this->u.timer.timer_pending = TRUE; + } + +- RtlLeaveCriticalSection( &timerqueue.cs ); ++ leave_critical_section( &timerqueue.cs ); + + if (submit_timer) + tp_object_submit( this, FALSE ); +@@ -2793,7 +2793,7 @@ VOID WINAPI TpSetWait( TP_WAIT *wait, HANDLE handle, LARGE_INTEGER *timeout ) + + TRACE( "%p %p %p\n", wait, handle, timeout ); + +- RtlEnterCriticalSection( &waitqueue.cs ); ++ enter_critical_section( &waitqueue.cs ); + + assert( this->u.wait.bucket ); + this->u.wait.handle = handle; +@@ -2837,7 +2837,7 @@ VOID WINAPI TpSetWait( TP_WAIT *wait, HANDLE handle, LARGE_INTEGER *timeout ) + NtSetEvent( bucket->update_event, NULL ); + } + +- RtlLeaveCriticalSection( &waitqueue.cs ); ++ leave_critical_section( &waitqueue.cs ); + + if (submit_wait) + tp_object_submit( this, FALSE ); +-- +2.13.1 + diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index e068a618..e3c7d3e4 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -234,6 +234,7 @@ patch_enable_all () enable_ntdll_Attach_Process_DLLs="$1" enable_ntdll_Builtin_Prot="$1" enable_ntdll_CLI_Images="$1" + enable_ntdll_CriticalSection="$1" enable_ntdll_DOS_Attributes="$1" enable_ntdll_Dealloc_Thread_Stack="$1" enable_ntdll_DeviceType_Systemroot="$1" @@ -971,6 +972,9 @@ patch_enable () ntdll-CLI_Images) enable_ntdll_CLI_Images="$2" ;; + ntdll-CriticalSection) + enable_ntdll_CriticalSection="$2" + ;; ntdll-DOS_Attributes) enable_ntdll_DOS_Attributes="$2" ;; @@ -5963,6 +5967,24 @@ if test "$enable_ntdll_CLI_Images" -eq 1; then ) >> "$patchlist" fi +# Patchset ntdll-CriticalSection +# | +# | Modified files: +# | * dlls/ntdll/critsection.c, dlls/ntdll/heap.c, dlls/ntdll/ntdll_misc.h, dlls/ntdll/threadpool.c, include/wine/port.h +# | +if test "$enable_ntdll_CriticalSection" -eq 1; then + patch_apply ntdll-CriticalSection/0001-include-Move-interlocked_inc-dec-to-port.h.patch + patch_apply ntdll-CriticalSection/0002-ntdll-Add-inline-versions-of-RtlEnterCriticalSection.patch + patch_apply ntdll-CriticalSection/0003-ntdll-Use-fast-CS-functions-for-heap-locking.patch + patch_apply ntdll-CriticalSection/0004-ntdll-Use-fast-CS-functions-for-threadpool-locking.patch + ( + printf '%s\n' '+ { "Sebastian Lackner", "include: Move interlocked_inc/dec to port.h.", 1 },'; + printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Add inline versions of RtlEnterCriticalSection / RtlLeaveCriticalSections.", 1 },'; + printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Use fast CS functions for heap locking.", 1 },'; + printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Use fast CS functions for threadpool locking.", 1 },'; + ) >> "$patchlist" +fi + # Patchset ntdll-DOS_Attributes # | # | This patchset fixes the following Wine bugs: