Alexandre Julliard : kernelbase: Implement SetThreadStackGuarantee().

Alexandre Julliard julliard at winehq.org
Mon Aug 26 15:47:27 CDT 2019


Module: wine
Branch: master
Commit: 505be3a0a2afeae3cebeaad48fc5f32e0b0336b7
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=505be3a0a2afeae3cebeaad48fc5f32e0b0336b7

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Sat Aug 24 10:03:51 2019 +0200

kernelbase: Implement SetThreadStackGuarantee().

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/tests/thread.c | 58 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/kernelbase/thread.c     | 15 ++++++++++--
 include/winternl.h           |  4 +--
 3 files changed, 73 insertions(+), 4 deletions(-)

diff --git a/dlls/kernel32/tests/thread.c b/dlls/kernel32/tests/thread.c
index 331db9b..f87f770 100644
--- a/dlls/kernel32/tests/thread.c
+++ b/dlls/kernel32/tests/thread.c
@@ -82,6 +82,7 @@ static HANDLE (WINAPI *pOpenThread)(DWORD,BOOL,DWORD);
 static BOOL (WINAPI *pQueueUserWorkItem)(LPTHREAD_START_ROUTINE,PVOID,ULONG);
 static DWORD (WINAPI *pSetThreadIdealProcessor)(HANDLE,DWORD);
 static BOOL (WINAPI *pSetThreadPriorityBoost)(HANDLE,BOOL);
+static BOOL (WINAPI *pSetThreadStackGuarantee)(ULONG*);
 static BOOL (WINAPI *pRegisterWaitForSingleObject)(PHANDLE,HANDLE,WAITORTIMERCALLBACK,PVOID,ULONG,ULONG);
 static BOOL (WINAPI *pUnregisterWait)(HANDLE);
 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL);
@@ -1016,6 +1017,61 @@ static VOID test_GetCurrentThreadStackLimits(void)
     ok(high == (ULONG_PTR)NtCurrentTeb()->Tib.StackBase, "expected %p, got %lx\n", NtCurrentTeb()->Tib.StackBase, high);
 }
 
+static void test_SetThreadStackGuarantee(void)
+{
+    ULONG size;
+    BOOL ret;
+
+    if (!pSetThreadStackGuarantee)
+    {
+        win_skip("SetThreadStackGuarantee not available.\n");
+        return;
+    }
+    size = 0;
+    ret = pSetThreadStackGuarantee( &size );
+    ok( ret, "failed err %u\n", GetLastError() );
+    ok( size == 0, "wrong size %u\n", size );
+    ok( NtCurrentTeb()->GuaranteedStackBytes == 0, "wrong teb %u\n",
+        NtCurrentTeb()->GuaranteedStackBytes );
+    size = 0xdeadbef;
+    ret = pSetThreadStackGuarantee( &size );
+    ok( !ret, "succeeded\n" );
+    ok( GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_INVALID_ADDRESS,
+        "wrong error %u\n", GetLastError());
+    ok( size == 0, "wrong size %u\n", size );
+    ok( NtCurrentTeb()->GuaranteedStackBytes == 0, "wrong teb %u\n",
+        NtCurrentTeb()->GuaranteedStackBytes );
+    size = 200;
+    ret = pSetThreadStackGuarantee( &size );
+    ok( ret, "failed err %u\n", GetLastError() );
+    ok( size == 0, "wrong size %u\n", size );
+    ok( NtCurrentTeb()->GuaranteedStackBytes == 4096 * sizeof(void *) / 4, "wrong teb %u\n",
+        NtCurrentTeb()->GuaranteedStackBytes );
+    size = 5000;
+    ret = pSetThreadStackGuarantee( &size );
+    ok( ret, "failed err %u\n", GetLastError() );
+    ok( size == 4096 * sizeof(void *) / 4, "wrong size %u\n", size );
+    ok( NtCurrentTeb()->GuaranteedStackBytes == 8192, "wrong teb %u\n",
+        NtCurrentTeb()->GuaranteedStackBytes );
+    size = 2000;
+    ret = pSetThreadStackGuarantee( &size );
+    ok( ret, "failed err %u\n", GetLastError() );
+    ok( size == 8192, "wrong size %u\n", size );
+    ok( NtCurrentTeb()->GuaranteedStackBytes == 8192, "wrong teb %u\n",
+        NtCurrentTeb()->GuaranteedStackBytes );
+    size = 10000;
+    ret = pSetThreadStackGuarantee( &size );
+    ok( ret, "failed err %u\n", GetLastError() );
+    ok( size == 8192, "wrong size %u\n", size );
+    ok( NtCurrentTeb()->GuaranteedStackBytes == 12288, "wrong teb %u\n",
+        NtCurrentTeb()->GuaranteedStackBytes );
+    ret = pSetThreadStackGuarantee( &size );
+    ok( ret, "failed err %u\n", GetLastError() );
+    ok( size == 12288, "wrong size %u\n", size );
+    ok( NtCurrentTeb()->GuaranteedStackBytes == 12288, "wrong teb %u\n",
+        NtCurrentTeb()->GuaranteedStackBytes );
+}
+
 static VOID test_GetThreadExitCode(void)
 {
     DWORD exitCode, threadid;
@@ -2029,6 +2085,7 @@ static void init_funcs(void)
     X(QueueUserWorkItem);
     X(SetThreadIdealProcessor);
     X(SetThreadPriorityBoost);
+    X(SetThreadStackGuarantee);
     X(RegisterWaitForSingleObject);
     X(UnregisterWait);
     X(IsWow64Process);
@@ -2110,6 +2167,7 @@ START_TEST(thread)
    test_CreateThread_stack();
    test_thread_priority();
    test_GetCurrentThreadStackLimits();
+   test_SetThreadStackGuarantee();
    test_GetThreadTimes();
    test_thread_processor();
    test_GetThreadExitCode();
diff --git a/dlls/kernelbase/thread.c b/dlls/kernelbase/thread.c
index cf8e6be..518ea93 100644
--- a/dlls/kernelbase/thread.c
+++ b/dlls/kernelbase/thread.c
@@ -470,8 +470,19 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetThreadPriorityBoost( HANDLE thread, BOOL disabl
  */
 BOOL WINAPI DECLSPEC_HOTPATCH SetThreadStackGuarantee( ULONG *size )
 {
-    static int once;
-    if (once++ == 0) FIXME("(%p): stub\n", size);
+    ULONG prev_size = NtCurrentTeb()->GuaranteedStackBytes;
+    ULONG new_size = (*size + 4095) & ~4095;
+
+    /* at least 2 pages on 64-bit */
+    if (sizeof(void *) > sizeof(int)) new_size = max( new_size, 8192 );
+
+    *size = prev_size;
+    if (new_size >= (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->DeallocationStack)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+    if (new_size > prev_size) NtCurrentTeb()->GuaranteedStackBytes = (new_size + 4095) & ~4095;
     return TRUE;
 }
 
diff --git a/include/winternl.h b/include/winternl.h
index 0ebfe8e..4715b05 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -397,8 +397,8 @@ typedef struct _TEB
     PVOID                        WinSockData;                       /* f6c/1738 */
     ULONG                        GdiBatchCount;                     /* f70/1740 */
     ULONG                        Spare2;                            /* f74/1744 */
-    PVOID                        Spare3;                            /* f78/1748 */
-    PVOID                        Spare4;                            /* f7c/1750 */
+    ULONG                        GuaranteedStackBytes;              /* f78/1748 */
+    PVOID                        ReservedForPerf;                   /* f7c/1750 */
     PVOID                        ReservedForOle;                    /* f80/1758 */
     ULONG                        WaitingOnLoaderLock;               /* f84/1760 */
     PVOID                        Reserved5[3];                      /* f88/1768 */




More information about the wine-cvs mailing list