Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
Stack sizes are only stored as pool parameters for now.
These are meant to replace 178405 and 178406.
dlls/ntdll/ntdll.spec | 2 ++ dlls/ntdll/tests/threadpool.c | 32 ++++++++++++++++++++++ dlls/ntdll/threadpool.c | 50 ++++++++++++++++++++++++++++++++--- include/winternl.h | 2 ++ 4 files changed, 82 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index fe36235bda..7aa953ca6c 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -1070,6 +1070,7 @@ @ stdcall TpDisassociateCallback(ptr) @ stdcall TpIsTimerSet(ptr) @ stdcall TpPostWork(ptr) +@ stdcall TpQueryPoolStackInformation(ptr ptr) @ stdcall TpReleaseCleanupGroup(ptr) @ stdcall TpReleaseCleanupGroupMembers(ptr long ptr) @ stdcall TpReleasePool(ptr) @@ -1078,6 +1079,7 @@ @ stdcall TpReleaseWork(ptr) @ stdcall TpSetPoolMaxThreads(ptr long) @ stdcall TpSetPoolMinThreads(ptr long) +@ stdcall TpSetPoolStackInformation(ptr ptr) @ stdcall TpSetTimer(ptr ptr long long) @ stdcall TpSetWait(ptr long ptr) @ stdcall TpSimpleTryPost(ptr ptr ptr) diff --git a/dlls/ntdll/tests/threadpool.c b/dlls/ntdll/tests/threadpool.c index bf5493cac0..912a77b82a 100644 --- a/dlls/ntdll/tests/threadpool.c +++ b/dlls/ntdll/tests/threadpool.c @@ -30,6 +30,7 @@ static NTSTATUS (WINAPI *pTpCallbackMayRunLong)(TP_CALLBACK_INSTANCE *); static VOID (WINAPI *pTpCallbackReleaseSemaphoreOnCompletion)(TP_CALLBACK_INSTANCE *,HANDLE,DWORD); static VOID (WINAPI *pTpDisassociateCallback)(TP_CALLBACK_INSTANCE *); static BOOL (WINAPI *pTpIsTimerSet)(TP_TIMER *); +static NTSTATUS (WINAPI *pTpQueryPoolStackInformation)(TP_POOL *, TP_POOL_STACK_INFORMATION *info); static VOID (WINAPI *pTpReleaseWait)(TP_WAIT *); static VOID (WINAPI *pTpPostWork)(TP_WORK *); static VOID (WINAPI *pTpReleaseCleanupGroup)(TP_CLEANUP_GROUP *); @@ -37,6 +38,7 @@ static VOID (WINAPI *pTpReleaseCleanupGroupMembers)(TP_CLEANUP_GROUP *,BOOL, static VOID (WINAPI *pTpReleasePool)(TP_POOL *); static VOID (WINAPI *pTpReleaseTimer)(TP_TIMER *); static VOID (WINAPI *pTpReleaseWork)(TP_WORK *); +static NTSTATUS (WINAPI *pTpSetPoolStackInformation)(TP_POOL *, TP_POOL_STACK_INFORMATION *info); static VOID (WINAPI *pTpSetPoolMaxThreads)(TP_POOL *,DWORD); static VOID (WINAPI *pTpSetTimer)(TP_TIMER *,LARGE_INTEGER *,LONG,LONG); static VOID (WINAPI *pTpSetWait)(TP_WAIT *,HANDLE,LARGE_INTEGER *); @@ -72,12 +74,14 @@ static BOOL init_threadpool(void) NTDLL_GET_PROC(TpDisassociateCallback); NTDLL_GET_PROC(TpIsTimerSet); NTDLL_GET_PROC(TpPostWork); + NTDLL_GET_PROC(TpQueryPoolStackInformation); NTDLL_GET_PROC(TpReleaseCleanupGroup); NTDLL_GET_PROC(TpReleaseCleanupGroupMembers); NTDLL_GET_PROC(TpReleasePool); NTDLL_GET_PROC(TpReleaseTimer); NTDLL_GET_PROC(TpReleaseWait); NTDLL_GET_PROC(TpReleaseWork); + NTDLL_GET_PROC(TpSetPoolStackInformation); NTDLL_GET_PROC(TpSetPoolMaxThreads); NTDLL_GET_PROC(TpSetTimer); NTDLL_GET_PROC(TpSetWait); @@ -601,6 +605,7 @@ static void CALLBACK work2_cb(TP_CALLBACK_INSTANCE *instance, void *userdata, TP
static void test_tp_work(void) { + TP_POOL_STACK_INFORMATION stack_info, stack_info2; TP_CALLBACK_ENVIRON environment; TP_WORK *work; TP_POOL *pool; @@ -615,6 +620,33 @@ static void test_tp_work(void) ok(pool != NULL, "expected pool != NULL\n"); pTpSetPoolMaxThreads(pool, 1);
+ if (pTpQueryPoolStackInformation) + { + status = pTpQueryPoolStackInformation(pool, NULL); + ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %#x.\n", status); + + status = pTpSetPoolStackInformation(pool, NULL); + ok(status == STATUS_INVALID_PARAMETER, "Unexpected status %#x.\n", status); + + status = pTpQueryPoolStackInformation(pool, &stack_info); + ok(!status, "Failed to get stack information, status %#x.\n", status); + ok(stack_info.StackReserve > 0 && stack_info.StackCommit > 0, "Unexpected stack info.\n"); + + stack_info2.StackReserve = 0; + stack_info2.StackCommit = 0; + status = pTpSetPoolStackInformation(pool, &stack_info2); + ok(!status, "Failed to get stack information, status %#x.\n", status); + + memset(&stack_info2, 0xcc, sizeof(stack_info2)); + status = pTpQueryPoolStackInformation(pool, &stack_info2); + ok(!status, "Failed to get stack information, status %#x.\n", status); + ok(!stack_info2.StackReserve && !stack_info2.StackCommit, "Unexpected stack info.\n"); + + /* Restore to original default values. */ + status = pTpSetPoolStackInformation(pool, &stack_info); + ok(!status, "Failed to get stack information, status %#x.\n", status); + } + /* allocate new work item */ work = NULL; memset(&environment, 0, sizeof(environment)); diff --git a/dlls/ntdll/threadpool.c b/dlls/ntdll/threadpool.c index a7ad321a8b..b7a096f981 100644 --- a/dlls/ntdll/threadpool.c +++ b/dlls/ntdll/threadpool.c @@ -131,6 +131,7 @@ struct threadpool int min_workers; int num_workers; int num_busy_workers; + TP_POOL_STACK_INFORMATION stack_info; };
enum threadpool_objtype @@ -1648,6 +1649,7 @@ static void tp_waitqueue_unlock( struct threadpool_object *wait ) */ static NTSTATUS tp_threadpool_alloc( struct threadpool **out ) { + IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress ); struct threadpool *pool; unsigned int i;
@@ -1666,10 +1668,12 @@ static NTSTATUS tp_threadpool_alloc( struct threadpool **out ) list_init( &pool->pools[i] ); RtlInitializeConditionVariable( &pool->update_event );
- pool->max_workers = 500; - pool->min_workers = 0; - pool->num_workers = 0; - pool->num_busy_workers = 0; + pool->max_workers = 500; + pool->min_workers = 0; + pool->num_workers = 0; + pool->num_busy_workers = 0; + pool->stack_info.StackReserve = nt->OptionalHeader.SizeOfStackReserve; + pool->stack_info.StackCommit = nt->OptionalHeader.SizeOfStackCommit;
TRACE( "allocated threadpool %p\n", pool );
@@ -2989,3 +2993,41 @@ VOID WINAPI TpWaitForWork( TP_WORK *work, BOOL cancel_pending ) tp_object_cancel( this ); tp_object_wait( this, FALSE ); } + +/*********************************************************************** + * TpSetPoolStackInformation (NTDLL.@) + */ +NTSTATUS WINAPI TpSetPoolStackInformation( TP_POOL *pool, TP_POOL_STACK_INFORMATION *stack_info ) +{ + struct threadpool *this = impl_from_TP_POOL( pool ); + + TRACE( "%p %p\n", pool, stack_info ); + + if (!stack_info) + return STATUS_INVALID_PARAMETER; + + RtlEnterCriticalSection( &this->cs ); + this->stack_info = *stack_info; + RtlLeaveCriticalSection( &this->cs ); + + return STATUS_SUCCESS; +} + +/*********************************************************************** + * TpQueryPoolStackInformation (NTDLL.@) + */ +NTSTATUS WINAPI TpQueryPoolStackInformation( TP_POOL *pool, TP_POOL_STACK_INFORMATION *stack_info ) +{ + struct threadpool *this = impl_from_TP_POOL( pool ); + + TRACE( "%p %p\n", pool, stack_info ); + + if (!stack_info) + return STATUS_INVALID_PARAMETER; + + RtlEnterCriticalSection( &this->cs ); + *stack_info = this->stack_info; + RtlLeaveCriticalSection( &this->cs ); + + return STATUS_SUCCESS; +} diff --git a/include/winternl.h b/include/winternl.h index ea6707714d..5298eaa0f7 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -3021,6 +3021,7 @@ NTSYSAPI void WINAPI TpCallbackUnloadDllOnCompletion(TP_CALLBACK_INSTANCE * NTSYSAPI void WINAPI TpDisassociateCallback(TP_CALLBACK_INSTANCE *); NTSYSAPI BOOL WINAPI TpIsTimerSet(TP_TIMER *); NTSYSAPI void WINAPI TpPostWork(TP_WORK *); +NTSYSAPI NTSTATUS WINAPI TpQueryPoolStackInformation(TP_POOL *, TP_POOL_STACK_INFORMATION *stack_info); NTSYSAPI void WINAPI TpReleaseCleanupGroup(TP_CLEANUP_GROUP *); NTSYSAPI void WINAPI TpReleaseCleanupGroupMembers(TP_CLEANUP_GROUP *,BOOL,PVOID); NTSYSAPI void WINAPI TpReleasePool(TP_POOL *); @@ -3029,6 +3030,7 @@ NTSYSAPI void WINAPI TpReleaseWait(TP_WAIT *); NTSYSAPI void WINAPI TpReleaseWork(TP_WORK *); NTSYSAPI void WINAPI TpSetPoolMaxThreads(TP_POOL *,DWORD); NTSYSAPI BOOL WINAPI TpSetPoolMinThreads(TP_POOL *,DWORD); +NTSYSAPI NTSTATUS WINAPI TpSetPoolStackInformation(TP_POOL *, TP_POOL_STACK_INFORMATION *stack_info); NTSYSAPI void WINAPI TpSetTimer(TP_TIMER *, LARGE_INTEGER *,LONG,LONG); NTSYSAPI void WINAPI TpSetWait(TP_WAIT *,HANDLE,LARGE_INTEGER *); NTSYSAPI NTSTATUS WINAPI TpSimpleTryPost(PTP_SIMPLE_CALLBACK,PVOID,TP_CALLBACK_ENVIRON *);