ntdll: Allocate the stack for all threads, don't rely on pthread to do it for us.
This commit is contained in:
parent
67e45d66d3
commit
1056771b91
|
@ -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,
|
||||||
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]
|
||||||
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;
|
||||||
/* 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)
|
||||||
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)
|
||||||
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)
|
||||||
&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
|
||||||
*
|
*
|
||||||
* 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 )
|
||||||
|
|
||||||
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 *
|
||||||
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 *
|
||||||
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 *
|
||||||
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 *
|
||||||
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:
|
||||||
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 )
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* 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;
|
||||||
|
|
||||||
|
if (!reserve_size || !commit_size)
|
||||||
|
{
|
||||||
|
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress );
|
||||||
|
if (!reserve_size) reserve_size = nt->OptionalHeader.SizeOfStackReserve;
|
||||||
|
if (!commit_size) commit_size = nt->OptionalHeader.SizeOfStackCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = max( reserve_size, commit_size );
|
||||||
|
if (size < 1024 * 1024) size = 1024 * 1024; /* Xlib needs a large stack */
|
||||||
|
size = (size + 0xffff) & ~0xffff; /* round to 64K boundary */
|
||||||
|
|
||||||
server_enter_uninterrupted_section( &csVirtual, &sigset );
|
server_enter_uninterrupted_section( &csVirtual, &sigset );
|
||||||
|
|
||||||
if (base) /* already allocated, create a system view */
|
if ((status = map_view( &view, NULL, size, 0xffff, 0,
|
||||||
{
|
VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_VALLOC )) != STATUS_SUCCESS)
|
||||||
size = ROUND_SIZE( base, size );
|
goto done;
|
||||||
base = ROUND_ADDR( base, page_mask );
|
|
||||||
if ((status = create_view( &view, base, size,
|
|
||||||
VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_VALLOC | VPROT_SYSTEM )) != STATUS_SUCCESS)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
size = (size + 0xffff) & ~0xffff; /* round to 64K boundary */
|
|
||||||
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 )
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue