Module: wine Branch: master Commit: e54503f7085a5b62dfc373aaa6b98116bde784d4 URL: http://source.winehq.org/git/wine.git/?a=commit;h=e54503f7085a5b62dfc373aaa6...
Author: Alexandre Julliard julliard@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))