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

This commit is contained in:
Alexandre Julliard 2009-02-23 14:24:59 +01:00
parent 67e45d66d3
commit 1056771b91
4 changed files with 39 additions and 67 deletions

View File

@ -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();

View File

@ -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 );

View File

@ -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 );

View File

@ -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;
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 );
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;