Added a VIRTUAL_alloc_teb function to allocate TEBs while making sure

they don't end up above the address space limit.
oldstable
Alexandre Julliard 2005-08-09 10:43:47 +00:00
parent b8d0f4cd10
commit 9f32a5c865
3 changed files with 78 additions and 45 deletions

View File

@ -51,7 +51,6 @@ extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handl
extern BOOL SIGNAL_Init(void); extern BOOL SIGNAL_Init(void);
extern void debug_init(void); extern void debug_init(void);
extern void thread_init(void); extern void thread_init(void);
extern void virtual_init(void);
/* server support */ /* server support */
extern time_t server_start_time; extern time_t server_start_time;
@ -90,6 +89,7 @@ extern NTSTATUS FILE_GetNtStatus(void);
extern BOOL DIR_is_hidden_file( const UNICODE_STRING *name ); extern BOOL DIR_is_hidden_file( const UNICODE_STRING *name );
/* virtual memory */ /* virtual memory */
extern NTSTATUS VIRTUAL_alloc_teb( void **ret, size_t size, BOOL first );
extern NTSTATUS VIRTUAL_HandleFault(LPCVOID addr); extern NTSTATUS VIRTUAL_HandleFault(LPCVOID addr);
extern BOOL VIRTUAL_HasMapping( LPCVOID addr ); extern BOOL VIRTUAL_HasMapping( LPCVOID addr );
extern void VIRTUAL_UseLargeAddressSpace(void); extern void VIRTUAL_UseLargeAddressSpace(void);

View File

@ -55,29 +55,26 @@ static LIST_ENTRY tls_links;
/*********************************************************************** /***********************************************************************
* alloc_teb * init_teb
*/ */
static TEB *alloc_teb( ULONG *size ) static inline NTSTATUS init_teb( TEB *teb )
{ {
TEB *teb; struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
struct ntdll_thread_data *thread_data;
*size = SIGNAL_STACK_SIZE + sizeof(TEB);
teb = wine_anon_mmap( NULL, *size, PROT_READ | PROT_WRITE, 0 );
if (teb == (TEB *)-1) return NULL;
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
if (!(thread_data->teb_sel = wine_ldt_alloc_fs()))
{
munmap( teb, *size );
return NULL;
}
teb->Tib.ExceptionList = (void *)~0UL; teb->Tib.ExceptionList = (void *)~0UL;
teb->Tib.StackBase = (void *)~0UL; teb->Tib.StackBase = (void *)~0UL;
teb->Tib.Self = &teb->Tib; teb->Tib.Self = &teb->Tib;
teb->Peb = &peb; teb->Peb = &peb;
teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
return teb;
if (!(thread_data->teb_sel = 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;
} }
@ -107,7 +104,7 @@ void thread_init(void)
{ {
TEB *teb; TEB *teb;
void *addr; void *addr;
ULONG size, info_size; ULONG info_size;
struct ntdll_thread_data *thread_data; struct ntdll_thread_data *thread_data;
struct wine_pthread_thread_info thread_info; struct wine_pthread_thread_info thread_info;
static struct debug_info debug_info; /* debug info for initial thread */ static struct debug_info debug_info; /* debug info for initial thread */
@ -127,19 +124,17 @@ void thread_init(void)
InitializeListHead( &ldr.InInitializationOrderModuleList ); InitializeListHead( &ldr.InInitializationOrderModuleList );
InitializeListHead( &tls_links ); InitializeListHead( &tls_links );
teb = alloc_teb( &size ); thread_info.teb_size = SIGNAL_STACK_SIZE + sizeof(TEB);
VIRTUAL_alloc_teb( &addr, thread_info.teb_size, TRUE );
teb = addr;
init_teb( teb );
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 );
thread_info.stack_base = NULL; thread_info.stack_base = NULL;
thread_info.stack_size = 0; thread_info.stack_size = 0;
thread_info.teb_base = teb; thread_info.teb_base = teb;
thread_info.teb_size = size;
thread_info.teb_sel = thread_data->teb_sel; thread_info.teb_sel = thread_data->teb_sel;
wine_pthread_init_current_teb( &thread_info ); wine_pthread_init_current_teb( &thread_info );
wine_pthread_init_thread( &thread_info ); wine_pthread_init_thread( &thread_info );
@ -147,17 +142,11 @@ void thread_init(void)
debug_info.str_pos = debug_info.strings; debug_info.str_pos = debug_info.strings;
debug_info.out_pos = debug_info.output; debug_info.out_pos = debug_info.output;
debug_init(); debug_init();
virtual_init();
/* setup the server connection */ /* setup the server connection */
server_init_process(); server_init_process();
info_size = server_init_thread( thread_info.pid, thread_info.tid, NULL ); info_size = server_init_thread( thread_info.pid, thread_info.tid, NULL );
/* create a memory view for the TEB */
addr = teb;
NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size,
MEM_SYSTEM, PAGE_READWRITE );
/* create the process heap */ /* create the process heap */
if (!(peb.ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL ))) if (!(peb.ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL )))
{ {
@ -245,12 +234,12 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
PRTL_THREAD_START_ROUTINE start, void *param, PRTL_THREAD_START_ROUTINE start, void *param,
HANDLE *handle_ptr, CLIENT_ID *id ) HANDLE *handle_ptr, CLIENT_ID *id )
{ {
struct ntdll_thread_data *thread_data; struct ntdll_thread_data *thread_data = NULL;
struct startup_info *info = NULL; struct startup_info *info = NULL;
void *addr;
HANDLE handle = 0; HANDLE handle = 0;
TEB *teb = NULL; TEB *teb;
DWORD tid = 0; DWORD tid = 0;
ULONG size;
int request_pipe[2]; int request_pipe[2];
NTSTATUS status; NTSTATUS status;
@ -286,24 +275,18 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
goto error; goto error;
} }
if (!(teb = alloc_teb( &size ))) info->pthread_info.teb_size = SIGNAL_STACK_SIZE + sizeof(TEB);
{ if ((status = VIRTUAL_alloc_teb( &addr, info->pthread_info.teb_size, FALSE ))) goto error;
status = STATUS_NO_MEMORY; teb = addr;
goto error; if ((status = init_teb( teb ))) goto error;
}
teb->ClientId.UniqueProcess = (HANDLE)GetCurrentProcessId(); teb->ClientId.UniqueProcess = (HANDLE)GetCurrentProcessId();
teb->ClientId.UniqueThread = (HANDLE)tid; teb->ClientId.UniqueThread = (HANDLE)tid;
thread_data = (struct ntdll_thread_data *)teb->SystemReserved2; thread_data = (struct ntdll_thread_data *)teb->SystemReserved2;
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;
info->pthread_info.teb_base = teb; info->pthread_info.teb_base = teb;
NtAllocateVirtualMemory( NtCurrentProcess(), &info->pthread_info.teb_base, 0, &size,
MEM_SYSTEM, PAGE_READWRITE );
info->pthread_info.teb_size = size;
info->pthread_info.teb_sel = thread_data->teb_sel; info->pthread_info.teb_sel = thread_data->teb_sel;
if (!stack_reserve || !stack_commit) if (!stack_reserve || !stack_commit)
@ -335,7 +318,12 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
return STATUS_SUCCESS; return STATUS_SUCCESS;
error: error:
if (teb) free_teb( teb ); if (thread_data) wine_ldt_free_fs( thread_data->teb_sel );
if (addr)
{
ULONG size = 0;
NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
}
if (info) RtlFreeHeap( GetProcessHeap(), 0, info ); if (info) RtlFreeHeap( GetProcessHeap(), 0, info );
if (handle) NtClose( handle ); if (handle) NtClose( handle );
close( request_pipe[1] ); close( request_pipe[1] );

View File

@ -1081,7 +1081,7 @@ BOOL is_current_process( HANDLE handle )
/*********************************************************************** /***********************************************************************
* virtual_init * virtual_init
*/ */
void virtual_init(void) static inline void virtual_init(void)
{ {
#ifndef page_mask #ifndef page_mask
page_size = getpagesize(); page_size = getpagesize();
@ -1094,6 +1094,51 @@ void virtual_init(void)
} }
/***********************************************************************
* VIRTUAL_alloc_teb
*
* Allocate a memory view for a new TEB. We don't care about granularity for TEBs.
*/
NTSTATUS VIRTUAL_alloc_teb( void **ret, size_t size, BOOL first )
{
void *ptr;
NTSTATUS status;
struct file_view *view;
BYTE vprot = VPROT_READ | VPROT_WRITE | VPROT_COMMITTED;
if (first) virtual_init();
*ret = NULL;
size = ROUND_SIZE( 0, size );
for (;;)
{
if ((ptr = wine_anon_mmap( NULL, size, VIRTUAL_GetUnixProt(vprot), 0 )) == (void *)-1)
{
if (errno == ENOMEM) return STATUS_NO_MEMORY;
return STATUS_INVALID_PARAMETER;
}
/* if we got something beyond the user limit, unmap it and retry */
if (is_beyond_limit( ptr, size, user_space_limit )) add_reserved_area( ptr, size );
else break;
}
if (!first) RtlEnterCriticalSection( &csVirtual );
status = create_view( &view, ptr, size, vprot );
if (status == STATUS_SUCCESS)
{
view->flags |= VFLAG_VALLOC;
*ret = ptr;
}
else unmap_area( ptr, size );
if (!first) RtlLeaveCriticalSection( &csVirtual );
return status;
}
/*********************************************************************** /***********************************************************************
* VIRTUAL_HandleFault * VIRTUAL_HandleFault
*/ */
@ -1456,7 +1501,7 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
{ {
/* make the address space end at the user limit, except if /* make the address space end at the user limit, except if
* the last view was mapped beyond that */ * the last view was mapped beyond that */
if (alloc_base < (char *)user_space_limit) if (alloc_base <= (char *)user_space_limit)
{ {
if (user_space_limit && base >= (char *)user_space_limit) if (user_space_limit && base >= (char *)user_space_limit)
{ {