diff --git a/patches/ntdll-Vista_Threadpool/0007-ntdll-Make-sure-that-threadpools-have-always-at-leas.patch b/patches/ntdll-Vista_Threadpool/0007-ntdll-Make-sure-that-threadpools-have-always-at-leas.patch new file mode 100644 index 00000000..3b9ca6bc --- /dev/null +++ b/patches/ntdll-Vista_Threadpool/0007-ntdll-Make-sure-that-threadpools-have-always-at-leas.patch @@ -0,0 +1,143 @@ +From 1cd9f0a44db192fb1add9989d040c96fd4f537a3 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 2 Feb 2015 13:26:06 +0100 +Subject: ntdll: Make sure that threadpools have always at least one worker + thread. + +Since various functions are declared as VOID on Windows, we always have +to make sure that tasks can be processed. We do that by spawning the first +worker immediately when the threadpool is created. +--- + dlls/ntdll/threadpool2.c | 45 ++++++++++++++++++++++++++++----------------- + 1 file changed, 28 insertions(+), 17 deletions(-) + +diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c +index 76aee5a..7829212 100644 +--- a/dlls/ntdll/threadpool2.c ++++ b/dlls/ntdll/threadpool2.c +@@ -233,7 +233,7 @@ static NTSTATUS tp_threadpool_alloc( struct threadpool **out ); + static BOOL tp_threadpool_release( struct threadpool *pool ); + static void tp_threadpool_shutdown( struct threadpool *pool ); + +-static NTSTATUS tp_object_submit( struct threadpool_object *object ); ++static void tp_object_submit( struct threadpool_object *object ); + static BOOL tp_object_release( struct threadpool_object *object ); + static void tp_object_shutdown( struct threadpool_object *object ); + +@@ -598,12 +598,14 @@ static struct threadpool *get_default_threadpool( void ) + static NTSTATUS tp_threadpool_alloc( struct threadpool **out ) + { + struct threadpool *pool; ++ NTSTATUS status; ++ HANDLE thread; + + pool = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*pool) ); + if (!pool) + return STATUS_NO_MEMORY; + +- pool->refcount = 1; ++ pool->refcount = 2; /* this thread + worker proc */ + pool->shutdown = FALSE; + + RtlInitializeCriticalSection( &pool->cs ); +@@ -615,9 +617,20 @@ static NTSTATUS tp_threadpool_alloc( struct threadpool **out ) + pool->max_workers = 500; + pool->min_workers = 1; + +- pool->num_workers = 0; ++ pool->num_workers = 1; + pool->num_busy_workers = 0; + ++ status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, NULL, 0, 0, ++ threadpool_worker_proc, pool, &thread, NULL ); ++ if (status != STATUS_SUCCESS) ++ { ++ pool->cs.DebugInfo->Spare[0] = 0; ++ RtlDeleteCriticalSection( &pool->cs ); ++ RtlFreeHeap( GetProcessHeap(), 0, pool ); ++ return status; ++ } ++ NtClose( thread ); ++ + TRACE("allocated threadpool %p\n", pool); + + *out = pool; +@@ -745,10 +758,10 @@ static void CALLBACK threadpool_worker_proc( void *param ) + if (pool->shutdown) + break; + +- /* Wait for new tasks or until timeout expires. */ ++ /* Wait for new tasks or until timeout expires. Never terminate the last worker. */ + timeout.QuadPart = (ULONGLONG)THREADPOOL_WORKER_TIMEOUT * -10000; + if (RtlSleepConditionVariableCS( &pool->update_event, &pool->cs, +- &timeout ) == STATUS_TIMEOUT && !list_head( &pool->pool )) ++ &timeout ) == STATUS_TIMEOUT && !list_head( &pool->pool ) && pool->num_workers > 1) + { + break; + } +@@ -1005,10 +1018,9 @@ static void tp_object_wait( struct threadpool_object *object ) + RtlLeaveCriticalSection( &pool->cs ); + } + +-static NTSTATUS tp_object_submit( struct threadpool_object *object ) ++static void tp_object_submit( struct threadpool_object *object ) + { + struct threadpool *pool = object->pool; +- NTSTATUS status = STATUS_SUCCESS; + + assert( !object->shutdown ); + assert( !pool->shutdown ); +@@ -1018,7 +1030,9 @@ static NTSTATUS tp_object_submit( struct threadpool_object *object ) + /* Start new worker threads if required (and allowed) */ + if (pool->num_busy_workers >= pool->num_workers && pool->num_workers < pool->max_workers) + { ++ NTSTATUS status; + HANDLE thread; ++ + status = RtlCreateUserThread( GetCurrentProcess(), NULL, FALSE, NULL, 0, 0, + threadpool_worker_proc, pool, &thread, NULL ); + if (status == STATUS_SUCCESS) +@@ -1027,25 +1041,21 @@ static NTSTATUS tp_object_submit( struct threadpool_object *object ) + pool->num_workers++; + NtClose( thread ); + } +- else if (pool->num_workers) ++ else + { ++ assert( pool->num_workers > 0 ); + RtlWakeConditionVariable( &pool->update_event ); +- status = STATUS_SUCCESS; + } + } + else RtlWakeConditionVariable( &pool->update_event ); + + /* Queue work item into pool and increment refcount */ +- if (!status) +- { +- if (!object->num_pending_callbacks++) +- list_add_tail( &pool->pool, &object->pool_entry ); ++ if (!object->num_pending_callbacks++) ++ list_add_tail( &pool->pool, &object->pool_entry ); + +- interlocked_inc(&object->refcount); +- } ++ interlocked_inc( &object->refcount ); + + RtlLeaveCriticalSection( &pool->cs ); +- return status; + } + + /*********************************************************************** +@@ -1410,7 +1420,8 @@ NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata, T + status = tp_object_alloc_simple( &object, callback, userdata, environment ); + if (!status) + { +- status = tp_object_submit( object ); ++ tp_object_submit( object ); ++ + tp_object_shutdown( object ); + tp_object_release( object ); + } +-- +2.2.2 + diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 83ac46e4..7c41da30 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -2235,6 +2235,7 @@ if test "$enable_ntdll_Vista_Threadpool" -eq 1; then patch_apply ntdll-Vista_Threadpool/0004-ntdll-Implement-threadpool-timer-functions.patch patch_apply ntdll-Vista_Threadpool/0005-ntdll-tests-Add-tests-for-Tp-threadpool-functions.patch patch_apply ntdll-Vista_Threadpool/0006-kernel32-Forward-various-threadpool-functions-to-ntd.patch + patch_apply ntdll-Vista_Threadpool/0007-ntdll-Make-sure-that-threadpools-have-always-at-leas.patch ( echo '+ { "Sebastian Lackner", "ntdll: Add threadpool stub functions to specfile.", 1 },'; echo '+ { "Sebastian Lackner", "ntdll: Implement threadpool, cleanup group and callback instance functions.", 1 },'; @@ -2242,6 +2243,7 @@ if test "$enable_ntdll_Vista_Threadpool" -eq 1; then echo '+ { "Sebastian Lackner", "ntdll: Implement threadpool timer functions.", 1 },'; echo '+ { "Sebastian Lackner", "ntdll/tests: Add tests for Tp* threadpool functions.", 1 },'; echo '+ { "Sebastian Lackner", "kernel32: Forward various threadpool functions to ntdll.", 1 },'; + echo '+ { "Sebastian Lackner", "ntdll: Make sure that threadpools have always at least one worker thread.", 1 },'; ) >> "$patchlist" fi