Alexandre Julliard : ntdll: Stop sharing the thread counter with the Unix library.

Alexandre Julliard julliard at winehq.org
Mon Jun 29 14:59:20 CDT 2020


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jun 29 12:09:25 2020 +0200

ntdll: Stop sharing the thread counter with the Unix library.

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

---

 dlls/ntdll/tests/info.c        | 31 +++++++++++++++++++++++++++++++
 dlls/ntdll/thread.c            |  9 +++++----
 dlls/ntdll/unix/thread.c       | 18 +++++++++---------
 dlls/ntdll/unix/unix_private.h |  2 +-
 dlls/ntdll/unixlib.h           |  4 ++--
 5 files changed, 48 insertions(+), 16 deletions(-)

diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index eaf2f1a45b..4de562b994 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -2670,6 +2670,36 @@ static void test_thread_lookup(void)
        "NtOpenThread returned %#x\n", status);
 }
 
+static void test_thread_info(void)
+{
+    NTSTATUS status;
+    ULONG len, data;
+
+    len = 0xdeadbeef;
+    data = 0xcccccccc;
+    status = pNtQueryInformationThread( GetCurrentThread(), ThreadAmILastThread,
+                                        &data, sizeof(data), &len );
+    ok( !status, "failed %x\n", status );
+    ok( data == 0 || data == 1, "wrong data %x\n", data );
+    ok( len == sizeof(data), "wrong len %u\n", len );
+
+    len = 0xdeadbeef;
+    data = 0xcccccccc;
+    status = pNtQueryInformationThread( GetCurrentThread(), ThreadAmILastThread,
+                                        &data, sizeof(data) - 1, &len );
+    ok( status == STATUS_INFO_LENGTH_MISMATCH, "failed %x\n", status );
+    ok( data == 0xcccccccc, "wrong data %x\n", data );
+    ok( len == 0xdeadbeef, "wrong len %u\n", len );
+
+    len = 0xdeadbeef;
+    data = 0xcccccccc;
+    status = pNtQueryInformationThread( GetCurrentThread(), ThreadAmILastThread,
+                                        &data, sizeof(data) + 1, &len );
+    ok( status == STATUS_INFO_LENGTH_MISMATCH, "failed %x\n", status );
+    ok( data == 0xcccccccc, "wrong data %x\n", data );
+    ok( len == 0xdeadbeef, "wrong len %u\n", len );
+}
+
 START_TEST(info)
 {
     char **argv;
@@ -2827,4 +2857,5 @@ START_TEST(info)
     test_query_data_alignment();
 
     test_thread_lookup();
+    test_thread_info();
 }
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index ec94338f3f..7b8a717241 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -45,7 +45,6 @@ static PEB_LDR_DATA ldr;
 static RTL_BITMAP tls_bitmap;
 static RTL_BITMAP tls_expansion_bitmap;
 static RTL_BITMAP fls_bitmap;
-static int nb_threads = 1;
 
 struct ldt_copy *__wine_ldt_copy = NULL;
 
@@ -105,7 +104,7 @@ int __cdecl __wine_dbg_output( const char *str )
 TEB *thread_init( SIZE_T *info_size )
 {
     ULONG_PTR val;
-    TEB *teb = unix_funcs->init_threading( &nb_threads, &__wine_ldt_copy, info_size );
+    TEB *teb = unix_funcs->init_threading( &__wine_ldt_copy, info_size );
 
     peb = teb->Peb;
     peb->FastPebLock        = &peb_lock;
@@ -147,6 +146,8 @@ TEB *thread_init( SIZE_T *info_size )
  */
 void WINAPI RtlExitUserThread( ULONG status )
 {
+    ULONG last;
+
     if (status)  /* send the exit code to the server (0 is already the default) */
     {
         SERVER_START_REQ( terminate_thread )
@@ -158,12 +159,12 @@ void WINAPI RtlExitUserThread( ULONG status )
         SERVER_END_REQ;
     }
 
-    if (InterlockedDecrement( &nb_threads ) <= 0)
+    NtQueryInformationThread( GetCurrentThread(), ThreadAmILastThread, &last, sizeof(last), NULL );
+    if (last)
     {
         LdrShutdownProcess();
         unix_funcs->exit_process( status );
     }
-
     LdrShutdownThread();
     RtlFreeThreadActivationContextStack();
     for (;;) unix_funcs->exit_thread( status );
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c
index c583a08c05..2be8d2d3e2 100644
--- a/dlls/ntdll/unix/thread.c
+++ b/dlls/ntdll/unix/thread.c
@@ -60,7 +60,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
 #define PTHREAD_STACK_MIN 16384
 #endif
 
-static int *nb_threads;
+static int nb_threads = 1;
 
 static inline int get_unix_exit_code( NTSTATUS status )
 {
@@ -86,7 +86,7 @@ static void pthread_exit_wrapper( int status )
 /***********************************************************************
  *           init_threading
  */
-TEB * CDECL init_threading( int *nb_threads_ptr, struct ldt_copy **ldt_copy, SIZE_T *size )
+TEB * CDECL init_threading( struct ldt_copy **ldt_copy, SIZE_T *size )
 {
     TEB *teb;
     BOOL suspend;
@@ -95,7 +95,6 @@ TEB * CDECL init_threading( int *nb_threads_ptr, struct ldt_copy **ldt_copy, SIZ
     extern struct ldt_copy __wine_ldt_copy;
     *ldt_copy = &__wine_ldt_copy;
 #endif
-    nb_threads = nb_threads_ptr;
 
     teb = virtual_alloc_first_teb();
 
@@ -290,10 +289,10 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT
                            (char *)teb->Tib.StackBase + extra_stack - (char *)teb->DeallocationStack );
     pthread_attr_setguardsize( &pthread_attr, 0 );
     pthread_attr_setscope( &pthread_attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */
-    InterlockedIncrement( nb_threads );
+    InterlockedIncrement( &nb_threads );
     if (pthread_create( &pthread_id, &pthread_attr, (void * (*)(void *))start_thread, teb ))
     {
-        InterlockedDecrement( nb_threads );
+        InterlockedDecrement( &nb_threads );
         virtual_free_teb( teb );
         status = STATUS_NO_MEMORY;
     }
@@ -319,7 +318,7 @@ done:
 void abort_thread( int status )
 {
     pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
-    if (InterlockedDecrement( nb_threads ) <= 0) abort_process( status );
+    if (InterlockedDecrement( &nb_threads ) <= 0) abort_process( status );
     signal_exit_thread( status, pthread_exit_wrapper );
 }
 
@@ -987,6 +986,7 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
 
     case ThreadAmILastThread:
     {
+        if (length != sizeof(ULONG)) return STATUS_INFO_LENGTH_MISMATCH;
         SERVER_START_REQ( get_thread_info )
         {
             req->handle = wine_server_obj_handle( handle );
@@ -994,9 +994,9 @@ NTSTATUS WINAPI NtQueryInformationThread( HANDLE handle, THREADINFOCLASS class,
             status = wine_server_call( req );
             if (status == STATUS_SUCCESS)
             {
-                BOOLEAN last = reply->last;
-                if (data) memcpy( data, &last, min( length, sizeof(last) ));
-                if (ret_len) *ret_len = min( length, sizeof(last) );
+                ULONG last = reply->last;
+                if (data) memcpy( data, &last, sizeof(last) );
+                if (ret_len) *ret_len = sizeof(last);
             }
         }
         SERVER_END_REQ;
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h
index d6a15d5f7b..1f4c2da0c6 100644
--- a/dlls/ntdll/unix/unix_private.h
+++ b/dlls/ntdll/unix/unix_private.h
@@ -117,7 +117,7 @@ extern NTSTATUS CDECL server_handle_to_fd( HANDLE handle, unsigned int access, i
                                            unsigned int *options ) DECLSPEC_HIDDEN;
 extern void CDECL server_release_fd( HANDLE handle, int unix_fd ) DECLSPEC_HIDDEN;
 extern void CDECL server_init_process_done( void *relay ) DECLSPEC_HIDDEN;
-extern TEB * CDECL init_threading( int *nb_threads_ptr, struct ldt_copy **ldt_copy, SIZE_T *size ) DECLSPEC_HIDDEN;
+extern TEB * CDECL init_threading( struct ldt_copy **ldt_copy, SIZE_T *size ) DECLSPEC_HIDDEN;
 extern void CDECL DECLSPEC_NORETURN exit_thread( int status ) DECLSPEC_HIDDEN;
 extern void CDECL DECLSPEC_NORETURN exit_process( int status ) DECLSPEC_HIDDEN;
 extern NTSTATUS CDECL exec_process( UNICODE_STRING *path, UNICODE_STRING *cmdline, NTSTATUS status ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/unixlib.h b/dlls/ntdll/unixlib.h
index 88010b695e..19e532da47 100644
--- a/dlls/ntdll/unixlib.h
+++ b/dlls/ntdll/unixlib.h
@@ -29,7 +29,7 @@ struct msghdr;
 struct _DISPATCHER_CONTEXT;
 
 /* increment this when you change the function table */
-#define NTDLL_UNIXLIB_VERSION 65
+#define NTDLL_UNIXLIB_VERSION 66
 
 struct unix_funcs
 {
@@ -319,7 +319,7 @@ struct unix_funcs
     void          (CDECL *virtual_set_large_address_space)(void);
 
     /* thread/process functions */
-    TEB *         (CDECL *init_threading)( int *nb_threads_ptr, struct ldt_copy **ldt_copy, SIZE_T *size );
+    TEB *         (CDECL *init_threading)( struct ldt_copy **ldt_copy, SIZE_T *size );
     void          (CDECL *exit_thread)( int status );
     void          (CDECL *exit_process)( int status );
     NTSTATUS      (CDECL *exec_process)( UNICODE_STRING *path, UNICODE_STRING *cmdline, NTSTATUS status );




More information about the wine-cvs mailing list