Alexandre Julliard : ntdll: Don' t free the thread stack and TEB while exiting, do it from the next thread.

Alexandre Julliard julliard at winehq.org
Mon Feb 23 10:00:38 CST 2009


Module: wine
Branch: master
Commit: 67e45d66d32a52bd4df8df24a75330bc59d4ec37
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=67e45d66d32a52bd4df8df24a75330bc59d4ec37

Author: Alexandre Julliard <julliard at 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 ))




More information about the wine-cvs mailing list