Alexandre Julliard : ntdll: Allocate TLS data in all running threads on module load.

Alexandre Julliard julliard at winehq.org
Mon Dec 23 13:44:58 CST 2013


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Dec 23 18:16:51 2013 +0100

ntdll: Allocate TLS data in all running threads on module load.

---

 dlls/ntdll/loader.c     |   49 +++++++++++++++++++++++++++++++++++++++++++---
 dlls/ntdll/ntdll_misc.h |    1 +
 dlls/ntdll/thread.c     |   11 ----------
 3 files changed, 46 insertions(+), 15 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index b8a9c66..e0907e7 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -97,6 +97,7 @@ static struct builtin_load_info *builtin_load_info = &default_load_info;
 static HANDLE main_exe_file;
 static UINT tls_module_count;      /* number of modules with TLS directory */
 static const IMAGE_TLS_DIRECTORY **tls_dirs;  /* array of TLS directories */
+LIST_ENTRY tls_links = { &tls_links, &tls_links };
 
 static RTL_CRITICAL_SECTION loader_section;
 static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
@@ -803,6 +804,7 @@ static SHORT alloc_tls_slot( LDR_MODULE *mod )
     const IMAGE_TLS_DIRECTORY *dir;
     ULONG i, size;
     void *new_ptr;
+    LIST_ENTRY *entry;
 
     if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &size )))
         return -1;
@@ -826,10 +828,41 @@ static SHORT alloc_tls_slot( LDR_MODULE *mod )
             new_ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, tls_dirs,
                                          new_count * sizeof(*tls_dirs) );
         if (!new_ptr) return -1;
+
+        /* resize the pointer block in all running threads */
+        for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
+        {
+            TEB *teb = CONTAINING_RECORD( entry, TEB, TlsLinks );
+            void **old = teb->ThreadLocalStoragePointer;
+            void **new = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*new));
+
+            if (!new) return -1;
+            if (old) memcpy( new, old, tls_module_count * sizeof(*new) );
+            teb->ThreadLocalStoragePointer = new;
+            TRACE( "thread %04lx tls block %p -> %p\n", (ULONG_PTR)teb->ClientId.UniqueThread, old, new );
+            /* FIXME: can't free old block here, should be freed at thread exit */
+        }
+
         tls_dirs = new_ptr;
         tls_module_count = new_count;
     }
 
+    /* allocate the data block in all running threads */
+    for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
+    {
+        TEB *teb = CONTAINING_RECORD( entry, TEB, TlsLinks );
+
+        if (!(new_ptr = RtlAllocateHeap( GetProcessHeap(), 0, size + dir->SizeOfZeroFill ))) return -1;
+        memcpy( new_ptr, (void *)dir->StartAddressOfRawData, size );
+        memset( (char *)new_ptr + size, 0, dir->SizeOfZeroFill );
+
+        TRACE( "thread %04lx slot %u: %u/%u bytes at %p\n",
+               (ULONG_PTR)teb->ClientId.UniqueThread, i, size, dir->SizeOfZeroFill, new_ptr );
+
+        RtlFreeHeap( GetProcessHeap(), 0,
+                     interlocked_xchg_ptr( (void **)teb->ThreadLocalStoragePointer + i, new_ptr ));
+    }
+
     *(DWORD *)dir->AddressOfIndex = i;
     tls_dirs[i] = dir;
     return i;
@@ -956,9 +989,8 @@ static NTSTATUS alloc_thread_tls(void)
         memcpy( pointers[i], (void *)dir->StartAddressOfRawData, size );
         memset( (char *)pointers[i] + size, 0, dir->SizeOfZeroFill );
 
-        TRACE( "thread %04x idx %d: %d/%d bytes from %p to %p\n",
-               GetCurrentThreadId(), i, size, dir->SizeOfZeroFill,
-               (void *)dir->StartAddressOfRawData, pointers[i] );
+        TRACE( "thread %04x slot %u: %u/%u bytes at %p\n",
+               GetCurrentThreadId(), i, size, dir->SizeOfZeroFill, pointers[i] );
     }
     NtCurrentTeb()->ThreadLocalStoragePointer = pointers;
     return STATUS_SUCCESS;
@@ -1229,6 +1261,10 @@ NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved )
 
     RtlEnterCriticalSection( &loader_section );
 
+    RtlAcquirePebLock();
+    InsertHeadList( &tls_links, &NtCurrentTeb()->TlsLinks );
+    RtlReleasePebLock();
+
     if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto done;
 
     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
@@ -2521,11 +2557,17 @@ void WINAPI LdrShutdownThread(void)
                         DLL_THREAD_DETACH, NULL );
     }
 
+    RtlAcquirePebLock();
+    RemoveEntryList( &NtCurrentTeb()->TlsLinks );
+    RtlReleasePebLock();
+
     if ((pointers = NtCurrentTeb()->ThreadLocalStoragePointer))
     {
         for (i = 0; i < tls_module_count; i++) RtlFreeHeap( GetProcessHeap(), 0, pointers[i] );
         RtlFreeHeap( GetProcessHeap(), 0, pointers );
     }
+    RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->FlsSlots );
+    RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots );
     RtlLeaveCriticalSection( &loader_section );
 }
 
@@ -2828,7 +2870,6 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,
     actctx_init();
     load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
     if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS) goto error;
-    if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error;
     heap_set_debug_flags( GetProcessHeap() );
 
     status = wine_call_on_stack( attach_process_dlls, wm, NtCurrentTeb()->Tib.StackBase );
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index a45e6b0..4370084 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -103,6 +103,7 @@ NTSTATUS NTDLL_create_struct_sd(PSECURITY_DESCRIPTOR nt_sd, struct security_desc
 void NTDLL_free_struct_sd(struct security_descriptor *server_sd) DECLSPEC_HIDDEN;
 
 /* module handling */
+extern LIST_ENTRY tls_links DECLSPEC_HIDDEN;
 extern NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved ) DECLSPEC_HIDDEN;
 extern FARPROC RELAY_GetProcAddress( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
                                      DWORD exp_size, FARPROC proc, DWORD ordinal, const WCHAR *user ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 8a63725..9f0dfc0 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -67,7 +67,6 @@ static WCHAR current_dir[MAX_NT_PATH_LENGTH];
 static RTL_BITMAP tls_bitmap;
 static RTL_BITMAP tls_expansion_bitmap;
 static RTL_BITMAP fls_bitmap;
-static LIST_ENTRY tls_links;
 static int nb_threads = 1;
 
 /***********************************************************************
@@ -261,7 +260,6 @@ HANDLE thread_init(void)
     InitializeListHead( &ldr.InLoadOrderModuleList );
     InitializeListHead( &ldr.InMemoryOrderModuleList );
     InitializeListHead( &ldr.InInitializationOrderModuleList );
-    InitializeListHead( &tls_links );
 #ifdef __APPLE__
     peb->Reserved[0] = get_dyld_image_info_addr();
 #endif
@@ -376,11 +374,6 @@ void exit_thread( int 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 );
 
@@ -425,10 +418,6 @@ static void start_thread( struct startup_info *info )
     server_init_thread( func );
     pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
 
-    RtlAcquirePebLock();
-    InsertHeadList( &tls_links, &teb->TlsLinks );
-    RtlReleasePebLock();
-
     MODULE_DllThreadAttach( NULL );
 
     if (TRACE_ON(relay))




More information about the wine-cvs mailing list