Module: wine Branch: master Commit: 67e45d66d32a52bd4df8df24a75330bc59d4ec37 URL: http://source.winehq.org/git/wine.git/?a=commit;h=67e45d66d32a52bd4df8df24a7...
Author: Alexandre Julliard julliard@winehq.org Date: Mon Feb 23 14:02:16 2009 +0100
ntdll: Don't free the thread stack and TEB while exiting, do it from the next thread.
---
dlls/ntdll/ntdll_misc.h | 3 +-- dlls/ntdll/thread.c | 42 +++++++++++++++++++++--------------------- 2 files changed, 22 insertions(+), 23 deletions(-)
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h index 3dd20d6..55eadd0 100644 --- a/dlls/ntdll/ntdll_misc.h +++ b/dlls/ntdll/ntdll_misc.h @@ -195,8 +195,7 @@ struct ntdll_thread_data int wait_fd[2]; /* 1e8 fd for sleeping server requests */ void *vm86_ptr; /* 1f0 data for vm86 mode */ void *pthread_data; /* 1f4 private data for pthread emulation */ - - void *pad[1]; /* 1f8 change this if you add fields! */ + pthread_t pthread_id; /* 1f8 pthread thread id */ };
static inline struct ntdll_thread_data *ntdll_get_thread_data(void) diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index e11976c..40bf507 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -353,9 +353,9 @@ HANDLE thread_init(void) */ void abort_thread( int status ) { + pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) _exit( status );
- pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[1] ); close( ntdll_get_thread_data()->reply_fd ); @@ -369,11 +369,8 @@ void abort_thread( int status ) */ static void DECLSPEC_NORETURN exit_thread( int status ) { - int fds[4]; - void *teb_addr; - SIZE_T teb_size; - - if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) exit( status ); + static void *prev_teb; + TEB *teb;
RtlAcquirePebLock(); RemoveEntryList( &NtCurrentTeb()->TlsLinks ); @@ -381,23 +378,26 @@ static void DECLSPEC_NORETURN exit_thread( int status ) RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->FlsSlots ); RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots );
- fds[0] = ntdll_get_thread_data()->wait_fd[0]; - fds[1] = ntdll_get_thread_data()->wait_fd[1]; - fds[2] = ntdll_get_thread_data()->reply_fd; - fds[3] = ntdll_get_thread_data()->request_fd; pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); + if (interlocked_xchg_add( &nb_threads, -1 ) <= 1) exit( status );
- virtual_free_system_view( &NtCurrentTeb()->DeallocationStack ); - teb_addr = NtCurrentTeb(); - teb_size = virtual_free_system_view( &teb_addr ); - - close( fds[0] ); - close( fds[1] ); - close( fds[2] ); - close( fds[3] ); + if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() ))) + { + struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2; + SIZE_T size; + + pthread_join( thread_data->pthread_id, NULL ); + wine_ldt_free_fs( thread_data->fs ); + size = 0; + NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE ); + size = 0; + NtFreeVirtualMemory( GetCurrentProcess(), (void **)&teb, &size, MEM_RELEASE ); + }
- wine_ldt_free_fs( wine_get_fs() ); - if (teb_size) munmap( teb_addr, teb_size ); + 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) ); }
@@ -479,6 +479,7 @@ static void start_thread( struct wine_pthread_thread_info *info ) debug_info.str_pos = debug_info.strings; debug_info.out_pos = debug_info.output; thread_data->debug_info = &debug_info; + thread_data->pthread_id = pthread_self();
signal_init_thread( teb ); server_init_thread( func ); @@ -632,7 +633,6 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
pthread_attr_init( &attr ); pthread_attr_setstacksize( &attr, stack_reserve ); - pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */ interlocked_xchg_add( &nb_threads, 1 ); if (pthread_create( &pthread_id, &attr, (void * (*)(void *))start_thread, info ))