Commit 2334f4e6 authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent 635593a0
......@@ -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();
}
......@@ -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 );
......
......@@ -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;
......
......@@ -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;
......
......@@ -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 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment