Commit 1056771b authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Allocate the stack for all threads, don't rely on pthread to do it for us.

parent 67e45d66
...@@ -2448,7 +2448,6 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3, ...@@ -2448,7 +2448,6 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3,
NTSTATUS status; NTSTATUS status;
WINE_MODREF *wm; WINE_MODREF *wm;
LPCWSTR load_path; LPCWSTR load_path;
SIZE_T stack_size;
PEB *peb = NtCurrentTeb()->Peb; PEB *peb = NtCurrentTeb()->Peb;
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress ); IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress );
...@@ -2471,10 +2470,7 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3, ...@@ -2471,10 +2470,7 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3,
RemoveEntryList( &wm->ldr.InLoadOrderModuleList ); RemoveEntryList( &wm->ldr.InLoadOrderModuleList );
InsertHeadList( &peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderModuleList ); InsertHeadList( &peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderModuleList );
stack_size = max( nt->OptionalHeader.SizeOfStackReserve, nt->OptionalHeader.SizeOfStackCommit ); if ((status = virtual_alloc_thread_stack( NtCurrentTeb(), 0, 0 )) != STATUS_SUCCESS) goto error;
if (stack_size < 1024 * 1024) stack_size = 1024 * 1024; /* Xlib needs a large stack */
if ((status = virtual_alloc_thread_stack( NULL, stack_size )) != STATUS_SUCCESS) goto error;
if ((status = server_init_process_done()) != STATUS_SUCCESS) goto error; if ((status = server_init_process_done()) != STATUS_SUCCESS) goto error;
actctx_init(); actctx_init();
......
...@@ -139,7 +139,7 @@ extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] ...@@ -139,7 +139,7 @@ extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES]
extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ); extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info );
extern NTSTATUS virtual_create_system_view( void *base, SIZE_T size, DWORD vprot ); extern NTSTATUS virtual_create_system_view( void *base, SIZE_T size, DWORD vprot );
extern SIZE_T virtual_free_system_view( PVOID *addr_ptr ); extern SIZE_T virtual_free_system_view( PVOID *addr_ptr );
extern NTSTATUS virtual_alloc_thread_stack( void *base, SIZE_T stack_size ); extern NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size, SIZE_T commit_size );
extern void virtual_clear_thread_stack(void); extern void virtual_clear_thread_stack(void);
extern BOOL virtual_handle_stack_fault( void *addr ); extern BOOL virtual_handle_stack_fault( void *addr );
extern NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err ); extern NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err );
......
...@@ -53,7 +53,7 @@ PUNHANDLED_EXCEPTION_FILTER unhandled_exception_filter = NULL; ...@@ -53,7 +53,7 @@ PUNHANDLED_EXCEPTION_FILTER unhandled_exception_filter = NULL;
/* info passed to a starting thread */ /* info passed to a starting thread */
struct startup_info struct startup_info
{ {
struct wine_pthread_thread_info pthread_info; TEB *teb;
PRTL_THREAD_START_ROUTINE entry_point; PRTL_THREAD_START_ROUTINE entry_point;
void *entry_arg; void *entry_arg;
}; };
...@@ -233,7 +233,6 @@ HANDLE thread_init(void) ...@@ -233,7 +233,6 @@ HANDLE thread_init(void)
HANDLE exe_file = 0; HANDLE exe_file = 0;
LARGE_INTEGER now; LARGE_INTEGER now;
struct ntdll_thread_data *thread_data; struct ntdll_thread_data *thread_data;
struct wine_pthread_thread_info thread_info;
static struct debug_info debug_info; /* debug info for initial thread */ static struct debug_info debug_info; /* debug info for initial thread */
virtual_init(); virtual_init();
...@@ -278,7 +277,6 @@ HANDLE thread_init(void) ...@@ -278,7 +277,6 @@ HANDLE thread_init(void)
while (1U << sigstack_zero_bits < sigstack_total_size) sigstack_zero_bits++; while (1U << sigstack_zero_bits < sigstack_total_size) sigstack_zero_bits++;
assert( 1U << sigstack_zero_bits == sigstack_total_size ); /* must be a power of 2 */ assert( 1U << sigstack_zero_bits == sigstack_total_size ); /* must be a power of 2 */
assert( sigstack_total_size >= sizeof(TEB) + sizeof(struct startup_info) ); assert( sigstack_total_size >= sizeof(TEB) + sizeof(struct startup_info) );
thread_info.teb_size = sigstack_total_size;
addr = NULL; addr = NULL;
size = sigstack_total_size; size = sigstack_total_size;
...@@ -286,19 +284,13 @@ HANDLE thread_init(void) ...@@ -286,19 +284,13 @@ HANDLE thread_init(void)
&size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE ); &size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE );
teb = addr; teb = addr;
teb->Peb = peb; teb->Peb = peb;
thread_info.teb_size = size;
init_teb( teb ); init_teb( teb );
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2; thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
thread_data->debug_info = &debug_info; thread_data->debug_info = &debug_info;
InsertHeadList( &tls_links, &teb->TlsLinks ); InsertHeadList( &tls_links, &teb->TlsLinks );
thread_info.stack_base = NULL;
thread_info.stack_size = 0;
thread_info.teb_base = teb;
thread_info.teb_sel = thread_data->fs;
wine_pthread_get_functions( &pthread_functions, sizeof(pthread_functions) ); wine_pthread_get_functions( &pthread_functions, sizeof(pthread_functions) );
signal_init_thread( teb ); signal_init_thread( teb );
pthread_functions.init_thread( &thread_info );
virtual_init_threading(); virtual_init_threading();
debug_info.str_pos = debug_info.strings; debug_info.str_pos = debug_info.strings;
...@@ -467,13 +459,12 @@ static void DECLSPEC_NORETURN call_thread_func( PRTL_THREAD_START_ROUTINE rtl_fu ...@@ -467,13 +459,12 @@ static void DECLSPEC_NORETURN call_thread_func( PRTL_THREAD_START_ROUTINE rtl_fu
* *
* Startup routine for a newly created thread. * Startup routine for a newly created thread.
*/ */
static void start_thread( struct wine_pthread_thread_info *info ) static void start_thread( struct startup_info *info )
{ {
TEB *teb = info->teb_base; TEB *teb = info->teb;
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2; struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
struct startup_info *startup_info = (struct startup_info *)info; PRTL_THREAD_START_ROUTINE func = info->entry_point;
PRTL_THREAD_START_ROUTINE func = startup_info->entry_point; void *arg = info->entry_arg;
void *arg = startup_info->entry_arg;
struct debug_info debug_info; struct debug_info debug_info;
debug_info.str_pos = debug_info.strings; debug_info.str_pos = debug_info.strings;
...@@ -483,8 +474,6 @@ static void start_thread( struct wine_pthread_thread_info *info ) ...@@ -483,8 +474,6 @@ static void start_thread( struct wine_pthread_thread_info *info )
signal_init_thread( teb ); signal_init_thread( teb );
server_init_thread( func ); server_init_thread( func );
pthread_functions.init_thread( info );
virtual_alloc_thread_stack( info->stack_base, info->stack_size );
pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL ); pthread_sigmask( SIG_UNBLOCK, &server_block_set, NULL );
RtlAcquirePebLock(); RtlAcquirePebLock();
...@@ -531,7 +520,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * ...@@ -531,7 +520,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
DWORD tid = 0; DWORD tid = 0;
int request_pipe[2]; int request_pipe[2];
NTSTATUS status; NTSTATUS status;
SIZE_T size, page_size = getpagesize(); SIZE_T size;
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
...@@ -593,7 +582,10 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * ...@@ -593,7 +582,10 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
teb = addr; teb = addr;
teb->Peb = NtCurrentTeb()->Peb; teb->Peb = NtCurrentTeb()->Peb;
info = (struct startup_info *)(teb + 1); info = (struct startup_info *)(teb + 1);
info->pthread_info.teb_size = size; info->teb = teb;
info->entry_point = start;
info->entry_arg = param;
if ((status = init_teb( teb ))) goto error; if ((status = init_teb( teb ))) goto error;
teb->ClientId.UniqueProcess = ULongToHandle(GetCurrentProcessId()); teb->ClientId.UniqueProcess = ULongToHandle(GetCurrentProcessId());
...@@ -603,9 +595,6 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * ...@@ -603,9 +595,6 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
thread_regs = (struct ntdll_thread_regs *)teb->SpareBytes1; thread_regs = (struct ntdll_thread_regs *)teb->SpareBytes1;
thread_data->request_fd = request_pipe[1]; thread_data->request_fd = request_pipe[1];
info->pthread_info.teb_base = teb;
info->pthread_info.teb_sel = thread_data->fs;
/* inherit debug registers from parent thread */ /* inherit debug registers from parent thread */
thread_regs->dr0 = ntdll_get_thread_regs()->dr0; thread_regs->dr0 = ntdll_get_thread_regs()->dr0;
thread_regs->dr1 = ntdll_get_thread_regs()->dr1; thread_regs->dr1 = ntdll_get_thread_regs()->dr1;
...@@ -614,31 +603,19 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR * ...@@ -614,31 +603,19 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
thread_regs->dr6 = ntdll_get_thread_regs()->dr6; thread_regs->dr6 = ntdll_get_thread_regs()->dr6;
thread_regs->dr7 = ntdll_get_thread_regs()->dr7; thread_regs->dr7 = ntdll_get_thread_regs()->dr7;
if (!stack_reserve || !stack_commit) if ((status = virtual_alloc_thread_stack( teb, stack_reserve, stack_commit ))) goto error;
{
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress );
if (!stack_reserve) stack_reserve = nt->OptionalHeader.SizeOfStackReserve;
if (!stack_commit) stack_commit = nt->OptionalHeader.SizeOfStackCommit;
}
if (stack_reserve < stack_commit) stack_reserve = stack_commit;
stack_reserve += page_size; /* for the guard page */
stack_reserve = (stack_reserve + 0xffff) & ~0xffff; /* round to 64K boundary */
if (stack_reserve < 1024 * 1024) stack_reserve = 1024 * 1024; /* Xlib needs a large stack */
info->pthread_info.stack_base = NULL;
info->pthread_info.stack_size = stack_reserve;
info->pthread_info.entry = start_thread;
info->entry_point = start;
info->entry_arg = param;
pthread_attr_init( &attr ); pthread_attr_init( &attr );
pthread_attr_setstacksize( &attr, stack_reserve ); pthread_attr_setstack( &attr, teb->DeallocationStack,
(char *)teb->Tib.StackBase - (char *)teb->DeallocationStack );
pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */ pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */
interlocked_xchg_add( &nb_threads, 1 ); interlocked_xchg_add( &nb_threads, 1 );
if (pthread_create( &pthread_id, &attr, (void * (*)(void *))start_thread, info )) if (pthread_create( &pthread_id, &attr, (void * (*)(void *))start_thread, info ))
{ {
interlocked_xchg_add( &nb_threads, -1 ); interlocked_xchg_add( &nb_threads, -1 );
pthread_attr_destroy( &attr ); pthread_attr_destroy( &attr );
size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
status = STATUS_NO_MEMORY; status = STATUS_NO_MEMORY;
goto error; goto error;
} }
...@@ -655,7 +632,7 @@ error: ...@@ -655,7 +632,7 @@ error:
if (thread_data) wine_ldt_free_fs( thread_data->fs ); if (thread_data) wine_ldt_free_fs( thread_data->fs );
if (addr) if (addr)
{ {
SIZE_T size = 0; size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE ); NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
} }
if (handle) NtClose( handle ); if (handle) NtClose( handle );
......
...@@ -1396,33 +1396,33 @@ SIZE_T virtual_free_system_view( PVOID *addr_ptr ) ...@@ -1396,33 +1396,33 @@ SIZE_T virtual_free_system_view( PVOID *addr_ptr )
/*********************************************************************** /***********************************************************************
* virtual_alloc_thread_stack * virtual_alloc_thread_stack
*/ */
NTSTATUS virtual_alloc_thread_stack( void *base, SIZE_T size ) NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size, SIZE_T commit_size )
{ {
FILE_VIEW *view; FILE_VIEW *view;
NTSTATUS status; NTSTATUS status;
sigset_t sigset; sigset_t sigset;
SIZE_T size;
server_enter_uninterrupted_section( &csVirtual, &sigset ); if (!reserve_size || !commit_size)
if (base) /* already allocated, create a system view */
{ {
size = ROUND_SIZE( base, size ); IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress );
base = ROUND_ADDR( base, page_mask ); if (!reserve_size) reserve_size = nt->OptionalHeader.SizeOfStackReserve;
if ((status = create_view( &view, base, size, if (!commit_size) commit_size = nt->OptionalHeader.SizeOfStackCommit;
VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_VALLOC | VPROT_SYSTEM )) != STATUS_SUCCESS)
goto done;
} }
else
{ size = max( reserve_size, commit_size );
size = (size + 0xffff) & ~0xffff; /* round to 64K boundary */ if (size < 1024 * 1024) size = 1024 * 1024; /* Xlib needs a large stack */
if ((status = map_view( &view, NULL, size, 0xffff, 0, size = (size + 0xffff) & ~0xffff; /* round to 64K boundary */
VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_VALLOC )) != STATUS_SUCCESS)
goto done; server_enter_uninterrupted_section( &csVirtual, &sigset );
if ((status = map_view( &view, NULL, size, 0xffff, 0,
VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_VALLOC )) != STATUS_SUCCESS)
goto done;
#ifdef VALGRIND_STACK_REGISTER #ifdef VALGRIND_STACK_REGISTER
/* no need to de-register the stack as it's the one of the main thread */ VALGRIND_STACK_REGISTER( view->base, (char *)view->base + view->size );
VALGRIND_STACK_REGISTER( view->base, (char *)view->base + view->size );
#endif #endif
}
/* setup no access guard page */ /* setup no access guard page */
VIRTUAL_SetProt( view, view->base, page_size, VPROT_COMMITTED ); VIRTUAL_SetProt( view, view->base, page_size, VPROT_COMMITTED );
...@@ -1430,10 +1430,9 @@ NTSTATUS virtual_alloc_thread_stack( void *base, SIZE_T size ) ...@@ -1430,10 +1430,9 @@ NTSTATUS virtual_alloc_thread_stack( void *base, SIZE_T size )
VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_GUARD ); VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_GUARD );
/* note: limit is lower than base since the stack grows down */ /* note: limit is lower than base since the stack grows down */
NtCurrentTeb()->DeallocationStack = view->base; teb->DeallocationStack = view->base;
NtCurrentTeb()->Tib.StackBase = (char *)view->base + view->size; teb->Tib.StackBase = (char *)view->base + view->size;
NtCurrentTeb()->Tib.StackLimit = (char *)view->base + 2 * page_size; teb->Tib.StackLimit = (char *)view->base + 2 * page_size;
done: done:
server_leave_uninterrupted_section( &csVirtual, &sigset ); server_leave_uninterrupted_section( &csVirtual, &sigset );
return status; return status;
......
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