ntdll: Moved the TEB allocation routines to the platform-specific files.
This commit is contained in:
parent
d4fc2fd746
commit
d4f1fffacc
|
@ -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,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.@)
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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.@)
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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.@)
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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.@)
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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] );
|
||||
|
|
Loading…
Reference in New Issue