Commit d4f1fffa authored by Alexandre Julliard's avatar Alexandre Julliard

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

parent d4fc2fd7
......@@ -59,9 +59,10 @@ extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handl
const LARGE_INTEGER *timeout, HANDLE signal_object );
/* 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_process(void);
extern size_t get_signal_stack_total_size(void);
extern void version_init( const WCHAR *appname );
extern void debug_init(void);
extern HANDLE thread_init(void);
......
......@@ -1995,35 +1995,74 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext )
}
/***********************************************************************
* __wine_set_signal_handler (NTDLL.@)
*/
int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
{
if (sig >= sizeof(handlers) / sizeof(handlers[0])) return -1;
if (handlers[sig] != NULL) return -2;
handlers[sig] = wsh;
return 0;
}
/**********************************************************************
* 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.
* signal_alloc_thread
*/
size_t get_signal_stack_total_size(void)
NTSTATUS signal_alloc_thread( TEB **teb )
{
if (!signal_stack_size)
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 size = 8192, min_size = teb_size + max( MINSIGSTKSZ, 8192 );
size_t 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;
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 signal_stack_size + teb_size;
}
return status;
}
/***********************************************************************
* __wine_set_signal_handler (NTDLL.@)
/**********************************************************************
* signal_free_thread
*/
int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
void signal_free_thread( TEB *teb )
{
if (sig >= sizeof(handlers) / sizeof(handlers[0])) return -1;
if (handlers[sig] != NULL) return -2;
handlers[sig] = wsh;
return 0;
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 );
}
......
......@@ -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.@)
*/
......@@ -991,6 +978,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
*/
void signal_init_thread( TEB *teb )
......
......@@ -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.@)
*/
......@@ -726,6 +713,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
*/
void signal_init_thread( TEB *teb )
......
......@@ -2191,35 +2191,63 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *ucontext )
}
/***********************************************************************
* __wine_set_signal_handler (NTDLL.@)
*/
int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
{
if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
if (handlers[sig] != NULL) return -2;
handlers[sig] = wsh;
return 0;
}
/**********************************************************************
* 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.
* signal_alloc_thread
*/
size_t get_signal_stack_total_size(void)
NTSTATUS signal_alloc_thread( TEB **teb )
{
assert( sizeof(TEB) <= teb_size );
if (!signal_stack_size)
static size_t sigstack_zero_bits;
SIZE_T size;
NTSTATUS status;
if (!sigstack_zero_bits)
{
size_t size = 8192, min_size = teb_size + max( MINSIGSTKSZ, 8192 );
size_t 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;
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 signal_stack_size + teb_size;
return status;
}
/***********************************************************************
* __wine_set_signal_handler (NTDLL.@)
/**********************************************************************
* signal_free_thread
*/
int CDECL __wine_set_signal_handler(unsigned int sig, wine_signal_handler wsh)
void signal_free_thread( TEB *teb )
{
if (sig > sizeof(handlers) / sizeof(handlers[0])) return -1;
if (handlers[sig] != NULL) return -2;
handlers[sig] = wsh;
return 0;
SIZE_T size;
if (teb->DeallocationStack)
{
size = 0;
NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
}
size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE );
}
......
......@@ -64,8 +64,6 @@ static RTL_BITMAP tls_bitmap;
static RTL_BITMAP tls_expansion_bitmap;
static RTL_BITMAP fls_bitmap;
static LIST_ENTRY tls_links;
static size_t sigstack_total_size;
static ULONG sigstack_zero_bits;
static int nb_threads = 1;
static RTL_CRITICAL_SECTION ldt_section;
......@@ -103,29 +101,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
*
* Copy a unicode string from the startup info.
......@@ -297,19 +272,17 @@ HANDLE thread_init(void)
/* allocate and initialize the initial TEB */
sigstack_total_size = get_signal_stack_total_size();
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;
signal_alloc_thread( &teb );
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->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;
InsertHeadList( &tls_links, &teb->TlsLinks );
......@@ -417,14 +390,9 @@ void exit_thread( int status )
if ((teb = interlocked_xchg_ptr( &prev_teb, NtCurrentTeb() )))
{
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
SIZE_T size;
pthread_join( thread_data->pthread_id, NULL );
wine_ldt_free_fs( thread_data->fs );
size = 0;
NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
size = 0;
NtFreeVirtualMemory( GetCurrentProcess(), (void **)&teb, &size, MEM_RELEASE );
signal_free_thread( teb );
}
close( ntdll_get_thread_data()->wait_fd[0] );
......@@ -482,16 +450,14 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
sigset_t sigset;
pthread_t pthread_id;
pthread_attr_t attr;
struct ntdll_thread_data *thread_data = NULL;
struct ntdll_thread_data *thread_data;
struct ntdll_thread_regs *thread_regs;
struct startup_info *info = NULL;
void *addr = NULL;
HANDLE handle = 0;
TEB *teb;
TEB *teb = NULL;
DWORD tid = 0;
int request_pipe[2];
NTSTATUS status;
SIZE_T size;
if (process != NtCurrentProcess())
{
......@@ -544,26 +510,25 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
pthread_sigmask( SIG_BLOCK, &server_block_set, &sigset );
addr = NULL;
size = sigstack_total_size;
if ((status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, sigstack_zero_bits,
&size, MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE )))
goto error;
teb = addr;
if ((status = signal_alloc_thread( &teb ))) goto error;
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->teb = teb;
info->entry_point = start;
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_regs = (struct ntdll_thread_regs *)teb->SpareBytes1;
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 */
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 );
pthread_attr_destroy( &attr );
size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
status = STATUS_NO_MEMORY;
goto error;
}
......@@ -599,12 +562,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
return STATUS_SUCCESS;
error:
if (thread_data) wine_ldt_free_fs( thread_data->fs );
if (addr)
{
size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
}
if (teb) signal_free_thread( teb );
if (handle) NtClose( handle );
pthread_sigmask( SIG_SETMASK, &sigset, NULL );
close( request_pipe[1] );
......
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