Allocate the TEB and signal stack separately from the main stack.
Dynamically allocate the initial TEB too so that it is properly page-aligned.
This commit is contained in:
parent
bcb09c198d
commit
7924f421e9
|
@ -55,32 +55,22 @@ WINE_DECLARE_DEBUG_CHANNEL(relay);
|
|||
*/
|
||||
TEB *THREAD_InitStack( TEB *teb, DWORD stack_size )
|
||||
{
|
||||
DWORD old_prot, total_size;
|
||||
DWORD old_prot;
|
||||
DWORD page_size = getpagesize();
|
||||
void *base;
|
||||
|
||||
/* Memory layout in allocated block:
|
||||
*
|
||||
* size contents
|
||||
* SIGNAL_STACK_SIZE signal stack
|
||||
* stack_size normal stack (including a PAGE_GUARD page at the bottom)
|
||||
* 1 page TEB (except for initial thread)
|
||||
*/
|
||||
|
||||
stack_size = (stack_size + (page_size - 1)) & ~(page_size - 1);
|
||||
total_size = stack_size + SIGNAL_STACK_SIZE;
|
||||
|
||||
if (!(base = VirtualAlloc( NULL, total_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE )))
|
||||
if (!(base = VirtualAlloc( NULL, stack_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE )))
|
||||
return NULL;
|
||||
|
||||
teb->DeallocationStack = base;
|
||||
teb->Tib.StackBase = (char *)base + SIGNAL_STACK_SIZE + stack_size;
|
||||
teb->Tib.StackBase = (char *)base + stack_size;
|
||||
teb->Tib.StackLimit = base; /* note: limit is lower than base since the stack grows down */
|
||||
|
||||
/* Setup guard pages */
|
||||
|
||||
VirtualProtect( (char *)base + SIGNAL_STACK_SIZE, 1,
|
||||
PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old_prot );
|
||||
VirtualProtect( base, 1, PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old_prot );
|
||||
return teb;
|
||||
}
|
||||
|
||||
|
|
|
@ -1933,16 +1933,7 @@ void __wine_process_init( int argc, char *argv[] )
|
|||
ANSI_STRING func_name;
|
||||
void (* DECLSPEC_NORETURN init_func)();
|
||||
|
||||
/* setup the server connection */
|
||||
wine_server_init_process();
|
||||
wine_server_init_thread();
|
||||
|
||||
/* create the process heap */
|
||||
if (!(NtCurrentTeb()->Peb->ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL )))
|
||||
{
|
||||
MESSAGE( "wine: failed to create the process heap\n" );
|
||||
exit(1);
|
||||
}
|
||||
thread_init();
|
||||
|
||||
/* setup the load callback and create ntdll modref */
|
||||
wine_dll_set_callback( load_builtin_callback );
|
||||
|
|
|
@ -31,6 +31,13 @@
|
|||
#include "thread.h"
|
||||
#include "wine/server.h"
|
||||
|
||||
/* The per-thread signal stack size */
|
||||
#ifdef __i386__
|
||||
#define SIGNAL_STACK_SIZE 4096
|
||||
#else
|
||||
#define SIGNAL_STACK_SIZE 0 /* we don't need a signal stack on non-i386 */
|
||||
#endif
|
||||
|
||||
/* debug helper */
|
||||
extern LPCSTR debugstr_us( const UNICODE_STRING *str );
|
||||
extern void dump_ObjectAttributes (const OBJECT_ATTRIBUTES *ObjectAttributes);
|
||||
|
@ -38,7 +45,11 @@ extern void dump_ObjectAttributes (const OBJECT_ATTRIBUTES *ObjectAttributes);
|
|||
extern void NTDLL_get_server_timeout( abs_time_t *when, const LARGE_INTEGER *timeout );
|
||||
extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UINT flags,
|
||||
const LARGE_INTEGER *timeout );
|
||||
|
||||
/* init routines */
|
||||
extern void wine_server_init_process(void);
|
||||
extern void wine_server_init_thread(void);
|
||||
extern void thread_init(void);
|
||||
|
||||
/* module handling */
|
||||
extern BOOL MODULE_GetSystemDirectory( UNICODE_STRING *sysdir );
|
||||
|
|
|
@ -466,7 +466,7 @@ static inline int get_error_code( const SIGCONTEXT *sigcontext )
|
|||
*/
|
||||
static inline void *get_signal_stack(void)
|
||||
{
|
||||
return NtCurrentTeb()->DeallocationStack;
|
||||
return (char *)NtCurrentTeb() + 4096;
|
||||
}
|
||||
|
||||
|
||||
|
@ -831,19 +831,20 @@ static EXCEPTION_RECORD *setup_exception( SIGCONTEXT *sigcontext, raise_func fun
|
|||
SYSDEPS_AbortThread(1);
|
||||
}
|
||||
|
||||
if ((char *)(stack - 1) < (char *)NtCurrentTeb()->Tib.StackLimit + SIGNAL_STACK_SIZE + 4096 ||
|
||||
if ((char *)(stack - 1) < (char *)NtCurrentTeb()->Tib.StackLimit + 4096 ||
|
||||
(char *)stack > (char *)NtCurrentTeb()->Tib.StackBase)
|
||||
{
|
||||
UINT diff = (char *)NtCurrentTeb()->Tib.StackLimit + SIGNAL_STACK_SIZE + 4096 - (char *)stack;
|
||||
UINT diff = (char *)NtCurrentTeb()->Tib.StackLimit + 4096 - (char *)stack;
|
||||
if (diff < 4096)
|
||||
{
|
||||
ERR( "stack overflow %u bytes in thread %04lx eip %08lx esp %08lx stack %p-%p\n",
|
||||
diff, GetCurrentThreadId(), EIP_sig(sigcontext), ESP_sig(sigcontext),
|
||||
NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase );
|
||||
else
|
||||
ERR( "exception outside of stack limits in thread %04lx eip %08lx esp %08lx stack %p-%p\n",
|
||||
GetCurrentThreadId(), EIP_sig(sigcontext), ESP_sig(sigcontext),
|
||||
NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase );
|
||||
SYSDEPS_AbortThread(1);
|
||||
SYSDEPS_AbortThread(1);
|
||||
}
|
||||
else WARN( "exception outside of stack limits in thread %04lx eip %08lx esp %08lx stack %p-%p\n",
|
||||
GetCurrentThreadId(), EIP_sig(sigcontext), ESP_sig(sigcontext),
|
||||
NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase );
|
||||
}
|
||||
|
||||
stack--; /* push the stack_layout structure */
|
||||
|
|
|
@ -58,7 +58,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(thread);
|
|||
struct thread_cleanup_info
|
||||
{
|
||||
void *stack_base;
|
||||
int stack_size;
|
||||
ULONG stack_size;
|
||||
void *teb_base;
|
||||
ULONG teb_size;
|
||||
int status;
|
||||
};
|
||||
|
||||
|
@ -126,6 +128,7 @@ static void cleanup_thread( void *ptr )
|
|||
/* copy the info structure since it is on the stack we will free */
|
||||
struct thread_cleanup_info info = *(struct thread_cleanup_info *)ptr;
|
||||
munmap( info.stack_base, info.stack_size );
|
||||
munmap( info.teb_base, info.teb_size );
|
||||
wine_ldt_free_fs( wine_get_fs() );
|
||||
#ifdef HAVE__LWP_CREATE
|
||||
_lwp_exit();
|
||||
|
@ -196,15 +199,13 @@ int SYSDEPS_SpawnThread( void (*func)(TEB *), TEB *teb )
|
|||
*/
|
||||
void SYSDEPS_ExitThread( int status )
|
||||
{
|
||||
TEB *teb = NtCurrentTeb();
|
||||
DWORD size = 0;
|
||||
|
||||
#ifdef HAVE_NPTL
|
||||
static TEB *teb_to_free;
|
||||
TEB *free_teb;
|
||||
|
||||
if ((free_teb = interlocked_xchg_ptr( (void **)&teb_to_free, teb )) != NULL)
|
||||
if ((free_teb = interlocked_xchg_ptr( (void **)&teb_to_free, NtCurrentTeb() )) != NULL)
|
||||
{
|
||||
DWORD size = 0;
|
||||
void *ptr;
|
||||
|
||||
TRACE("freeing prev teb %p stack %p fs %04x\n",
|
||||
|
@ -214,26 +215,28 @@ void SYSDEPS_ExitThread( int status )
|
|||
wine_ldt_free_fs( free_teb->teb_sel );
|
||||
ptr = free_teb->DeallocationStack;
|
||||
NtFreeVirtualMemory( GetCurrentProcess(), &ptr, &size, MEM_RELEASE );
|
||||
ptr = free_teb;
|
||||
NtFreeVirtualMemory( GetCurrentProcess(), &ptr, &size, MEM_RELEASE | MEM_SYSTEM );
|
||||
munmap( ptr, size );
|
||||
}
|
||||
SYSDEPS_AbortThread( status );
|
||||
#else
|
||||
struct thread_cleanup_info info;
|
||||
MEMORY_BASIC_INFORMATION meminfo;
|
||||
|
||||
NtQueryVirtualMemory( GetCurrentProcess(), teb->Tib.StackBase, MemoryBasicInformation,
|
||||
&meminfo, sizeof(meminfo), NULL );
|
||||
info.stack_base = meminfo.AllocationBase;
|
||||
info.stack_size = meminfo.RegionSize + ((char *)teb->Tib.StackBase - (char *)meminfo.AllocationBase);
|
||||
info.status = status;
|
||||
|
||||
SIGNAL_Block();
|
||||
size = 0;
|
||||
NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE | MEM_SYSTEM );
|
||||
close( teb->wait_fd[0] );
|
||||
close( teb->wait_fd[1] );
|
||||
close( teb->reply_fd );
|
||||
close( teb->request_fd );
|
||||
SIGNAL_Reset();
|
||||
info.status = status;
|
||||
info.stack_base = NtCurrentTeb()->DeallocationStack;
|
||||
info.stack_size = 0;
|
||||
NtFreeVirtualMemory( GetCurrentProcess(), &info.stack_base,
|
||||
&info.stack_size, MEM_RELEASE | MEM_SYSTEM );
|
||||
info.teb_base = NtCurrentTeb();
|
||||
info.teb_size = 0;
|
||||
NtFreeVirtualMemory( GetCurrentProcess(), &info.teb_base,
|
||||
&info.teb_size, MEM_RELEASE | MEM_SYSTEM );
|
||||
close( NtCurrentTeb()->wait_fd[0] );
|
||||
close( NtCurrentTeb()->wait_fd[1] );
|
||||
close( NtCurrentTeb()->reply_fd );
|
||||
close( NtCurrentTeb()->request_fd );
|
||||
wine_switch_to_stack( cleanup_thread, &info, get_temp_stack() );
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -21,15 +21,68 @@
|
|||
#include "config.h"
|
||||
#include "wine/port.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include "ntstatus.h"
|
||||
#include "thread.h"
|
||||
#include "winternl.h"
|
||||
#include "wine/library.h"
|
||||
#include "wine/server.h"
|
||||
#include "wine/debug.h"
|
||||
#include "ntdll_misc.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(thread);
|
||||
|
||||
static PEB peb;
|
||||
static PEB_LDR_DATA ldr;
|
||||
static RTL_USER_PROCESS_PARAMETERS params; /* default parameters if no parent */
|
||||
static RTL_BITMAP tls_bitmap;
|
||||
static LIST_ENTRY tls_links;
|
||||
static struct debug_info info; /* debug info for initial thread */
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* alloc_teb
|
||||
*/
|
||||
static TEB *alloc_teb( ULONG *size )
|
||||
{
|
||||
TEB *teb;
|
||||
|
||||
*size = SIGNAL_STACK_SIZE + sizeof(TEB);
|
||||
teb = wine_anon_mmap( NULL, *size, PROT_READ | PROT_WRITE | PROT_EXEC, 0 );
|
||||
if (teb == (TEB *)-1) return NULL;
|
||||
if (!(teb->teb_sel = wine_ldt_alloc_fs()))
|
||||
{
|
||||
munmap( teb, *size );
|
||||
return NULL;
|
||||
}
|
||||
teb->Tib.ExceptionList = (void *)~0UL;
|
||||
teb->Tib.Self = &teb->Tib;
|
||||
teb->Peb = &peb;
|
||||
teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
|
||||
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
|
||||
return teb;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* free_teb
|
||||
*/
|
||||
static inline void free_teb( TEB *teb )
|
||||
{
|
||||
ULONG size = 0;
|
||||
void *addr = teb;
|
||||
|
||||
if (teb->DeallocationStack)
|
||||
NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE );
|
||||
NtFreeVirtualMemory( GetCurrentProcess(), &addr, &size, MEM_RELEASE );
|
||||
wine_ldt_free_fs( teb->teb_sel );
|
||||
munmap( teb, SIGNAL_STACK_SIZE + sizeof(TEB) );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* thread_init
|
||||
|
@ -38,35 +91,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(thread);
|
|||
*
|
||||
* NOTES: The first allocated TEB on NT is at 0x7ffde000.
|
||||
*/
|
||||
DECL_GLOBAL_CONSTRUCTOR(thread_init)
|
||||
void thread_init(void)
|
||||
{
|
||||
static TEB teb;
|
||||
static PEB peb;
|
||||
static PEB_LDR_DATA ldr;
|
||||
static RTL_USER_PROCESS_PARAMETERS params; /* default parameters if no parent */
|
||||
static RTL_BITMAP tls_bitmap;
|
||||
static struct debug_info info; /* debug info for initial thread */
|
||||
|
||||
if (teb.Tib.Self) return; /* do it only once */
|
||||
TEB *teb;
|
||||
void *addr;
|
||||
ULONG size;
|
||||
|
||||
info.str_pos = info.strings;
|
||||
info.out_pos = info.output;
|
||||
|
||||
teb.Tib.ExceptionList = (void *)~0UL;
|
||||
teb.Tib.StackBase = (void *)~0UL;
|
||||
teb.Tib.Self = &teb.Tib;
|
||||
teb.Peb = &peb;
|
||||
teb.tibflags = TEBF_WIN32;
|
||||
teb.request_fd = -1;
|
||||
teb.reply_fd = -1;
|
||||
teb.wait_fd[0] = -1;
|
||||
teb.wait_fd[1] = -1;
|
||||
teb.teb_sel = wine_ldt_alloc_fs();
|
||||
teb.debug_info = &info;
|
||||
teb.StaticUnicodeString.MaximumLength = sizeof(teb.StaticUnicodeBuffer);
|
||||
teb.StaticUnicodeString.Buffer = teb.StaticUnicodeBuffer;
|
||||
InitializeListHead( &teb.TlsLinks );
|
||||
|
||||
peb.ProcessParameters = ¶ms;
|
||||
peb.TlsBitmap = &tls_bitmap;
|
||||
peb.LdrData = &ldr;
|
||||
|
@ -74,12 +107,42 @@ DECL_GLOBAL_CONSTRUCTOR(thread_init)
|
|||
InitializeListHead( &ldr.InLoadOrderModuleList );
|
||||
InitializeListHead( &ldr.InMemoryOrderModuleList );
|
||||
InitializeListHead( &ldr.InInitializationOrderModuleList );
|
||||
InitializeListHead( &tls_links );
|
||||
|
||||
SYSDEPS_SetCurThread( &teb );
|
||||
teb = alloc_teb( &size );
|
||||
teb->Tib.StackBase = (void *)~0UL;
|
||||
teb->tibflags = TEBF_WIN32;
|
||||
teb->request_fd = -1;
|
||||
teb->reply_fd = -1;
|
||||
teb->wait_fd[0] = -1;
|
||||
teb->wait_fd[1] = -1;
|
||||
teb->debug_info = &info;
|
||||
InsertHeadList( &tls_links, &teb->TlsLinks );
|
||||
|
||||
SYSDEPS_SetCurThread( teb );
|
||||
|
||||
/* setup the server connection */
|
||||
wine_server_init_process();
|
||||
wine_server_init_thread();
|
||||
|
||||
/* create a memory view for the TEB */
|
||||
NtAllocateVirtualMemory( GetCurrentProcess(), &addr, teb, &size,
|
||||
MEM_SYSTEM, PAGE_EXECUTE_READWRITE );
|
||||
|
||||
/* create the process heap */
|
||||
if (!(peb.ProcessHeap = RtlCreateHeap( HEAP_GROWABLE, NULL, 0, 0, NULL, NULL )))
|
||||
{
|
||||
MESSAGE( "wine: failed to create the process heap\n" );
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* startup routine for a newly created thread */
|
||||
/***********************************************************************
|
||||
* start_thread
|
||||
*
|
||||
* Startup routine for a newly created thread.
|
||||
*/
|
||||
static void start_thread( TEB *teb )
|
||||
{
|
||||
LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)teb->entry_point;
|
||||
|
@ -93,6 +156,10 @@ static void start_thread( TEB *teb )
|
|||
SIGNAL_Init();
|
||||
wine_server_init_thread();
|
||||
|
||||
RtlAcquirePebLock();
|
||||
InsertHeadList( &tls_links, &teb->TlsLinks );
|
||||
RtlReleasePebLock();
|
||||
|
||||
NtTerminateThread( GetCurrentThread(), func( NtCurrentTeb()->entry_arg ) );
|
||||
}
|
||||
|
||||
|
@ -107,11 +174,10 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
|||
HANDLE *handle_ptr, CLIENT_ID *id )
|
||||
{
|
||||
HANDLE handle = 0;
|
||||
TEB *teb;
|
||||
TEB *teb = NULL;
|
||||
DWORD tid = 0;
|
||||
SIZE_T total_size;
|
||||
SIZE_T page_size = getpagesize();
|
||||
void *ptr, *base = NULL;
|
||||
ULONG size;
|
||||
void *base;
|
||||
int request_pipe[2];
|
||||
NTSTATUS status;
|
||||
|
||||
|
@ -135,49 +201,13 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
|||
|
||||
if (status) goto error;
|
||||
|
||||
if (!stack_reserve || !stack_commit)
|
||||
if (!(teb = alloc_teb( &size )))
|
||||
{
|
||||
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 = (stack_reserve + 0xffff) & ~0xffff; /* round to 64K boundary */
|
||||
|
||||
/* Memory layout in allocated block:
|
||||
*
|
||||
* size contents
|
||||
* SIGNAL_STACK_SIZE signal stack
|
||||
* stack_size normal stack (including a PAGE_GUARD page at the bottom)
|
||||
* 1 page TEB (except for initial thread)
|
||||
*/
|
||||
|
||||
total_size = stack_reserve + SIGNAL_STACK_SIZE + page_size;
|
||||
if ((status = NtAllocateVirtualMemory( GetCurrentProcess(), &base, NULL, &total_size,
|
||||
MEM_COMMIT, PAGE_EXECUTE_READWRITE )) != STATUS_SUCCESS)
|
||||
goto error;
|
||||
|
||||
teb = (TEB *)((char *)base + total_size - page_size);
|
||||
|
||||
if (!(teb->teb_sel = wine_ldt_alloc_fs()))
|
||||
{
|
||||
status = STATUS_TOO_MANY_THREADS;
|
||||
status = STATUS_NO_MEMORY;
|
||||
goto error;
|
||||
}
|
||||
|
||||
teb->Tib.ExceptionList = (void *)~0UL;
|
||||
teb->Tib.StackBase = (char *)base + SIGNAL_STACK_SIZE + stack_reserve;
|
||||
teb->Tib.StackLimit = base; /* limit is lower than base since the stack grows down */
|
||||
teb->Tib.Self = &teb->Tib;
|
||||
teb->ClientId.UniqueProcess = (HANDLE)GetCurrentProcessId();
|
||||
teb->ClientId.UniqueThread = (HANDLE)tid;
|
||||
teb->Peb = NtCurrentTeb()->Peb;
|
||||
teb->DeallocationStack = base;
|
||||
teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer;
|
||||
teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer);
|
||||
RtlAcquirePebLock();
|
||||
InsertHeadList( &NtCurrentTeb()->TlsLinks, &teb->TlsLinks );
|
||||
RtlReleasePebLock();
|
||||
teb->ClientId.UniqueProcess = (HANDLE)GetCurrentProcessId();
|
||||
teb->ClientId.UniqueThread = (HANDLE)tid;
|
||||
|
||||
teb->tibflags = TEBF_WIN32;
|
||||
teb->exit_code = STILL_ACTIVE;
|
||||
|
@ -189,17 +219,33 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
|||
teb->entry_arg = param;
|
||||
teb->htask16 = NtCurrentTeb()->htask16;
|
||||
|
||||
NtAllocateVirtualMemory( GetCurrentProcess(), &base, teb, &size,
|
||||
MEM_SYSTEM, PAGE_EXECUTE_READWRITE );
|
||||
|
||||
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 = (stack_reserve + 0xffff) & ~0xffff; /* round to 64K boundary */
|
||||
|
||||
status = NtAllocateVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, NULL,
|
||||
&stack_reserve, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
|
||||
if (status != STATUS_SUCCESS) goto error;
|
||||
|
||||
/* limit is lower than base since the stack grows down */
|
||||
teb->Tib.StackBase = (char *)teb->DeallocationStack + stack_reserve;
|
||||
teb->Tib.StackLimit = teb->DeallocationStack;
|
||||
|
||||
/* setup the guard page */
|
||||
ptr = (char *)base + SIGNAL_STACK_SIZE;
|
||||
NtProtectVirtualMemory( GetCurrentProcess(), &ptr, &page_size,
|
||||
size = 1;
|
||||
NtProtectVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size,
|
||||
PAGE_EXECUTE_READWRITE | PAGE_GUARD, NULL );
|
||||
|
||||
if (SYSDEPS_SpawnThread( start_thread, teb ) == -1)
|
||||
{
|
||||
RtlAcquirePebLock();
|
||||
RemoveEntryList( &teb->TlsLinks );
|
||||
RtlReleasePebLock();
|
||||
wine_ldt_free_fs( teb->teb_sel );
|
||||
status = STATUS_TOO_MANY_THREADS;
|
||||
goto error;
|
||||
}
|
||||
|
@ -211,11 +257,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
|||
return STATUS_SUCCESS;
|
||||
|
||||
error:
|
||||
if (base)
|
||||
{
|
||||
total_size = 0;
|
||||
NtFreeVirtualMemory( GetCurrentProcess(), &base, &total_size, MEM_RELEASE );
|
||||
}
|
||||
if (teb) free_teb( teb );
|
||||
if (handle) NtClose( handle );
|
||||
close( request_pipe[1] );
|
||||
return status;
|
||||
|
@ -444,19 +486,18 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
|
|||
case ThreadZeroTlsCell:
|
||||
if (handle == GetCurrentThread())
|
||||
{
|
||||
LIST_ENTRY *entry = &NtCurrentTeb()->TlsLinks;
|
||||
LIST_ENTRY *entry;
|
||||
DWORD index;
|
||||
|
||||
if (length != sizeof(DWORD)) return STATUS_INVALID_PARAMETER;
|
||||
index = *(DWORD *)data;
|
||||
if (index >= 64) return STATUS_INVALID_PARAMETER;
|
||||
RtlAcquirePebLock();
|
||||
do
|
||||
for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
|
||||
{
|
||||
TEB *teb = CONTAINING_RECORD(entry, TEB, TlsLinks);
|
||||
teb->TlsSlots[index] = 0;
|
||||
entry = entry->Flink;
|
||||
} while (entry != &NtCurrentTeb()->TlsLinks);
|
||||
}
|
||||
RtlReleasePebLock();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -834,7 +834,7 @@ DWORD VIRTUAL_HandleFault( LPCVOID addr )
|
|||
{
|
||||
BYTE vprot = view->prot[((char *)addr - (char *)view->base) >> page_shift];
|
||||
void *page = (void *)((UINT_PTR)addr & ~page_mask);
|
||||
char *stack = (char *)NtCurrentTeb()->DeallocationStack + SIGNAL_STACK_SIZE;
|
||||
char *stack = NtCurrentTeb()->Tib.StackLimit;
|
||||
if (vprot & VPROT_GUARD)
|
||||
{
|
||||
VIRTUAL_SetProt( view, page, page_mask + 1, vprot & ~VPROT_GUARD );
|
||||
|
@ -1101,8 +1101,12 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, ULONG *siz
|
|||
|
||||
if (type & MEM_SYSTEM)
|
||||
{
|
||||
/* return the values that the caller should use to unmap the area */
|
||||
*addr_ptr = view->base;
|
||||
*size_ptr = view->size;
|
||||
view->flags |= VFLAG_SYSTEM;
|
||||
type &= ~MEM_SYSTEM;
|
||||
VIRTUAL_DeleteView( view );
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if ((type != MEM_DECOMMIT) && (type != MEM_RELEASE))
|
||||
|
|
|
@ -140,14 +140,6 @@ typedef struct _TEB
|
|||
#define TEBF_WIN32 0x0001
|
||||
#define TEBF_TRAP 0x0002
|
||||
|
||||
/* The per-thread signal stack size */
|
||||
#ifdef __i386__
|
||||
#define SIGNAL_STACK_SIZE 0x100000 /* 1Mb FIXME: should be much smaller than that */
|
||||
#else
|
||||
#define SIGNAL_STACK_SIZE 0 /* we don't need a signal stack on non-i386 */
|
||||
#endif
|
||||
|
||||
|
||||
/* scheduler/thread.c */
|
||||
extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size );
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ extern void wine_server_send_fd( int fd );
|
|||
extern int wine_server_fd_to_handle( int fd, unsigned int access, int inherit, obj_handle_t *handle );
|
||||
extern int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd,
|
||||
enum fd_type *type, int *flags );
|
||||
extern void wine_server_init_thread(void);
|
||||
|
||||
/* do a server call and set the last error code */
|
||||
inline static unsigned int wine_server_call_err( void *req_ptr )
|
||||
|
|
Loading…
Reference in New Issue