[PATCH 1/3] ntdll: Add threadpool stack information exports.

Nikolay Sivov nsivov at codeweavers.com
Wed Feb 12 00:42:45 CST 2020


Signed-off-by: Nikolay Sivov <nsivov at 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 *);
-- 
2.25.0




More information about the wine-devel mailing list