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;
|
||||
WINE_MODREF *wm;
|
||||
LPCWSTR load_path;
|
||||
SIZE_T stack_size;
|
||||
PEB *peb = NtCurrentTeb()->Peb;
|
||||
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress );
|
||||
|
||||
|
@ -2471,10 +2470,7 @@ void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3,
|
|||
RemoveEntryList( &wm->ldr.InLoadOrderModuleList );
|
||||
InsertHeadList( &peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderModuleList );
|
||||
|
||||
stack_size = max( nt->OptionalHeader.SizeOfStackReserve, nt->OptionalHeader.SizeOfStackCommit );
|
||||
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 = virtual_alloc_thread_stack( NtCurrentTeb(), 0, 0 )) != STATUS_SUCCESS) goto error;
|
||||
if ((status = server_init_process_done()) != STATUS_SUCCESS) goto error;
|
||||
|
||||
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 NTSTATUS virtual_create_system_view( void *base, SIZE_T size, DWORD vprot );
|
||||
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 BOOL virtual_handle_stack_fault( void *addr );
|
||||
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 */
|
||||
struct startup_info
|
||||
{
|
||||
struct wine_pthread_thread_info pthread_info;
|
||||
TEB *teb;
|
||||
PRTL_THREAD_START_ROUTINE entry_point;
|
||||
void *entry_arg;
|
||||
};
|
||||
|
@ -233,7 +233,6 @@ HANDLE thread_init(void)
|
|||
HANDLE exe_file = 0;
|
||||
LARGE_INTEGER now;
|
||||
struct ntdll_thread_data *thread_data;
|
||||
struct wine_pthread_thread_info thread_info;
|
||||
static struct debug_info debug_info; /* debug info for initial thread */
|
||||
|
||||
virtual_init();
|
||||
|
@ -278,7 +277,6 @@ HANDLE thread_init(void)
|
|||
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( sigstack_total_size >= sizeof(TEB) + sizeof(struct startup_info) );
|
||||
thread_info.teb_size = sigstack_total_size;
|
||||
|
||||
addr = NULL;
|
||||
size = sigstack_total_size;
|
||||
|
@ -286,19 +284,13 @@ HANDLE thread_init(void)
|
|||
&size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE );
|
||||
teb = addr;
|
||||
teb->Peb = peb;
|
||||
thread_info.teb_size = size;
|
||||
init_teb( teb );
|
||||
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
|
||||
thread_data->debug_info = &debug_info;
|
||||
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) );
|
||||
signal_init_thread( teb );
|
||||
pthread_functions.init_thread( &thread_info );
|
||||
virtual_init_threading();
|
||||
|
||||
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.
|
||||
*/
|
||||
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 startup_info *startup_info = (struct startup_info *)info;
|
||||
PRTL_THREAD_START_ROUTINE func = startup_info->entry_point;
|
||||
void *arg = startup_info->entry_arg;
|
||||
PRTL_THREAD_START_ROUTINE func = info->entry_point;
|
||||
void *arg = info->entry_arg;
|
||||
struct debug_info debug_info;
|
||||
|
||||
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 );
|
||||
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 );
|
||||
|
||||
RtlAcquirePebLock();
|
||||
|
@ -531,7 +520,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
|||
DWORD tid = 0;
|
||||
int request_pipe[2];
|
||||
NTSTATUS status;
|
||||
SIZE_T size, page_size = getpagesize();
|
||||
SIZE_T size;
|
||||
|
||||
if (process != NtCurrentProcess())
|
||||
{
|
||||
|
@ -593,7 +582,10 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
|||
teb = addr;
|
||||
teb->Peb = NtCurrentTeb()->Peb;
|
||||
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;
|
||||
|
||||
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_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 */
|
||||
thread_regs->dr0 = ntdll_get_thread_regs()->dr0;
|
||||
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->dr7 = ntdll_get_thread_regs()->dr7;
|
||||
|
||||
if (!stack_reserve || !stack_commit)
|
||||
{
|
||||
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;
|
||||
if ((status = virtual_alloc_thread_stack( teb, stack_reserve, stack_commit ))) goto error;
|
||||
|
||||
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 */
|
||||
interlocked_xchg_add( &nb_threads, 1 );
|
||||
if (pthread_create( &pthread_id, &attr, (void * (*)(void *))start_thread, info ))
|
||||
{
|
||||
interlocked_xchg_add( &nb_threads, -1 );
|
||||
pthread_attr_destroy( &attr );
|
||||
size = 0;
|
||||
NtFreeVirtualMemory( NtCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
|
||||
status = STATUS_NO_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
|
@ -655,7 +632,7 @@ error:
|
|||
if (thread_data) wine_ldt_free_fs( thread_data->fs );
|
||||
if (addr)
|
||||
{
|
||||
SIZE_T size = 0;
|
||||
size = 0;
|
||||
NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
|
||||
}
|
||||
if (handle) NtClose( handle );
|
||||
|
|
|
@ -1396,33 +1396,33 @@ SIZE_T virtual_free_system_view( PVOID *addr_ptr )
|
|||
/***********************************************************************
|
||||
* 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;
|
||||
NTSTATUS status;
|
||||
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 );
|
||||
|
||||
if (base) /* already allocated, create a system view */
|
||||
{
|
||||
size = ROUND_SIZE( base, size );
|
||||
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
|
||||
/* 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 );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* setup no access guard page */
|
||||
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 );
|
||||
|
||||
/* note: limit is lower than base since the stack grows down */
|
||||
NtCurrentTeb()->DeallocationStack = view->base;
|
||||
NtCurrentTeb()->Tib.StackBase = (char *)view->base + view->size;
|
||||
NtCurrentTeb()->Tib.StackLimit = (char *)view->base + 2 * page_size;
|
||||
|
||||
teb->DeallocationStack = view->base;
|
||||
teb->Tib.StackBase = (char *)view->base + view->size;
|
||||
teb->Tib.StackLimit = (char *)view->base + 2 * page_size;
|
||||
done:
|
||||
server_leave_uninterrupted_section( &csVirtual, &sigset );
|
||||
return status;
|
||||
|
|
Loading…
Reference in New Issue