diff --git a/patches/ntdll-Vista_Threadpool/0001-ntdll-Implement-TpSimpleTryPost-and-basic-threadpool.patch b/patches/ntdll-Vista_Threadpool/0001-ntdll-Implement-TpSimpleTryPost-and-basic-threadpool.patch index edeb57cb..dbdee1ec 100644 --- a/patches/ntdll-Vista_Threadpool/0001-ntdll-Implement-TpSimpleTryPost-and-basic-threadpool.patch +++ b/patches/ntdll-Vista_Threadpool/0001-ntdll-Implement-TpSimpleTryPost-and-basic-threadpool.patch @@ -1,33 +1,19 @@ -From 674272bb028c74d513416d2f776c1ecd6b229c7f Mon Sep 17 00:00:00 2001 +From 4693a9204a3131172e0d1be292ecbe70777057de Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Tue, 24 Feb 2015 05:42:07 +0100 Subject: ntdll: Implement TpSimpleTryPost and basic threadpool infrastructure. --- - dlls/ntdll/Makefile.in | 1 + dlls/ntdll/ntdll.spec | 3 + dlls/ntdll/tests/threadpool.c | 3 +- - dlls/ntdll/threadpool2.c | 424 ++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 430 insertions(+), 1 deletion(-) - create mode 100644 dlls/ntdll/threadpool2.c + dlls/ntdll/threadpool.c | 370 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 375 insertions(+), 1 deletion(-) -diff --git a/dlls/ntdll/Makefile.in b/dlls/ntdll/Makefile.in -index ed4bb94..2cecac6 100644 ---- a/dlls/ntdll/Makefile.in -+++ b/dlls/ntdll/Makefile.in -@@ -47,6 +47,7 @@ C_SRCS = \ - tape.c \ - thread.c \ - threadpool.c \ -+ threadpool2.c \ - time.c \ - version.c \ - virtual.c \ diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index 9355d04..aa16021 100644 +index c3307b2..d9aafdd 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec -@@ -967,6 +967,9 @@ +@@ -968,6 +968,9 @@ @ stdcall RtlxOemStringToUnicodeSize(ptr) RtlOemStringToUnicodeSize @ stdcall RtlxUnicodeStringToAnsiSize(ptr) RtlUnicodeStringToAnsiSize @ stdcall RtlxUnicodeStringToOemSize(ptr) RtlUnicodeStringToOemSize @@ -58,60 +44,36 @@ index 2e31b34..6f164e9 100644 ok(status == STATUS_INVALID_PARAMETER || broken(!status) /* Vista/2008 */, "TpSimpleTryPost unexpectedly returned status %x\n", status); if (!status) -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -new file mode 100644 -index 0000000..e912729 ---- /dev/null -+++ b/dlls/ntdll/threadpool2.c -@@ -0,0 +1,424 @@ +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index 513c13d..df92ef2 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -2,6 +2,7 @@ + * Thread pooling + * + * Copyright (c) 2006 Robert Shearman ++ * Copyright (c) 2014-2015 Sebastian Lackner + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -37,6 +38,10 @@ + + WINE_DEFAULT_DEBUG_CHANNEL(threadpool); + +/* -+ * Object-oriented thread pool API -+ * -+ * Copyright 2014-2015 Sebastian Lackner -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++ * Old thread pooling API + */ + -+#include "config.h" -+#include "wine/port.h" -+ -+#include -+#include -+#include -+ -+#define NONAMELESSUNION -+#include "ntstatus.h" -+#define WIN32_NO_STATUS -+#include "winternl.h" -+ -+#include "wine/debug.h" -+#include "wine/list.h" -+ -+#include "ntdll_misc.h" -+ -+WINE_DEFAULT_DEBUG_CHANNEL(threadpool); -+ -+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; -+} + #define OLD_WORKER_TIMEOUT 30000 /* 30 seconds */ + #define EXPIRE_NEVER (~(ULONGLONG)0) + #define TIMER_QUEUE_MAGIC 0x516d6954 /* TimQ */ +@@ -127,6 +132,64 @@ struct timer_queue + HANDLE thread; + }; + ++/* ++ * New object-oriented thread pooling API ++ */ + +#define THREADPOOL_WORKER_TIMEOUT 5000 + @@ -165,33 +127,15 @@ index 0000000..e912729 +} + +static void CALLBACK threadpool_worker_proc( void *param ); -+static NTSTATUS tp_threadpool_alloc( struct threadpool **out ); -+static void tp_threadpool_shutdown( struct threadpool *pool ); -+static BOOL tp_threadpool_release( struct threadpool *pool ); -+static void tp_object_submit( struct threadpool_object *object ); -+static void tp_object_shutdown( struct threadpool_object *object ); -+static BOOL tp_object_release( struct threadpool_object *object ); -+ +static struct threadpool *default_threadpool = NULL; + -+/* allocates or returns the default threadpool */ -+static struct threadpool *get_default_threadpool( void ) -+{ -+ if (!default_threadpool) -+ { -+ struct threadpool *pool; -+ -+ if (tp_threadpool_alloc( &pool ) != STATUS_SUCCESS) -+ return NULL; -+ -+ if (interlocked_cmpxchg_ptr( (void *)&default_threadpool, pool, NULL ) != NULL) -+ { -+ tp_threadpool_shutdown( pool ); -+ tp_threadpool_release( pool ); -+ } -+ } -+ return default_threadpool; -+} + static inline LONG interlocked_inc( PLONG dest ) + { + return interlocked_xchg_add( dest, 1 ) + 1; +@@ -1044,3 +1107,310 @@ NTSTATUS WINAPI RtlDeleteTimer(HANDLE TimerQueue, HANDLE Timer, + + return status; + } + +/* allocate a new threadpool (with at least one worker thread) */ +static NTSTATUS tp_threadpool_alloc( struct threadpool **out ) @@ -262,69 +206,23 @@ index 0000000..e912729 + return TRUE; +} + -+/* threadpool worker function */ -+static void CALLBACK threadpool_worker_proc( void *param ) ++/* allocates or returns the default threadpool */ ++static struct threadpool *get_default_threadpool( void ) +{ -+ struct threadpool *pool = param; -+ LARGE_INTEGER timeout; -+ struct list *ptr; -+ -+ RtlEnterCriticalSection( &pool->cs ); -+ for (;;) ++ if (!default_threadpool) + { -+ while ((ptr = list_head( &pool->pool ))) ++ struct threadpool *pool; ++ ++ if (tp_threadpool_alloc( &pool ) != STATUS_SUCCESS) ++ return NULL; ++ ++ if (interlocked_cmpxchg_ptr( (void *)&default_threadpool, pool, NULL ) != NULL) + { -+ struct threadpool_object *object = LIST_ENTRY( ptr, struct threadpool_object, pool_entry ); -+ assert( object->num_pending_callbacks > 0 ); -+ -+ /* If further pending callbacks are queued, move the work item to -+ * the end of the pool list. Otherwise remove it from the pool. */ -+ list_remove( &object->pool_entry ); -+ if (--object->num_pending_callbacks) -+ list_add_tail( &pool->pool, &object->pool_entry ); -+ -+ /* Leave critical section and do the actual callback. */ -+ object->num_running_callbacks++; -+ pool->num_busy_workers++; -+ RtlLeaveCriticalSection( &pool->cs ); -+ -+ switch (object->type) -+ { -+ case TP_OBJECT_TYPE_SIMPLE: -+ { -+ TRACE( "executing simple callback %p(NULL, %p)\n", -+ object->u.simple.callback, object->userdata ); -+ object->u.simple.callback( NULL, object->userdata ); -+ TRACE( "callback %p returned\n", object->u.simple.callback ); -+ break; -+ } -+ -+ default: -+ assert(0); -+ break; -+ } -+ -+ RtlEnterCriticalSection( &pool->cs ); -+ pool->num_busy_workers--; -+ object->num_running_callbacks--; -+ tp_object_release( object ); -+ } -+ -+ /* Shutdown worker thread if requested. */ -+ if (pool->shutdown) -+ break; -+ -+ /* 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 ) && pool->num_workers > 1) -+ { -+ break; ++ tp_threadpool_shutdown( pool ); ++ tp_threadpool_release( pool ); + } + } -+ pool->num_workers--; -+ RtlLeaveCriticalSection( &pool->cs ); -+ tp_threadpool_release( pool ); ++ return default_threadpool; +} + +/* initializes a new threadpool object */ @@ -350,38 +248,6 @@ index 0000000..e912729 + TRACE("allocated object %p of type %u\n", object, object->type); +} + -+/* allocates and submits a 'simple' threadpool task. */ -+static NTSTATUS tp_object_submit_simple( PTP_SIMPLE_CALLBACK callback, PVOID userdata, -+ TP_CALLBACK_ENVIRON *environment ) -+{ -+ struct threadpool_object *object; -+ struct threadpool *pool = NULL; -+ -+ if (environment) -+ pool = (struct threadpool *)environment->Pool; -+ -+ if (!pool) -+ { -+ pool = get_default_threadpool(); -+ if (!pool) -+ return STATUS_NO_MEMORY; -+ } -+ -+ object = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*object) ); -+ if (!object) -+ return STATUS_NO_MEMORY; -+ -+ object->type = TP_OBJECT_TYPE_SIMPLE; -+ object->u.simple.callback = callback; -+ tp_object_initialize( object, pool, userdata, environment ); -+ -+ tp_object_submit( object ); -+ -+ tp_object_shutdown( object ); -+ tp_object_release( object ); -+ return STATUS_SUCCESS; -+} -+ +/* submits an object to a threadpool */ +static void tp_object_submit( struct threadpool_object *object ) +{ @@ -446,6 +312,70 @@ index 0000000..e912729 + return TRUE; +} + ++/* threadpool worker function */ ++static void CALLBACK threadpool_worker_proc( void *param ) ++{ ++ struct threadpool *pool = param; ++ LARGE_INTEGER timeout; ++ struct list *ptr; ++ ++ RtlEnterCriticalSection( &pool->cs ); ++ for (;;) ++ { ++ while ((ptr = list_head( &pool->pool ))) ++ { ++ struct threadpool_object *object = LIST_ENTRY( ptr, struct threadpool_object, pool_entry ); ++ assert( object->num_pending_callbacks > 0 ); ++ ++ /* If further pending callbacks are queued, move the work item to ++ * the end of the pool list. Otherwise remove it from the pool. */ ++ list_remove( &object->pool_entry ); ++ if (--object->num_pending_callbacks) ++ list_add_tail( &pool->pool, &object->pool_entry ); ++ ++ /* Leave critical section and do the actual callback. */ ++ object->num_running_callbacks++; ++ pool->num_busy_workers++; ++ RtlLeaveCriticalSection( &pool->cs ); ++ ++ switch (object->type) ++ { ++ case TP_OBJECT_TYPE_SIMPLE: ++ { ++ TRACE( "executing simple callback %p(NULL, %p)\n", ++ object->u.simple.callback, object->userdata ); ++ object->u.simple.callback( NULL, object->userdata ); ++ TRACE( "callback %p returned\n", object->u.simple.callback ); ++ break; ++ } ++ ++ default: ++ assert(0); ++ break; ++ } ++ ++ RtlEnterCriticalSection( &pool->cs ); ++ pool->num_busy_workers--; ++ object->num_running_callbacks--; ++ tp_object_release( object ); ++ } ++ ++ /* Shutdown worker thread if requested. */ ++ if (pool->shutdown) ++ break; ++ ++ /* 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 ) && pool->num_workers > 1) ++ { ++ break; ++ } ++ } ++ pool->num_workers--; ++ RtlLeaveCriticalSection( &pool->cs ); ++ tp_threadpool_release( pool ); ++} + +/*********************************************************************** + * TpAllocPool (NTDLL.@) @@ -484,10 +414,35 @@ index 0000000..e912729 +NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata, + TP_CALLBACK_ENVIRON *environment ) +{ ++ struct threadpool_object *object; ++ struct threadpool *pool = NULL; ++ + TRACE("%p %p %p\n", callback, userdata, environment); + -+ return tp_object_submit_simple( callback, userdata, environment ); ++ if (environment) ++ pool = (struct threadpool *)environment->Pool; ++ ++ if (!pool) ++ { ++ pool = get_default_threadpool(); ++ if (!pool) ++ return STATUS_NO_MEMORY; ++ } ++ ++ object = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*object) ); ++ if (!object) ++ return STATUS_NO_MEMORY; ++ ++ object->type = TP_OBJECT_TYPE_SIMPLE; ++ object->u.simple.callback = callback; ++ tp_object_initialize( object, pool, userdata, environment ); ++ ++ tp_object_submit( object ); ++ ++ tp_object_shutdown( object ); ++ tp_object_release( object ); ++ return STATUS_SUCCESS; +} -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0002-ntdll-Implement-TpSetPool-Min-Max-Threads.patch b/patches/ntdll-Vista_Threadpool/0002-ntdll-Implement-TpSetPool-Min-Max-Threads.patch index 67668a7b..b1ca490e 100644 --- a/patches/ntdll-Vista_Threadpool/0002-ntdll-Implement-TpSetPool-Min-Max-Threads.patch +++ b/patches/ntdll-Vista_Threadpool/0002-ntdll-Implement-TpSetPool-Min-Max-Threads.patch @@ -1,18 +1,18 @@ -From b2f107dc3bbde6a242f2ce0fc4b350728f8135f5 Mon Sep 17 00:00:00 2001 +From 13635df17569be46833f21980ba22f2b4db85102 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 00:16:20 +0100 Subject: ntdll: Implement TpSetPool[Min|Max]Threads. --- - dlls/ntdll/ntdll.spec | 2 ++ - dlls/ntdll/threadpool2.c | 33 +++++++++++++++++++++++++++++++++ + dlls/ntdll/ntdll.spec | 2 ++ + dlls/ntdll/threadpool.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index aa16021..9a7ddeb 100644 +index d9aafdd..88d915b 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec -@@ -969,6 +969,8 @@ +@@ -970,6 +970,8 @@ @ stdcall RtlxUnicodeStringToOemSize(ptr) RtlUnicodeStringToOemSize @ stdcall TpAllocPool(ptr ptr) @ stdcall TpReleasePool(ptr) @@ -21,11 +21,11 @@ index aa16021..9a7ddeb 100644 @ stdcall TpSimpleTryPost(ptr ptr ptr) @ stdcall -ret64 VerSetConditionMask(int64 long long) @ stdcall ZwAcceptConnectPort(ptr long ptr long long ptr) NtAcceptConnectPort -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -index e912729..08bcde0 100644 ---- a/dlls/ntdll/threadpool2.c -+++ b/dlls/ntdll/threadpool2.c -@@ -413,6 +413,39 @@ VOID WINAPI TpReleasePool( TP_POOL *pool ) +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index df92ef2..16d9209 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -1380,6 +1380,39 @@ VOID WINAPI TpReleasePool( TP_POOL *pool ) } /*********************************************************************** @@ -66,5 +66,5 @@ index e912729..08bcde0 100644 */ NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata, -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0003-ntdll-Implement-threadpool-cleanup-group-functions.patch b/patches/ntdll-Vista_Threadpool/0003-ntdll-Implement-threadpool-cleanup-group-functions.patch index 3f54f115..44557e69 100644 --- a/patches/ntdll-Vista_Threadpool/0003-ntdll-Implement-threadpool-cleanup-group-functions.patch +++ b/patches/ntdll-Vista_Threadpool/0003-ntdll-Implement-threadpool-cleanup-group-functions.patch @@ -1,18 +1,18 @@ -From c6e44243dba7ac4a57ccef25e83645fa09855b98 Mon Sep 17 00:00:00 2001 +From 63ebc5c972502aaa60d50b1f6ca54f6a9646fca6 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 00:52:18 +0100 Subject: ntdll: Implement threadpool cleanup group functions. --- - dlls/ntdll/ntdll.spec | 3 + - dlls/ntdll/threadpool2.c | 261 ++++++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 259 insertions(+), 5 deletions(-) + dlls/ntdll/ntdll.spec | 3 + + dlls/ntdll/threadpool.c | 259 +++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 257 insertions(+), 5 deletions(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index 9a7ddeb..6dad2bb 100644 +index 88d915b..853ca09 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec -@@ -967,7 +967,10 @@ +@@ -968,7 +968,10 @@ @ stdcall RtlxOemStringToUnicodeSize(ptr) RtlOemStringToUnicodeSize @ stdcall RtlxUnicodeStringToAnsiSize(ptr) RtlUnicodeStringToAnsiSize @ stdcall RtlxUnicodeStringToOemSize(ptr) RtlUnicodeStringToOemSize @@ -23,11 +23,11 @@ index 9a7ddeb..6dad2bb 100644 @ stdcall TpReleasePool(ptr) @ stdcall TpSetPoolMaxThreads(ptr long) @ stdcall TpSetPoolMinThreads(ptr long) -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -index 08bcde0..30f1e6d 100644 ---- a/dlls/ntdll/threadpool2.c -+++ b/dlls/ntdll/threadpool2.c -@@ -78,9 +78,14 @@ struct threadpool_object +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index 16d9209..092fa6f 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -167,9 +167,14 @@ struct threadpool_object /* read-only information */ enum threadpool_objtype type; struct threadpool *pool; @@ -42,7 +42,7 @@ index 08bcde0..30f1e6d 100644 LONG num_pending_callbacks; LONG num_running_callbacks; /* arguments for callback */ -@@ -93,11 +98,26 @@ struct threadpool_object +@@ -182,12 +187,30 @@ struct threadpool_object } u; }; @@ -67,26 +67,64 @@ index 08bcde0..30f1e6d 100644 +} + static void CALLBACK threadpool_worker_proc( void *param ); - static NTSTATUS tp_threadpool_alloc( struct threadpool **out ); - static void tp_threadpool_shutdown( struct threadpool *pool ); -@@ -105,6 +125,7 @@ static BOOL tp_threadpool_release( struct threadpool *pool ); - static void tp_object_submit( struct threadpool_object *object ); - static void tp_object_shutdown( struct threadpool_object *object ); - static BOOL tp_object_release( struct threadpool_object *object ); -+static BOOL tp_group_release( struct threadpool_group *group ); - ++static void tp_object_submit( struct threadpool_object *object ); ++static void tp_object_shutdown( struct threadpool_object *object ); ++static BOOL tp_object_release( struct threadpool_object *object ); static struct threadpool *default_threadpool = NULL; -@@ -241,6 +262,8 @@ static void CALLBACK threadpool_worker_proc( void *param ) - RtlEnterCriticalSection( &pool->cs ); - pool->num_busy_workers--; - object->num_running_callbacks--; -+ if (!object->num_pending_callbacks && !object->num_running_callbacks) -+ RtlWakeAllConditionVariable( &object->finished_event ); - tp_object_release( object ); - } + static inline LONG interlocked_inc( PLONG dest ) +@@ -1196,27 +1219,111 @@ static struct threadpool *get_default_threadpool( void ) + return default_threadpool; + } -@@ -265,23 +288,60 @@ static void CALLBACK threadpool_worker_proc( void *param ) ++/* allocates a new cleanup group */ ++static NTSTATUS tp_group_alloc( struct threadpool_group **out ) ++{ ++ struct threadpool_group *group; ++ ++ group = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*group) ); ++ if (!group) ++ return STATUS_NO_MEMORY; ++ ++ group->refcount = 1; ++ group->shutdown = FALSE; ++ ++ RtlInitializeCriticalSection( &group->cs ); ++ group->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": threadpool_group.cs"); ++ ++ list_init( &group->members ); ++ ++ TRACE("allocated group %p\n", group); ++ ++ *out = group; ++ return STATUS_SUCCESS; ++} ++ ++/* marks a cleanup group for shutdown */ ++static void tp_group_shutdown( struct threadpool_group *group ) ++{ ++ group->shutdown = TRUE; ++} ++ ++/* releases a reference to a cleanup group */ ++static BOOL tp_group_release( struct threadpool_group *group ) ++{ ++ if (interlocked_dec( &group->refcount )) ++ return FALSE; ++ ++ TRACE("destroying group %p\n", group); ++ ++ assert( group->shutdown ); ++ assert( list_empty( &group->members ) ); ++ ++ group->cs.DebugInfo->Spare[0] = 0; ++ RtlDeleteCriticalSection( &group->cs ); ++ ++ RtlFreeHeap( GetProcessHeap(), 0, group ); ++ return TRUE; ++} ++ + /* initializes a new threadpool object */ static void tp_object_initialize( struct threadpool_object *object, struct threadpool *pool, PVOID userdata, TP_CALLBACK_ENVIRON *environment ) { @@ -147,19 +185,8 @@ index 08bcde0..30f1e6d 100644 + } } - /* allocates and submits a 'simple' threadpool task. */ -@@ -309,10 +369,6 @@ static NTSTATUS tp_object_submit_simple( PTP_SIMPLE_CALLBACK callback, PVOID use - object->u.simple.callback = callback; - tp_object_initialize( object, pool, userdata, environment ); - -- tp_object_submit( object ); -- -- tp_object_shutdown( object ); -- tp_object_release( object ); - return STATUS_SUCCESS; - } - -@@ -355,6 +411,41 @@ out: + /* submits an object to a threadpool */ +@@ -1258,6 +1365,41 @@ out: RtlLeaveCriticalSection( &pool->cs ); } @@ -201,7 +228,7 @@ index 08bcde0..30f1e6d 100644 /* mark an object as 'shutdown', submitting is no longer possible */ static void tp_object_shutdown( struct threadpool_object *object ) { -@@ -373,6 +464,22 @@ static BOOL tp_object_release( struct threadpool_object *object ) +@@ -1276,6 +1418,22 @@ static BOOL tp_object_release( struct threadpool_object *object ) assert( !object->num_pending_callbacks ); assert( !object->num_running_callbacks ); @@ -224,112 +251,19 @@ index 08bcde0..30f1e6d 100644 /* release reference to threadpool */ tp_threadpool_release( object->pool ); -@@ -380,6 +487,121 @@ static BOOL tp_object_release( struct threadpool_object *object ) - return TRUE; +@@ -1328,6 +1486,8 @@ static void CALLBACK threadpool_worker_proc( void *param ) + RtlEnterCriticalSection( &pool->cs ); + pool->num_busy_workers--; + object->num_running_callbacks--; ++ if (!object->num_pending_callbacks && !object->num_running_callbacks) ++ RtlWakeAllConditionVariable( &object->finished_event ); + tp_object_release( object ); + } + +@@ -1348,6 +1508,20 @@ static void CALLBACK threadpool_worker_proc( void *param ) + tp_threadpool_release( pool ); } -+/* allocates a new cleanup group */ -+static NTSTATUS tp_group_alloc( struct threadpool_group **out ) -+{ -+ struct threadpool_group *group; -+ -+ group = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*group) ); -+ if (!group) -+ return STATUS_NO_MEMORY; -+ -+ group->refcount = 1; -+ group->shutdown = FALSE; -+ -+ RtlInitializeCriticalSection( &group->cs ); -+ group->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": threadpool_group.cs"); -+ -+ list_init( &group->members ); -+ -+ TRACE("allocated group %p\n", group); -+ -+ *out = group; -+ return STATUS_SUCCESS; -+} -+ -+/* marks a cleanup group for shutdown */ -+static void tp_group_shutdown( struct threadpool_group *group ) -+{ -+ group->shutdown = TRUE; -+} -+ -+/* releases a reference to a cleanup group */ -+static BOOL tp_group_release( struct threadpool_group *group ) -+{ -+ if (interlocked_dec( &group->refcount )) -+ return FALSE; -+ -+ TRACE("destroying group %p\n", group); -+ -+ assert( group->shutdown ); -+ assert( list_empty( &group->members ) ); -+ -+ group->cs.DebugInfo->Spare[0] = 0; -+ RtlDeleteCriticalSection( &group->cs ); -+ -+ RtlFreeHeap( GetProcessHeap(), 0, group ); -+ return TRUE; -+} -+ -+/* releases all group members of a cleanup group */ -+static void tp_group_release_members( struct threadpool_group *group, BOOL cancel_pending, PVOID userdata ) -+{ -+ struct threadpool_object *object, *next; -+ struct list members; -+ -+ RtlEnterCriticalSection( &group->cs ); -+ -+ /* Unset group, increase references, and mark objects for shutdown */ -+ LIST_FOR_EACH_ENTRY_SAFE( object, next, &group->members, struct threadpool_object, group_entry ) -+ { -+ assert( object->group == group ); -+ assert( object->is_group_member ); -+ -+ /* Simple callbacks are very special. The user doesn't hold any reference, so -+ * they would be released too early. Add one additional temporary reference. */ -+ if (object->type == TP_OBJECT_TYPE_SIMPLE) -+ { -+ if (interlocked_inc( &object->refcount ) == 1) -+ { -+ /* Object is basically already destroyed, but group reference -+ * was not deleted yet. We can safely ignore this object. */ -+ interlocked_dec( &object->refcount ); -+ list_remove( &object->group_entry ); -+ object->is_group_member = FALSE; -+ continue; -+ } -+ } -+ -+ object->is_group_member = FALSE; -+ tp_object_shutdown( object ); -+ } -+ -+ /* Move members to a local list */ -+ list_init( &members ); -+ list_move_tail( &members, &group->members ); -+ -+ RtlLeaveCriticalSection( &group->cs ); -+ -+ /* Cancel pending callbacks if requested */ -+ if (cancel_pending) -+ { -+ LIST_FOR_EACH_ENTRY( object, &members, struct threadpool_object, group_entry ) -+ { -+ tp_object_cancel( object ); -+ } -+ } -+ -+ /* Wait for remaining callbacks to finish */ -+ LIST_FOR_EACH_ENTRY_SAFE( object, next, &members, struct threadpool_object, group_entry ) -+ { -+ tp_object_wait( object ); -+ tp_object_release( object ); -+ } -+} + +/*********************************************************************** + * TpAllocCleanupGroup (NTDLL.@) @@ -343,10 +277,11 @@ index 08bcde0..30f1e6d 100644 + + return tp_group_alloc( (struct threadpool_group **)out ); +} - ++ /*********************************************************************** * TpAllocPool (NTDLL.@) -@@ -398,6 +620,35 @@ NTSTATUS WINAPI TpAllocPool( TP_POOL **out, PVOID reserved ) + */ +@@ -1365,6 +1539,85 @@ NTSTATUS WINAPI TpAllocPool( TP_POOL **out, PVOID reserved ) } /*********************************************************************** @@ -370,11 +305,61 @@ index 08bcde0..30f1e6d 100644 +VOID WINAPI TpReleaseCleanupGroupMembers( TP_CLEANUP_GROUP *group, BOOL cancel_pending, PVOID userdata ) +{ + struct threadpool_group *this = impl_from_TP_CLEANUP_GROUP( group ); ++ struct threadpool_object *object, *next; ++ struct list members; ++ + TRACE("%p %d %p\n", group, cancel_pending, userdata); + -+ if (this) ++ if (!this) ++ return; ++ ++ RtlEnterCriticalSection( &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 ) + { -+ tp_group_release_members( this, cancel_pending, userdata ); ++ assert( object->group == this ); ++ assert( object->is_group_member ); ++ ++ /* Simple callbacks are very special. The user doesn't hold any reference, so ++ * they would be released too early. Add one additional temporary reference. */ ++ if (object->type == TP_OBJECT_TYPE_SIMPLE) ++ { ++ if (interlocked_inc( &object->refcount ) == 1) ++ { ++ /* Object is basically already destroyed, but group reference ++ * was not deleted yet. We can safely ignore this object. */ ++ interlocked_dec( &object->refcount ); ++ list_remove( &object->group_entry ); ++ object->is_group_member = FALSE; ++ continue; ++ } ++ } ++ ++ object->is_group_member = FALSE; ++ tp_object_shutdown( object ); ++ } ++ ++ /* Move members to a local list */ ++ list_init( &members ); ++ list_move_tail( &members, &this->members ); ++ ++ RtlLeaveCriticalSection( &this->cs ); ++ ++ /* Cancel pending callbacks if requested */ ++ if (cancel_pending) ++ { ++ LIST_FOR_EACH_ENTRY( object, &members, struct threadpool_object, group_entry ) ++ { ++ tp_object_cancel( object ); ++ } ++ } ++ ++ /* Wait for remaining callbacks to finish */ ++ LIST_FOR_EACH_ENTRY_SAFE( object, next, &members, struct threadpool_object, group_entry ) ++ { ++ tp_object_wait( object ); ++ tp_object_release( object ); + } +} + @@ -382,6 +367,16 @@ index 08bcde0..30f1e6d 100644 * TpReleasePool (NTDLL.@) */ VOID WINAPI TpReleasePool( TP_POOL *pool ) +@@ -1441,9 +1694,5 @@ NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata, + object->u.simple.callback = callback; + tp_object_initialize( object, pool, userdata, environment ); + +- tp_object_submit( object ); +- +- tp_object_shutdown( object ); +- tp_object_release( object ); + return STATUS_SUCCESS; + } -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0004-ntdll-tests-Add-tests-for-TpAllocCleanupGroup-and-re.patch b/patches/ntdll-Vista_Threadpool/0004-ntdll-tests-Add-tests-for-TpAllocCleanupGroup-and-re.patch index 6f23702f..d5f03f71 100644 --- a/patches/ntdll-Vista_Threadpool/0004-ntdll-tests-Add-tests-for-TpAllocCleanupGroup-and-re.patch +++ b/patches/ntdll-Vista_Threadpool/0004-ntdll-tests-Add-tests-for-TpAllocCleanupGroup-and-re.patch @@ -1,4 +1,4 @@ -From 8517209b838b33e7ff69d70285c4e53d5b5a4258 Mon Sep 17 00:00:00 2001 +From f8532f86e968848db4b8e4f87d3556dfcaa753e8 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 01:19:41 +0100 Subject: ntdll/tests: Add tests for TpAllocCleanupGroup and related functions. @@ -98,5 +98,5 @@ index 6f164e9..effa7fc 100644 CloseHandle(semaphore); } -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0005-ntdll-Implement-threadpool-work-item-functions.patch b/patches/ntdll-Vista_Threadpool/0005-ntdll-Implement-threadpool-work-item-functions.patch index 14deb697..0a7add79 100644 --- a/patches/ntdll-Vista_Threadpool/0005-ntdll-Implement-threadpool-work-item-functions.patch +++ b/patches/ntdll-Vista_Threadpool/0005-ntdll-Implement-threadpool-work-item-functions.patch @@ -1,18 +1,18 @@ -From 5e0c3a3b77b95434e19f273da7dcadc7cd224cea Mon Sep 17 00:00:00 2001 +From d4b4fc976cad98a6e483584da8de8f011f029c20 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 01:30:57 +0100 Subject: ntdll: Implement threadpool work item functions. --- - dlls/ntdll/ntdll.spec | 4 ++ - dlls/ntdll/threadpool2.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 111 insertions(+), 1 deletion(-) + dlls/ntdll/ntdll.spec | 4 ++ + dlls/ntdll/threadpool.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index 6dad2bb..1c768c9 100644 +index 853ca09..96edd67 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec -@@ -969,12 +969,16 @@ +@@ -970,12 +970,16 @@ @ stdcall RtlxUnicodeStringToOemSize(ptr) RtlUnicodeStringToOemSize @ stdcall TpAllocCleanupGroup(ptr) @ stdcall TpAllocPool(ptr ptr) @@ -29,11 +29,11 @@ index 6dad2bb..1c768c9 100644 @ stdcall -ret64 VerSetConditionMask(int64 long long) @ stdcall ZwAcceptConnectPort(ptr long ptr long long ptr) NtAcceptConnectPort @ stdcall ZwAccessCheck(ptr long long ptr ptr ptr ptr ptr) NtAccessCheck -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -index 30f1e6d..31b5e2e 100644 ---- a/dlls/ntdll/threadpool2.c -+++ b/dlls/ntdll/threadpool2.c -@@ -67,7 +67,8 @@ struct threadpool +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index 092fa6f..1989d56 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -156,7 +156,8 @@ struct threadpool enum threadpool_objtype { @@ -43,7 +43,7 @@ index 30f1e6d..31b5e2e 100644 }; /* internal threadpool object representation */ -@@ -95,6 +96,10 @@ struct threadpool_object +@@ -184,6 +185,10 @@ struct threadpool_object { PTP_SIMPLE_CALLBACK callback; } simple; @@ -54,7 +54,7 @@ index 30f1e6d..31b5e2e 100644 } u; }; -@@ -113,6 +118,13 @@ static inline struct threadpool *impl_from_TP_POOL( TP_POOL *pool ) +@@ -202,6 +207,13 @@ static inline struct threadpool *impl_from_TP_POOL( TP_POOL *pool ) return (struct threadpool *)pool; } @@ -68,7 +68,7 @@ index 30f1e6d..31b5e2e 100644 static inline struct threadpool_group *impl_from_TP_CLEANUP_GROUP( TP_CLEANUP_GROUP *group ) { return (struct threadpool_group *)group; -@@ -254,6 +266,15 @@ static void CALLBACK threadpool_worker_proc( void *param ) +@@ -1478,6 +1490,15 @@ static void CALLBACK threadpool_worker_proc( void *param ) break; } @@ -84,16 +84,20 @@ index 30f1e6d..31b5e2e 100644 default: assert(0); break; -@@ -372,6 +393,34 @@ static NTSTATUS tp_object_submit_simple( PTP_SIMPLE_CALLBACK callback, PVOID use - return STATUS_SUCCESS; +@@ -1539,6 +1560,53 @@ NTSTATUS WINAPI TpAllocPool( TP_POOL **out, PVOID reserved ) } -+static NTSTATUS tp_object_alloc_work( struct threadpool_object **out, PTP_WORK_CALLBACK callback, -+ PVOID userdata, TP_CALLBACK_ENVIRON *environment ) + /*********************************************************************** ++ * TpAllocWork (NTDLL.@) ++ */ ++NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID userdata, ++ TP_CALLBACK_ENVIRON *environment ) +{ + struct threadpool_object *object; + struct threadpool *pool = NULL; + ++ TRACE("%p %p %p %p\n", out, callback, userdata, environment); ++ + if (environment) + pool = (struct threadpool *)environment->Pool; + @@ -112,27 +116,9 @@ index 30f1e6d..31b5e2e 100644 + object->u.work.callback = callback; + tp_object_initialize( object, pool, userdata, environment ); + -+ *out = object; ++ *out = (TP_WORK *)object; + return STATUS_SUCCESS; +} -+ - /* submits an object to a threadpool */ - static void tp_object_submit( struct threadpool_object *object ) - { -@@ -620,6 +669,32 @@ NTSTATUS WINAPI TpAllocPool( TP_POOL **out, PVOID reserved ) - } - - /*********************************************************************** -+ * TpAllocWork (NTDLL.@) -+ */ -+NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID userdata, -+ TP_CALLBACK_ENVIRON *environment ) -+{ -+ TRACE("%p %p %p %p\n", out, callback, userdata, environment); -+ -+ return tp_object_alloc_work( (struct threadpool_object **)out, callback, -+ userdata, environment ); -+} + +/*********************************************************************** + * TpPostWork (NTDLL.@) @@ -152,7 +138,7 @@ index 30f1e6d..31b5e2e 100644 * TpReleaseCleanupGroup (NTDLL.@) */ VOID WINAPI TpReleaseCleanupGroup( TP_CLEANUP_GROUP *group ) -@@ -664,6 +739,21 @@ VOID WINAPI TpReleasePool( TP_POOL *pool ) +@@ -1633,6 +1701,21 @@ VOID WINAPI TpReleasePool( TP_POOL *pool ) } /*********************************************************************** @@ -174,9 +160,9 @@ index 30f1e6d..31b5e2e 100644 * TpSetPoolMaxThreads (NTDLL.@) */ VOID WINAPI TpSetPoolMaxThreads( TP_POOL *pool, DWORD maximum ) -@@ -706,3 +796,19 @@ NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata, +@@ -1696,3 +1779,19 @@ NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata, - return tp_object_submit_simple( callback, userdata, environment ); + return STATUS_SUCCESS; } + +/*********************************************************************** @@ -195,5 +181,5 @@ index 30f1e6d..31b5e2e 100644 + } +} -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0006-ntdll-tests-Add-basic-tests-for-threadpool-work-item.patch b/patches/ntdll-Vista_Threadpool/0006-ntdll-tests-Add-basic-tests-for-threadpool-work-item.patch index def5d29f..3db0bae2 100644 --- a/patches/ntdll-Vista_Threadpool/0006-ntdll-tests-Add-basic-tests-for-threadpool-work-item.patch +++ b/patches/ntdll-Vista_Threadpool/0006-ntdll-tests-Add-basic-tests-for-threadpool-work-item.patch @@ -1,4 +1,4 @@ -From 688ef1722a39b3b51797cd179181012b0863cd1e Mon Sep 17 00:00:00 2001 +From a0ad4f0f9186dbce96da918255f2c0cd5f4aae7f Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 01:38:23 +0100 Subject: ntdll/tests: Add basic tests for threadpool work items. @@ -104,5 +104,5 @@ index effa7fc..420979c 100644 + test_tp_work(); } -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0007-ntdll-tests-Add-threadpool-scheduler-tests-for-work-.patch b/patches/ntdll-Vista_Threadpool/0007-ntdll-tests-Add-threadpool-scheduler-tests-for-work-.patch index d5eefede..e9b901a6 100644 --- a/patches/ntdll-Vista_Threadpool/0007-ntdll-tests-Add-threadpool-scheduler-tests-for-work-.patch +++ b/patches/ntdll-Vista_Threadpool/0007-ntdll-tests-Add-threadpool-scheduler-tests-for-work-.patch @@ -1,4 +1,4 @@ -From d796254c2e3c5188d893fb8d1de4978bb864357e Mon Sep 17 00:00:00 2001 +From 792ceb3a01f63e523811d42d7a28f6e31a70e2f7 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 01:45:11 +0100 Subject: ntdll/tests: Add threadpool scheduler tests for work items. @@ -128,5 +128,5 @@ index 420979c..1cfd67b 100644 + test_tp_work_scheduler(); } -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0008-ntdll-Add-support-for-threadpool-group-cancel-callba.patch b/patches/ntdll-Vista_Threadpool/0008-ntdll-Add-support-for-threadpool-group-cancel-callba.patch index 719b892a..be07280d 100644 --- a/patches/ntdll-Vista_Threadpool/0008-ntdll-Add-support-for-threadpool-group-cancel-callba.patch +++ b/patches/ntdll-Vista_Threadpool/0008-ntdll-Add-support-for-threadpool-group-cancel-callba.patch @@ -1,17 +1,17 @@ -From af02399ac80682e6ca5c093150460dca20c7323b Mon Sep 17 00:00:00 2001 +From 624d6ab353109a57dfe0d80053795ef64b6adc3e Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 06:57:53 +0100 Subject: ntdll: Add support for threadpool group cancel callback. --- - dlls/ntdll/threadpool2.c | 17 ++++++++++++++--- + dlls/ntdll/threadpool.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -index 31b5e2e..5233271 100644 ---- a/dlls/ntdll/threadpool2.c -+++ b/dlls/ntdll/threadpool2.c -@@ -81,6 +81,7 @@ struct threadpool_object +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index 1989d56..e30d45c 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -170,6 +170,7 @@ struct threadpool_object struct threadpool *pool; struct threadpool_group *group; PVOID userdata; @@ -19,7 +19,7 @@ index 31b5e2e..5233271 100644 /* information about the group, locked via .group->cs */ struct list group_entry; BOOL is_group_member; -@@ -317,6 +318,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa +@@ -1290,6 +1291,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa object->pool = pool; object->group = NULL; object->userdata = userdata; @@ -27,7 +27,7 @@ index 31b5e2e..5233271 100644 memset( &object->group_entry, 0, sizeof(object->group_entry) ); object->is_group_member = FALSE; -@@ -332,6 +334,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa +@@ -1305,6 +1307,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa FIXME("unsupported environment version %u\n", environment->Version); object->group = impl_from_TP_CLEANUP_GROUP( environment->CleanupGroup ); @@ -35,7 +35,7 @@ index 31b5e2e..5233271 100644 WARN("environment not fully implemented yet\n"); } -@@ -460,7 +463,7 @@ out: +@@ -1377,7 +1380,7 @@ out: RtlLeaveCriticalSection( &pool->cs ); } @@ -44,7 +44,7 @@ index 31b5e2e..5233271 100644 { struct threadpool *pool = object->pool; LONG pending_callbacks = 0; -@@ -477,6 +480,14 @@ static void tp_object_cancel( struct threadpool_object *object ) +@@ -1394,6 +1397,14 @@ static void tp_object_cancel( struct threadpool_object *object ) RtlLeaveCriticalSection( &pool->cs ); @@ -59,7 +59,7 @@ index 31b5e2e..5233271 100644 /* Release references */ while (pending_callbacks--) tp_object_release( object ); -@@ -627,7 +638,7 @@ static void tp_group_release_members( struct threadpool_group *group, BOOL cance +@@ -1673,7 +1684,7 @@ VOID WINAPI TpReleaseCleanupGroupMembers( TP_CLEANUP_GROUP *group, BOOL cancel_p { LIST_FOR_EACH_ENTRY( object, &members, struct threadpool_object, group_entry ) { @@ -68,7 +68,7 @@ index 31b5e2e..5233271 100644 } } -@@ -808,7 +819,7 @@ VOID WINAPI TpWaitForWork( TP_WORK *work, BOOL cancel_pending ) +@@ -1791,7 +1802,7 @@ VOID WINAPI TpWaitForWork( TP_WORK *work, BOOL cancel_pending ) if (this) { if (cancel_pending) @@ -78,5 +78,5 @@ index 31b5e2e..5233271 100644 } } -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0009-ntdll-Add-support-for-threadpool-finalization-callba.patch b/patches/ntdll-Vista_Threadpool/0009-ntdll-Add-support-for-threadpool-finalization-callba.patch index 3a60e4f4..68a14895 100644 --- a/patches/ntdll-Vista_Threadpool/0009-ntdll-Add-support-for-threadpool-finalization-callba.patch +++ b/patches/ntdll-Vista_Threadpool/0009-ntdll-Add-support-for-threadpool-finalization-callba.patch @@ -1,17 +1,17 @@ -From 7fb1d9cfd7dbae474fa0965a143be2408240eeb2 Mon Sep 17 00:00:00 2001 +From d92b2f79160613f6d2f258cbf98624fee30844a8 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 07:03:15 +0100 Subject: ntdll: Add support for threadpool finalization callback. --- - dlls/ntdll/threadpool2.c | 12 ++++++++++++ + dlls/ntdll/threadpool.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -index 5233271..d9e08ac 100644 ---- a/dlls/ntdll/threadpool2.c -+++ b/dlls/ntdll/threadpool2.c -@@ -82,6 +82,7 @@ struct threadpool_object +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index e30d45c..927d31c 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -171,6 +171,7 @@ struct threadpool_object struct threadpool_group *group; PVOID userdata; PTP_CLEANUP_GROUP_CANCEL_CALLBACK group_cancel_callback; @@ -19,7 +19,23 @@ index 5233271..d9e08ac 100644 /* information about the group, locked via .group->cs */ struct list group_entry; BOOL is_group_member; -@@ -281,6 +282,15 @@ static void CALLBACK threadpool_worker_proc( void *param ) +@@ -1292,6 +1293,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa + object->group = NULL; + object->userdata = userdata; + object->group_cancel_callback = NULL; ++ object->finalization_callback = NULL; + + memset( &object->group_entry, 0, sizeof(object->group_entry) ); + object->is_group_member = FALSE; +@@ -1308,6 +1310,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa + + object->group = impl_from_TP_CLEANUP_GROUP( environment->CleanupGroup ); + object->group_cancel_callback = environment->CleanupGroupCancelCallback; ++ object->finalization_callback = environment->FinalizationCallback; + + WARN("environment not fully implemented yet\n"); + } +@@ -1515,6 +1518,15 @@ static void CALLBACK threadpool_worker_proc( void *param ) break; } @@ -35,22 +51,6 @@ index 5233271..d9e08ac 100644 RtlEnterCriticalSection( &pool->cs ); pool->num_busy_workers--; object->num_running_callbacks--; -@@ -319,6 +329,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa - object->group = NULL; - object->userdata = userdata; - object->group_cancel_callback = NULL; -+ object->finalization_callback = NULL; - - memset( &object->group_entry, 0, sizeof(object->group_entry) ); - object->is_group_member = FALSE; -@@ -335,6 +346,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa - - object->group = impl_from_TP_CLEANUP_GROUP( environment->CleanupGroup ); - object->group_cancel_callback = environment->CleanupGroupCancelCallback; -+ object->finalization_callback = environment->FinalizationCallback; - - WARN("environment not fully implemented yet\n"); - } -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0010-ntdll-Implement-threadpool-RaceDll-environment-varia.patch b/patches/ntdll-Vista_Threadpool/0010-ntdll-Implement-threadpool-RaceDll-environment-varia.patch index 65e83a2a..e8430018 100644 --- a/patches/ntdll-Vista_Threadpool/0010-ntdll-Implement-threadpool-RaceDll-environment-varia.patch +++ b/patches/ntdll-Vista_Threadpool/0010-ntdll-Implement-threadpool-RaceDll-environment-varia.patch @@ -1,17 +1,17 @@ -From 3080d2d1a5526d61c02efee05d8804611f860976 Mon Sep 17 00:00:00 2001 +From a2fdd577db91938092d4c38d16a469ddf46189fb Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 07:07:07 +0100 Subject: ntdll: Implement threadpool RaceDll environment variable. --- - dlls/ntdll/threadpool2.c | 11 +++++++++++ + dlls/ntdll/threadpool.c | 11 +++++++++++ 1 file changed, 11 insertions(+) -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -index d9e08ac..a5203f0 100644 ---- a/dlls/ntdll/threadpool2.c -+++ b/dlls/ntdll/threadpool2.c -@@ -83,6 +83,7 @@ struct threadpool_object +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index 927d31c..47f6f6f 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -172,6 +172,7 @@ struct threadpool_object PVOID userdata; PTP_CLEANUP_GROUP_CANCEL_CALLBACK group_cancel_callback; PTP_SIMPLE_CALLBACK finalization_callback; @@ -19,7 +19,7 @@ index d9e08ac..a5203f0 100644 /* information about the group, locked via .group->cs */ struct list group_entry; BOOL is_group_member; -@@ -330,6 +331,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa +@@ -1294,6 +1295,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa object->userdata = userdata; object->group_cancel_callback = NULL; object->finalization_callback = NULL; @@ -27,7 +27,7 @@ index d9e08ac..a5203f0 100644 memset( &object->group_entry, 0, sizeof(object->group_entry) ); object->is_group_member = FALSE; -@@ -347,10 +349,15 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa +@@ -1311,10 +1313,15 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa object->group = impl_from_TP_CLEANUP_GROUP( environment->CleanupGroup ); object->group_cancel_callback = environment->CleanupGroupCancelCallback; object->finalization_callback = environment->FinalizationCallback; @@ -43,7 +43,7 @@ index d9e08ac..a5203f0 100644 /* Increase reference-count on the pool */ interlocked_inc( &pool->refcount ); -@@ -555,6 +562,10 @@ static BOOL tp_object_release( struct threadpool_object *object ) +@@ -1463,6 +1470,10 @@ static BOOL tp_object_release( struct threadpool_object *object ) /* release reference to threadpool */ tp_threadpool_release( object->pool ); @@ -55,5 +55,5 @@ index d9e08ac..a5203f0 100644 return TRUE; } -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0011-ntdll-Implement-TpCallbackMayRunLong-and-instance-st.patch b/patches/ntdll-Vista_Threadpool/0011-ntdll-Implement-TpCallbackMayRunLong-and-instance-st.patch index cffee481..bab7671f 100644 --- a/patches/ntdll-Vista_Threadpool/0011-ntdll-Implement-TpCallbackMayRunLong-and-instance-st.patch +++ b/patches/ntdll-Vista_Threadpool/0011-ntdll-Implement-TpCallbackMayRunLong-and-instance-st.patch @@ -1,18 +1,18 @@ -From 750a6fed12e8b667325b93919a05daf6cbc648b4 Mon Sep 17 00:00:00 2001 +From 11233cc79c1790974d7cb401e64f9f8dcc94e1f3 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 07:25:35 +0100 Subject: ntdll: Implement TpCallbackMayRunLong and instance structure. --- - dlls/ntdll/ntdll.spec | 1 + - dlls/ntdll/threadpool2.c | 104 ++++++++++++++++++++++++++++++++++++++++++----- - 2 files changed, 95 insertions(+), 10 deletions(-) + dlls/ntdll/ntdll.spec | 1 + + dlls/ntdll/threadpool.c | 103 +++++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 94 insertions(+), 10 deletions(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index 1c768c9..38e6fe8 100644 +index 96edd67..b7f1555 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec -@@ -970,6 +970,7 @@ +@@ -971,6 +971,7 @@ @ stdcall TpAllocCleanupGroup(ptr) @ stdcall TpAllocPool(ptr ptr) @ stdcall TpAllocWork(ptr ptr ptr ptr) @@ -20,11 +20,11 @@ index 1c768c9..38e6fe8 100644 @ stdcall TpPostWork(ptr) @ stdcall TpReleaseCleanupGroup(ptr) @ stdcall TpReleaseCleanupGroupMembers(ptr long ptr) -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -index a5203f0..90f2ab7 100644 ---- a/dlls/ntdll/threadpool2.c -+++ b/dlls/ntdll/threadpool2.c -@@ -83,6 +83,7 @@ struct threadpool_object +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index 47f6f6f..d1733c8 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -172,6 +172,7 @@ struct threadpool_object PVOID userdata; PTP_CLEANUP_GROUP_CANCEL_CALLBACK group_cancel_callback; PTP_SIMPLE_CALLBACK finalization_callback; @@ -32,7 +32,7 @@ index a5203f0..90f2ab7 100644 HMODULE race_dll; /* information about the group, locked via .group->cs */ struct list group_entry; -@@ -106,6 +107,14 @@ struct threadpool_object +@@ -195,6 +196,14 @@ struct threadpool_object } u; }; @@ -47,7 +47,7 @@ index a5203f0..90f2ab7 100644 /* internal threadpool group representation */ struct threadpool_group { -@@ -133,6 +142,11 @@ static inline struct threadpool_group *impl_from_TP_CLEANUP_GROUP( TP_CLEANUP_GR +@@ -222,6 +231,11 @@ static inline struct threadpool_group *impl_from_TP_CLEANUP_GROUP( TP_CLEANUP_GR return (struct threadpool_group *)group; } @@ -57,70 +57,9 @@ index a5203f0..90f2ab7 100644 +} + static void CALLBACK threadpool_worker_proc( void *param ); - static NTSTATUS tp_threadpool_alloc( struct threadpool **out ); - static void tp_threadpool_shutdown( struct threadpool *pool ); -@@ -140,6 +154,7 @@ static BOOL tp_threadpool_release( struct threadpool *pool ); static void tp_object_submit( struct threadpool_object *object ); static void tp_object_shutdown( struct threadpool_object *object ); - static BOOL tp_object_release( struct threadpool_object *object ); -+static void tp_instance_initialize( struct threadpool_instance *instance, struct threadpool_object *object ); - static BOOL tp_group_release( struct threadpool_group *group ); - - static struct threadpool *default_threadpool = NULL; -@@ -235,6 +250,8 @@ static BOOL tp_threadpool_release( struct threadpool *pool ) - /* threadpool worker function */ - static void CALLBACK threadpool_worker_proc( void *param ) - { -+ struct threadpool_instance instance; -+ TP_CALLBACK_INSTANCE *cb_instance = (TP_CALLBACK_INSTANCE *)&instance; - struct threadpool *pool = param; - LARGE_INTEGER timeout; - struct list *ptr; -@@ -257,23 +274,24 @@ static void CALLBACK threadpool_worker_proc( void *param ) - object->num_running_callbacks++; - pool->num_busy_workers++; - RtlLeaveCriticalSection( &pool->cs ); -+ tp_instance_initialize( &instance, object ); - - switch (object->type) - { - case TP_OBJECT_TYPE_SIMPLE: - { -- TRACE( "executing simple callback %p(NULL, %p)\n", -- object->u.simple.callback, object->userdata ); -- object->u.simple.callback( NULL, object->userdata ); -+ TRACE( "executing simple callback %p(%p, %p)\n", -+ object->u.simple.callback, cb_instance, object->userdata ); -+ object->u.simple.callback( cb_instance, object->userdata ); - TRACE( "callback %p returned\n", object->u.simple.callback ); - break; - } - - case TP_OBJECT_TYPE_WORK: - { -- TRACE( "executing work callback %p(NULL, %p, %p)\n", -- object->u.work.callback, object->userdata, object ); -- object->u.work.callback( NULL, object->userdata, (TP_WORK *)object ); -+ TRACE( "executing work callback %p(%p, %p, %p)\n", -+ object->u.work.callback, cb_instance, object->userdata, object ); -+ object->u.work.callback( cb_instance, object->userdata, (TP_WORK *)object ); - TRACE( "callback %p returned\n", object->u.work.callback ); - break; - } -@@ -286,9 +304,9 @@ static void CALLBACK threadpool_worker_proc( void *param ) - /* Execute finalization callback */ - if (object->finalization_callback) - { -- TRACE( "executing finalization callback %p(NULL, %p)\n", -- object->finalization_callback, object->userdata ); -- object->finalization_callback( NULL, object->userdata ); -+ TRACE( "executing finalization callback %p(%p, %p)\n", -+ object->finalization_callback, cb_instance, object->userdata ); -+ object->finalization_callback( cb_instance, object->userdata ); - TRACE( "callback %p returned\n", object->finalization_callback ); - } - -@@ -331,6 +349,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa +@@ -1295,6 +1309,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa object->userdata = userdata; object->group_cancel_callback = NULL; object->finalization_callback = NULL; @@ -128,7 +67,7 @@ index a5203f0..90f2ab7 100644 object->race_dll = NULL; memset( &object->group_entry, 0, sizeof(object->group_entry) ); -@@ -349,9 +368,14 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa +@@ -1313,9 +1328,14 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa object->group = impl_from_TP_CLEANUP_GROUP( environment->CleanupGroup ); object->group_cancel_callback = environment->CleanupGroupCancelCallback; object->finalization_callback = environment->FinalizationCallback; @@ -144,7 +83,7 @@ index a5203f0..90f2ab7 100644 } /* Increase dll refcount */ -@@ -570,6 +594,52 @@ static BOOL tp_object_release( struct threadpool_object *object ) +@@ -1478,9 +1498,57 @@ static BOOL tp_object_release( struct threadpool_object *object ) return TRUE; } @@ -194,10 +133,59 @@ index a5203f0..90f2ab7 100644 + return !status; +} + - /* allocates a new cleanup group */ - static NTSTATUS tp_group_alloc( struct threadpool_group **out ) + /* threadpool worker function */ + static void CALLBACK threadpool_worker_proc( void *param ) { -@@ -715,6 +785,20 @@ NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID us ++ struct threadpool_instance instance; ++ TP_CALLBACK_INSTANCE *cb_instance = (TP_CALLBACK_INSTANCE *)&instance; + struct threadpool *pool = param; + LARGE_INTEGER timeout; + struct list *ptr; +@@ -1503,23 +1571,24 @@ static void CALLBACK threadpool_worker_proc( void *param ) + object->num_running_callbacks++; + pool->num_busy_workers++; + RtlLeaveCriticalSection( &pool->cs ); ++ tp_instance_initialize( &instance, object ); + + switch (object->type) + { + case TP_OBJECT_TYPE_SIMPLE: + { +- TRACE( "executing simple callback %p(NULL, %p)\n", +- object->u.simple.callback, object->userdata ); +- object->u.simple.callback( NULL, object->userdata ); ++ TRACE( "executing simple callback %p(%p, %p)\n", ++ object->u.simple.callback, cb_instance, object->userdata ); ++ object->u.simple.callback( cb_instance, object->userdata ); + TRACE( "callback %p returned\n", object->u.simple.callback ); + break; + } + + case TP_OBJECT_TYPE_WORK: + { +- TRACE( "executing work callback %p(NULL, %p, %p)\n", +- object->u.work.callback, object->userdata, object ); +- object->u.work.callback( NULL, object->userdata, (TP_WORK *)object ); ++ TRACE( "executing work callback %p(%p, %p, %p)\n", ++ object->u.work.callback, cb_instance, object->userdata, object ); ++ object->u.work.callback( cb_instance, object->userdata, (TP_WORK *)object ); + TRACE( "callback %p returned\n", object->u.work.callback ); + break; + } +@@ -1532,9 +1601,9 @@ static void CALLBACK threadpool_worker_proc( void *param ) + /* Execute finalization callback */ + if (object->finalization_callback) + { +- TRACE( "executing finalization callback %p(NULL, %p)\n", +- object->finalization_callback, object->userdata ); +- object->finalization_callback( NULL, object->userdata ); ++ TRACE( "executing finalization callback %p(%p, %p)\n", ++ object->finalization_callback, cb_instance, object->userdata ); ++ object->finalization_callback( cb_instance, object->userdata ); + TRACE( "callback %p returned\n", object->finalization_callback ); + } + +@@ -1627,6 +1696,20 @@ NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID us } /*********************************************************************** @@ -219,5 +207,5 @@ index a5203f0..90f2ab7 100644 */ VOID WINAPI TpPostWork( TP_WORK *work ) -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0012-ntdll-Implement-TpDisassociateCallback.patch b/patches/ntdll-Vista_Threadpool/0012-ntdll-Implement-TpDisassociateCallback.patch index e8c77f0f..7e0bec92 100644 --- a/patches/ntdll-Vista_Threadpool/0012-ntdll-Implement-TpDisassociateCallback.patch +++ b/patches/ntdll-Vista_Threadpool/0012-ntdll-Implement-TpDisassociateCallback.patch @@ -1,18 +1,18 @@ -From c3f8e7288538d526ece6b07ff69790e6ff7b1d9d Mon Sep 17 00:00:00 2001 +From 472f35764b63622fd5887ac16194e8b5089f0fc6 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 07:31:27 +0100 Subject: ntdll: Implement TpDisassociateCallback. --- - dlls/ntdll/ntdll.spec | 1 + - dlls/ntdll/threadpool2.c | 52 +++++++++++++++++++++++++++++++++++++++++++++--- + dlls/ntdll/ntdll.spec | 1 + + dlls/ntdll/threadpool.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index 38e6fe8..aaf1c64 100644 +index b7f1555..63426c5 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec -@@ -971,6 +971,7 @@ +@@ -972,6 +972,7 @@ @ stdcall TpAllocPool(ptr ptr) @ stdcall TpAllocWork(ptr ptr ptr ptr) @ stdcall TpCallbackMayRunLong(ptr) @@ -20,11 +20,11 @@ index 38e6fe8..aaf1c64 100644 @ stdcall TpPostWork(ptr) @ stdcall TpReleaseCleanupGroup(ptr) @ stdcall TpReleaseCleanupGroupMembers(ptr long ptr) -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -index 90f2ab7..c40c06a 100644 ---- a/dlls/ntdll/threadpool2.c -+++ b/dlls/ntdll/threadpool2.c -@@ -112,6 +112,7 @@ struct threadpool_instance +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index d1733c8..4861ba6 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -201,6 +201,7 @@ struct threadpool_instance { struct threadpool_object *object; DWORD threadid; @@ -32,23 +32,7 @@ index 90f2ab7..c40c06a 100644 BOOL may_run_long; }; -@@ -312,9 +313,12 @@ static void CALLBACK threadpool_worker_proc( void *param ) - - RtlEnterCriticalSection( &pool->cs ); - pool->num_busy_workers--; -- object->num_running_callbacks--; -- if (!object->num_pending_callbacks && !object->num_running_callbacks) -- RtlWakeAllConditionVariable( &object->finished_event ); -+ if (!instance.disassociated) -+ { -+ object->num_running_callbacks--; -+ if (!object->num_pending_callbacks && !object->num_running_callbacks) -+ RtlWakeAllConditionVariable( &object->finished_event ); -+ } - tp_object_release( object ); - } - -@@ -599,9 +603,37 @@ static void tp_instance_initialize( struct threadpool_instance *instance, struct +@@ -1503,9 +1504,37 @@ static void tp_instance_initialize( struct threadpool_instance *instance, struct { instance->object = object; instance->threadid = GetCurrentThreadId(); @@ -86,7 +70,23 @@ index 90f2ab7..c40c06a 100644 /* hint for the threadpool that the execution might take long, spawn additional workers */ static BOOL tp_instance_may_run_long( struct threadpool_instance *instance ) { -@@ -799,6 +831,20 @@ NTSTATUS WINAPI TpCallbackMayRunLong( TP_CALLBACK_INSTANCE *instance ) +@@ -1609,9 +1638,12 @@ static void CALLBACK threadpool_worker_proc( void *param ) + + RtlEnterCriticalSection( &pool->cs ); + pool->num_busy_workers--; +- object->num_running_callbacks--; +- if (!object->num_pending_callbacks && !object->num_running_callbacks) +- RtlWakeAllConditionVariable( &object->finished_event ); ++ if (!instance.disassociated) ++ { ++ object->num_running_callbacks--; ++ if (!object->num_pending_callbacks && !object->num_running_callbacks) ++ RtlWakeAllConditionVariable( &object->finished_event ); ++ } + tp_object_release( object ); + } + +@@ -1710,6 +1742,20 @@ NTSTATUS WINAPI TpCallbackMayRunLong( TP_CALLBACK_INSTANCE *instance ) } /*********************************************************************** @@ -108,5 +108,5 @@ index 90f2ab7..c40c06a 100644 */ VOID WINAPI TpPostWork( TP_WORK *work ) -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0013-ntdll-Implement-various-TpCallback-OnCompletion-func.patch b/patches/ntdll-Vista_Threadpool/0013-ntdll-Implement-various-TpCallback-OnCompletion-func.patch index f0e7b5ac..90e9c525 100644 --- a/patches/ntdll-Vista_Threadpool/0013-ntdll-Implement-various-TpCallback-OnCompletion-func.patch +++ b/patches/ntdll-Vista_Threadpool/0013-ntdll-Implement-various-TpCallback-OnCompletion-func.patch @@ -1,18 +1,18 @@ -From 6229d9139d7b30f00e78c6f1f8410c1c99712295 Mon Sep 17 00:00:00 2001 +From 16d0eb264d85a90fa7faf1b429dec1f4efe385a2 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 07:40:02 +0100 Subject: ntdll: Implement various TpCallback*OnCompletion functions. --- - dlls/ntdll/ntdll.spec | 5 ++ - dlls/ntdll/threadpool2.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 159 insertions(+) + dlls/ntdll/ntdll.spec | 5 ++ + dlls/ntdll/threadpool.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 158 insertions(+) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index aaf1c64..0c5ad39 100644 +index 63426c5..6100a7e 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec -@@ -970,7 +970,12 @@ +@@ -971,7 +971,12 @@ @ stdcall TpAllocCleanupGroup(ptr) @ stdcall TpAllocPool(ptr ptr) @ stdcall TpAllocWork(ptr ptr ptr ptr) @@ -25,11 +25,11 @@ index aaf1c64..0c5ad39 100644 @ stdcall TpDisassociateCallback(ptr) @ stdcall TpPostWork(ptr) @ stdcall TpReleaseCleanupGroup(ptr) -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -index c40c06a..ebf8b94 100644 ---- a/dlls/ntdll/threadpool2.c -+++ b/dlls/ntdll/threadpool2.c -@@ -114,6 +114,15 @@ struct threadpool_instance +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index 4861ba6..aa2d8e9 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -203,6 +203,15 @@ struct threadpool_instance DWORD threadid; BOOL disassociated; BOOL may_run_long; @@ -45,23 +45,7 @@ index c40c06a..ebf8b94 100644 }; /* internal threadpool group representation */ -@@ -156,6 +165,7 @@ static void tp_object_submit( struct threadpool_object *object ); - static void tp_object_shutdown( struct threadpool_object *object ); - static BOOL tp_object_release( struct threadpool_object *object ); - static void tp_instance_initialize( struct threadpool_instance *instance, struct threadpool_object *object ); -+static NTSTATUS tp_instance_cleanup( struct threadpool_instance *instance ); - static BOOL tp_group_release( struct threadpool_group *group ); - - static struct threadpool *default_threadpool = NULL; -@@ -311,6 +321,7 @@ static void CALLBACK threadpool_worker_proc( void *param ) - TRACE( "callback %p returned\n", object->finalization_callback ); - } - -+ tp_instance_cleanup( &instance ); - RtlEnterCriticalSection( &pool->cs ); - pool->num_busy_workers--; - if (!instance.disassociated) -@@ -605,6 +616,48 @@ static void tp_instance_initialize( struct threadpool_instance *instance, struct +@@ -1506,8 +1515,50 @@ static void tp_instance_initialize( struct threadpool_instance *instance, struct instance->threadid = GetCurrentThreadId(); instance->disassociated = FALSE; instance->may_run_long = object->may_run_long; @@ -71,8 +55,8 @@ index c40c06a..ebf8b94 100644 + instance->cleanup.semaphore_count = 0; + instance->cleanup.event = NULL; + instance->cleanup.library = NULL; -+} -+ + } + +static NTSTATUS tp_instance_cleanup( struct threadpool_instance *instance ) +{ + NTSTATUS status; @@ -107,10 +91,20 @@ index c40c06a..ebf8b94 100644 + } + + return STATUS_SUCCESS; - } - ++ } ++ /* disassociates the current thread from the threadpool object */ -@@ -817,6 +870,26 @@ NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID us + static void tp_instance_disassociate_thread( struct threadpool_instance *instance ) + { +@@ -1636,6 +1687,7 @@ static void CALLBACK threadpool_worker_proc( void *param ) + TRACE( "callback %p returned\n", object->finalization_callback ); + } + ++ tp_instance_cleanup( &instance ); + RtlEnterCriticalSection( &pool->cs ); + pool->num_busy_workers--; + if (!instance.disassociated) +@@ -1728,6 +1780,26 @@ NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID us } /*********************************************************************** @@ -137,7 +131,7 @@ index c40c06a..ebf8b94 100644 * TpCallbackMayRunLong (NTDLL.@) */ NTSTATUS WINAPI TpCallbackMayRunLong( TP_CALLBACK_INSTANCE *instance ) -@@ -831,6 +904,87 @@ NTSTATUS WINAPI TpCallbackMayRunLong( TP_CALLBACK_INSTANCE *instance ) +@@ -1742,6 +1814,87 @@ NTSTATUS WINAPI TpCallbackMayRunLong( TP_CALLBACK_INSTANCE *instance ) } /*********************************************************************** @@ -226,5 +220,5 @@ index c40c06a..ebf8b94 100644 */ VOID WINAPI TpDisassociateCallback( TP_CALLBACK_INSTANCE *instance ) -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0014-ntdll-Add-remaining-threadpool-functions-to-specfile.patch b/patches/ntdll-Vista_Threadpool/0014-ntdll-Add-remaining-threadpool-functions-to-specfile.patch index 7500b785..eb8b019f 100644 --- a/patches/ntdll-Vista_Threadpool/0014-ntdll-Add-remaining-threadpool-functions-to-specfile.patch +++ b/patches/ntdll-Vista_Threadpool/0014-ntdll-Add-remaining-threadpool-functions-to-specfile.patch @@ -1,4 +1,4 @@ -From 0fbfe7ef91e7c0614cf45b75211ab70b500029db Mon Sep 17 00:00:00 2001 +From ac6e2e281ba4f0b6cb9643ed288aaf05fd2710f7 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 08:01:00 +0100 Subject: ntdll: Add remaining threadpool functions to specfile. @@ -8,10 +8,10 @@ Subject: ntdll: Add remaining threadpool functions to specfile. 1 file changed, 43 insertions(+) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index 0c5ad39..970bdeb 100644 +index 6100a7e..19e63a5 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec -@@ -967,24 +967,67 @@ +@@ -968,24 +968,67 @@ @ stdcall RtlxOemStringToUnicodeSize(ptr) RtlOemStringToUnicodeSize @ stdcall RtlxUnicodeStringToAnsiSize(ptr) RtlUnicodeStringToAnsiSize @ stdcall RtlxUnicodeStringToOemSize(ptr) RtlUnicodeStringToOemSize @@ -80,5 +80,5 @@ index 0c5ad39..970bdeb 100644 @ stdcall -ret64 VerSetConditionMask(int64 long long) @ stdcall ZwAcceptConnectPort(ptr long ptr long long ptr) NtAcceptConnectPort -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0015-ntdll-Implement-threadpool-timer-functions.-rev-2.patch b/patches/ntdll-Vista_Threadpool/0015-ntdll-Implement-threadpool-timer-functions.-rev-2.patch index 53b3c227..f3532831 100644 --- a/patches/ntdll-Vista_Threadpool/0015-ntdll-Implement-threadpool-timer-functions.-rev-2.patch +++ b/patches/ntdll-Vista_Threadpool/0015-ntdll-Implement-threadpool-timer-functions.-rev-2.patch @@ -1,18 +1,18 @@ -From badc2951cd6764ce4115097874dadcdfa084354e Mon Sep 17 00:00:00 2001 +From fa631b5349a02927f1fec95235a40e7b9a75e7b6 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 08:19:47 +0100 Subject: ntdll: Implement threadpool timer functions. (rev 2) --- - dlls/ntdll/ntdll.spec | 10 +- - dlls/ntdll/threadpool2.c | 390 ++++++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 394 insertions(+), 6 deletions(-) + dlls/ntdll/ntdll.spec | 10 +- + dlls/ntdll/threadpool.c | 383 +++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 387 insertions(+), 6 deletions(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index 970bdeb..24b4c30 100644 +index 19e63a5..7aa8bda 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec -@@ -973,7 +973,7 @@ +@@ -974,7 +974,7 @@ # @ stub TpAllocIoCompletion # @ stub TpAllocJobNotification @ stdcall TpAllocPool(ptr ptr) @@ -21,7 +21,7 @@ index 970bdeb..24b4c30 100644 # @ stub TpAllocWait @ stdcall TpAllocWork(ptr ptr ptr ptr) # @ stub TpAlpcRegisterCompletionList -@@ -995,7 +995,7 @@ +@@ -996,7 +996,7 @@ # @ stub TpDbgSetLogRoutine # @ stub TpDisablePoolCallbackChecks @ stdcall TpDisassociateCallback(ptr) @@ -30,7 +30,7 @@ index 970bdeb..24b4c30 100644 @ stdcall TpPostWork(ptr) # @ stub TpQueryPoolStackInformation # @ stub TpReleaseAlpcCompletion -@@ -1004,7 +1004,7 @@ +@@ -1005,7 +1005,7 @@ # @ stub TpReleaseIoCompletion # @ stub TpReleaseJobNotification @ stdcall TpReleasePool(ptr) @@ -39,7 +39,7 @@ index 970bdeb..24b4c30 100644 # @ stub TpReleaseWait @ stdcall TpReleaseWork(ptr) # @ stub TpSetDefaultPoolMaxThreads -@@ -1015,7 +1015,7 @@ +@@ -1016,7 +1016,7 @@ # @ stub TpSetPoolStackInformation # @ stub TpSetPoolThreadBasePriority # @ stub TpSetPoolWorkerThreadIdleTimeout @@ -48,7 +48,7 @@ index 970bdeb..24b4c30 100644 # @ stub TpSetTimerEx # @ stub TpSetWait # @ stub TpSetWaitEx -@@ -1026,7 +1026,7 @@ +@@ -1027,7 +1027,7 @@ # @ stub TpWaitForAlpcCompletion # @ stub TpWaitForIoCompletion # @ stub TpWaitForJobNotification @@ -57,11 +57,11 @@ index 970bdeb..24b4c30 100644 # @ stub TpWaitForWait @ stdcall TpWaitForWork(ptr long) @ stdcall -ret64 VerSetConditionMask(int64 long long) -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -index ebf8b94..a1089a4 100644 ---- a/dlls/ntdll/threadpool2.c -+++ b/dlls/ntdll/threadpool2.c -@@ -68,7 +68,8 @@ struct threadpool +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index aa2d8e9..afb35aa 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -157,7 +157,8 @@ struct threadpool enum threadpool_objtype { TP_OBJECT_TYPE_SIMPLE, @@ -71,7 +71,7 @@ index ebf8b94..a1089a4 100644 }; /* internal threadpool object representation */ -@@ -104,6 +105,18 @@ struct threadpool_object +@@ -193,6 +194,18 @@ struct threadpool_object { PTP_WORK_CALLBACK callback; } work; @@ -90,7 +90,7 @@ index ebf8b94..a1089a4 100644 } u; }; -@@ -135,6 +148,33 @@ struct threadpool_group +@@ -224,6 +237,33 @@ struct threadpool_group struct list members; }; @@ -124,7 +124,7 @@ index ebf8b94..a1089a4 100644 static inline struct threadpool *impl_from_TP_POOL( TP_POOL *pool ) { return (struct threadpool *)pool; -@@ -147,6 +187,13 @@ static inline struct threadpool_object *impl_from_TP_WORK( TP_WORK *work ) +@@ -236,6 +276,13 @@ static inline struct threadpool_object *impl_from_TP_WORK( TP_WORK *work ) return object; } @@ -138,17 +138,17 @@ index ebf8b94..a1089a4 100644 static inline struct threadpool_group *impl_from_TP_CLEANUP_GROUP( TP_CLEANUP_GROUP *group ) { return (struct threadpool_group *)group; -@@ -158,6 +205,7 @@ static inline struct threadpool_instance *impl_from_TP_CALLBACK_INSTANCE( TP_CAL +@@ -247,6 +294,7 @@ static inline struct threadpool_instance *impl_from_TP_CALLBACK_INSTANCE( TP_CAL } static void CALLBACK threadpool_worker_proc( void *param ); +static void CALLBACK timerqueue_thread_proc( void *param ); - static NTSTATUS tp_threadpool_alloc( struct threadpool **out ); - static void tp_threadpool_shutdown( struct threadpool *pool ); - static BOOL tp_threadpool_release( struct threadpool *pool ); -@@ -168,6 +216,230 @@ static void tp_instance_initialize( struct threadpool_instance *instance, struct - static NTSTATUS tp_instance_cleanup( struct threadpool_instance *instance ); - static BOOL tp_group_release( struct threadpool_group *group ); + static void tp_object_submit( struct threadpool_object *object ); + static void tp_object_shutdown( struct threadpool_object *object ); + static BOOL tp_object_release( struct threadpool_object *object ); +@@ -1170,6 +1218,230 @@ NTSTATUS WINAPI RtlDeleteTimer(HANDLE TimerQueue, HANDLE Timer, + return status; + } +static NTSTATUS tp_timerqueue_acquire( struct threadpool_object *timer ) +{ @@ -374,10 +374,20 @@ index ebf8b94..a1089a4 100644 + RtlLeaveCriticalSection( &timerqueue.cs ); +} + - static struct threadpool *default_threadpool = NULL; + /* allocate a new threadpool (with at least one worker thread) */ + static NTSTATUS tp_threadpool_alloc( struct threadpool **out ) + { +@@ -1466,6 +1738,9 @@ static void tp_object_wait( struct threadpool_object *object ) + /* mark an object as 'shutdown', submitting is no longer possible */ + static void tp_object_shutdown( struct threadpool_object *object ) + { ++ if (object->type == TP_OBJECT_TYPE_TIMER) ++ tp_timerqueue_release( object ); ++ + object->shutdown = TRUE; + } - /* allocates or returns the default threadpool */ -@@ -307,6 +579,15 @@ static void CALLBACK threadpool_worker_proc( void *param ) +@@ -1673,6 +1948,15 @@ static void CALLBACK threadpool_worker_proc( void *param ) break; } @@ -393,17 +403,21 @@ index ebf8b94..a1089a4 100644 default: assert(0); break; -@@ -482,6 +763,43 @@ static NTSTATUS tp_object_alloc_work( struct threadpool_object **out, PTP_WORK_C - return STATUS_SUCCESS; +@@ -1747,6 +2031,48 @@ NTSTATUS WINAPI TpAllocPool( TP_POOL **out, PVOID reserved ) } -+static NTSTATUS tp_object_alloc_timer( struct threadpool_object **out, PTP_TIMER_CALLBACK callback, -+ PVOID userdata, TP_CALLBACK_ENVIRON *environment ) + /*********************************************************************** ++ * TpAllocTimer (NTDLL.@) ++ */ ++NTSTATUS WINAPI TpAllocTimer( TP_TIMER **out, PTP_TIMER_CALLBACK callback, PVOID userdata, ++ TP_CALLBACK_ENVIRON *environment ) +{ + struct threadpool_object *object; + struct threadpool *pool = NULL; + NTSTATUS status; + ++ TRACE("%p %p %p %p\n", out, callback, userdata, environment); ++ + if (environment) + pool = (struct threadpool *)environment->Pool; + @@ -430,43 +444,15 @@ index ebf8b94..a1089a4 100644 + + tp_object_initialize( object, pool, userdata, environment ); + -+ *out = object; ++ *out = (TP_TIMER *)object; + return STATUS_SUCCESS; +} -+ - /* submits an object to a threadpool */ - static void tp_object_submit( struct threadpool_object *object ) - { -@@ -567,6 +885,9 @@ static void tp_object_wait( struct threadpool_object *object ) - /* mark an object as 'shutdown', submitting is no longer possible */ - static void tp_object_shutdown( struct threadpool_object *object ) - { -+ if (object->type == TP_OBJECT_TYPE_TIMER) -+ tp_timerqueue_release( object ); -+ - object->shutdown = TRUE; - } - -@@ -858,6 +1179,18 @@ NTSTATUS WINAPI TpAllocPool( TP_POOL **out, PVOID reserved ) - } - - /*********************************************************************** -+ * TpAllocTimer (NTDLL.@) -+ */ -+NTSTATUS WINAPI TpAllocTimer( TP_TIMER **out, PTP_TIMER_CALLBACK callback, PVOID userdata, -+ TP_CALLBACK_ENVIRON *environment ) -+{ -+ TRACE("%p %p %p %p\n", out, callback, userdata, environment); -+ -+ return tp_object_alloc_timer( (struct threadpool_object **)out, callback, -+ userdata, environment ); -+} + +/*********************************************************************** * TpAllocWork (NTDLL.@) */ NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID userdata, -@@ -999,6 +1332,17 @@ VOID WINAPI TpDisassociateCallback( TP_CALLBACK_INSTANCE *instance ) +@@ -1909,6 +2235,17 @@ VOID WINAPI TpDisassociateCallback( TP_CALLBACK_INSTANCE *instance ) } /*********************************************************************** @@ -484,7 +470,7 @@ index ebf8b94..a1089a4 100644 * TpPostWork (NTDLL.@) */ VOID WINAPI TpPostWork( TP_WORK *work ) -@@ -1057,6 +1401,21 @@ VOID WINAPI TpReleasePool( TP_POOL *pool ) +@@ -2017,6 +2354,21 @@ VOID WINAPI TpReleasePool( TP_POOL *pool ) } /*********************************************************************** @@ -506,7 +492,7 @@ index ebf8b94..a1089a4 100644 * TpReleaseWork (NTDLL.@) */ VOID WINAPI TpReleaseWork( TP_WORK *work ) -@@ -1105,6 +1464,20 @@ BOOL WINAPI TpSetPoolMinThreads( TP_POOL *pool, DWORD minimum ) +@@ -2065,6 +2417,20 @@ BOOL WINAPI TpSetPoolMinThreads( TP_POOL *pool, DWORD minimum ) } /*********************************************************************** @@ -527,7 +513,7 @@ index ebf8b94..a1089a4 100644 * TpSimpleTryPost (NTDLL.@) */ NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata, -@@ -1116,6 +1489,21 @@ NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata, +@@ -2097,6 +2463,21 @@ NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata, } /*********************************************************************** @@ -550,5 +536,5 @@ index ebf8b94..a1089a4 100644 */ VOID WINAPI TpWaitForWork( TP_WORK *work, BOOL cancel_pending ) -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0016-ntdll-tests-Add-tests-for-Tp-threadpool-functions.patch b/patches/ntdll-Vista_Threadpool/0016-ntdll-tests-Add-tests-for-Tp-threadpool-functions.patch index 32b46dd5..63dfa49c 100644 --- a/patches/ntdll-Vista_Threadpool/0016-ntdll-tests-Add-tests-for-Tp-threadpool-functions.patch +++ b/patches/ntdll-Vista_Threadpool/0016-ntdll-tests-Add-tests-for-Tp-threadpool-functions.patch @@ -1,4 +1,4 @@ -From 63d215c8d93f67821f4defe1dcb61f7702639c1a Mon Sep 17 00:00:00 2001 +From 4a3ad1401f815720b35b0ab48e6ab1cc08835f5e Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 13:17:04 +0100 Subject: ntdll/tests: Add tests for Tp* threadpool functions. @@ -526,5 +526,5 @@ index 1cfd67b..b44b0f5 100644 + Sleep(100); } -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0017-kernel32-Forward-various-threadpool-functions-to-ntd.patch b/patches/ntdll-Vista_Threadpool/0017-kernel32-Forward-various-threadpool-functions-to-ntd.patch index 820ea55d..f2644bd8 100644 --- a/patches/ntdll-Vista_Threadpool/0017-kernel32-Forward-various-threadpool-functions-to-ntd.patch +++ b/patches/ntdll-Vista_Threadpool/0017-kernel32-Forward-various-threadpool-functions-to-ntd.patch @@ -1,4 +1,4 @@ -From 62fdd332539cd14b48077665d6c88f12ac12b091 Mon Sep 17 00:00:00 2001 +From 6a7aaa0145d32fde06229bae7f8cb879ea2ac182 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sun, 1 Feb 2015 19:41:13 +0100 Subject: kernel32: Forward various threadpool functions to ntdll. @@ -11,7 +11,7 @@ Subject: kernel32: Forward various threadpool functions to ntdll. 4 files changed, 155 insertions(+), 27 deletions(-) diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec -index c95c446..54d83da 100644 +index 1179af2..f65f894 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -204,7 +204,7 @@ @@ -191,10 +191,10 @@ index d3ecd2a..25801b2 100644 static void test_reserved_tls(void) diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c -index 0abfdf1..085b011 100644 +index 3dabf94..945fe0b 100644 --- a/dlls/kernel32/thread.c +++ b/dlls/kernel32/thread.c -@@ -831,3 +831,104 @@ BOOL WINAPI GetThreadPreferredUILanguages( DWORD flags, PULONG count, PCZZWSTR b +@@ -860,3 +860,104 @@ BOOL WINAPI GetThreadPreferredUILanguages( DWORD flags, PULONG count, PCZZWSTR b *buffersize = 0; return TRUE; } @@ -300,10 +300,10 @@ index 0abfdf1..085b011 100644 + TpSetTimer( timer, due_time ? &timeout : NULL, period, window_length ); +} diff --git a/include/winternl.h b/include/winternl.h -index 3992309..7608d21 100644 +index f88001f..4f16d24 100644 --- a/include/winternl.h +++ b/include/winternl.h -@@ -2604,6 +2604,33 @@ NTSYSAPI LONGLONG WINAPI RtlLargeIntegerSubtract(LONGLONG,LONGLONG); +@@ -2596,6 +2596,33 @@ NTSYSAPI LONGLONG WINAPI RtlLargeIntegerSubtract(LONGLONG,LONGLONG); NTSYSAPI NTSTATUS WINAPI RtlLargeIntegerToChar(const ULONGLONG *,ULONG,ULONG,PCHAR); #endif @@ -338,5 +338,5 @@ index 3992309..7608d21 100644 NTSYSAPI NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRING *unix_name_ret, -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0018-ntdll-Implement-threadpool-wait-objects.patch b/patches/ntdll-Vista_Threadpool/0018-ntdll-Implement-threadpool-wait-objects.patch index 272fdb11..e3d47bc7 100644 --- a/patches/ntdll-Vista_Threadpool/0018-ntdll-Implement-threadpool-wait-objects.patch +++ b/patches/ntdll-Vista_Threadpool/0018-ntdll-Implement-threadpool-wait-objects.patch @@ -1,18 +1,18 @@ -From 59afc4395781ac5bddc1c846605771529eb2055b Mon Sep 17 00:00:00 2001 +From 56bf4aa534b59ba3a7d6175bea587b7b2aba1206 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Wed, 4 Mar 2015 13:33:25 +0100 Subject: ntdll: Implement threadpool wait objects. --- - dlls/ntdll/ntdll.spec | 8 +- - dlls/ntdll/threadpool2.c | 486 ++++++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 483 insertions(+), 11 deletions(-) + dlls/ntdll/ntdll.spec | 8 +- + dlls/ntdll/threadpool.c | 479 +++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 476 insertions(+), 11 deletions(-) diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec -index 24b4c30..b4cfe69 100644 +index 7aa8bda..7c15f76 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec -@@ -974,7 +974,7 @@ +@@ -975,7 +975,7 @@ # @ stub TpAllocJobNotification @ stdcall TpAllocPool(ptr ptr) @ stdcall TpAllocTimer(ptr ptr ptr) @@ -21,7 +21,7 @@ index 24b4c30..b4cfe69 100644 @ stdcall TpAllocWork(ptr ptr ptr ptr) # @ stub TpAlpcRegisterCompletionList # @ stub TpAlpcUnregisterCompletionList -@@ -1005,7 +1005,7 @@ +@@ -1006,7 +1006,7 @@ # @ stub TpReleaseJobNotification @ stdcall TpReleasePool(ptr) @ stdcall TpReleaseTimer(ptr) @@ -30,7 +30,7 @@ index 24b4c30..b4cfe69 100644 @ stdcall TpReleaseWork(ptr) # @ stub TpSetDefaultPoolMaxThreads # @ stub TpSetDefaultPoolStackInformation -@@ -1017,7 +1017,7 @@ +@@ -1018,7 +1018,7 @@ # @ stub TpSetPoolWorkerThreadIdleTimeout @ stdcall TpSetTimer(ptr ptr long long) # @ stub TpSetTimerEx @@ -39,7 +39,7 @@ index 24b4c30..b4cfe69 100644 # @ stub TpSetWaitEx @ stdcall TpSimpleTryPost(ptr ptr ptr) # @ stub TpStartAsyncIoOperation -@@ -1027,7 +1027,7 @@ +@@ -1028,7 +1028,7 @@ # @ stub TpWaitForIoCompletion # @ stub TpWaitForJobNotification @ stdcall TpWaitForTimer(ptr long) @@ -48,19 +48,19 @@ index 24b4c30..b4cfe69 100644 @ stdcall TpWaitForWork(ptr long) @ stdcall -ret64 VerSetConditionMask(int64 long long) @ stdcall ZwAcceptConnectPort(ptr long ptr long long ptr) NtAcceptConnectPort -diff --git a/dlls/ntdll/threadpool2.c b/dlls/ntdll/threadpool2.c -index a1089a4..9b2a0c8 100644 ---- a/dlls/ntdll/threadpool2.c -+++ b/dlls/ntdll/threadpool2.c -@@ -48,6 +48,7 @@ static inline LONG interlocked_dec( PLONG dest ) - } +diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c +index afb35aa..706d62b 100644 +--- a/dlls/ntdll/threadpool.c ++++ b/dlls/ntdll/threadpool.c +@@ -137,6 +137,7 @@ struct timer_queue + */ #define THREADPOOL_WORKER_TIMEOUT 5000 +#define MAXIMUM_WAITQUEUE_OBJECTS (MAXIMUM_WAIT_OBJECTS - 1) /* internal threadpool representation */ struct threadpool -@@ -69,7 +70,8 @@ enum threadpool_objtype +@@ -158,7 +159,8 @@ enum threadpool_objtype { TP_OBJECT_TYPE_SIMPLE, TP_OBJECT_TYPE_WORK, @@ -70,7 +70,7 @@ index a1089a4..9b2a0c8 100644 }; /* internal threadpool object representation */ -@@ -117,6 +119,17 @@ struct threadpool_object +@@ -206,6 +208,17 @@ struct threadpool_object LONG period; LONG window_length; } timer; @@ -88,7 +88,7 @@ index a1089a4..9b2a0c8 100644 } u; }; -@@ -175,6 +188,38 @@ static RTL_CRITICAL_SECTION_DEBUG timerqueue_debug = +@@ -264,6 +277,38 @@ static RTL_CRITICAL_SECTION_DEBUG timerqueue_debug = 0, 0, { (DWORD_PTR)(__FILE__ ": timerqueue.cs") } }; @@ -127,7 +127,7 @@ index a1089a4..9b2a0c8 100644 static inline struct threadpool *impl_from_TP_POOL( TP_POOL *pool ) { return (struct threadpool *)pool; -@@ -194,6 +239,13 @@ static inline struct threadpool_object *impl_from_TP_TIMER( TP_TIMER *timer ) +@@ -283,6 +328,13 @@ static inline struct threadpool_object *impl_from_TP_TIMER( TP_TIMER *timer ) return object; } @@ -141,20 +141,17 @@ index a1089a4..9b2a0c8 100644 static inline struct threadpool_group *impl_from_TP_CLEANUP_GROUP( TP_CLEANUP_GROUP *group ) { return (struct threadpool_group *)group; -@@ -206,10 +258,11 @@ static inline struct threadpool_instance *impl_from_TP_CALLBACK_INSTANCE( TP_CAL +@@ -295,7 +347,8 @@ static inline struct threadpool_instance *impl_from_TP_CALLBACK_INSTANCE( TP_CAL static void CALLBACK threadpool_worker_proc( void *param ); static void CALLBACK timerqueue_thread_proc( void *param ); -+static void CALLBACK waitqueue_thread_proc( void *param ); - static NTSTATUS tp_threadpool_alloc( struct threadpool **out ); - static void tp_threadpool_shutdown( struct threadpool *pool ); - static BOOL tp_threadpool_release( struct threadpool *pool ); -static void tp_object_submit( struct threadpool_object *object ); ++static void CALLBACK waitqueue_thread_proc( void *param ); +static void tp_object_submit( struct threadpool_object *object, BOOL success ); static void tp_object_shutdown( struct threadpool_object *object ); static BOOL tp_object_release( struct threadpool_object *object ); - static void tp_instance_initialize( struct threadpool_instance *instance, struct threadpool_object *object ); -@@ -347,7 +400,7 @@ update_timer: + static struct threadpool *default_threadpool = NULL; +@@ -1349,7 +1402,7 @@ update_timer: RtlLeaveCriticalSection( &timerqueue.cs ); if (submit_timer) @@ -163,7 +160,7 @@ index a1089a4..9b2a0c8 100644 } static void CALLBACK timerqueue_thread_proc( void *param ) -@@ -374,7 +427,7 @@ static void CALLBACK timerqueue_thread_proc( void *param ) +@@ -1376,7 +1429,7 @@ static void CALLBACK timerqueue_thread_proc( void *param ) /* Queue a new callback in one of the worker threads */ list_remove( &timer->u.timer.timer_entry ); @@ -172,7 +169,7 @@ index a1089a4..9b2a0c8 100644 /* Requeue the timer, except its marked for shutdown */ if (!timer->shutdown && timer->u.timer.period) -@@ -440,6 +493,301 @@ static void CALLBACK timerqueue_thread_proc( void *param ) +@@ -1442,6 +1495,301 @@ static void CALLBACK timerqueue_thread_proc( void *param ) RtlLeaveCriticalSection( &timerqueue.cs ); } @@ -471,10 +468,58 @@ index a1089a4..9b2a0c8 100644 + RtlFreeHeap( GetProcessHeap(), 0, bucket ); +} + - static struct threadpool *default_threadpool = NULL; + /* allocate a new threadpool (with at least one worker thread) */ + static NTSTATUS tp_threadpool_alloc( struct threadpool **out ) + { +@@ -1633,7 +1981,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa + * to the cleanup group. As soon as the cleanup group members are released ->shutdown + * will be set, and tp_object_submit would fail with an assertion. */ + if (simple_cb) +- tp_object_submit( object ); ++ tp_object_submit( object, FALSE ); - /* allocates or returns the default threadpool */ -@@ -536,6 +884,7 @@ static void CALLBACK threadpool_worker_proc( void *param ) + if (object->group) + { +@@ -1654,7 +2002,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa + } + + /* submits an object to a threadpool */ +-static void tp_object_submit( struct threadpool_object *object ) ++static void tp_object_submit( struct threadpool_object *object, BOOL success ) + { + struct threadpool *pool = object->pool; + +@@ -1689,6 +2037,10 @@ out: + if (!object->num_pending_callbacks++) + list_add_tail( &pool->pool, &object->pool_entry ); + ++ /* increment success counter by one */ ++ if (object->type == TP_OBJECT_TYPE_WAIT && success) ++ object->u.wait.signaled++; ++ + RtlLeaveCriticalSection( &pool->cs ); + } + +@@ -1707,6 +2059,9 @@ static void tp_object_cancel( struct threadpool_object *object, BOOL group_cance + list_remove( &object->pool_entry ); + } + ++ if (object->type == TP_OBJECT_TYPE_WAIT) ++ object->u.wait.signaled = 0; ++ + RtlLeaveCriticalSection( &pool->cs ); + + /* Execute group cancellation callback if defined, and if this was actually a group cancel. */ +@@ -1740,6 +2095,8 @@ static void tp_object_shutdown( struct threadpool_object *object ) + { + if (object->type == TP_OBJECT_TYPE_TIMER) + tp_timerqueue_release( object ); ++ else if (object->type == TP_OBJECT_TYPE_WAIT) ++ tp_waitqueue_release( object ); + + object->shutdown = TRUE; + } +@@ -1905,6 +2262,7 @@ static void CALLBACK threadpool_worker_proc( void *param ) struct threadpool_instance instance; TP_CALLBACK_INSTANCE *cb_instance = (TP_CALLBACK_INSTANCE *)&instance; struct threadpool *pool = param; @@ -482,7 +527,7 @@ index a1089a4..9b2a0c8 100644 LARGE_INTEGER timeout; struct list *ptr; -@@ -553,6 +902,18 @@ static void CALLBACK threadpool_worker_proc( void *param ) +@@ -1922,6 +2280,18 @@ static void CALLBACK threadpool_worker_proc( void *param ) if (--object->num_pending_callbacks) list_add_tail( &pool->pool, &object->pool_entry ); @@ -501,7 +546,7 @@ index a1089a4..9b2a0c8 100644 /* Leave critical section and do the actual callback. */ object->num_running_callbacks++; pool->num_busy_workers++; -@@ -588,6 +949,15 @@ static void CALLBACK threadpool_worker_proc( void *param ) +@@ -1957,6 +2327,15 @@ static void CALLBACK threadpool_worker_proc( void *param ) break; } @@ -517,26 +562,21 @@ index a1089a4..9b2a0c8 100644 default: assert(0); break; -@@ -687,7 +1057,7 @@ static void tp_object_initialize( struct threadpool_object *object, struct threa - * to the cleanup group. As soon as the cleanup group members are released ->shutdown - * will be set, and tp_object_submit would fail with an assertion. */ - if (simple_cb) -- tp_object_submit( object ); -+ tp_object_submit( object, FALSE ); - - if (object->group) - { -@@ -800,8 +1170,45 @@ static NTSTATUS tp_object_alloc_timer( struct threadpool_object **out, PTP_TIMER - return STATUS_SUCCESS; +@@ -2073,6 +2452,48 @@ NTSTATUS WINAPI TpAllocTimer( TP_TIMER **out, PTP_TIMER_CALLBACK callback, PVOID } -+static NTSTATUS tp_object_alloc_wait( struct threadpool_object **out, PTP_WAIT_CALLBACK callback, -+ PVOID userdata, TP_CALLBACK_ENVIRON *environment ) + /*********************************************************************** ++ * TpAllocWait (NTDLL.@) ++ */ ++NTSTATUS WINAPI TpAllocWait( TP_WAIT **out, PTP_WAIT_CALLBACK callback, PVOID userdata, ++ TP_CALLBACK_ENVIRON *environment ) +{ + struct threadpool_object *object; + struct threadpool *pool = NULL; + NTSTATUS status; + ++ TRACE("%p %p %p %p\n", out, callback, userdata, environment); ++ + if (environment) + pool = (struct threadpool *)environment->Pool; + @@ -563,66 +603,15 @@ index a1089a4..9b2a0c8 100644 + + tp_object_initialize( object, pool, userdata, environment ); + -+ *out = object; ++ *out = (TP_WAIT *)object; + return STATUS_SUCCESS; +} -+ - /* submits an object to a threadpool */ --static void tp_object_submit( struct threadpool_object *object ) -+static void tp_object_submit( struct threadpool_object *object, BOOL success ) - { - struct threadpool *pool = object->pool; - -@@ -836,6 +1243,10 @@ out: - if (!object->num_pending_callbacks++) - list_add_tail( &pool->pool, &object->pool_entry ); - -+ /* increment success counter by one */ -+ if (object->type == TP_OBJECT_TYPE_WAIT && success) -+ object->u.wait.signaled++; -+ - RtlLeaveCriticalSection( &pool->cs ); - } - -@@ -854,6 +1265,9 @@ static void tp_object_cancel( struct threadpool_object *object, BOOL group_cance - list_remove( &object->pool_entry ); - } - -+ if (object->type == TP_OBJECT_TYPE_WAIT) -+ object->u.wait.signaled = 0; -+ - RtlLeaveCriticalSection( &pool->cs ); - - /* Execute group cancellation callback if defined, and if this was actually a group cancel. */ -@@ -887,6 +1301,8 @@ static void tp_object_shutdown( struct threadpool_object *object ) - { - if (object->type == TP_OBJECT_TYPE_TIMER) - tp_timerqueue_release( object ); -+ else if (object->type == TP_OBJECT_TYPE_WAIT) -+ tp_waitqueue_release( object ); - - object->shutdown = TRUE; - } -@@ -1191,6 +1607,18 @@ NTSTATUS WINAPI TpAllocTimer( TP_TIMER **out, PTP_TIMER_CALLBACK callback, PVOID - } - - /*********************************************************************** -+ * TpAllocWait (NTDLL.@) -+ */ -+NTSTATUS WINAPI TpAllocWait( TP_WAIT **out, PTP_WAIT_CALLBACK callback, PVOID userdata, -+ TP_CALLBACK_ENVIRON *environment ) -+{ -+ TRACE("%p %p %p %p\n", out, callback, userdata, environment); -+ -+ return tp_object_alloc_wait( (struct threadpool_object **)out, callback, -+ userdata, environment ); -+} + +/*********************************************************************** * TpAllocWork (NTDLL.@) */ NTSTATUS WINAPI TpAllocWork( TP_WORK **out, PTP_WORK_CALLBACK callback, PVOID userdata, -@@ -1352,7 +1780,7 @@ VOID WINAPI TpPostWork( TP_WORK *work ) +@@ -2255,7 +2676,7 @@ VOID WINAPI TpPostWork( TP_WORK *work ) if (this) { @@ -631,7 +620,7 @@ index a1089a4..9b2a0c8 100644 } } -@@ -1416,6 +1844,21 @@ VOID WINAPI TpReleaseTimer( TP_TIMER *timer ) +@@ -2369,6 +2790,21 @@ VOID WINAPI TpReleaseTimer( TP_TIMER *timer ) } /*********************************************************************** @@ -653,7 +642,7 @@ index a1089a4..9b2a0c8 100644 * TpReleaseWork (NTDLL.@) */ VOID WINAPI TpReleaseWork( TP_WORK *work ) -@@ -1478,6 +1921,20 @@ VOID WINAPI TpSetTimer( TP_TIMER *timer, LARGE_INTEGER *timeout, LONG period, LO +@@ -2431,6 +2867,20 @@ VOID WINAPI TpSetTimer( TP_TIMER *timer, LARGE_INTEGER *timeout, LONG period, LO } /*********************************************************************** @@ -674,7 +663,7 @@ index a1089a4..9b2a0c8 100644 * TpSimpleTryPost (NTDLL.@) */ NTSTATUS WINAPI TpSimpleTryPost( PTP_SIMPLE_CALLBACK callback, PVOID userdata, -@@ -1504,6 +1961,21 @@ VOID WINAPI TpWaitForTimer( TP_TIMER *timer, BOOL cancel_pending ) +@@ -2478,6 +2928,21 @@ VOID WINAPI TpWaitForTimer( TP_TIMER *timer, BOOL cancel_pending ) } /*********************************************************************** @@ -697,5 +686,5 @@ index a1089a4..9b2a0c8 100644 */ VOID WINAPI TpWaitForWork( TP_WORK *work, BOOL cancel_pending ) -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0019-ntdll-tests-Add-tests-for-threadpool-wait-objects.patch b/patches/ntdll-Vista_Threadpool/0019-ntdll-tests-Add-tests-for-threadpool-wait-objects.patch index e6592a13..903c0c08 100644 --- a/patches/ntdll-Vista_Threadpool/0019-ntdll-tests-Add-tests-for-threadpool-wait-objects.patch +++ b/patches/ntdll-Vista_Threadpool/0019-ntdll-tests-Add-tests-for-threadpool-wait-objects.patch @@ -1,4 +1,4 @@ -From be47a4f14f26fde351a5a2d0bd9d613bb56a1268 Mon Sep 17 00:00:00 2001 +From 274f80bef1283a43868aedf0ea55f5b842ceff86 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Fri, 6 Feb 2015 20:09:41 +0100 Subject: ntdll/tests: Add tests for threadpool wait objects. @@ -313,5 +313,5 @@ index b44b0f5..91d1b95 100644 /* FIXME: Make sure worker threads have terminated before. */ Sleep(100); -- -2.3.0 +2.3.3 diff --git a/patches/ntdll-Vista_Threadpool/0020-kernel32-Forward-threadpool-wait-functions-to-ntdll.patch b/patches/ntdll-Vista_Threadpool/0020-kernel32-Forward-threadpool-wait-functions-to-ntdll.patch index 986fb48b..c1ffb3b8 100644 --- a/patches/ntdll-Vista_Threadpool/0020-kernel32-Forward-threadpool-wait-functions-to-ntdll.patch +++ b/patches/ntdll-Vista_Threadpool/0020-kernel32-Forward-threadpool-wait-functions-to-ntdll.patch @@ -1,4 +1,4 @@ -From 921fe6b2ea88ca6be056a8fd733ae099f2839eb5 Mon Sep 17 00:00:00 2001 +From bd2b6f3c1602f5bd24781ae12052994cae0bad73 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Fri, 6 Feb 2015 20:24:27 +0100 Subject: kernel32: Forward threadpool wait functions to ntdll. @@ -10,7 +10,7 @@ Subject: kernel32: Forward threadpool wait functions to ntdll. 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec -index 54d83da..abee11b 100644 +index f65f894..4eba956 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -233,7 +233,7 @@ @@ -50,10 +50,10 @@ index 54d83da..abee11b 100644 @ stdcall WaitNamedPipeA (str long) @ stdcall WaitNamedPipeW (wstr long) diff --git a/dlls/kernel32/thread.c b/dlls/kernel32/thread.c -index 085b011..77037ef 100644 +index 945fe0b..89b0b60 100644 --- a/dlls/kernel32/thread.c +++ b/dlls/kernel32/thread.c -@@ -894,6 +894,27 @@ PTP_TIMER WINAPI CreateThreadpoolTimer( PTP_TIMER_CALLBACK callback, PVOID userd +@@ -923,6 +923,27 @@ PTP_TIMER WINAPI CreateThreadpoolTimer( PTP_TIMER_CALLBACK callback, PVOID userd } /*********************************************************************** @@ -81,7 +81,7 @@ index 085b011..77037ef 100644 * CreateThreadpoolWork (KERNEL32.@) */ PTP_WORK WINAPI CreateThreadpoolWork( PTP_WORK_CALLBACK callback, PVOID userdata, -@@ -932,3 +953,25 @@ VOID WINAPI SetThreadpoolTimer( TP_TIMER *timer, FILETIME *due_time, +@@ -961,3 +982,25 @@ VOID WINAPI SetThreadpoolTimer( TP_TIMER *timer, FILETIME *due_time, TpSetTimer( timer, due_time ? &timeout : NULL, period, window_length ); } @@ -108,10 +108,10 @@ index 085b011..77037ef 100644 + TpSetWait( wait, handle, due_time ? &timeout : NULL ); +} diff --git a/include/winternl.h b/include/winternl.h -index 7608d21..dca7f46 100644 +index 4f16d24..ee38c48 100644 --- a/include/winternl.h +++ b/include/winternl.h -@@ -2609,6 +2609,7 @@ NTSYSAPI NTSTATUS WINAPI RtlLargeIntegerToChar(const ULONGLONG *,ULONG,ULONG,PC +@@ -2601,6 +2601,7 @@ NTSYSAPI NTSTATUS WINAPI RtlLargeIntegerToChar(const ULONGLONG *,ULONG,ULONG,PC NTSYSAPI NTSTATUS WINAPI TpAllocCleanupGroup(TP_CLEANUP_GROUP **); NTSYSAPI NTSTATUS WINAPI TpAllocPool(TP_POOL **,PVOID); NTSYSAPI NTSTATUS WINAPI TpAllocTimer(TP_TIMER **,PTP_TIMER_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *); @@ -119,7 +119,7 @@ index 7608d21..dca7f46 100644 NTSYSAPI NTSTATUS WINAPI TpAllocWork(TP_WORK **,PTP_WORK_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *); NTSYSAPI void WINAPI TpCallbackLeaveCriticalSectionOnCompletion(TP_CALLBACK_INSTANCE *,RTL_CRITICAL_SECTION *); NTSYSAPI NTSTATUS WINAPI TpCallbackMayRunLong(TP_CALLBACK_INSTANCE *); -@@ -2623,12 +2624,15 @@ NTSYSAPI void WINAPI TpReleaseCleanupGroup(TP_CLEANUP_GROUP *); +@@ -2615,12 +2616,15 @@ NTSYSAPI void WINAPI TpReleaseCleanupGroup(TP_CLEANUP_GROUP *); NTSYSAPI void WINAPI TpReleaseCleanupGroupMembers(TP_CLEANUP_GROUP *,BOOL,PVOID); NTSYSAPI void WINAPI TpReleasePool(TP_POOL *); NTSYSAPI void WINAPI TpReleaseTimer(TP_TIMER *); @@ -136,5 +136,5 @@ index 7608d21..dca7f46 100644 /* Wine internal functions */ -- -2.3.0 +2.3.3 diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index f8e72365..f7f24d08 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -3197,8 +3197,8 @@ fi # | * [#37306] Implement threadpool timers # | # | Modified files: -# | * dlls/kernel32/kernel32.spec, dlls/kernel32/tests/thread.c, dlls/kernel32/thread.c, dlls/ntdll/Makefile.in, -# | dlls/ntdll/ntdll.spec, dlls/ntdll/tests/threadpool.c, dlls/ntdll/threadpool2.c, include/winternl.h +# | * dlls/kernel32/kernel32.spec, dlls/kernel32/tests/thread.c, dlls/kernel32/thread.c, dlls/ntdll/ntdll.spec, +# | dlls/ntdll/tests/threadpool.c, dlls/ntdll/threadpool.c, include/winternl.h # | if test "$enable_ntdll_Vista_Threadpool" -eq 1; then patch_apply ntdll-Vista_Threadpool/0001-ntdll-Implement-TpSimpleTryPost-and-basic-threadpool.patch