/*********************************************************************** * exit_thread */ void exit_thread( int status ) { static void *prev_teb; shmlocal_t *shmlocal; sigset_t sigset; 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, 0 ) <= 1) { LdrShutdownProcess(); exit( status ); } LdrShutdownThread(); RtlFreeThreadActivationContextStack(); shmlocal = interlocked_xchg_ptr( &NtCurrentTeb()->Reserved5[2], NULL ); if (shmlocal) NtUnmapViewOfSection( NtCurrentProcess(), shmlocal ); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() ))) { struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; if (thread_data->pthread_id) { pthread_join( thread_data->pthread_id, NULL ); signal_free_thread( teb ); } } sigemptyset( &sigset ); sigaddset( &sigset, SIGQUIT ); pthread_sigmask( SIG_BLOCK, &sigset, NULL ); if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) _exit( status ); close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); close( ntdll_get_thread_data()->request_fd ); pthread_exit( UIntToPtr(status) ); }
/* * @implemented */ VOID NTAPI RtlExitUserThread(NTSTATUS Status) { /* Call the Loader and tell him to notify the DLLs */ LdrShutdownThread(); /* Shut us down */ NtCurrentTeb()->FreeStackOnTermination = TRUE; NtTerminateThread(NtCurrentThread(), Status); }
/*********************************************************************** * exit_thread */ 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(); #ifdef CONFIG_UNIFIED_KERNEL server_kill_thread( status ); #endif exit( status ); } LdrShutdownThread(); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() ))) { struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; if (thread_data->pthread_id) { pthread_join( thread_data->pthread_id, NULL ); signal_free_thread( teb ); } } close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); close( ntdll_get_thread_data()->request_fd ); #ifdef CONFIG_UNIFIED_KERNEL server_kill_thread( status ); #endif pthread_exit( UIntToPtr(status) ); }
/*********************************************************************** * exit_thread */ 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(); RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->FlsSlots ); RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots ); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() ))) { struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; if (thread_data->pthread_id) { pthread_join( thread_data->pthread_id, NULL ); signal_free_thread( teb ); } } close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); close( ntdll_get_thread_data()->request_fd ); pthread_exit( UIntToPtr(status) ); }