diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 61299627562..34ae2d62d55 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -78,6 +78,7 @@ extern size_t server_init_thread( void *entry_point ); extern void DECLSPEC_NORETURN server_protocol_error( const char *err, ... ); extern void DECLSPEC_NORETURN server_protocol_perror( const char *err ); extern void DECLSPEC_NORETURN abort_thread( int status ); +extern void DECLSPEC_NORETURN exit_thread( int status ); extern sigset_t server_block_set; extern void server_enter_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ); extern void server_leave_uninterrupted_section( RTL_CRITICAL_SECTION *cs, sigset_t *sigset ); diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index 0efce897121..ff251fa3d0a 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -2274,7 +2274,7 @@ __ASM_GLOBAL_FUNC(call_thread_func, "call *8(%ebp)\n\t" "leal -4(%ebp),%esp\n\t" "pushl %eax\n\t" - "call " __ASM_NAME("RtlExitUserThread") "\n\t" + "call " __ASM_NAME("exit_thread") "\n\t" "int $3" ) /*********************************************************************** @@ -2294,6 +2294,13 @@ void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) abort(); /* should not be reached */ } +/*********************************************************************** + * RtlExitUserThread (NTDLL.@) + */ +void WINAPI RtlExitUserThread( ULONG status ) +{ + exit_thread( status ); +} /********************************************************************** * DbgBreakPoint (NTDLL.@) diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c index 4401006edc4..92288ad558a 100644 --- a/dlls/ntdll/signal_powerpc.c +++ b/dlls/ntdll/signal_powerpc.c @@ -1093,7 +1093,7 @@ void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) { __TRY { - RtlExitUserThread( entry( arg )); + exit_thread( entry( arg )); } __EXCEPT(unhandled_exception_filter) { @@ -1103,6 +1103,14 @@ void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) abort(); /* should not be reached */ } +/*********************************************************************** + * RtlExitUserThread (NTDLL.@) + */ +void WINAPI RtlExitUserThread( ULONG status ) +{ + exit_thread( status ); +} + /********************************************************************** * DbgBreakPoint (NTDLL.@) */ diff --git a/dlls/ntdll/signal_sparc.c b/dlls/ntdll/signal_sparc.c index 17bfc542f4a..55b2a791913 100644 --- a/dlls/ntdll/signal_sparc.c +++ b/dlls/ntdll/signal_sparc.c @@ -835,7 +835,7 @@ void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) { __TRY { - RtlExitUserThread( entry( arg )); + exit_thread( entry( arg )); } __EXCEPT(unhandled_exception_filter) { @@ -845,6 +845,14 @@ void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) abort(); /* should not be reached */ } +/*********************************************************************** + * RtlExitUserThread (NTDLL.@) + */ +void WINAPI RtlExitUserThread( ULONG status ) +{ + exit_thread( status ); +} + /********************************************************************** * DbgBreakPoint (NTDLL.@) */ diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index 7ff38aff4d1..716efea3401 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -2558,7 +2558,7 @@ void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) { __TRY { - RtlExitUserThread( entry( arg )); + exit_thread( entry( arg )); } __EXCEPT(unhandled_exception_filter) { @@ -2569,6 +2569,15 @@ void call_thread_entry_point( LPTHREAD_START_ROUTINE entry, void *arg ) } +/*********************************************************************** + * RtlExitUserThread (NTDLL.@) + */ +void WINAPI RtlExitUserThread( ULONG status ) +{ + exit_thread( status ); +} + + /********************************************************************** * __wine_enter_vm86 (NTDLL.@) */ diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index cd54b31e251..0b924b2cf7e 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -353,11 +353,29 @@ void abort_thread( int status ) /*********************************************************************** * exit_thread */ -static void DECLSPEC_NORETURN exit_thread( int status ) +void exit_thread( int status ) { static void *prev_teb; TEB *teb; + if (status) /* send the exit code to the server (0 is already the default) */ + { + SERVER_START_REQ( terminate_thread ) + { + req->handle = wine_server_obj_handle( GetCurrentThread() ); + req->exit_code = status; + wine_server_call( req ); + } + SERVER_END_REQ; + } + + if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) + { + LdrShutdownProcess(); + exit( status ); + } + + LdrShutdownThread(); RtlAcquirePebLock(); RemoveEntryList( &NtCurrentTeb()->TlsLinks ); RtlReleasePebLock(); @@ -365,7 +383,6 @@ static void DECLSPEC_NORETURN exit_thread( int status ) RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots ); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); - if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) exit( status ); if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() ))) { @@ -566,36 +583,6 @@ error: } -/*********************************************************************** - * RtlExitUserThread (NTDLL.@) - */ -void WINAPI RtlExitUserThread( ULONG status ) -{ - BOOL last; - - SERVER_START_REQ( terminate_thread ) - { - /* send the exit code to the server */ - req->handle = wine_server_obj_handle( GetCurrentThread() ); - req->exit_code = status; - wine_server_call( req ); - last = reply->last; - } - SERVER_END_REQ; - - if (last) - { - LdrShutdownProcess(); - exit( status ); - } - else - { - LdrShutdownThread(); - exit_thread( status ); - } -} - - /*********************************************************************** * NtOpenThread (NTDLL.@) * ZwOpenThread (NTDLL.@)