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