ntdll: Moved the TEB allocation routines to the platform-specific files.

This commit is contained in:
Alexandre Julliard 2009-11-19 12:25:52 +01:00
parent d4fc2fd746
commit d4f1fffacc
6 changed files with 224 additions and 132 deletions

View File

@ -59,9 +59,10 @@ extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handl
const LARGE_INTEGER *timeout, HANDLE signal_object ); const LARGE_INTEGER *timeout, HANDLE signal_object );
/* init routines */ /* init routines */
extern NTSTATUS signal_alloc_thread( TEB **teb );
extern void signal_free_thread( TEB *teb );
extern void signal_init_thread( TEB *teb ); extern void signal_init_thread( TEB *teb );
extern void signal_init_process(void); extern void signal_init_process(void);
extern size_t get_signal_stack_total_size(void);
extern void version_init( const WCHAR *appname ); extern void version_init( const WCHAR *appname );
extern void debug_init(void); extern void debug_init(void);
extern HANDLE thread_init(void); extern HANDLE thread_init(void);

View File

@ -1995,26 +1995,6 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext )
} }
/**********************************************************************
* get_signal_stack_total_size
*
* Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
* Must be a power of two.
*/
size_t get_signal_stack_total_size(void)
{
if (!signal_stack_size)
{
size_t size = 8192, min_size = teb_size + max( MINSIGSTKSZ, 8192 );
/* find the first power of two not smaller than min_size */
while (size < min_size) size *= 2;
signal_stack_mask = size - 1;
signal_stack_size = size - teb_size;
}
return signal_stack_size + teb_size;
}
/*********************************************************************** /***********************************************************************
* __wine_set_signal_handler (NTDLL.@) * __wine_set_signal_handler (NTDLL.@)
*/ */
@ -2027,6 +2007,65 @@ int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
} }
/**********************************************************************
* signal_alloc_thread
*/
NTSTATUS signal_alloc_thread( TEB **teb )
{
static size_t sigstack_zero_bits;
struct ntdll_thread_data *thread_data;
SIZE_T size;
void *addr = NULL;
NTSTATUS status;
if (!sigstack_zero_bits)
{
size_t min_size = teb_size + max( MINSIGSTKSZ, 8192 );
/* find the first power of two not smaller than min_size */
sigstack_zero_bits = 12;
while ((1u << sigstack_zero_bits) < min_size) sigstack_zero_bits++;
signal_stack_mask = (1 << sigstack_zero_bits) - 1;
signal_stack_size = (1 << sigstack_zero_bits) - teb_size;
}
size = signal_stack_mask + 1;
if (!(status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, sigstack_zero_bits,
&size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE )))
{
*teb = addr;
(*teb)->Tib.Self = &(*teb)->Tib;
(*teb)->Tib.ExceptionList = (void *)~0UL;
thread_data = (struct ntdll_thread_data *)(*teb)->SystemReserved2;
if (!(thread_data->fs = wine_ldt_alloc_fs()))
{
size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
status = STATUS_TOO_MANY_THREADS;
}
}
return status;
}
/**********************************************************************
* signal_free_thread
*/
void signal_free_thread( TEB *teb )
{
SIZE_T size;
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
if (thread_data) wine_ldt_free_fs( thread_data->fs );
if (teb->DeallocationStack)
{
size = 0;
NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
}
size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE );
}
/********************************************************************** /**********************************************************************
* signal_init_thread * signal_init_thread
*/ */

View File

@ -965,19 +965,6 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext )
} }
/**********************************************************************
* get_signal_stack_total_size
*
* Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
* Must be a power of two.
*/
size_t get_signal_stack_total_size(void)
{
assert( sizeof(TEB) <= getpagesize() );
return getpagesize(); /* this is just for the TEB, we don't need a signal stack */
}
/*********************************************************************** /***********************************************************************
* __wine_set_signal_handler (NTDLL.@) * __wine_set_signal_handler (NTDLL.@)
*/ */
@ -990,6 +977,52 @@ int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
} }
/**********************************************************************
* signal_alloc_thread
*/
NTSTATUS signal_alloc_thread( TEB **teb )
{
static size_t sigstack_zero_bits;
SIZE_T size;
NTSTATUS status;
if (!sigstack_zero_bits)
{
size_t min_size = getpagesize(); /* this is just for the TEB, we don't use a signal stack yet */
/* find the first power of two not smaller than min_size */
while ((1u << sigstack_zero_bits) < min_size) sigstack_zero_bits++;
assert( sizeof(TEB) <= min_size );
}
size = 1 << sigstack_zero_bits;
*teb = NULL;
if (!(status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)teb, sigstack_zero_bits,
&size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE )))
{
(*teb)->Tib.Self = &(*teb)->Tib;
(*teb)->Tib.ExceptionList = (void *)~0UL;
}
return status;
}
/**********************************************************************
* signal_free_thread
*/
void signal_free_thread( TEB *teb )
{
SIZE_T size;
if (teb->DeallocationStack)
{
size = 0;
NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
}
size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE );
}
/********************************************************************** /**********************************************************************
* signal_init_thread * signal_init_thread
*/ */

View File

@ -700,19 +700,6 @@ static void usr1_handler( int signal, struct siginfo *info, void *ucontext )
} }
/**********************************************************************
* get_signal_stack_total_size
*
* Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
* Must be a power of two.
*/
size_t get_signal_stack_total_size(void)
{
assert( sizeof(TEB) <= getpagesize() );
return getpagesize(); /* this is just for the TEB, we don't need a signal stack */
}
/*********************************************************************** /***********************************************************************
* __wine_set_signal_handler (NTDLL.@) * __wine_set_signal_handler (NTDLL.@)
*/ */
@ -725,6 +712,52 @@ int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
} }
/**********************************************************************
* signal_alloc_thread
*/
NTSTATUS signal_alloc_thread( TEB **teb )
{
static size_t sigstack_zero_bits;
SIZE_T size;
NTSTATUS status;
if (!sigstack_zero_bits)
{
size_t min_size = getpagesize(); /* this is just for the TEB, we don't use a signal stack yet */
/* find the first power of two not smaller than min_size */
while ((1u << sigstack_zero_bits) < min_size) sigstack_zero_bits++;
assert( sizeof(TEB) <= min_size );
}
size = 1 << sigstack_zero_bits;
*teb = NULL;
if (!(status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)teb, sigstack_zero_bits,
&size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE )))
{
(*teb)->Tib.Self = &(*teb)->Tib;
(*teb)->Tib.ExceptionList = (void *)~0UL;
}
return status;
}
/**********************************************************************
* signal_free_thread
*/
void signal_free_thread( TEB *teb )
{
SIZE_T size;
if (teb->DeallocationStack)
{
size = 0;
NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
}
size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE );
}
/********************************************************************** /**********************************************************************
* signal_init_thread * signal_init_thread
*/ */

View File

@ -2191,26 +2191,6 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *ucontext )
} }
/**********************************************************************
* get_signal_stack_total_size
*
* Retrieve the size to allocate for the signal stack, including the TEB at the bottom.
* Must be a power of two.
*/
size_t get_signal_stack_total_size(void)
{
assert( sizeof(TEB) <= teb_size );
if (!signal_stack_size)
{
size_t size = 8192, min_size = teb_size + max( MINSIGSTKSZ, 8192 );
/* find the first power of two not smaller than min_size */
while (size < min_size) size *= 2;
signal_stack_size = size - teb_size;
}
return signal_stack_size + teb_size;
}
/*********************************************************************** /***********************************************************************
* __wine_set_signal_handler (NTDLL.@) * __wine_set_signal_handler (NTDLL.@)
*/ */
@ -2223,6 +2203,54 @@ int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
} }
/**********************************************************************
* signal_alloc_thread
*/
NTSTATUS signal_alloc_thread( TEB **teb )
{
static size_t sigstack_zero_bits;
SIZE_T size;
NTSTATUS status;
if (!sigstack_zero_bits)
{
size_t min_size = teb_size + max( MINSIGSTKSZ, 8192 );
/* find the first power of two not smaller than min_size */
sigstack_zero_bits = 12;
while ((1u << sigstack_zero_bits) < min_size) sigstack_zero_bits++;
signal_stack_size = (1 << sigstack_zero_bits) - teb_size;
assert( sizeof(TEB) <= teb_size );
}
size = 1 << sigstack_zero_bits;
*teb = NULL;
if (!(status = NtAllocateVirtualMemory( NtCurrentProcess(), (void **)teb, sigstack_zero_bits,
&size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE )))
{
(*teb)->Tib.Self = &(*teb)->Tib;
(*teb)->Tib.ExceptionList = (void *)~0UL;
}
return status;
}
/**********************************************************************
* signal_free_thread
*/
void signal_free_thread( TEB *teb )
{
SIZE_T size;
if (teb->DeallocationStack)
{
size = 0;
NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
}
size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE );
}
/********************************************************************** /**********************************************************************
* signal_init_thread * signal_init_thread
*/ */

View File

@ -64,8 +64,6 @@ 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 LIST_ENTRY tls_links;
static size_t sigstack_total_size;
static ULONG sigstack_zero_bits;
static int nb_threads = 1; static int nb_threads = 1;
static RTL_CRITICAL_SECTION ldt_section; static RTL_CRITICAL_SECTION ldt_section;
@ -102,29 +100,6 @@ static void ldt_unlock(void)
} }
/***********************************************************************
* init_teb
*/
static inline NTSTATUS init_teb( TEB *teb )
{
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
teb->Tib.ExceptionList = (void *)~0UL;
teb->Tib.StackBase = (void *)~0UL;
teb->Tib.Self = &teb->Tib;
teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
if (!(thread_data->fs = wine_ldt_alloc_fs())) return STATUS_TOO_MANY_THREADS;
thread_data->request_fd = -1;
thread_data->reply_fd = -1;
thread_data->wait_fd[0] = -1;
thread_data->wait_fd[1] = -1;
return STATUS_SUCCESS;
}
/*********************************************************************** /***********************************************************************
* get_unicode_string * get_unicode_string
* *
@ -297,19 +272,17 @@ HANDLE thread_init(void)
/* allocate and initialize the initial TEB */ /* allocate and initialize the initial TEB */
sigstack_total_size = get_signal_stack_total_size(); signal_alloc_thread( &teb );
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) );
addr = NULL;
size = sigstack_total_size;
NtAllocateVirtualMemory( NtCurrentProcess(), &addr, sigstack_zero_bits,
&size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE );
teb = addr;
teb->Peb = peb; teb->Peb = peb;
init_teb( teb ); teb->Tib.StackBase = (void *)~0UL;
teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2; thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
thread_data->request_fd = -1;
thread_data->reply_fd = -1;
thread_data->wait_fd[0] = -1;
thread_data->wait_fd[1] = -1;
thread_data->debug_info = &debug_info; thread_data->debug_info = &debug_info;
InsertHeadList( &tls_links, &teb->TlsLinks ); InsertHeadList( &tls_links, &teb->TlsLinks );
@ -417,14 +390,9 @@ void exit_thread( int status )
if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() ))) if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() )))
{ {
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2; struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
SIZE_T size;
pthread_join( thread_data->pthread_id, NULL ); pthread_join( thread_data->pthread_id, NULL );
wine_ldt_free_fs( thread_data->fs ); signal_free_thread( teb );
size = 0;
NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
size = 0;
NtFreeVirtualMemory( GetCurrentProcess(), (void **)&teb, &size, MEM_RELEASE );
} }
close( ntdll_get_thread_data()->wait_fd[0] ); close( ntdll_get_thread_data()->wait_fd[0] );
@ -482,16 +450,14 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
sigset_t sigset; sigset_t sigset;
pthread_t pthread_id; pthread_t pthread_id;
pthread_attr_t attr; pthread_attr_t attr;
struct ntdll_thread_data *thread_data = NULL; struct ntdll_thread_data *thread_data;
struct ntdll_thread_regs *thread_regs; struct ntdll_thread_regs *thread_regs;
struct startup_info *info = NULL; struct startup_info *info = NULL;
void *addr = NULL;
HANDLE handle = 0; HANDLE handle = 0;
TEB *teb; TEB *teb = NULL;
DWORD tid = 0; DWORD tid = 0;
int request_pipe[2]; int request_pipe[2];
NTSTATUS status; NTSTATUS status;
SIZE_T size;
if (process != NtCurrentProcess()) if (process != NtCurrentProcess())
{ {
@ -544,26 +510,25 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
pthread_sigmask( SIG_BLOCK, &server_block_set, &sigset ); pthread_sigmask( SIG_BLOCK, &server_block_set, &sigset );
addr = NULL; if ((status = signal_alloc_thread( &teb ))) goto error;
size = sigstack_total_size;
if ((status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, sigstack_zero_bits,
&size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE )))
goto error;
teb = addr;
teb->Peb = NtCurrentTeb()->Peb; teb->Peb = NtCurrentTeb()->Peb;
teb->ClientId.UniqueProcess = ULongToHandle(GetCurrentProcessId());
teb->ClientId.UniqueThread = ULongToHandle(tid);
teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
info = (struct startup_info *)(teb + 1); info = (struct startup_info *)(teb + 1);
info->teb = teb; info->teb = teb;
info->entry_point = start; info->entry_point = start;
info->entry_arg = param; info->entry_arg = param;
if ((status = init_teb( teb ))) goto error;
teb->ClientId.UniqueProcess = ULongToHandle(GetCurrentProcessId());
teb->ClientId.UniqueThread = ULongToHandle(tid);
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2; thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
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];
thread_data->reply_fd = -1;
thread_data->wait_fd[0] = -1;
thread_data->wait_fd[1] = -1;
/* 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;
@ -584,8 +549,6 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
{ {
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;
} }
@ -599,12 +562,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
return STATUS_SUCCESS; return STATUS_SUCCESS;
error: error:
if (thread_data) wine_ldt_free_fs( thread_data->fs ); if (teb) signal_free_thread( teb );
if (addr)
{
size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
}
if (handle) NtClose( handle ); if (handle) NtClose( handle );
pthread_sigmask( SIG_SETMASK, &sigset, NULL ); pthread_sigmask( SIG_SETMASK, &sigset, NULL );
close( request_pipe[1] ); close( request_pipe[1] );