Support arbitrary sizes for the thread signal stack, and set the
default size from the MINSIGSTKSZ constant.
This commit is contained in:
parent
305b221cf0
commit
fb9cead92b
@ -28,13 +28,6 @@
|
|||||||
#include "winioctl.h"
|
#include "winioctl.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
|
|
||||||
|
|
||||||
#define MAX_NT_PATH_LENGTH 277
|
#define MAX_NT_PATH_LENGTH 277
|
||||||
|
|
||||||
extern void WINAPI __regs_RtlRaiseException( PEXCEPTION_RECORD, PCONTEXT );
|
extern void WINAPI __regs_RtlRaiseException( PEXCEPTION_RECORD, PCONTEXT );
|
||||||
@ -50,6 +43,7 @@ extern NTSTATUS NTDLL_wait_for_multiple_objects( UINT count, const HANDLE *handl
|
|||||||
|
|
||||||
/* init routines */
|
/* init routines */
|
||||||
extern BOOL SIGNAL_Init(void);
|
extern BOOL SIGNAL_Init(void);
|
||||||
|
extern size_t get_signal_stack_total_size(void);
|
||||||
extern void version_init( const WCHAR *appname );
|
extern void version_init( const WCHAR *appname );
|
||||||
extern void debug_init(void);
|
extern void debug_init(void);
|
||||||
extern void thread_init(void);
|
extern void thread_init(void);
|
||||||
|
@ -443,6 +443,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
|
|||||||
|
|
||||||
typedef int (*wine_signal_handler)(unsigned int sig);
|
typedef int (*wine_signal_handler)(unsigned int sig);
|
||||||
|
|
||||||
|
static size_t signal_stack_mask;
|
||||||
|
static size_t signal_stack_size;
|
||||||
|
|
||||||
static wine_signal_handler handlers[256];
|
static wine_signal_handler handlers[256];
|
||||||
|
|
||||||
extern void DECLSPEC_NORETURN __wine_call_from_32_restore_regs( CONTEXT context );
|
extern void DECLSPEC_NORETURN __wine_call_from_32_restore_regs( CONTEXT context );
|
||||||
@ -506,7 +509,7 @@ static inline TEB *get_current_teb(void)
|
|||||||
{
|
{
|
||||||
unsigned long esp;
|
unsigned long esp;
|
||||||
__asm__("movl %%esp,%0" : "=g" (esp) );
|
__asm__("movl %%esp,%0" : "=g" (esp) );
|
||||||
return (TEB *)((esp & ~4095) - 4096);
|
return (TEB *)(esp & ~signal_stack_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -753,7 +756,7 @@ static EXCEPTION_RECORD *setup_exception( SIGCONTEXT *sigcontext, raise_func fun
|
|||||||
/* stack sanity checks */
|
/* stack sanity checks */
|
||||||
|
|
||||||
if ((char *)stack >= (char *)get_signal_stack() &&
|
if ((char *)stack >= (char *)get_signal_stack() &&
|
||||||
(char *)stack < (char *)get_signal_stack() + SIGNAL_STACK_SIZE)
|
(char *)stack < (char *)get_signal_stack() + signal_stack_size)
|
||||||
{
|
{
|
||||||
ERR( "nested exception on signal stack in thread %04lx eip %08lx esp %08lx stack %p-%p\n",
|
ERR( "nested exception on signal stack 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),
|
||||||
@ -1156,6 +1159,28 @@ static HANDLER_DEF(usr1_handler)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
static const size_t teb_size = 4096; /* we reserve one page for the TEB */
|
||||||
|
|
||||||
|
if (!signal_stack_size)
|
||||||
|
{
|
||||||
|
size_t size = 4096, min_size = teb_size + max( MINSIGSTKSZ, 4096 );
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* set_handler
|
* set_handler
|
||||||
*
|
*
|
||||||
@ -1174,7 +1199,7 @@ static int set_handler( int sig, int have_sigaltstack, void (*func)() )
|
|||||||
sig_act.ksa_mask = (1 << (SIGINT-1)) |
|
sig_act.ksa_mask = (1 << (SIGINT-1)) |
|
||||||
(1 << (SIGUSR2-1));
|
(1 << (SIGUSR2-1));
|
||||||
/* point to the top of the signal stack */
|
/* point to the top of the signal stack */
|
||||||
sig_act.ksa_restorer = (char *)get_signal_stack() + SIGNAL_STACK_SIZE;
|
sig_act.ksa_restorer = (char *)get_signal_stack() + signal_stack_size;
|
||||||
return wine_sigaction( sig, &sig_act, NULL );
|
return wine_sigaction( sig, &sig_act, NULL );
|
||||||
}
|
}
|
||||||
#endif /* linux */
|
#endif /* linux */
|
||||||
@ -1220,7 +1245,7 @@ BOOL SIGNAL_Init(void)
|
|||||||
#ifdef HAVE_SIGALTSTACK
|
#ifdef HAVE_SIGALTSTACK
|
||||||
struct sigaltstack ss;
|
struct sigaltstack ss;
|
||||||
ss.ss_sp = get_signal_stack();
|
ss.ss_sp = get_signal_stack();
|
||||||
ss.ss_size = SIGNAL_STACK_SIZE;
|
ss.ss_size = signal_stack_size;
|
||||||
ss.ss_flags = 0;
|
ss.ss_flags = 0;
|
||||||
if (!sigaltstack(&ss, NULL)) have_sigaltstack = 1;
|
if (!sigaltstack(&ss, NULL)) have_sigaltstack = 1;
|
||||||
#ifdef linux
|
#ifdef linux
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "wine/port.h"
|
#include "wine/port.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@ -584,6 +585,19 @@ static HANDLER_DEF(usr1_handler)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* 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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* set_handler
|
* set_handler
|
||||||
*
|
*
|
||||||
|
@ -21,7 +21,9 @@
|
|||||||
#ifdef __sparc__
|
#ifdef __sparc__
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "wine/port.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
@ -386,7 +388,20 @@ static HANDLER_DEF(usr1_handler)
|
|||||||
|
|
||||||
/* wait with 0 timeout, will only return once the thread is no longer suspended */
|
/* wait with 0 timeout, will only return once the thread is no longer suspended */
|
||||||
timeout.QuadPart = 0;
|
timeout.QuadPart = 0;
|
||||||
NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout );
|
NTDLL_wait_for_multiple_objects( 0, NULL, 0, &timeout, 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.
|
||||||
|
*/
|
||||||
|
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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ static WCHAR current_dir[MAX_NT_PATH_LENGTH];
|
|||||||
static RTL_BITMAP tls_bitmap;
|
static RTL_BITMAP tls_bitmap;
|
||||||
static RTL_BITMAP tls_expansion_bitmap;
|
static RTL_BITMAP tls_expansion_bitmap;
|
||||||
static LIST_ENTRY tls_links;
|
static LIST_ENTRY tls_links;
|
||||||
|
static size_t sigstack_total_size;
|
||||||
|
|
||||||
struct wine_pthread_functions pthread_functions = { NULL };
|
struct wine_pthread_functions pthread_functions = { NULL };
|
||||||
|
|
||||||
@ -93,7 +94,7 @@ static inline void free_teb( TEB *teb )
|
|||||||
|
|
||||||
NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
|
NtFreeVirtualMemory( NtCurrentProcess(), &addr, &size, MEM_RELEASE );
|
||||||
wine_ldt_free_fs( thread_data->teb_sel );
|
wine_ldt_free_fs( thread_data->teb_sel );
|
||||||
munmap( teb, SIGNAL_STACK_SIZE + sizeof(TEB) );
|
munmap( teb, sigstack_total_size );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -128,7 +129,8 @@ void thread_init(void)
|
|||||||
InitializeListHead( &ldr.InInitializationOrderModuleList );
|
InitializeListHead( &ldr.InInitializationOrderModuleList );
|
||||||
InitializeListHead( &tls_links );
|
InitializeListHead( &tls_links );
|
||||||
|
|
||||||
thread_info.teb_size = SIGNAL_STACK_SIZE + sizeof(TEB);
|
sigstack_total_size = get_signal_stack_total_size();
|
||||||
|
thread_info.teb_size = sigstack_total_size;
|
||||||
VIRTUAL_alloc_teb( &addr, thread_info.teb_size, TRUE );
|
VIRTUAL_alloc_teb( &addr, thread_info.teb_size, TRUE );
|
||||||
teb = addr;
|
teb = addr;
|
||||||
init_teb( teb );
|
init_teb( teb );
|
||||||
@ -280,7 +282,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->pthread_info.teb_size = SIGNAL_STACK_SIZE + sizeof(TEB);
|
info->pthread_info.teb_size = sigstack_total_size;
|
||||||
if ((status = VIRTUAL_alloc_teb( &addr, info->pthread_info.teb_size, FALSE ))) goto error;
|
if ((status = VIRTUAL_alloc_teb( &addr, info->pthread_info.teb_size, FALSE ))) goto error;
|
||||||
teb = addr;
|
teb = addr;
|
||||||
if ((status = init_teb( teb ))) goto error;
|
if ((status = init_teb( teb ))) goto error;
|
||||||
|
@ -548,6 +548,26 @@ static BOOL VIRTUAL_SetProt( FILE_VIEW *view, /* [in] Pointer to view */
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* unmap_extra_space
|
||||||
|
*
|
||||||
|
* Release the extra memory while keeping the range starting on the granularity boundary.
|
||||||
|
*/
|
||||||
|
static inline void *unmap_extra_space( void *ptr, size_t total_size, size_t wanted_size, size_t mask )
|
||||||
|
{
|
||||||
|
if ((ULONG_PTR)ptr & mask)
|
||||||
|
{
|
||||||
|
size_t extra = mask + 1 - ((ULONG_PTR)ptr & mask);
|
||||||
|
munmap( ptr, extra );
|
||||||
|
ptr = (char *)ptr + extra;
|
||||||
|
total_size -= extra;
|
||||||
|
}
|
||||||
|
if (total_size > wanted_size)
|
||||||
|
munmap( (char *)ptr + wanted_size, total_size - wanted_size );
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* map_view
|
* map_view
|
||||||
*
|
*
|
||||||
@ -608,18 +628,7 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size,
|
|||||||
if (is_beyond_limit( ptr, view_size, user_space_limit )) add_reserved_area( ptr, view_size );
|
if (is_beyond_limit( ptr, view_size, user_space_limit )) add_reserved_area( ptr, view_size );
|
||||||
else break;
|
else break;
|
||||||
}
|
}
|
||||||
|
ptr = unmap_extra_space( ptr, view_size, size, granularity_mask );
|
||||||
/* Release the extra memory while keeping the range
|
|
||||||
* starting on the granularity boundary. */
|
|
||||||
if ((ULONG_PTR)ptr & granularity_mask)
|
|
||||||
{
|
|
||||||
size_t extra = granularity_mask + 1 - ((ULONG_PTR)ptr & granularity_mask);
|
|
||||||
munmap( ptr, extra );
|
|
||||||
ptr = (char *)ptr + extra;
|
|
||||||
view_size -= extra;
|
|
||||||
}
|
|
||||||
if (view_size > size)
|
|
||||||
munmap( (char *)ptr + size, view_size - size );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status = create_view( view_ret, ptr, size, vprot );
|
status = create_view( view_ret, ptr, size, vprot );
|
||||||
@ -1109,30 +1118,36 @@ static inline void virtual_init(void)
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* VIRTUAL_alloc_teb
|
* VIRTUAL_alloc_teb
|
||||||
*
|
*
|
||||||
* Allocate a memory view for a new TEB. We don't care about granularity for TEBs.
|
* Allocate a memory view for a new TEB, properly aligned to a multiple of the size.
|
||||||
*/
|
*/
|
||||||
NTSTATUS VIRTUAL_alloc_teb( void **ret, size_t size, BOOL first )
|
NTSTATUS VIRTUAL_alloc_teb( void **ret, size_t size, BOOL first )
|
||||||
{
|
{
|
||||||
void *ptr;
|
void *ptr;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
struct file_view *view;
|
struct file_view *view;
|
||||||
|
size_t align_size = page_size;
|
||||||
BYTE vprot = VPROT_READ | VPROT_WRITE | VPROT_COMMITTED;
|
BYTE vprot = VPROT_READ | VPROT_WRITE | VPROT_COMMITTED;
|
||||||
|
|
||||||
if (first) virtual_init();
|
if (first) virtual_init();
|
||||||
|
|
||||||
*ret = NULL;
|
*ret = NULL;
|
||||||
size = ROUND_SIZE( 0, size );
|
size = ROUND_SIZE( 0, size );
|
||||||
|
while (align_size < size) align_size *= 2;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if ((ptr = wine_anon_mmap( NULL, size, VIRTUAL_GetUnixProt(vprot), 0 )) == (void *)-1)
|
if ((ptr = wine_anon_mmap( NULL, 2 * align_size, VIRTUAL_GetUnixProt(vprot), 0 )) == (void *)-1)
|
||||||
{
|
{
|
||||||
if (errno == ENOMEM) return STATUS_NO_MEMORY;
|
if (errno == ENOMEM) return STATUS_NO_MEMORY;
|
||||||
return STATUS_INVALID_PARAMETER;
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
if (!is_beyond_limit( ptr, 2 * align_size, user_space_limit ))
|
||||||
|
{
|
||||||
|
ptr = unmap_extra_space( ptr, 2 * align_size, align_size, align_size - 1 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
/* if we got something beyond the user limit, unmap it and retry */
|
/* 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 );
|
add_reserved_area( ptr, 2 * align_size );
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!first) RtlEnterCriticalSection( &csVirtual );
|
if (!first) RtlEnterCriticalSection( &csVirtual );
|
||||||
|
Loading…
x
Reference in New Issue
Block a user