Commit e54503f7 authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent 1a4eca6f
...@@ -97,6 +97,7 @@ static struct builtin_load_info *builtin_load_info = &default_load_info; ...@@ -97,6 +97,7 @@ static struct builtin_load_info *builtin_load_info = &default_load_info;
static HANDLE main_exe_file; static HANDLE main_exe_file;
static UINT tls_module_count; /* number of modules with TLS directory */ static UINT tls_module_count; /* number of modules with TLS directory */
static const IMAGE_TLS_DIRECTORY **tls_dirs; /* array of TLS directories */ 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 loader_section;
static RTL_CRITICAL_SECTION_DEBUG critsect_debug = static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
...@@ -803,6 +804,7 @@ static SHORT alloc_tls_slot( LDR_MODULE *mod ) ...@@ -803,6 +804,7 @@ static SHORT alloc_tls_slot( LDR_MODULE *mod )
const IMAGE_TLS_DIRECTORY *dir; const IMAGE_TLS_DIRECTORY *dir;
ULONG i, size; ULONG i, size;
void *new_ptr; void *new_ptr;
LIST_ENTRY *entry;
if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &size ))) if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &size )))
return -1; return -1;
...@@ -826,10 +828,41 @@ static SHORT alloc_tls_slot( LDR_MODULE *mod ) ...@@ -826,10 +828,41 @@ static SHORT alloc_tls_slot( LDR_MODULE *mod )
new_ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, tls_dirs, new_ptr = RtlReAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, tls_dirs,
new_count * sizeof(*tls_dirs) ); new_count * sizeof(*tls_dirs) );
if (!new_ptr) return -1; 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_dirs = new_ptr;
tls_module_count = new_count; 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; *(DWORD *)dir->AddressOfIndex = i;
tls_dirs[i] = dir; tls_dirs[i] = dir;
return i; return i;
...@@ -956,9 +989,8 @@ static NTSTATUS alloc_thread_tls(void) ...@@ -956,9 +989,8 @@ static NTSTATUS alloc_thread_tls(void)
memcpy( pointers[i], (void *)dir->StartAddressOfRawData, size ); memcpy( pointers[i], (void *)dir->StartAddressOfRawData, size );
memset( (char *)pointers[i] + size, 0, dir->SizeOfZeroFill ); memset( (char *)pointers[i] + size, 0, dir->SizeOfZeroFill );
TRACE( "thread %04x idx %d: %d/%d bytes from %p to %p\n", TRACE( "thread %04x slot %u: %u/%u bytes at %p\n",
GetCurrentThreadId(), i, size, dir->SizeOfZeroFill, GetCurrentThreadId(), i, size, dir->SizeOfZeroFill, pointers[i] );
(void *)dir->StartAddressOfRawData, pointers[i] );
} }
NtCurrentTeb()->ThreadLocalStoragePointer = pointers; NtCurrentTeb()->ThreadLocalStoragePointer = pointers;
return STATUS_SUCCESS; return STATUS_SUCCESS;
...@@ -1229,6 +1261,10 @@ NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved ) ...@@ -1229,6 +1261,10 @@ NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved )
RtlEnterCriticalSection( &loader_section ); RtlEnterCriticalSection( &loader_section );
RtlAcquirePebLock();
InsertHeadList( &tls_links, &NtCurrentTeb()->TlsLinks );
RtlReleasePebLock();
if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto done; if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto done;
mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList; mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
...@@ -2521,11 +2557,17 @@ void WINAPI LdrShutdownThread(void) ...@@ -2521,11 +2557,17 @@ void WINAPI LdrShutdownThread(void)
DLL_THREAD_DETACH, NULL ); DLL_THREAD_DETACH, NULL );
} }
RtlAcquirePebLock();
RemoveEntryList( &NtCurrentTeb()->TlsLinks );
RtlReleasePebLock();
if ((pointers = NtCurrentTeb()->ThreadLocalStoragePointer)) if ((pointers = NtCurrentTeb()->ThreadLocalStoragePointer))
{ {
for (i = 0; i < tls_module_count; i++) RtlFreeHeap( GetProcessHeap(), 0, pointers[i] ); for (i = 0; i < tls_module_count; i++) RtlFreeHeap( GetProcessHeap(), 0, pointers[i] );
RtlFreeHeap( GetProcessHeap(), 0, pointers ); RtlFreeHeap( GetProcessHeap(), 0, pointers );
} }
RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->FlsSlots );
RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots );
RtlLeaveCriticalSection( &loader_section ); RtlLeaveCriticalSection( &loader_section );
} }
...@@ -2828,7 +2870,6 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2, ...@@ -2828,7 +2870,6 @@ void WINAPI LdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,
actctx_init(); actctx_init();
load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer; load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS) goto error; 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() ); heap_set_debug_flags( GetProcessHeap() );
status = wine_call_on_stack( attach_process_dlls, wm, NtCurrentTeb()->Tib.StackBase ); status = wine_call_on_stack( attach_process_dlls, wm, NtCurrentTeb()->Tib.StackBase );
......
...@@ -103,6 +103,7 @@ NTSTATUS NTDLL_create_struct_sd(PSECURITY_DESCRIPTOR nt_sd, struct security_desc ...@@ -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; void NTDLL_free_struct_sd(struct security_descriptor *server_sd) DECLSPEC_HIDDEN;
/* module handling */ /* module handling */
extern LIST_ENTRY tls_links DECLSPEC_HIDDEN;
extern NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved ) DECLSPEC_HIDDEN; extern NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved ) DECLSPEC_HIDDEN;
extern FARPROC RELAY_GetProcAddress( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports, extern FARPROC RELAY_GetProcAddress( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
DWORD exp_size, FARPROC proc, DWORD ordinal, const WCHAR *user ) DECLSPEC_HIDDEN; DWORD exp_size, FARPROC proc, DWORD ordinal, const WCHAR *user ) DECLSPEC_HIDDEN;
......
...@@ -67,7 +67,6 @@ static WCHAR current_dir[MAX_NT_PATH_LENGTH]; ...@@ -67,7 +67,6 @@ static WCHAR current_dir[MAX_NT_PATH_LENGTH];
static RTL_BITMAP tls_bitmap; static RTL_BITMAP tls_bitmap;
static RTL_BITMAP tls_expansion_bitmap; static RTL_BITMAP tls_expansion_bitmap;
static RTL_BITMAP fls_bitmap; static RTL_BITMAP fls_bitmap;
static LIST_ENTRY tls_links;
static int nb_threads = 1; static int nb_threads = 1;
/*********************************************************************** /***********************************************************************
...@@ -261,7 +260,6 @@ HANDLE thread_init(void) ...@@ -261,7 +260,6 @@ HANDLE thread_init(void)
InitializeListHead( &ldr.InLoadOrderModuleList ); InitializeListHead( &ldr.InLoadOrderModuleList );
InitializeListHead( &ldr.InMemoryOrderModuleList ); InitializeListHead( &ldr.InMemoryOrderModuleList );
InitializeListHead( &ldr.InInitializationOrderModuleList ); InitializeListHead( &ldr.InInitializationOrderModuleList );
InitializeListHead( &tls_links );
#ifdef __APPLE__ #ifdef __APPLE__
peb->Reserved[0] = get_dyld_image_info_addr(); peb->Reserved[0] = get_dyld_image_info_addr();
#endif #endif
...@@ -376,11 +374,6 @@ void exit_thread( int status ) ...@@ -376,11 +374,6 @@ void exit_thread( int status )
} }
LdrShutdownThread(); LdrShutdownThread();
RtlAcquirePebLock();
RemoveEntryList( &NtCurrentTeb()->TlsLinks );
RtlReleasePebLock();
RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->FlsSlots );
RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->TlsExpansionSlots );
pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL );
...@@ -425,10 +418,6 @@ static void start_thread( struct startup_info *info ) ...@@ -425,10 +418,6 @@ static void start_thread( struct startup_info *info )
server_init_thread( func ); server_init_thread( func );
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
RtlAcquirePebLock();
InsertHeadList( &tls_links, &teb->TlsLinks );
RtlReleasePebLock();
MODULE_DllThreadAttach( NULL ); MODULE_DllThreadAttach( NULL );
if (TRACE_ON(relay)) if (TRACE_ON(relay))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment