Alexandre Julliard : ntdll: Allocate TLS slots dynamically on module load.

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


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Dec 23 12:54:26 2013 +0100

ntdll: Allocate TLS slots dynamically on module load.

---

 dlls/ntdll/loader.c |  110 ++++++++++++++++++++++++++++----------------------
 1 files changed, 62 insertions(+), 48 deletions(-)

diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 817cf8a..b8a9c66 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -792,6 +792,65 @@ static BOOL is_dll_native_subsystem( HMODULE module, const IMAGE_NT_HEADERS *nt,
     return TRUE;
 }
 
+/*************************************************************************
+ *		alloc_tls_slot
+ *
+ * Allocate a TLS slot for a newly-loaded module.
+ * The loader_section must be locked while calling this function.
+ */
+static SHORT alloc_tls_slot( LDR_MODULE *mod )
+{
+    const IMAGE_TLS_DIRECTORY *dir;
+    ULONG i, size;
+    void *new_ptr;
+
+    if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &size )))
+        return -1;
+
+    size = dir->EndAddressOfRawData - dir->StartAddressOfRawData;
+    if (!size && !dir->SizeOfZeroFill && !dir->AddressOfCallBacks) return -1;
+
+    for (i = 0; i < tls_module_count; i++) if (!tls_dirs[i]) break;
+
+    TRACE( "module %p data %p-%p zerofill %u index %p callback %p flags %x -> slot %u\n", mod->BaseAddress,
+           (void *)dir->StartAddressOfRawData, (void *)dir->EndAddressOfRawData, dir->SizeOfZeroFill,
+           (void *)dir->AddressOfIndex, (void *)dir->AddressOfCallBacks, dir->Characteristics, i );
+
+    if (i == tls_module_count)
+    {
+        UINT new_count = max( 32, tls_module_count * 2 );
+
+        if (!tls_dirs)
+            new_ptr = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*tls_dirs) );
+        else
+            new_ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, tls_dirs,
+                                         new_count * sizeof(*tls_dirs) );
+        if (!new_ptr) return -1;
+        tls_dirs = new_ptr;
+        tls_module_count = new_count;
+    }
+
+    *(DWORD *)dir->AddressOfIndex = i;
+    tls_dirs[i] = dir;
+    return i;
+}
+
+
+/*************************************************************************
+ *		free_tls_slot
+ *
+ * Free the module TLS slot on unload.
+ * The loader_section must be locked while calling this function.
+ */
+static void free_tls_slot( LDR_MODULE *mod )
+{
+    ULONG i = (USHORT)mod->TlsIndex;
+
+    if (mod->TlsIndex == -1) return;
+    assert( i < tls_module_count );
+    tls_dirs[i] = NULL;
+}
+
 
 /*************************************************************************
  *		alloc_module
@@ -816,7 +875,6 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
     wm->ldr.SizeOfImage   = nt->OptionalHeader.SizeOfImage;
     wm->ldr.Flags         = LDR_DONT_RESOLVE_REFS;
     wm->ldr.LoadCount     = 1;
-    wm->ldr.TlsIndex      = -1;
     wm->ldr.SectionHandle = NULL;
     wm->ldr.CheckSum      = 0;
     wm->ldr.TimeDateStamp = 0;
@@ -853,6 +911,8 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
     wm->ldr.InInitializationOrderModuleList.Flink = NULL;
     wm->ldr.InInitializationOrderModuleList.Blink = NULL;
 
+    wm->ldr.TlsIndex = alloc_tls_slot( &wm->ldr );
+
     if (!(nt->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT))
     {
         ULONG flags = MEM_EXECUTE_OPTION_ENABLE;
@@ -864,52 +924,6 @@ static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
 
 
 /*************************************************************************
- *              alloc_process_tls
- *
- * Allocate the process-wide structure for module TLS storage.
- */
-static NTSTATUS alloc_process_tls(void)
-{
-    PLIST_ENTRY mark, entry;
-    PLDR_MODULE mod;
-    const IMAGE_TLS_DIRECTORY *dir;
-    ULONG size, i;
-
-    mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
-    for (entry = mark->Flink; entry != mark; entry = entry->Flink)
-    {
-        mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
-        if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE,
-                                                  IMAGE_DIRECTORY_ENTRY_TLS, &size )))
-            continue;
-        size = (dir->EndAddressOfRawData - dir->StartAddressOfRawData) + dir->SizeOfZeroFill;
-        if (!size && !dir->AddressOfCallBacks) continue;
-        tls_module_count++;
-    }
-    if (!tls_module_count) return STATUS_SUCCESS;
-
-    TRACE( "count %u\n", tls_module_count );
-
-    tls_dirs = RtlAllocateHeap( GetProcessHeap(), 0, tls_module_count * sizeof(*tls_dirs) );
-    if (!tls_dirs) return STATUS_NO_MEMORY;
-
-    for (i = 0, entry = mark->Flink; entry != mark; entry = entry->Flink)
-    {
-        mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
-        if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE,
-                                                  IMAGE_DIRECTORY_ENTRY_TLS, &size )))
-            continue;
-        tls_dirs[i] = dir;
-        *(DWORD *)dir->AddressOfIndex = i;
-        mod->TlsIndex = i;
-        mod->LoadCount = -1;  /* can't unload it */
-        i++;
-    }
-    return STATUS_SUCCESS;
-}
-
-
-/*************************************************************************
  *              alloc_thread_tls
  *
  * Allocate the per-thread structure for module TLS storage.
@@ -2540,6 +2554,7 @@ static void free_modref( WINE_MODREF *wm )
     }
     SERVER_END_REQ;
 
+    free_tls_slot( &wm->ldr );
     RtlReleaseActivationContext( wm->ldr.ActivationContext );
     NtUnmapViewOfSection( NtCurrentProcess(), wm->ldr.BaseAddress );
     if (wm->ldr.Flags & LDR_WINE_INTERNAL) wine_dll_unload( wm->ldr.SectionHandle );
@@ -2813,7 +2828,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_process_tls()) != STATUS_SUCCESS) goto error;
     if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error;
     heap_set_debug_flags( GetProcessHeap() );
 




More information about the wine-cvs mailing list