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:
Alexandre Julliard 2003-11-04 04:50:18 +00:00
parent bcb09c198d
commit 7924f421e9
9 changed files with 179 additions and 147 deletions

View File

@ -55,32 +55,22 @@ WINE_DECLARE_DEBUG_CHANNEL(relay);
*/ */
TEB *THREAD_InitStack( TEB *teb, DWORD stack_size ) TEB *THREAD_InitStack( TEB *teb, DWORD stack_size )
{ {
DWORD old_prot, total_size; DWORD old_prot;
DWORD page_size = getpagesize(); DWORD page_size = getpagesize();
void *base; 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); 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; return NULL;
teb->DeallocationStack = base; 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 */ teb->Tib.StackLimit = base; /* note: limit is lower than base since the stack grows down */
/* Setup guard pages */ /* Setup guard pages */
VirtualProtect( (char *)base + SIGNAL_STACK_SIZE, 1, VirtualProtect( base, 1, PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old_prot );
PAGE_EXECUTE_READWRITE | PAGE_GUARD, &old_prot );
return teb; return teb;
} }

View File

@ -1933,16 +1933,7 @@ void __wine_process_init( int argc, char *argv[] )
ANSI_STRING func_name; ANSI_STRING func_name;
void (* DECLSPEC_NORETURN init_func)(); void (* DECLSPEC_NORETURN init_func)();
/* setup the server connection */ thread_init();
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);
}
/* setup the load callback and create ntdll modref */ /* setup the load callback and create ntdll modref */
wine_dll_set_callback( load_builtin_callback ); wine_dll_set_callback( load_builtin_callback );

View File

@ -31,6 +31,13 @@
#include "thread.h" #include "thread.h"
#include "wine/server.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 */ /* debug helper */
extern LPCSTR debugstr_us( const UNICODE_STRING *str ); extern LPCSTR debugstr_us( const UNICODE_STRING *str );
extern void dump_ObjectAttributes (const OBJECT_ATTRIBUTES *ObjectAttributes); 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 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, extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handles, UINT flags,
const LARGE_INTEGER *timeout ); const LARGE_INTEGER *timeout );
/* init routines */
extern void wine_server_init_process(void); extern void wine_server_init_process(void);
extern void wine_server_init_thread(void);
extern void thread_init(void);
/* module handling */ /* module handling */
extern BOOL MODULE_GetSystemDirectory( UNICODE_STRING *sysdir ); extern BOOL MODULE_GetSystemDirectory( UNICODE_STRING *sysdir );

View File

@ -466,7 +466,7 @@ static inline int get_error_code( const SIGCONTEXT *sigcontext )
*/ */
static inline void *get_signal_stack(void) 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); 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) (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) if (diff < 4096)
{
ERR( "stack overflow %u bytes in thread %04lx eip %08lx esp %08lx stack %p-%p\n", ERR( "stack overflow %u bytes in thread %04lx eip %08lx esp %08lx stack %p-%p\n",
diff, GetCurrentThreadId(), EIP_sig(sigcontext), ESP_sig(sigcontext), diff, GetCurrentThreadId(), EIP_sig(sigcontext), ESP_sig(sigcontext),
NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase ); NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase );
else SYSDEPS_AbortThread(1);
ERR( "exception outside of stack limits in thread %04lx eip %08lx esp %08lx stack %p-%p\n", }
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), GetCurrentThreadId(), EIP_sig(sigcontext), ESP_sig(sigcontext),
NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase ); NtCurrentTeb()->Tib.StackLimit, NtCurrentTeb()->Tib.StackBase );
SYSDEPS_AbortThread(1);
} }
stack--; /* push the stack_layout structure */ stack--; /* push the stack_layout structure */

View File

@ -58,7 +58,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(thread);
struct thread_cleanup_info struct thread_cleanup_info
{ {
void *stack_base; void *stack_base;
int stack_size; ULONG stack_size;
void *teb_base;
ULONG teb_size;
int status; 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 */ /* copy the info structure since it is on the stack we will free */
struct thread_cleanup_info info = *(struct thread_cleanup_info *)ptr; struct thread_cleanup_info info = *(struct thread_cleanup_info *)ptr;
munmap( info.stack_base, info.stack_size ); munmap( info.stack_base, info.stack_size );
munmap( info.teb_base, info.teb_size );
wine_ldt_free_fs( wine_get_fs() ); wine_ldt_free_fs( wine_get_fs() );
#ifdef HAVE__LWP_CREATE #ifdef HAVE__LWP_CREATE
_lwp_exit(); _lwp_exit();
@ -196,15 +199,13 @@ int SYSDEPS_SpawnThread( void (*func)(TEB *), TEB *teb )
*/ */
void SYSDEPS_ExitThread( int status ) void SYSDEPS_ExitThread( int status )
{ {
TEB *teb = NtCurrentTeb();
DWORD size = 0;
#ifdef HAVE_NPTL #ifdef HAVE_NPTL
static TEB *teb_to_free; static TEB *teb_to_free;
TEB *free_teb; 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; void *ptr;
TRACE("freeing prev teb %p stack %p fs %04x\n", 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 ); wine_ldt_free_fs( free_teb->teb_sel );
ptr = free_teb->DeallocationStack; ptr = free_teb->DeallocationStack;
NtFreeVirtualMemory( GetCurrentProcess(), &ptr, &size, MEM_RELEASE ); NtFreeVirtualMemory( GetCurrentProcess(), &ptr, &size, MEM_RELEASE );
ptr = free_teb;
NtFreeVirtualMemory( GetCurrentProcess(), &ptr, &size, MEM_RELEASE | MEM_SYSTEM );
munmap( ptr, size );
} }
SYSDEPS_AbortThread( status ); SYSDEPS_AbortThread( status );
#else #else
struct thread_cleanup_info info; 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(); SIGNAL_Block();
size = 0; info.status = status;
NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE | MEM_SYSTEM ); info.stack_base = NtCurrentTeb()->DeallocationStack;
close( teb->wait_fd[0] ); info.stack_size = 0;
close( teb->wait_fd[1] ); NtFreeVirtualMemory( GetCurrentProcess(), &info.stack_base,
close( teb->reply_fd ); &info.stack_size, MEM_RELEASE | MEM_SYSTEM );
close( teb->request_fd ); info.teb_base = NtCurrentTeb();
SIGNAL_Reset(); 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() ); wine_switch_to_stack( cleanup_thread, &info, get_temp_stack() );
#endif #endif
} }

View File

@ -21,15 +21,68 @@
#include "config.h" #include "config.h"
#include "wine/port.h" #include "wine/port.h"
#include <sys/types.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include "ntstatus.h" #include "ntstatus.h"
#include "thread.h" #include "thread.h"
#include "winternl.h" #include "winternl.h"
#include "wine/library.h" #include "wine/library.h"
#include "wine/server.h" #include "wine/server.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "ntdll_misc.h"
WINE_DEFAULT_DEBUG_CHANNEL(thread); 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 * thread_init
@ -38,35 +91,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(thread);
* *
* NOTES: The first allocated TEB on NT is at 0x7ffde000. * NOTES: The first allocated TEB on NT is at 0x7ffde000.
*/ */
DECL_GLOBAL_CONSTRUCTOR(thread_init) void thread_init(void)
{ {
static TEB teb; TEB *teb;
static PEB peb; void *addr;
static PEB_LDR_DATA ldr; ULONG size;
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 */
info.str_pos = info.strings; info.str_pos = info.strings;
info.out_pos = info.output; 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 = &params; peb.ProcessParameters = &params;
peb.TlsBitmap = &tls_bitmap; peb.TlsBitmap = &tls_bitmap;
peb.LdrData = &ldr; peb.LdrData = &ldr;
@ -74,12 +107,42 @@ DECL_GLOBAL_CONSTRUCTOR(thread_init)
InitializeListHead( &ldr.InLoadOrderModuleList ); InitializeListHead( &ldr.InLoadOrderModuleList );
InitializeListHead( &ldr.InMemoryOrderModuleList ); InitializeListHead( &ldr.InMemoryOrderModuleList );
InitializeListHead( &ldr.InInitializationOrderModuleList ); 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 ) static void start_thread( TEB *teb )
{ {
LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)teb->entry_point; LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)teb->entry_point;
@ -93,6 +156,10 @@ static void start_thread( TEB *teb )
SIGNAL_Init(); SIGNAL_Init();
wine_server_init_thread(); wine_server_init_thread();
RtlAcquirePebLock();
InsertHeadList( &tls_links, &teb->TlsLinks );
RtlReleasePebLock();
NtTerminateThread( GetCurrentThread(), func( NtCurrentTeb()->entry_arg ) ); 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_ptr, CLIENT_ID *id )
{ {
HANDLE handle = 0; HANDLE handle = 0;
TEB *teb; TEB *teb = NULL;
DWORD tid = 0; DWORD tid = 0;
SIZE_T total_size; ULONG size;
SIZE_T page_size = getpagesize(); void *base;
void *ptr, *base = NULL;
int request_pipe[2]; int request_pipe[2];
NTSTATUS status; NTSTATUS status;
@ -135,49 +201,13 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
if (status) goto error; if (status) goto error;
if (!stack_reserve || !stack_commit) if (!(teb = alloc_teb( &size )))
{ {
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress ); status = STATUS_NO_MEMORY;
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;
goto error; 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.UniqueProcess = (HANDLE)GetCurrentProcessId();
teb->ClientId.UniqueThread = (HANDLE)tid; 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->tibflags = TEBF_WIN32; teb->tibflags = TEBF_WIN32;
teb->exit_code = STILL_ACTIVE; teb->exit_code = STILL_ACTIVE;
@ -189,17 +219,33 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
teb->entry_arg = param; teb->entry_arg = param;
teb->htask16 = NtCurrentTeb()->htask16; 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 */ /* setup the guard page */
ptr = (char *)base + SIGNAL_STACK_SIZE; size = 1;
NtProtectVirtualMemory( GetCurrentProcess(), &ptr, &page_size, NtProtectVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size,
PAGE_EXECUTE_READWRITE | PAGE_GUARD, NULL ); PAGE_EXECUTE_READWRITE | PAGE_GUARD, NULL );
if (SYSDEPS_SpawnThread( start_thread, teb ) == -1) if (SYSDEPS_SpawnThread( start_thread, teb ) == -1)
{ {
RtlAcquirePebLock();
RemoveEntryList( &teb->TlsLinks );
RtlReleasePebLock();
wine_ldt_free_fs( teb->teb_sel );
status = STATUS_TOO_MANY_THREADS; status = STATUS_TOO_MANY_THREADS;
goto error; goto error;
} }
@ -211,11 +257,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
return STATUS_SUCCESS; return STATUS_SUCCESS;
error: error:
if (base) if (teb) free_teb( teb );
{
total_size = 0;
NtFreeVirtualMemory( GetCurrentProcess(), &base, &total_size, MEM_RELEASE );
}
if (handle) NtClose( handle ); if (handle) NtClose( handle );
close( request_pipe[1] ); close( request_pipe[1] );
return status; return status;
@ -444,19 +486,18 @@ NTSTATUS WINAPI NtSetInformationThread( HANDLE handle, THREADINFOCLASS class,
case ThreadZeroTlsCell: case ThreadZeroTlsCell:
if (handle == GetCurrentThread()) if (handle == GetCurrentThread())
{ {
LIST_ENTRY *entry = &NtCurrentTeb()->TlsLinks; LIST_ENTRY *entry;
DWORD index; DWORD index;
if (length != sizeof(DWORD)) return STATUS_INVALID_PARAMETER; if (length != sizeof(DWORD)) return STATUS_INVALID_PARAMETER;
index = *(DWORD *)data; index = *(DWORD *)data;
if (index >= 64) return STATUS_INVALID_PARAMETER; if (index >= 64) return STATUS_INVALID_PARAMETER;
RtlAcquirePebLock(); RtlAcquirePebLock();
do for (entry = tls_links.Flink; entry != &tls_links; entry = entry->Flink)
{ {
TEB *teb = CONTAINING_RECORD(entry, TEB, TlsLinks); TEB *teb = CONTAINING_RECORD(entry, TEB, TlsLinks);
teb->TlsSlots[index] = 0; teb->TlsSlots[index] = 0;
entry = entry->Flink; }
} while (entry != &NtCurrentTeb()->TlsLinks);
RtlReleasePebLock(); RtlReleasePebLock();
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View File

@ -834,7 +834,7 @@ DWORD VIRTUAL_HandleFault( LPCVOID addr )
{ {
BYTE vprot = view->prot[((char *)addr - (char *)view->base) >> page_shift]; BYTE vprot = view->prot[((char *)addr - (char *)view->base) >> page_shift];
void *page = (void *)((UINT_PTR)addr & ~page_mask); 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) if (vprot & VPROT_GUARD)
{ {
VIRTUAL_SetProt( view, page, page_mask + 1, 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) 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; view->flags |= VFLAG_SYSTEM;
type &= ~MEM_SYSTEM; VIRTUAL_DeleteView( view );
return STATUS_SUCCESS;
} }
if ((type != MEM_DECOMMIT) && (type != MEM_RELEASE)) if ((type != MEM_DECOMMIT) && (type != MEM_RELEASE))

View File

@ -140,14 +140,6 @@ typedef struct _TEB
#define TEBF_WIN32 0x0001 #define TEBF_WIN32 0x0001
#define TEBF_TRAP 0x0002 #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 */ /* scheduler/thread.c */
extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size ); extern TEB *THREAD_InitStack( TEB *teb, DWORD stack_size );

View File

@ -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_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, extern int wine_server_handle_to_fd( obj_handle_t handle, unsigned int access, int *unix_fd,
enum fd_type *type, int *flags ); enum fd_type *type, int *flags );
extern void wine_server_init_thread(void);
/* do a server call and set the last error code */ /* do a server call and set the last error code */
inline static unsigned int wine_server_call_err( void *req_ptr ) inline static unsigned int wine_server_call_err( void *req_ptr )